From ca9b09c0295932c4d0cfb28d97492af93fd81b3e Mon Sep 17 00:00:00 2001 From: Eric Wagoner Date: Fri, 28 Aug 2026 10:22:59 -0400 Subject: [PATCH] Powerstone blesses a number already played this turn MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On the table the stone and the number land together; digitally the display can come a beat late and the +1 silently vanished. Displaying POWERSTONE now grants the stride retroactively when a number was already played for movement this turn, with a chronicle line so the gain is visible. Pure widening — no rev needed. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_015RCWSTnb1KYTPyL4GmhGnF --- packages/engine/src/game.ts | 11 ++++++++++- packages/web/src/net.svelte.ts | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/engine/src/game.ts b/packages/engine/src/game.ts index adb5ff0..de91415 100644 --- a/packages/engine/src/game.ts +++ b/packages/engine/src/game.ts @@ -715,6 +715,7 @@ export type GameEvent = | { type: "treasureTorn"; attacker: PlayerId; defender: PlayerId; treasureId: string; toFloor: boolean } | { type: "tearResisted"; attacker: PlayerId; defender: PlayerId } | { type: "treasureTearAttempted"; attacker: PlayerId; defender: PlayerId } + | { type: "powerstoneBoost"; player: PlayerId; newAllowance: number } | { type: "treasureDropped"; player: PlayerId; treasureId: string; at: Cell; onHomeOf: PlayerId | null } | { type: "playerEliminated"; player: PlayerId; reason: "killed" | "treasuresLost" } | { type: "cardsDiscarded"; player: PlayerId; cards: CardInstance[] } @@ -1652,7 +1653,15 @@ const CARD_EFFECTS: Record }, // --- Magic stones --------------------------------------------------------- bloodstone: stoneEffect(), - powerstone: stoneEffect(), + // "Add 1 to any NUMBER card played." On the table the stone and the + // number land together; digitally the display may come a beat late, so + // it blesses a number already played for movement this turn. + powerstone: stoneEffect((state, events, caster) => { + if (activePlayer(state).id === caster.id && state.turn.numberPlayedForMovement) { + state.turn.movementAllowance += 1; + events.push({ type: "powerstoneBoost", player: caster.id, newAllowance: state.turn.movementAllowance }); + } + }), shadowstone: stoneEffect(), soulstone: stoneEffect(), speedstone: stoneEffect((state, _events, caster) => { diff --git a/packages/web/src/net.svelte.ts b/packages/web/src/net.svelte.ts index 540724a..6aa93da 100644 --- a/packages/web/src/net.svelte.ts +++ b/packages/web/src/net.svelte.ts @@ -67,6 +67,7 @@ export function humanize(e: GameEvent): string | null { : `${e.attacker} TEARS the treasure from ${e.defender}'s arms!`; case "tearResisted": return `${e.defender} clutches the treasure with white knuckles — ${e.attacker} comes away empty!`; case "treasureTearAttempted": return `${e.attacker} grabs for the treasure in ${e.defender}'s arms!`; + case "powerstoneBoost": return `The powerstone hums over the number already played — ${e.player} gains a stride (${e.newAllowance} total).`; case "trapSprung": return e.cardId === "gift-from-below" ? `${e.player} draws GIFT FROM BELOW — it bites for 3, then deals again!` : `${e.player} walked into an old TRAP! Lose a turn.`;