The Ward is played in the moment (rules rev 31)
'When a player picks up one of your treasures, you may play at that time (out of turn) this card on him' — the owner read the card and is right: no arming ahead. When a treasure whose owner holds WARD is grabbed, the grab hangs (new wardPending phase, outranking all other input) and the owner alone answers: spring it (3 damage, card spent) or let them go (card kept, silence). Automatons always spring it on a thief of their gold. The arming mechanic is refused at rev 31 and its button hidden; rev 3-30 games keep their armed wards and rev 1-2 keep the automatic spring, replaying unchanged. The window does reveal that the owner holds SOMETHING - as it would at any real table when the room turns to look at them. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0138A8CjeQRpvzKxuMfz1Bqc
This commit is contained in:
co-authored by
Claude Fable 5
parent
b7f93fe454
commit
75d3d44c6c
@@ -1,4 +1,5 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { giveCard } from "./helpers";
|
||||
import {
|
||||
applyCommand,
|
||||
activePlayer,
|
||||
@@ -262,3 +263,52 @@ describe("elimination by lost treasures drops what the fallen carried (rev 30)",
|
||||
expect(btAfter.position).toEqual(cAfter.position);
|
||||
});
|
||||
});
|
||||
|
||||
describe("the Ward is played in the moment (rules rev 31)", () => {
|
||||
function grabRig() {
|
||||
let { state } = createGame({ playerIds: ["thief", "owner"], seed: 42, sets: ["basic"], deckRev: 31 });
|
||||
const thief = state.players.find((p) => p.id === "thief")!;
|
||||
const owner = state.players.find((p) => p.id === "owner")!;
|
||||
giveCard(state, "owner", "ward", "W", 0);
|
||||
const t = state.treasures.find((t) => t.owner === "owner" && t.position)!;
|
||||
thief.position = { ...t.position! };
|
||||
while (state.players[state.turn.activeIndex]!.id !== "thief") {
|
||||
const r = applyCommand(state, state.players[state.turn.activeIndex]!.id, { type: "endTurn", draw: 0 });
|
||||
if (!r.ok) throw new Error(r.error);
|
||||
state = r.state;
|
||||
}
|
||||
const r = applyCommand(state, "thief", { type: "pickUpTreasure" });
|
||||
if (!r.ok) throw new Error(r.error);
|
||||
return { state: r.state, owner, thief };
|
||||
}
|
||||
|
||||
it("the grab hangs on the owner; springing costs the thief 3 and the card", () => {
|
||||
let { state } = grabRig();
|
||||
expect(state.wardPending).toEqual({ ownerId: "owner", takerId: "thief" });
|
||||
// Nobody else may act while it hangs.
|
||||
expect(applyCommand(state, "thief", { type: "endTurn", draw: 0 }).ok).toBe(false);
|
||||
const r = applyCommand(state, "owner", { type: "wardChoice", play: true });
|
||||
if (!r.ok) throw new Error(r.error);
|
||||
state = r.state;
|
||||
expect(state.wardPending).toBeNull();
|
||||
expect(state.players.find((p) => p.id === "thief")!.life).toBe(12);
|
||||
expect(state.players.find((p) => p.id === "owner")!.hand.some((c) => c.cardId === "ward")).toBe(false);
|
||||
});
|
||||
|
||||
it("declining lets the thief go, Ward still in hand", () => {
|
||||
let { state } = grabRig();
|
||||
const r = applyCommand(state, "owner", { type: "wardChoice", play: false });
|
||||
if (!r.ok) throw new Error(r.error);
|
||||
state = r.state;
|
||||
expect(state.players.find((p) => p.id === "thief")!.life).toBe(15);
|
||||
expect(state.players.find((p) => p.id === "owner")!.hand.some((c) => c.cardId === "ward")).toBe(true);
|
||||
expect(applyCommand(state, "thief", { type: "endTurn", draw: 0 }).ok).toBe(true);
|
||||
});
|
||||
|
||||
it("arming is refused in this vintage", () => {
|
||||
let { state } = createGame({ playerIds: ["a", "b"], seed: 42, sets: ["basic"], deckRev: 31 });
|
||||
giveCard(state, state.players[state.turn.activeIndex]!.id, "ward", "W", 0);
|
||||
const r = applyCommand(state, state.players[state.turn.activeIndex]!.id, { type: "armWard", armed: true });
|
||||
expect(r.ok).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user