Round two of the owner's tactics: exile, wand-slip, finishers, boosts
- TELEPORT OPPONENT exiles a delivery in progress — the thief of the bot's gold, or any carrier within six of home — to the square farthest (by walking distance) from the victim's own home; a sealed pocket wins outright. No LOS needed for the destination, per the card. - WARP WAND joins the roadwork: a wall slips open for a 4+-step shortcut when the crossing fits this turn's remaining legs (the wall returns at end of turn); charges itself with the smallest number on first use. - ADRENALINE is the finisher: cast when no single attack in hand kills the target but the top two together do; the attack window now honors the second swing. - STRENGTH doubles a thrown dagger or rock exactly when that turns a wound into a kill. - EXTEND rides afflictions, doubling the misery's stay. - MEGA-MONSTER doubles a pet's stride (movement over life) so the menagerie actually catches people. All six leave the bottom discard tier. 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
4bda6087b1
commit
3087f00bdc
@@ -374,3 +374,56 @@ describe("the widened spellbook", () => {
|
||||
if (!r.ok) throw new Error(r.error);
|
||||
});
|
||||
});
|
||||
|
||||
describe("round two of the owner's tactics", () => {
|
||||
it("exiles a thief carrying its gold to the far end of nowhere", () => {
|
||||
let { state } = createGame({ playerIds: ["bot", "other"], seed: 42, sets: ["basic", "expansion1"], deckRev: 24 });
|
||||
// burn round 1 and reach the bot's turn
|
||||
for (let guard = 0; guard < 10 && !(actingSeat(state) === "bot" && state.turn.round > 1); guard++) {
|
||||
const r = applyCommand(state, actingSeat(state), { type: "endTurn", draw: 0 });
|
||||
if (!r.ok) throw new Error(r.error);
|
||||
state = r.state;
|
||||
}
|
||||
const bot = state.players.find((p) => p.id === "bot")!;
|
||||
const thief = state.players.find((p) => p.id === "other")!;
|
||||
const t = state.treasures.find((t) => t.owner === "bot")!;
|
||||
t.position = null;
|
||||
t.carriedBy = "other";
|
||||
thief.carriedTreasureId = t.id;
|
||||
// The thief is a step from delivering; the bot watches from beside them.
|
||||
thief.position = { x: thief.home.x, y: thief.home.y === 0 ? 1 : thief.home.y - 1 };
|
||||
bot.position = { ...thief.position };
|
||||
bot.hand = [{ instanceId: "teleport-opponent#T", cardId: "teleport-opponent" }];
|
||||
const cmd = automatonCommand(viewFor(state, "bot"), "hunter", "archmage");
|
||||
expect(cmd).toMatchObject({ type: "cast", instanceId: "teleport-opponent#T" });
|
||||
const dest = (cmd as { params: { cell: { x: number; y: number } } }).params.cell;
|
||||
// The chosen square is a long march from the thief's own home.
|
||||
const d = Math.abs(dest.x - thief.home.x) + Math.abs(dest.y - thief.home.y);
|
||||
expect(d).toBeGreaterThanOrEqual(5);
|
||||
const r = applyCommand(state, "bot", cmd!);
|
||||
if (!r.ok) throw new Error(r.error);
|
||||
});
|
||||
|
||||
it("casts adrenaline when two blows finish what one cannot", () => {
|
||||
let { state } = createGame({ playerIds: ["bot", "other"], seed: 42, sets: ["basic", "expansion1"], deckRev: 24 });
|
||||
for (let guard = 0; guard < 10 && !(actingSeat(state) === "bot" && state.turn.round > 1); guard++) {
|
||||
const r = applyCommand(state, actingSeat(state), { type: "endTurn", draw: 0 });
|
||||
if (!r.ok) throw new Error(r.error);
|
||||
state = r.state;
|
||||
}
|
||||
const bot = state.players.find((p) => p.id === "bot")!;
|
||||
const prey = state.players.find((p) => p.id === "other")!;
|
||||
prey.position = { ...bot.position };
|
||||
prey.life = 7; // fireball (5) alone cannot; fireball + dagger (3) can
|
||||
bot.hand = [
|
||||
{ instanceId: "adrenaline#T", cardId: "adrenaline" },
|
||||
{ instanceId: "fireball#T", cardId: "fireball" },
|
||||
{ instanceId: "dagger#T", cardId: "dagger" },
|
||||
{ instanceId: "number-2#T", cardId: "number-2" },
|
||||
];
|
||||
const cmd = automatonCommand(viewFor(state, "bot"), "berserker", "archmage");
|
||||
expect(cmd).toMatchObject({ type: "cast", instanceId: "adrenaline#T" });
|
||||
const r = applyCommand(state, "bot", cmd!);
|
||||
if (!r.ok) throw new Error(r.error);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user