# Surfaces How the project ships two usable fronts on **one** rules engine. This is product/engineering framing, not a second ruleset. ## Verdict Yes. We maintain **two surfaces**: | # | Surface | Who uses it | Job | | --- | --- | --- | --- | | 1 | **Headless** | Dev, AI, batch sims, CI, balance | Fast, no UI (or terminal-only). Same rules as the player game. | | 2 | **Interactive** | Human players (and playtesters) | Click/type legal actions; see `GameState` and play `GameEvent`s. | They are not two games. They are two **adapters** over `Game.Core` (+ in-run progression such as `RunProgress`). ``` ┌─────────────────────┐ │ Game.Core │ │ rules · RNG · AI │ │ RunProgress · packs │ └──────────┬──────────┘ ┌───────────────┼───────────────┐ ▼ ▼ Headless surface Interactive surface tools / tests / batch playtest client → later Godot ``` ## 1. Headless surface **Purpose:** AI search, auto fights, full-run loops, regression tests, future balance batches. Anything that must be cheap to run and easy to pin with a seed. **Today:** - `tools/HeadlessBattle` — single fight and `--run` full run (terminal I/O is convenience, not a second rules layer) - `tests/Game.Core.Tests` — pinned scenarios - In-process AI (`TurnBeamSearch`) calling `GetLegalActions` / `Execute` / `Clone` **Later (same surface family):** - Batch sims / PT reports / seed sweeps - Headless full-run without printing every step - Replay from `seed + action log` **Must:** - Depend only on Core (and content JSON), never on Godot or browser UI - Stay deterministic: same seed + choices → same result - Be the path AI and automated tests use in production of balance data **Must not:** - Reimplement card text, pack unlocks, or combat resolution “for speed” - Become a simplified AI-only ruleset ## 2. Interactive surface **Purpose:** What a human actually plays. Input becomes `GameAction`; screen shows state and events. Presentation only. **Today:** - `Game.Client` — browser playtest (emoji/SVG placeholders) - Optional: interactive mode of `HeadlessBattle` (numbered legal actions) as a thin terminal client — still surface 2 in spirit, but not the player-facing target **Later:** - Godot .NET desktop / Steam presentation - Art pass replaces placeholders; rules stay in Core **Must:** - Call the same Core APIs as headless (`GetLegalActions`, `Execute`, …) - Own layout, input, animation, audio, UX copy - Refuse to “fix” rules bugs in the UI **Must not:** - Encode damage formulas, pack conditions, legal-move filters, or win checks locally - Drift into a parallel progression model for “the real game” ## Shared core (the only rules owner) Both surfaces consume: - Combat: `GameState`, `GameAction`, `GameEvent`, `GameRng` - Progression: `RunProgress`, rewards, Holder, simple upgrades, in-run packs - AI: evaluation + current-turn search that **reads** Core, does not own it If a feature matters for “how the game works,” it lands in Core (and tests) first. Surfaces only expose or automate it. ## How work usually splits | Change type | Land in | Headless | Interactive | | --- | --- | --- | --- | | New rule / card effect / pack condition | Core + tests | exercise via CLI/tests | render/input only if needed | | Faster AI / batch balance | Core + tools | primary | optional “show AI candidates” | | UX, targeting UX, animation, art | Client (later Godot) | no | primary | | Full-run loop (reward → upgrade → next fight) | Core + headless first | prove it | then wire the same loop in the client | Default order stays **simulation first**: headless (or tests) prove the loop; interactive follows. ## Roadmap mapping 1. CLI combat / CLI full run → headless surface (also a crude interactive terminal) 2. Playtest client → interactive surface v1 3. Art pass / Godot → interactive surface v2 (same Core) 4. Expansion packs → content + Core; both surfaces pick them up automatically ## Non-goals - Two rulebooks (player vs AI) - Meta / cross-run unlocks on either surface - Making the browser client a permanent architecture requirement (it is a playtest skin; Godot may replace it) ## Related docs - Principles: `docs/FOUNDATION.md` (simulation vs presentation) - Layout & phases: `docs/ARCHITECTURE.md` - AI constraints: `docs/AI.md` - Run / Holder grammar: `docs/RULES.md`