Files

729 lines
42 KiB
Markdown
Raw Permalink 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.
# Implications of the four recovered design files
Four files were added to `docs/` on 2026-07-30 that were part of the original design but never made
it into this workspace:
| File | What it is |
| --- | --- |
| `Deck cards2.xlsx` | The **complete card list** — every card, its count, where it may be placed, what it does |
| `Mainline Cards.pdf` | The **Mainline card types** — Plains, Curves, Hilly, Heavy Grade, Double Track, Uncontrolled Siding, Tunnel, Trestle, Yard, and both Division Points |
| `Trains3.pdf` | The **train cards** — all 22, with names, speed class, consist and individual operating rules |
| `tracks.png` | **Card art** for track and industry cards |
This document records what they imply and proposes what to do. **§1a below records what has since been
implemented**; everything else is still a proposal.
---
## 1. The headline: the game is roughly 3× what we built
| | Built | Recovered design | Change |
| --- | ---: | ---: | --- |
| Home Office deck | 52 | **115** | 2.2× |
| Track cards | in the deck (12) | **104**, a per-player supply of 26 | moved out of the deck entirely |
| Start cards | ad-hoc | **12** (4 Whistle Posts, 8 Limits) | formalised |
| **Total components** | ~52 | **231** | |
| Train cards | 16 | **22** | 12 timetabled + 10 Extras |
| Distinct card categories | 6 | **10** | four categories are entirely new |
The sheet's own totals (115 / 104 / 12 / 231) reconcile exactly with the line items, so these
numbers are the design's, not an inference.
**Most of my invented numbers are now superseded, and that is a good outcome.** Everything in
`card-reference.md` was explicitly provisional — placeholders standing in for exactly this document.
---
## 1b. Implementation status after the answers (2026-07-31)
All nine answers are implemented, **170 tests passing**:
| Answer | Implemented as |
| --- | --- |
| Q1 crossing time | `crossingStages()` — a 60 card takes 1 Stage, a 30 takes 2. Mainline nodes now carry a **terrain type** dealt at setup, and trains count down Stages instead of stepping through regions. The `Region` model is gone. |
| Q2 Fast/Slow | Slow adds one Stage to every card. Hilly reads the consist (any coach = passenger). |
| Q3 Expedite | An expedited train departs the Stage it arrives — it gets a second `moveTrain` in the same Mainline Phase, still subject to §8.1 clearance. |
| Q4 Lockouts | `isLockedOut()` rejects the placement with `FACILITY_LOCKED`. |
| Q5 Run-around | Nothing to do — reachability is geometric, so a built bypass already works. |
| Q6 Space-use | **Solitaire decks omit all 22 opponent-directed cards**: `buildDeck('solitaire')` returns **93**, competitive returns 115. |
| Q7 Downward-only | Office cards have a stub **below only**; turnout and curve legs always diverge south; placement and modifier candidates above the Running Track are rejected. §9's "nine nearby spots" is really **six**. |
| Q8 Crew Tray cap | Already correct. |
| Q9 Second Section | `newTrain.secondSection` plays on a train due out; an identical train is made up behind it next New Train Phase. The **Sister trains optional rule is removed** from Appendix B. |
**Enhancements (18) are now implemented** — placement rules, Small Yard consist re-ordering, ABS
Signals, Yard Office diversion, Interlocking, the Telegraph/Telephone/Radio dispatch bonuses and the
three defensive cards, covered by `test/enhancements.test.ts`.
**Mainline modifiers (7) and Maneuvers (6 of 7) are now implemented**, covered by
`test/mainline-cards.test.ts`. They are *not* multiplayer-only — that was a mistaken impression
given earlier. Brakeman, Airbrakes, Helpers and Realignment all change your own crossing times, and
Red Flags prevents a rear-ender, which happens in solitaire too. The real reason they lagged was
sequencing: Enhancements were done first because they change core loops.
| Card | Where it lives | Effect |
| --- | --- | --- |
| Brakeman, Airbrakes | `mainline.modify` on a grade | 1 Stage downhill each; Airbrakes needs Brakeman on the card |
| Helpers | `mainline.modify` on a grade | 1 Stage uphill |
| Realignment ×2 | `mainline.modify` on any Mainline card | converts per `REALIGNMENTS`; barred while a train is on the card |
| Facing Point Locks ×2 | grid, as the Enhancement | the sheet prints this card in **both** lists — one card, not two |
| Red Flags ×5 | `maneuver.redFlags` on a stopped train | an approaching train is held instead of colliding; flags come in when the train rolls |
| Flying Switch | `maneuver.flyingSwitch` during switching | cuts cars into an adjacent industry without the engine entering; costs a Move |
| Poling | — | **deliberately unimplemented** |
Crossing time never falls below one Stage — a train cannot cross in no time.
**Poling stays unimplemented.** The recovered sheet records its effect as "TBD in the source", so
there is nothing to build. A test asserts it remains TBD, to stop anyone "fixing" it by inventing
an effect; a silent no-op would be worse than a rejection.
**Q11, answered from the source.** The Heavy Grade card prints **"(Up)"** and **"Player sets
orientation"**, so which way it climbs is a property of the placed card, not a fixed compass
direction. `DivisionNode.gradeUp` records the direction a train travels when **climbing**; a train
going the other way is descending. Brakeman and Airbrakes apply to the descent, Helpers to the
climb, so turning the card around swaps which trains each card helps.
One gap remains, and it is a **setup** gap rather than a rules one: `createGame` is synchronous and
returns a ready state, so there is no point at which a player can be asked. Orientation is currently
**rolled** — deterministic from the seed, and roughly even (51/49 east/west across 400 games) — and
should become a real player choice when setup gains an interactive phase.
**Still not implemented**: the Action (10) and Space-use (12) cards, which are genuinely
multiplayer-only. Playing them is rejected with `NOT_IMPLEMENTED`.
### Parking trains — two engine bugs and a bot defect
Trains reached an Office and never left: **668 arrivals against 515 departures**. A train may only
highball from the Office square itself (§8.1, Gap 2b); from anywhere else `moveTrain` returns
`held`, permanently. 77 of 93 leftover crews were sitting somewhere they could never depart from.
Three separate causes, found by following the stranded crews:
1. **Reverse was hardcoded to east/west.** `destinationsFor` computed the backing-out port as
`facing === 'e' ? 'w' : 'e'`. A crew facing *south* reversed to *east* — a port a north-south
card does not have — so it could never back out of a district spur. Now `opposite(facing)`.
2. **Facing was derived from `direction`, which only carries east and west.** A crew standing on a
north-south spur was given an exit port its card did not have, leaving it with no legal moves at
all. `CrewTray.facing` now records the actual port, updated on every move from the port the crew
entered through.
3. **The bot never went home,** and its "no useful work" fallback took an *arbitrary* legal move —
the same shuttling bug as before, re-entered by a different door. It now heads for the Office
whenever nothing productive remains, and a crew stranded away from the Office can claim a whole
Local Operations turn to walk back.
Flying Switch was also mis-modelled: it tested **orthogonal adjacency** when the cut *rolls along
the track*, which both allowed a cut to cross to a cell with no rail between and refused a siding
two cards along the same track. It made the card nearly unplayable — held for 1,400 turns across 60
games and legal on 2. Now the target must be track-connected.
| | before | after |
| --- | --- | --- |
| arrivals / departures | 668 / 515 (77%) | **795 / 793 (99.7%)** |
| leftover crews stranded off the Office | 77 of 93 | 24 of 53 |
| collisions per game | 0.2 | **0.7** |
| revenue per player | 1.0 | **1.1** |
**Revenue got worse, and that is the honest result.** Parked trains were not colliding. With trains
circulating properly, every collision is now `no free A/D track` — 35 of 35 across 60 games — and
collisions cost **3.3** of the 1.1 net. The previous figure was flattered by a bug.
### A/D congestion is not congestion — it is the Whistle Post
Chasing it found no congestion at all. The Office is **empty at 88% of Stage starts** (occupancy 0
at 3,136 of 3,600) and mean dwell on an A/D track is **1.4 Stages**. Collisions are bursts, and they
are concentrated in one place:
- **25 of 26 collisions happen at Whistle Post**, which has **one** A/D track, so any second arrival
is an automatic collision (§8.3, Gap 2a). One collision occurred at Depot; none above it.
- **No collision was ever recorded in a district holding an Interlocking.** The enhancement is a
complete cure — it just arrives too late and too rarely.
- **25 of 100 games never escape Whistle Post at all**, and those are exactly the games that never
drew a Depot card. Mean first upgrade is Stage **9.3 of 60**.
The damage is concentrated, not spread:
| | games | mean revenue | worst |
| --- | --- | --- | --- |
| never upgraded past Whistle Post | 25 | **6.0** | 54 |
| upgraded at least once | 75 | **0.4** | +9 (best) |
That is what makes the median **+1.0** while the mean is **1.0**: a quarter of games are ruined by
a draw that never comes. The bot now plays an Office upgrade ahead of everything else and prefers
Interlocking over other Enhancements; both were previously unranked. Neither moves the mean, because
the constraint is **draw luck, not policy** — escaping Whistle Post requires one of **4 Depot cards
in 133**.
### Q12 answered — office density doubled
**Players always start at a Whistle Post**; that is settled and not up for change. The lever is
therefore card density. Office `copiesInDeck` is **doubled**: Depot 4→8, Station 2→4, Terminal 1→2.
Offices go 7 → 14 and the deck 133 → **140** (solitaire 111 → **118**).
Station and Terminal were doubled alongside Depot rather than lifting Depot alone, because upgrades
are strictly sequential (Gap 3b): the ladder has to stay a pyramid or players reach a rung whose
next card is scarcer than the one that got them there. The test now asserts that **property**
instead of the literal counts, so it survives the next density change.
| | 7 offices / 133 | 14 offices / 140 |
| --- | --- | --- |
| revenue per player | 1.0 | **0.7** |
| games never leaving Whistle Post | 25 | **13** |
| mean revenue, games that did upgrade | 0.4 | **1.9** |
| collisions per game | 0.7 | **0.3** |
| lost to collisions | 3.3 | **1.6** |
| worst game | 48 | 28 |
All 37 remaining collisions are still at Whistle Post, which confirms the diagnosis rather than
undermining it. Note the games that *still* never upgrade got worse (6.0 → 10.5): they are now a
smaller, unluckier group, so the mean is both more extreme and noisier. **Still 0 wins.**
> **PROVISIONAL — re-evaluate later.** These counts were chosen to remove a 25% chance of an
> unwinnable opening deal, not taken from the recovered design, and the instrument is blunt: it
> lifts the whole office ladder and dilutes every other category slightly. Revisit once the victory
> target is settled and freight carries its intended share. The better answer may turn out to be
> fewer Terminals, a cheaper first upgrade, or more A/D capacity at the Whistle Post itself.
### Measuring, after getting it wrong
A throwaway probe reported "60 of 60 games never upgraded past Whistle Post" while the Office-tier
histogram from the same run plainly showed Depots, Stations and Terminals. Events reach the log from
**two** sources — the phase driver (`pump`) and player intents (`applyIntent`) — and the probe
watched only the first. Office upgrades arrive through the second.
The cause was hand-rolling the drive loop. `playGame` already tallied both sources correctly; it was
re-implemented because it returns the event log but not the *state at the moment an event fired*,
which is what questions like "what tier was the Office at this collision" need.
`playGame` now takes an optional `PlayObserver``(event, state) => void`, called from the single
point both sources funnel through. Two tests guard it: one asserts the observer sees **exactly** the
events the log records, one asserts office upgrades are visible in the log across 25 games.
Reintroducing the original mistake fails both.
**A wrong measurement is worse than a missing one, because it gets believed and acted on.**
### Freight throughput — a self-inflicted deadlock
Freight was 10% of gross revenue with 27 industries on the board, so the Gap 12 tripling had bought
facilities but not freight. The pipeline said why: **415 loads started, 413 unjams, 13 completions**
across 60 games — a **3%** completion rate, with the Freight Agent spending more than half its
actions clearing jams it had caused.
A load leaves MEN|AT|WORK only onto a **spotted empty car of its own type** (§9.3). Starting one with
no car spotted parks it on WORK — and a load on WORK **locks the industry track**, which blocks the
very car that would clear it. The bot started a load whenever the intent was legal, so it jammed its
own facilities and then spent its turns unjamming them.
Two fixes, both in the bot; the engine was right throughout.
- **Only start a load that can finish.** `loadCanFinish` requires the receiving car to be spotted
already. Worth recording that the first attempt kept a last-resort `startLoad` "rather than idle a
Laborer" and measured *identical* to having no gate at all — the fallback was taken every time. An
idle Laborer is strictly better than a jam, which costs an action to clear and locks the track
meanwhile.
- **Weigh the whole consist, not just the back car.** 744 switch turns produced 135 Moves and 741
immediate ends: a crew holding wanted cars behind one unwanted car concluded there was nothing to
do. §A.3 makes the back car the only *droppable* one; it does not make it the only one worth
travelling for. The crew now sets out dead weight on a plain spur **before** travelling — ordering
that matters, because doing it after produced the shuttling loop for the third time.
| | before | after |
| --- | --- | --- |
| loads started / completed | 415 / 13 (**3%**) | 44 / 38 (**86%**) |
| unjams | 413 | 281 |
| cars dropped | 151 | 197 |
| cars coupled | 14 | 25 |
| unloads completed | 40 | 74 |
| **revenue per player** | 0.7 | **2.2** |
| cards played | 12.4 | 16.9 |
| trains scheduled | 2.0 | 2.7 |
| passenger revenue | 1.3 | 2.7 |
Freeing the Laborers freed the whole turn economy — passenger revenue doubled without a single
passenger rule changing. **Still 0 wins against a target of 20**, and freight is still only 13% of
gross, so the loop runs now but does not yet carry the game.
### Track was unplayable (found while wiring up Enhancements)
Moving track out of the deck into a per-player supply (§12.2) left **no way to play it**. Districts
could only grow through Freight-Facility and Modifier cards, so the Running-Track and
Secondary-Track *straights* that Enhancements attach to essentially never existed. Two bugs
compounded it: `legalActions` offered Enhancements only **empty** grid cells, when an Enhancement
attaches to an **occupied** card.
Measured before the fix: a hand held a playable Enhancement on **4,778** turns and could legally
place one on **33** — and those 33 were all ABS Signals, which targets a Mainline card rather than
the grid.
Fixed by adding a `track.lay` intent drawing from `OfficeArea.trackSupply`, and by giving
Enhancements the occupied cells as candidates. Enhancement placements went 21 → 98 per 40 games.
**Q10, answered.** Track is laid during the "draw a card" option, **one piece a turn** — which is
how track behaved when it *was* a card.
### Measurement after the answers
100 solitaire Standard games: mean revenue **1.3**, trains scheduled **2.8**, cards played **11.3**.
After Enhancements and the track fix: mean revenue **0.0**, trains scheduled **2.9**, cards played
**13.9**, collisions **0.3**. Still **0 wins against a target of 20**.
### Gap 12 resolved — industry density
The shortfall was structural rather than a missing rule. Freight was 10% of gross revenue and
`carsCoupled` fired **4 times in 100 games**: the chain needs a Freight Facility, an empty car of
its exact type spotted on its industry track, three Laborer advances, and then a crew with spare
capacity to lift the load — and there were only **1.6 freight facilities per game**, because the
recovered sheet puts **9 industries in a 115-card deck** where the prototype had 10 in 52.
**Every industry's `copies` is tripled: 9 → 27, deck 115 → 133** (solitaire 93 → 111). Tripling
uniformly restores roughly the prototype ratio while preserving the sheet's proportions exactly —
the outbound/inbound balance and the lockout structure are untouched.
`ROLLING_STOCK_SUPPLY` scaled with it, from 62 pieces to **80**: worst-case demand at 27 industries
is boxcar 15, hopper 12, tank 9, reefer 6, and a Division Yard that runs dry would starve the very
loop the increase exists to feed. That supply was already flagged as provisional, not transcribed.
| | 9 industries / 115 | 27 industries / 133 |
| --- | --- | --- |
| revenue per player | 0.0 | **1.1** |
| freight facilities per game | 1.6 | **3.6** |
| freight share of gross | 10% | **18%** |
| laborer actions | 9.8 | **16.9** |
| collisions | 0.3 | **0.1** |
| trains scheduled | 2.9 | **2.1** |
First positive mean revenue recorded, and the `carsCoupled` anomaly cleared. **Still 0 wins against
a target of 20**, so this is progress on a diagnosis, not a balanced game. Note the side effect:
trains scheduled fell 2.9 → 2.1, because 22 train cards in 133 are drawn less often than 22 in 115.
Train density may need the same treatment.
Still no wins, and still **not a verdict** — roughly a third of the deck does nothing yet, and the
Small Yard enhancement (which is what makes the switching puzzle solvable) is among the unimplemented
cards. Gap 12 stays invalidated until the enhancements are in.
---
## 1a. What has been done so far (2026-07-31)
**Transcribed and in code**, with 169 tests passing:
- The full **115-card deck**`deckComposition()` reconciles exactly with the sheet's own total.
- **Track removed from the deck** and modelled as a per-player supply of **26** pieces
(`TRACK_SUPPLY`), with printed handedness and a **move cost** field (2 for sharp curves).
- **Curves** added to the track graph; the invented run-around card removed.
- All **22 trains** with names, Fast/Slow speed class, category-based consists and per-card
operating rules.
- **Industries retuned to 1-out / 1-loader**, with the real six kinds and their lockout lists.
- All **23 modifiers**, each tied to its specific hosts, with their effects applied on placement.
- **Office slots corrected** to equal porter count; deck copies corrected to Depot 4 / Station 2 /
Terminal 1.
- The **ten Mainline card types** with speeds and named entry points, as data.
- The four new categories (space-use, enhancements, mainline modifiers, maneuver, action) are in
the deck. **Playing them is rejected with `NOT_IMPLEMENTED`** rather than silently doing nothing —
the failure mode that left Modifiers as dead weight for weeks.
**Not done, pending the questions in §10**: the speed model, Expedite, lockout enforcement,
space-use semantics, and everything the four new categories actually do.
### First measurement on the real catalogue
100 solitaire Standard games, same bot: mean revenue **1.9**, trains scheduled **2.3** (was 4.8),
cards played **10.5** (was 16.3).
Development has slowed sharply, and the reason is visible in the composition: **industries are now
9 cards in 115 (7.8%), where the placeholder had 10 in 52 (19%)**. Their density more than halved,
and trains fell from 16-in-52 to 22-in-115. The deck is much more diluted, which is exactly what the
enhancements, maneuver and action cards are there to fill — and none of those do anything yet.
**Read no balance conclusions from this number.** It measures a half-implemented ruleset.
---
## 2. Deck composition
### What the design says — 115 cards
| Category | Cards | Notes |
| --- | ---: | --- |
| Offices (Depot 4, Station 2, Terminal 1) | 7 | *We had 9 (4/3/2)* |
| Passenger modifiers (Waiting area 3, Restaurant 2, Hotel 1) | 6 | each adds 1 passenger-out + 1 porter |
| Industries (Freight House 2, Mine Tipple 2, Refinery 1, Power Plant 2, Packing Sheds 1, Grocer's Warehouse 1) | 9 | *We had 10 in a different mix* |
| Industry modifiers | 17 | each tied to a **specific** industry |
| Trains (12 timetabled + 10 Extras) | 22 | *We had 16* |
| **Space-use cards** | 12 | **entirely new** — cards that burn table space |
| **Enhancements** | 18 | **entirely new** |
| **Mainline modifiers** | 7 | **entirely new** |
| **Maneuver cards** | 7 | Red Flags ×5, Flying Switch, Poling |
| **Action cards ("screw you")** | 10 | **entirely new** — played *at other players* |
| **Total** | **115** | |
### Proposal
- Replace `content.ts` wholesale with this catalogue. It is data, so this is transcription rather
than design.
- **Gap 4a (52-card deck) is superseded.** Record it as such rather than deleting the reasoning —
the deck was a stand-in and it did its job.
- **Gap 13 (deck scaling by player count) largely dissolves.** Track is now per-player by
construction, which was the real pressure I measured. The 115-card deck is shared. Re-measure
before concluding anything further.
---
## 3. Track — the biggest structural change
### What the design says
Track is **not in the deck**. Each player gets a fixed personal supply of **26 pieces**:
| Piece | Per player | Total (4p) | Notes |
| --- | ---: | ---: | --- |
| Straight | 8 | 32 | |
| Curved left | 4 | 16 | **we have no curves at all** |
| Curved right | 4 | 16 | |
| Sharp curved left | 1 | 4 | **any move across is doubled — two Moves** |
| Sharp curved right | 1 | 4 | |
| Turnout left | 4 | 16 | |
| Turnout right | 4 | 16 | |
Column J ("Train can stop here") is set for straights and curves, blank for turnouts — which matches
what we built: a turnout is not Operational Rail.
### What this changes
1. **Curves exist and we have none.** Our geometry is straight / turnout / run-around. The design has
straight / curved / sharp-curved / turnout, each in left and right hands. Run-around is not a card
at all — it is presumably *built* from a turnout pair.
2. **Handedness is printed, not chosen.** Left and right are distinct physical cards.
**Gap 11's decision — "orientation is chosen on placement" — is therefore superseded.** The
measurement behind it stands (a fixed default made vertical growth impossible), but the design's
answer is different and better: give the player a supply containing both hands.
3. **Sharp curves cost two Moves.** A per-card movement cost, which our Move model does not have.
4. **Track no longer competes for deck slots**, so the draw is entirely about industry, trains and
enhancements. This materially changes the economy I measured.
### Proposal
- Rework `track.ts` around a per-player supply with printed handedness; drop the variant machinery.
- Add a **move cost** per card (1 normally, 2 for sharp curves) and charge it against the six Moves.
- Confirm with the designer whether run-around is a built pattern rather than a card — see §10.
---
## 4. Industries and modifiers — much smaller, much more specific
### What the design says
Each industry is **one car out and one loader**, not the 23 capacity and 23 Laborers I invented:
| Industry | In deck | Car | Direction | Base capacity |
| --- | ---: | --- | --- | --- |
| Freight House | 2 | Box | BOTH | 1 boxcar out, 1 loader; boxcars in |
| Mine Tipple | 2 | Hopper | OUT | 1 hopper out, 1 loader |
| Refinery | 1 | Tank | OUT | 1 tank out, 1 loader |
| Power Plant | 2 | Hopper, Tank | IN | 1 loader |
| Packing Sheds | 1 | Reefer | OUT | 1 reefer out, 1 loader |
| Grocer's Warehouse | 1 | Box, Reefer | IN | — |
Capacity is then grown by **industry-specific modifiers**, each adding "+1 out, +1 loader":
- Mine Tipple → Prep Plant, Coal Piles, Conveyor Belts
- Refinery → Pipelines, Oil Depot, Viscosity breakers
- Power Plant → Transmission lines, Rotary Dumps, Steam Turbines
- Packing Sheds / Grocer's → Ice House, Local small groceries
- Freight House / Packing Sheds / Grocer's → Truck dock, Forklifts, Railroad Express Agency
**Column E is a lockout list** — a concept we do not have at all. Freight House locks out Grocer's
Warehouse; Mine Tipple locks out Power Plant; Refinery locks out Power Plant; Packing Sheds locks out
Grocer's Warehouse. Presumably a player may not build both of a locked-out pair.
### Passenger side — our guesses were right
| Office | Design | What we built |
| --- | --- | --- |
| Depot | 1 psgr out, 1 in, 1 porter, **2 A/D** | 1 porter, 2 green, 2 red, 2 A/D |
| Station | 2 / 2 / 2 porters, **3 A/D** | 2 porters, 3 green, 3 red, 3 A/D |
| Terminal | 3 / 3 / 3 porters, **4 A/D** | 3 porters, 4 green, 4 red, 4 A/D |
| Whistle Post | 1 A/D, not in deck, 4 copies | 1 A/D ✓ |
Porters and A/D tracks match exactly. **Our slot capacities are one too generous at every tier**
the design gives slots equal to porters, not one more. Passenger modifiers (Waiting area, Restaurant,
Hotel) are what grow them.
### Proposal
- Retune every industry to **1 out / 1 loader** and rebuild capacity growth around the 17 modifiers.
This makes Gap 10a's "moderate, varied by industry" profile obsolete.
- Correct passenger slots to equal porter count.
- Implement **lockouts** — a new placement constraint.
- **This changes the economy substantially**: a base industry is far weaker than what we modelled, so
Gap 12's balance measurements must be re-run from scratch rather than adjusted.
---
## 5. Trains — names, speed classes, and per-train rules
### Timetabled (112)
| # | Name | Speed | Consist | Rule |
| --- | --- | --- | --- | --- |
| 1/2 | Crack Limited | Fast | 3 coaches | Stop at Terminals only. No switching. Expedite. |
| 3/4 | Express | Fast | 2 freight | May drop or pick up one freight car at every location. Expedite. |
| 5/6 | The Sparrow | Fast | 2 coaches | No switching. Expedite. |
| 7/8 | Local | Slow | 1 freight + 1 coach | Coach must remain on station track if switching. |
| 9/10 | Heavy Freight | Slow | 3 freight + caboose | |
| 11/12 | Drag Freight | Slow | 2 freight + caboose | |
### Extras (X13X22) — ten distinct trains, not four generic ones
Appleseed Extra (MT freight only, may drop but not pick up), Fruit Growers Express (reefers only),
Yard Xfer, Light Engine Move (no cars at all), Campaign Train (one turn at station for speeches),
Circus Train (**one turn stopped anywhere earns 1 point**), Military Train, Director's Private Car,
Freight Extra, Pee-Dee (per-diem, may only pick up empties). Plus a **Second Section** card that
duplicates the next scheduled train's seniority, rules and consist.
### What this changes
1. **Consists are by CATEGORY** — "Freight (2)" means any two freight cars, not two hoppers. Our
`allowedTypes` model is too narrow.
2. **Fast / Slow is a train property** that pairs with the Mainline cards' 60/30 speeds (§6). We have
no speed model at all.
3. **"Expedite"** is a keyword appearing on seven trains, meaning is not yet defined for us.
4. **Per-train operating rules** — "no switching", "stop at Terminals only", "may drop or pick up one
freight car at every location". We have none of these.
5. **Extras are X13X22**, all junior to every timetabled train. **Gap 5 (Extra vs Timetabled ties)
becomes unreachable** — the tie it resolves cannot occur. The decision is harmless but moot.
6. **The Circus Train earns a point for standing still** — the first revenue source that is not a
load/unload operation. Our scoring model assumes only §9 operations and collisions.
7. **Second Section** makes the "Sister trains" optional rule concrete.
### Proposal
- Rewrite the train catalogue from `Trains3.pdf`.
- Add `speed: fast | slow` and a `rules` field per train; implement the operating rules as checks in
`apply.ts`.
- Define "Expedite" with the designer before implementing it — see §10.
---
## 6. Mainline cards — a whole system we reduced to a constant
We modelled a Mainline card as **2 regions, uniform**. The design has **ten distinct card types**:
| Card | Speed | Notes |
| --- | --- | --- |
| Plains | 60 | |
| Curves | 30 | |
| Hilly | **P60 / F30** | different speeds for passenger and freight |
| Heavy Grade (Up) | **G** | player sets orientation; Brakeman/Airbrakes/Helpers unlock better start positions |
| Double Track | 60 | **trains may pass** |
| Uncontrolled Siding | 60 | trains may pass; separate "no pass" and "passing" starts |
| Tunnel | 30 | |
| Trestle | 60 | |
| Yard | 60 | **sort cars into any new order**; has a Yard Limit |
| East / West Division Point | — | the ends |
Each card shows **Start positions** — where a train enters depending on direction, train type, and
which modifier cards are in play. The Heavy Grade card has five distinct starts (plain, brakemen,
airbrakes, plain, helpers), so playing Brakeman literally moves your entry point further along.
`Realignment` can convert one Mainline card type into another (Plains→Double Track, Curves→Plains,
Uncontrolled Siding→Double Track, Trestle→Uncontrolled Siding).
### What this changes
**This is the single largest mechanical gap.** Our Mainline Phase moves every train one region per
Stage, unconditionally. The design has speed classes, per-train-type speeds, passing, grades that
modifier cards ameliorate, and yards that re-sort consists.
It also bears directly on **Gap 12**. I measured "a train stands at the Office only 18% of Stages"
and treated it as a possible balance problem. With Double Track, passing sidings, and 60-speed
cards, traffic density is a *designed variable* — the measurement was taken against a placeholder.
### Proposal
- Model Mainline cards as typed, with a speed and a set of named entry points.
- Implement Fast/Slow × card-speed to derive how far a train moves per Stage.
- **Re-run every Gap 12 measurement afterwards.** The current numbers describe a game that does not
exist.
---
## 7. Four entirely new card categories
### Space-use cards (12)
Bean House, Flop House, Watertower, Hobo Jungle, Section House, City Blocks ×4, Engine Shops,
Tenderloin District, Engineer Cemetery. All "burn tablespace" — they occupy a grid cell and do
nothing for you. Presumably played at opponents, or a cost of drawing.
### Enhancements (18)
- **Interlocking** (+ Facing Point Locks): may stop an inbound train on the Limit track.
- **Yard Office**: an inbound train with no coaches may arrive at the yard instead of the Train Order
Office.
- **Small Yard**: a train spending one Move in the yard **may sort itself into any order, including
cars ahead of the engine**.
- **Water Column**: lets you remove a Watertower.
- **Overpass**: removes restrictions on a Railroad Crossing.
- **Telegraph / Telephone / Radio**: once a day, when dispatching facing trains, add **+4 / +8 / +12**
to the other train's number. A genuine dispatching-technology progression.
- **ABS Signals**: trains on this Mainline card will not rear-end each other; they stop short.
**Small Yard deserves special note.** It solves precisely the problem my bot cannot handle: §A.3
forces cars off in seated order, so spotting a specific car needs the consist re-ordered. A Small
Yard makes that possible. The switching puzzle was *designed* to have this answer, and we did not
have the card.
**ABS Signals directly touches Gap 2.** We made collisions unconditional; this card makes them
avoidable on a given card.
### Mainline modifiers (7)
Brakeman, Airbrakes (requires Brakeman), Helpers, Realignment ×2, Facing Point Locks ×2.
### Action cards — played at other players (10)
Derail, Broken Coupler, Railroad Crossing, Per Diem Inventory, Demurrage Charge, Customer
Complaints, Vandalism, Hotbox, Outlawed.
**We have no player-interaction mechanic whatsoever.** Several of these cause *point losses* based on
board state — "lose one point per 2 empty cars on Secondary Tracks" — which is a scoring channel our
model does not have. In a Competitive game these are presumably a large part of the tension.
### Proposal
Treat these as four separate work packages, in this order: **Enhancements** (they change core
movement and switching), **Mainline modifiers**, **Action cards** (needed for multiplayer to mean
anything), **Space-use** (lowest mechanical weight).
---
## 8. What this does to the decided gaps
| Gap | Status now | Why |
| --- | --- | --- |
| 1 Phase order | **stands** | nothing in the new files contradicts it |
| 2 Collisions automatic | **amended** | ABS Signals makes them avoidable on a card |
| 3 Office upgrades | **stands**, counts confirmed | A/D and porters match exactly |
| 4a Deck composition | **superseded** | 52 → 115, track removed from deck |
| 4b Piece counts | **needs re-derivation** | Mainline speeds change train turnaround entirely |
| 4c Consist criteria | **superseded** | consists are by category, with per-train rules |
| 5 Extra/Timetabled ties | **moot** | Extras are X13X22; the tie cannot occur |
| 6 Victory conditions | **needs re-derivation** | new revenue sources and point losses |
| 7 Terminology | **stands** | |
| 8 Office junction stubs | **needs checking against the art** | `tracks.png` shows the through-line at the card's top edge, not the middle |
| 9 Make-up round repeats | **stands** | |
| 10 Card faces | **superseded** | this is the real card list |
| 11 Track orientation | **superseded** | handedness is printed; both hands are supplied |
| 12 Balance targets | **invalidated, re-measure** | measured against a placeholder ruleset |
| 13 Deck scaling | **largely dissolves** | track is per-player by construction |
Superseded decisions should be **marked, not deleted** — the reasoning that produced them is how we
know what questions the design answers.
---
## 9. Code impact
| Component | Impact | Notes |
| --- | --- | --- |
| 1 Card catalogue | **Rewrite** | pure data; largest single edit but lowest risk |
| 2 State model | **Major** | new card kinds, per-player track supply, typed Mainline cards, train speed/rules |
| 3 Track graph | **Major** | curves, printed handedness, per-card move cost |
| 4 apply | **Major** | per-train operating rules, enhancements, action cards played at opponents |
| 5 Phase driver | **Major** | speed model, passing, grades, yard sorting |
| 6 legalActions | Moderate | follows from 4; the discipline of delegating to `check` protects it |
| 7 RNG | None | |
| 17 Bot | **Rewrite** | Small Yard changes the switching problem fundamentally |
| 18 Harness | Minor | re-run everything |
| 16 Replay | Moderate | new card types and mechanics to narrate |
| 19 Tests | **Substantial** | most rules assertions need revisiting |
**The engine's architecture holds.** Nothing here breaks the `check`/`execute`/`reduce` split, the
event log, or the pure-engine boundary. This is a large content and rules expansion inside a
structure that was built to take it — which is the main thing worth saying about it.
---
## 9a. Answers from the designer
Recorded as they are given, so nothing is lost between sessions.
| # | Question | Answer |
| --- | --- | --- |
| 1 | What do Mainline 60 / 30 mean? | **Miles per hour, expressed as crossing time.** A 60 card takes **one Stage** to cross; a 30 card takes **two**. The printed cells are decoration. Realignment (Curves→Plains) therefore has real value, and 30-cards are genuine chokepoints. |
| 2 | How does Fast/Slow affect crossing? | **Slow adds one Stage to every card.** Fast 60→1, 30→2; Slow 60→2, 30→3. The label therefore matters on every card. Consequence to watch: Slow trains occupy a Crew Tray roughly twice as long, so tray scarcity (§7) bites considerably harder than the placeholder measured. |
| 3 | What does "Expedite" mean? | **The train departs the same Stage it arrives** — it does not spend a Stage standing at the Office. Still subject to the normal §8.1 clearance rules, so it can be held. Fits X17's "one turn at station *then* expedite", and partly offsets the Slow-train transit cost below. |
| 4 | What does a lockout prevent? | **Building both in your district.** If you hold a Mine Tipple, a Power Plant card is unplayable in your Office Area, and vice versa. Each locked pair is a producer and the consumer of the same commodity, so this forces traffic to flow *between* districts — a deliberate multiplayer-interdependence mechanic. In solitaire it simply narrows the build options. |
| 5 | Is a run-around a card? | **No — a pattern built from the track supply.** Opposite-hand turnouts joined by straights. Nothing to implement: reachability is computed from geometry, so a valid bypass already works. This explains the 8 turnouts per player, and makes §A.5's facing-point move a building achievement rather than a lucky draw. |
| 6 | How are Space-use cards played? | **At another player's district**, consuming a grid cell they wanted. This explains Water Column ("remove any Watertower in *your* district" — one an opponent gave you) and Vandalism (exploits a Hobo Jungle you were saddled with). A second, milder attack channel alongside the Action cards. **In solitaire they have no target** — see the note below. |
| 7 | Does a district grow both ways? | **Downward only** — the through-track sits at the card's top edge and everything diverges beneath it, matching `tracks.png`. A district is a Running Track with all Secondary Track hanging below. **Supersedes Gap 8's north-and-south stubs.** Consequences: buildable area halves; districts become long and shallow; §9's nine-spot Modifier neighbourhood needs rewording, since three of the nine spots are above the track and no longer exist. |
| 8 | Any cap on trains in play? | **No — Crew Trays are the only limit.** All 12 timetabled trains may end up scheduled; Extras run on top ad hoc; a due train with no free crew is held (§7). Already implemented. This makes the Crew Tray count (`players + 3`) the single most important balance dial, and "held" a common visible state. |
| 9 | What is the Second Section card? | **A card played on a train that is due out.** A second identical train runs immediately behind it — same number, rules and consist — and needs its own Crew Tray. It deliberately creates the following-train situation §8.1 makes the Superintendent rule on, so a player can force the game's central decision onto the table. Explains the green flags on the artwork. **Supersedes the "Sister trains" optional rule**, which should be removed from Appendix B. |
### Solitaire consequence of Q6
If Space-use cards are played at opponents, then in the **solitaire MVP they have no legal target**
12 of 115 cards (10.4%) become dead draws. Combined with the 10 Action cards, which are also
opponent-directed, **22 of 115 cards (19%) do nothing in a one-player game.**
That is a real finding for the MVP, and there are only a few honest ways to handle it: remove them
from a solitaire deck, allow them to be discarded freely, or accept that solitaire draws are a fifth
dead. Worth deciding explicitly rather than by default. Not blocking — flagged for after the
remaining questions.
### Consequence noted at the time of answering
Under Q1 + Q2, on a 3-player Division (4 Mainline cards, mixed terrain):
| | Mainline Stages | + Office stops | End-to-end |
| --- | ---: | ---: | ---: |
| Fast train | 6 | 3 | **9 Stages** |
| Slow train | 10 | 3 | **13 Stages** |
A Day is 12 Stages, so **every Slow train is still on the road when the next Day begins**, holding
its Crew Tray. With `players + 3` trays this will throttle freight hard. Expedite (Q3) relieves it
somewhat for the trains that carry it — but none of the Slow freight trains do. Worth re-measuring
once the speed model is implemented; the Crew Tray count is the obvious dial.
---
## 10. Questions only the designer can answer
1. **"Expedite"** — appears on seven trains and is never defined. Priority? No stopping? Extra speed?
2. **Speed numbers.** Do 60 and 30 mean "cells per Stage", "Stages to cross", or literal mph against
a 2-hour Stage? A Mainline card is "roughly a hundred miles" (§2.1), so 60 mph × 2 h ≈ one card
per Stage and 30 ≈ two — but this should be confirmed, not inferred.
3. **Fast vs Slow trains** — how do they interact with a card's speed? Does a Slow train take double
on every card, or only where the card distinguishes (Hilly's P60/F30)?
4. **Lockouts** (spreadsheet column E) — does one card prevent *building* the other, or prevent both
*operating*?
5. **Run-around** — we treat it as a card; it is not in the supply. Is it a pattern built from two
turnouts?
6. **Space-use cards** — played at yourself as a cost of drawing, or at opponents?
7. **Where the Office's junction stubs are.** `tracks.png` draws the through-line along the top edge
with curves diverging downward. Gap 8 assumed stubs above *and* below a centred track.
8. **Are all 22 trains in play at once**, or is the timetable still 12 slots with Extras run on top?
9. **Second Section** — is it a card played on a scheduled train, or its own train?
---
## 11. Recommended sequencing
The temptation is to rebuild everything at once. I would not.
1. **Transcribe the catalogue first** (`content.ts` from the spreadsheet and `Trains3.pdf`). Pure
data, no rules risk, and it makes the true scope concrete.
2. **Answer §10's questions**, particularly speed and Expedite — several later decisions hang on
them.
3. **Mainline card types and the speed model.** The largest mechanical gap and the one that
invalidates the current balance numbers.
4. **Track supply and curves**, including the sharp-curve double Move cost.
5. **Industry retune to 1-out/1-loader plus the modifier system**, then re-run the harness. Expect
very different numbers.
6. **Enhancements**, starting with Small Yard and ABS Signals — both change core loops.
7. **Action cards**, which is when multiplayer becomes a real game rather than parallel solitaire.
8. **Space-use cards** last.
**Do not retune anything against current measurements.** Gap 12's numbers describe a placeholder
ruleset. Re-measure after step 5 and treat everything before that as void.