Mist shields its wizard from creatures; a glued square turns with its sector; Waterbolt splits the power it is cast with

Three of Ramses's reports from KFJL:
- Rev 28: MIST-BODY's "may not attack or be attacked" holds against
  creatures. A wraith's or democratic monster's touch, a fire imp's
  scorch, and an ordered troll/skeleton/shadow blow all pass the mist by;
  older games keep the strike their ledgers recorded. The automaton no
  longer orders its creatures at a misted wizard.
- ROTATE and RELOCATE SECTOR threw while GLUE was down: GLUE keeps its
  cell's key in the sustained effect's edge slot, and the remap read it
  as an edge. It maps as a cell now (the throw never reached a ledger,
  so this ships ungated).
- WATERBOLT's damage/knockback split was sized by the NUMBER's face; the
  engine weighs POWERSTONE's +1 and AMPLIFY's doubling, so a 5 behind a
  powerstone was refused for not totalling 6.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Eric Wagoner
2026-10-21 19:54:43 -04:00
co-authored by Claude Opus 5.5
parent 3368a92cf5
commit 8dcdfd2415
5 changed files with 109 additions and 5 deletions
+61
View File
@@ -1044,3 +1044,64 @@ describe("the troll's fist on a wall", () => {
expect(again.ok).toBe(false);
});
});
describe("creatures cannot strike the mist (rev 28)", () => {
// MIST-BODY: "You may not attack or be attacked." Rev 28 holds the
// card against creatures as well as wizards; older games let them strike.
function mistRig(deckRev?: number) {
let { state } = createGame({ playerIds: ["a", "b"], seed: 42, sets: ["basic", "expansion1"], deckRev });
state = toRound2(state);
const creator = activePlayer(state);
state = summon(state, creator.id, "democratic-monster").state;
state = must(state, creator.id, { type: "endTurn", draw: 0 });
const mover = activePlayer(state);
const victim = state.players.find((p) => p.id !== mover.id)!;
pushSustained(state, { id: "fx-mist", cardId: "mist-body", casterId: victim.id, targetId: victim.id, remainingTurns: 2 });
const dm = state.creatures.find((c) => c.kind === "democratic-monster")!;
const spot = emptyNeighborCell(state, victim.position);
dm.position = { ...spot.cell };
return { state, mover: mover.id, victim: victim.id, dm: dm.id, into: opposite(spot.side) };
}
it("a democratic monster passes through a misted wizard without clawing", () => {
const { state, mover, dm, into } = mistRig();
const r = applyCommand(state, mover, { type: "moveCreature", creatureId: dm, direction: into });
if (!r.ok) throw new Error(r.error);
expect(r.state.stack).toBeNull();
expect(r.events.some((e) => e.type === "creatureTouched")).toBe(false);
expect(r.state.creatures.find((c) => c.id === dm)!.attackUsed).toBe(false);
});
it("older games let the monster claw the mist", () => {
const { state, mover, dm, into } = mistRig(27);
const r = applyCommand(state, mover, { type: "moveCreature", creatureId: dm, direction: into });
if (!r.ok) throw new Error(r.error);
expect(r.state.stack?.creatureId ?? null).toBe(dm);
});
function skeletonRig(deckRev?: number) {
let { state } = createGame({ playerIds: ["a", "b"], seed: 42, sets: ["basic", "expansion1"], deckRev });
state = toRound2(state);
const me = activePlayer(state).id;
state = summon(state, me, "skeleton").state;
state = must(state, me, { type: "endTurn", draw: 0 });
const other = activePlayer(state).id;
state = must(state, other, { type: "endTurn", draw: 0 });
const victim = state.players.find((p) => p.id === other)!;
victim.position = { ...state.creatures[0]!.position };
pushSustained(state, { id: "fx-mist", cardId: "mist-body", casterId: other, targetId: other, remainingTurns: 2 });
return { state, me, victim: other, skeleton: state.creatures[0]!.id };
}
it("no skeleton may be ordered to strike a misted wizard", () => {
const { state, me, victim, skeleton } = skeletonRig();
const r = applyCommand(state, me, { type: "creatureAttack", creatureId: skeleton, targetId: victim });
expect(r.ok).toBe(false);
});
it("older games let the order stand", () => {
const { state, me, victim, skeleton } = skeletonRig(27);
const r = applyCommand(state, me, { type: "creatureAttack", creatureId: skeleton, targetId: victim });
expect(r.ok).toBe(true);
});
});