# UCI Engine Architecture Plan ## Goal Support two families of executables: 1. **GUI/UI executable** - Renders and tracks games. - Lets humans play/edit/replay games. - Can let people play against bots. - Can spawn bot/engine executables as subprocesses on demand. - Speaks UCI to engine subprocesses. - Can optionally use a user-selected external UCI engine, such as Stockfish, for playback analysis. - Eventually stores games in a database. 2. **Bot/engine executables** - No GUI. - Implement chess engine logic. - Speak UCI over stdin/stdout. - Can be launched by the GUI. - Can also run as long-lived processes connected to external services such as lichess.org through a service adapter. ## Important terminology In UCI terminology, the **engine** is the side that implements the UCI command loop over stdin/stdout. The GUI/app is the **UCI controller/client**: ```text GUI/controller ├── starts engine process ├── writes UCI commands to engine stdin ├── reads UCI responses from engine stdout └── applies bestmove to the current game ``` The engine executable is the **UCI engine/server-like process**: ```text Engine ├── reads commands from stdin ├── maintains/searches position ├── writes info/bestmove responses to stdout └── exits on quit ``` Avoid naming the GUI-side wrapper a "server" in code. Prefer names like: ```text UciEngineClient UciController EngineProcess ``` ## Desired long-term process architecture ```text ┌─────────────────────┐ │ zig-chess-gui │ │ │ │ - Vulkan UI │ │ - game tracking │ │ - human input │ │ - playback │ │ - database later │ │ - UCI client │ └──────────┬──────────┘ │ UCI stdin/stdout ▼ ┌─────────────────────┐ │ zig-chess-engine-* │ │ │ │ - evaluation │ │ - search │ │ - move selection │ │ - UCI command loop │ └─────────────────────┘ ``` Future external-service architecture: ```text ┌─────────────────────┐ │ lichess-adapter │ │ │ │ - lichess API │ │ - account/game I/O │ │ - UCI client │ └──────────┬──────────┘ │ UCI stdin/stdout or socket/process bridge ▼ ┌─────────────────────┐ │ zig-chess-engine-* │ └─────────────────────┘ ``` Key design principle: ```text GUI ───────────────┐ ├── UCI ── engine executable Lichess adapter ───┘ ``` The engine should not know whether it is being used by the GUI, a test harness, or a lichess adapter. ## Suggested source layout Possible future layout: ```text src/ ├── chess/ // board/game/FEN/PGN/legal moves ├── main.zig // current GUI entry point, or later src/gui/main.zig ├── uci/ │ ├── protocol.zig // shared UCI parse/format types │ ├── client.zig // GUI/service side: controls engine process │ └── server.zig // engine side: stdin/stdout command loop ├── engine/ │ ├── engine.zig // common engine interface │ ├── eval.zig // static evaluation │ ├── search.zig // search algorithms │ └── perft.zig // move-generator validation tooling └── bots/ ├── random.zig // random/legal-move bot executable ├── material.zig // material-eval bot executable └── search.zig // stronger search bot executable ``` This layout can evolve. The important boundary is that engine executables communicate with outside controllers through UCI. ## Build targets Eventually `build.zig` should produce multiple executables, for example: ```text zig-chess-gui zig-chess-random-bot zig-chess-material-bot zig-chess-search-bot ``` The GUI target links rendering/UI code. The engine targets should avoid linking Vulkan/windowing code. ## Analysis engine policy The GUI should support an optional external UCI engine for real-time analysis during game playback. Primary intended use case: ```text Playback mode ├── user steps through game ├── GUI sends current position to analysis engine ├── analysis engine returns eval/PV/best line └── GUI displays analysis to the user ``` This analysis engine is separate from project bot engines: - It is for user-facing analysis only. - It must not be used by project bot engines as their search/evaluation implementation. - Project bots should have their own evaluation/search logic. - The GUI should treat the analysis engine as just another external UCI process. ### Stockfish licensing policy Stockfish is GPL-3.0 licensed. Because this project is intended to be MIT licensed, do **not** bundle Stockfish directly into the executable or source distribution by default. Preferred approaches: 1. **User-provided engine path** - User installs Stockfish or another UCI engine separately. - GUI stores/configures the path. - GUI launches it as an external process. 2. **Optional download flow** - GUI can offer to download Stockfish or guide the user through downloading it. - The download should be explicit and optional. - The UI should clearly identify the engine and its license before download/use. - Keep downloaded engine files outside the MIT-licensed source tree/release bundle unless licensing obligations are intentionally handled. 3. **Generic UCI analysis engine support** - Do not hard-code Stockfish as the only option. - Any compatible UCI engine path should work. ### Analysis engine UI/config needs Eventually the GUI should provide: - analysis engine executable path - enable/disable analysis - analysis depth or movetime - optional thread/hash settings via UCI options - current eval display - principal variation display - best move display - start/stop analysis when stepping through playback Suggested app-side abstraction: ```text AnalysisEngine ├── engine_process / UciEngineClient ├── executable_path ├── enabled ├── depth or movetime limit ├── latest_score ├── latest_pv └── latest_bestmove ``` ## UCI protocol responsibilities ### GUI/client side The GUI should be able to: - Spawn an engine executable. - Send UCI commands. - Read engine output asynchronously or incrementally. - Track engine readiness. - Track available engine options. - Send current game position. - Request a move/search. - Stop a search. - Shut down the engine process cleanly. Common commands sent by GUI: ```text uci isready ucinewgame position startpos position startpos moves e2e4 e7e5 position fen moves ... go depth 5 go movetime 1000 stop quit ``` Common responses parsed by GUI: ```text id name id author option name type ... uciok readyok info depth 3 score cp 20 nodes 1234 time 10 pv e2e4 e7e5 bestmove e2e4 bestmove e2e4 ponder e7e5 ``` ### Engine/server side Each engine executable should: - Read one line at a time from stdin. - Parse UCI commands. - Maintain an internal position. - Search when given `go`. - Print `bestmove ...` when done. - Print `info ...` optionally during search. - Respond to `stop` promptly. - Exit on `quit`. ## First milestone: minimal UCI engine executable Implement an engine executable that supports only: Input: ```text uci isready quit ``` Output: ```text id name ZigChess Random Bot id author WayfinderAK uciok readyok ``` No search or move generation required yet. Purpose: - Prove executable separation. - Prove stdin/stdout loop. - Prove GUI/test harness can launch and communicate with engine. ## Second milestone: GUI-side engine process wrapper Implement a UI/application-side wrapper that can: - Start an engine executable by path. - Send `uci`. - Wait for `uciok`. - Send `isready`. - Wait for `readyok`. - Send `quit` on shutdown. Suggested name: ```zig UciEngineClient ``` or: ```zig EngineProcess ``` This code belongs on the GUI/controller side, not inside the engine bot. ## Third milestone: position and bestmove Add UCI support for: ```text position startpos position startpos moves e2e4 e7e5 position fen moves ... go depth 1 bestmove ``` For the first engine, `go depth 1` can simply pick the first legal move or a random legal move. Move format is UCI long algebraic coordinate format: ```text e2e4 e7e8q e1g1 ``` This is different from SAN/PGN notation. ## Fourth milestone: reusable protocol module Create shared parse/format helpers for UCI text: ```text src/uci/protocol.zig ``` Potential responsibilities: - Parse GUI-to-engine commands. - Parse engine-to-GUI responses. - Format moves as UCI coordinate moves. - Parse UCI coordinate moves into from/to/promotion. - Format `position ...` commands from a `Game` move list. Keep protocol parsing separate from subprocess management and separate from search/evaluation. ## Fifth milestone: stronger engines Once the protocol boundary works: - random legal move engine - material evaluation engine - shallow search engine - alpha-beta search engine - improved move ordering - transposition table - time management Each stronger engine can be its own executable or selected by options/config. ## Future lichess adapter Do not put lichess-specific code inside the engine. Instead, later create a separate adapter/service that: - talks to lichess.org APIs - manages authentication/account events - receives games/moves from lichess - launches or connects to an engine executable - sends positions/search commands via UCI - sends engine moves back to lichess This keeps engines reusable by: - GUI - lichess adapter - local match runner - tournament harness - tests/benchmarks ## Future playback analysis milestone After the generic UCI client exists, add analysis support to playback mode: 1. Let the user configure an external UCI engine path. 2. Start that engine as an analysis process. 3. Send `uci` / `isready` handshake. 4. When playback cursor changes, send: ```text position fen go depth ``` or: ```text position fen go movetime ``` 5. Parse `info` lines for score and PV. 6. Display the latest analysis in the UI. 7. Send `stop` when the user moves to another ply or disables analysis. 8. Send `quit` when closing the app or changing engine path. Keep this separate from bot-vs-human play. The analysis engine is an advisor for the user, not the implementation of project bots. ## References Primary UCI reference: - Stefan Meyer-Kahlen, **Universal Chess Interface (UCI)** protocol, April 2006. Commonly distributed as `uci.txt` and mirrored by chess-programming resources. Covers `uci`, `isready`, `position`, `go`, `stop`, `quit`, `info`, `bestmove`, and engine options. Stockfish licensing/reference: - Official Stockfish repository: https://github.com/official-stockfish/Stockfish - Stockfish `Copying.txt`: GNU General Public License v3.0, https://github.com/official-stockfish/Stockfish/blob/master/Copying.txt - Because the project goal is MIT licensing, Stockfish should be user-provided or optionally downloaded rather than bundled by default. Useful related notation distinction: - UCI moves are coordinate moves such as `e2e4` or `e7e8q`. - PGN/SAN moves are display/game-record notation such as `e4`, `Nf3`, `O-O`, `Qxf7#`. - The GUI move list should display PGN/SAN. - Engine communication should use UCI coordinate moves.