A test walks a wizard into a slime with a spell waiting in it

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-07 15:55:00 -05:00
co-authored by Claude Fable 5.1
parent c09bcc481d
commit 16fac5e6ca
+32 -1
View File
@@ -3,7 +3,7 @@ import { applyCommand, activePlayer, boardView, createGame, gameLos, type GameSt
import { cellKey, edgeKey, neighbor, opposite, SIDES, stepTarget, type Cell, type Side } from "../src/board"; import { cellKey, edgeKey, neighbor, opposite, SIDES, stepTarget, type Cell, type Side } from "../src/board";
import type { CardInstance } from "../src/cards"; import type { CardInstance } from "../src/cards";
import { eligibleCellsFor, sightedCellsFor, viewFor } from "../src/view"; import { eligibleCellsFor, sightedCellsFor, viewFor } from "../src/view";
import { newExpansionGame as newGame, must, giveCard, emptyNeighborCell, plainRimWall } from "./helpers"; import { newExpansionGame as newGame, must, giveCard, emptyNeighborCell, plainRimWall, toRound2 } from "./helpers";
/** The sides a walker may leave a pit by, having entered it heading `entry`. */ /** The sides a walker may leave a pit by, having entered it heading `entry`. */
function rimExits(state: GameState, pit: Cell, entry: Side): Side[] { function rimExits(state: GameState, pit: Cell, entry: Side): Side[] {
@@ -675,3 +675,34 @@ describe("a wave names its victims before it pushes (LK97)", () => {
}); });
} }
}); });
describe("spells cast at a slime wait in the gel", () => {
it("a lightning blast lodges in the slime and goes off on the next wizard in, once", () => {
let { state } = newGame(42);
state = toRound2(state);
const caster = activePlayer(state);
const victim = state.players.find((p) => p.id !== caster.id)!;
const spot = emptyNeighborCell(state, caster.position);
state.squareContents[cellKey(spot.cell)] = { kind: "slime", damage: 0, createdBy: caster.id };
const bolt = giveCard(state, caster.id, "lightning-blast");
const cast = applyCommand(state, caster.id, { type: "cast", instanceId: bolt.instanceId, target: { kind: "cell", cell: spot.cell } });
expect(cast.ok).toBe(true);
if (!cast.ok) return;
expect(cast.events.some((e) => e.type === "spellTrapped")).toBe(true);
expect(cast.state.slimeTraps[cellKey(spot.cell)]?.length).toBe(1);
// Nobody is hurt yet; the victim walks in on their own turn.
state = must(cast.state, caster.id, { type: "endTurn", draw: 2 });
victim.position = { ...caster.position };
const v = state.players.find((p) => p.id === victim.id)!;
v.position = { ...caster.position };
const walk = applyCommand(state, victim.id, { type: "move", direction: spot.side });
expect(walk.ok).toBe(true);
if (!walk.ok) return;
expect(walk.events.some((e) => e.type === "slimeTrapSprung")).toBe(true);
expect(walk.state.stack?.defenderId).toBe(victim.id);
expect(walk.state.stack?.trapped).toBe(true);
const hit = must(walk.state, victim.id, { type: "pass" });
expect(hit.players.find((p) => p.id === victim.id)!.life).toBeLessThan(15);
expect(hit.slimeTraps[cellKey(spot.cell)]).toBeUndefined();
});
});