I've noticed that trains do not seem to take the Mainline cards correctly. In the example I'm including, a train takes two hours to clear double track. However, double track should be a one-hour crossing. I see this a lot.
I've noticed that trains do not seem to take the Mainline cards correctly. In the example I'm including, a train takes two hours to clear double track. However, double track should be a one-hour crossing. I see this a lot.
From Claude - details of how trains cross mainline cards and what influences how fast they cross and where they show on the display.
Here's how it actually works, read out of the engine rather than the rules docs.
When does a train go onto a Mainline card?
Only during the Mainline Phase, which runs itself — s.clock.currentActor = null, no player acts. Every tray with a train number is sorted lowest number first, Timetabled before an Extra of the same number, and each gets exactly one attempt (movedThisPhase).
A train is eligible to leave from two places:
A Division Point, where it was made up.
The Office square itself — not Secondary Track. A train parked elsewhere in the district is not in the queue at all.
Then two gates before it may enter:
Made up (§8.2). badlyMadeUp refuses a broken-backed train — the engine buried among its own cars — and a caboose anywhere but the far end from the engine. It's direction-free: engine at either end is fine, pulling or pushing. Fails → the train holds, it isn't rejected, so the A/D track stays occupied and eventually bites. The remedies are a run-around or a Move in a Small Yard.
Clearance (§8.1), and this is the interesting one: it asks about the next Subdivision, not the next card. A Subdivision runs between boundaries, where a boundary is a Division Point or an Office that is a Control Point. Every Office starts as a Whistle Post, so at the opening the entire railroad is one Subdivision — which is why early traffic is so constrained, and why an Office upgrade buys capacity by splitting one in two.
Within that Subdivision, in two passes:
Any opposing train → blocked, absolutely. Exception: dispatch technology. Telegraph / Telephone / Radio, once a
Any opposing train → blocked, absolutely. Exception: dispatch technology. Telegraph / Telephone / Radio, once a Day, add +4 / +8 / +12 to the other train's number and let the meet happen.
A same-direction train → the Superintendent rules. Unless the other train is Red Flagged, or its card has ABS Signals — either of those blocks outright and there's no judgment to make.
Nowhere — and this is the part most likely to surprise you. There is no position. enterMainline pushes a Transit { tray, stagesRemaining, stagesTotal, direction } and that's it. Crossing is a countdown, not a walk across cells. state.ts says it plainly: "the cells printed on the cards are decoration."
Position is derived, in one place, for two purposes:
REGIONS_PER_MAINLINE_CARD = 2, marked provisional. The consequence of that entry term: a train crossing in one Stage enters already in region 1 — half a card in — while a train taking two or more starts at region 0. A fast train doesn't traverse a fast card, it appears at the far half of it.
stagesTotal is stored rather than recomputed, deliberately: a modifier played onto the card mid-crossing would change the answer and make the train appear to jump backwards.
The derived region is used for exactly two things — drawing the map, and the catch-up test below.
How is crossing time tracked?
Computed once, on entry, by crossingStages, and then counted down one per Mainline Phase:
mph = uniform value | Hilly's P/F split | 30 for a grade
base = mph >= 60 ? 1 : 2
stages = base + (train is slow ? 1 : 0) − gradeReduction floor of 1
Hilly reads the consist, not the train's class. Any coach on the train makes it a "passenger" train for that card. A fast freight crosses Hilly slower than a slow passenger train.
Heavy Grade has no printed number. It's a 30 until a modifier lands. Which way it climbs (gradeUp) is rolled from the seed at setup, not chosen by a player — Jesse's v0.5.0 call, because the card sits between two districts and orienting it advantages one neighbour over the other.
The loop, end to end
Each Mainline Phase, for each train in order:
stagesRemaining > 1 → catch-up check, then decrement.
stagesRemaining == 1 → leave the card. Next node is an Office (arrive, take an A/D track) or a Division Point (the run is over — the train retires, everyone scores trainPerTransit, which defaults to 0).
The catch-up check is how rear-end collisions happen. The train computes the region it's about to enter; if a same-direction train is already there and the card doesn't allow passing, they collide — both trains destroyed, charged to the Superintendent, since granting clearance is what let it in behind. ABS Signals converts that into holding short instead.
One asymmetry: this only runs while stagesRemaining > 1, so there's no catch-up test on the final Stage — the train is leaving the card that Stage regardless.
Trains stop at every Office they reach; there's no through-running. The terminalsOnly rule affects passenger work, not stopping.
The modifiers
Mainline modifier cards (mainline.modify, played from hand onto a Division node):
┌─────────────┬─────────────────────────────┬─────────────────────────────────────────────────────────────────────┐
│ Card │ Where │ Effect │
├─────────────┼─────────────────────────────┼─────────────────────────────────────────────────────────────────────┤
│ Brakeman │ Heavy Grade only │ −1 Stage downhill │
├─────────────┼─────────────────────────────┼─────────────────────────────────────────────────────────────────────┤
│ Airbrakes │ Heavy Grade only, needs │ −1 Stage downhill │
│ │ Brakeman already there │ │
├─────────────┼─────────────────────────────┼─────────────────────────────────────────────────────────────────────┤
│ Helpers │ Heavy Grade only │ −1 Stage uphill │
├─────────────┼─────────────────────────────┼─────────────────────────────────────────────────────────────────────┤
│ Realignment │ any card, not while a train │ changes the card: Curves→Plains, Plains→Double Track, Uncontrolled │
│ │ is on it │ Siding→Double Track, Trestle→Uncontrolled Siding │
└─────────────┴─────────────────────────────┴─────────────────────────────────────────────────────────────────────┘
Never below one Stage. So a fully-equipped grade is 1 Stage downhill for a fast train and 1 uphill with Helpers — but Brakeman and Airbrakes are dead weight to anything climbing.
Other things that change a crossing: ABS Signals (an Enhancement on a Mainline card — stop short, don't rear-end); Red Flags (a maneuver card protecting one specific stopped train, where ABS protects everything on the card); Telegraph/Telephone/Radio (once a Day, force a facing meet); and Office upgrades, which don't touch crossing time but split Subdivisions and so change what can be on the line at once.
One thing I should flag. docs/rules/implications.md Q3 says Expedite means "the train departs the same Stage it arrives." The engine does not implement that — isExpedited is purely a fault rule: an expedited train not standing on the Office square when a Mainline Phase begins costs its owner Revenue, every Phase it's away. The code comment says so explicitly: "Expedite does not change WHEN a train leaves." That was the v0.4.9 "expedite rewrite"; the Q3 row didn't move with it, and the pacing table below it still leans on the old reading. Want me to correct that row, or add it to the TODO?Day, add +4 / +8 / +12 to the other train's number and let the meet happen.
2. A same-direction train → the Superintendent rules. Unless the other train is Red Flagged, or its card has ABS Signals — either of those blocks outright and there's no judgment to make.
Nowhere — and this is the part most likely to surprise you. There is no position. enterMainline pushes a Transit { tray, stagesRemaining, stagesTotal, direction } and that's it. Crossing is a countdown, not a walk across cells. state.ts says it plainly: "the cells printed on the cards are decoration."
Position is derived, in one place, for two purposes:
REGIONS_PER_MAINLINE_CARD = 2, marked provisional. The consequence of that entry term: a train crossing in one Stage enters already in region 1 — half a card in — while a train taking two or more starts at region 0. A fast train doesn't traverse a fast card, it appears at the far half of it.
stagesTotal is stored rather than recomputed, deliberately: a modifier played onto the card mid-crossing would change the answer and make the train appear to jump backwards.
The derived region is used for exactly two things — drawing the map, and the catch-up test below.
How is crossing time tracked?
Computed once, on entry, by crossingStages, and then counted down one per Mainline Phase:
mph = uniform value | Hilly's P/F split | 30 for a grade
base = mph >= 60 ? 1 : 2
stages = base + (train is slow ? 1 : 0) − gradeReduction floor of 1
From Claude - details of how trains cross mainline cards and what influences how fast they cross and where they show on the display.
Here's how it actually works, read out of the engine rather than the rules docs.
1. When does a train go onto a Mainline card?
Only during the Mainline Phase, which runs itself — s.clock.currentActor = null, no player acts. Every tray with a train number is sorted lowest number first, Timetabled before an Extra of the same number, and each gets exactly one attempt (movedThisPhase).
A train is eligible to leave from two places:
- A Division Point, where it was made up.
- The Office square itself — not Secondary Track. A train parked elsewhere in the district is not in the queue at all.
Then two gates before it may enter:
Made up (§8.2). badlyMadeUp refuses a broken-backed train — the engine buried among its own cars — and a caboose anywhere but the far end from the engine. It's direction-free: engine at either end is fine, pulling or pushing. Fails → the train holds, it isn't rejected, so the A/D track stays occupied and eventually bites. The remedies are a run-around or a Move in a Small Yard.
Clearance (§8.1), and this is the interesting one: it asks about the next Subdivision, not the next card. A Subdivision runs between boundaries, where a boundary is a Division Point or an Office that is a Control Point. Every Office starts as a Whistle Post, so at the opening the entire railroad is one Subdivision — which is why early traffic is so constrained, and why an Office upgrade buys capacity by splitting one in two.
Within that Subdivision, in two passes:
1. Any opposing train → blocked, absolutely. Exception: dispatch technology. Telegraph / Telephone / Radio, once a
✔ Update installed · Restart to update
──────────────────────────────────────────────────────────
1. Any opposing train → blocked, absolutely. Exception: dispatch technology. Telegraph / Telephone / Radio, once a Day, add +4 / +8 / +12 to the other train's number and let the meet happen.
2. A same-direction train → the Superintendent rules. Unless the other train is Red Flagged, or its card has ABS Signals — either of those blocks outright and there's no judgment to make.
Cards printing "trains may pass" (Double Track, Uncontrolled Siding) skip occupancy entirely.
2. Where is it placed on the card?
Nowhere — and this is the part most likely to surprise you. There is no position. enterMainline pushes a Transit { tray, stagesRemaining, stagesTotal, direction } and that's it. Crossing is a countdown, not a walk across cells. state.ts says it plainly: "the cells printed on the cards are decoration."
Position is derived, in one place, for two purposes:
regionOf(t) = clamp( (2 − stagesTotal) + (stagesTotal − stagesRemaining), 0, 1 )
REGIONS_PER_MAINLINE_CARD = 2, marked provisional. The consequence of that entry term: a train crossing in one Stage enters already in region 1 — half a card in — while a train taking two or more starts at region 0. A fast train doesn't traverse a fast card, it appears at the far half of it.
stagesTotal is stored rather than recomputed, deliberately: a modifier played onto the card mid-crossing would change the answer and make the train appear to jump backwards.
The derived region is used for exactly two things — drawing the map, and the catch-up test below.
3. How is crossing time tracked?
Computed once, on entry, by crossingStages, and then counted down one per Mainline Phase:
mph = uniform value | Hilly's P/F split | 30 for a grade
base = mph >= 60 ? 1 : 2
stages = base + (train is slow ? 1 : 0) − gradeReduction floor of 1
┌─────────────────────┬───────────┬────────┬────────┬─────────────────────────────┐
│ Card │ Speed │ Fast │ Slow │ Notes │
├─────────────────────┼───────────┼────────┼────────┼─────────────────────────────┤
│ Plains │ 60 │ 1 │ 2 │ │
├─────────────────────┼───────────┼────────┼────────┼─────────────────────────────┤
│ Double Track │ 60 │ 1 │ 2 │ trains may pass │
├─────────────────────┼───────────┼────────┼────────┼─────────────────────────────┤
│ Uncontrolled Siding │ 60 │ 1 │ 2 │ trains may pass │
├─────────────────────┼───────────┼────────┼────────┼─────────────────────────────┤
│ Trestle │ 60 │ 1 │ 2 │ │
├─────────────────────┼───────────┼────────┼────────┼─────────────────────────────┤
│ Interchange │ 60 │ 1 │ 2 │ cars may be re-sorted here │
├─────────────────────┼───────────┼────────┼────────┼─────────────────────────────┤
│ Curves │ 30 │ 2 │ 3 │ │
├─────────────────────┼───────────┼────────┼────────┼─────────────────────────────┤
│ Tunnel │ 30 │ 2 │ 3 │ │
├─────────────────────┼───────────┼────────┼────────┼─────────────────────────────┤
│ Hilly │ P60 / F30 │ 1 or 2 │ 2 or 3 │ by consist, not speed class │
├─────────────────────┼───────────┼────────┼────────┼─────────────────────────────┤
│ Heavy Grade │ grade │ 2 │ 3 │ before modifiers │
└─────────────────────┴───────────┴────────┴────────┴─────────────────────────────┘
Two things worth pulling out:
- Hilly reads the consist, not the train's class. Any coach on the train makes it a "passenger" train for that card. A fast freight crosses Hilly slower than a slow passenger train.
- Heavy Grade has no printed number. It's a 30 until a modifier lands. Which way it climbs (gradeUp) is rolled from the seed at setup, not chosen by a player — Jesse's v0.5.0 call, because the card sits between two districts and orienting it advantages one neighbour over the other.
4. The loop, end to end
Each Mainline Phase, for each train in order:
- stagesRemaining > 1 → catch-up check, then decrement.
- stagesRemaining == 1 → leave the card. Next node is an Office (arrive, take an A/D track) or a Division Point (the run is over — the train retires, everyone scores trainPerTransit, which defaults to 0).
The catch-up check is how rear-end collisions happen. The train computes the region it's about to enter; if a same-direction train is already there and the card doesn't allow passing, they collide — both trains destroyed, charged to the Superintendent, since granting clearance is what let it in behind. ABS Signals converts that into holding short instead.
One asymmetry: this only runs while stagesRemaining > 1, so there's no catch-up test on the final Stage — the train is leaving the card that Stage regardless.
Trains stop at every Office they reach; there's no through-running. The terminalsOnly rule affects passenger work, not stopping.
5. The modifiers
Mainline modifier cards (mainline.modify, played from hand onto a Division node):
┌─────────────┬─────────────────────────────┬─────────────────────────────────────────────────────────────────────┐
│ Card │ Where │ Effect │
├─────────────┼─────────────────────────────┼─────────────────────────────────────────────────────────────────────┤
│ Brakeman │ Heavy Grade only │ −1 Stage downhill │
├─────────────┼─────────────────────────────┼─────────────────────────────────────────────────────────────────────┤
│ Airbrakes │ Heavy Grade only, needs │ −1 Stage downhill │
│ │ Brakeman already there │ │
├─────────────┼─────────────────────────────┼─────────────────────────────────────────────────────────────────────┤
│ Helpers │ Heavy Grade only │ −1 Stage uphill │
├─────────────┼─────────────────────────────┼─────────────────────────────────────────────────────────────────────┤
│ Realignment │ any card, not while a train │ changes the card: Curves→Plains, Plains→Double Track, Uncontrolled │
│ │ is on it │ Siding→Double Track, Trestle→Uncontrolled Siding │
└─────────────┴─────────────────────────────┴─────────────────────────────────────────────────────────────────────┘
Never below one Stage. So a fully-equipped grade is 1 Stage downhill for a fast train and 1 uphill with Helpers — but Brakeman and Airbrakes are dead weight to anything climbing.
Other things that change a crossing: ABS Signals (an Enhancement on a Mainline card — stop short, don't rear-end); Red Flags (a maneuver card protecting one specific stopped train, where ABS protects everything on the card); Telegraph/Telephone/Radio (once a Day, force a facing meet); and Office upgrades, which don't touch crossing time but split Subdivisions and so change what can be on the line at once.
---
One thing I should flag. docs/rules/implications.md Q3 says Expedite means "the train departs the same Stage it arrives." The engine does not implement that — isExpedited is purely a fault rule: an expedited train not standing on the Office square when a Mainline Phase begins costs its owner Revenue, every Phase it's away. The code comment says so explicitly: "Expedite does not change WHEN a train leaves." That was the v0.4.9 "expedite rewrite"; the Q3 row didn't move with it, and the pacing table below it still leans on the old reading. Want me to correct that row, or add it to the TODO?Day, add +4 / +8 / +12 to the other train's number and let the meet happen.
2. A same-direction train → the Superintendent rules. Unless the other train is Red Flagged, or its card has ABS Signals — either of those blocks outright and there's no judgment to make.
Cards printing "trains may pass" (Double Track, Uncontrolled Siding) skip occupancy entirely.
2. Where is it placed on the card?
Nowhere — and this is the part most likely to surprise you. There is no position. enterMainline pushes a Transit { tray, stagesRemaining, stagesTotal, direction } and that's it. Crossing is a countdown, not a walk across cells. state.ts says it plainly: "the cells printed on the cards are decoration."
Position is derived, in one place, for two purposes:
regionOf(t) = clamp( (2 − stagesTotal) + (stagesTotal − stagesRemaining), 0, 1 )
REGIONS_PER_MAINLINE_CARD = 2, marked provisional. The consequence of that entry term: a train crossing in one Stage enters already in region 1 — half a card in — while a train taking two or more starts at region 0. A fast train doesn't traverse a fast card, it appears at the far half of it.
stagesTotal is stored rather than recomputed, deliberately: a modifier played onto the card mid-crossing would change the answer and make the train appear to jump backwards.
The derived region is used for exactly two things — drawing the map, and the catch-up test below.
3. How is crossing time tracked?
Computed once, on entry, by crossingStages, and then counted down one per Mainline Phase:
mph = uniform value | Hilly's P/F split | 30 for a grade
base = mph >= 60 ? 1 : 2
stages = base + (train is slow ? 1 : 0) − gradeReduction floor of 1
┌─────────────────────┬───────────┬────────┬────────┬─────────────────────────────┐
│ Card │ Speed │ Fast │ Slow │ Notes │
├─────────────────────┼───────────┼────────┼────────┼─────────────────────────────┤
RAR email:
Also, problems on the mainline cards. I know that Plains is 1 stage for ALL trains. So are interlockings, with a second stage for incoming extras to hold at. Haven't checked the rest but will as they show up.
Curve are 2 stages, fast or slow, doesn't matter.
Double is one stage, fast or slow, also doesn't matter.
Heavy Grade - Trying to put ABS signals on grade. Not allowed. Need them there. BTW, grade should tell you which way is up.
RAR email:
Also, problems on the mainline cards. I know that Plains is 1 stage for ALL trains. So are interlockings, with a second stage for incoming extras to hold at. Haven't checked the rest but will as they show up.
Curve are 2 stages, fast or slow, doesn't matter.
Double is one stage, fast or slow, also doesn't matter.
Heavy Grade - Trying to put ABS signals on grade. Not allowed. Need them there. BTW, grade should tell you which way is up.
Root-caused. The double-track case in the report and the stage counts in your email are the same bug, and it traces back to a recorded answer that now looks wrong.
Crossing time is computed from two rules:
Q1 — the printed 60/30 are mph expressed as crossing time. A 60 card takes one Stage, a 30 card takes two. The printed cells are decoration.
Q2 — "Slow adds one Stage to every card. Fast 60→1, 30→2; Slow 60→2, 30→3."
Q2 is recorded in docs/rules/implications.md §9a as your own answer, and the engine implements it literally. That is why Double Track cost two Stages in the save: the train was Slow, so the 60-card's one Stage became two.
Your email says Q2 is wrong, and the three counts you give are all consistent with dropping it entirely:
Card
You say
Engine, fast
Engine, slow
Plains (60)
1 for all trains
1
2
Curves (30)
2, fast or slow
2
3
Double Track (60)
1, fast or slow
1
2
Every mismatch is exactly the Slow penalty. Drop Q2 and all three of your numbers come out right, with no other change. So the question is narrow: does Fast/Slow affect crossing time at all, or does the printed card number decide it on its own? If it is the latter, the fix is one line, and Hilly (P60/F30) becomes the only card that distinguishes trains — reading the consist, not the speed label.
Please confirm before I change it, because Q2 is load-bearing elsewhere. It was the basis for a measured consequence: on a 3-player Division a Fast train crosses end-to-end in 9 Stages and a Slow one in 13 — so under Q2 every Slow train is still on the road when the next Day begins, holding its Crew Tray. Removing Q2 takes that pressure off, which is probably desirable, but it changes what players + 3 trays is worth and the balance numbers will need re-measuring.
Interlockings — a second Stage for an incoming Extra to hold at is a different mechanism from crossing time and is implemented separately; I have not checked it against your reading yet.
Two smaller items from your email, both confirmed:
ABS Signals on Heavy Grade. The engine does not forbid this — the placement check accepts any Mainline card, Heavy Grade included, and the card's own text says "any Mainline card". So what stopped you is a UI problem, not a rule. A save or a screenshot of the moment you tried would pin it down; my guess is the card was not offered as a selectable target rather than the play being refused.
"Grade should tell you which way is up." Confirmed gap, and a deliberate one so far. The card prints "Player sets orientation" and the game does not implement it — the uphill direction is fixed rather than chosen, because a Mainline card sits between districts and no player has a fair claim to the choice, and the choice is not cosmetic: it decides permanently which of Brakeman / Airbrakes / Helpers can ever pay, and therefore which direction of traffic is favoured. Giving it to the Superintendent was considered and rejected (the office rotates every three Stages; the advantage would not). But whatever the answer, the board should say which way is up — right now it does not display it at all, which is the part that is simply missing. Reasoning is in implications.md §10 Q11 if you want to overrule the first half.
**Root-caused. The double-track case in the report and the stage counts in your email are the same bug, and it traces back to a recorded answer that now looks wrong.**
Crossing time is computed from two rules:
- **Q1** — the printed 60/30 are mph expressed as crossing time. A 60 card takes one Stage, a 30 card takes two. The printed cells are decoration.
- **Q2** — *"Slow adds one Stage to every card. Fast 60→1, 30→2; Slow 60→2, 30→3."*
Q2 is recorded in `docs/rules/implications.md` §9a as your own answer, and the engine implements it literally. That is why Double Track cost two Stages in the save: the train was **Slow**, so the 60-card's one Stage became two.
**Your email says Q2 is wrong**, and the three counts you give are all consistent with dropping it entirely:
| Card | You say | Engine, fast | Engine, slow |
| --- | --- | --- | --- |
| Plains (60) | 1 for all trains | 1 | **2** |
| Curves (30) | 2, fast or slow | 2 | **3** |
| Double Track (60) | 1, fast or slow | 1 | **2** |
Every mismatch is exactly the Slow penalty. Drop Q2 and all three of your numbers come out right, with no other change. So the question is narrow: **does Fast/Slow affect crossing time at all, or does the printed card number decide it on its own?** If it is the latter, the fix is one line, and Hilly (P60/F30) becomes the only card that distinguishes trains — reading the consist, not the speed label.
**Please confirm before I change it**, because Q2 is load-bearing elsewhere. It was the basis for a measured consequence: on a 3-player Division a Fast train crosses end-to-end in 9 Stages and a Slow one in 13 — so under Q2 every Slow train is still on the road when the next Day begins, holding its Crew Tray. Removing Q2 takes that pressure off, which is probably desirable, but it changes what `players + 3` trays is worth and the balance numbers will need re-measuring.
**Interlockings** — a second Stage for an incoming Extra to hold at is a different mechanism from crossing time and is implemented separately; I have not checked it against your reading yet.
---
**Two smaller items from your email, both confirmed:**
**ABS Signals on Heavy Grade.** The engine does *not* forbid this — the placement check accepts any Mainline card, Heavy Grade included, and the card's own text says "any Mainline card". So what stopped you is a UI problem, not a rule. A save or a screenshot of the moment you tried would pin it down; my guess is the card was not offered as a selectable target rather than the play being refused.
**"Grade should tell you which way is up."** Confirmed gap, and a deliberate one so far. The card prints "Player sets orientation" and the game does not implement it — the uphill direction is fixed rather than chosen, because a Mainline card sits between districts and no player has a fair claim to the choice, and the choice is not cosmetic: it decides permanently which of Brakeman / Airbrakes / Helpers can ever pay, and therefore which direction of traffic is favoured. Giving it to the Superintendent was considered and rejected (the office rotates every three Stages; the advantage would not). But **whatever the answer, the board should say which way is up** — right now it does not display it at all, which is the part that is simply missing. Reasoning is in `implications.md` §10 Q11 if you want to overrule the first half.
RAR - I notice that you are basing stages in mainline cards off coach/non-coach. Actually, I'm including the train sheets again. You'll see that all trains are rated as FAST and SLOW. These define the starting points on most of these mainline cards.
RAR - I notice that you are basing stages in mainline cards off coach/non-coach. Actually, I'm including the train sheets again. You'll see that all trains are rated as FAST and SLOW. These define the starting points on most of these mainline cards.
Reviewed
some of my notes and your latest cards. Crossing time for a mainline
card is currently implemented based on two rules (with original
speeds). latest cards have speeds of 50, 30, P50, F25, G, 60, 25.
Latest trains designated as Fast / Slow and #Freight / #coach /
#caboose.
Rule 1The printed 60/30 are mph expressed as crossing time. A 60 card takes one Stage, a 30 card takes two.
Rule 2Slow adds one Stage to every card. Fast 60→1, 30→2; Slow 60→2, 30→3.
That is why Double Track cost two Stages in the save game you sent me: the train wasSlow, so the 60-card's one Stage became two.
Card
You say
Engine, fast
Engine, slow
Plains (60)
1 for all trains
1
2
Curves (30)
2, fast or slow
2
3
Double Track (60)
1, fast or slow
1
2
Starting location / stages to cross a mainline card should not be based on coach vs. freight, but fast / slow. So how does Fast/Slow affect crossing time? Are trains correctly assigned to Fast / Slow?
We should discuss. Currently
on a 3-player Division a Fast train crosses (w/out office area
switching delays) end-to-end in 9 Stages and a Slow one in 13. so
currently every Slow train will take more than 24 hours to complete -
holding its Crew Tray. Currently we implement players + 3trays . That assumption should be re-examined as well...
Email from RAR:
Yeah, I was wondering about the times.
So, please ignore the speed signs I put on the cards - those are nothing but scene-setting graphics that mimic the speed you are traveling (if it's 60 mile across the Mainline card). It's just ambiance, nothing more.
All movement is based on FAST/SLOW ratings on the train cards. Most of the freights are slow, but there are fast ones. But yes, you need to check the trains speed and that determines the starting stage.
Been worried about the time it takes to cross the division. More thunking on this is needed.
Email from RAR:
Yeah, I was wondering about the times.
So, please ignore the speed signs I put on the cards - those are nothing but scene-setting graphics that mimic the speed you are traveling (if it's 60 mile across the Mainline card). It's just ambiance, nothing more.
All movement is based on FAST/SLOW ratings on the train cards. Most of the freights are slow, but there are fast ones. But yes, you need to check the trains speed and that determines the starting stage.
Been worried about the time it takes to cross the division. More thunking on this is needed.
Regions shown on cards indicate how many stages it takes to cross. Plains is 1. double track is 1, tunnel is 2, Curves is 2, heavy grade is 3 unless you have help. In which case it may be less.
Some cards say fast / slow. This is an indication that if on the train card, the train is listed as fast or slow, that's starting position / how many stages it takes to traverse the card. Fast / Slow does not apply to every card - just those that say fast / slow on them. currently this is only hilly.
Other cards list other things
grade. if you play the home deck card 'helpers' against the mainline card heavy grade, it remains there the rest of the game and helps all trains going up hill by starting 1 region easier - so 2 to traverse not 3. other cards help the other direction, similar idea. airbrakes is an upgrade from brakemen (which must be played first).
uncontrolled siding. if a train already exists when you arrive, you go in the second stage back (you are in the siding and are one behind the other train). this prevents a collision - since you are not in same exact location
interchange has new extras show up in second region (like uncontrolled siding)
Mainline card- ABS. This is played on a mainline card to prevent collisions. if a collision would normally occur, the train moving onto the card is instead held back. ABS should be able to be played on ANY mainline card.
Ignore speed signs. they are just graphics.
Regions shown on cards indicate how many stages it takes to cross. Plains is 1. double track is 1, tunnel is 2, Curves is 2, heavy grade is 3 unless you have help. In which case it may be less.
Some cards say fast / slow. This is an indication that if on the train card, the train is listed as fast or slow, that's starting position / how many stages it takes to traverse the card. Fast / Slow does not apply to every card - just those that say fast / slow on them. currently this is only hilly.
Other cards list other things
- grade. if you play the home deck card 'helpers' against the mainline card heavy grade, it remains there the rest of the game and helps all trains going up hill by starting 1 region easier - so 2 to traverse not 3. other cards help the other direction, similar idea. airbrakes is an upgrade from brakemen (which must be played first).
- uncontrolled siding. if a train already exists when you arrive, you go in the second stage back (you are in the siding and are one behind the other train). this prevents a collision - since you are not in same exact location
- interchange has new extras show up in second region (like uncontrolled siding)
Mainline card- ABS. This is played on a mainline card to prevent collisions. if a collision would normally occur, the train moving onto the card is instead held back. ABS should be able to be played on ANY mainline card.
This replaces two recorded rulings rather than correcting a number — Q1, that the printed 60/30
are crossing time, and Q2, that a Slow train adds a Stage to every card. Q2 is what produced the
report: the train was Slow, so Double Track's one Stage became two. Both are struck through in implications.md and replaced by Q1a, which quotes your ruling.
A card now costs one Stage per printed region, and where a train STARTS is what varies. Plains 1,
Double Track 1, Trestle 1, Curves 2, Tunnel 2, Heavy Grade 3. Fast/Slow is read on Hilly and nowhere
else, and Hilly no longer reads the consist — which had a fast freight crossing slower than a slow
passenger train. Helpers start an uphill train a region on, Brakeman a downhill one, Airbrakes
another again. The Uncontrolled Siding and Interchange print a back region that is not road: a train
through starts past it, one arriving to find the siding occupied takes it and runs a region behind,
and an Extra beginning its run at an Interchange starts there.
Three things turned out to be missing rather than wrong. With Plains at one region, a following
train is in the same place as the train ahead the moment it enters — and nothing tested that, because
the catch-up check sits inside stagesRemaining > 1, which a one-Stage crossing never reaches. That
is exactly the case ABS describes and it had to be built. ABS was also holding silently on the
Office and Division Point paths, so the one card whose purpose is preventing a wreck did its job
invisibly. And collide never released the A/D track — which never mattered while every collision
happened out on the road, but a train destroyed as it LEAVES is still standing at the Office. The
Uncontrolled Siding was marked "trains may pass", which skipped the collision test altogether and
made the siding do nothing at all.
Measured, on the thing you said you were worried about. On the Mainline cards of a 3-player
Division, a fast train pays ~5.6 Stages against ~5.4 before, and a slow one ~6.0 against ~9.4. Fast
traffic is unchanged; slow traffic is about a third quicker, and the Fast/Slow gap across a whole
Division collapses from roughly four Stages to under one. Q2's recorded consequence — every Slow
train still on the road when the next Day begins, holding its Crew Tray — no longer holds, so the players + 3 tray count is due a re-examination. That is in TODO.md, not done here.
Two side effects recorded rather than acted on: freight share fell 8% to 5% and completed freight
loads got scarcer, which runs against the obvious expectation and is not yet explained; and the bot
stopped playing Red Flags (offered 4,212 times in 600 games, played 4).
Fixed in **v0.7.2** (`2ab25e3`) and **v0.4.9h** (`e9683cc`).
**This replaces two recorded rulings rather than correcting a number** — Q1, that the printed 60/30
are crossing time, and Q2, that a Slow train adds a Stage to every card. Q2 is what produced the
report: the train was Slow, so Double Track's one Stage became two. Both are struck through in
`implications.md` and replaced by Q1a, which quotes your ruling.
A card now costs **one Stage per printed region**, and where a train STARTS is what varies. Plains 1,
Double Track 1, Trestle 1, Curves 2, Tunnel 2, Heavy Grade 3. Fast/Slow is read on Hilly and nowhere
else, and Hilly no longer reads the consist — which had a fast freight crossing slower than a slow
passenger train. Helpers start an uphill train a region on, Brakeman a downhill one, Airbrakes
another again. The Uncontrolled Siding and Interchange print a back region that is not road: a train
through starts past it, one arriving to find the siding occupied takes it and runs a region behind,
and an Extra beginning its run at an Interchange starts there.
**Three things turned out to be missing rather than wrong.** With Plains at one region, a following
train is in the same place as the train ahead the moment it enters — and nothing tested that, because
the catch-up check sits inside `stagesRemaining > 1`, which a one-Stage crossing never reaches. That
is exactly the case ABS describes and it had to be built. ABS was also holding **silently** on the
Office and Division Point paths, so the one card whose purpose is preventing a wreck did its job
invisibly. And `collide` never released the A/D track — which never mattered while every collision
happened out on the road, but a train destroyed as it LEAVES is still standing at the Office. The
Uncontrolled Siding was marked "trains may pass", which skipped the collision test altogether and
made the siding do nothing at all.
**Measured, on the thing you said you were worried about.** On the Mainline cards of a 3-player
Division, a fast train pays ~5.6 Stages against ~5.4 before, and a slow one ~6.0 against ~9.4. Fast
traffic is unchanged; **slow traffic is about a third quicker**, and the Fast/Slow gap across a whole
Division collapses from roughly four Stages to under one. Q2's recorded consequence — every Slow
train still on the road when the next Day begins, holding its Crew Tray — no longer holds, so the
`players + 3` tray count is due a re-examination. That is in `TODO.md`, not done here.
Two side effects recorded rather than acted on: freight share fell 8% to 5% and completed freight
loads got scarcer, which runs against the obvious expectation and is not yet explained; and the bot
stopped playing Red Flags (offered 4,212 times in 600 games, played 4).
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
I've noticed that trains do not seem to take the Mainline cards correctly. In the example I'm including, a train takes two hours to clear double track. However, double track should be a one-hour crossing. I see this a lot.
From Claude - details of how trains cross mainline cards and what influences how fast they cross and where they show on the display.
Here's how it actually works, read out of the engine rather than the rules docs.
Only during the Mainline Phase, which runs itself — s.clock.currentActor = null, no player acts. Every tray with a train number is sorted lowest number first, Timetabled before an Extra of the same number, and each gets exactly one attempt (movedThisPhase).
A train is eligible to leave from two places:
Then two gates before it may enter:
Made up (§8.2). badlyMadeUp refuses a broken-backed train — the engine buried among its own cars — and a caboose anywhere but the far end from the engine. It's direction-free: engine at either end is fine, pulling or pushing. Fails → the train holds, it isn't rejected, so the A/D track stays occupied and eventually bites. The remedies are a run-around or a Move in a Small Yard.
Clearance (§8.1), and this is the interesting one: it asks about the next Subdivision, not the next card. A Subdivision runs between boundaries, where a boundary is a Division Point or an Office that is a Control Point. Every Office starts as a Whistle Post, so at the opening the entire railroad is one Subdivision — which is why early traffic is so constrained, and why an Office upgrade buys capacity by splitting one in two.
Within that Subdivision, in two passes:
Any opposing train → blocked, absolutely. Exception: dispatch technology. Telegraph / Telephone / Radio, once a
──────────────────────────────────────────────────────────
Cards printing "trains may pass" (Double Track, Uncontrolled Siding) skip occupancy entirely.
Nowhere — and this is the part most likely to surprise you. There is no position. enterMainline pushes a Transit { tray, stagesRemaining, stagesTotal, direction } and that's it. Crossing is a countdown, not a walk across cells. state.ts says it plainly: "the cells printed on the cards are decoration."
Position is derived, in one place, for two purposes:
regionOf(t) = clamp( (2 − stagesTotal) + (stagesTotal − stagesRemaining), 0, 1 )
REGIONS_PER_MAINLINE_CARD = 2, marked provisional. The consequence of that entry term: a train crossing in one Stage enters already in region 1 — half a card in — while a train taking two or more starts at region 0. A fast train doesn't traverse a fast card, it appears at the far half of it.
stagesTotal is stored rather than recomputed, deliberately: a modifier played onto the card mid-crossing would change the answer and make the train appear to jump backwards.
The derived region is used for exactly two things — drawing the map, and the catch-up test below.
Computed once, on entry, by crossingStages, and then counted down one per Mainline Phase:
mph = uniform value | Hilly's P/F split | 30 for a grade
base = mph >= 60 ? 1 : 2
stages = base + (train is slow ? 1 : 0) − gradeReduction floor of 1
┌─────────────────────┬───────────┬────────┬────────┬─────────────────────────────┐
│ Card │ Speed │ Fast │ Slow │ Notes │
├─────────────────────┼───────────┼────────┼────────┼─────────────────────────────┤
│ Plains │ 60 │ 1 │ 2 │ │
├─────────────────────┼───────────┼────────┼────────┼─────────────────────────────┤
│ Double Track │ 60 │ 1 │ 2 │ trains may pass │
├─────────────────────┼───────────┼────────┼────────┼─────────────────────────────┤
│ Uncontrolled Siding │ 60 │ 1 │ 2 │ trains may pass │
├─────────────────────┼───────────┼────────┼────────┼─────────────────────────────┤
│ Trestle │ 60 │ 1 │ 2 │ │
├─────────────────────┼───────────┼────────┼────────┼─────────────────────────────┤
│ Interchange │ 60 │ 1 │ 2 │ cars may be re-sorted here │
├─────────────────────┼───────────┼────────┼────────┼─────────────────────────────┤
│ Curves │ 30 │ 2 │ 3 │ │
├─────────────────────┼───────────┼────────┼────────┼─────────────────────────────┤
│ Tunnel │ 30 │ 2 │ 3 │ │
├─────────────────────┼───────────┼────────┼────────┼─────────────────────────────┤
│ Hilly │ P60 / F30 │ 1 or 2 │ 2 or 3 │ by consist, not speed class │
├─────────────────────┼───────────┼────────┼────────┼─────────────────────────────┤
│ Heavy Grade │ grade │ 2 │ 3 │ before modifiers │
└─────────────────────┴───────────┴────────┴────────┴─────────────────────────────┘
Two things worth pulling out:
Each Mainline Phase, for each train in order:
The catch-up check is how rear-end collisions happen. The train computes the region it's about to enter; if a same-direction train is already there and the card doesn't allow passing, they collide — both trains destroyed, charged to the Superintendent, since granting clearance is what let it in behind. ABS Signals converts that into holding short instead.
One asymmetry: this only runs while stagesRemaining > 1, so there's no catch-up test on the final Stage — the train is leaving the card that Stage regardless.
Trains stop at every Office they reach; there's no through-running. The terminalsOnly rule affects passenger work, not stopping.
Mainline modifier cards (mainline.modify, played from hand onto a Division node):
┌─────────────┬─────────────────────────────┬─────────────────────────────────────────────────────────────────────┐
│ Card │ Where │ Effect │
├─────────────┼─────────────────────────────┼─────────────────────────────────────────────────────────────────────┤
│ Brakeman │ Heavy Grade only │ −1 Stage downhill │
├─────────────┼─────────────────────────────┼─────────────────────────────────────────────────────────────────────┤
│ Airbrakes │ Heavy Grade only, needs │ −1 Stage downhill │
│ │ Brakeman already there │ │
├─────────────┼─────────────────────────────┼─────────────────────────────────────────────────────────────────────┤
│ Helpers │ Heavy Grade only │ −1 Stage uphill │
├─────────────┼─────────────────────────────┼─────────────────────────────────────────────────────────────────────┤
│ Realignment │ any card, not while a train │ changes the card: Curves→Plains, Plains→Double Track, Uncontrolled │
│ │ is on it │ Siding→Double Track, Trestle→Uncontrolled Siding │
└─────────────┴─────────────────────────────┴─────────────────────────────────────────────────────────────────────┘
Never below one Stage. So a fully-equipped grade is 1 Stage downhill for a fast train and 1 uphill with Helpers — but Brakeman and Airbrakes are dead weight to anything climbing.
Other things that change a crossing: ABS Signals (an Enhancement on a Mainline card — stop short, don't rear-end); Red Flags (a maneuver card protecting one specific stopped train, where ABS protects everything on the card); Telegraph/Telephone/Radio (once a Day, force a facing meet); and Office upgrades, which don't touch crossing time but split Subdivisions and so change what can be on the line at once.
One thing I should flag. docs/rules/implications.md Q3 says Expedite means "the train departs the same Stage it arrives." The engine does not implement that — isExpedited is purely a fault rule: an expedited train not standing on the Office square when a Mainline Phase begins costs its owner Revenue, every Phase it's away. The code comment says so explicitly: "Expedite does not change WHEN a train leaves." That was the v0.4.9 "expedite rewrite"; the Q3 row didn't move with it, and the pacing table below it still leans on the old reading. Want me to correct that row, or add it to the TODO?Day, add +4 / +8 / +12 to the other train's number and let the meet happen.
2. A same-direction train → the Superintendent rules. Unless the other train is Red Flagged, or its card has ABS Signals — either of those blocks outright and there's no judgment to make.
Cards printing "trains may pass" (Double Track, Uncontrolled Siding) skip occupancy entirely.
Nowhere — and this is the part most likely to surprise you. There is no position. enterMainline pushes a Transit { tray, stagesRemaining, stagesTotal, direction } and that's it. Crossing is a countdown, not a walk across cells. state.ts says it plainly: "the cells printed on the cards are decoration."
Position is derived, in one place, for two purposes:
regionOf(t) = clamp( (2 − stagesTotal) + (stagesTotal − stagesRemaining), 0, 1 )
REGIONS_PER_MAINLINE_CARD = 2, marked provisional. The consequence of that entry term: a train crossing in one Stage enters already in region 1 — half a card in — while a train taking two or more starts at region 0. A fast train doesn't traverse a fast card, it appears at the far half of it.
stagesTotal is stored rather than recomputed, deliberately: a modifier played onto the card mid-crossing would change the answer and make the train appear to jump backwards.
The derived region is used for exactly two things — drawing the map, and the catch-up test below.
Computed once, on entry, by crossingStages, and then counted down one per Mainline Phase:
mph = uniform value | Hilly's P/F split | 30 for a grade
base = mph >= 60 ? 1 : 2
stages = base + (train is slow ? 1 : 0) − gradeReduction floor of 1
┌─────────────────────┬───────────┬────────┬────────┬─────────────────────────────┐
│ Card │ Speed │ Fast │ Slow │ Notes │
├─────────────────────┼───────────┼────────┼────────┼─────────────────────────────┤
RAR email:
Also, problems on the mainline cards. I know that Plains is 1 stage for ALL trains. So are interlockings, with a second stage for incoming extras to hold at. Haven't checked the rest but will as they show up.
Curve are 2 stages, fast or slow, doesn't matter.
Double is one stage, fast or slow, also doesn't matter.
Heavy Grade - Trying to put ABS signals on grade. Not allowed. Need them there. BTW, grade should tell you which way is up.
Root-caused. The double-track case in the report and the stage counts in your email are the same bug, and it traces back to a recorded answer that now looks wrong.
Crossing time is computed from two rules:
Q2 is recorded in
docs/rules/implications.md§9a as your own answer, and the engine implements it literally. That is why Double Track cost two Stages in the save: the train was Slow, so the 60-card's one Stage became two.Your email says Q2 is wrong, and the three counts you give are all consistent with dropping it entirely:
Every mismatch is exactly the Slow penalty. Drop Q2 and all three of your numbers come out right, with no other change. So the question is narrow: does Fast/Slow affect crossing time at all, or does the printed card number decide it on its own? If it is the latter, the fix is one line, and Hilly (P60/F30) becomes the only card that distinguishes trains — reading the consist, not the speed label.
Please confirm before I change it, because Q2 is load-bearing elsewhere. It was the basis for a measured consequence: on a 3-player Division a Fast train crosses end-to-end in 9 Stages and a Slow one in 13 — so under Q2 every Slow train is still on the road when the next Day begins, holding its Crew Tray. Removing Q2 takes that pressure off, which is probably desirable, but it changes what
players + 3trays is worth and the balance numbers will need re-measuring.Interlockings — a second Stage for an incoming Extra to hold at is a different mechanism from crossing time and is implemented separately; I have not checked it against your reading yet.
Two smaller items from your email, both confirmed:
ABS Signals on Heavy Grade. The engine does not forbid this — the placement check accepts any Mainline card, Heavy Grade included, and the card's own text says "any Mainline card". So what stopped you is a UI problem, not a rule. A save or a screenshot of the moment you tried would pin it down; my guess is the card was not offered as a selectable target rather than the play being refused.
"Grade should tell you which way is up." Confirmed gap, and a deliberate one so far. The card prints "Player sets orientation" and the game does not implement it — the uphill direction is fixed rather than chosen, because a Mainline card sits between districts and no player has a fair claim to the choice, and the choice is not cosmetic: it decides permanently which of Brakeman / Airbrakes / Helpers can ever pay, and therefore which direction of traffic is favoured. Giving it to the Superintendent was considered and rejected (the office rotates every three Stages; the advantage would not). But whatever the answer, the board should say which way is up — right now it does not display it at all, which is the part that is simply missing. Reasoning is in
implications.md§10 Q11 if you want to overrule the first half.RAR - I notice that you are basing stages in mainline cards off coach/non-coach. Actually, I'm including the train sheets again. You'll see that all trains are rated as FAST and SLOW. These define the starting points on most of these mainline cards.
Emailed to RAR:
<html>Reviewed some of my notes and your latest cards. Crossing time for a mainline card is currently implemented based on two rules (with original speeds). latest cards have speeds of 50, 30, P50, F25, G, 60, 25. Latest trains designated as Fast / Slow and #Freight / #coach / #caboose.
That is why Double Track cost two Stages in the save game you sent me: the train was Slow, so the 60-card's one Stage became two.
Starting location / stages to cross a mainline card should not be based on coach vs. freight, but fast / slow. So how does Fast/Slow affect crossing time? Are trains correctly assigned to Fast / Slow?
We should discuss. Currently on a 3-player Division a Fast train crosses (w/out office area switching delays) end-to-end in 9 Stages and a Slow one in 13. so currently every Slow train will take more than 24 hours to complete - holding its Crew Tray. Currently we implement
players + 3trays . That assumption should be re-examined as well...Jesse
</html>Email from RAR:
Yeah, I was wondering about the times.
So, please ignore the speed signs I put on the cards - those are nothing but scene-setting graphics that mimic the speed you are traveling (if it's 60 mile across the Mainline card). It's just ambiance, nothing more.
All movement is based on FAST/SLOW ratings on the train cards. Most of the freights are slow, but there are fast ones. But yes, you need to check the trains speed and that determines the starting stage.
Been worried about the time it takes to cross the division. More thunking on this is needed.
Ignore speed signs. they are just graphics.
Regions shown on cards indicate how many stages it takes to cross. Plains is 1. double track is 1, tunnel is 2, Curves is 2, heavy grade is 3 unless you have help. In which case it may be less.
Some cards say fast / slow. This is an indication that if on the train card, the train is listed as fast or slow, that's starting position / how many stages it takes to traverse the card. Fast / Slow does not apply to every card - just those that say fast / slow on them. currently this is only hilly.
Other cards list other things
Mainline card- ABS. This is played on a mainline card to prevent collisions. if a collision would normally occur, the train moving onto the card is instead held back. ABS should be able to be played on ANY mainline card.
Fixed in v0.7.2 (
2ab25e3) and v0.4.9h (e9683cc).This replaces two recorded rulings rather than correcting a number — Q1, that the printed 60/30
are crossing time, and Q2, that a Slow train adds a Stage to every card. Q2 is what produced the
report: the train was Slow, so Double Track's one Stage became two. Both are struck through in
implications.mdand replaced by Q1a, which quotes your ruling.A card now costs one Stage per printed region, and where a train STARTS is what varies. Plains 1,
Double Track 1, Trestle 1, Curves 2, Tunnel 2, Heavy Grade 3. Fast/Slow is read on Hilly and nowhere
else, and Hilly no longer reads the consist — which had a fast freight crossing slower than a slow
passenger train. Helpers start an uphill train a region on, Brakeman a downhill one, Airbrakes
another again. The Uncontrolled Siding and Interchange print a back region that is not road: a train
through starts past it, one arriving to find the siding occupied takes it and runs a region behind,
and an Extra beginning its run at an Interchange starts there.
Three things turned out to be missing rather than wrong. With Plains at one region, a following
train is in the same place as the train ahead the moment it enters — and nothing tested that, because
the catch-up check sits inside
stagesRemaining > 1, which a one-Stage crossing never reaches. Thatis exactly the case ABS describes and it had to be built. ABS was also holding silently on the
Office and Division Point paths, so the one card whose purpose is preventing a wreck did its job
invisibly. And
collidenever released the A/D track — which never mattered while every collisionhappened out on the road, but a train destroyed as it LEAVES is still standing at the Office. The
Uncontrolled Siding was marked "trains may pass", which skipped the collision test altogether and
made the siding do nothing at all.
Measured, on the thing you said you were worried about. On the Mainline cards of a 3-player
Division, a fast train pays ~5.6 Stages against ~5.4 before, and a slow one ~6.0 against ~9.4. Fast
traffic is unchanged; slow traffic is about a third quicker, and the Fast/Slow gap across a whole
Division collapses from roughly four Stages to under one. Q2's recorded consequence — every Slow
train still on the road when the next Day begins, holding its Crew Tray — no longer holds, so the
players + 3tray count is due a re-examination. That is inTODO.md, not done here.Two side effects recorded rather than acted on: freight share fell 8% to 5% and completed freight
loads got scarcer, which runs against the obvious expectation and is not yet explained; and the bot
stopped playing Red Flags (offered 4,212 times in 600 games, played 4).