109 lines
6.3 KiB
Markdown
109 lines
6.3 KiB
Markdown
# Station Master — design index
|
||
|
||
Station Master is a tabletop railroad-operations game set in the era of timetable-and-train-order
|
||
railroading (1840–1950), 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 8–13 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 1–6 are done** — the rules engine (components 1–7), 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.
|