v0.7.4 — Red Flags hold a train out of your Limits (Gitea#19)
"If played, asked FLAG EAST or FLAG WEST. That stops all trains from entering your limits from that direction (i.e. Flag East holds westbound trains). You can do this if you see a problem or wish to complete switching." REPLACES the old rule outright, per Jesse's call. Red Flags used to be played on a stopped train out on the Mainline and protected it from a rear-ender: offered 4,212 times and played 4 across 600 games, a mechanic nobody used, and ABS Signals already does that job better. The flag is now planted on one side of your own district and holds the next train arriving from that side. SPENT ON THE TRAIN IT STOPS. One card, one train, so there is no lifting action to build, nothing to forget, and a flag cannot quietly strangle the Division. The held train loses one Mainline Phase and comes in on the next — it buys a Stage to clear the lead, which is what "wish to complete switching" asks for. PLAYABLE OUT OF PHASE, which is the other half of the issue: when an arrival would certainly collide and the district's owner holds the card, the phase breaks in and asks. Offered ONLY to somebody holding one — a prompt with a single button is not a choice, and it would leak that a collision is coming. The danger is read from §8.3's own two triggers rather than restated, so the prompt cannot offer a flag against a collision that will not happen. Built on the decision union Gitea#5 introduced: this adds a `redFlag` case and nothing else structural. THE BOT STILL NEVER PLAYS IT, AND I MEASURED RATHER THAN ASSUMED. It now takes the out-of-phase prompt unconditionally — the engine has already established the danger, so there is nothing left to judge — and over 200 solitaire games `redFlagsSet` fires ZERO times. The prompt needs an arrival that would collide (0.14 per game, about one game in seven) to coincide with holding the card from a three-card hand out of 121. So the anomaly exemption in sim.test.ts stays, but its comment no longer claims the bot is unwilling: it is measuring deck luck. What is left to fix is the half of the card a human would use, planting a flag on purpose to buy switching time, and TODO.md now says that instead of the old finding. A BUG WORTH RECORDING, because the next interruption will meet it too: the flag was originally taken down in a `reduce` case, which never fires for an event advance.ts emits — the phase driver mutates state and then describes it. The flag stayed up and held every train that came. test/events.test.ts's unreduced-event registry is what makes that class of mistake visible, and `redFlagSpent` is on it deliberately now, with the reasoning. 858 tests pass. Closes #19 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EAgJSmeV8zrMh55Mj85ESb
This commit is contained in:
co-authored by
Claude Opus 5
parent
228027637b
commit
19a6a47ab6
@@ -19,6 +19,80 @@ page as `v0.1.0 · <sha> · <date>`, so what is deployed can always be identifie
|
||||
|
||||
---
|
||||
|
||||
## 0.7.4 — 2026-08-29
|
||||
|
||||
Three rules issues off the tracker, in the order Jesse asked for them: #13, #5, #19. All three are
|
||||
rules Jesse has designed or redefined, and two of them turned out to be rules the code claimed to
|
||||
have and did not.
|
||||
|
||||
### Some Extras must run loaded (Gitea#13)
|
||||
|
||||
X17 Campaign, X18 Circus and X19 Military now prefer loaded cars at make-up — "if not loaded, then
|
||||
empty, and if none available, run without". It is a preference ORDER, so the rule is asked of the
|
||||
Division Yard: an empty is refused only while the yard can still supply a loaded car this train
|
||||
would take, per category, and once it cannot the empty is legal and the train may depart short.
|
||||
|
||||
The per-stop point is **once per Office Area** rather than once per game (Jesse: "in a multiplayer
|
||||
game, each player could score if the circus stops in their area"), and only when the train is fully
|
||||
loaded — every non-caboose car, with a coach counting as loaded when occupied. That last detail is
|
||||
what makes the rule work for the Campaign Train, which carries one coach and no freight, so "fully
|
||||
loaded" is exactly "the candidate is aboard". X17 also GAINS the point; it had `stopThenExpedite`
|
||||
and no scoring rule at all.
|
||||
|
||||
**Two bugs found doing it.** `ConsistSpec.emptiesOnly` was declared on X13 Appleseed, rendered to
|
||||
the player as "(empties only)", and enforced nowhere — the same rule as this issue pointing the
|
||||
other way, so it would have been perverse to add one and leave the other. And a set-up out on the
|
||||
Mainline paid its point to PLAYER 0 whoever was playing, because `playerAtSeat` needs a seat and off
|
||||
the grid the fallback was `0`; scoping the rule to Office Areas removes that rather than patching it.
|
||||
|
||||
### The Yard Office is offered, reachable, and can be run into (Gitea#5)
|
||||
|
||||
It was implemented, in a form missing all three of the rule's conditions: a qualifying train was
|
||||
TELEPORTED onto the card. Nobody was asked, no route was computed — so the card's own printed "that
|
||||
can reach the yard office in one move" was unenforced — and because nothing was walked, nothing was
|
||||
ever met on the way in.
|
||||
|
||||
Now it is offered to the district's owner; reachability is the engine's own move walk, which already
|
||||
means what the card means; and cars on the lead collide. The walk COUPLES standing cars rather than
|
||||
treating them as obstacles, because that is what a switching move does — so what an arriving train
|
||||
would have coupled is what it is about to hit, and `destination.couples` turned out to be the
|
||||
fouling signal with no new machinery. Per Jesse's ruling the two failures are kept apart: no route
|
||||
means no offer and the history says why; a route that exists but is fouled is offered, and taking it
|
||||
crashes.
|
||||
|
||||
**This needed a refactor that #19 then reused.** `pendingDecision` was one question asked of one
|
||||
player, and `currentActor` hardcoded that. It is a discriminated union now, with `decisionActor` as
|
||||
the single place mapping a question to whoever answers it; six copies of `pendingDecision !== null ?
|
||||
superintendent : currentActor` across engine, sim, web and tests collapse into `actingPlayer`.
|
||||
|
||||
### Red Flags, redesigned (Gitea#19)
|
||||
|
||||
The old card protected a stopped train out on the Mainline: offered 4,212 times and played 4 across
|
||||
600 games. It is replaced outright by a flag planted on one side of your own Limits, holding the
|
||||
next train from that direction — "Flag East holds westbound trains" — spent on the train it stops.
|
||||
One card, one train, so there is no lifting action to build and a flag cannot strangle the Division.
|
||||
|
||||
It can also be played **out of phase**: when an arrival would certainly collide and the district's
|
||||
owner holds the card, the phase breaks in with the question. Offered only to somebody holding one,
|
||||
because a prompt with a single button is not a choice and would leak that a collision is coming.
|
||||
|
||||
**The bot still never plays it, and the reason changed — measured, not assumed.** It now takes the
|
||||
out-of-phase prompt unconditionally, since the engine has already established the danger. Over 200
|
||||
solitaire games it plays ZERO, because the prompt needs an arrival that would collide (about one
|
||||
game in seven) to coincide with holding the card from a three-card hand out of 121. The anomaly
|
||||
exemption in `sim.test.ts` stays, but its comment no longer claims the bot is unwilling; what is
|
||||
left to fix is the half of the card a human uses — planting a flag on purpose to buy switching time.
|
||||
|
||||
**A bug the redesign walked into**, recorded because the next interruption will meet it too: the
|
||||
flag was originally taken down in a `reduce` case, which never fires for an event `advance.ts`
|
||||
emits — the phase driver mutates and then describes. The flag stayed up and held every train that
|
||||
came. `test/events.test.ts`'s unreduced-event registry is what makes that class of mistake visible,
|
||||
and `redFlagSpent` is now on it deliberately.
|
||||
|
||||
858 tests pass.
|
||||
|
||||
---
|
||||
|
||||
## 0.7.3 — 2026-08-29
|
||||
|
||||
Two issues off the tracker, and they are halves of one thing: the end of a game. Gitea#11 stops the
|
||||
|
||||
Reference in New Issue
Block a user