BIG MAN pushes around corners; at a fork the pushed wizard chooses

Eric, a giant on his first turn, could only shove a wizard in a
straight line: the engine shoved in the giant's own direction or
refused. The FAQ says otherwise — "If Big Man pushes someone to an
intersection, then the other player gets to decide which direction to
go." Now a pushed wizard leaves by any open side but the way the giant
came. One open side is taken. Several are theirs to choose: the stride
hangs in a pushPending window like the Ward's, the pushed wizard
answers with pushChoice (a dialog offers the ways; an automaton steps
out of the giant's line), and the stride resumes with the answer — a
blinded giant's roll is not rolled twice.

Rounding a corner was a refusal before, so every game may do it now.
Only the case that used to resolve — straight ahead open — keeps its
old reading in games dealt before rev 15; from rev 15 the pushed
wizard chooses there too. Tests pin the corner, the fork's window and
its refusals, and the older reading; 84 ledgers replay.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
This commit is contained in:
Eric Wagoner
2026-09-04 17:19:34 -04:00
co-authored by Claude Fable 5.1
parent c6913ea1bc
commit e724267b0a
8 changed files with 216 additions and 25 deletions
+21
View File
@@ -1677,6 +1677,25 @@
{/if}
{/if}
{#if view?.pushPending && view.pushPending.pusheeId === view.you}
<div class="scrim attack-scrim" role="alertdialog" aria-label="you are pushed">
<div class="attack-notice">
<div class="attack-title">{view.pushPending.giantId} bears down on you!</div>
<div class="attack-power">
The giant fills the corridor and shoves you ahead of him. The way
forks here — which way do you go?
</div>
<div class="attack-actions">
{#each view.pushPending.exits as d (d)}
<button class="stamp primary" onclick={() => dispatch({ type: "pushChoice", direction: d })}>
{d === "N" ? "North" : d === "S" ? "South" : d === "E" ? "East" : "West"}
</button>
{/each}
</div>
</div>
</div>
{/if}
{#if view?.slowDeathPending && view.slowDeathPending.playerId === view.you}
{@const sdPoints = view.slowDeathPending.points}
{@const sdAbsorb = view.yourHand.find((c) => c.cardId === "absorb")}
@@ -2611,6 +2630,8 @@
</div>
{:else if view.stack}
<div class="slip">Waiting on {view.stack.waitingOn}…</div>
{:else if view.pushPending && view.pushPending.pusheeId !== view.you}
<div class="slip">Waiting on {view.pushPending.pusheeId} to choose which way they are pushed…</div>
{:else if view.outOfTurnWindow?.playerId === view.you}
<div class="slip urgent">Your interruption — pick an attack card and a target, or <button class="stamp tiny" onclick={pass}>waste it</button></div>
{:else if isYourTurn}
+2
View File
@@ -65,6 +65,8 @@ export function humanize(e: GameEvent): string | null {
case "warpOpened": return `The outer wall breaches clean through — a new warp opens across the maze!`;
case "extraTurnGranted": return `${e.player} speeds up — extra turn banked.`;
case "wardWindow": return `The grab hangs in the air — ${e.owner} clutches something…`;
case "pushWindow": return `${e.giant} bears down on ${e.pushee} at a fork — which way will they go?`;
case "pushChosen": return `${e.pushee} breaks ${e.direction === "N" ? "north" : e.direction === "S" ? "south" : e.direction === "E" ? "east" : "west"}.`;
case "treasureTorn": return e.toFloor
? `${e.attacker} TEARS the treasure from ${e.defender}'s arms — it tumbles to the floor!`
: `${e.attacker} TEARS the treasure from ${e.defender}'s arms!`;