Files
station-master/docs/components.md
T
Jesse.MarkowitzandClaude Opus 5 b90c0413d2 v0.8.0.17 — four things the game knew and the screen did not say
All four reported from a table on Day 1 of v0.8.0.16, and all the same shape.

ABS SIGNALS COULD ONLY BE PLAYED ON ONE MAINLINE CARD, while its tooltip said
"any Mainline card". The engine was never wrong: check accepts any node whose
kind is mainline and legalActions filters by check, so all of them were legal.
The failure was the LABEL — describeIntent named i.placement and never i.node,
so every placement described itself as plain "play ABS Signals", and the action
list drops duplicate labels. All but the lowest-index node were discarded before
the menu saw them. This is the THIRD time that trap has fired and the file
documents the other two three lines apart: a turnout's two rotations, and three
Department discards. Same fix — name what distinguishes them.

The card is also called what the card face calls it. prettyKey rendered
absSignals as "Abs Signals" beside a tooltip saying ABS, an acronym no
key-splitter can recover, so the authored names now win. Three of those names
were transcribed in sentence case and were CORRECTED rather than adopted: the
repository says "Yard Office" 36 times against "Yard office" twice. A lookup
that imports its own source's typos is the drift it exists to prevent.

NOTHING ON A MAINLINE CARD SHOWED WHAT WAS STANDING ON IT. Played, ABS left no
mark and you found out by hovering — the same complaint the Heavy Grade wedge
answered, and it matters more here because ABS decides whether a second train on
that card is safe. It draws a signal mast with a lit lamp now; a signal is the
literal object and needs no room for words, which is what lets it sit clear of a
name as long as "Uncontrolled Siding" on a 152px cell. The Mainline modifiers
draw as BRK, AIR and HLP. Realignment is deliberately not among them: reduce
takes the `became` branch and changes node.card, so a realigned Trestle IS an
Uncontrolled Siding afterwards. Asserted, so the absence reads as a finding.

A FREIGHT AGENT TURN SAID A CAR MOVED WHEN NONE HAD. Three faults behind one
line. It asserted an outcome, where §6.3 requires no action and the bot declines
deliberately — unjamming a healthy box destroys a load that cost a whole action
to stock. An idle Agent was then silent, which read as a dropped turn; a new
freightAgentIdled event says so and why, reducing to nothing exactly like
switchingEnded. And the work named a coordinate rather than the industry, though
a `place` helper has existed for precisely that since the switching lines moved
to it. "Loaded a loaded boxcar INTO the green Outbound box at the Freight House",
with the direction in capitals because to-or-from was the question asked.

THE LOG AND THE ACTION MENU SPELLED THE SAME SQUARE DIFFERENTLY. view.ts wrote
(col,row) — X,Y, east/west then north/south — with a comment saying why;
narrate.ts wrote the internal storage order with no comment at all. So the menu
offered a move to "(1,-1)" and the log reported it at "(-1,1)", side by side.
Pinned by a test that renders one square through BOTH describers and compares
them to each other: a test written against either file alone would have passed.

THE DOCUMENTATION IS REACHABLE FROM A RUNNING GAME, AND ALL OF IT IS PUBLISHED.
v0.8.0.16 published the Quickstart and nothing it points at — its §8 links five
documents by relative path and every one 404'd on the package, verified against
the running container. The build publishes the full set, and the test reads the
links OUT OF the guide rather than listing them. They are linked from the This
Game card, where reference already lives, rather than the header that must not
wrap; no mode awareness is needed, because solitaire and multiplayer are the
same page on the same origin.

THE REFERENCES DROPPED THE VERSION FROM THEIR NAMES. Four described v0.8.0.16
and had since the v0.8.0.15 audit; the v0.4.5 was the prototype edition they
were first written against, kept only because 36 citations pointed at it — and
it read as documentation five minor versions stale. They are quickstart.md,
rules.md, home-deck.md, mainline-deck.md and components.md now, kept current
with each release rather than published as editions. Two errors surfaced while
checking them against this release, which is the argument for doing it:
home-deck.md filed ABS Signals under Enhancements "played into your district"
that "change what a square does" — it does neither, this release's bug written
down — and mainline-deck.md, which lists everything playable onto a Mainline
card, never mentioned it at all.

1010 fast tests and 35 sim tests pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MUizFYCMHRWhbWwXhp7WPR
2026-09-21 05:53:52 -04:00

5.3 KiB
Raw Permalink Blame History

Station Master — Components and Markers

Describes the game as built at v0.8.0.17 (2026-09-21). These references are kept current with every release rather than versioned as editions, so there is no version in the filename: this file is always the latest, and the build it describes is stated here.

Scope: non-card physical components and supplies. Card-created facilities, workers, deck piles, hand state, timetable state and other markers are documented with their cards or in the rules book.

The figures below are checked against ROLLING_STOCK_SUPPLY and the supply constants in src/engine/content.ts. They are physical inventory rather than deck tuning, which is why they are printed here at all — per-category CARD counts are deliberately not published anywhere (TODO #15a).

Rolling stock

Rolling stock has a type and a load state. In the interface, coloured cars are loaded and white cars are empty. The Division Yard starts with the following supply.

Type Loaded Empty Total Use
Coach 8 8 16 Passenger work.
Boxcar 10 10 20 Freight House outbound/inbound; Grocer’s Warehouse inbound.
Hopper 8 8 16 Mine Tipple outbound; Power Plant inbound.
Reefer 5 5 10 Packing Sheds outbound; Grocer’s Warehouse inbound.
Tank car 6 6 12 Refinery outbound; Power Plant inbound.
Caboose 6 0 6 Required or permitted at the rear of the applicable train cards.
Total 43 35 78

The engine is not rolling stock and does not count against the four-car Crew Tray limit.

Other supplies

Component Count Note
Crew Trays players + 3 Engine and tray are one combined resource; there is no "engine without a tray".
Whistle Post cards 4 Every player starts on one; it is not drawn from the deck.
Limits signs 8 "2N + spares", so relocating one is never a supply question.

The two yards

Division Yard

The Division Yard is the active supply. It provides:

  • loaded cars to a Freight Agent stocking a green outbound box;
  • empty cars for building up trains;
  • an empty coach when passengers detrain; and
  • an empty matching freight car when a loaded freight car begins unloading.

When a train completes a run or is destroyed, its caboose returns to the Division Yard. When a car is taken from the Division Yard and that yard has become entirely empty, every car from the Classification Yard moves back into the Division Yard immediately.

Classification Yard

The Classification Yard collects used rolling stock: cars displaced by boarding passengers, cars cleared from inbound red boxes, cars removed by unjamming a facility, ordinary cars from completed or destroyed trains, and empty cars replaced by a completed outbound freight load. It is not a player-selectable source. It returns to service only when the Division Yard is empty.

This is a one-way ratchet for COACHES, and it decides games. Boarding sends an emptied coach here; detraining takes a fresh empty out of the Division Yard. Nothing returns a coach to the Division Yard except the bare-yard refill — and a yard kept topped up with freight cars returning from industries may never run bare. Measured over one three-Day game, every coach was here by the middle of Day 2 and stayed. See Rules §4.6.

Crew Trays and trains

Crew Trays represent an engine and its coupled consist. The game creates players + 3 free trays at setup. A tray is scarce: a due train without a free tray is held for that Stage, and Extras wait until one becomes free.

Within a tray, the engine can pull, push, or be between cars while switching. To depart an Office for the Mainline, it must be made up with the engine at an outer end; if it has a caboose, the caboose must be at the opposite outer end. A train may have at most four cars. A scheduled train can run under-strength but never with more than its card allows.

Fedora

The Fedora is the physical marker for the Superintendent. The player with it resolves following-train clearance decisions, takes the Yard Office and Red Flag questions, and is the player every round round the table starts with. A Mainline collision is their fault by §10, and costs 5 Revenue. The initial holder is the first player tied for the highest Superintendent setup D12 roll.

It passes at the end of Stages 3, 6, 9 and 12 — every third Stage, at the Supervisor Shift. Since v0.8.0.13 the handover is announced on screen and written into the history: it is the one thing in the game that changes hands on the clock rather than because somebody did something, so nobody is watching for it. Note that the Supervisor Shift refreshes every Laborer and Porter every Stage while the Fedora moves only every third.

D12 and seeded randomness

The D12 is used by the engine for:

  • the initial seating roll in a multi-player engine game;
  • the initial Superintendent roll;
  • a timetabled train’s timetable slot; and
  • all shuffled deck order and automatic setup selection through the same seeded random stream.

The rules engine uses a deterministic 32-bit seeded random generator. The same numeric seed, player configuration, house rules, and accepted intent sequence reconstruct the same game. A seed by itself is not enough when house rules differ.