the Roster Pass: every train at the Office visible
Builds "The Roster Pass" / "Two Trains, One Card" (station display for multiple trains at one Office). The Office is the one square where more than one train may legally stand at once (one per A/D track), and CellView.train had room for exactly one — a second train at a busy Station was counted in the old A/D pips and never drawn. CellView.train -> CellView.trains: TrainView[], seat-filtered and collecting every match rather than the first (fixes a latent cross-district leak in the process: trainOnCard never checked seat). The A/D pips are replaced with one roster chip per A/D track, always, free or occupied; clicking a chip sets selectedCrew, wiring the board and the action panel to the same value. standingWest moves from CrewTray to TrackCard: two trays sharing one Office card need one shared split, not one each, and there is no such thing as "west of one particular A/D track". No save migration — Save replays through the engine — and a stale value on an emptied card is inert because nothing reads a split with no train standing there. The Division map's Office cell is now sized by A/D capacity rather than occupancy, so it holds still as trains arrive and leave; chips lay into fixed slots instead of centre-spreading onto the Limits cards either side. 584 tests, 0 failures. Verified end-to-end against the built app and a direct render of a 4-train Terminal (screenshotted). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SAt2YCXgd5qCjBcF2x34aK
This commit is contained in:
+44
-3
@@ -21,9 +21,10 @@ page as `v0.1.0 · <sha> · <date>`, so what is deployed can always be identifie
|
||||
|
||||
## 0.4.8 — 2026-08-19
|
||||
|
||||
Three reports from the same game, all about squares: which ones a card may go on, which one a button
|
||||
in the action list means, and — when there is more than one legal road to the same square — which
|
||||
one a train actually takes.
|
||||
Four reports from the same game, all about squares: which ones a card may go on, which one a button
|
||||
in the action list means, when there is more than one legal road to the same square which one a
|
||||
train actually takes, and — when more than one train is standing at the same Office — which is
|
||||
which.
|
||||
|
||||
### The Limits bound the district, not just the Running Track
|
||||
|
||||
@@ -168,6 +169,46 @@ built a district where the discarded route would have mattered. 400 full games (
|
||||
ablation flag to run at all and this is not a bot heuristic, so paired A/B was not applicable here;
|
||||
the enumeration-based argument above is the actual evidence.
|
||||
|
||||
### The Roster Pass — every train at the Office visible
|
||||
|
||||
**The Office is the one square where more than one train may legally stand at once** — it has
|
||||
several A/D tracks, each holding one — and the board drew it as if only one ever could. Two trays
|
||||
at a Station couple onto the identical `officeCoord`; `trainOnCard()` returned on the first match
|
||||
and `CellView.train` had room for exactly one, so a second train was counted in the old A/D pips
|
||||
and never drawn at all. Reported directly, and analysed in "Two Trains, One Card": the pips and the
|
||||
picture were reading different fields.
|
||||
|
||||
**`CellView.train` is now `CellView.trains: TrainView[]`** — every train standing on the card, each
|
||||
carrying its own `trayId`. The A/D pips are gone; in their place is one roster chip per A/D track,
|
||||
always (`adTracks` of them, not one per train), free tracks reading a dashed, dimmed "free" rather
|
||||
than vanishing. The selected train's chip is lit the same amber the crew strip and action buttons
|
||||
use, and its consist is the one drawn at the rail — clicking any occupied chip sets `selectedCrew`,
|
||||
the same value the "Which train are you switching?" picker already wrote, so the board and the
|
||||
action panel drive one value in both directions.
|
||||
|
||||
**`standingWest` moved from `CrewTray` to `TrackCard`.** The split still means what it always meant
|
||||
— west/east of the row of standing cars — and it is still only meaningful while an engine stands on
|
||||
the card (an unattended cut has no near or far side; that reasoning did not change). What forced the
|
||||
move: two trays sharing one Office card could otherwise hold two different splits of the identical
|
||||
row, and there is no such thing as "west of one particular A/D track" — a cut lies west or east of
|
||||
the *whole block* of A/D tracks, so there has to be exactly one number for the card to carry. No
|
||||
save migration: `Save = {seed, history, rules?}` replays through the engine rather than being
|
||||
loaded, and a stale value on an emptied card is inert because nothing reads a split with no train
|
||||
standing there.
|
||||
|
||||
**The Division map stopped drawing trains on their neighbours.** The Office's Running Track cell was
|
||||
a fixed 78px regardless of how many A/D tracks it had, so two chips centre-spread wider than the
|
||||
cell and spilled onto the Limits cards either side. The cell is now sized by **capacity**
|
||||
(`max(78, adTracks·54+12)`), not by how many tracks are occupied — sized by occupancy instead, the
|
||||
board would have shifted the East Division Point sideways every time a train arrived or left — and
|
||||
chips are laid into fixed slots, one per A/D track, so none can ever overhang the cell.
|
||||
|
||||
**Verified:** two trays at a Station are both drawn, each with its own chip; a Terminal's four
|
||||
tracks all fit; a bare cut with a stale `standingWest` still draws left-aligned; every roster chip's
|
||||
x-extent lies inside its Office cell at full occupancy; and a packed replay row from before this
|
||||
feature — a lone train object, not an array — rehydrates into a one-train roster rather than
|
||||
throwing. 584 tests, 0 failures.
|
||||
|
||||
### Also
|
||||
|
||||
- The three published replays were re-recorded. A save is a seed and its intents, so tightening a
|
||||
|
||||
Reference in New Issue
Block a user