The dimming aid stops lying about boobytrap, glue, and safe

Three cards sat wrongly in the creation bucket of eligibleCellsFor,
so the targeting dim demanded sighted empty squares the engine never
asks for. Boobytrap tokens go anywhere on the board but solid stone —
no sight required; a trap you can see coming is a poor trap. Glue and
the safe were worse than restricted: inverted. Both seize a square
that HOLDS a loose object or treasure, exactly the squares the empty-
square rule dimmed out. Each now has its own branch mirroring the
engine's actual checks, pinned by tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Eric Wagoner
2026-08-16 19:31:57 -04:00
co-authored by Claude Fable 5
parent 1275ac9287
commit ac53773fe4
2 changed files with 56 additions and 1 deletions
@@ -161,3 +161,35 @@ describe("expansion terrain", () => {
// Wave side effects vary by geometry; the melt itself is the pinned behavior.
});
});
describe("eligibility dimming mirrors the engine", () => {
it("boobytrap tokens go anywhere but solid stone, sight be damned", async () => {
const { viewFor, eligibleCellsFor } = await import("../src/view");
let { state } = newGame();
const caster = activePlayer(state).id;
const view = viewFor(state, caster);
const lit = eligibleCellsFor(view, "boobytrap")!;
// Every board square is fair game (the fresh maze holds no solid stone),
// including squares far outside the caster's sight.
expect(lit.size).toBe(Object.keys(view.board.cells).length);
});
it("glue lights only sighted squares that hold something", async () => {
const { viewFor, eligibleCellsFor } = await import("../src/view");
let { state } = newGame();
const caster = activePlayer(state);
// Drop a dagger at the caster's feet — the one guaranteed-sighted object.
const here = { ...caster.position };
state.groundObjects[cellKey(here)] = [{ instanceId: "dagger#G", cardId: "dagger" }];
const lit = eligibleCellsFor(viewFor(state, caster.id), "glue")!;
expect(lit.has(cellKey(here))).toBe(true);
// Empty squares stay dim — glue needs something to glue down.
for (const k of lit) {
const view = viewFor(state, caster.id);
const held =
(view.groundObjects[k] ?? []).length > 0 ||
view.treasures.some((t) => t.position && cellKey(t.position) === k);
expect(held).toBe(true);
}
});
});