A reflected Lightning Blast ends the caster's turn on the spot (rev 28)

FAQ: 'If this gets FULLY REFLECTED, you lose the rest of your turn and
cannot draw cards (in addition to damage).' When the returned bolt
stuns its own caster mid-turn, their remaining actions end at once and
the end-of-turn draw comes up empty (new turn.drawForbidden flag); the
normal stun still costs them the next turn. The affected player sees
'Your own bolt has left you reeling' in place of the usual spent-turn
slip. Older revisions played on and stored games replay so.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138A8CjeQRpvzKxuMfz1Bqc
This commit is contained in:
Eric Wagoner
2026-08-17 23:47:25 -04:00
co-authored by Claude Fable 5
parent 67157ad3a2
commit 1d7407cb20
5 changed files with 62 additions and 4 deletions
+42
View File
@@ -1023,3 +1023,45 @@ describe("the reflected-attack window (rules rev 25)", () => {
expect(state.players.find((p) => p.id === attacker)!.life).toBe(5);
});
});
describe("a reflected lightning blast ends the caster's turn (rules rev 28)", () => {
function boltRig(deckRev: number) {
let { state } = createGame({ playerIds: ["a", "b"], seed: 42, sets: ["basic"], deckRev });
state = toRound2(state);
const { attacker, defender } = faceOff(state);
const lb = giveCard(state, attacker, "lightning-blast");
giveCard(state, attacker, "number-3", "N", 1);
giveCard(state, defender, "full-reflection", "FR", 0);
state = must(state, attacker, {
type: "cast", instanceId: lb.instanceId, numberInstanceIds: ["number-3#N"],
target: { kind: "player", playerId: defender },
});
state = must(state, defender, { type: "counteract", instanceId: "full-reflection#FR" });
state = must(state, attacker, { type: "pass" });
// rev 25+: the returned bolt opens its window; the caster declines to answer.
if (state.stack) state = must(state, attacker, { type: "pass" });
return { state, attacker, defender };
}
it("FAQ: 'you lose the rest of your turn and can't draw cards'", () => {
let { state, attacker } = boltRig(28);
expect(state.players.find((p) => p.id === attacker)!.life).toBe(12);
expect(state.turn.actionsEnded).toBe(true);
// No more marching, and the end-of-turn draw comes up empty.
expect(applyCommand(state, attacker, { type: "move", direction: "N" }).ok).toBe(false);
const before = state.players.find((p) => p.id === attacker)!.hand.length;
state = must(state, attacker, { type: "endTurn", draw: 2 });
expect(state.players.find((p) => p.id === attacker)!.hand.length).toBe(before);
// And the stun still costs the next turn.
expect(state.players.find((p) => p.id === attacker)!.lostTurns
+ (activePlayer(state).id === attacker ? 1 : 0)).toBeGreaterThanOrEqual(1);
});
it("rev 27 keeps the old behavior: the caster plays on and draws", () => {
let { state, attacker } = boltRig(27);
expect(state.turn.actionsEnded).toBe(false);
const before = state.players.find((p) => p.id === attacker)!.hand.length;
state = must(state, attacker, { type: "endTurn", draw: 2 });
expect(state.players.find((p) => p.id === attacker)!.hand.length).toBeGreaterThan(before);
});
});