Rev 24: a REFLECTION against a permanent curse afflicts both wizards
"If this spell is REFLECTed, both players take 1/2 point of damage per space moved" (WALKING DEAD); "In case of REFLECTION, both players are affected" (IDIOT); SLOW DEATH follows REFLECTION's own rule that a spell works for both parties. A permanent curse has no duration for the reflection's split to halve, so the caster went untouched; the curse is now laid on them as well, as if cast back. Older games replay as they were; PRPM, reflected at seq 108 with no move since, was re-stamped to 24 at its table's request. 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
f26893f45b
commit
f738957100
@@ -247,7 +247,7 @@ export interface CastParams {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** The revision new games are dealt under; GameConfig.deckRev pins it per game. */
|
/** The revision new games are dealt under; GameConfig.deckRev pins it per game. */
|
||||||
export const CURRENT_RULES_REV = 23;
|
export const CURRENT_RULES_REV = 24;
|
||||||
|
|
||||||
/** Every rulings revision since the baseline, newest last — the entries a
|
/** Every rulings revision since the baseline, newest last — the entries a
|
||||||
* game's deckRev freezes it before or after. Shown to players as the house
|
* game's deckRev freezes it before or after. Shown to players as the house
|
||||||
@@ -275,6 +275,7 @@ export const RULES_REVISIONS: { rev: number; note: string }[] = [
|
|||||||
{ rev: 21, note: "Two cards keep their whole promise. LIFESAVER's holder is not eliminated for losing both treasures. FORCE FIELD, after stopping the spell, stands until the end of the opponent's turn: they may not enter its caster's square, nor cast on or past them — on every side, where the card says one." },
|
{ rev: 21, note: "Two cards keep their whole promise. LIFESAVER's holder is not eliminated for losing both treasures. FORCE FIELD, after stopping the spell, stands until the end of the opponent's turn: they may not enter its caster's square, nor cast on or past them — on every side, where the card says one." },
|
||||||
{ rev: 22, note: "TELEPORT ignores the maze's outer edge as it ignores any wall: a teleporter leaving the maze at any square's edge re-enters at the opposite edge on the same line, one space on. Older games crossed the edge only at the lettered openings." },
|
{ rev: 22, note: "TELEPORT ignores the maze's outer edge as it ignores any wall: a teleporter leaving the maze at any square's edge re-enters at the opposite edge on the same line, one space on. Older games crossed the edge only at the lettered openings." },
|
||||||
{ rev: 23, note: "POWER DRAIN drains the number played: the caster gains it whether the blow is BLUNTed or ABSORBed (FAQ: the counter blunts the damage done, not the drain), and a wall drained for its points gives them up too. Older games gave the caster only what the opponent lost, and nothing from a wall." },
|
{ rev: 23, note: "POWER DRAIN drains the number played: the caster gains it whether the blow is BLUNTed or ABSORBed (FAQ: the counter blunts the damage done, not the drain), and a wall drained for its points gives them up too. Older games gave the caster only what the opponent lost, and nothing from a wall." },
|
||||||
|
{ rev: 24, note: "A REFLECTION against a permanent curse afflicts both wizards: WALKING DEAD and IDIOT say so on the card, and SLOW DEATH follows REFLECTION's own rule that a spell works for both parties. Older games left the caster untouched." },
|
||||||
];
|
];
|
||||||
|
|
||||||
export interface GameConfig {
|
export interface GameConfig {
|
||||||
@@ -6610,6 +6611,23 @@ function resolveStack(state: GameState, events: GameEvent[]): void {
|
|||||||
redirected: pipe.redirected,
|
redirected: pipe.redirected,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Rev 24: "If this spell is REFLECTed, both players take 1/2 point of
|
||||||
|
// damage per space moved" (WALKING DEAD); "In case of REFLECTION, both
|
||||||
|
// players are affected" (IDIOT). A permanent curse has no duration for
|
||||||
|
// REFLECTION's split to halve, so the curse is laid on the caster as
|
||||||
|
// well, as if the defender had cast it back.
|
||||||
|
const curseShared = effect?.permanentCurse === true && (state.config.deckRev ?? 1) >= 24 &&
|
||||||
|
!pipe.redirected && !pipe.fullyStopped && !stack.reflectedBase && !stack.trapped && attacker.alive &&
|
||||||
|
stack.counters.some((c) => !c.nullified && c.card.cardId === "reflection");
|
||||||
|
if (effect?.onResolved && curseShared) {
|
||||||
|
effect.onResolved({
|
||||||
|
state, events,
|
||||||
|
attacker: defender, defender: attacker,
|
||||||
|
origin: defender.position,
|
||||||
|
damageDealt: 0, fullyStopped: false, reversed: pipe.reversed, duration: pipe.duration,
|
||||||
|
stack,
|
||||||
|
});
|
||||||
|
}
|
||||||
if (effect?.onResolved && !pipe.redirected) {
|
if (effect?.onResolved && !pipe.redirected) {
|
||||||
effect.onResolved({
|
effect.onResolved({
|
||||||
state,
|
state,
|
||||||
|
|||||||
@@ -1394,3 +1394,28 @@ describe("disease makes the caster the carrier (rev 7)", () => {
|
|||||||
throw new Error("no adjacent step for the return walk");
|
throw new Error("no adjacent step for the return walk");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("a REFLECTION against a permanent curse afflicts both (rev 24)", () => {
|
||||||
|
const cursed = (s: GameState, id: string) => s.sustained.some((e) => e.cardId === "walking-dead" && e.targetId === id);
|
||||||
|
const play = (deckRev: number) => {
|
||||||
|
let { state } = createGame({ playerIds: ["alice", "bob"], seed: 42, sets: ["basic"], deckRev });
|
||||||
|
state = toRound2(state);
|
||||||
|
const { attacker, defender } = faceOff(state);
|
||||||
|
const wd = giveCard(state, attacker, "walking-dead");
|
||||||
|
state.players.find((p) => p.id === defender)!.hand[0] = { instanceId: "reflection#T", cardId: "reflection" };
|
||||||
|
state = must(state, attacker, { type: "cast", instanceId: wd.instanceId, target: { kind: "player", playerId: defender } });
|
||||||
|
state = must(state, defender, { type: "counteract", instanceId: "reflection#T" });
|
||||||
|
state = drain(state);
|
||||||
|
return { state, attacker, defender };
|
||||||
|
};
|
||||||
|
it("lays WALKING DEAD on the caster too", () => {
|
||||||
|
const { state, attacker, defender } = play(24);
|
||||||
|
expect(cursed(state, defender)).toBe(true);
|
||||||
|
expect(cursed(state, attacker)).toBe(true);
|
||||||
|
});
|
||||||
|
it("older games left the caster untouched", () => {
|
||||||
|
const { state, attacker, defender } = play(23);
|
||||||
|
expect(cursed(state, defender)).toBe(true);
|
||||||
|
expect(cursed(state, attacker)).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -245,6 +245,7 @@ export const HOUSE_RULINGS: HouseRuling[] = [
|
|||||||
"A REVERSE against SLOW DEATH or WALKING DEAD turns the whole curse, as the FAQ rules: a point gained per card drawn, half a point per space walked, permanently.",
|
"A REVERSE against SLOW DEATH or WALKING DEAD turns the whole curse, as the FAQ rules: a point gained per card drawn, half a point per space walked, permanently.",
|
||||||
"A FULL REFLECTION returns a permanent curse — SLOW DEATH, WALKING DEAD, IDIOT — onto its caster instead of letting it evaporate.",
|
"A FULL REFLECTION returns a permanent curse — SLOW DEATH, WALKING DEAD, IDIOT — onto its caster instead of letting it evaporate.",
|
||||||
"REFLECTION's returning half is an attack on the caster in its own right, with the caster's own counteraction window: an ABSORB or a BLUNT meets it as it would any blow.",
|
"REFLECTION's returning half is an attack on the caster in its own right, with the caster's own counteraction window: an ABSORB or a BLUNT meets it as it would any blow.",
|
||||||
|
"A REFLECTION against a permanent curse afflicts both wizards. WALKING DEAD and IDIOT say so on the card; SLOW DEATH follows REFLECTION's own rule that a spell works for both parties.",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user