The fireball-then-buddy lockout
Per the owner's favorite play: the pact only breaks when its caster attacks the target, so a blow landed BEFORE the pact leaves it intact. After spending its attack, a non-berserker bot with BUDDY in hand signs it onto the weakest visible unpacted enemy — the one it likely just burned — barring their revenge. The berserker skips it: it would only break its own pact tomorrow. 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
3087f00bdc
commit
21884fa26e
@@ -1250,6 +1250,23 @@ export function automatonCommand(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BUDDY after the blow: the wounded cannot come looking for payback —
|
||||||
|
// the pact holds unless the clockwork strikes them again. The berserker
|
||||||
|
// skips it; it would only break its own pact tomorrow.
|
||||||
|
if (tier.buffs && view.turn.attackUsed && style !== "berserker") {
|
||||||
|
const pact = inHand(view, "buddy");
|
||||||
|
if (pact) {
|
||||||
|
const sighted = sightedCellsFor(view);
|
||||||
|
const mark = livingEnemies(view)
|
||||||
|
.filter((p) => sighted.has(cellKey(p.position)) &&
|
||||||
|
!view.sustained.some((s) => s.cardId === "buddy" && s.casterId === you && s.targetId === p.id))
|
||||||
|
.sort((a, b) => a.life - b.life)[0];
|
||||||
|
if (mark) {
|
||||||
|
return { type: "cast", instanceId: pact.instanceId, target: { kind: "player", playerId: mark.id } };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// March. The thief-chase outranks everything; the berserker hunts wizards
|
// March. The thief-chase outranks everything; the berserker hunts wizards
|
||||||
// over gold; the worrier keeps its distance; the hunter goes to the gold.
|
// over gold; the worrier keeps its distance; the hunter goes to the gold.
|
||||||
if (view.turn.movementUsed < view.turn.movementAllowance) {
|
if (view.turn.movementUsed < view.turn.movementAllowance) {
|
||||||
|
|||||||
@@ -427,3 +427,43 @@ describe("round two of the owner's tactics", () => {
|
|||||||
if (!r.ok) throw new Error(r.error);
|
if (!r.ok) throw new Error(r.error);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("the fireball-then-buddy lockout", () => {
|
||||||
|
it("burns the target, then signs the pact so they cannot hit back", () => {
|
||||||
|
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 };
|
||||||
|
bot.hand = [
|
||||||
|
{ instanceId: "fireball#T", cardId: "fireball" },
|
||||||
|
{ instanceId: "buddy#T", cardId: "buddy" },
|
||||||
|
];
|
||||||
|
// First: the blow.
|
||||||
|
let cmd = automatonCommand(viewFor(state, "bot"), "hunter", "archmage");
|
||||||
|
expect(cmd).toMatchObject({ type: "cast", instanceId: "fireball#T" });
|
||||||
|
let r = applyCommand(state, "bot", cmd!);
|
||||||
|
if (!r.ok) throw new Error(r.error);
|
||||||
|
state = r.state;
|
||||||
|
r = applyCommand(state, "other", { type: "pass" });
|
||||||
|
if (!r.ok) throw new Error(r.error);
|
||||||
|
state = r.state;
|
||||||
|
// Then: the pact.
|
||||||
|
cmd = automatonCommand(viewFor(state, "bot"), "hunter", "archmage");
|
||||||
|
expect(cmd).toEqual({
|
||||||
|
type: "cast", instanceId: "buddy#T",
|
||||||
|
target: { kind: "player", playerId: "other" },
|
||||||
|
});
|
||||||
|
r = applyCommand(state, "bot", cmd!);
|
||||||
|
if (!r.ok) throw new Error(r.error);
|
||||||
|
state = r.state;
|
||||||
|
// The pact holds: the victim cannot strike their tormentor.
|
||||||
|
expect(state.sustained.some(
|
||||||
|
(s) => s.cardId === "buddy" && s.casterId === "bot" && s.targetId === "other",
|
||||||
|
)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user