Credibility pass: the collapse loses its scaffolding
Blind reviews over the rev-37..40 features and the gate collapse. The scripted surgery's scars come out: bare brace blocks unwrapped (with one hiding an unreachable scrambleHands), the amputated comment healed, the dead events parameter unthreaded from the illusion-sight chain, the laziness probe in perceivedBoard collapsed to the rule it always produced, GameView.deckRev retired with its last reader, the ward's arming stub told honestly, and every comment or test title still citing the retired revision numbering reworded to the rule it guards. Rim mechanics unify on rimWarpMouth and breachRim; the test suite gains plainRimWall and pushSustained and loses its loop-shaped scars and rev-named helpers. No behavior changes; 255 tests pass unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
8a50ff7f36
commit
4a91d56d24
@@ -2,7 +2,7 @@ import { describe, expect, it } from "vitest";
|
||||
import { applyCommand, activePlayer, boardView, creatureAt, type GameState, type PlayerId, createGame } from "../src/game";
|
||||
import { cellKey, edgeKey, SIDES, stepTarget, type Cell, type Side } from "../src/board";
|
||||
import type { CardInstance } from "../src/cards";
|
||||
import { newExpansionGame as newGame, must, giveCard, toRound2, emptyNeighborCell } from "./helpers";
|
||||
import { newExpansionGame as newGame, must, giveCard, toRound2, emptyNeighborCell, pushSustained } from "./helpers";
|
||||
|
||||
/** Summon a creature next to its creator (round 2+, consumes the attack). */
|
||||
function summon(state: GameState, playerId: PlayerId, kind: string, tag = "S") {
|
||||
@@ -139,7 +139,6 @@ describe("monsters", () => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// The touch opens the victim's counteraction window; they take it raw.
|
||||
state = must(state, enemy2.id, { type: "pass" });
|
||||
const bitten = state.players.find((p) => p.id !== me)!;
|
||||
expect(bitten.life).toBe(13);
|
||||
@@ -299,7 +298,7 @@ describe("expansion support cards", () => {
|
||||
});
|
||||
|
||||
describe("counteracting a creature's blow", () => {
|
||||
function rev4() {
|
||||
function freshGame() {
|
||||
return createGame({ playerIds: ["alice", "bob"], seed: 42, sets: ["basic", "expansion1"] });
|
||||
}
|
||||
function wraithOnVictim(state: GameState) {
|
||||
@@ -317,7 +316,7 @@ describe("counteracting a creature's blow", () => {
|
||||
}
|
||||
|
||||
it("BLUNT halves the wraith's touch; the card theft still lands", () => {
|
||||
let { state } = rev4();
|
||||
let { state } = freshGame();
|
||||
const rig = wraithOnVictim(state);
|
||||
state = rig.state;
|
||||
giveCard(state, rig.victim, "blunt", "B", 0);
|
||||
@@ -333,7 +332,7 @@ describe("counteracting a creature's blow", () => {
|
||||
});
|
||||
|
||||
it("FULL REFLECTION turns the touch back on the wraith, theft and all", () => {
|
||||
let { state } = rev4();
|
||||
let { state } = freshGame();
|
||||
const rig = wraithOnVictim(state);
|
||||
state = rig.state;
|
||||
giveCard(state, rig.victim, "full-reflection", "FR", 0);
|
||||
@@ -348,7 +347,7 @@ describe("counteracting a creature's blow", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("big man (rules rev 5)", () => {
|
||||
describe("big man", () => {
|
||||
function bigRig() {
|
||||
let { state } = createGame({ playerIds: ["alice", "bob"], seed: 42, sets: ["basic", "expansion1"] });
|
||||
state = toRound2(state);
|
||||
@@ -465,7 +464,7 @@ describe("monsters roll to hit the hidden", () => {
|
||||
return { state, me, victim, skeletonId: bones.id };
|
||||
}
|
||||
|
||||
it("rev 13: the skeleton's blow takes the 1-in-4 roll — 'any attack' means any", () => {
|
||||
it("the skeleton's blow takes the 1-in-4 roll — 'any attack' means any", () => {
|
||||
let { state, me, victim, skeletonId } = creatureVsInvisible();
|
||||
const rngBefore = JSON.stringify(state.rng);
|
||||
state = must(state, me, { type: "creatureAttack", creatureId: skeletonId, targetId: victim.id });
|
||||
@@ -475,7 +474,7 @@ describe("monsters roll to hit the hidden", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("elimination sweeps the board either way (rules rev 14)", () => {
|
||||
describe("elimination sweeps the board either way", () => {
|
||||
it("a treasure-eliminated wizard's fire imp vanishes with them", () => {
|
||||
let { state } = createGame({ playerIds: ["a", "b", "c"], seed: 42, sets: ["basic", "expansion1"] });
|
||||
const victim = state.players.find((p) => p.id === "c")!;
|
||||
@@ -536,7 +535,7 @@ describe("creatures walk open doorways", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("the wave carries monsters (rules rev 17)", () => {
|
||||
describe("the wave carries monsters", () => {
|
||||
it("a cornered skeleton takes the waterwall crush", () => {
|
||||
let { state } = createGame({ playerIds: ["a", "b"], seed: 42, sets: ["basic", "expansion1"] });
|
||||
state = toRound2(state);
|
||||
@@ -575,7 +574,7 @@ describe("the wave carries monsters (rules rev 17)", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("the democratic monster's claw survives the first wizard's death (rules rev 18)", () => {
|
||||
describe("the democratic monster's claw survives the first wizard's death", () => {
|
||||
it("refreshes each round even with the roll-off winner dead", () => {
|
||||
let { state } = createGame({ playerIds: ["a", "b", "c"], seed: 42, sets: ["basic", "expansion1"] });
|
||||
state = toRound2(state);
|
||||
@@ -602,7 +601,7 @@ describe("the democratic monster's claw survives the first wizard's death (rules
|
||||
});
|
||||
});
|
||||
|
||||
describe("a mid-round democratic monster claws on the next turn (rules rev 18)", () => {
|
||||
describe("a mid-round democratic monster claws on the next turn", () => {
|
||||
it("creation spends the turn, not the round", () => {
|
||||
let { state } = createGame({ playerIds: ["a", "b"], seed: 42, sets: ["basic", "expansion1"] });
|
||||
state = toRound2(state);
|
||||
@@ -656,7 +655,7 @@ describe("collapsing walls crush monsters too", () => {
|
||||
throw new Error("setup: no interior wall found");
|
||||
}
|
||||
|
||||
it("rev 21: the adjacent troll takes the four points", () => {
|
||||
it("the adjacent troll takes the four points", () => {
|
||||
const state = wallRig();
|
||||
const troll = state.creatures.find((c) => c.id === "tr1");
|
||||
// Four points on a six-point troll: hurt but standing (or regenerating).
|
||||
@@ -681,7 +680,7 @@ describe("the self-stack resolves on a pass", () => {
|
||||
return { state: r.state, creator: creator.id };
|
||||
}
|
||||
|
||||
it("rev 22: passing your own monster's touch takes the claw and moves on", () => {
|
||||
it("passing your own monster's touch takes the claw and moves on", () => {
|
||||
const { state, creator } = selfTouch();
|
||||
if (!state.stack) return; // a wall between: the touch never opened
|
||||
expect(state.stack.attackerId).toBe(creator);
|
||||
@@ -693,16 +692,16 @@ describe("the self-stack resolves on a pass", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("fear holds off monsters and unwilling feet alike (rules rev 32)", () => {
|
||||
describe("fear holds off monsters and unwilling feet alike", () => {
|
||||
it("a commanded monster cannot close within three of the fearsome", () => {
|
||||
let { state } = createGame({ playerIds: ["a", "b"], seed: 42, sets: ["basic", "expansion1"] });
|
||||
const a = state.players.find((p) => p.id === "a")!;
|
||||
const b = state.players.find((p) => p.id === "b")!;
|
||||
// b radiates fear; a's troll stands exactly four away, aimed straight at b.
|
||||
state.sustained.push({
|
||||
pushSustained(state, {
|
||||
id: "fx-fear", cardId: "fear", casterId: "b", targetId: "b",
|
||||
remainingTurns: 5, data: {},
|
||||
} as never);
|
||||
});
|
||||
b.position = { x: 2, y: 5 };
|
||||
a.position = { x: 0, y: 0 };
|
||||
state.creatures.push({
|
||||
|
||||
Reference in New Issue
Block a user