Rev 18: REFLECTION's returning half is the caster's to counteract (96WE)
Kestrel's blade came back halved off the automaton's REFLECTION and landed before he could raise the ABSORB in his hand. FULL REFLECTION's return was already a fresh attack with the caster's own window; the half now goes the same way — its damage and any split duration ride a returned stack the caster may meet with an ABSORB, a BLUNT, or another REFLECTION. Trapped spells and creatures' touches keep the instant half. Older games replay as they landed. A test soaks the half and takes it, under rev 18 and rev 17. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
2fd324a475
commit
34d76d9feb
@@ -117,6 +117,48 @@ describe("attack spells", () => {
|
||||
expect(state.players.find((p) => p.id === attacker)!.life).toBe(10);
|
||||
});
|
||||
|
||||
it("reflection's returning half is the caster's to counteract (rev 18)", () => {
|
||||
const setup = (deckRev: number) => {
|
||||
let { state } = createGame({ playerIds: ["alice", "bob"], seed: 42, sets: ["basic"], deckRev });
|
||||
state = toRound2(state);
|
||||
const { attacker, defender } = faceOff(state);
|
||||
const fb = giveCard(state, attacker, "fireball");
|
||||
const d = state.players.find((p) => p.id === defender)!;
|
||||
d.hand[0] = { instanceId: "reflection#T", cardId: "reflection" };
|
||||
const a = state.players.find((p) => p.id === attacker)!;
|
||||
a.hand.push({ instanceId: "absorb#T", cardId: "absorb" });
|
||||
state = must(state, attacker, { type: "cast", instanceId: fb.instanceId, target: { kind: "player", playerId: defender } });
|
||||
state = must(state, defender, { type: "counteract", instanceId: "reflection#T" });
|
||||
state = must(state, attacker, { type: "pass" });
|
||||
state = must(state, defender, { type: "pass" });
|
||||
return { state, attacker, defender };
|
||||
};
|
||||
const life = (s: GameState, id: string) => s.players.find((p) => p.id === id)!.life;
|
||||
// Rev 18: the defender takes their half; the half coming back waits on the caster.
|
||||
{
|
||||
const { state, attacker, defender } = setup(18);
|
||||
expect(life(state, defender)).toBe(12);
|
||||
expect(life(state, attacker)).toBe(15);
|
||||
expect(state.stack?.waitingOn).toBe(attacker);
|
||||
expect(state.stack?.reflectedBase?.damage).toBe(3);
|
||||
// A counter hands the word to the reflector, who may answer; both pass to resolve.
|
||||
const soaked = must(state, attacker, { type: "counteract", instanceId: "absorb#T" });
|
||||
const done = must(must(soaked, defender, { type: "pass" }), attacker, { type: "pass" });
|
||||
expect(life(done, attacker)).toBe(15);
|
||||
expect(done.stack).toBeNull();
|
||||
const taken = must(state, attacker, { type: "pass" });
|
||||
expect(life(taken, attacker)).toBe(12);
|
||||
expect(taken.stack).toBeNull();
|
||||
}
|
||||
// Rev 17: the half landed at once.
|
||||
{
|
||||
const { state, attacker, defender } = setup(17);
|
||||
expect(life(state, defender)).toBe(12);
|
||||
expect(life(state, attacker)).toBe(12);
|
||||
expect(state.stack).toBeNull();
|
||||
}
|
||||
});
|
||||
|
||||
it("absorb spell nullifies the attack and takes the card into hand", () => {
|
||||
let { state } = newGame();
|
||||
state = toRound2(state);
|
||||
|
||||
Reference in New Issue
Block a user