diff --git a/CHANGELOG.md b/CHANGELOG.md index 727e310..897e62f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,76 @@ page as `v0.1.0 · · `, so what is deployed can always be identifie ## Unreleased +## 0.4.3 — 2026-08-14 + +### A load has to have somewhere to go + +Jesse walked through how loading an industry is meant to work at the table, and the engine got four of +the five steps exactly right. It got the first one wrong, in both directions. + +**You could stage cargo against no car.** §9.3 requires an empty car of the right type standing on the +industry's track before anything else happens — *"otherwise you are just dropping cargo onto the +tracks, pointless waste"*. The engine checked for that car only at the **last** step, when the load +came off WORK. So you could fetch cargo with the Freight Agent, walk it M→A→W across three Stages and +three Laborers, and only then find there was nowhere to put it. Worse than waste: from the moment the +load lands on M the industry track is **locked**, so no train can come in to spot the car you now need. +The only way out was a Freight Agent unjam — another whole turn, to undo a move the rules should never +have offered. + +Now gated in three places, all counted rather than merely present: + +- **`freightAgent.stockOutbound`** — no cargo is fetched unless a matching empty is spotted and not + already promised to a load already in the box or on the sign. +- **`laborer.startLoad`** — the same check again, because it is not redundant: coupling is mandatory, + so a crew running over that industry track *must* pick up the spotted empty, and the cargo you + staged an hour ago can be left with nothing. +- **`laborer.beginUnload`** — the mirror. The red Inbound box is where an inbound load lands, and it + was checked only at the final step too. Counted, because only the W box must be free to begin: once + a load moves W→A a second can start behind it, and every red box in play holds exactly one car. + +**Strict type matching throughout** — a hopper load cannot be swapped onto a tank. And `startLoad` no +longer always takes `outboundBox[0]`: it starts the first load that has a car to land on, so a Power +Plant holding a hopper load and a tank load against one spotted tank works the tank instead of +reporting the whole facility blocked. + +**Passengers are deliberately exempt and it is written down.** People can wait on a platform for a +train that has not arrived, so a Passenger Facility still stocks freely. Freight cannot: a crate on the +ground is not a shipment. + +**Measured before building it, which is why it was worth building.** Requiring the car removes **78% of +the `stockOutbound` moves the menu offered** (704 → 157 across 200 games) — but **99.3% of the moves the +bot actually took survive** (138 of 139). The rule deletes offers a competent player would never have +used. Bot unchanged at 7.3 mean. On the unload side it removes 2.2% of offers, and the jam it prevents +was caught happening three times in 200 games. + +### The Blocked panel says what to do, and in what order + +The refusal codes never reach a player, because the menu simply stops offering the action — so with +78% of stocking moves gone the panel was the only thing that could explain it. It said *"green box +empty — nothing to load (needs a Freight Agent action)"*, which is step two told to someone who has not +done step one. It now says to bring a car in first, names the commodity, and distinguishes "MEN is +occupied" from "there is nothing here to load onto", which send you to fix quite different things. + +### Rolling stock is exactly conserved + +`TODO.md` recorded the inbound path minting ~1.3 cars a game and blocked tuning `ROLLING_STOCK_SUPPLY` +until it was settled. Re-audited: **exactly conserved, 100 games out of 100, range 0..0.** The +asymmetry had already been closed from the other end when `unloadBegan` and `passengersDetrained` +started taking their replacement empty out of the Division Yard instead of conjuring it — a load is a +car that moved, not a car that appeared, which is exactly the tabletop procedure Jesse described. + +Both conjuring fallbacks now **throw** instead of minting, so the leak cannot come back quietly; +neither fired across the suite or the audit. `ROLLING_STOCK_SUPPLY` is unblocked for the rebalance. + +(The original audit's arithmetic was off in the same way mine was on the first attempt: cars set out on +a card live in `card.standing` and are easy to leave out of the count, which makes a conserved game +look like a leaking one.) + +### Replays + +Two of five died on the rule change — they replayed 138/336 and 81/347, which on screen looks exactly +like a game that ended early. Re-recorded; three published, all verified to their last intent. + ## 0.4.2 — 2026-08-13 ### A completed run pays the whole table diff --git a/README.md b/README.md index b423f8e..a638971 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ train into an occupied Subdivision. Get that wrong and two trains meet at speed. ## Status -**v0.4.2 — solitaire is playable in a browser.** The whole game runs client-side: the engine is pure, +**v0.4.3 — solitaire is playable in a browser.** The whole game runs client-side: the engine is pure, imports nothing outside itself, and never touches `Math.random`, so a static host is all it needs. - **Rules** — specified, with **three open questions** left. Thirteen gaps in the original prototype diff --git a/TODO.md b/TODO.md index cfe2a35..290daa5 100644 --- a/TODO.md +++ b/TODO.md @@ -122,24 +122,21 @@ Ordered within each section by how much it is currently costing us. present it that way — the supply has to change, not the player.** Options: give track its own hand or yard the way the prototype did, raise the hand limit for track specifically, or print a siding as a single card. Nothing else reaches it. -- [ ] **CLEARING AN INBOUND BOX MINTS A CAR — measured at 1.29 a game against a supply of 80.** - Answered, and it is duplication after all. The two directions are not symmetrical: - - **Outbound is paid for.** `stockToOutbound` SPLICES a loaded car out of the Division Yard to - become the load, and `loadCompleted` swaps the emptied car into the Classification Yard as - the loaded one takes its place on the industry track. Objects in, objects out. - - **Inbound is not.** `unloadBegan` (apply.ts) turns one loaded car into an empty car on the - track **plus** a load on MEN|AT|WORK, and `passengersDetrained` does the same to a coach — - one loaded coach becomes an empty coach in the train plus an object in the red box. Then - `inboundCleared` pushes that object into the **Classification Yard as a car**. The cargo - becomes rolling stock, while the car it came out of is already back in service. - - Measured over 200 games: cars at the end minus 80, plus collision losses, equals the - `inboundCleared` count in 71/200 games exactly and 258 against 279 in total — the rest is - loads still in flight at the final whistle. So the supply inflates by about 1.3 cars a game. - That is the number `ROLLING_STOCK_SUPPLY` is supposed to control, so **no supply figure below - can be tuned until this is settled**. The fix is a decision, not a patch: either a load stops - being a `RollingStock` and becomes its own type, or `inboundCleared` discards rather than - banking. Found by a conservation audit, not by a failing test. +- [x] **~~CLEARING AN INBOUND BOX MINTS A CAR — measured at 1.29 a game against a supply of 80.~~ + Re-audited in v0.4.3: rolling stock is EXACTLY CONSERVED, 100 games out of 100, range 0..0.** + The old audit's premise was right — the two directions were not symmetrical — but the asymmetry + has since been closed from the other end. `unloadBegan` and `passengersDetrained` now take their + replacement empty OUT of the Division Yard rather than conjuring it, so a load is a car that + moved rather than a car that appeared: one leaves the yard, one arrives in Classification. + Jesse's description of the tabletop procedure confirms this is the intended model — the token + you push along the MEN|AT|WORK sign IS the car, fetched from the yard by the Freight Agent and + swapped onto the industry track at the end. + Both conjuring fallbacks now **throw** rather than minting, so the leak cannot silently return; + neither fired across the suite or 100 audited games. + **`ROLLING_STOCK_SUPPLY` is therefore unblocked** — it was waiting on this and can now be tuned + in the rebalance pass. (The first audit's own arithmetic was off in the same way mine was on the + first attempt: cars set out on a card, in `card.standing`, are easy to leave out of the count and + make a conserved game look like a leaking one.) - [x] **`state = fold(events)` was not true, and the docs said it was. Settled: the INTENTS are canonical.** Measured before deciding — `advance.ts` never calls `reduce`, so **14 of the 46 event types are never reduced**: the clock, and the entire Mainline phase, which is every train diff --git a/docs/design.md b/docs/design.md index 24ccfe9..cc52390 100644 --- a/docs/design.md +++ b/docs/design.md @@ -49,7 +49,7 @@ must do. ## Current status -**v0.4.2.** Rules formalized, card faces specified, architecture documented, and the game playable +**v0.4.3.** Rules formalized, card faces specified, architecture documented, and the game playable solitaire in a browser. See [`../CHANGELOG.md`](../CHANGELOG.md) for what each version changed and [`../TODO.md`](../TODO.md) for what is open; this section is the shape of the project, not a running tally, because a hand-maintained tally is what drifted last time. diff --git a/package.json b/package.json index 4892da8..7827b32 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "station-master", - "version": "0.4.2", + "version": "0.4.3", "private": true, "type": "module", "description": "Station Master — a railroad operations game", diff --git a/public/replays/seed-1022551.json b/public/replays/seed-1022551.json index 0ae86ac..defa6a0 100644 --- a/public/replays/seed-1022551.json +++ b/public/replays/seed-1022551.json @@ -1,7 +1,7 @@ { "seed": 1022551, "title": "27 Revenue · seed 1022551", - "note": "27 Revenue over 5 Days · 2 train(s) on the timetable · 21 cards down · no collisions · played by developer", + "note": "27 Revenue over 5 Days · 2 train(s) on the timetable · 19 cards down · no collisions · played by developer", "history": [ { "type": "localOps.choose", @@ -864,12 +864,7 @@ "option": "freightAgent" }, { - "type": "freightAgent.stockOutbound", - "at": { - "row": -1, - "col": -2 - }, - "carType": "boxcar" + "type": "freightAgent.end" }, { "type": "laborer.advanceLoad", @@ -1026,12 +1021,7 @@ "option": "freightAgent" }, { - "type": "freightAgent.stockOutbound", - "at": { - "row": -1, - "col": -2 - }, - "carType": "boxcar" + "type": "freightAgent.end" }, { "type": "laborer.advanceLoad", @@ -1147,6 +1137,205 @@ }, "index": 0 }, + { + "type": "laborer.beginUnload", + "at": { + "row": -1, + "col": -2 + }, + "carIndex": 1 + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -2 + }, + "box": 2 + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "freightAgent" + }, + { + "type": "freightAgent.stockOutbound", + "at": { + "row": -1, + "col": -2 + }, + "carType": "boxcar" + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -2 + }, + "box": 1 + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -2 + }, + "box": 0 + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "freightAgent" + }, + { + "type": "freightAgent.clearInbound", + "at": { + "row": -1, + "col": -2 + }, + "index": 0 + }, + { + "type": "porter.detrain", + "at": { + "row": 0, + "col": 0 + } + }, + { + "type": "porter.board", + "at": { + "row": 0, + "col": 0 + } + }, + { + "type": "laborer.startLoad", + "at": { + "row": -1, + "col": -2 + } + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -2 + }, + "box": 0 + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "freightAgent" + }, + { + "type": "freightAgent.clearInbound", + "at": { + "row": 0, + "col": 0 + }, + "index": 0 + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -2 + }, + "box": 1 + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -2 + }, + "box": 2 + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "freightAgent" + }, + { + "type": "freightAgent.stockOutbound", + "at": { + "row": 0, + "col": 0 + }, + "carType": "coach" + }, + { + "type": "laborer.beginUnload", + "at": { + "row": -1, + "col": -2 + }, + "carIndex": 0 + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -2 + }, + "box": 2 + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "freightAgent" + }, + { + "type": "freightAgent.stockOutbound", + "at": { + "row": -1, + "col": -2 + }, + "carType": "boxcar" + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -2 + }, + "box": 1 + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -2 + }, + "box": 0 + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "freightAgent" + }, + { + "type": "freightAgent.clearInbound", + "at": { + "row": -1, + "col": -2 + }, + "index": 0 + }, { "type": "laborer.startLoad", "at": { @@ -1184,216 +1373,6 @@ { "type": "draw.end" }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": -2 - }, - "box": 1 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": -2 - }, - "box": 2 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.discard", - "cardId": "c48", - "toSlot": 2 - }, - { - "type": "draw.end" - }, - { - "type": "porter.detrain", - "at": { - "row": 0, - "col": 0 - } - }, - { - "type": "porter.board", - "at": { - "row": 0, - "col": 0 - } - }, - { - "type": "laborer.beginUnload", - "at": { - "row": -1, - "col": -2 - }, - "carIndex": 0 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": -2 - }, - "box": 2 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.clearInbound", - "at": { - "row": 0, - "col": 0 - }, - "index": 0 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": -2 - }, - "box": 1 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": -2 - }, - "box": 0 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.clearInbound", - "at": { - "row": -1, - "col": -2 - }, - "index": 0 - }, - { - "type": "laborer.startLoad", - "at": { - "row": -1, - "col": -2 - } - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": -2 - }, - "box": 0 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.stockOutbound", - "at": { - "row": 0, - "col": 0 - }, - "carType": "coach" - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": -2 - }, - "box": 1 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": -2 - }, - "box": 2 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromDepartment", - "slot": 2 - }, - { - "type": "card.discard", - "cardId": "c61", - "toSlot": 2 - }, - { - "type": "draw.end" - }, - { - "type": "laborer.beginUnload", - "at": { - "row": -1, - "col": -2 - }, - "carIndex": 0 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": -2 - }, - "box": 2 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromDepartment", - "slot": 2 - }, - { - "type": "card.discard", - "cardId": "c163", - "toSlot": 2 - }, - { - "type": "draw.end" - }, { "type": "newTrain.placeCar", "trayId": "tray2", @@ -1432,22 +1411,25 @@ "row": -1, "col": -2 }, - "box": 0 + "box": 2 }, { "type": "loadUnload.end" }, { "type": "localOps.choose", - "option": "freightAgent" + "option": "draw" }, { - "type": "freightAgent.clearInbound", - "at": { - "row": -1, - "col": -2 - }, - "index": 0 + "type": "draw.fromHomeOffice" + }, + { + "type": "card.discard", + "cardId": "c48", + "toSlot": 2 + }, + { + "type": "draw.end" }, { "type": "newTrain.placeCar", @@ -1468,6 +1450,54 @@ "type": "localOps.choose", "option": "draw" }, + { + "type": "draw.fromDepartment", + "slot": 2 + }, + { + "type": "card.discard", + "cardId": "c61", + "toSlot": 2 + }, + { + "type": "draw.end" + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromDepartment", + "slot": 2 + }, + { + "type": "card.discard", + "cardId": "c163", + "toSlot": 2 + }, + { + "type": "draw.end" + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "switch" + }, + { + "type": "switch.end" + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, { "type": "draw.fromHomeOffice" }, @@ -1503,16 +1533,6 @@ { "type": "loadUnload.end" }, - { - "type": "localOps.choose", - "option": "switch" - }, - { - "type": "switch.end" - }, - { - "type": "loadUnload.end" - }, { "type": "localOps.choose", "option": "draw" @@ -1528,6 +1548,42 @@ { "type": "draw.end" }, + { + "type": "porter.detrain", + "at": { + "row": 0, + "col": 0 + } + }, + { + "type": "porter.board", + "at": { + "row": 0, + "col": 0 + } + }, + { + "type": "porter.detrain", + "at": { + "row": 0, + "col": 0 + } + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "freightAgent" + }, + { + "type": "freightAgent.clearInbound", + "at": { + "row": 0, + "col": 0 + }, + "index": 0 + }, { "type": "loadUnload.end" }, @@ -1572,42 +1628,6 @@ { "type": "draw.end" }, - { - "type": "porter.detrain", - "at": { - "row": 0, - "col": 0 - } - }, - { - "type": "porter.board", - "at": { - "row": 0, - "col": 0 - } - }, - { - "type": "porter.detrain", - "at": { - "row": 0, - "col": 0 - } - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.clearInbound", - "at": { - "row": 0, - "col": 0 - }, - "index": 0 - }, { "type": "loadUnload.end" }, @@ -1648,44 +1668,6 @@ { "type": "draw.end" }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromDepartment", - "slot": 1 - }, - { - "type": "card.discard", - "cardId": "c61", - "toSlot": 1 - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromDepartment", - "slot": 1 - }, - { - "type": "card.discard", - "cardId": "c150", - "toSlot": 1 - }, - { - "type": "draw.end" - }, { "type": "newTrain.placeCar", "trayId": "tray3", @@ -1718,16 +1700,13 @@ "option": "draw" }, { - "type": "draw.fromHomeOffice" + "type": "draw.fromDepartment", + "slot": 1 }, { - "type": "card.play", - "cardId": "c205", - "placement": { - "row": 0, - "col": -5 - }, - "variant": 0 + "type": "card.discard", + "cardId": "c61", + "toSlot": 1 }, { "type": "draw.end" @@ -1752,16 +1731,13 @@ "option": "draw" }, { - "type": "draw.fromHomeOffice" + "type": "draw.fromDepartment", + "slot": 1 }, { - "type": "card.play", - "cardId": "c126", - "placement": { - "row": 0, - "col": -6 - }, - "variant": 0 + "type": "card.discard", + "cardId": "c150", + "toSlot": 1 }, { "type": "draw.end" @@ -1778,10 +1754,10 @@ }, { "type": "card.play", - "cardId": "c136", + "cardId": "c205", "placement": { "row": 0, - "col": 6 + "col": -5 }, "variant": 0 }, diff --git a/public/replays/seed-3334899.json b/public/replays/seed-1703585.json similarity index 76% rename from public/replays/seed-3334899.json rename to public/replays/seed-1703585.json index 7f932e8..f64e70b 100644 --- a/public/replays/seed-3334899.json +++ b/public/replays/seed-1703585.json @@ -1,22 +1,23 @@ { - "seed": 3334899, - "title": "29 Revenue · seed 3334899", - "note": "29 Revenue over 5 Days · 2 train(s) on the timetable · 16 cards down · no collisions · played by developer", + "seed": 1703585, + "title": "26 Revenue · seed 1703585", + "note": "26 Revenue over 5 Days · 3 train(s) on the timetable · 27 cards down · 4 collision(s) · played by developer", "history": [ { "type": "localOps.choose", "option": "draw" }, { - "type": "draw.fromHomeOffice" + "type": "draw.fromDepartment", + "slot": 0 }, { "type": "card.play", - "cardId": "c14" + "cardId": "c13" }, { "type": "card.play", - "cardId": "c135", + "cardId": "c143", "placement": { "row": 0, "col": 1 @@ -25,7 +26,7 @@ }, { "type": "card.play", - "cardId": "c145", + "cardId": "c206", "placement": { "row": 0, "col": -1 @@ -34,12 +35,12 @@ }, { "type": "card.play", - "cardId": "c119", + "cardId": "c166", "placement": { - "row": 0, - "col": -2 + "row": -1, + "col": -1 }, - "variant": 0 + "variant": 1 }, { "type": "draw.end" @@ -47,13 +48,13 @@ { "type": "newTrain.placeCar", "trayId": "tray3", - "carType": "boxcar", + "carType": "reefer", "loaded": true }, { "type": "newTrain.placeCar", "trayId": "tray3", - "carType": "boxcar", + "carType": "reefer", "loaded": true }, { @@ -74,1584 +75,7 @@ }, { "type": "card.play", - "cardId": "c7" - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.play", - "cardId": "c184", - "placement": { - "row": 0, - "col": 2 - }, - "variant": 0 - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.discard", - "cardId": "c176", - "toSlot": 0 - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.discard", - "cardId": "c109", - "toSlot": 1 - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.discard", - "cardId": "c167", - "toSlot": 2 - }, - { - "type": "draw.end" - }, - { - "type": "newTrain.placeCar", - "trayId": "tray2", - "carType": "coach", - "loaded": false - }, - { - "type": "newTrain.placeCar", - "trayId": "tray2", - "carType": "boxcar", - "loaded": true - }, - { - "type": "mainline.clearance", - "allow": false - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.discard", - "cardId": "c101", - "toSlot": 0 - }, - { - "type": "draw.end" - }, - { - "type": "mainline.clearance", - "allow": false - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.play", - "cardId": "c139", - "placement": { - "row": 0, - "col": 3 - }, - "variant": 0 - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.play", - "cardId": "c196", - "placement": { - "row": -1, - "col": 2 - }, - "variant": 1 - }, - { - "type": "card.play", - "cardId": "c54", - "placement": { - "row": -1, - "col": 1 - }, - "variant": 0 - }, - { - "type": "card.play", - "cardId": "c38", - "placement": { - "row": -1, - "col": 3 - }, - "variant": 0 - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.play", - "cardId": "c73", - "placement": { - "row": -1, - "col": 4 - }, - "variant": 0 - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "switch" - }, - { - "type": "switch.move", - "trayId": "tray2", - "to": { - "row": -1, - "col": 3 - }, - "reverse": false - }, - { - "type": "switch.dropCars", - "trayId": "tray2", - "count": 1 - }, - { - "type": "switch.move", - "trayId": "tray2", - "to": { - "row": 0, - "col": 0 - }, - "reverse": true - }, - { - "type": "switch.end" - }, - { - "type": "laborer.beginUnload", - "at": { - "row": -1, - "col": 3 - }, - "carIndex": 0 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 2 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.stockOutbound", - "at": { - "row": -1, - "col": 3 - }, - "carType": "boxcar" - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 1 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 0 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.clearInbound", - "at": { - "row": -1, - "col": 3 - }, - "index": 0 - }, - { - "type": "laborer.startLoad", - "at": { - "row": -1, - "col": 3 - } - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 0 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.stockOutbound", - "at": { - "row": -1, - "col": 3 - }, - "carType": "boxcar" - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 1 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 2 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.play", - "cardId": "c150", - "placement": { - "row": -1, - "col": 0 - }, - "variant": 1 - }, - { - "type": "draw.end" - }, - { - "type": "laborer.beginUnload", - "at": { - "row": -1, - "col": 3 - }, - "carIndex": 0 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 2 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.stockOutbound", - "at": { - "row": -1, - "col": 3 - }, - "carType": "boxcar" - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 1 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 0 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.clearInbound", - "at": { - "row": -1, - "col": 3 - }, - "index": 0 - }, - { - "type": "laborer.startLoad", - "at": { - "row": -1, - "col": 3 - } - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 0 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.stockOutbound", - "at": { - "row": -1, - "col": 3 - }, - "carType": "boxcar" - }, - { - "type": "newTrain.placeCar", - "trayId": "tray2", - "carType": "hopper", - "loaded": true - }, - { - "type": "newTrain.placeCar", - "trayId": "tray2", - "carType": "coach", - "loaded": false - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 1 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 2 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "draw.end" - }, - { - "type": "laborer.beginUnload", - "at": { - "row": -1, - "col": 3 - }, - "carIndex": 0 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 2 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "draw.end" - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 1 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 0 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "switch" - }, - { - "type": "switch.end" - }, - { - "type": "laborer.startLoad", - "at": { - "row": -1, - "col": 3 - } - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 0 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.clearInbound", - "at": { - "row": -1, - "col": 3 - }, - "index": 0 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 1 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 2 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.play", - "cardId": "c63", - "placement": { - "row": 1, - "col": 0 - }, - "variant": 0 - }, - { - "type": "draw.end" - }, - { - "type": "laborer.beginUnload", - "at": { - "row": -1, - "col": 3 - }, - "carIndex": 0 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 2 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.stockOutbound", - "at": { - "row": -1, - "col": 3 - }, - "carType": "boxcar" - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 1 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 0 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.clearInbound", - "at": { - "row": -1, - "col": 3 - }, - "index": 0 - }, - { - "type": "laborer.startLoad", - "at": { - "row": -1, - "col": 3 - } - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 0 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.stockOutbound", - "at": { - "row": -1, - "col": 3 - }, - "carType": "boxcar" - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 1 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 2 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.discard", - "cardId": "c74", - "toSlot": 1 - }, - { - "type": "draw.end" - }, - { - "type": "laborer.beginUnload", - "at": { - "row": -1, - "col": 3 - }, - "carIndex": 0 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 2 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.play", - "cardId": "c210", - "placement": { - "row": 0, - "col": -1 - }, - "variant": 0 - }, - { - "type": "card.play", - "cardId": "c178", - "placement": { - "row": -1, - "col": -1 - }, - "variant": 1 - }, - { - "type": "draw.end" - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 1 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 0 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.clearInbound", - "at": { - "row": -1, - "col": 3 - }, - "index": 0 - }, - { - "type": "laborer.startLoad", - "at": { - "row": -1, - "col": 3 - } - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 0 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.stockOutbound", - "at": { - "row": -1, - "col": 3 - }, - "carType": "boxcar" - }, - { - "type": "newTrain.placeCar", - "trayId": "tray2", - "carType": "hopper", - "loaded": true - }, - { - "type": "newTrain.placeCar", - "trayId": "tray2", - "carType": "coach", - "loaded": false - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 1 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 2 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "draw.end" - }, - { - "type": "laborer.beginUnload", - "at": { - "row": -1, - "col": 3 - }, - "carIndex": 0 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 2 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.discard", - "cardId": "c41", - "toSlot": 2 - }, - { - "type": "draw.end" - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 1 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 0 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "switch" - }, - { - "type": "switch.move", - "trayId": "tray2", - "to": { - "row": -1, - "col": -1 - }, - "reverse": true - }, - { - "type": "switch.move", - "trayId": "tray2", - "to": { - "row": 0, - "col": 0 - }, - "reverse": false - }, - { - "type": "switch.move", - "trayId": "tray2", - "to": { - "row": -1, - "col": -1 - }, - "reverse": true - }, - { - "type": "switch.move", - "trayId": "tray2", - "to": { - "row": 0, - "col": 0 - }, - "reverse": false - }, - { - "type": "switch.move", - "trayId": "tray2", - "to": { - "row": -1, - "col": -1 - }, - "reverse": true - }, - { - "type": "switch.move", - "trayId": "tray2", - "to": { - "row": 0, - "col": 0 - }, - "reverse": false - }, - { - "type": "laborer.startLoad", - "at": { - "row": -1, - "col": 3 - } - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 0 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.clearInbound", - "at": { - "row": -1, - "col": 3 - }, - "index": 0 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 1 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 2 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromDepartment", - "slot": 2 - }, - { - "type": "card.discard", - "cardId": "c3", - "toSlot": 2 - }, - { - "type": "draw.end" - }, - { - "type": "laborer.beginUnload", - "at": { - "row": -1, - "col": 3 - }, - "carIndex": 0 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 2 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromDepartment", - "slot": 2 - }, - { - "type": "card.discard", - "cardId": "c56", - "toSlot": 2 - }, - { - "type": "draw.end" - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 1 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 0 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.clearInbound", - "at": { - "row": -1, - "col": 3 - }, - "index": 0 - }, - { - "type": "laborer.startLoad", - "at": { - "row": -1, - "col": 3 - } - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 0 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromDepartment", - "slot": 2 - }, - { - "type": "card.discard", - "cardId": "c106", - "toSlot": 2 - }, - { - "type": "draw.end" - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 1 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 2 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.play", - "cardId": "c24" - }, - { - "type": "card.play", - "cardId": "c3" - }, - { - "type": "draw.end" - }, - { - "type": "laborer.beginUnload", - "at": { - "row": -1, - "col": 3 - }, - "carIndex": 0 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 2 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.stockOutbound", - "at": { - "row": 0, - "col": 0 - }, - "carType": "coach" - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 1 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 3 - }, - "box": 0 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.clearInbound", - "at": { - "row": -1, - "col": 3 - }, - "index": 0 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.play", - "cardId": "c30" - }, - { - "type": "draw.end" - }, - { - "type": "newTrain.placeCar", - "trayId": "tray2", - "carType": "hopper", - "loaded": true - }, - { - "type": "newTrain.placeCar", - "trayId": "tray2", - "carType": "coach", - "loaded": true - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.stockOutbound", - "at": { - "row": 0, - "col": 0 - }, - "carType": "coach" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "draw.end" - }, - { - "type": "porter.detrain", - "at": { - "row": 0, - "col": 0 - } - }, - { - "type": "porter.board", - "at": { - "row": 0, - "col": 0 - } - }, - { - "type": "porter.detrain", - "at": { - "row": 0, - "col": 0 - } - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "switch" - }, - { - "type": "switch.move", - "trayId": "tray2", - "to": { - "row": -1, - "col": -1 - }, - "reverse": true - }, - { - "type": "switch.move", - "trayId": "tray2", - "to": { - "row": 0, - "col": 0 - }, - "reverse": false - }, - { - "type": "switch.move", - "trayId": "tray2", - "to": { - "row": -1, - "col": -1 - }, - "reverse": true - }, - { - "type": "switch.move", - "trayId": "tray2", - "to": { - "row": 0, - "col": 0 - }, - "reverse": false - }, - { - "type": "switch.move", - "trayId": "tray2", - "to": { - "row": -1, - "col": -1 - }, - "reverse": true - }, - { - "type": "switch.move", - "trayId": "tray2", - "to": { - "row": 0, - "col": 0 - }, - "reverse": false - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.clearInbound", - "at": { - "row": 0, - "col": 0 - }, - "index": 0 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.clearInbound", - "at": { - "row": 0, - "col": 0 - }, - "index": 0 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.stockOutbound", - "at": { - "row": 0, - "col": 0 - }, - "carType": "coach" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.discard", - "cardId": "c41", - "toSlot": 0 - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromDepartment", - "slot": 0 - }, - { - "type": "card.discard", - "cardId": "c56", - "toSlot": 0 - }, - { - "type": "draw.end" - }, - { - "type": "newTrain.placeCar", - "trayId": "tray2", - "carType": "hopper", - "loaded": true - }, - { - "type": "newTrain.placeCar", - "trayId": "tray2", - "carType": "hopper", - "loaded": true - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromDepartment", - "slot": 0 - }, - { - "type": "card.discard", "cardId": "c49", - "toSlot": 0 - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromDepartment", - "slot": 0 - }, - { - "type": "card.discard", - "cardId": "c27", - "toSlot": 0 - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.play", - "cardId": "c86", - "placement": { - "row": 0, - "col": 1 - }, - "variant": 0 - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.play", - "cardId": "c141", "placement": { "row": -1, "col": -2 @@ -1661,15 +85,260 @@ { "type": "draw.end" }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromHomeOffice" + }, + { + "type": "card.play", + "cardId": "c39", + "placement": { + "row": -1, + "col": -3 + }, + "variant": 0 + }, + { + "type": "card.play", + "cardId": "c72", + "placement": { + "row": 0, + "col": -3 + }, + "variant": 0 + }, + { + "type": "draw.end" + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromHomeOffice" + }, + { + "type": "card.play", + "cardId": "c92", + "placement": { + "row": 0, + "col": 1 + }, + "variant": 0 + }, + { + "type": "draw.end" + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromHomeOffice" + }, + { + "type": "card.play", + "cardId": "c1" + }, + { + "type": "draw.end" + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromHomeOffice" + }, + { + "type": "card.play", + "cardId": "c25" + }, + { + "type": "draw.end" + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "freightAgent" + }, + { + "type": "freightAgent.stockOutbound", + "at": { + "row": 0, + "col": 0 + }, + "carType": "coach" + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromHomeOffice" + }, + { + "type": "card.play", + "cardId": "c189", + "placement": { + "row": 0, + "col": -2 + }, + "variant": 0 + }, + { + "type": "draw.end" + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromHomeOffice" + }, + { + "type": "draw.end" + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromHomeOffice" + }, + { + "type": "card.play", + "cardId": "c186", + "placement": { + "row": 0, + "col": 2 + }, + "variant": 0 + }, + { + "type": "draw.end" + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromHomeOffice" + }, + { + "type": "mainline.modify", + "cardId": "c107", + "node": 1 + }, + { + "type": "draw.end" + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromHomeOffice" + }, + { + "type": "card.play", + "cardId": "c71", + "placement": { + "row": -2, + "col": -2 + }, + "variant": 0 + }, + { + "type": "draw.end" + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromHomeOffice" + }, + { + "type": "card.play", + "cardId": "c168", + "placement": { + "row": -1, + "col": -4 + }, + "variant": 0 + }, + { + "type": "draw.end" + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromHomeOffice" + }, + { + "type": "card.discard", + "cardId": "c115", + "toSlot": 0 + }, + { + "type": "draw.end" + }, { "type": "newTrain.placeCar", - "trayId": "tray2", - "carType": "hopper", + "trayId": "tray3", + "carType": "coach", "loaded": true }, { "type": "newTrain.placeCar", - "trayId": "tray2", + "trayId": "tray3", + "carType": "coach", + "loaded": true + }, + { + "type": "newTrain.placeCar", + "trayId": "tray3", "carType": "coach", "loaded": true }, @@ -1683,6 +352,120 @@ { "type": "draw.fromHomeOffice" }, + { + "type": "card.discard", + "cardId": "c82", + "toSlot": 1 + }, + { + "type": "draw.end" + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromHomeOffice" + }, + { + "type": "card.play", + "cardId": "c10" + }, + { + "type": "draw.end" + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromHomeOffice" + }, + { + "type": "card.play", + "cardId": "c131", + "placement": { + "row": 0, + "col": 3 + }, + "variant": 0 + }, + { + "type": "draw.end" + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromHomeOffice" + }, + { + "type": "card.play", + "cardId": "c193", + "placement": { + "row": -1, + "col": 2 + }, + "variant": 1 + }, + { + "type": "card.play", + "cardId": "c59", + "placement": { + "row": -1, + "col": 1 + }, + "variant": 0 + }, + { + "type": "draw.end" + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromHomeOffice" + }, + { + "type": "card.play", + "cardId": "c146", + "placement": { + "row": -1, + "col": 0 + }, + "variant": 0 + }, + { + "type": "draw.end" + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromHomeOffice" + }, + { + "type": "card.play", + "cardId": "c32" + }, { "type": "card.play", "cardId": "c34" @@ -1706,7 +489,152 @@ "carType": "coach" }, { - "type": "porter.detrain", + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "freightAgent" + }, + { + "type": "freightAgent.stockOutbound", + "at": { + "row": 0, + "col": 0 + }, + "carType": "coach" + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromHomeOffice" + }, + { + "type": "card.play", + "cardId": "c65", + "placement": { + "row": 1, + "col": 0 + }, + "variant": 0 + }, + { + "type": "draw.end" + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "freightAgent" + }, + { + "type": "freightAgent.stockOutbound", + "at": { + "row": 0, + "col": 0 + }, + "carType": "coach" + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromHomeOffice" + }, + { + "type": "draw.end" + }, + { + "type": "newTrain.placeCar", + "trayId": "tray3", + "carType": "tank", + "loaded": false + }, + { + "type": "newTrain.placeCar", + "trayId": "tray3", + "carType": "tank", + "loaded": false + }, + { + "type": "newTrain.placeCar", + "trayId": "tray3", + "carType": "caboose", + "loaded": true + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromHomeOffice" + }, + { + "type": "card.play", + "cardId": "c46", + "placement": { + "row": -1, + "col": 3 + }, + "variant": 0 + }, + { + "type": "draw.end" + }, + { + "type": "newTrain.placeCar", + "trayId": "tray2", + "carType": "coach", + "loaded": true + }, + { + "type": "newTrain.placeCar", + "trayId": "tray2", + "carType": "coach", + "loaded": false + }, + { + "type": "newTrain.placeCar", + "trayId": "tray2", + "carType": "coach", + "loaded": false + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromHomeOffice" + }, + { + "type": "card.play", + "cardId": "c128", + "placement": { + "row": 0, + "col": -3 + }, + "variant": 0 + }, + { + "type": "draw.end" + }, + { + "type": "porter.board", "at": { "row": 0, "col": 0 @@ -1736,63 +664,446 @@ { "type": "loadUnload.end" }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromHomeOffice" + }, + { + "type": "card.play", + "cardId": "c208", + "placement": { + "row": 0, + "col": -4 + }, + "variant": 0 + }, + { + "type": "draw.end" + }, + { + "type": "porter.detrain", + "at": { + "row": 0, + "col": 0 + } + }, + { + "type": "porter.board", + "at": { + "row": 0, + "col": 0 + } + }, + { + "type": "porter.detrain", + "at": { + "row": 0, + "col": 0 + } + }, + { + "type": "loadUnload.end" + }, { "type": "localOps.choose", "option": "switch" }, { "type": "switch.move", - "trayId": "tray2", + "trayId": "tray3", "to": { "row": -1, "col": -1 }, + "reverse": false + }, + { + "type": "switch.dropCars", + "trayId": "tray3", + "count": 1 + }, + { + "type": "switch.move", + "trayId": "tray3", + "to": { + "row": 0, + "col": 0 + }, "reverse": true }, { "type": "switch.move", - "trayId": "tray2", + "trayId": "tray3", "to": { - "row": 0, - "col": 0 + "row": -1, + "col": -2 }, "reverse": false }, + { + "type": "switch.dropCars", + "trayId": "tray3", + "count": 1, + "fromNose": true + }, { "type": "switch.move", + "trayId": "tray3", + "to": { + "row": 0, + "col": 0 + }, + "reverse": true + }, + { + "type": "switch.end" + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "freightAgent" + }, + { + "type": "freightAgent.clearInbound", + "at": { + "row": 0, + "col": 0 + }, + "index": 0 + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromHomeOffice" + }, + { + "type": "card.play", + "cardId": "c69", + "placement": { + "row": -2, + "col": -3 + }, + "variant": 0 + }, + { + "type": "draw.end" + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromHomeOffice" + }, + { + "type": "card.play", + "cardId": "c188", + "placement": { + "row": 0, + "col": 4 + }, + "variant": 0 + }, + { + "type": "draw.end" + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromHomeOffice" + }, + { + "type": "draw.end" + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromHomeOffice" + }, + { + "type": "card.play", + "cardId": "c122", + "placement": { + "row": -1, + "col": 4 + }, + "variant": 0 + }, + { + "type": "draw.end" + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromHomeOffice" + }, + { + "type": "card.play", + "cardId": "c170", + "placement": { + "row": -2, + "col": -4 + }, + "variant": 1 + }, + { + "type": "draw.end" + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromHomeOffice" + }, + { + "type": "card.play", + "cardId": "c176", + "placement": { + "row": -1, + "col": 5 + }, + "variant": 1 + }, + { + "type": "draw.end" + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromHomeOffice" + }, + { + "type": "card.play", + "cardId": "c141", + "placement": { + "row": 0, + "col": 5 + }, + "variant": 0 + }, + { + "type": "draw.end" + }, + { + "type": "newTrain.placeCar", + "trayId": "tray3", + "carType": "boxcar", + "loaded": false + }, + { + "type": "newTrain.placeCar", + "trayId": "tray3", + "carType": "boxcar", + "loaded": false + }, + { + "type": "newTrain.placeCar", + "trayId": "tray3", + "carType": "caboose", + "loaded": true + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromHomeOffice" + }, + { + "type": "card.play", + "cardId": "c8" + }, + { + "type": "draw.end" + }, + { + "type": "newTrain.placeCar", "trayId": "tray2", + "carType": "coach", + "loaded": false + }, + { + "type": "newTrain.placeCar", + "trayId": "tray2", + "carType": "coach", + "loaded": false + }, + { + "type": "newTrain.placeCar", + "trayId": "tray2", + "carType": "coach", + "loaded": false + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromHomeOffice" + }, + { + "type": "card.play", + "cardId": "c161", + "placement": { + "row": -2, + "col": -5 + }, + "variant": 1 + }, + { + "type": "draw.end" + }, + { + "type": "newTrain.placeCar", + "trayId": "tray1", + "carType": "boxcar", + "loaded": false + }, + { + "type": "newTrain.placeCar", + "trayId": "tray1", + "carType": "boxcar", + "loaded": false + }, + { + "type": "newTrain.placeCar", + "trayId": "tray1", + "carType": "boxcar", + "loaded": false + }, + { + "type": "newTrain.placeCar", + "trayId": "tray1", + "carType": "caboose", + "loaded": true + }, + { + "type": "mainline.clearance", + "allow": false + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "switch" + }, + { + "type": "switch.end" + }, + { + "type": "mainline.clearance", + "allow": false + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "switch" + }, + { + "type": "switch.move", + "trayId": "tray3", "to": { "row": -1, "col": -1 }, + "reverse": false + }, + { + "type": "switch.dropCars", + "trayId": "tray3", + "count": 1 + }, + { + "type": "switch.move", + "trayId": "tray3", + "to": { + "row": 0, + "col": 0 + }, "reverse": true }, { "type": "switch.move", - "trayId": "tray2", + "trayId": "tray3", "to": { - "row": 0, - "col": 0 + "row": -1, + "col": -3 }, "reverse": false }, + { + "type": "switch.dropCars", + "trayId": "tray3", + "count": 2, + "fromNose": true + }, + { + "type": "switch.dropCars", + "trayId": "tray3", + "count": 1 + }, + { + "type": "switch.dropCars", + "trayId": "tray3", + "count": 1 + }, { "type": "switch.move", - "trayId": "tray2", + "trayId": "tray3", "to": { - "row": -1, - "col": -1 + "row": 0, + "col": 0 }, "reverse": true }, { - "type": "switch.move", - "trayId": "tray2", - "to": { - "row": 0, - "col": 0 - }, - "reverse": false + "type": "switch.end" }, { "type": "loadUnload.end" @@ -1834,10 +1145,698 @@ { "type": "freightAgent.stockOutbound", "at": { + "row": -1, + "col": -3 + }, + "carType": "boxcar" + }, + { + "type": "laborer.startLoad", + "at": { + "row": -1, + "col": -3 + } + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -3 + }, + "box": 0 + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -3 + }, + "box": 1 + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -3 + }, + "box": 2 + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "freightAgent" + }, + { + "type": "freightAgent.stockOutbound", + "at": { + "row": -1, + "col": -3 + }, + "carType": "boxcar" + }, + { + "type": "laborer.startLoad", + "at": { + "row": -1, + "col": -3 + } + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -3 + }, + "box": 0 + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -3 + }, + "box": 1 + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -3 + }, + "box": 2 + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromHomeOffice" + }, + { + "type": "card.discard", + "cardId": "c85", + "toSlot": 2 + }, + { + "type": "draw.end" + }, + { + "type": "laborer.beginUnload", + "at": { + "row": -1, + "col": -3 + }, + "carIndex": 2 + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -3 + }, + "box": 2 + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -3 + }, + "box": 1 + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -3 + }, + "box": 0 + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "switch" + }, + { + "type": "switch.move", + "trayId": "tray1", + "to": { + "row": -1, + "col": -1 + }, + "reverse": false + }, + { + "type": "switch.dropCars", + "trayId": "tray1", + "count": 1 + }, + { + "type": "switch.move", + "trayId": "tray1", + "to": { "row": 0, "col": 0 }, - "carType": "coach" + "reverse": true + }, + { + "type": "switch.end" + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "freightAgent" + }, + { + "type": "freightAgent.clearInbound", + "at": { + "row": -1, + "col": -3 + }, + "index": 0 + }, + { + "type": "laborer.beginUnload", + "at": { + "row": -1, + "col": -3 + }, + "carIndex": 2 + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -3 + }, + "box": 2 + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -3 + }, + "box": 1 + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -3 + }, + "box": 0 + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "freightAgent" + }, + { + "type": "freightAgent.clearInbound", + "at": { + "row": -1, + "col": -3 + }, + "index": 0 + }, + { + "type": "newTrain.placeCar", + "trayId": "tray3", + "carType": "tank", + "loaded": false + }, + { + "type": "newTrain.placeCar", + "trayId": "tray3", + "carType": "tank", + "loaded": false + }, + { + "type": "newTrain.placeCar", + "trayId": "tray3", + "carType": "caboose", + "loaded": true + }, + { + "type": "laborer.beginUnload", + "at": { + "row": -1, + "col": -3 + }, + "carIndex": 2 + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -3 + }, + "box": 2 + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -3 + }, + "box": 1 + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -3 + }, + "box": 0 + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "freightAgent" + }, + { + "type": "freightAgent.clearInbound", + "at": { + "row": -1, + "col": -3 + }, + "index": 0 + }, + { + "type": "laborer.beginUnload", + "at": { + "row": -1, + "col": -3 + }, + "carIndex": 3 + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -3 + }, + "box": 2 + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -3 + }, + "box": 1 + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -3 + }, + "box": 0 + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "freightAgent" + }, + { + "type": "freightAgent.clearInbound", + "at": { + "row": -1, + "col": -3 + }, + "index": 0 + }, + { + "type": "newTrain.placeCar", + "trayId": "tray2", + "carType": "tank", + "loaded": false + }, + { + "type": "newTrain.placeCar", + "trayId": "tray2", + "carType": "tank", + "loaded": false + }, + { + "type": "newTrain.placeCar", + "trayId": "tray2", + "carType": "boxcar", + "loaded": false + }, + { + "type": "newTrain.placeCar", + "trayId": "tray2", + "carType": "caboose", + "loaded": true + }, + { + "type": "mainline.clearance", + "allow": false + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "freightAgent" + }, + { + "type": "freightAgent.stockOutbound", + "at": { + "row": -1, + "col": -3 + }, + "carType": "boxcar" + }, + { + "type": "mainline.clearance", + "allow": false + }, + { + "type": "laborer.startLoad", + "at": { + "row": -1, + "col": -3 + } + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -3 + }, + "box": 0 + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -3 + }, + "box": 1 + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -3 + }, + "box": 2 + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "switch" + }, + { + "type": "switch.move", + "trayId": "tray3", + "to": { + "row": -1, + "col": -1 + }, + "reverse": false + }, + { + "type": "switch.dropCars", + "trayId": "tray3", + "count": 1, + "fromNose": true + }, + { + "type": "switch.dropCars", + "trayId": "tray3", + "count": 1 + }, + { + "type": "switch.move", + "trayId": "tray3", + "to": { + "row": 0, + "col": 0 + }, + "reverse": true + }, + { + "type": "switch.move", + "trayId": "tray3", + "to": { + "row": -1, + "col": -2 + }, + "reverse": false + }, + { + "type": "switch.dropCars", + "trayId": "tray3", + "count": 1 + }, + { + "type": "switch.move", + "trayId": "tray3", + "to": { + "row": 0, + "col": 0 + }, + "reverse": true + }, + { + "type": "switch.end" + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "freightAgent" + }, + { + "type": "freightAgent.stockOutbound", + "at": { + "row": -1, + "col": -2 + }, + "carType": "tank" + }, + { + "type": "laborer.startLoad", + "at": { + "row": -1, + "col": -2 + } + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "freightAgent" + }, + { + "type": "freightAgent.stockOutbound", + "at": { + "row": -1, + "col": -3 + }, + "carType": "boxcar" + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -2 + }, + "box": 0 + }, + { + "type": "laborer.startLoad", + "at": { + "row": -1, + "col": -3 + } + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -3 + }, + "box": 0 + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -3 + }, + "box": 1 + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -3 + }, + "box": 2 + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "freightAgent" + }, + { + "type": "freightAgent.stockOutbound", + "at": { + "row": -1, + "col": -3 + }, + "carType": "boxcar" + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -2 + }, + "box": 1 + }, + { + "type": "laborer.startLoad", + "at": { + "row": -1, + "col": -3 + } + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -3 + }, + "box": 0 + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -3 + }, + "box": 1 + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -3 + }, + "box": 2 + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "freightAgent" + }, + { + "type": "freightAgent.stockOutbound", + "at": { + "row": -1, + "col": -3 + }, + "carType": "boxcar" + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -2 + }, + "box": 2 + }, + { + "type": "laborer.startLoad", + "at": { + "row": -1, + "col": -3 + } + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -3 + }, + "box": 0 + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -3 + }, + "box": 1 + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -3 + }, + "box": 2 + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "switch" + }, + { + "type": "switch.end" + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "switch" + }, + { + "type": "switch.end" + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "switch" + }, + { + "type": "switch.end" }, { "type": "loadUnload.end" diff --git a/public/replays/seed-1980750.json b/public/replays/seed-1980750.json index 5ee6881..7a0bb3c 100644 --- a/public/replays/seed-1980750.json +++ b/public/replays/seed-1980750.json @@ -524,12 +524,7 @@ "option": "freightAgent" }, { - "type": "freightAgent.stockOutbound", - "at": { - "row": -1, - "col": -2 - }, - "carType": "boxcar" + "type": "freightAgent.end" }, { "type": "laborer.advanceLoad", @@ -544,22 +539,10 @@ }, { "type": "localOps.choose", - "option": "draw" + "option": "freightAgent" }, { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.play", - "cardId": "c76", - "placement": { - "row": 0, - "col": -3 - }, - "variant": 0 - }, - { - "type": "draw.end" + "type": "freightAgent.end" }, { "type": "laborer.advanceLoad", @@ -574,22 +557,10 @@ }, { "type": "localOps.choose", - "option": "draw" + "option": "freightAgent" }, { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.play", - "cardId": "c181", - "placement": { - "row": 0, - "col": -2 - }, - "variant": 0 - }, - { - "type": "draw.end" + "type": "freightAgent.end" }, { "type": "laborer.advanceLoad", @@ -610,9 +581,13 @@ "type": "draw.fromHomeOffice" }, { - "type": "card.discard", - "cardId": "c41", - "toSlot": 2 + "type": "card.play", + "cardId": "c76", + "placement": { + "row": 0, + "col": -3 + }, + "variant": 0 }, { "type": "draw.end" @@ -687,19 +662,15 @@ }, { "type": "localOps.choose", - "option": "draw" + "option": "freightAgent" }, { - "type": "draw.fromDepartment", - "slot": 2 - }, - { - "type": "card.discard", - "cardId": "c36", - "toSlot": 2 - }, - { - "type": "draw.end" + "type": "freightAgent.stockOutbound", + "at": { + "row": -1, + "col": -2 + }, + "carType": "boxcar" }, { "type": "laborer.advanceLoad", @@ -717,13 +688,16 @@ "option": "draw" }, { - "type": "draw.fromDepartment", - "slot": 2 + "type": "draw.fromHomeOffice" }, { - "type": "card.discard", - "cardId": "c40", - "toSlot": 2 + "type": "card.play", + "cardId": "c181", + "placement": { + "row": 0, + "col": -2 + }, + "variant": 0 }, { "type": "draw.end" @@ -778,12 +752,7 @@ "option": "freightAgent" }, { - "type": "freightAgent.stockOutbound", - "at": { - "row": -1, - "col": -2 - }, - "carType": "boxcar" + "type": "freightAgent.end" }, { "type": "porter.detrain", @@ -879,12 +848,11 @@ "option": "draw" }, { - "type": "draw.fromDepartment", - "slot": 2 + "type": "draw.fromHomeOffice" }, { "type": "card.discard", - "cardId": "c53", + "cardId": "c41", "toSlot": 2 }, { @@ -903,19 +871,15 @@ }, { "type": "localOps.choose", - "option": "draw" + "option": "freightAgent" }, { - "type": "draw.fromDepartment", - "slot": 2 - }, - { - "type": "card.discard", - "cardId": "c41", - "toSlot": 2 - }, - { - "type": "draw.end" + "type": "freightAgent.stockOutbound", + "at": { + "row": -1, + "col": -2 + }, + "carType": "boxcar" }, { "type": "laborer.advanceLoad", @@ -1041,12 +1005,7 @@ "option": "freightAgent" }, { - "type": "freightAgent.stockOutbound", - "at": { - "row": -1, - "col": -2 - }, - "carType": "boxcar" + "type": "freightAgent.end" }, { "type": "laborer.advanceLoad", @@ -1061,19 +1020,10 @@ }, { "type": "localOps.choose", - "option": "draw" + "option": "freightAgent" }, { - "type": "draw.fromDepartment", - "slot": 2 - }, - { - "type": "card.discard", - "cardId": "c40", - "toSlot": 2 - }, - { - "type": "draw.end" + "type": "freightAgent.end" }, { "type": "laborer.advanceLoad", @@ -1088,19 +1038,10 @@ }, { "type": "localOps.choose", - "option": "draw" + "option": "freightAgent" }, { - "type": "draw.fromDepartment", - "slot": 2 - }, - { - "type": "card.discard", - "cardId": "c53", - "toSlot": 2 - }, - { - "type": "draw.end" + "type": "freightAgent.end" }, { "type": "newTrain.placeCar", @@ -1135,7 +1076,7 @@ }, { "type": "card.discard", - "cardId": "c41", + "cardId": "c40", "toSlot": 2 }, { @@ -1154,19 +1095,15 @@ }, { "type": "localOps.choose", - "option": "draw" + "option": "freightAgent" }, { - "type": "draw.fromDepartment", - "slot": 2 - }, - { - "type": "card.discard", - "cardId": "c36", - "toSlot": 2 - }, - { - "type": "draw.end" + "type": "freightAgent.stockOutbound", + "at": { + "row": -1, + "col": -2 + }, + "carType": "boxcar" }, { "type": "porter.board", @@ -1203,7 +1140,7 @@ }, { "type": "card.discard", - "cardId": "c40", + "cardId": "c53", "toSlot": 2 }, { @@ -1248,7 +1185,7 @@ }, { "type": "card.discard", - "cardId": "c53", + "cardId": "c41", "toSlot": 2 }, { @@ -1292,12 +1229,7 @@ "option": "freightAgent" }, { - "type": "freightAgent.stockOutbound", - "at": { - "row": -1, - "col": -2 - }, - "carType": "boxcar" + "type": "freightAgent.end" }, { "type": "laborer.advanceLoad", @@ -1312,19 +1244,10 @@ }, { "type": "localOps.choose", - "option": "draw" + "option": "freightAgent" }, { - "type": "draw.fromDepartment", - "slot": 2 - }, - { - "type": "card.discard", - "cardId": "c41", - "toSlot": 2 - }, - { - "type": "draw.end" + "type": "freightAgent.end" }, { "type": "laborer.advanceLoad", @@ -1339,19 +1262,10 @@ }, { "type": "localOps.choose", - "option": "draw" + "option": "freightAgent" }, { - "type": "draw.fromDepartment", - "slot": 2 - }, - { - "type": "card.discard", - "cardId": "c36", - "toSlot": 2 - }, - { - "type": "draw.end" + "type": "freightAgent.end" }, { "type": "laborer.advanceLoad", @@ -1374,7 +1288,7 @@ }, { "type": "card.discard", - "cardId": "c40", + "cardId": "c36", "toSlot": 2 }, { @@ -1405,19 +1319,15 @@ }, { "type": "localOps.choose", - "option": "draw" + "option": "freightAgent" }, { - "type": "draw.fromDepartment", - "slot": 2 - }, - { - "type": "card.discard", - "cardId": "c53", - "toSlot": 2 - }, - { - "type": "draw.end" + "type": "freightAgent.stockOutbound", + "at": { + "row": -1, + "col": -2 + }, + "carType": "boxcar" }, { "type": "laborer.advanceLoad", @@ -1440,7 +1350,7 @@ }, { "type": "card.discard", - "cardId": "c41", + "cardId": "c40", "toSlot": 2 }, { @@ -1467,7 +1377,7 @@ }, { "type": "card.discard", - "cardId": "c36", + "cardId": "c53", "toSlot": 2 }, { @@ -1528,7 +1438,7 @@ }, { "type": "card.discard", - "cardId": "c40", + "cardId": "c41", "toSlot": 2 }, { @@ -1555,7 +1465,7 @@ }, { "type": "card.discard", - "cardId": "c53", + "cardId": "c36", "toSlot": 2 }, { @@ -1598,6 +1508,60 @@ "type": "draw.fromDepartment", "slot": 2 }, + { + "type": "card.discard", + "cardId": "c40", + "toSlot": 2 + }, + { + "type": "draw.end" + }, + { + "type": "laborer.advanceLoad", + "at": { + "row": -1, + "col": -2 + }, + "box": 2 + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromDepartment", + "slot": 2 + }, + { + "type": "card.discard", + "cardId": "c53", + "toSlot": 2 + }, + { + "type": "draw.end" + }, + { + "type": "laborer.beginUnload", + "at": { + "row": -1, + "col": -2 + }, + "carIndex": 0 + }, + { + "type": "loadUnload.end" + }, + { + "type": "localOps.choose", + "option": "draw" + }, + { + "type": "draw.fromDepartment", + "slot": 2 + }, { "type": "card.discard", "cardId": "c41", @@ -1633,60 +1597,6 @@ { "type": "draw.end" }, - { - "type": "laborer.beginUnload", - "at": { - "row": -1, - "col": -2 - }, - "carIndex": 0 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromDepartment", - "slot": 2 - }, - { - "type": "card.discard", - "cardId": "c40", - "toSlot": 2 - }, - { - "type": "draw.end" - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": -2 - }, - "box": 2 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromDepartment", - "slot": 2 - }, - { - "type": "card.discard", - "cardId": "c53", - "toSlot": 2 - }, - { - "type": "draw.end" - }, { "type": "laborer.advanceLoad", "at": { @@ -1708,7 +1618,7 @@ }, { "type": "card.discard", - "cardId": "c41", + "cardId": "c40", "toSlot": 2 }, { @@ -1762,7 +1672,7 @@ }, { "type": "card.discard", - "cardId": "c36", + "cardId": "c53", "toSlot": 2 }, { @@ -1781,7 +1691,7 @@ }, { "type": "card.discard", - "cardId": "c40", + "cardId": "c41", "toSlot": 2 }, { diff --git a/public/replays/seed-2242077.json b/public/replays/seed-2242077.json deleted file mode 100644 index 83b92d6..0000000 --- a/public/replays/seed-2242077.json +++ /dev/null @@ -1,1626 +0,0 @@ -{ - "seed": 2242077, - "title": "30 Revenue · seed 2242077", - "note": "30 Revenue over 5 Days · 3 train(s) on the timetable · 19 cards down · 3 collision(s) · played by developer", - "history": [ - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.play", - "cardId": "c8" - }, - { - "type": "card.play", - "cardId": "c181", - "placement": { - "row": 0, - "col": 1 - }, - "variant": 0 - }, - { - "type": "card.play", - "cardId": "c151", - "placement": { - "row": -1, - "col": 1 - }, - "variant": 1 - }, - { - "type": "card.play", - "cardId": "c200", - "placement": { - "row": 0, - "col": -1 - }, - "variant": 0 - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.play", - "cardId": "c176", - "placement": { - "row": -1, - "col": -1 - }, - "variant": 1 - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.play", - "cardId": "c25" - }, - { - "type": "card.play", - "cardId": "c30" - }, - { - "type": "draw.end" - }, - { - "type": "newTrain.placeCar", - "trayId": "tray3", - "carType": "boxcar", - "loaded": true - }, - { - "type": "newTrain.placeCar", - "trayId": "tray3", - "carType": "boxcar", - "loaded": true - }, - { - "type": "newTrain.placeCar", - "trayId": "tray3", - "carType": "boxcar", - "loaded": true - }, - { - "type": "newTrain.placeCar", - "trayId": "tray3", - "carType": "caboose", - "loaded": true - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.stockOutbound", - "at": { - "row": 0, - "col": 0 - }, - "carType": "coach" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.stockOutbound", - "at": { - "row": 0, - "col": 0 - }, - "carType": "coach" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.play", - "cardId": "c40", - "placement": { - "row": -1, - "col": 2 - }, - "variant": 0 - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.play", - "cardId": "c203", - "placement": { - "row": 0, - "col": -2 - }, - "variant": 0 - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.discard", - "cardId": "c110", - "toSlot": 0 - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.play", - "cardId": "c2" - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.play", - "cardId": "c120", - "placement": { - "row": 0, - "col": 2 - }, - "variant": 0 - }, - { - "type": "card.play", - "cardId": "c87", - "placement": { - "row": 0, - "col": 2 - }, - "variant": 0 - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.play", - "cardId": "c7" - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.play", - "cardId": "c162", - "placement": { - "row": -1, - "col": -2 - }, - "variant": 1 - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.discard", - "cardId": "c106", - "toSlot": 1 - }, - { - "type": "draw.end" - }, - { - "type": "newTrain.placeCar", - "trayId": "tray3", - "carType": "boxcar", - "loaded": false - }, - { - "type": "newTrain.placeCar", - "trayId": "tray3", - "carType": "boxcar", - "loaded": false - }, - { - "type": "newTrain.placeCar", - "trayId": "tray3", - "carType": "boxcar", - "loaded": false - }, - { - "type": "newTrain.placeCar", - "trayId": "tray3", - "carType": "caboose", - "loaded": true - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.discard", - "cardId": "c116", - "toSlot": 2 - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.discard", - "cardId": "c36", - "toSlot": 0 - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromDepartment", - "slot": 0 - }, - { - "type": "card.discard", - "cardId": "c29", - "toSlot": 0 - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "switch" - }, - { - "type": "switch.move", - "trayId": "tray3", - "to": { - "row": -1, - "col": -1 - }, - "reverse": false - }, - { - "type": "switch.dropCars", - "trayId": "tray3", - "count": 1 - }, - { - "type": "switch.move", - "trayId": "tray3", - "to": { - "row": -1, - "col": 2 - }, - "reverse": true - }, - { - "type": "switch.dropCars", - "trayId": "tray3", - "count": 1 - }, - { - "type": "switch.dropCars", - "trayId": "tray3", - "count": 1 - }, - { - "type": "switch.move", - "trayId": "tray3", - "to": { - "row": 0, - "col": 0 - }, - "reverse": false - }, - { - "type": "switch.end" - }, - { - "type": "newTrain.placeCar", - "trayId": "tray2", - "carType": "boxcar", - "loaded": true - }, - { - "type": "newTrain.placeCar", - "trayId": "tray2", - "carType": "boxcar", - "loaded": true - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.stockOutbound", - "at": { - "row": -1, - "col": 2 - }, - "carType": "boxcar" - }, - { - "type": "laborer.startLoad", - "at": { - "row": -1, - "col": 2 - } - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.stockOutbound", - "at": { - "row": -1, - "col": 2 - }, - "carType": "boxcar" - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 2 - }, - "box": 0 - }, - { - "type": "loadUnload.end" - }, - { - "type": "mainline.clearance", - "allow": false - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.discard", - "cardId": "c37", - "toSlot": 1 - }, - { - "type": "draw.end" - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 2 - }, - "box": 1 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromDepartment", - "slot": 1 - }, - { - "type": "card.discard", - "cardId": "c82", - "toSlot": 1 - }, - { - "type": "draw.end" - }, - { - "type": "newTrain.placeCar", - "trayId": "tray3", - "carType": "coach", - "loaded": true - }, - { - "type": "newTrain.placeCar", - "trayId": "tray3", - "carType": "boxcar", - "loaded": true - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 2 - }, - "box": 2 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.play", - "cardId": "c138", - "placement": { - "row": 0, - "col": 3 - }, - "variant": 0 - }, - { - "type": "draw.end" - }, - { - "type": "laborer.startLoad", - "at": { - "row": -1, - "col": 2 - } - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.stockOutbound", - "at": { - "row": -1, - "col": 2 - }, - "carType": "boxcar" - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 2 - }, - "box": 0 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.play", - "cardId": "c58", - "placement": { - "row": -1, - "col": 3 - }, - "variant": 0 - }, - { - "type": "draw.end" - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 2 - }, - "box": 1 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.play", - "cardId": "c204", - "placement": { - "row": 0, - "col": -3 - }, - "variant": 0 - }, - { - "type": "draw.end" - }, - { - "type": "newTrain.placeCar", - "trayId": "tray2", - "carType": "reefer", - "loaded": false - }, - { - "type": "newTrain.placeCar", - "trayId": "tray2", - "carType": "reefer", - "loaded": false - }, - { - "type": "newTrain.placeCar", - "trayId": "tray2", - "carType": "reefer", - "loaded": false - }, - { - "type": "newTrain.placeCar", - "trayId": "tray2", - "carType": "caboose", - "loaded": true - }, - { - "type": "porter.detrain", - "at": { - "row": 0, - "col": 0 - } - }, - { - "type": "porter.board", - "at": { - "row": 0, - "col": 0 - } - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 2 - }, - "box": 2 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.clearInbound", - "at": { - "row": 0, - "col": 0 - }, - "index": 0 - }, - { - "type": "porter.detrain", - "at": { - "row": 0, - "col": 0 - } - }, - { - "type": "porter.board", - "at": { - "row": 0, - "col": 0 - } - }, - { - "type": "laborer.beginUnload", - "at": { - "row": -1, - "col": 2 - }, - "carIndex": 0 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.clearInbound", - "at": { - "row": 0, - "col": 0 - }, - "index": 0 - }, - { - "type": "porter.detrain", - "at": { - "row": 0, - "col": 0 - } - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 2 - }, - "box": 2 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.clearInbound", - "at": { - "row": 0, - "col": 0 - }, - "index": 0 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 2 - }, - "box": 1 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.stockOutbound", - "at": { - "row": 0, - "col": 0 - }, - "carType": "coach" - }, - { - "type": "newTrain.placeCar", - "trayId": "tray1", - "carType": "reefer", - "loaded": false - }, - { - "type": "newTrain.placeCar", - "trayId": "tray1", - "carType": "reefer", - "loaded": false - }, - { - "type": "porter.board", - "at": { - "row": 0, - "col": 0 - } - }, - { - "type": "porter.detrain", - "at": { - "row": 0, - "col": 0 - } - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 2 - }, - "box": 0 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.clearInbound", - "at": { - "row": 0, - "col": 0 - }, - "index": 0 - }, - { - "type": "laborer.startLoad", - "at": { - "row": -1, - "col": 2 - } - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.clearInbound", - "at": { - "row": -1, - "col": 2 - }, - "index": 0 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 2 - }, - "box": 0 - }, - { - "type": "loadUnload.end" - }, - { - "type": "mainline.clearance", - "allow": false - }, - { - "type": "localOps.choose", - "option": "switch" - }, - { - "type": "switch.end" - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 2 - }, - "box": 1 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "switch" - }, - { - "type": "switch.end" - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 2 - }, - "box": 2 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.stockOutbound", - "at": { - "row": 0, - "col": 0 - }, - "carType": "coach" - }, - { - "type": "laborer.beginUnload", - "at": { - "row": -1, - "col": 2 - }, - "carIndex": 0 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.stockOutbound", - "at": { - "row": 0, - "col": 0 - }, - "carType": "coach" - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 2 - }, - "box": 2 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.stockOutbound", - "at": { - "row": -1, - "col": 2 - }, - "carType": "boxcar" - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 2 - }, - "box": 1 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.play", - "cardId": "c140", - "placement": { - "row": 0, - "col": -4 - }, - "variant": 0 - }, - { - "type": "draw.end" - }, - { - "type": "newTrain.placeCar", - "trayId": "tray1", - "carType": "boxcar", - "loaded": false - }, - { - "type": "newTrain.placeCar", - "trayId": "tray1", - "carType": "boxcar", - "loaded": false - }, - { - "type": "newTrain.placeCar", - "trayId": "tray1", - "carType": "boxcar", - "loaded": false - }, - { - "type": "newTrain.placeCar", - "trayId": "tray1", - "carType": "caboose", - "loaded": true - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 2 - }, - "box": 0 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.clearInbound", - "at": { - "row": -1, - "col": 2 - }, - "index": 0 - }, - { - "type": "laborer.startLoad", - "at": { - "row": -1, - "col": 2 - } - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.play", - "cardId": "c166", - "placement": { - "row": -1, - "col": -3 - }, - "variant": 1 - }, - { - "type": "draw.end" - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 2 - }, - "box": 0 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.play", - "cardId": "c71", - "placement": { - "row": -2, - "col": 1 - }, - "variant": 0 - }, - { - "type": "draw.end" - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 2 - }, - "box": 1 - }, - { - "type": "laborer.advanceLoad", - "at": { - "row": -1, - "col": 2 - }, - "box": 2 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "switch" - }, - { - "type": "switch.move", - "trayId": "tray1", - "to": { - "row": -1, - "col": -3 - }, - "reverse": false - }, - { - "type": "switch.dropCars", - "trayId": "tray1", - "count": 1 - }, - { - "type": "switch.move", - "trayId": "tray1", - "to": { - "row": 0, - "col": 0 - }, - "reverse": true - }, - { - "type": "switch.end" - }, - { - "type": "newTrain.placeCar", - "trayId": "tray3", - "carType": "boxcar", - "loaded": false - }, - { - "type": "newTrain.placeCar", - "trayId": "tray3", - "carType": "boxcar", - "loaded": false - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.discard", - "cardId": "c36", - "toSlot": 2 - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromDepartment", - "slot": 2 - }, - { - "type": "card.discard", - "cardId": "c90", - "toSlot": 2 - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "mainline.clearance", - "allow": false - }, - { - "type": "localOps.choose", - "option": "switch" - }, - { - "type": "switch.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "switch" - }, - { - "type": "switch.end" - }, - { - "type": "newTrain.placeCar", - "trayId": "tray1", - "carType": "coach", - "loaded": true - }, - { - "type": "newTrain.placeCar", - "trayId": "tray1", - "carType": "reefer", - "loaded": true - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.discard", - "cardId": "c37", - "toSlot": 0 - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromDepartment", - "slot": 0 - }, - { - "type": "card.discard", - "cardId": "c114", - "toSlot": 0 - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.discard", - "cardId": "c36", - "toSlot": 1 - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromDepartment", - "slot": 1 - }, - { - "type": "card.discard", - "cardId": "c115", - "toSlot": 1 - }, - { - "type": "draw.end" - }, - { - "type": "newTrain.placeCar", - "trayId": "tray3", - "carType": "reefer", - "loaded": true - }, - { - "type": "newTrain.placeCar", - "trayId": "tray3", - "carType": "reefer", - "loaded": true - }, - { - "type": "newTrain.placeCar", - "trayId": "tray3", - "carType": "reefer", - "loaded": true - }, - { - "type": "newTrain.placeCar", - "trayId": "tray3", - "carType": "caboose", - "loaded": true - }, - { - "type": "porter.detrain", - "at": { - "row": 0, - "col": 0 - } - }, - { - "type": "porter.board", - "at": { - "row": 0, - "col": 0 - } - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.clearInbound", - "at": { - "row": 0, - "col": 0 - }, - "index": 0 - }, - { - "type": "porter.detrain", - "at": { - "row": 0, - "col": 0 - } - }, - { - "type": "porter.board", - "at": { - "row": 0, - "col": 0 - } - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.clearInbound", - "at": { - "row": 0, - "col": 0 - }, - "index": 0 - }, - { - "type": "porter.detrain", - "at": { - "row": 0, - "col": 0 - } - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.clearInbound", - "at": { - "row": 0, - "col": 0 - }, - "index": 0 - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "freightAgent" - }, - { - "type": "freightAgent.stockOutbound", - "at": { - "row": 0, - "col": 0 - }, - "carType": "coach" - }, - { - "type": "newTrain.placeCar", - "trayId": "tray2", - "carType": "reefer", - "loaded": true - }, - { - "type": "newTrain.placeCar", - "trayId": "tray2", - "carType": "hopper", - "loaded": true - }, - { - "type": "porter.board", - "at": { - "row": 0, - "col": 0 - } - }, - { - "type": "porter.detrain", - "at": { - "row": 0, - "col": 0 - } - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.play", - "cardId": "c153", - "placement": { - "row": -1, - "col": 4 - }, - "variant": 0 - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.play", - "cardId": "c73", - "placement": { - "row": -2, - "col": 2 - }, - "variant": 0 - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "mainline.clearance", - "allow": false - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromHomeOffice" - }, - { - "type": "card.discard", - "cardId": "c37", - "toSlot": 2 - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromDepartment", - "slot": 2 - }, - { - "type": "card.discard", - "cardId": "c16", - "toSlot": 2 - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - }, - { - "type": "localOps.choose", - "option": "draw" - }, - { - "type": "draw.fromDepartment", - "slot": 2 - }, - { - "type": "card.discard", - "cardId": "c36", - "toSlot": 2 - }, - { - "type": "draw.end" - }, - { - "type": "loadUnload.end" - } - ] -} \ No newline at end of file diff --git a/src/engine/apply.ts b/src/engine/apply.ts index b264e10..0ae559c 100644 --- a/src/engine/apply.ts +++ b/src/engine/apply.ts @@ -297,11 +297,56 @@ function workTrack(f: Facility): [Load | null, Load | null, Load | null] { return f.menAtWork; } +/** + * HOW MANY EMPTY CARS OF THIS TYPE ARE SPOTTED AND NOT ALREADY PROMISED TO A LOAD. + * + * §9.3 — a load has to have somewhere to go. You cannot start the MEN | AT | WORK moves until an + * empty car of the right type is standing on the industry's track, "otherwise you are just dropping + * cargo onto the tracks — pointless waste". The final swap needs a car of the LOAD's type, so a + * hopper load cannot be swapped onto a tank: strict matching, not "any empty car". + * + * Counted rather than merely present, because green boxes and industry tracks both grow past one + * slot with Modifiers (measured: capacity > 1 on 24.5% of freight facilities and a track longer than + * one on 41%). Two loads staged against one spotted car would put the second one on the sign with + * nowhere to land, which is the jam this rule exists to prevent — just one step later. + * + * Loads already in the green box and already walking the sign both count as claims on a car. + */ +export function unclaimedEmpties(f: Facility, type: CarType): number { + const spotted = f.industryTrack.cars.filter((c) => !c.loaded && c.type === type).length; + const staged = f.outboundBox.filter((c) => c.type === type).length; + const working = (f.menAtWork ?? []).filter((l) => l?.dir === 'out' && l.type === type).length; + return spotted - staged - working; +} + +/** + * The green-box load that may start down the sign, or null if none may. + * + * Not simply `outboundBox[0]`. A Power Plant takes hoppers AND tanks, so a green box holding a + * hopper load and a tank load against one spotted empty tank must start the TANK — taking the first + * entry regardless would report the whole facility as blocked while a perfectly legal load sat + * beside it. + */ +export function startableLoad(f: Facility): number | null { + const claims = new Map(); + for (let i = 0; i < f.outboundBox.length; i++) { + const type = f.outboundBox[i]!.type; + // Each earlier entry of the same type has first claim on the spotted cars. + const ahead = claims.get(type) ?? 0; + const working = (f.menAtWork ?? []).filter((l) => l?.dir === 'out' && l.type === type).length; + const spotted = f.industryTrack.cars.filter((c) => !c.loaded && c.type === type).length; + if (spotted - working - ahead > 0) return i; + claims.set(type, ahead + 1); + } + return null; +} + export function canStartLoad(f: Facility): boolean { if (!f.menAtWork) return false; if (laborersLeft(f) < 1) return false; if (f.outboundBox.length === 0) return false; - return f.menAtWork[0] === null; + if (f.menAtWork[0] !== null) return false; + return startableLoad(f) !== null; } /** §9.2 — boarding needs a loaded coach in a green slot and a train with an empty coach. */ @@ -741,6 +786,15 @@ export function check(s: GameState, player: PlayerIndex, i: Intent): RejectionCo if (!s.yards.divisionYard.some((c) => c.type === i.carType && c.loaded)) { return 'NO_SUITABLE_CAR'; } + /** + * §9.3 — FREIGHT NEEDS A CAR AT THE DOCK BEFORE THE CARGO IS FETCHED. Staging a load against + * no car is fetching cargo you cannot ship. + * + * PASSENGERS ARE DELIBERATELY DIFFERENT and this is not an oversight: people can wait on the + * platform for a train that has not arrived, so a Passenger Facility stocks freely. Freight + * cannot — a crate on the ground is not a shipment. + */ + if (f.kind === 'freight' && unclaimedEmpties(f, i.carType) < 1) return 'NO_EMPTY_CAR_SPOTTED'; return null; } @@ -844,7 +898,13 @@ export function check(s: GameState, player: PlayerIndex, i: Intent): RejectionCo const f = facilityAt(s, player, i.at); if (!f) return 'NO_SUCH_FACILITY'; if (laborersLeft(f) < 1) return 'RESOURCE_SPENT'; - return canStartLoad(f) ? null : 'BOX_EMPTY'; + if (!f.menAtWork) return 'NO_SUCH_FACILITY'; + if (f.outboundBox.length === 0) return 'BOX_EMPTY'; + if (f.menAtWork[0] !== null) return 'BOX_FULL'; + // The car can be coupled away after the cargo was staged — running over an industry track + // couples whatever stands on it, mandatorily (§A.4) — so the Freight Agent's check is not + // enough on its own. Both gates are required. + return startableLoad(f) !== null ? null : 'NO_EMPTY_CAR_SPOTTED'; } case 'laborer.advanceLoad': { @@ -874,7 +934,20 @@ export function check(s: GameState, player: PlayerIndex, i: Intent): RejectionCo // The load is placed on WORK, the last box, so that box must be free — and a Passenger // Facility has no such box, so there is nothing to unload into. if (!f.menAtWork) return 'NO_SUCH_FACILITY'; - return f.menAtWork[f.menAtWork.length - 1] === null ? null : 'BOX_FULL'; + if (f.menAtWork[f.menAtWork.length - 1] !== null) return 'BOX_FULL'; + /** + * THE MIRROR OF THE LOAD RULE: a load coming IN needs somewhere to land too, and its + * destination is the red Inbound box. This was checked only at the last step, so an unload + * could be begun into a full box and walked W→A→M over three Stages before discovering it had + * nowhere to go — jamming the industry, which is then locked and needs a Freight Agent turn to + * clear. Measured: rare (2.2% of offers) but real, and seen jamming three times in 200 games. + * + * COUNTED, not just "is there a slot". Only the W box has to be free to begin, so once a load + * moves W→A a second can start behind it — two loads walking toward one slot. Every red box in + * play today holds exactly one car, which is precisely when that bites. + */ + const inFlight = f.menAtWork.filter((l) => l?.dir === 'in').length; + return f.capacity.inbound - f.inboundBox.length > inFlight ? null : 'INBOUND_BOX_FULL'; } case 'loadUnload.end': @@ -1360,7 +1433,8 @@ function execute(s: GameState, player: PlayerIndex, i: Intent): GameEvent[] { case 'laborer.startLoad': { const f = facilityAt(s, player, i.at)!; - return [{ type: 'loadStarted', player, at: i.at, carType: f.outboundBox[0]!.type }]; + // The first load with a car to land on, which is not always the first in the box. + return [{ type: 'loadStarted', player, at: i.at, carType: f.outboundBox[startableLoad(f)!]!.type }]; } case 'laborer.advanceLoad': { @@ -1744,9 +1818,10 @@ export function reduce(s: GameState, e: GameEvent): void { const ci = tray?.consist.findIndex((c) => c.type === 'coach' && c.loaded) ?? -1; if (tray && ci >= 0) { // The empty coach comes OUT OF THE DIVISION YARD, as §9.2 says. It used to be conjured, - // which minted a coach on every de-training. + // which minted a coach on every de-training. Throws now, for the reason in `unloadBegan`. const yi = s.yards.divisionYard.findIndex((c) => c.type === 'coach' && !c.loaded); - const empty = yi >= 0 ? s.yards.divisionYard.splice(yi, 1)[0]! : { type: 'coach' as const, loaded: false }; + if (yi < 0) throw new Error('passengersDetrained: no empty coach in the Division Yard'); + const empty = s.yards.divisionYard.splice(yi, 1)[0]!; refillDivisionYardIfEmpty(s); f.inboundBox.push(tray.consist[ci]!); tray.consist[ci] = empty; @@ -1798,10 +1873,17 @@ export function reduce(s: GameState, e: GameEvent): void { const f = facilityAt(s, e.player, e.at)!; const ci = f.industryTrack.cars.findIndex((c) => c.loaded); if (ci >= 0) { - // §9.3 — the replacement empty comes out of the Division Yard. Conjuring it here is what - // minted a car on every unload, and it also skipped a requirement the rule states. + /** + * §9.3 — the replacement empty comes out of the Division Yard. Conjuring it here is what + * minted a car on every unload, and it also skipped a requirement the rule states. + * + * THROWS rather than falling back. `check` guarantees the car is there, so reaching this is + * a broken invariant, and the old fallback quietly minted rolling stock instead of saying + * so — which is exactly the shape of leak `TODO.md` spent a conservation audit chasing. + */ const yi = s.yards.divisionYard.findIndex((c) => c.type === e.carType && !c.loaded); - const empty = yi >= 0 ? s.yards.divisionYard.splice(yi, 1)[0]! : { type: e.carType, loaded: false }; + if (yi < 0) throw new Error(`unloadBegan: no empty ${e.carType} in the Division Yard`); + const empty = s.yards.divisionYard.splice(yi, 1)[0]!; refillDivisionYardIfEmpty(s); f.industryTrack.cars[ci] = empty; } diff --git a/src/engine/intents.ts b/src/engine/intents.ts index 7edf577..00eca56 100644 --- a/src/engine/intents.ts +++ b/src/engine/intents.ts @@ -170,6 +170,12 @@ export type RejectionCode = * fallback fired 51 times with a coach train in front of the player: 27 with nobody waiting to * travel, 24 with passengers waiting and every coach on the train already full. */ + /** + * §9.3 — the green box may only be stocked, and a load may only start down the sign, when an empty + * car of THAT type is standing on the industry's track and is not already promised to another + * load. Fetching cargo you cannot ship is "just dropping it onto the tracks". + */ + | 'NO_EMPTY_CAR_SPOTTED' | 'NO_PORTERS_HERE' | 'NO_PASSENGERS_WAITING' | 'NO_EMPTY_COACH' diff --git a/src/sim/narrate.ts b/src/sim/narrate.ts index d8a634e..8de9e2e 100644 --- a/src/sim/narrate.ts +++ b/src/sim/narrate.ts @@ -17,7 +17,7 @@ import { adTrackCount, coordKey, seatOf, turnOf } from '../engine/state.ts'; import type { GameState, GridCoord, PlayerIndex, RollingStock, TrayId } from '../engine/state.ts'; -import { areaOf, canAdvanceLoad, canStartLoad, facilityCarType, laborersLeft, movesFor, portersLeft } from '../engine/apply.ts'; +import { areaOf, canAdvanceLoad, canStartLoad, facilityCarType, facilityCarTypes, laborersLeft, movesFor, portersLeft } from '../engine/apply.ts'; import type { GameEvent } from '../engine/events.ts'; // --------------------------------------------------------------------------- @@ -478,17 +478,36 @@ export function impediments(s: GameState, player: PlayerIndex = 0): Impediment[] } if (f.outboundBox.length > 0 && !canStartLoad(f) && laborersLeft(f) > 0) { + // Two quite different reasons, and telling a player "MEN is occupied" when the real answer is + // "there is no car to load onto" sends them to fix the wrong thing. + const blockedByBox = f.menAtWork?.[0] != null; out.push({ where: `${name} ${key}`, - why: 'green box has a load but MEN is occupied', - severity: 'waiting', + why: blockedByBox + ? 'green box has a load but MEN is occupied' + : `no empty ${want} spotted on this industry's track — a load has nowhere to go until a ` + + 'crew sets one out here (§9.3)', + severity: blockedByBox ? 'waiting' : 'stuck', }); } if (f.allows.outbound && f.outboundBox.length === 0) { + /** + * WHAT TO DO NEXT, in the order you have to do it. + * + * A freight industry cannot be stocked at all until an empty car of its commodity is standing + * on its track (§9.3) — so "needs a Freight Agent action" was the second step told to a player + * who had not done the first, and the Freight Agent option simply would not be there. Measured + * before the rule was enforced, 78% of the stocking moves the menu offered had no car to load + * onto. + */ + const spotted = f.industryTrack.cars.some((c) => !c.loaded && facilityCarTypes(f).includes(c.type)); out.push({ where: `${name} ${key}`, - why: 'green box empty — nothing to load (needs a Freight Agent action)', + why: spotted + ? 'green box empty — nothing to load (needs a Freight Agent action)' + : `green box empty, and no empty ${want} is spotted here — bring one in with a crew FIRST, ` + + 'then the Freight Agent can stage a load onto it (§9.3)', severity: 'waiting', }); } diff --git a/test/apply.test.ts b/test/apply.test.ts index ef52b36..633a930 100644 --- a/test/apply.test.ts +++ b/test/apply.test.ts @@ -449,7 +449,10 @@ describe('Freight Agent operations (§6.3)', () => { inboundBox: [], capacity: { outbound: 3, inbound: 0 }, menAtWork: [null, null, null], - industryTrack: { length: 4, cars: [] }, + // An empty hopper is SPOTTED. §9.3 refuses to stage cargo against no car — "otherwise you + // are just dropping cargo onto the tracks" — so a fixture with a bare track is a facility + // the Freight Agent cannot legally touch. + industryTrack: { length: 4, cars: [{ type: 'hopper', loaded: false }] }, laborers: 3, porters: 0, usedThisStage: { laborers: 0, porters: 0 },