v0.7.2 — a leg that is part of the row, the deck the sheet prints, regions not miles per hour, and a Division you read left to right
Gitea#17 — a 45° leg is an end of the west-to-east row, so backing into a cut through a curve's south leg no longer couples it back to front. The same assumption left a crew's own cut standing when it pulled out through a leg, which is the "cars left behind" report we had failed to reproduce. Gitea#14 — every count is docs/Deck cards5.xlsx. Track halved, and the Q12 office doubling and Gap 12 industry tripling both come out with it: they were measured against a deck with twice the track, and keeping them at the sheet's track count wipes out the reefer chain entirely. 84 rows now match card for card; the ten Safety, Event and Inspection cards it adds are not built and are held out. Cards the sheet no longer lists are dealt zero copies rather than deleted, so their rules stay implemented. Gitea#15 — RAR reversed it: a rail may stop dead against its neighbour and the placement is legal. What must hold is that no train crosses the gap, which was already true and is now pinned against the reported board. Gitea#3 — the printed speeds are scenery. A card costs one Stage per printed region and where a train STARTS is what varies; Fast/Slow is read on Hilly alone. Entering a one-region card behind another is a collision now, which is what ABS exists to prevent, and ABS no longer holds trains silently. Gitea#18 — the Division draws as one row, west to east, with no office-area detail. East is finally always to the right. Closes #3 Closes #14 Closes #15 Closes #17 Closes #18
This commit is contained in:
@@ -50,8 +50,10 @@ Queued 2026-08-22, from a v0.4.9d gameplay-testing report (six bugs, forwarded b
|
||||
it just boarded**~~ — done in v0.4.9e / the release below.
|
||||
11. ~~**The Grocer's Warehouse ships and the Refinery receives**~~ — done in v0.4.9e / the release
|
||||
below: both are one-way again.
|
||||
12. **NOT REPRODUCED: cars left behind when backing up over them** — see Rules Questions below. The
|
||||
one report of the six that is still open, and it needs a board from whoever filed it.
|
||||
12. **PARTLY REPRODUCED: cars left behind when backing up over them** — see Rules Questions below.
|
||||
Half of it turned out to be the second half of Gitea#17 and is fixed (2026-08-26): a train
|
||||
pulling out through a 45° leg left its own cut standing. The "I can later drive right through
|
||||
them" half is still unexplained and still needs a board from whoever filed it.
|
||||
|
||||
Queued 2026-08-22, from the v0.4.9e gameplay-testing report filed as Gitea issues.
|
||||
|
||||
@@ -127,30 +129,31 @@ Queued 2026-08-22, from a session looking at the screen rather than the rules. A
|
||||
means something different and useful: hide it now, bring it back at the end of the phase.
|
||||
18. **Give every phase a visible beat.** The automatic phases are not too fast — they are never
|
||||
drawn at all, because `pump` runs them all before the page renders once.
|
||||
19. **Turn the track art vertical on a Division card laid vertically** — a side lane currently reads
|
||||
as stacked left-right segments rather than one continuous run.
|
||||
20. **Run the inter-row connector round the OUTSIDE**, draw it as rail rather than a plain line, and
|
||||
give the corners an angled piece.
|
||||
21. **The Division Point captions overflow the map**, and the buffer stops point the wrong way once
|
||||
the route wraps.
|
||||
22. **Fill the dead centre of the Division map with the common board** — timetable, yards, the
|
||||
Department and Salvage decks. Then the map is what everyone shares and the right column is yours.
|
||||
19. ~~**Turn the track art vertical on a Division card laid vertically**~~ — **SUPERSEDED by
|
||||
Gitea#18** (Jesse, 2026-08-26). There are no vertical lanes any more: the Division draws as a
|
||||
single row, west to east.
|
||||
20. ~~**Run the inter-row connector round the OUTSIDE**~~ — **SUPERSEDED by Gitea#18.** No second
|
||||
row, so nothing to connect.
|
||||
21. ~~**The Division Point captions overflow the map**, and the buffer stops point the wrong way once
|
||||
the route wraps~~ — **SUPERSEDED by Gitea#18.** Nothing wraps; both ends face outward.
|
||||
22. ~~**Fill the dead centre of the Division map with the common board**~~ — **SUPERSEDED by
|
||||
Gitea#18.** A row has no centre to fill.
|
||||
23. **History: newest at the top?** Plus the timestamps question from item 14, which lands here.
|
||||
24. **Put the viewer's own district at the BOTTOM of the Division map** and wrap the table around
|
||||
them, so the screen sits you at the table. Needs no new data; the cost is that "west to east"
|
||||
stops starting where you start reading.
|
||||
24. ~~**Put the viewer's own district at the BOTTOM of the Division map** and wrap the table around
|
||||
them~~ — **DEFINITIVELY SUPERSEDED by Gitea#18** (Jesse's word, 2026-08-26). A single row and a
|
||||
table wrapped around the viewer cannot both hold, and the row wins: being able to rely on east
|
||||
meaning right is worth more than being seated at the table.
|
||||
|
||||
Queued 2026-08-23, from Jesse playing the v0.7.0 build on StartOS. **All three are the same drawing
|
||||
pass as 19-21 and 24 above, and he asked for them to be discussed together rather than picked off:**
|
||||
Queued 2026-08-23, from Jesse playing the v0.7.0 build on StartOS. **All three were the same drawing
|
||||
pass as 19-21 and 24 above, and all three are answered by Gitea#18 rather than fixed:**
|
||||
|
||||
25. **The Division map does not draw track geometry at all** — a turnout laid on the Running Track
|
||||
looks exactly like the straight it replaced, because the only thing that changes is a caption.
|
||||
Reasoning and the measurement in Display below.
|
||||
26. **CONFIRMED IN PLAY: the buffer stop points the wrong way** at two players — see item 21, now
|
||||
reported from a real game rather than read off the code.
|
||||
27. **CONFIRMED IN PLAY: east is not always to the right.** As a train crosses the Division the route
|
||||
wraps through the lanes, so a player's east can be drawn south, west or north. See item 20; it is
|
||||
the same wrap that puts the buffer stop in the wrong place.
|
||||
25. ~~**The Division map does not draw track geometry at all**~~ — **SUPERSEDED by Gitea#18.** The
|
||||
Division map stops drawing office-area detail altogether, so there is no Running Track on it to
|
||||
draw geometry for. The geometry belongs to the Office map, which already draws it.
|
||||
26. ~~**CONFIRMED IN PLAY: the buffer stop points the wrong way** at two players~~ — **SUPERSEDED by
|
||||
Gitea#18**, with item 21.
|
||||
27. ~~**CONFIRMED IN PLAY: east is not always to the right.**~~ — **FIXED OUTRIGHT by Gitea#18**, and
|
||||
the reason it wins over item 24. One row means east is always to the right.
|
||||
|
||||
28. **INVESTIGATE: move the game's settings off the top line and into a card of their own** — and
|
||||
show ALL of them, not the four that fit. Reasoning in Display below.
|
||||
@@ -315,6 +318,18 @@ The replay viewer, the save format, and how a game gets shared.
|
||||
|
||||
## Bot Performance
|
||||
|
||||
- [ ] **THE BOT WILL NOT PLAY RED FLAGS, and the reachability canary now says so.** Measured over
|
||||
600 games (2026-08-26): `maneuver.redFlags` is OFFERED **4,212 times**, first in game 5 — the
|
||||
rule is live and constantly available — and the bot PLAYS it **4 times**, first in game 252.
|
||||
It is exempted by name in `sim.test.ts`'s anomaly test alongside `flyingSwitch`, and deleting
|
||||
that line is what proves this fixed.
|
||||
|
||||
Two changes compounded to make it rarer without breaking anything: Gitea#14 took Red Flags from
|
||||
5 copies to the sheet's 3, and Gitea#3 shortened most crossings to a single Stage, so the
|
||||
window in which a train is STANDING on a Mainline card — the only place the card may be played
|
||||
— is now usually one Stage wide.
|
||||
|
||||
|
||||
What the developer bot can and cannot yet do, measured. Every revenue figure below measured before
|
||||
v0.4.7 is low by roughly half a point — see the stub-industry entry — and the rebalance pass should
|
||||
not read that drop as a deck problem.
|
||||
@@ -428,6 +443,30 @@ not read that drop as a deck problem.
|
||||
|
||||
## Play Balance
|
||||
|
||||
- [ ] **FREIGHT GOT SCARCER WHEN THE MAINLINE WENT ONTO REGIONS, and nobody knows why yet.**
|
||||
Gitea#3, measured 2026-08-26 across the same 100 games: freight share of gross fell **8% → 5%**,
|
||||
and completed freight loads went from something a 40-game sample caught reliably to needing
|
||||
200 — on `sim.test.ts`'s seeds, 40 games now yield 0 loads, 80 yield 3, 120 yield 10, 200
|
||||
yield 21.
|
||||
|
||||
**It runs against the obvious expectation.** The change SPEEDS crossings up, so more trains
|
||||
should reach more districts, not fewer. Revenue is flat (−0.2 against 0.0) and collisions are
|
||||
unchanged at 0.1 a game, so nothing is obviously eating the traffic. Candidates worth checking:
|
||||
trains now clear a district before a crew can work them; the entry-time collision rule
|
||||
(below) destroying trains at the Office; or simply that faster turnover means fewer trains
|
||||
standing where freight can be loaded.
|
||||
|
||||
- [ ] **THE CREW TRAY COUNT IS DUE A RE-EXAMINATION, and this is the change that triggers it.**
|
||||
`players + 3` was set when a Slow train took roughly twice as long to cross as a Fast one, and
|
||||
Q2's recorded consequence was that "every Slow train is still on the road when the next Day
|
||||
begins, holding its Crew Tray". Gitea#3 removed the Slow penalty from every card but Hilly.
|
||||
Measured on the Mainline cards alone, a 3-player Division now costs a fast train ~5.6 Stages
|
||||
and a slow one ~6.0, against ~5.4 and ~9.4 before: **fast traffic is unchanged, slow traffic is
|
||||
about a third quicker**, and the gap across a whole Division collapses from roughly four Stages
|
||||
to less than one. RAR's own closing note on the issue: "been worried about the time it takes to
|
||||
cross the division. More thunking on this is needed."
|
||||
|
||||
|
||||
Numbers chosen to fix a measured problem rather than taken from the design. Revisit once the victory
|
||||
target is settled and freight carries its intended share; read no balance conclusion from a revenue
|
||||
number until the rules stop moving.
|
||||
@@ -1178,6 +1217,14 @@ Deferred while planning the server; decisions and reasoning are in `docs/archite
|
||||
|
||||
## Display
|
||||
|
||||
- [ ] **THE BOARD STILL DOES NOT SAY WHICH WAY A HEAVY GRADE CLIMBS.** RAR, twice: "grade should
|
||||
tell you which way is up." `gradeUp` is dealt at setup and drives which of Helpers or
|
||||
Brakeman/Airbrakes can ever pay, and Gitea#3 made it matter more — the modifiers now move a
|
||||
train's STARTING REGION, so playing the wrong one is three Stages of climb instead of two. The
|
||||
tooltip says it (`mainlineDescription`); the map does not. Untouched by Gitea#3, which was
|
||||
about the rules rather than the drawing.
|
||||
|
||||
|
||||
What is on the screen and where. Split out of Other 2026-08-22; the rules are elsewhere.
|
||||
|
||||
- [ ] **The log's start marker only works while the whole log fits.** Added 2026-08-23: a multiplayer
|
||||
@@ -1529,17 +1576,31 @@ What is on the screen and where. Split out of Other 2026-08-22; the rules are el
|
||||
|
||||
## Rules Questions
|
||||
|
||||
- [ ] **NOT REPRODUCED: "when I back up to collect standing cars and, further down the tracks, the
|
||||
- [ ] **PARTLY REPRODUCED: "when I back up to collect standing cars and, further down the tracks, the
|
||||
caboose, I get the caboose but the cars remain. I can later drive right through them."**
|
||||
Reported against v0.4.9d by a playtester (not Jesse, who forwarded it and could not add detail;
|
||||
his guess was that the cars were spotted at an industry).
|
||||
|
||||
**HALF OF IT IS NOW REPRODUCED AND FIXED (2026-08-26), as the second half of Gitea#17.** The
|
||||
one case the earlier sweep did not try is a train pulling out through a 45° LEG rather than an
|
||||
east or west port. `cutTowards` answered "you meet nothing" for a north or south exit, so a
|
||||
crew standing on a curve drove away and left the cut beside it standing — the reported symptom
|
||||
exactly, and against §A.4's mandatory coupling. `rowEndAt` (`track.ts`) fixes it, and
|
||||
`cut-ordering.test.ts` pins it.
|
||||
|
||||
**WHAT IS STILL UNEXPLAINED is the second sentence — "I can later drive right through them."**
|
||||
Nothing found so far accounts for that. A card is swept by `carsOn` whenever a train enters it,
|
||||
whichever port it enters by, so a later pass over those cars picks them up. Until that half has
|
||||
a board behind it this stays open: the fix above may be the whole report, or only the part that
|
||||
happened to be reachable from the code.
|
||||
|
||||
**What was tried, all of which works.** Cars on plain track on the way to the caboose; cars
|
||||
SPOTTED AT AN INDUSTRY on the way; the train's own cut standing on the square it is pulling out
|
||||
of; a stale `standingWest` on the intermediate card; the industry locked by MEN AT WORK (which
|
||||
correctly blocks the whole route rather than letting the crew past). Every one couples the lot.
|
||||
The first three are pinned in `apply.test.ts` — "backing up over a cut to something beyond it
|
||||
takes both" — so if the case is found later it is somewhere none of them cover.
|
||||
of *through an east or west port*; a stale `standingWest` on the intermediate card; the industry
|
||||
locked by MEN AT WORK (which correctly blocks the whole route rather than letting the crew
|
||||
past). Every one couples the lot. The first three are pinned in `apply.test.ts` — "backing up
|
||||
over a cut to something beyond it takes both" — so if the remaining case is found later it is
|
||||
somewhere none of them cover.
|
||||
|
||||
**Why it is hard to make happen.** Coupling is mandatory (§A.4) and `exploreMoves` accumulates
|
||||
what it meets card by card, so a route that reaches the caboose has already met everything
|
||||
@@ -1570,6 +1631,50 @@ What is on the screen and where. Split out of Other 2026-08-22; the rules are el
|
||||
|
||||
Doesn't fit the above.
|
||||
|
||||
- [ ] **THE DECK IS `docs/Deck cards5.xlsx` EXACTLY, BAR TEN CARDS THAT ARE NOT BUILT.** Gitea#14,
|
||||
2026-08-26. Card for card, **84 rows agree with the sheet** and the only ones that do not are
|
||||
the ten it adds that we have never implemented — Cargo Theft, Civic Improvement, Civilian
|
||||
angel, Delayed Clearance, Flares 2, Robbery, Service Delays, Shipper complaints, Strike,
|
||||
Union Hall 2: **12 copies**, held out on Jesse's instruction until they are built. Gitea#12
|
||||
partly specifies the Inspections among them.
|
||||
|
||||
What landed: track halved; the Q12 office doubling and the Gap 12 industry tripling both
|
||||
removed; Interlocking 2→1, Water column 2→1, ABS Signals 2→1, Red Flags 5→3. **Everything
|
||||
sheet 5 does not list is dealt 0 copies rather than deleted** — the Telegraph/Telephone/Radio
|
||||
dispatching ladder, Facing Point Locks (Enhancement and Mainline both), Flying Switch, Section
|
||||
House, Vandalism, all confirmed by Jesse as deliberate removals from the design, plus Poling
|
||||
and the sharp curves which were already there. The rows and their rules stay, so the design
|
||||
stays visible and each mechanic works the moment it is dealt again. Deck 206 → **121** dealt.
|
||||
|
||||
Measured, 100 games, developer bot: revenue per player **−0.2 → +0.4**, trains scheduled
|
||||
1.3 → 1.6, cards played 16.8 → 13.0. Freight share fell 9% → 4%, and part of that is Flying
|
||||
Switch going to zero — it was a freight mechanic. Worth a look if freight is meant to carry
|
||||
more.
|
||||
|
||||
**NOT A DISCREPANCY, though it looks like one in a card-by-card diff:** Second Section is on
|
||||
neither sheet and is not a drawn card here either. It is a New Train phase intent
|
||||
(`newTrain.secondSection`), and the `copies: 1` on the `SECOND_SECTION` constant is vestigial —
|
||||
nothing deals it. Worth removing that field so the next diff does not flag it again.
|
||||
|
||||
**The deck reads 40% track against the sheet's 31%**, and the whole of that gap is the ten
|
||||
held-out cards concentrating everything else. Building them moves the ratio to the sheet's on
|
||||
its own, which is why the share is held to a loose band in `setup.test.ts` rather than pinned.
|
||||
|
||||
- [ ] **FIVE TEST FIXTURES PINNED A SEED AND MEANT "A GAME LIKE THIS".** All five broke on Gitea#14
|
||||
and none of them was about card counts — the deck's SIZE moves the RNG stream, so changing it
|
||||
re-deals every fixture that names a seed. Fixed in place: `mainline-cards` now searches for a
|
||||
Division holding a single-track card, `multiplayer` for a game that reaches Day 3, `web` clicks
|
||||
every play verb rather than assuming the first one goes on the board, and the two `sim`
|
||||
commodity samples were re-measured (tank is first set out at game **216** now, unload Revenue
|
||||
at game **46**). The `web` fix is on BOTH lines — it broke on `main` at the next count change,
|
||||
exactly as predicted. `multiplayer`'s seed search is still playtest-only; port it when
|
||||
convenient.
|
||||
|
||||
A sixth turned up when the dropped cards went to zero: `mainline-cards`' `hand()` helper threw
|
||||
if the card it wanted was not in the deck, so zeroing Flying Switch took five passing tests of
|
||||
an UNCHANGED rule down with it. It mints a card that is no longer dealt now — which is the
|
||||
point of keeping a row at zero, and the same will hold for the ladder if anyone tests it.
|
||||
|
||||
- [ ] **THE 0.4.9 PLAYTEST LINE IS BEHIND ON A RULES RULING, and that was checked rather than
|
||||
assumed.** Recorded 2026-08-23, when Jesse asked whether any of v0.7.0 needed porting to the
|
||||
`playtest` branch. Almost none of it does — that line has no lobby and no server, and the
|
||||
@@ -1577,12 +1682,29 @@ Doesn't fit the above.
|
||||
`configWith` only ever varies the house rules the save already restores.
|
||||
|
||||
**But one v0.5.0 ruling is a CODE difference the testers do not have.** §A.4, the Local's
|
||||
coach: `main`'s `apply.ts` reads `if (dropRules.coachStaysOnStationTrack && cut.some(coach) &&
|
||||
!atOffice)`, and `playtest`'s is the same line **without `&& !atOffice`** — so on that build a
|
||||
coach still may not be set out at the Office. The other two questions the 0.4.9 README calls
|
||||
open are documentation-only there (Poling is already at 0 copies; Heavy Grade behaves
|
||||
identically and even deals the Mainline deck without replacement, so the correction applies
|
||||
word for word).
|
||||
coach — so on that build a coach still may not be set out at the Office.
|
||||
|
||||
**IT IS THREE SITES, NOT ONE.** This entry named only the first until 2026-08-25, when a full
|
||||
branch diff found the other two. Porting just the `apply.ts` line would leave the build in a
|
||||
WORSE state than either line is in today: the coach could be set out at the Office and the next
|
||||
arriving train would then collide with it.
|
||||
|
||||
1. `src/engine/apply.ts` — `main` reads `if (dropRules.coachStaysOnStationTrack &&
|
||||
cut.some(coach) && !atOffice)`; `playtest`'s is the same line **without `&& !atOffice`**.
|
||||
This is the one that refuses the drop.
|
||||
2. `src/engine/track.ts` — `canDropCarsAt(area, coord, count, coachesOnly)` takes a fourth
|
||||
`coachesOnly` parameter on `main` and returns the Office square as droppable when it is set.
|
||||
`playtest`'s signature has no such parameter and returns `false` for the Office outright.
|
||||
3. `src/engine/advance.ts` — the §8.3 "cars fouling the Running Track" check. `main` reads
|
||||
`officeCard.standing.some((c) => c.type !== 'coach')`, so a coach parked at the Office is
|
||||
not a hazard to the next arrival; `playtest` reads `officeCard.standing.length > 0`, which
|
||||
collides with anything standing there. **This one is behavioural and easy to miss** — it is
|
||||
in a different file from the drop rules and reads as a collision fix rather than a coach one.
|
||||
|
||||
The other two questions the 0.4.9 README calls open are documentation-only there (Poling is
|
||||
already at 0 copies; Heavy Grade behaves identically — both lines run the same
|
||||
`rng.nextInt(2)`, re-verified 2026-08-25 — and it even deals the Mainline deck without
|
||||
replacement, so the correction applies word for word).
|
||||
|
||||
**Jesse's call, 2026-08-23: do not port it now.** A settled rules change is not a playtest bug
|
||||
fix, and pushing one into the build people are mid-playtest on would invalidate the feedback
|
||||
@@ -1690,6 +1812,32 @@ Doesn't fit the above.
|
||||
|
||||
## Done, kept for the reasoning
|
||||
|
||||
- **Gitea#15 — a rail may stop dead against its neighbour, and the rule is on MOVEMENT.**
|
||||
Filed 2026-08-25 as "track placements must connect": a right-hand curve had been laid with its
|
||||
north leg against an Ice House and the turnout below pointing at its portless south edge, and the
|
||||
report called that illegal. **RAR reversed it on review (2026-08-26)** — the placement is fine, and
|
||||
a stub like that has a use, as a siding to park cars on. What he asked to confirm instead is that
|
||||
no train can traverse the gap.
|
||||
|
||||
It could not, and cannot: `exploreMoves` gates every hop on `joins`, which tests both ports AND
|
||||
that two 45° legs lie on the same diagonal — never a bare pair of `hasPort` calls. That was already
|
||||
true; `track.test.ts` now pins it against the reported geometry, including the check that the curve
|
||||
IS reachable from the side that joins, so the negative test cannot pass on a card that is merely
|
||||
unreachable.
|
||||
|
||||
**A per-edge placement check was written and then taken out**, along with the matching guard on
|
||||
`checkTurnoutUpgrade`. Both are documented in place as deliberately absent, because this is exactly
|
||||
the rule someone will "fix" again. `canPlaceAt` keeps only the weaker requirement it always had:
|
||||
the piece must touch the network somewhere, which is what stops orphaned track.
|
||||
|
||||
**A Modifier is scenery** (Jesse, 2026-08-26): a rail pointing at a building is fine, so nothing
|
||||
guards Modifier placement either. Measured before the ruling: 24 of 283 Modifiers across 200 bot
|
||||
games sit where a neighbour's rail points at them, and that is simply legal.
|
||||
|
||||
The attached save is dead — Gitea#14 took the deck from 206 cards to 121, so its card ids no longer
|
||||
exist and the replay stops at the first `card.play`. **Every save filed before that deck change is
|
||||
in the same position**, including Gitea#17's. Reproduce from the geometry, not the file.
|
||||
|
||||
- [x] **Put rolling stock back into circulation.** The Classification Yard was write-only — seven
|
||||
writers, no readers — so 37% of all rolling stock left the game by Day 5. Returning it at the
|
||||
Day boundary is **+2.32 ± 0.52 (t = 8.79)**, the largest single change measured on this bot,
|
||||
|
||||
Reference in New Issue
Block a user