How utkarsh-naman/unc works
1. Repository purpose and overall shape
This repo packages a “solved” Chopsticks bot around a precomputed game graph. The architecture is not a typical on-demand search engine; it is a pipeline that builds the full state graph offline, annotates it with values, then ships a runtime engine that reads the finalized graph and plays from it.
2. Core domain model
The game logic is centered on compact state representations for the two players’ hand counts and whose turn it is. The include/rules.hpp, include/utils/state_repr.hpp, and corresponding src/utils/state_repr.cpp files define the canonical representation used throughout the solver, builder, serializer, and runtime engine.
3. Move-generation subsystem
Legal game transitions are implemented as a set of focused move modules under include/utils/moves and src/utils/moves. These cover attack variations and redistribution behavior, with helpers such as arrange_*, left_to_*, right_to_*, distribute, and next_state. This subsystem is the forward edge generator for the game graph.
4. Reverse-transition / parent discovery subsystem
A parallel set of modules under include/utils/unmove and src/utils/unmove computes predecessor states. This is important because the solver is built bottom-up: instead of exploring forward from the start state, it propagates values backward from terminal positions through parent links.
5. Offline map builder pipeline
The src/MapBuilder and build/ directories contain the graph-construction utilities for initial maps such as map_0 and map_p_0. These builders create the raw state graph and the parent map artifacts that later stages consume. The presence of test_map0, test_map_p_0, and related binaries shows this stage is independently validated.
6. Value-setting / solving pipeline
src/MapValueSetter is where the graph gets solved. The files set_terminal_depth.cpp, set_suicides.cpp, and set_score.cpp indicate a staged annotation process: first mark terminal depths, then assign special values for suicide/terminal conditions, then propagate scores across the graph. The repository’s README calls this the “MaxiMax” approach, but architecturally it is a backward propagation of game values over the precomputed graph.
7. Final solved map artifact
The culmination of the offline pipeline is map_final plus supporting serialized files in bin/output/map/.... This final dataset is what the runtime consumes. The architecture depends on this artifact being complete and consistent; the bot’s runtime behavior is driven by lookup and evaluation against this precomputed map, not by running a deep search at play time.
8. Runtime engine boundary
src/UncEngine and WASM/engine_unc.cpp contain the play-time engine. This layer loads the final map, evaluates the current game state, and selects a move. It is deliberately separated from the map-building code so the deployed bot stays lightweight and deterministic.
9. Serialization boundary
serializer.cpp/.hpp, p_serializer.cpp, and state_repr.cpp/.hpp implement the file format and in-memory encoding used to move graph data between builder, solver, and engine. This is the key boundary between the algorithmic graph pipeline and the runtime consumer, and it is also what enables the preloaded .data file in the browser build.
10. WASM / browser packaging
The WASM directory contains the browser-facing build: bindings.cpp exposes the C++ engine to JavaScript via Emscripten, index.html is the demo shell, and server.py supports local serving. The generated chopsticks_bot.js, chopsticks_bot.wasm, and chopsticks_bot.data are the deployable artifacts; cdn and cdn4 hold copies for publishing.
11. Testing and verification
The tests directory contains concept checks, reference implementations, parent-map validation, and bot tests. These are important because the solution depends on graph correctness rather than heuristic quality; the tests verify that generated parent relationships and solved values match expected behavior.
12. Build system and artifact layout
The root CMakeLists.txt and the various *.txt command lists in src/MapBuilder, src/MapValueSetter, and WASM reflect a multi-stage build process rather than a single compile step. The repo contains both source and generated binaries/data, which signals that the architecture is a toolchain plus runtime, not just a library.
Main entry points: MapBuilder Graph builder · MapValueSetter Value setter · state_repr.hpp State repr · UncEngine Unc engine
Components 17
Game model
Canonical Chopsticks state representation and rule helpers.
- Rules · Core game constraints and turn semantics.
include/rules.hpp - State repr · Compact canonical state encoding shared across the solver and engine.
include/utils/state_repr.hpp
Transition logic
Forward move generation and reverse predecessor discovery used by the solver.
Offline pipeline
Build stages that construct the state graph, derive parent maps, and annotate values.
- Graph builder · Offline construction of raw state graphs and parent maps.
src/MapBuilder - Value setter · Staged annotation pipeline for terminal depth, suicides, and scores.
src/MapValueSetter - Raw map · Precomputed graph before value propagation.
bin/output/map/unvalued/map_0 - Parent map · Graph artifact containing reverse links for solving.
bin/output/map/unvalued/map_p_0 - Depth map · Intermediate valued map after terminal-depth propagation.
bin/output/map/valued/map_1_depth - Final map · Completed solved dataset consumed by the runtime engine.
bin/output/map/valued/map_final
Runtime
Play-time engine that loads the finalized map and selects moves.
- Unc engine · Play-time engine that loads the final map and chooses moves.
src/UncEngine
Packaging
Serialization and browser deployment boundary for precomputed artifacts.
- Serializer · Read/write boundary for map and state data.
include/utils/serializer.hpp - P serializer · Specialized serialization for parent-map artifacts.
include/utils/p_serializer.hpp - WASM engine · Emscripten-exposed engine and browser-facing wrapper.
WASM/bindings.cpp - WASM assets · Generated JS, WASM, and data payload used by the browser demo.
WASM/chopsticks_bot.data
Verification
Checks that validate generated maps, parents, and runtime behavior.
- Map tests · Checks for map construction, parent correctness, and bot behavior.
tests - Build entry · Top-level CMake build orchestration for sources and generated artifacts.
CMakeLists.txt
Connections 23
- Rules → State repr: defines · Rules constrain the canonical state representation.
- State repr → Moves: drives · State encoding feeds forward move generation.
- State repr → Unmoves: drives · State encoding also feeds predecessor discovery.
- Moves → Graph builder: builds · Forward transitions populate the offline graph builder.
- Unmoves → Graph builder: builds · Reverse transitions support parent-map construction.
- Graph builder → Raw map: writes · Builder emits the raw unvalued map.
- Graph builder → Parent map: writes · Builder emits the parent map artifact.
- Raw map → Value setter: inputs · Raw graph is the substrate for solving passes.
- Parent map → Value setter: inputs · Parent links guide backward value propagation.
- Value setter → Depth map: produces · Intermediate depth annotation is staged output.
- Depth map → Final map: produces · Final score propagation yields the solved map.
- Final map → Unc engine: loads · Runtime engine consumes the solved dataset.
- State repr → Serializer: serialized by · State representation is persisted through the serializer boundary.
- Parent map → P serializer: serialized by · Parent-map artifacts use a specialized serializer.
- Serializer → Unc engine: feeds · Engine relies on serialized map/state loading.
- Unc engine → WASM engine: wrapped by · Browser build exposes the engine via bindings.
- WASM engine → WASM assets: bundles · Browser packaging produces JS/WASM/data artifacts.
- Build entry → Graph builder: orchestrates · Build system drives map-builder targets.
- Build entry → Value setter: orchestrates · Build system drives value-setter targets.
- Build entry → WASM engine: orchestrates · Build system also drives the WASM target.
- Map tests → Graph builder: validates · Tests check builder output and parent maps.
- Map tests → Value setter: validates · Tests verify solved values and special cases.
- Map tests → Unc engine: validates · Bot tests exercise the runtime engine behavior.