# DECISIONS.md — Duplicate Chess Decision Log Project-specific decisions. For global/cross-cutting decisions, see `~/bin/DECISIONS.md`. Format: `YYYY-MM-DD: ` ## Architecture 2026-05-19: First deliverable is a local single-operator sandbox/visualizer, not a networked game — the inventor's stated need is to *see* a mock game to comprehend the variant; networked four-player play is a separable later project. 2026-05-19: Single Vite + Svelte 5 + TS app, no server — duplicate chess is perfect-information, so the whole engine and all four boards live client-side. No pnpm workspace (unlike blind_chess, which needs a server as its trusted view boundary). 2026-05-19: Engine lives in a pure, DOM-free `src/engine/` tree (vitest-tested); Svelte UI in `src/lib/`. Keeps the coupled-legality logic isolated and portable if a networked version is ever built. 2026-05-19: Engine = 4× `chess.js` + an intersection layer. A player's legal moves = the moves legal on *both* their boards, keyed by `(from,to,promotion)`. Ghost immobility, the synchronized-checkmate definition, and en-passant/castling divergence all fall out of the intersection — no special-case code. 2026-05-19: Authoritative game state is an ordered list of synchronized moves; "replay to ply N" rebuilds all four `chess.js` boards. Powers undo and history scrubbing. ## Implementation 2026-05-19: Compass UI — four boards rendered as 45° diamonds in an X/pinwheel (NW 225°, NE 135°, SW 315°, SE 45°), players seated in the four V-notches, pieces rotate *with* their board so each player's army faces their seat. Confirmed against Andrew's sketch (`USERFILES/4personchess.png` in blind_chess). 2026-05-19: Four player colours (one per player) instead of White/Black fill — makes two-board ownership readable at a glance. 2026-05-19: Intersection highlighting (teaching mode) — grabbing a piece shows playable squares (legal on both boards) AND board-local-only squares, so the coupling is visible. 2026-05-19: Coordinate notation (`e2e4`) for the move log, not SAN — SAN's disambiguation differs between a player's two boards once they diverge, so it cannot be the single identical token. 2026-05-19: Click-to-move, not drag — cleaner on rotated boards. 2026-05-19: Provisional endgame rules picked by Claude, marked PROVISIONAL — Andrew can revise. First terminal event ends the game; any no-synchronized-move stalemate ends the game with all four drawing; threefold/50-move tracked on the whole four-board system; insufficient material not auto-detected. ## Deferred / Rejected 2026-05-19: Networked four-player play — deferred; separable later project, would reuse the `src/engine/` tree. 2026-05-19: AI opponents — deferred; the sandbox is operator-driven. 2026-05-19: Free position editor — rejected for v1; play-from-start + history scrubbing keeps every shown position reachable by legal play, preserving the "every board is real chess" invariant. 2026-05-19: Counter-rotating pieces upright on the diamonds — rejected; pieces rotate with their board so each player's army faces their seat (the point of the compass). 2026-05-19: Deployment behind Caddy — deferred; v1 runs locally, the static build can be hosted later trivially. 2026-05-19: A separate "dual view" of the on-move player's two boards — rejected; the compass is the whole UI, with the triple-highlight happening directly on it.