Every wall card learns the rim (rules rev 40)
The full audit Wall of Fire started: WATERWALL crashes on a warp mouth, washing both rims inward; ILLUSION WALL hangs its scrim on a mouth (the create-wall bluff); STONE TO WATER melts a brick over a warp at both ends and breaches a plain rim wall exactly as DESTROY WALL does — far side washes out, a warp opens, the wave floods the fresh tunnel; the WARP WAND bores a temporary wraparound that closes when its wall returns; and CREATE DOOR stops hanging dead doors onto the void. Older ledgers keep their refusals and danglings, and replay so. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
f82e4625af
commit
e8df6efcde
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { applyCommand, activePlayer, boardView } from "../src/game";
|
||||
import { applyCommand, activePlayer, boardView, createGame } from "../src/game";
|
||||
import { cellKey, edgeKey, SIDES, type Cell, type Side } from "../src/board";
|
||||
import type { CardInstance } from "../src/cards";
|
||||
import { newExpansionGame as newGame, must, giveCard, toRound2, faceOff } from "./helpers";
|
||||
@@ -143,6 +143,46 @@ describe("magic wands", () => {
|
||||
expect(boardView(state).edges[key]).toBe("wall");
|
||||
});
|
||||
|
||||
it("warp wand bores the rim for one turn from rev 40 — a temporary wraparound", () => {
|
||||
let { state } = createGame({
|
||||
playerIds: ["alice", "bob"], seed: 42, sets: ["basic", "expansion1"], deckRev: 40,
|
||||
});
|
||||
const me = activePlayer(state);
|
||||
const view = boardView(state);
|
||||
// A plain rim wall: off-board neighbor, no existing warp mouth.
|
||||
let rim: { cell: Cell; side: Side } | null = null;
|
||||
outer: for (const k of Object.keys(view.cells)) {
|
||||
const [x, y] = k.split(",").map(Number) as [number, number];
|
||||
for (const side of SIDES) {
|
||||
const dest = { x: x + (side === "E" ? 1 : side === "W" ? -1 : 0),
|
||||
y: y + (side === "S" ? 1 : side === "N" ? -1 : 0) };
|
||||
if (view.cells[cellKey(dest)]) continue;
|
||||
if (view.edges[edgeKey({ x, y }, side)] !== "wall") continue;
|
||||
if (state.board.warps.some((w) => cellKey(w.from.cell) === k && w.from.side === side)) continue;
|
||||
rim = { cell: { x, y }, side };
|
||||
break outer;
|
||||
}
|
||||
}
|
||||
if (!rim) throw new Error("setup: no plain rim wall found");
|
||||
me.position = { ...rim.cell };
|
||||
const warpsBefore = state.board.warps.length;
|
||||
const wand = giveCard(state, me.id, "warp-wand");
|
||||
giveCard(state, me.id, "number-2", "N", 1);
|
||||
state = must(state, me.id, {
|
||||
type: "cast", instanceId: wand.instanceId, numberInstanceIds: ["number-2#N"],
|
||||
target: { kind: "edge", cell: rim.cell, side: rim.side },
|
||||
});
|
||||
expect(state.board.warps.length).toBe(warpsBefore + 2);
|
||||
// The wraparound runs: step off the rim and land on the opposite edge.
|
||||
state = must(state, me.id, { type: "move", direction: rim.side });
|
||||
const across = state.players.find((p) => p.id === me.id)!.position;
|
||||
expect(cellKey(across)).not.toBe(cellKey(rim.cell));
|
||||
// Turn's end: the walls return and the warp closes with them.
|
||||
state = must(state, me.id, { type: "endTurn", draw: 0 });
|
||||
expect(boardView(state).edges[edgeKey(rim.cell, rim.side)]).toBe("wall");
|
||||
expect(state.board.warps.length).toBe(warpsBefore);
|
||||
});
|
||||
|
||||
it("deja-vu retrieves from the discard, but never a wand", () => {
|
||||
let { state } = newGame();
|
||||
const me = activePlayer(state);
|
||||
|
||||
Reference in New Issue
Block a user