Files
station-master/docs/home-deck.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

158 lines
9.2 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 — Home Deck
**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:** the Home Office deck — how it is dealt, drawn, discarded and reshuffled, and what the
rules are for playing each kind of card out of it.
> **Per-card facts live in [`rules/as-built.md`](rules/as-built.md)**, which is GENERATED from
> `src/engine/content.ts` and checked by `test/card-reference.test.ts`, so it cannot disagree with
> the game. Read it for every card's name, effect, placement and whether its printed effect actually
> resolves yet. This document is how the deck WORKS; that one is what is in it.
>
> **No card counts appear here, deliberately** (TODO #15a, Jesse's call 2026-08-22): counts move
> with play balance, so a document printing them is answering a question that has a different answer
> after the next retune. Where a count matters it is rendered as a yes/no — whether the deck deals
> the card at all — which is a fact about the design. This page used to print a full counts table
> and it was wrong for a month before anyone noticed.
## The piles
- **Home Office deck** — face down. The pile a Draw comes from.
- **Three Departments** — face-up discard piles. A discard goes onto one, which is precisely so a
rival may take it; a Draw may take the top card of a Department instead of the deck.
- **Salvage Yard** — where a played-out card ends up. An Extra's card goes here after its run.
When the Home Office deck runs out it is rebuilt from the Salvage Yard and **all three Departments
in full**, reshuffled from the seeded stream. A **spent timetabled train** is not collected — its
number is on the timetable and it cannot run twice — but a *discarded* train was never played and
is still runnable, so it comes back.
## Hand and turn
The hand limit is **three**, or four while you hold a Red Flag. You may not end a turn over the
limit: play a card or discard one to a Department. Some cards cannot be discarded at all — an Extra
never can, and a timetabled train cannot when the `discardTimetabled` house rule is off — so a hand
of nothing but those has exactly one way forward, which is to play one.
The opening deal is a house-rule choice made when the game is dealt. The default (`threeRandom`) is
three cards from one shuffled deck; `threeTrackThreeOther` deals three track and three others from
two separately shuffled piles, deliberately over the hand limit, so the first turn is spent choosing
which district you can afford to build.
Drawing is one of the three Local Operations options — see [Rules](rules.md)
§4.2. Taking the option lets you draw **and** play or discard within the same turn.
## Track cards
Track cards are ordinary Home Office cards, not a separate personal supply.
- A placed card must **connect to existing rail**: at least one neighbour must join it.
- The **Running Track** is the row from Limit to Limit. A card placed there must carry an east–west
through route, or it breaks the main.
- Placing track **on a Limit sign** extends the Running Track and moves that sign outward. The sign
is a physical card, so it moves rather than being left stranded mid-track.
- **Nothing may be placed outside your Limits** — track, industries and, since v0.8.0.14, Modifiers
too. Your district ends at its sign.
- Curves and turnouts are printed left- or right-handed. A card may be turned 180° but never flipped
over, so its 45° leg never changes diagonal.
- A **turnout may upgrade** an existing straight, or a curve whose arc is exactly the turnout's
diverging arc. Not if the card holds standing cars or an enhancement. Every other occupied square
is unavailable.
- A turnout may be **run through but not stopped on**: it is not Operational Rail, so a Move may not
end there.
## Office cards
Every player begins at a **Whistle Post**, which is not drawn from the deck: one A/D track, no
Porters, no passenger slots, and not a Control Point.
Office cards are **upgrades in strict sequence** — Whistle Post → Depot → Station → Terminal — and
each upgrades the Office in place rather than replacing its card or its attached track. Modifiers
already beside it are preserved. Each tier adds an A/D track, a Porter, and an outbound and inbound
passenger slot; a Depot and above is a Control Point and a Passenger Facility.
An upgrade takes no placement: the Office is where it already is.
## Freight facilities
An industry is placed on a connected straight **stub off the Running Track** — never on the Running
Track itself, and never outside the Limits. A Facility carries its own rails, so placing one places
track.
Each begins with one Laborer and a three-box **MEN | AT | WORK** pipeline. No Office Area may hold a
duplicate industry, or both ends of a lockout pair — a producer and the consumer of the same
commodity cannot be built in one district.
**An industry track holds four cars, like any other card.** It is *not* sized by the industry's box
count. That distinction was a real bug: box count is how much WORK an industry can hold, not how
much RAIL it has, and conflating the two invented a printed siding no industry card carries.
## Facility modifiers
A Modifier sits on an empty square among the **nine spots around its host Facility** — and, since
v0.8.0.14, **inside your Limits**, like everything else. It may not stand in the Running Track row.
One of each kind per Office Area.
**A Modifier adds a BOX, never room for a car.** A Truck Dock beside a Grocer's Warehouse gives it a
second red box — somewhere for one more arriving load to be cleared to — and changes nothing about
how many cars may be spotted there.
**A grant the host cannot use does nothing**, and the game says so rather than pretending. An
outbound bonus beside an inbound-only facility, or the Truck Dock's inbound bonus beside the
outbound-only Packing Sheds, is discarded — the latter leaving that card with no effect at all.
Passenger modifiers beside a **Whistle Post** add Porters but create no outbound slot until the
Office becomes a Passenger Facility; the panel reports that as DORMANT rather than claiming the
facility "only receives", which was wrong in both directions.
## Train cards
Playing a **timetabled** train rolls the seeded D12 and puts its number in the first open timetable
slot at or after the result, wrapping around the 12-slot chart. It then runs at that Stage **every
Day**.
Playing an **Extra** queues it; it is made up when a Crew Tray comes free, and **the player who
played the card chooses where it starts and loads it as they choose** (§7). Where it may start is a
house rule — `divisionPointsOnly`, `ownOffice`, or `anyOffice` (the default) — and the Interchange is
also available, because it is the one Mainline card with a yard. An Extra runs once and its card
goes to the Salvage Yard.
> The v0.4.5 behaviour of launching every Extra eastbound from the Western Division Point was
> replaced in v0.6.2. The number no longer decides an Extra's direction; the start does.
The listed consist is a **maximum, not a minimum**. A train may depart with fewer cars, but not with
more, not of the wrong category, not with a car behind the caboose, and not with the engine buried
among its own cars. A Crew Tray holds four pieces, and a caboose counts toward the four.
A train made up short of what its card calls for is reported as such, with what it wanted and why
the yard could not supply it — see Rules §4.4.
**Per-train consists and printed rules: [`rules/as-built.md`](rules/as-built.md) § Trains.** It
carries the `empties only`, `reefers only`, `drop only` and `pick up empties only` restrictions,
every one of which the engine enforces.
## Enhancements, Mainline modifiers and Maneuvers
- **Enhancements** are played into your district and change what a square does — the **Small Yard**
(re-order a consist for one Move), **Interlocking**, **Yard Office** and the rest. `as-built.md`
marks each one `live`, `dormantSolo` or `unbuilt`, which is the part only the implementation
knows.
- **ABS Signals is the exception, and it matters.** It is dealt as an Enhancement but is **not
played into your district**: it goes onto a **Mainline card** — any one of them — and stops
trains there rear-ending each other. It takes no square and is not part of anybody's Office
Area. See [Mainline deck](mainline-deck.md).
- **Mainline modifiers** are played onto a Mainline card: the Heavy Grade helpers and Realignment.
See [Mainline deck](mainline-deck.md).
- **Maneuvers** are held and spent: **Red Flags** and **Flying Switch** have their own actions.
Poling is catalogued but its effect is recorded as "TBD in the source", so there is nothing to
implement.
## Opponent-directed cards — not dealt
The **Action** and **Space-use** categories are opponent-directed and are **excluded from every
dealt deck**, because their play rules are not implemented. They are catalogued in
`as-built.md` so the composition is on record, and `check` refuses to play one. This is deliberate:
silently accepting them would make a card look playable while doing nothing.