Commit Graph
6 Commits
Author SHA1 Message Date
Eric WagonerandClaude Fable 5 31a727d02c Refusals persist in the chronicle, not just the fading toast
"When I cast Speed, it doesn't seem to do anything" — the engine had
refused correctly (actions end when you pick up an object) and said
so in a toast, but a toast fades in five seconds and leaves no trace.
Refusals now also land in the chronicle as "— reason —" lines, the
way hotseat games always recorded them, so the answer to "why did
nothing happen" survives long enough to be read.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-16 14:37:21 -04:00
Eric WagonerandClaude Fable 5 df52e9b53a Table talk: chat woven into the chronicle
A say-box under the chronicle sends table talk to the room; messages
land in the event log itself, styled as parchment asides — banter
between the battle lines, the way it happens at a real table. Talk is
seat-authenticated, stripped and capped at 300 chars, rate-limited by
the existing bucket, persisted as chat lines in the room file (the
game replay ignores them; the room keeps its last 500), and replayed
to anyone joining. Async games get unread badges in the lobby ledger
(💬3), cleared by watching the table, and catch-up replays speak the
lines at the step where they were said. Public to the whole room, no
whispers — and no chat in hotseat, where the table talks for itself.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-16 14:24:22 -04:00
Eric WagonerandClaude Fable 5 ed9585aa59 Five fidelity gaps closed: teleport escapes, slime traps, the Big Man
moves like a giant, and the boards are diagram-verified

TELEPORT as a counteraction (official FAQ: "the attack has no chance
of hitting you"): the defender names an escape square within four
spaces, the escape resolves before anything lands, and an ANTI-ANTI
pins their boots to the floor. Additive — no revision gate needed.

FILL SQUARE WITH SLIME holds spells now: an attack cast at the slime
sticks in the gel (leaving the discard pile), springs once at whoever
is inside or next enters, and counteractions against the trapped
blast cannot touch its caster — reflections vanish into the ooze. A
five-point waterbolt washes the slime and its cargo away, and the
waterwall waves clear slime from their path.

BIG MAN, under rules rev 5, finally moves like the card says: he
pushes players and monsters down the corridor ahead of him (stuck or
unpushable occupants block his advance), steps over a pit, tacks, or
killer ooze for two movement points without ever entering the square
(click two cells beyond the hazard), and monsters may not enter his
square. All gated so stored games replay under their own rules.

The boards were never wrong — the rulebook's Set-Up Diagram photo
confirms every pairing the code already had: 2p crossed, 3p stair
with the Aisle Warp arc, 4p/6p straight-across, 5p plus with all four
corner arcs. The stale TODOs are gone, replaced by tests pinning each
letter pair, and relocation's "only opposite board edges connect"
(which discards the aisle warp) is pinned too. Wall of Fire vs
Waterbolt turned out to be implemented and tested all along — its
TODO comment was the only thing wrong.

Also: hotseat saves now request durable storage (iOS evicts
unprotected origins under pressure).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-16 14:17:37 -04:00
Eric WagonerandClaude Fable 5 28bc91c3ac Room codes also dodge orphaned files on disk
makeRoomCode checked only the in-memory map, which covers every live
and restored room — but a file that failed to restore stays on disk
with no map entry, and a new room taking its code would append a
second game into the orphaned file, corrupting both. The generator
now rerolls on disk presence too.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-16 14:02:04 -04:00
Eric WagonerandClaude Fable 5 bed29c4992 Cache headers end the stale-bundle era; finished games rest their buttons
The static server sent no Cache-Control at all, so browsers
heuristically cached index.html — and a stale index.html pins its
user to last deploy's hashed assets no matter how often they reload.
That is how "watch the whole game" could show someone an app without
the feature minutes after it shipped. Hashed assets now cache forever
(immutable); everything else revalidates.

And per playtesting: a finished game offers no actions — isYourTurn
now requires the playing phase, which retires the pick-up/drop/punch/
discard/end-turn row the moment the trophy drops.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-16 13:57:10 -04:00
Eric WagonerandClaude Fable 5 ced4dc5749 Link previews and a wizard in the tab
Sharing the game's URL now unfurls a proper card: Open Graph and
Twitter meta tags with a 1200x630 preview composed from the physical
set's own counter art — WIZ-WAR in tall caps over the parchment, the
tagline in script, a row of wizard, troll, and treasure tokens, and
the fan-project line beneath. The favicon becomes the purple wizard
in his black hat, cropped from the counter sheet; the your-turn
variant wears a red badge, replacing the old lettered SVGs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-16 11:28:22 -04:00