From 0ced49ca6ce22e940eb96405600e4675cbc839d4 Mon Sep 17 00:00:00 2001 From: Eric Wagoner Date: Wed, 21 Oct 2026 20:10:56 -0400 Subject: [PATCH] A wall beyond the door you stand at and have unlocked is in sight for wall-aimed spells Edge casts judged sight on the bare board, where every door hangs shut, so the threshold peek (an unlocked, held, removed or pickable door at your elbow) reached only square-aimed spells. Ramses (BDFS) unlocked a door with MASTER KEY and could not STONE TO WATER the wall beyond it until he stepped through. Edge casts now see with the caster's eye. Widening only: refused casts never entered ledgers. Co-Authored-By: Claude Opus 5.5 --- packages/engine/src/game.ts | 3 +++ .../engine/test/durations-doors-cards.test.ts | 20 +++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/packages/engine/src/game.ts b/packages/engine/src/game.ts index 95cb674..6f60a60 100644 --- a/packages/engine/src/game.ts +++ b/packages/engine/src/game.ts @@ -599,6 +599,9 @@ function castSightEdge( cell: Cell, side: Side, ): boolean { + // The caster's own eye, as for square-aimed casts: a held door stands + // open, and the door at their elbow they may pull ajar and look through. + board = doorsAjar(state, caster.id, openedDoors(state, board)); if (losToEdge(board, caster.position, cell, side)) return true; if (displays(caster, "visionstone") && throughOneEdge(board, (b) => losToEdge(b, caster.position, cell, side))) { diff --git a/packages/engine/test/durations-doors-cards.test.ts b/packages/engine/test/durations-doors-cards.test.ts index 3979df4..e769300 100644 --- a/packages/engine/test/durations-doors-cards.test.ts +++ b/packages/engine/test/durations-doors-cards.test.ts @@ -458,6 +458,26 @@ describe("a held door is an open doorway to the eye", () => { expect(cast.ok).toBe(true); }); + it("a wall beyond the unlocked door is in sight for wall-aimed spells too (BDFS)", () => { + // Edge casts once judged sight on the bare board, where every door + // hangs shut — the threshold peek reached only square-aimed spells. + let { state, cell, side, holder } = sightRig(); + const near = neighbor(cell, side); + const view = boardView(state); + const far = SIDES.find((s) => s !== opposite(side) && view.edges[edgeKey(near, s)] === "wall"); + if (!far) throw new Error("setup: no wall on the far side of seed 42's door"); + const pick = giveCard(state, holder, "pick-lock"); + state = must(state, holder, { + type: "cast", instanceId: pick.instanceId, + target: { kind: "edge", cell, side }, + }); + const dw = giveCard(state, holder, "destroy-wall", "DW", 1); + const cast = applyCommand(state, holder, { + type: "cast", instanceId: dw.instanceId, target: { kind: "edge", cell: near, side: far }, + }); + expect(cast.ok).toBe(true); + }); + it("a lock REMOVED lets any wizard beside the door peek through", () => { let { state, cell, side, holder, pursuer } = sightRig(); const rm = giveCard(state, holder, "remove-lock");