Files
station-master/docs/design.md
T
2026-07-31 07:19:57 -04:00

109 lines
6.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Station Master — design index
Station Master is a tabletop railroad-operations game set in the era of timetable-and-train-order
railroading (18401950), being developed into a multiplayer digital game: players connect from a
web browser and an authoritative server manages lobbies and game state.
## Source of record
- `StationMasterPrototypeRules.pdf` — the original prototype rules
- `StationMaster-PrototypeTurnChart.pdf` — the 12-Stage turn chart
These stay as-is. Everything below is derived from them.
## Rules
| Document | What it is |
| --- | --- |
| [`rules/rules-v0.1.md`](rules/rules-v0.1.md) | Faithful markdown transcription of the PDFs. No corrections. The baseline everything diffs against. |
| [`rules/rules-v0.2.md`](rules/rules-v0.2.md) | **The working ruleset.** v0.1 with all ten gaps resolved, each change marked with its gap number. |
| [`rules/card-reference.md`](rules/card-reference.md) | What is printed on every card, plus the economy summary. The spec an engine or a print-and-play layout consumes. |
| [`rules/glossary.md`](rules/glossary.md) | Every defined term, alphabetized. |
| [`rules/open-questions.md`](rules/open-questions.md) | All thirteen gaps, each with the options considered, the decision, and the rationale. |
## Architecture
Target is **small self-hosted** scale: a handful of concurrent games, hosted on a website or as a
StartOS service. Stack is deliberately undecided; these documents describe what any implementation
must do.
| Document | What it is |
| --- | --- |
| [`architecture/components.md`](architecture/components.md) | **The project plan.** All 20 buildable pieces — where each runs, when, MVP vs finished size — plus dependency graph and build order. |
| [`architecture/overview.md`](architecture/overview.md) | Why the server is authoritative; state/intent/event split; transport; the rules-engine boundary. |
| [`architecture/game-state.md`](architecture/game-state.md) | The entity model, and the constraints that are easy to lose. |
| [`architecture/protocol.md`](architecture/protocol.md) | Intents, events, and per-player view redaction. |
| [`architecture/lobby-and-sessions.md`](architecture/lobby-and-sessions.md) | Create/join, seating, reconnection, persistence. |
| [`architecture/deployment.md`](architecture/deployment.md) | Plain web host vs StartOS service — and the one constraint that differs. |
## Current status
Rules formalized, card faces specified, architecture documented, and the rules engine built and
simulated. Eleven of thirteen gaps are closed; **Gap 12 (balance variance) and Gap 13 (deck scaling)
remain open**, both with data behind them.
Gaps 813 were all found by working the design forward — building it or simulating it — rather than
by reading the PDFs. None arises in tabletop play, where a person simply does the sensible thing.
**The economy, in one line:** Local Operations actions are the main currency — one per Stage, twelve
per Day — but **inbound work bypasses them**, which is where the game's variance comes from. See
`card-reference.md` §7.
**Wanted, not yet designed:** post-game replay — watching a finished game back at speed. The
architecture already produces what it needs (an ordered append-only event log plus a stored seed), so
the note in `architecture/overview.md` exists to keep the capability from being designed out. It is
explicitly not scheduled.
**Provisional numbers** — the victory targets are now confirmed at the mean by simulation. Still
untested by play: Crew Tray count, Laborer counts, and whether the variance in Gap 12 is a flaw.
**Next steps.** The specification is complete enough to build against or to play on paper.
The build path is laid out in [`architecture/components.md`](architecture/components.md) — 20
components, a dependency graph, and a twelve-step order. Its **MVP is solitaire: one Office, a fixed
number of Days, a server talking to a single browser, display functional rather than pretty.** The
milestones worth knowing:
- **Step 4** — a full solitaire game runs to completion headless, proving the rules before a pixel is
drawn.
- **Step 6** — the balance harness validates or retunes the provisional numbers, while changing them
is still free.
- **Step 10** — MVP complete; a human plays end to end.
**Stack: TypeScript**, chosen so the engine runs in both the server and the browser — one
implementation of the movement rules, and instant affordances without a round-trip. Node 22 runs
TypeScript natively, so there is no build step during development.
**Steps 16 are done** — the rules engine (components 17), heuristic bots (17) and the balance
harness (18), with 134 tests passing.
**The step 4 milestone is met: a full solitaire game runs to completion, headless.** Games are
reproducible from a seed, terminate from every seed tried, conserve all 62 rolling stock pieces, and
develop properly.
**End-of-game statistics** (`src/sim/stats.ts`) report revenue by source, traffic, development,
action mix and strategy buckets — plus an **anomaly detector** that treats "this event never fired"
as a finding. It caught two bugs on its first run.
**The step 6 milestone is met, with a caveat.** The harness found **five engine bugs that no test had
caught**, and once they were fixed the numbers came good: **~35% win rate and 5.0 Revenue/player/Day,
matching the Gap 10e prediction of 5-6.**
The caveat is large: those numbers were themselves measured against a **scoring bug**, since fixed.
Honest figures are ~0.9 Revenue/Day and a **0% win rate** — the targets are currently unreachable.
The bot is still the prime suspect (it uses ~10 Laborer actions per game out of ~900 available), so
this is **Gap 12** and remains open. One genuine signal did emerge: **mixed freight/passenger
strategies outscore pure ones**, with pure freight much the worst.
**Gap 11 is decided** — track orientation is chosen on placement, settled by measurement.
**Gap 13** answers the deck-size question: do not double it; scale only the buildable cards with
player count.
Next: step 7 begins the server (components 8, 9, 20).
Run the harness with `node src/sim/harness.ts [games] [length]`.
Running alongside, and independent of all of it: **print-and-play components.** `card-reference.md`
specifies every card face, so layout and art are the only remaining work before a table playtest —
which answers the one question simulation cannot, whether it is fun.