Credibility pass: comments say what the code can't, and the seams are gone

Engine: pit-rim exits live in one helper (pitRimExits) shared by the
resolver and the automaton; chargeReach names the six-stride cap; dust
sight is inDust + dustAtEnd; PushPending is exported once; the force-field
counter builds its events in one list; drawUnderSlowDeath says what it
draws under. Test groups are named for the rule they pin, not the
revision that introduced it.

Client: one smoothstep; one edgeScar per battle-scarred edge; one
board-zone rule (which also seats the caption strip on phones); the
compass names live in SIDE_NAMES; net.flash() is the one toast; MediaQuery
replaces two hand-rolled matchMedia listeners; sprites carry their sizes
as plain numbers and their CSS in one rule each; canvas helpers are
formatted like the rest of the tree. Comments that told how a cel or a
fallback used to look now say what it draws. The actions-over notice no
longer blames a pickup when slime ended the turn.

Server and ops: dataRoot() is the one data directory; headlineOf builds
its deeds without a cast; the rollup and skills read the same way the
code behaves.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
This commit is contained in:
Eric Wagoner
2026-09-16 00:21:34 -04:00
co-authored by Claude Fable 5.1
parent 85690f0e23
commit 6e49fc9020
40 changed files with 331 additions and 293 deletions
+5 -4
View File
@@ -396,7 +396,7 @@ describe("big man", () => {
/** From a giant's square: a step into a square whose exits (all sides but
* the way back) number exactly `want` — a corner (1, not straight) or a
* fork (2+). Returns the giant's start, the pushee's square, and the exits. */
function pushSite(state: GameState, want: "corner" | "fork") {
function pushSite(state: GameState, want: "corner" | "fork" | "straight-fork") {
const view = boardView(state);
for (const key of Object.keys(view.cells)) {
const [x, y] = key.split(",").map(Number) as [number, number];
@@ -407,6 +407,7 @@ describe("big man", () => {
const exits = SIDES.filter((d) => d !== opposite(side) && stepTarget(view, t1.to, d).kind === "step");
if (want === "corner" && exits.length === 1 && exits[0] !== side) return { at: { x, y }, side, mid: t1.to, exits };
if (want === "fork" && exits.length >= 2) return { at: { x, y }, side, mid: t1.to, exits };
if (want === "straight-fork" && exits.length >= 2 && exits.includes(side)) return { at: { x, y }, side, mid: t1.to, exits };
}
}
throw new Error(`no ${want} on this board`);
@@ -453,15 +454,15 @@ describe("big man", () => {
expect(state.turn.movementUsed).toBe(used + 1);
});
it("an older game shoves straight ahead when it can, and now rounds a corner when it cannot", () => {
it("a pre-rev-15 game shoves straight ahead when it can and rounds a corner when it cannot", () => {
let { state } = createGame({ playerIds: ["alice", "bob"], seed: 42, sets: ["basic", "expansion1"], deckRev: 14 });
state = toRound2(state);
const giant = activePlayer(state);
state.sustained.push({ id: "fx-big", cardId: "big-man", casterId: giant.id, targetId: giant.id, remainingTurns: 9, data: {} });
const victim = state.players.find((p) => p.id !== giant.id)!;
// A fork where straight ahead is open: no window, straight it is.
const fork = pushSite(state, "fork");
if (fork.exits.includes(fork.side)) {
const fork = pushSite(state, "straight-fork");
{
giant.position = { ...fork.at };
victim.position = { ...fork.mid };
const r = applyCommand(state, giant.id, { type: "move", direction: fork.side });