Creatures walk open doorways, and the interruption gets its fanfare

Player movement asked the full question of a door — removed, keyed
this turn, or held — while creature movement only saw "door" and
refused, so a skeleton balked at a doorway its master had unlocked
for good. One doorIsOpen() now answers for both, and an open doorway
costs a wraith none of its wall passes.

And the interruption window earns the modal it deserved: "The maze
holds its breath" — the card shown, the instruction plain, dismissed
with "Seize it". No more hunting the rail for a slip while time
stands parted.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Eric Wagoner
2026-08-17 13:50:38 -04:00
co-authored by Claude Fable 5
parent 44c14f5ce1
commit e7c8ddc0b3
3 changed files with 65 additions and 4 deletions
+29
View File
@@ -521,3 +521,32 @@ describe("elimination sweeps the board either way (rules rev 14)", () => {
expect(state.sustained.some((s) => s.targetId === "c")).toBe(false);
});
});
describe("creatures walk open doorways", () => {
it("a skeleton passes a door whose lock was removed", () => {
let { state } = createGame({ playerIds: ["a", "b"], seed: 42, sets: ["basic", "expansion1"], deckRev: 16 });
state = toRound2(state);
const view = boardView(state);
for (const [key, edge] of Object.entries(view.edges)) {
if (edge !== "door") continue;
const [kind, coords] = key.split(",").length ? key.split(":") as [string, string] : ["", ""];
const [x, y] = coords.split(",").map(Number) as [number, number];
const side = kind === "V" ? ("E" as Side) : ("S" as Side);
state.doorStates[key] = "removed";
state.creatures.push({
id: "sk1", kind: "skeleton", controllerId: activePlayer(state).id,
position: { x, y }, damage: 0, maxDamage: 4, movesPerTurn: 3,
movementUsed: 0, attackUsed: false, justCreated: false,
wallPassesPerTurn: 0, wallPassUsed: 0, scorchedThisTurn: [],
});
const r = applyCommand(state, activePlayer(state).id, {
type: "moveCreature", creatureId: "sk1", direction: side,
});
if (!r.ok) throw new Error(r.error);
const sk = r.state.creatures.find((c) => c.id === "sk1")!;
expect(cellKey(sk.position)).toBe(cellKey({ x: x + (side === "E" ? 1 : 0), y: y + (side === "S" ? 1 : 0) }));
return;
}
throw new Error("setup: seed 42 grew a maze with no doors");
});
});