把规则、架构与实现路线写成仓库文档。
后续改内容或结算顺序时有冻结依据,不必再翻原始稿才能对齐。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
# 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`
|
||||
Reference in New Issue
Block a user