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
+6 -6
View File
@@ -8,7 +8,7 @@ import {
} from "../src/game";
import { cellKey, edgeKey } from "../src/board";
import { sightedCellsFor, viewFor } from "../src/view";
import { automatonCommand, automatonFallback, drawUnderCurses, pathToward, type AutomatonStyle, type AutomatonTier } from "../src/automaton";
import { automatonCommand, automatonFallback, drawUnderSlowDeath, pathToward, type AutomatonStyle, type AutomatonTier } from "../src/automaton";
import { pushSustained } from "./helpers";
/** Whose input does the maze want right now? */
@@ -1129,14 +1129,14 @@ describe("the clockwork under a curse, and before a pit", () => {
const state = botsTurn();
const bot = state.players.find((p) => p.id === "bot")!;
const plain = viewFor(state, "bot");
expect(drawUnderCurses(plain, 2)).toBe(2);
expect(drawUnderSlowDeath(plain, 2)).toBe(2);
pushSustained(state, { id: "sd", cardId: "slow-death", casterId: "human", targetId: "bot", remainingTurns: 1e9 });
bot.life = 7;
expect(drawUnderCurses(viewFor(state, "bot"), 2)).toBe(2);
expect(drawUnderSlowDeath(viewFor(state, "bot"), 2)).toBe(2);
bot.life = 5;
expect(drawUnderCurses(viewFor(state, "bot"), 2)).toBe(1);
expect(drawUnderSlowDeath(viewFor(state, "bot"), 2)).toBe(1);
bot.life = 4;
expect(drawUnderCurses(viewFor(state, "bot"), 2)).toBe(0);
expect(drawUnderSlowDeath(viewFor(state, "bot"), 2)).toBe(0);
});
it("raises no SHADOW while bleeding, nor with little blood to spare", () => {
@@ -1152,7 +1152,7 @@ describe("the clockwork under a curse, and before a pit", () => {
for (let guard = 0; guard < 30 && actingSeat(state) === "bot"; guard++) {
const view = viewFor(state, "bot");
const cmd = automatonCommand(view, "berserker", "archmage") ?? automatonFallback(view, "archmage");
expect(JSON.stringify(cmd)).not.toContain("shadow#T");
expect(cmd.type === "cast" && cmd.instanceId === "shadow#T").toBe(false);
const r = applyCommand(state, "bot", cmd);
if (!r.ok) break;
state = r.state;