Reversed, Walking Dead heals half a point per step (rules rev 11)
The same FAQ turn as Slow Death's: a REVERSE riding the cast attaches the curse backward, and every second space walked gains the point the bite would have taken. Older ledgers attached it biting and replay so. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015RCWSTnb1KYTPyL4GmhGnF
This commit is contained in:
co-authored by
Claude Fable 5
parent
4430a0def1
commit
b538a0a2ae
@@ -270,10 +270,11 @@ export interface GameConfig {
|
||||
* Rev 10: BUTT-HEAD's ram is MOVEMENT — the charge walks real
|
||||
* corridors on the turn's legal legs (three plus numbers) and spends
|
||||
* them.
|
||||
* Rev 11: a REVERSE against SLOW DEATH turns the whole curse (FAQ) —
|
||||
* the victim gains a point for every card drawn, permanently — and a
|
||||
* FULL REFLECTION returns a permanent curse (SLOW DEATH, WALKING DEAD,
|
||||
* IDIOT) onto its caster instead of letting it evaporate.
|
||||
* Rev 11: a REVERSE against SLOW DEATH or WALKING DEAD turns the whole
|
||||
* curse (FAQ) — a point gained per card drawn, half a point per space
|
||||
* walked, permanently — and a FULL REFLECTION returns a permanent
|
||||
* curse (SLOW DEATH, WALKING DEAD, IDIOT) onto its caster instead of
|
||||
* letting it evaporate.
|
||||
*/
|
||||
deckRev?: number;
|
||||
}
|
||||
@@ -2219,9 +2220,13 @@ const CARD_EFFECTS: Record<string, AttackEffect | NeutralEffect | CounterEffect>
|
||||
baseDamage: () => 0,
|
||||
permanentCurse: true,
|
||||
// "1/2 point of damage for every space moved. This spell is permanent."
|
||||
// Rev 11: REVERSED at cast, the walk heals instead — half a point
|
||||
// gained per space, as permanently. Older games attached it biting.
|
||||
onResolved: (ctx) => {
|
||||
if (ctx.fullyStopped || !ctx.defender.alive) return;
|
||||
attachSustained(ctx.state, ctx.events, "walking-dead", ctx.attacker.id, ctx.defender.id, PERMANENT_TURNS);
|
||||
const reversed = ctx.reversed && (ctx.state.config.deckRev ?? 1) >= 11;
|
||||
attachSustained(ctx.state, ctx.events, "walking-dead", ctx.attacker.id, ctx.defender.id,
|
||||
PERMANENT_TURNS, reversed ? { reversed: 1 } : {});
|
||||
},
|
||||
},
|
||||
disease: {
|
||||
@@ -4312,14 +4317,20 @@ function doMove(prev: GameState, direction: Side, over = false): CommandResult {
|
||||
state.turn.movementUsed++;
|
||||
events.push({ type: "moved", player: p.id, from, to: p.position, direction, via });
|
||||
|
||||
// WALKING DEAD: 1/2 point per space moved (a full point every two steps).
|
||||
// WALKING DEAD: 1/2 point per space moved (a full point every two
|
||||
// steps) — gained instead of bled for a curse REVERSED at its casting.
|
||||
for (const fx of sustainedOn(state, p.id, "walking-dead")) {
|
||||
fx.data.halfSteps = (fx.data.halfSteps ?? 0) + 1;
|
||||
if (fx.data.halfSteps % 2 === 0) {
|
||||
if (fx.data.reversed) {
|
||||
p.life += 1;
|
||||
events.push({ type: "lifeGained", player: p.id, amount: 1, source: "walking dead (reversed)", lifeAfter: p.life });
|
||||
} else {
|
||||
applyDamage(state, events, p, 1, "walking dead", null);
|
||||
checkVictory(state, events);
|
||||
}
|
||||
}
|
||||
}
|
||||
// DISEASE: the carrier infects every other player in a square they enter.
|
||||
if (p.alive && sustainedOn(state, p.id, "disease").length > 0) {
|
||||
for (const other of state.players) {
|
||||
|
||||
@@ -170,6 +170,32 @@ describe("slow death", () => {
|
||||
expect(state.players.find((p) => p.id === defender)!.life).toBe(17);
|
||||
});
|
||||
|
||||
it("a reversed walking dead heals half a point per space walked (rev 11)", () => {
|
||||
let { state } = newGame();
|
||||
state = toRound2(state);
|
||||
const { attacker, defender } = faceOff(state);
|
||||
const wd = giveCard(state, attacker, "walking-dead");
|
||||
giveCard(state, defender, "reverse", "RV", 0);
|
||||
const r = applyCommand(state, attacker, {
|
||||
type: "cast", instanceId: wd.instanceId, target: { kind: "player", playerId: defender },
|
||||
});
|
||||
if (!r.ok) throw new Error(r.error);
|
||||
state = must(r.state, defender, { type: "counteract", instanceId: "reverse#RV" });
|
||||
state = drain(state);
|
||||
expect(sustainedOn(state, defender, "walking-dead").length).toBe(1);
|
||||
|
||||
state = must(state, attacker, { type: "endTurn", draw: 0 });
|
||||
// Two spaces walked: one point gained, not bled.
|
||||
let steps = 0;
|
||||
for (const dir of ["N", "S", "E", "W", "N", "S", "E", "W"] as const) {
|
||||
if (steps >= 2) break;
|
||||
const mv = applyCommand(state, defender, { type: "move", direction: dir });
|
||||
if (mv.ok) { state = mv.state; steps++; }
|
||||
}
|
||||
expect(steps).toBe(2);
|
||||
expect(state.players.find((p) => p.id === defender)!.life).toBe(16);
|
||||
});
|
||||
|
||||
it("a full reflection returns the curse onto its caster (rev 11)", () => {
|
||||
let { state } = newGame();
|
||||
state = toRound2(state);
|
||||
|
||||
Reference in New Issue
Block a user