v0.8.0.7 — the Salvage Yard had nothing to say, and phases too little time to read

The Salvage Yard was face up all along; its tile just read "a card". apply.ts
pushes a synthetic train-<n> id on trainScheduled, nothing in s.cards matches it,
and cardName fell through to its default — and since a train is scheduled several
times a Day that id is on top most of the time. Measured before touching anything:
the tile read "a card" from the opening frame through 60 pushes while its depth
climbed from 2 to 8. cardName resolves it now, in sim/view.ts, because this is a
name.

The engine half is filed as Gitea#23 rather than fixed here. reshuffleIfDepleted
sweeps the Salvage Yard back into the draw deck, so that synthetic id can be
shuffled in and drawn into a hand as an id with no card behind it. Eight games
driven to 4000 moves across eight seeds produced zero reshuffles, so it is latent;
there are two defensible fixes and the choice turns on what the synthetic id is
for, which is not a call to make while fixing a label.

And phases scale with the speed control again, damped to a third of the rate. They
were pinned in v0.8.0.3 because scaling them walled off a player's own turn; pinned
turns out to be too short to read at 10x. Damped satisfies both: 1x unchanged, 10x
lands exactly on the four-times guess. Bounded because phase beats cluster rather
than accumulate — 1.0 per push on average, 4 at worst, so the wait after a move is
~2.4s typical.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X6cF1iYvJ1kNmzYBzu4QX6
This commit is contained in:
Jesse.Markowitz
2026-09-10 06:58:09 -04:00
co-authored by Claude Opus 5
parent 64e8ce584f
commit d0e5091824
6 changed files with 142 additions and 12 deletions
+17
View File
@@ -1791,6 +1791,23 @@ export function snapshot(
/** A card id turned into something a person can read. */
export function cardName(s: GameState, id: string): string {
/**
* A SCHEDULED TRAIN IS IN THE SALVAGE YARD UNDER A SYNTHETIC ID, and without this the pile that is
* supposed to be face up reads "a card".
*
* `trainScheduled` pushes `train-<number>` rather than the id of the card that was played
* (`apply.ts`), so there is nothing in `s.cards` to look up — and since a train is scheduled
* several times a Day, that synthetic id is on top of the Salvage Yard most of the time. Reported
* by Jesse 2026-09-10 as "why is salvage deck not face up. I should see the card played onto
* salvage": it was face up all along and simply had nothing to say.
*
* Resolved here rather than in the engine because this is a NAME, which is this file's job. Whether
* the engine should be pushing a real card id instead is a separate question with a separate
* consequence — the Salvage Yard is swept back into the draw deck when it runs out — and is filed
* rather than answered in passing.
*/
const scheduled = /^train-(\d+)$/.exec(id);
if (scheduled) return `Train ${scheduled[1]}`;
const k = s.cards.get(id)?.kind;
if (!k) return 'a card';
switch (k.kind) {