|
io-chess
UCI chess engine
|
The infrastructure subsystem provides all the supporting components that the search and evaluation depend on: hash tables, time control, protocol handling, endgame databases, and opening theory.
The transposition table (TT) is a large hash table that stores results from previously searched positions. Because many different move sequences lead to the same position (transpositions), the TT avoids redundant work and is the single most impactful data structure in a chess engine.
Each entry stores:
| Field | Description |
|---|---|
| Zobrist key | 64-bit position hash for collision detection |
| Best move | The move that was best when this position was last searched |
| Score | The evaluation score at the stored depth |
| Depth | How deeply this position was searched |
| Bound type | Whether the score is exact, a lower bound (fail-high), or an upper bound (fail-low) |
| Age | Generation counter for replacement decisions |
The table uses a bucket-based replacement scheme: each hash index maps to a bucket of entries, and new entries replace the shallowest or oldest entry in the bucket. Table size is configured at startup via the UCI Hash option (in megabytes, default 64 MB).
Because all search threads share a single TT instance, entries are accessed using lock-free atomic operations to avoid data races.
The TimeManager converts the remaining clock time and increment into a per-move time budget. Good time management is crucial: spending too long on one move can leave the engine in time trouble later, while moving too quickly wastes potential depth.
Supported time control modes:
| Mode | Description |
|---|---|
| Fischer increment | Time + increment per move |
| Bronstein delay | Time with delay before clock starts |
| Fixed time per move | Exact time budget per move (movetime) |
| Infinite analysis | No time limit (infinite) |
| Depth limit | Search to a fixed depth (depth) |
| Node limit | Search a fixed number of nodes (nodes) |
The time manager also implements dynamic extension: when the root best move changes between iterations (indicating instability), the engine allocates extra time to resolve the uncertainty before committing.
When 6 or fewer pieces remain on the board, the engine probes Syzygy endgame tablebases for theoretically perfect play. These tablebases contain the complete solution for every possible position with up to 6 pieces.
Probing happens at two levels:
The tablebase path is configured via the UCI SyzygyPath option.
The UCI module implements the Universal Chess Interface protocol, which is the standard communication interface between chess engines and graphical user interfaces. The module parses incoming commands, manages engine options, and formats search output.
Key supported commands:
| Command | Description |
|---|---|
| uci | Engine identification and option advertisement |
| isready / readyok | Synchronisation handshake |
| position | Set up a position from FEN or startpos + moves |
| go | Start searching with time/depth/node constraints |
| stop | Interrupt the current search |
| setoption | Configure engine parameters (Hash, Threads, etc.) |
Configurable options:
| Option | Type | Default | Description |
|---|---|---|---|
| Hash | spin | 64 | Transposition table size (MB) |
| Threads | spin | 1 | Number of search threads |
| SyzygyPath | string | (empty) | Path to Syzygy tablebase files |
| MoveOverhead | spin | 10 | Safety margin for time management (ms) |
An optional Polyglot-format opening book can be loaded to play pre-computed book moves in the opening phase. When a book move is available, the engine plays it immediately without running the search, saving time and providing variety in the opening.
The Polyglot format stores positions as Zobrist hashes with associated moves and weights, allowing probabilistic move selection for more varied play. The engine walks the book until no matching position is found, then switches to its own search.