v0.4.9g — a caboose is not a load, a Day that says it ended, and a train you may throw away

The v0.7.1 bugfix set ported to the playtest line: Gitea#8, #10, #9 and #2. Reasoning, and what
differs from main, in CHANGELOG.md.

- Gitea#8: X22 Pee-Dee refused every caboose, including the one it was made up with. A caboose
  carries the crew, not freight, so it is never a load.
- Gitea#10: a dialog when the Day rolls over, carrying the standings, the Days left and your Revenue
  against the target with the pace. Suppressed on the first frame, on Undo stepping back across a
  rollover, and on the Day the game ends.
- Gitea#9, superseding Gitea#6 from v0.4.9f: a Timetabled train may be discarded, an Extra may not.
  This line takes the plain rule — main has it as a New Game setting.
- Gitea#2: the shortage stays, by Jesse's ruling. A blocked platform now gives its reason instead of
  simply having no button.

Three things are written for this line rather than ported: the Timetabled discard has no setting and
no URL parameter, the Day-end dialog reads f.objective (this line's per-player target) where main
reads its combined victory dials, and Frame gained the viewer index the dialog needs to mark your
row. 636 tests pass; no published replay was retired.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FLnYR4XtXQNamYJXGYT8oC
This commit is contained in:
Jesse.Markowitz
2026-08-25 10:47:10 -04:00
co-authored by Claude Opus 5
parent e255076b5c
commit 9735468d25
15 changed files with 867 additions and 107 deletions
+101
View File
@@ -19,6 +19,107 @@ page as `v0.1.0 · <sha> · <date>`, so what is deployed can always be identifie
---
## 0.4.9g — 2026-08-25
Four more off the Gitea tracker, all of them things a player saw at the board: **#8** a per-diem train
that could not couple a caboose, **#10** no way to tell when the Day turned over, **#9** a ruling that
lets a Timetabled train be thrown away — which supersedes **#6**, shipped three days ago in 0.4.9f —
and **#2**, which turned out not to be an engine bug at all, so what is fixed there is that the game
now says why.
The same four ship as **0.7.1** on the main line. The full reasoning for every item is in that line's
CHANGELOG; this entry records what reached the playtest build and what differs.
### Gitea#8 — a caboose is not a load
X22 Pee-Dee, whose card reads "may only pick up MTs", refused every caboose — including the one it was
made up with, so setting it out at the end of a sweep stranded the train. All six cabooses are minted
`loaded: true`, because §2.2's "coloured is loaded, white is empty" doubles as a PIECE COUNT in the
supply table and there is no white caboose to make a train up from. Exactly one read of the flag took
that literally. A caboose carries the crew, not freight, so it is never a load; the restriction itself
is untouched, and a loaded car alongside the caboose still refuses. The card now says so
("A caboose is not a load"), because a player reading "EMPTIES ONLY" cannot know which reading the
game took.
### Gitea#10 — a dialog when the Day rolls over
"Hard to keep track of time." Nothing on screen was wrong — the clock, the turn chart and the
timetable all said which Day it was — but a Day turns over inside the phases that run themselves, so
it passes between one click and the next, and the phase banner that announces it is gone in 2.6
seconds. A modal stops and waits, which is the whole request. It carries the Day that ended, the
standings in Revenue order, the Days left to run, and your Revenue against the target with the pace.
Suppressed on the first frame (arriving in a game already on Day 3 is not Day 2 ending), on Undo
stepping back across a rollover, and on the Day the game ends — the outcome panel is the thing to
read then.
### Gitea#9 — a Timetabled train may be thrown away
**This supersedes Gitea#6 above, which shipped in 0.4.9f three days ago.** Jesse: "Timetabled trains
are at the choice of the player — they can either play or discard. If someone else wants to pick it
up, they are more than able to. The reason: I don't want, if you decide to play a game longer than
five days, to decide that maybe there are too many trains, the stations are jammed, and the railroad
doesn't need any more. You can toss it. Someone else might disagree and pick it up."
An **Extra** is still never discardable: it never joins the timetable, so it can never be what jams
it. The second half of the ruling needed no code — a discard already goes face-up onto a Department
pile, which is exactly where a rival draws from.
**Gitea#6's corner survives, narrowed.** A hand with no discardable card still has exactly one way on
— play one — with nothing in the engine computing "you must play a train". The hand that reaches it
is now four Extras rather than any four trains.
### Gitea#2 — why nothing is moving on the platform
"The Sparrow pulled into the station with two loaded coaches. There are two passengers on the
platform. Four porters. My thought was to unload two and load two. I never get the chance to load the
last two."
**The engine is not deviating from the rules**, and this was checked step by step against the reported
save. §9.2 discards the white coach into the Classification Yard on boarding and draws one from the
Division Yard on de-training; §2.2 returns the Classification Yard only when the Division Yard is
empty. All three are implemented exactly. What bites is the interaction: both halves of every
passenger cycle consume coaches one-way, and a single global refill condition over a pile of ~60 cars
means they do not come back. Over the reported game the coach pool goes 8+/8− on Day 1 to 0+/1− by
Day 5, with eight coaches stranded in Classification.
**Jesse's ruling is that the shortage stays** — "it is possible to run out, that's part of the
strategy" — so the three balance options written up in `TODO.md` are declined, not deferred.
What was unambiguously a bug is that the game said **nothing**. A Porter action that cannot be taken
is simply absent from the menu, and the "why nothing is moving" panel covered freight facilities only,
so a platform had never had anything to say for itself. It now reports passengers with no train, a
train whose card bars Porters, full coaches, full red slots, the same-district rule, and the coach
shortage itself — naming how many coaches sit in Classification and what brings them back. The reason
text comes from the engine's own predicate, so the panel cannot drift from the rule that refused.
Fixing the label found a second defect: a Passenger Facility rides on the `office` card, so every
passenger row would have read `facility 0,0`; it is named by its Office tier now.
### What differs from the main line
- **The Timetabled discard is the plain rule here, not a setting.** On main it is a New Game checkbox
(`discardTimetabled`, on by default) because Jesse's reasoning is about games run LONGER than five
Days. This line has no settings-form scaffolding and no `?toss=` parameter — a Timetabled train can
simply be discarded. Both lines play the same game at main's default. The house rule itself is kept
in the engine, unreachable from the page, so `keepReason` is identical on both lines and old saves
still replay.
- **The Day-end dialog's goal half is written for this line's Frame, not ported.** Main reads a
COMBINED Revenue floor off its victory dials; this line has no such dials and instead has
`objective`, which already resolves a per-player target from the game length and whether you are on
pace. The dialog asks `objective` rather than recomputing it, so it cannot disagree with the status
block. Its tests were rewritten to match.
- **`Frame` gained a `viewer` field.** `snapshot` has always taken a viewer and resolved `revenue`,
`handCount` and `objective` against it; the index itself was missing, so a panel drawing the whole
table had no way to mark which row is yours without assuming the web client's `viewer = 0`.
- The lobby, the game types and the multiplayer handoff overlay that main's versions of `main.ts`,
`play.html` and `web.test.ts` are built around do not exist here, so those four files were
hand-resolved rather than patched.
**636 tests pass.** No replay was retired: Gitea#9 only ADDS a legal action, #8 only widens one, and
neither #10 nor #2 touches the engine, so nothing already recorded means something different now.
---
## 0.4.9f — 2026-08-22
Three more from the v0.4.9e gameplay-testing round, filed as Gitea issues: **#4** extras did not start