- TELEPORT OPPONENT exiles a delivery in progress — the thief of the
bot's gold, or any carrier within six of home — to the square farthest
(by walking distance) from the victim's own home; a sealed pocket wins
outright. No LOS needed for the destination, per the card.
- WARP WAND joins the roadwork: a wall slips open for a 4+-step shortcut
when the crossing fits this turn's remaining legs (the wall returns at
end of turn); charges itself with the smallest number on first use.
- ADRENALINE is the finisher: cast when no single attack in hand kills
the target but the top two together do; the attack window now honors
the second swing.
- STRENGTH doubles a thrown dagger or rock exactly when that turns a
wound into a kill.
- EXTEND rides afflictions, doubling the misery's stay.
- MEGA-MONSTER doubles a pet's stride (movement over life) so the
menagerie actually catches people.
All six leave the bottom discard tier.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138A8CjeQRpvzKxuMfz1Bqc
Per the owner's briefing on how these cards are actually played:
- Roadwork on the march: DISPEL CREATION un-creates conjured walls and
filled squares; STONE TO WATER melts walls and stone blocks (cast only
from outside its own wave); CREATE DOOR plus a lock-opener turns a wall
into a doorway; DIMENSIONAL WARP folds a 6+-step detour into one step,
and the bot steps through its tokens when the far side is closer.
- Path denial grows: JAM LOCK seals doors on a threat's road, ILLUSION
WALL stands in for CREATE WALL, the full nuisance shelf (pit, slime,
ooze, rosebush, tacks, dust cloud) joins stone and thornbush, and a
BOOBYTRAP lands mid-path when nothing can reroute the thief.
- Bursts: ADD joins a second number to the march; MAD DASH doubles the
sprint to gold (never while carrying); POWER RUN buys the last spaces
of a winning delivery with blood.
- Breathing room when pressed (worrier, treasure-carrier, or bleeding):
FEAR at three paces, UGLY when they crowd in, BUDDY to pacify the hound.
- AROUND THE CORNER: an enemy one bend out of sight can be attacked; new
bentSightFor mirrors the engine's bentLos from the viewer's knowledge.
- GameView gains createdEdges (public — the table watched them conjured).
All newly playable cards leave the bottom discard tier via USEFUL_NEUTRALS.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138A8CjeQRpvzKxuMfz1Bqc
The end-of-turn shed was eating cards the brain itself casts: BIG MAN,
MIST BODY, SHRINK, LIFESAVER, and STONE DEAD all sat at or below the shed
threshold. But worth is contextual — LIFESAVER is genuinely dead at a
two-seat table, BIG MAN outside the berserker's book — so discardValue now
takes the view and style: STONE DEAD joins the attacks tier outright, the
rest are kept exactly by the wizard who can play them.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138A8CjeQRpvzKxuMfz1Bqc
Pass Through Wall joins the march: the bot banks a crossing when stepping
through one wall beats the walk by 4+ steps (or no road exists), walks to
the chosen wall, and spends the charge stepping through. passWallCharges
is now in PlayerPublicView — the cast is public at a physical table.
Path denial for guardGold tiers: when an enemy carries the bot's treasure
toward home, or closes on its gold on the floor, the bot reconstructs the
threat's shortest path and prices every corridor line and empty square on
it; CREATE WALL, FILL SQUARE WITH STONE, or THORNBUSH lands wherever the
detour costs the enemy 3+ steps, legality mirrored from the engine
(sighted, empty, off homes and warp tokens).
All five cards leave the bottom discard tier (2 -> 6).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138A8CjeQRpvzKxuMfz1Bqc
Rules rev 24: a waterwall wave that finds a victim dist cells from its
source has only range-dist spaces of push left — a range-2 wave throws its
adjacent victim two spaces but a victim at its far edge only one, and
spent force never converts into crush damage. Applies to WATERWALL and
both STONE TO WATER waves; older revisions keep the flat full-range wash
so stored games replay unchanged.
Automatons now use DESTROY WALL on the march: two BFS distance maps (from
the bot, from its objectives) price every visible wall by the shortcut its
removal opens; the bot blasts when it saves 4+ steps of walking — or when
no road exists at all — never standing beside the blast unless trapped
and healthy. The card also leaves the shed pile: discardValue 2 -> 6.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138A8CjeQRpvzKxuMfz1Bqc
The cast validation demands LOS to a stone block, but the dimming aid lit
every stone square on the map — including ones the caster cannot see. Now
only sighted blocks light; and since the card equally targets stone walls
(edges the cell-shadow cannot express), no sighted block means no shadow
at all rather than a maze dimmed away from its true targets.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138A8CjeQRpvzKxuMfz1Bqc
The 5e-inherited card database carried 85 rows tagged expansion2; 6e has
only the basic deck and Expansion Set #1, and buildDeck never dealt them.
They kept leaking into things that cite the database (rulebook text, the
IDIOT aid list), so the rows are gone and CardSet no longer names the set.
Other editions can reintroduce their own sets when they arrive.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138A8CjeQRpvzKxuMfz1Bqc
vampire, werewolf, flight, and exploding-door are expansion2 rows in the
card database — a set this edition does not have; buildDeck never deals
them. Listing them as idiot-permitted aids cited cards that cannot occur.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138A8CjeQRpvzKxuMfz1Bqc
Rules rev 23 — IDIOT, per the card and FAQ:
- No handling items: pick up / drop of treasures and objects refused
(dropping was the exploit: capturing a stolen treasure on your own home,
or dropping your own treasure underfoot for an instant cure)
- No punching, no thrown dagger / large rock (attacks on players)
- No effect on a victim already carrying one of their own treasures
Ungated (permissive): counteractions are now castable while idiotized (the
one thing the card expressly allows — the gate wrongly blocked them), and
goal-aiding spells (IDIOT_AIDS: destroy-wall, teleport, mad-dash, ...) per
the FAQ's 'you could, however, destroy a wall'.
Sight tracing: while an LOS attack sits on the stack, the board draws the
line it traveled — straight when direct, leg by leg through both warp
mouths (with pulsing rings) when the maze's wraparound carried it. Engine
traceSight/traceSightFor/stackSightTrace; overlay in Board.svelte; shown
live and in replays. Verified against H3PC's cross-board Idiot cast.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138A8CjeQRpvzKxuMfz1Bqc
A democratic monster touching its own creator opens a stack where one
player wears both hats, and doPass matched the attacker first: every
pass "bounced the exchange to the defender" — the same wizard —
forever. Room 928D livelocked there at seq 83; once the boot kick
revived its pump, the automaton politely passed 389 times. At rev 22
a self-stack pass RESOLVES (the claw lands, the game moves on);
older ledgers hold their recorded bounces and replay so. 928D itself
was repaired by truncating the no-op run and lifting it to rev 22,
verified clean and unstuck on a copy before installation.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The bot pump only ran when a command or join arrived, so a server
restart landing mid-bot-turn left the restored room waiting forever
for a human to poke it — room 928D sat exactly there, its automaton
holding a perfectly answerable stack. Boot now kicks the pump for
every restored still-running room, two seconds after restore.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two numbers for movement work by playing them one after another, the
Add spending itself on the second — but clicking the ADD card itself,
the natural first instinct, showed nothing but a cancel button. It
now says how the ride works; a second number without an Add in hand
says what is missing instead of offering a doomed button; and the
button's label says "spends your Add" at the moment it does.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
DESTROY WALL's "anyone in either square next to the wall takes 4
points" swept only wizards; a troll leaned on the falling masonry
untouched. The expansion sheet is explicit — "if a card specifies
'Opponent' or 'Anyone' as a target, this includes Monsters" — so the
collapse now crushes creatures in both squares, at the rim breach's
far side too. Earlier ledgers keep their charmed monsters.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The rules tab carried a paraphrase and the FAQ; now the court of
final appeal sits between them — the full base rulebook text (the
5th-edition wording the 6th shipped with) and the Expansion Set 1
sections, word for word from the designer's own wizwar.com, with
copyright and provenance shown rather than hidden. This edition has
no Expansion 2 — Artifacts and Transformations do not exist here and
are not included. The text moves out of research/ into real source.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The rulebook (Cards And Actions That Change The Map): a CREATE WALL
or DESTROY WALL alteration on a junction between sectors rolls a
50-50 when "some other moron" rotates one of them — 1-2 stays with
the standing sector, 3-4 travels with the moving one, per the book's
own low/high convention. Both rotation and relocation roll (the same
seam tears either way), demolished holes roll alongside conjured
walls, the pips land loud in the chronicle, and a traveling edge
rides anchored to its in-sector cell. Rev-gated: the roll consumes
dice that stored games never spent.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Destroying a wall on the board's outer edge used to leave a one-sided
hole into nothing. The table's physics prevail: the outer rim wraps,
so the breach goes clean through — the opposite perimeter wall in the
same row or column crumbles too (collapse damage and all), and a new
warp pair opens between the two edges, shimmering at both mouths.
Rev-gated: stored games hold one-sided breaches and replay so. Sector
moves recompute the wraparounds and forget improvised openings, as
the maze's own reshaping always has.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Create Wall refused the board-edge openings: no far cell, so "walls
must be created between two spaces". But bricking over a lettered
opening is a classic play, and the far space is the tunnel itself.
A warp mouth now counts as wallable — with the wall raised at BOTH
mouths, since a tunnel has one passage: no walking in from the far
board, no warp sight through a sealed pair, and tearing down either
end reopens both. The client grows edge hitboxes at the perimeter
mouths so the line is clickable at all.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
GIFT FROM BELOW bit for three in the middle of end-of-turn noise and
nobody saw it — not live, not in the replay, where its log line even
claimed "lose a turn" (the other trap's fate). The trapSprung event
now names its card; drawing a trap YOURSELF raises the full modal —
the card, what it did, "Curse the deck" — and the chronicle tells
each trap's true consequence. The amplify narration was already
fixed; replays re-derive events, so both now show in old games'
reels too.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Room 9BBV's "impossible" 14-point powerthrust was an archmage playing
correctly: 2 + 5, AMPLIFIED. The engine's math was honest and its
narration was not — neither the log line nor the attack modal
mentioned the amplify, so a legal kill read as a bug. The spellCast
event now carries its amplify count, the chronicle says "casts
Powerthrust with a 5, AMPLIFIED, at Kestrel", and the modal's power
line shows "powered by a 5 — AMPLIFIED ×2" while there is still time
to respect it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every creature is born with attackUsed spent — the right way to say
"cannot attack the turn created" for monsters whose flag refreshes
next turn. But the democratic monster's flag budgets its ROUND, so a
mid-round summon arrived pre-spent and bumped harmlessly until the
round rolled over. Creation-turn pacifism now rides justCreated
alone for the monster (checked at the touch), and its round-claw
starts live — folded into rev 18 with the boundary refresh.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Its one-attack-per-round refreshed inside beginTurnFor when the turn
index matched the roll-off winner's seat — and only the living begin
turns, so once that wizard fell the claw never refreshed again: one
attack, then a lifetime of harmless bumping. The refresh now lives at
the true round boundary in the turn-advance loop, which passes dead
seats without skipping the count. Earlier ledgers keep their gummed
monster and replay so.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The relocation flourish corrected its coordinates against the view —
but effects are mapped when the events arrive, one message before
the new state, so the correction read the PRE-move board and the
ghost slid between unrelated squares. The sectorRelocated event now
carries its origins in final coordinates, computed after the maze
renormalizes, and the flourish trusts the event alone.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Stone to Water's wave (and every waterwall collapse) washed wizards
back and crushed them against the maze — while a skeleton in the
same water stood dry. The wave only knew creatures well enough to
drown fire imps. From rev 17 it carries them all: washed back along
the surge, one point of crush per space the maze refuses, fire imps
still destroyed outright. Earlier ledgers keep their dry monsters
and replay so.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
pickUpTreasure grabbed whichever treasure the list offered first —
with two on a square, no choice and sometimes the wrong one. The
command now takes an optional treasureId (absent in every stored
ledger, so old replays keep their old grab), and when the square
holds more than one, the button asks "whose?" before dispatching.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
SWAP HOME BASES traded homes correctly but borrowed the
positionsSwapped event, so the chronicle claimed the wizards
themselves changed places. It now speaks its own event — "swap home
bases — the maze's loyalties shift!" — and both hearths shimmer as
their allegiance changes.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Player movement asked the full question of a door — removed, keyed
this turn, or held — while creature movement only saw "door" and
refused, so a skeleton balked at a doorway its master had unlocked
for good. One doorIsOpen() now answers for both, and an open doorway
costs a wraith none of its wall passes.
And the interruption window earns the modal it deserved: "The maze
holds its breath" — the card shown, the instruction plain, dismissed
with "Seize it". No more hunting the rail for a slip while time
stands parted.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
OPPORTUNITY FIRE and INTERRUPT bought a moment the client would not
honor: every selection and targeting gate asked "is it your turn?",
and mid-interruption it is not — so the window's holder could click
attack cards into silence while the engine sat ready to accept the
cast. A window is now yourMoment: hand selection, player/creature/
cell/edge targeting, and the dimming aid all open exactly as on your
own turn, and the slip says what to do with it ("pick an attack card
and a target") instead of the cryptic "cast now".
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A believed ILLUSIONARY ATTACK, the goat's ram, and the hurled
treasure all deal their damage inside the attack's own resolution
hook — past the pipeline where the empathy mirror lived, so a linked
caster walked away unbloodied. One resolvedBlow helper now carries
the mirror to all three: "any attack done in ANY form" means these
too. Rev-gated: proactive empathy predates this, so stored ledgers
may hold unmirrored blows and replay them as struck.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
An automaton's ILLUSIONARY ATTACK arrived as a mystery: the modal
showed only the illusion card, never the spell being faked — though
the stack has always carried it face-up. The defender now sees both
cards side by side, the caption names the fake ("an ILLUSIONARY
Fireball — it bites only if believed"), and the hint bar says which
spell to weigh a counter against.
And EMPATHY — corner: COUNTERACTION — was refused at the door like
INVISIBLE before it, while the automatons' own counter ladder had
been reaching for it and silently failing into the fallback all
along. It now raises mid-stack: the blow lands on both wizards, the
link lingers for its NUMBER card's turns, and ANTI-ANTI severs it
cleanly (empathy is no escape). The number-riding-a-counter idiom is
one shared helper now. Permissive both ways: no stored ledger
contains either play, so no rev gate.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
An automaton answered NO SPELL with an Absorb — which "has no effect
on duration-based spells." Afflictions sat outside the price table
and drew the phantom two-point default, tripping the point-soaking
rungs. An affliction's weight is now its duration, and the two
counters that touch only points — ABSORB and REVERSE — stand aside
for it, leaving the ones that genuinely bite durations: full shield,
remove curse, blunt, reflection, shieldstone numbers. Pinned: under
NO SPELL with both in hand, the bot blunts, never absorbs.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The table holds doors open to cast back through them at pursuers;
our held door opened for feet but not for eyes. From rev 15 a held
door is an open doorway to sight — casting at players, creatures,
and squares sees through it, the client's dimming aid and the
automatons alike (they share sightedCellsFor). REMOVE LOCK's "still
considered to block L.O.S." stands: that speaks of a CLOSED door,
and an unheld unlocked door still blocks. Rev-gated because rev-14
ledgers may already contain holds and must replay blind.
Pinned three ways: the holder blasts a pursuer through the held
doorway; an unheld unlocked door still blocks; rev 14 stays blind.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
MASTER KEY and PICK LOCK each read: "You may 'hold the door open' for
others, if you wish" — and the engine always slammed it at end of
turn. Now the cast takes a hold param: the door stays unlocked past
the turn, for anyone, as long as its holder stands adjacent and
alive. A step away, a shove, a teleport, or a killing blow lets it
swing shut — swept after every command, since anything can move a
wizard. New state, new param: no old ledger contains either, so no
rev gate is needed.
The client offers a "hold the door open" checkbox when either card is
selected; a held door shows pale with a green jamb ("held open by a
standing wizard"), and the chronicle records the holding and the
shutting. Pinned: a held door outlives the turn and admits the other
wizard; walking away releases it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Scoped to everything since the last pass (3308850). Three blind
reviews, every finding verified before touching anything.
Confirmed and fixed: two identical comment-splitting insertions left
doc comments orphaned from their fields (net and local alike); a
51-line CSS fossil of the pre-extraction inline effects survived in
Board.svelte; the rev-13 miss-roll test asserted tautologies while
its comment claimed a check the code never made — it now proves the
die was consumed, and the skeleton is no longer returned as trollId;
the sprite registry's `as never` silently disabled the completeness
its annotation advertised (now a mapped type, one cast at the
dispatch seam); a dead ternary guarded a union that doesn't exist;
Bolt carried a duplicate .fork rule from a color iteration; fxTtl
contradicted three sprites' real animation lengths; the permanence
sentinel was reinvented as a magic 9000 (the engine now exports
isPermanentDuration); CELL was declared thrice (fx.ts now imports
it); App and Replay ran two divergent fx schedulers (one scheduleFx
now, cancellable — stale flourishes can no longer fire after leaving
a game); TokenArt retried missing files forever; the anti-anti
escape guards merge with the gate asymmetry explained; wall-of-fire's
rev-12 carve-out is marked; overLimit ignored a displayed BRAINSTONE
(bots over-discarded by two); botRemark's header mis-stated its own
branches; deliverGold fired on any drop, not a home-base delivery;
escape and win banter never fired from the steps that carry them.
Rejected: "as a human would" (house voice); FxGallery's dev-harness
framing (trimmed one plea, kept the facts).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Clicking a board token now shows the thing itself, enlarged, above
its card in the peek modal — whichever art is active, photograph or
SVG. The art tables move to art.ts so the board renderer and the
modal share one source.
First cut overlapped: the card scales 2.1x out of its layout box, so
flow neighbors sat underneath its visual footprint (the note had been
compensating with a 6.8rem margin hack). A card-stage now reserves
the card's TRUE visual size; token above, note below, nothing buried.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
An svg referenced through an <image> element is rasterized once at
its layout size in user units — about 29 pixels for a wizard — and
scales as a blurry bitmap thereafter, defeating the entire point of
vector art. TokenArt.svelte now fetches each file once, namespaces
its ids (45 tokens' worth of filter and pattern defs share one
document), and inlines it as a nested <svg>: live vector at any
zoom, verified crisp at 3x device scale. PNG art keeps the <image>
path untouched, and the token style family goes :global to reach the
component's elements.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The symlink into research/ becomes real files: public/tokens-svg now
owns the hand-drawn set, edited in place and served as-is by the dev
server. The research folder is scaffolding with a demolition date,
not a place for shipped assets to live.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The hand-drawn SVG token set wires in behind deliberately
undocumented query params — svgPlayers, svgCreatures, svgTerrain,
svgObjects, each =true — swapping that category's art everywhere it
draws: board tokens, lobby standees, roster. public/tokens-svg
symlinks research/tokens-svg, so under the dev server an edit to the
source art shows on the next refresh, and the production build copies
real files through the link. Nobody finds the door unless handed the
key; the photographed set remains the face of the game.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Projectiles flew cell-center to cell-center, launching from the
caster's feet and landing under the target's chin — tokens sit high
in their squares and fan sideways when crowded. Every travelling
effect (fireball, waterbolt, bolt, streak, and the reflection's
return flight) now resolves token anchors that mirror the board's
exact positioning, fan-out included: caster's center to target's
center, wizard or creature. Spots with no token to aim at fall back
to sensible cell points, and wash/knockback streaks end on the
carried wizard wherever they fanned to.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Tokens jumped square to square, which made the portal shimmer look
late — the wizard had already re-appeared before the threshold lit.
Wizards and creatures are now identity-keyed movers positioned by a
transform, so the DOM node survives a move and a single step glides
(260ms). Anything farther than a step — teleports, warps, drags,
sector moves — snaps as before, because sliding a wizard across the
whole maze would tell a false story; the warp's instant jump beside
its threshold shimmer is now the point, not the bug. Replays glide
the same way, and reduced motion stills it all.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The transmutation fired no flourish: its event carried no coordinates
for the wall case and the mapper knew neither it nor the wave it
raises. The event now carries its edge; the burst splashes both sides
of the vanished wall (or the freed square, for a block), and every
wizard the collapsing wave carries leaves a wash streak — which also
gives the plain WATERWALL's wave its motion for free.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Winning raised the modal on the same frame the fireworks lit,
covering them. The modal now waits behind the curtain for 2.4
seconds — three volleys over the winner's home, seen — then takes
the stage.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The bolt deepens to saturated gold over a dark amber glow; the splash
throws a wider crown of five droplets over a broader pool; the
fireworks lose their protractor — uneven angles, lengths, sizes, and
staggered timing, as a real burst has; the portal-cell's void gains
turning swirl arms so the dark center reads as motion, not blur; the
streak narrows and softens so its peak frame no longer resembles a
drawn white line.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The whiff darkens to slate and sweeps longer; the portal-cell opens
a dark void behind its collapsing rings — an opening in space, not a
selected square; the tacks grow half again and recoil harder; the
streak's reveal slows so the travel reads even in a sampled frame;
dust lifts its contrast a step without turning heavy. The sector
ghosts stay board-machinery on purpose — the reviewer allowed it,
and the maze grinding IS an operation, not a spell.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The outside review's diagnosis was right — the weak sprites had one
element doing one motion. Now each tells its story: the whiff is
three air streaks sweeping past a dodger with a wobble; the hit is a
contact flash, a compressed ring punched outward, and flying debris;
the streak's head visibly travels, drawing a tapered trail that
collapses into the destination; the sparkle snaps white-hot between
counter-rotating glints and sheds motes; the tacks are drawn
silhouettes now, points up as a tack on the floor menaces, hopping in
sequence; the claw slashes reveal one by one along their length with
a bright leading edge while the whole strike rakes sideways.
The sector ghosts keep their dashed frames but earn motion arcs,
directional chevrons, corner dust, and a grinding shudder as they
settle. The portal opens wide, ripples along its length, and pinches
shut; cell mouths collapse rings of energy inward. The thornbush
springs actual branches with thorn spurs. The slime is an asymmetric
blob that grips, with elastic strands snapping toward the caught.
Dust gains contrast, varied grain, and blows perpendicular to the
wall that shed it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Its hole was a near-black disc that sat on the parchment like spilled
ink. Now an earthen gradient ellipse, offset toward the far wall,
with the far lip catching the light — a hole you look INTO.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Eric's fireball lands as the house style — layered construction,
gradient core, glow halo, a directional tail riding rotate="auto" —
with its defs scoped per instance via $props.id(), so simultaneous
fireballs cannot steal each other's gradients. The rest of the
catalog is rebuilt in its image: the waterbolt becomes its cold
sibling (spray tail, no turbulence — one heavy filter stack is
enough); lightning grows a glowing core and branching forks; the
burst blooms through a fire gradient with a shockwave and flying
embers; the splash throws a crown of droplets; the shield raises a
gradient dome with a rim strike; the pow star flashes white and
radiates speed dashes; claws leave tapered gashes; the absorbed card
spirals in along a pull ring; the soul is a proper little ghost with
eyes, swaying as it rises; fireworks ride colored trails; Chaos
catches card slips in its vortex; the pit opens a gradient hole that
swallows a faller; ooze splats and flings blobs; the thornbush sheds
leaves; slime closes over and pops bubbles; masonry dust goes soft
with falling grit. Whiff, tacks, portal, and the sector ghosts keep
their simpler forms on purpose — restraint is part of the style.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The effects move out of Board.svelte into src/fx-sprites/ — one
component per flourish, markup and animation CSS together, so editing
the fireball means opening Fireball.svelte and nothing else. A
registry (index.ts) maps kind to sprite; Board renders through it.
The event mapping stays in fx.ts.
And a viewer: /?fx opens the Flourish Workshop — every sprite on a
labeled parchment tile, replaying on a 2.2-second beat. Under the dev
server, editing any sprite file hot-reloads the gallery mid-loop.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Punching was mostly deck arithmetic — nineteen castable damage cards
in a 196-card deck — but three leaks made it worse. The march was
burning the biggest NUMBER card on long walks, starving waterbolts
and lightning; the biggest number is now reserved whenever an attack
in hand wants it. Heave-Ho, priced for defense, was being cast
without a treasure to throw (refused, turn stumbled) — now never
cast. Illusionary Attack was cast without naming a spell to fake —
now it fakes a fireball, the best-selling lie. And STONE DEAD joins
the arsenal against anyone flashing displayed stones: number times
the visible count, cast when the arithmetic beats the alternatives.
Measured across thirty berserker mirrors: attack casts up a quarter,
the tier handicap sharper (25-5), no stalls.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Green rings at the traveler's squares become a portal curtain: the
opening LINE itself shimmers on both boards — resolved from the warp
table via the step's direction — in iridescent cyan over a soft
violet breath, dashes drifting like light through a veil. Dimensional
warp tokens, whose mouths are whole squares, wrap in the same veil
around the square instead.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The showstopper: sectors visibly move — a dashed parchment ghost
rotates through its quarter-turn or slides the whole way to its new
ground (corrected for rev-11 renormalization, since the event records
pre-shift origins and the view holds the truth). Death sends a small
soul drifting up from the token; victory bursts fireworks over the
winner's home, three volleys; CHAOS spins a triple spiral over the
whole maze and stands alone in its batch.
And the slapstick tier: knockbacks, shoves, drags, and pit-jumps
leave a motion streak; falling in a pit swallows dark with dust;
ooze gets a wobbling pratfall ellipse; tacks sting in three hopping
asterisks; thornbush snaps green; slime sinks its ring; a successful
pit climb puffs dust.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The reflected spell turns in the air and flies home wearing its own
colors, striking its caster with the hit it meant for someone else.
Warp travel glows green at both mouths. Punches land as a proper
burst star; creature blows rake three red gashes; an absorbed spell
is a little card swallowed into the absorber, spinning as it shrinks.
And ongoing spells now wear their look between events: firewalls lick
and glow, the invisible and misted breathe at a fraction of opacity,
Medusa's victims gray to stone, and the webbed wear their webs. The
pulses stop under reduced motion; the informative looks stay.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replay steps carry the same events the live table saw, so the spells
flare on catch-up reels and whole-game replays alike — retroactively:
stored games re-derive their events on replay, so every fireball ever
thrown bursts again. Step changes clear pending effects so scrubbing
backward does not smear.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A cosmetic effects layer on the board svg, fed by the same event
stream that writes the log. Fireballs streak and burst; waterbolts
arc and splash; lightning jags and flickers; teleports shimmer at
both ends; walls rise and fall in dust; stopped attacks flash a
golden shield; hits ring red; misses whiff; other attack spells
sparkle at the caster. Successive visuals from one command stagger by
a beat, everything self-expires, reduced-motion hides the layer
whole, and nothing here touches game state — the effects are mapped
from events in fx.ts and drawn in Board.svelte, online and hotseat
alike.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
BOT_LINES leaves the server internals for banter.ts, keyed by
semantic trigger instead of raw event type, so editing the clockwork's
voice takes no knowledge of the event stream. The repertoire grows
from fourteen lines to fifty across twelve occasions — grabbing and
delivering gold, dealing and taking pain, killing and dying,
summoning, walling, escaping, springing traps, dodging, and winning.
Bots also now speak when things happen TO them: the actor remarks on
its deeds, bystanders on their suffering — a berserker taking a hit
answers "I FELT THAT. DO IT AGAIN." even on your turn. Still at most
one voice per step, still half the time, menace over chatter.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two ways out of the game, one cleanup. A wizard killed by damage took
their monsters, sustained spells, and armed ambushes with them; a
wizard eliminated by treasure loss left everything standing — a fire
imp scorching for a dead master, a Medusa still gazing at a corpse.
Both paths now share one sweep, gated at rev 14 so stored games keep
their orphans acting as recorded.
Also: Lifesaver lasts until used, carried as a near-billion-turn
sentinel — which the scoresheet printed. Durations that mean forever
no longer show a number.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Once a gap opened — a backgrounded tab during the bots' turns was
enough — the mark-seen condition (exactly one move behind) could
never hold again, so the banner grew with every move a player watched
happen in front of them. Now only the first state after arriving (or
reconnecting) announces a gap; while present and visible, play marks
itself seen, an announced gap stays frozen until watched or skipped,
and a hidden tab still accumulates its gap honestly.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Rejoining a room replays the whole chronicle through the same events
channel that carries live play, so the opening roll-off modal fired
on every return. The replayed chronicle is now flagged, and one-time
fanfare stays quiet on it — the log still rebuilds in full.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two archmages idled turn after turn: hands clogged with situational
neutrals, and doEndTurn caps the draw by the room left, so a full
hand never refreshed. Nothing to cast, nothing to draw, nothing done.
The brain now sheds dead weight before ending the turn — only cards
it has no play for; good counters and attacks stay hoarded — so the
draw always has room. The trick is repertoire, so it is tier-gated:
adepts and archmages churn, the apprentice hoards like the novice it
is. Measured across forty berserker mirrors that sharpened the
handicap from two-to-one to three-to-one with zero stalled games.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
An opponent's wraith refused to be dispelled — the engine was willing
all along (any controller's creature, sight required), but creature
clicks never routed cell-target spells, so the cast never left the
client. Clicking a creature with a cell spell selected now lands on
its square. The dimming aid told the same lie twice over: it lit
every created square including ones out of sight (a caster's own
thornbush beyond the walls) and never lit creatures at all. It now
mirrors the engine — anything created, whoever made it, in sight.
And "click a wall line" stops standing in for every edge card: each
now says what the click actually is — a locked door for the keys, a
corridor line for the fire, the creation itself for the dispel — and
attacks no longer show two hints for one wall.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The four placements accumulated invisibly until the last click cast
the spell. Each token now marks its square as it is placed, numbered
in click order — the 1 is the real trap — and tapping a placed token
lifts it again, since the four must be distinct squares.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
One tap cast the jump, and a player reaching for click-per-square
movement spent their teleport on the adjacent floor. Now the first
tap only marks the destination (the familiar pulsing square), and the
jump commits on a second tap of the same square or the hint-bar
button — with the hint spelling out the four-square, walls-ignored
range. The escape teleport gets the same two-tap arming; a counter
wasted on a misclick is a counter wasted.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
First wizard was never random: createGame has always rolled a die
per player from the seed, re-rolling ties, and the gameStarted event
carried every pip — straight into a log line that said only "X goes
first." Now the table sees the ceremony: a dice modal as the boards
flip, one row per wizard, the trophy on the high roll, a note when
tied wizards rolled again — in online games and hotseat alike. The
chronicle line keeps the full roll-off too. Pure presentation; the
dice were always honest.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
An automaton answered DROP OBJECT with an Absorb, then a Blunt —
two counters drained against a spell that carries no points. The
brain's price table listed only the classic damage spells; anything
unknown was guessed at 2 points, which tripped every damage-counter
rung. Utility attacks (dropping, dragging, swapping, peeking) now
route past those rungs entirely: the bot passes, or spends a full
stop when the effect actually threatens something — a shield for the
treasure it carries, a worrier's refusal to be dragged. Stone Dead,
Butt Head, Heave-Ho, and Illusionary Attack join the price table
while the hood is up.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A lock removed, a lock jammed, and a door picked open for the turn
all looked exactly like a locked door. Now the door itself tells:
pale wood for a lock gone for good, near-black for one jammed shut,
pale with a dashed jamb for a door standing open until end of turn —
each with a hover title saying so in words.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
"The creature shares your square — there is nowhere to hide" appeared
on no card and in no rulebook. Neither did the convention beneath it:
the engine skipped INVISIBLE and SHRINK miss rolls for creature blows
on the theory that a monster in your square has nothing to aim. The
cards say otherwise — SHRINK reduces the chance to hit "in any
attack", and INVISIBLE's D4 carves out no exception for monsters.
From rev 13, creature blows roll the same dice as every other attack
(1 finds the unseen; 1-2 find the tiny), INVISIBLE may be counter-
cast against a creature's blow, and the automatons will do so. The
rolls consume RNG, so earlier games keep their certainty and replay
without them — the refusal survives only there, reworded to blame the
revision instead of inventing a rule.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
INVISIBLE's corner reads NEUTRAL/COUNTERACTION, and ANTI-ANTI's own
face names it an escape — yet the engine refused it at the door. Now
it counters: the vanishing goes up mid-stack (duration from a NUMBER
card riding the counteract command), the attacker's 1-in-4 hit roll
happens at resolution, the spell lingers after the exchange, and
ANTI-ANTI cannot pin it. WATERWALL — "Acts as counteraction to
FIREBALL" — now mirrors WALL OF FIRE's waterbolt-stopping role and
counts as a total stop. WALL OF FIRE itself joins the total-stop set
at rev 12 only: stored rev-10/11 games bounced after it and replay so.
While responding, tapping a number card holds it to ride the next
counter (unless a displayed Shieldstone makes the number itself the
counteraction, as before). The automatons learn the trick too: vanish
when the blow is heavy and the shields are spent, and never waste
ANTI-ANTI against an escape.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
"Doubles the existing life-points OR movement rate" — the engine
always took the OR's left side because the client never asked. With
Mega-Monster selected, the hint bar now offers the choice (hit points
lit by default), and the pick rides the cast as params.boost — its
own field, freeing params.cardId for the name-a-card spells it
belongs to. Both halves of the OR are pinned in the creature suite.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The lobby's automaton row was a no-wrap inline-flex: at card width the
"seat a" label collapsed to a vertical sliver and the MYSTERY button
ran clean off the paper. The row now wraps centered within the card
and the label holds one line.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Scoped to everything since the last pass (695307d). The residue of
fast iteration, removed: a reduced-motion media query that had
swallowed a full copy of the .faq-seal rules; doc comments orphaned
from their functions by inserted methods; the FAQ scrape's seams
(section headings run into ruling bodies under the wrong topics, a
next-page heading shipped as a ruling, an amputated "h", and rulings
filed under alphabetically-nearest strangers — Large Rock/Dagger now
lives on those cards; Book of Spells and Torquemada describe no card
in this set and are gone); the write-only aisle flag left behind by
the reverted rev 7; a linter-silenced dead destructure; a duplicated
median lookup; dead casts; and the fallback path that ignored the
apprentice's one-card draw.
Tests now typecheck (tsconfig includes test/), which surfaced the
missing type imports and a drifted creature literal hiding under an
as-cast. Also: a no-op self-assignment, mid-file imports hoisted, a
dynamic-import habit made static, a hedge comment replaced with a
loud setup failure, the fallback-retries-itself dead rung removed
from both bot drivers, and the twin peek scrims merged.
Deliberately kept: the TIERS lookup guard (ledger JSON is untrusted),
the wand-cost stanzas (they differ on the power-attack trade — a
rules question, not a dedup), and rollDie's coexistence with rollD4
(migrating changes visible logs; future work).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Relocate Sector could never land a sector west or north of the origin
— placements the physical game allows by simply sliding the whole map
across the table. The coordinate grid still cannot go negative, but
now it does not need to: a sector may land at negative coordinates
and the whole maze renormalizes, zero-anchoring on both axes (which
also pulls the maze snug when the origin corner is vacated, instead
of leaving a blank band). The client offers the new landings as ghost
slots on every side, verified slot-for-slot against engine truth.
The move also closes a real gap: remapState never carried creatures,
boobytrap tokens, glue, open safes, or dimensional warp tokens when a
sector relocated or rotated — they were left hovering at their old
coordinates. Sectors now carry everything standing on them. Both
changes ride rules rev 11; older ledgers replay their flaws intact,
as replay determinism demands.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The card asked for a destination click that did not exist: a sector
relocates onto an EMPTY 5x5 slot, and empty slots have no floor to
click — the board only rendered cells that are part of the maze. Now
lifting a sector outlines the whole 5x5 (not one square) and dashed
green landings appear beyond the maze edge, one per legal slot; the
svg canvas grows to hold them. Clicking a landing completes the cast.
The landings mirror the engine's own relocateSector law — on the
5-grid, non-negative, vacant, every sector still adjacent to at least
one other — verified slot-for-slot against engine ground truth across
2p and 4p boards. Clicking the maze again re-picks the sector, and a
sector with nowhere legal to go says so in the hint bar.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Slow Death, countered with Force Field — and the battle modal popped
right back up as if nothing had happened, goading a second counter
out of a hand that had already won the exchange. The engine was
bouncing every attacker's pass back to the defender so counters could
stack; correct for partial stops (Blunt, Absorb, Reflection numbers),
senseless past a total one. Under rules rev 10, when a Full Shield,
Force Field, Teleport escape, Full Reflection, or Reverse stands
unnullified, the attacker's declined answer resolves the stack on the
spot. Older ledgers keep the bounce and replay unchanged.
And when the exchange legitimately returns — a partial counter
standing, or a shield broken by Anti-Anti — the modal now says so:
"Your Blunt stands — only what slips past it will land," or "Your
Full Shield was nullified — the attack comes on unchecked," instead
of replaying the fanfare of a fresh, unanswered attack.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Three cards sat wrongly in the creation bucket of eligibleCellsFor,
so the targeting dim demanded sighted empty squares the engine never
asks for. Boobytrap tokens go anywhere on the board but solid stone —
no sight required; a trap you can see coming is a poor trap. Glue and
the safe were worse than restricted: inverted. Both seize a square
that HOLDS a loose object or treasure, exactly the squares the empty-
square rule dimmed out. Each now has its own branch mirroring the
engine's actual checks, pinned by tests.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Safari collapsed the replay board to nothing: an svg with only a
viewBox has no intrinsic size there, and inside the replay's
max-height flex column WebKit sized it 0x0 while Chrome inferred the
ratio and filled the frame. Explicit width/height attributes (doubled,
so the CSS max-* caps still govern the display size) give every engine
the same answer — verified 560x560 in both WebKit and Chromium, with
the main board-zone rendering unchanged.
Commanding your own creature no longer opens the centered card peek —
a modal squarely blocks the squares you are about to march it across.
The card now docks in the paper rail with its live stats, the one
place a card enlarges outside the center of the table. Enemy creatures
and idle peeks keep the modal; they ask nothing of the board.
And once an object is pocketed, the hand goes visibly quiet: cards dim
and refuse selection instead of walking you through target-picking
toward an engine refusal, with a rail slip saying what remains (draw
and end the turn). Counters, chaos shields, and discards still play —
an ambush sprung by the very pickup must be answerable.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Tiers degrade resources and repertoire, never judgment — the design
constraint was that no tier may ever look dumb. The APPRENTICE draws
one card a turn instead of two (a poorer wizard, not a worse one),
spends counters only on heavy hits (thrift, not blindness), and
carries a modest spellbook: damage, summons, stones, keys, and
treasure play, with no afflictions, amplifies, ambushes, guarding
tricks, or deja-vu. The ADEPT draws fully and knows everything except
ambushes and amplify. The ARCHMAGE is the full curriculum. Every card
any tier plays, it plays correctly.
The lobby workshop gains a tier picker beside the temperaments
(default adept); the tier persists with the seat, shows in roster and
scoresheet ("⚙ apprentice mystery"), and rides the drive loop.
Measured where it should matter: in berserker combat mirrors the
archmage beats the apprentice two to one, while pure treasure races
stay honest — the handicap lives in the card exchanges a human
actually feels, pinned deterministically in the tournament suite.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every playable card now has a place in the automaton's mind. The
damage table completes: lightning blast, wizardblade, and power drain
scale with numbers (and are skipped without one), disease bites in
the shared square, the dagger's true three points corrected. A new
affliction book casts the miseries — blind, slow, medusa, no-spell,
lock-in-place, walking dead, slow death, idiot, thought steal,
go-away — with a number for the duration, and WEAKNESS is saved for
whoever carries stolen gold. AMPLIFY doubles the heavy spells.
The counteraction ladder runs the full rack: REVERSE eats the big
blasts, ABSORB SPELL steals the good ones, FULL SHIELD, FULL
REFLECTION, REMOVE CURSE refuses afflictions at the door, REFLECTION
halves, ABSORB soaks the mid-range, BLUNT, EMPATHY out of berserker
spite, teleport escapes, shieldstone numbers.
Housekeeping: every stone hits the table the turn it is drawn, GIFT
FROM ABOVE is cashed instantly, curses get scrubbed with REMOVE
CURSE, LIFESAVER goes up at three players, a SAFE or GLUE guards
floor gold with enemies near, and DEJA-VU pulls the best attack back
from the discard when the hand runs dry of violence.
Table talk verified live ("ACQUISITION COMPLETE." mid-probe) — the
silence was timing, not plumbing — and the remark odds rise to half.
Three-way tournaments tell true stories now: the hunter wins on
gold, the worrier survives to win by attrition, and the berserker
learns that aggression in a three-way gets you buried first.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every play-strength item, in one education. DOORS: the pathfinder
walks through doors it can open — already-opened ones freely, locked
ones when holding Master Key or Pick Lock, casting the key at the
door on the path before stepping through (and a loop where the
clockwork re-keyed an already-open door forever is fixed: opened
doors read as open). TREASURE DEFENSE: a wizard carrying the
automaton's gold becomes the priority — chased over all objectives,
shaken down with DROP OBJECT when held, and attacked first. WIDER
SPELLCRAFT: blaster wands charged by number and fired; teleport as
escape when wounded and hunted, and as a counteraction clear of big
incoming spells; SPEED cast on sight; WARD armed to guard the gold;
shieldstone displayed so spare numbers soak small hits; ANTI-ANTI
pressed against counters (never against escapes); the berserker grows
BIG with an enemy near, the worrier fades invisible or slams a
CREATE WALL in its pursuer's face; ambushes armed from held
interrupts — the worrier trapping its doorstep, the others trapping
the treasure. Tournament suite green across all temperaments.
And the clockwork speaks: sparing, temperament-voiced table talk on
its own deeds — "ACQUISITION COMPLETE.", "SCHEDULED DEMISE:
DELIVERED.", "good wall. safe wall." — through the same chat ledger
as everyone else. The tally gains "games fought against the
clockwork", and automatons no longer pollute the count of wizards
seated.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Playtesting read the card right and the engine had it wrong. "Placing
the A tokens on one set of exits & the B tokens on the other" means
the two exits you mark BECOME a pair — and their former partners pair
with each other — not that the two exits trade destinations. Under
rev 9, click the exit and then the exit you want it to connect TO
(the hint now says so); already-connected exits are refused. Earlier
games keep the swap their logs were validated against. Test pins the
full four-way rewiring.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Playtesting read the card right and the engine had it wrong. "Placing
the A tokens on one set of exits & the B tokens on the other" means
the two exits you mark BECOME a pair — and their former partners pair
with each other — not that the two exits trade destinations. Under
rev 9, click the exit and then the exit you want it to connect TO
(the hint now says so); already-connected exits are refused. Earlier
games keep the swap their logs were validated against. Test pins the
full four-way rewiring.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
"Random" read as random ACTIONS, and a revealed random pick is barely
a mystery anyway. The fourth workshop button is now "mystery": the
server rolls the temperament and keeps it — the join line records it
for replay, the drive loop plays it, but the room tells the table
only "mystery". Roster and scoresheet show ⚙ mystery; the machine's
behavior is the only tell.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The lobby's automaton row gains "random" (the server already rolled
when no style was named — now the choice is offered). And each
automaton's temperament shows beside its name on the in-game
scoresheet in the handwritten face, so you always know whether the
machine across the maze wants your gold or your blood.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The automaton now plays number cards where they matter: attached to
value-scaled attacks (waterbolt, powerthrust) choosing the biggest
for damage, and played for movement when the goal is just out of
stride. It raises its monsters when no wizard is in spell range and
commands them every turn — creatures march at enemies by the same
hazard-shy BFS and maul whoever shares their square. Targets are
picked by lowest life.
And it has moods. The HUNTER plays the classic game: gold first,
violence when convenient. The BERSERKER hunts wizards over treasure
and finishes games by last-wizard-standing. The WORRIER paths around
enemies, counters at a lower threshold, shields against chaos, and
never brawls. Hosts pick the temperament when seating one (or the
workshop assigns at random); it persists with the seat, shows in the
roster, and the tournament harness proves every pairing finishes.
Across ten seeds of berserker versus hunter: six treasure wins to
four kills — the moods play genuinely different games.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The edge-click dispatch attached the tapped number card only for
wall attacks, so the warp wand's first use could never receive its
charges ("a wand's first use needs a number card" no matter what),
and wall of fire silently burned one turn instead of its NUMBER.
Cell-target casts had the same gap for duration terrain. The attached
number now rides every edge and cell cast.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The edge-click dispatch attached the tapped number card only for
wall attacks, so the warp wand's first use could never receive its
charges ("a wand's first use needs a number card" no matter what),
and wall of fire silently burned one turn instead of its NUMBER.
Cell-target casts had the same gap for duration terrain. The attached
number now rides every edge and cell cast.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
One command per beat — 1.5 seconds, the replay's 1x cadence — each
broadcast with its board state as it lands, starting a beat after
the human's own action settles. The pump is per-room, re-entrancy
guarded, and stops the moment the maze wants a human (or the game
ends). Watching an automaton stalk your treasure across the maze is
now a spectacle instead of a teleport.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Phase 4 begins. The automaton is a pure function in the engine —
automatonCommand(view) — playing from its own redacted GameView, the
same information a human seat receives: hidden hands stay hidden from
the clockwork. It ranks simple damage spells, counters what hurts
(full shield at 3+, reflection at 4+, blunt at 2+), discards its
worst cards by a value order, BFS-pathfinds to enemy treasures and
home again, refuses to path through hazards, brawls when there is
nothing to steal, and always has a safe fallback; the server's drive
loop steps any bot-held seat through the same runCommand path as
humans, so bot commands log, persist, replay, and broadcast like
anyone's.
Hosts seat them pre-start with "⚙ seat an automaton" (Automaton,
Automaton II, ... V); bot seats persist as tokenless join lines and
restore on boot. Proven three ways: bot-vs-bot engine games conclude
across seeds in 8-14 rounds (~100 commands — human-scale), a full
four-automaton table finishes, and a live websocket game of human
vs. automaton ended with the clockwork carrying two treasures home
through a do-nothing opponent.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Live chat interleaved correctly, but a reload sank every past message
to the bottom: the rejoin sent the whole game history first and the
chat history after. Talk is now a tableTalk event in the room's event
stream at the moment it was said — the room file already preserved
the interleaving, since chat lines append between command lines — so
rejoining players read the banter between the battle lines where it
happened. The separate chatHistory message retires; unread counting
rides the event stream instead.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every player-facing D4 roll now lands in the chronicle as pips with
its purpose: "🎲 alice rolls a 3 — aiming at the unseen — only a 1
finds them." A shared rollD4 helper threads the generic dieRolled
event through blind staggers and swings, pit leaps, ooze and pit
struggles, and the invisible/shrink miss rolls — the table sees the
die land, exactly as it would in person. Rolls whose numbers already
showed (the troll's swing, the misdirection direction, the opening
roll-off) keep their lines.
And the physical die's other job — "any 50-50 call" — gets its
button: 🎲 beside the say-box in online games (server-rolled,
published through the chat ledger so it persists, replays, and counts
toward unread badges) and under the chronicle in hotseat, rolled on
the device. Chronicle only; no game state touched.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Rules rev 8 closes the last two fidelity threads. A SPEED bonus turn
burns a turn of duration spells on the hastened wizard — recipient-
counted, per the FAQ's most obscure ruling — with self-cast durations
already burning through the normal turn-start sweep (expiry extracted
into expireEffect so both paths share the cleanup). And nothing can
be created on a DIMENSIONAL WARP token, as the card face always said.
The general-topic FAQ sections (Combat, Line of Sight, Monsters,
Treasures, and five more) join the rules tab verbatim under a double-
ruled divider, completing the FAQ's absorption: card rulings on the
cards, general rulings in the rules.
The four promoted UX items: cell-target spells now dim ineligible
squares (creations mirror emptySquareTarget from the viewer's
knowledge, summons want clear sighted squares, teleport BFSes its
four spaces exactly as the engine does, stone-to-water lights only
stone, dispel lights only creations); hotseat games get the full
replay reel, each step seen from its actor's own seat; a "stop
announcing attacks on this device" link in the fanfare modal (undo
lives beside the notification toggle in the lobby); the corner
inspector now serves only the selected casting card, with every
examine-a-card peek unified on the centered treatment; and the dev
socket URL keys on vite's port instead of hijacking every localhost.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Tapping a discarded card summoned the corner inspector beneath the
pile's own overlay — same layering trap the card library had. The
pile now enlarges its card centered above itself, FAQ seal included,
dismissed with a tap anywhere.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The FAQ affordance moves onto the card itself: a small dark seal in
the corner of any card with official rulings, everywhere cards render
— hand, inspector, peek, final reveal, discard pile, card library —
opening the rulings modal on tap (the link, never the text: card
faces stay verbatim card text). The separate inspector buttons and
library chips retire in its favor.
And clicking a library card mid-game no longer summons the App-level
inspector beneath the help modal, greyed out and useless — the
library enlarges its card in its own overlay, centered above the
booklet, seal included.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
An hour of rules archaeology, summarized: DIMENSIONAL WARP denies
LOS explicitly (its tokens stay sightless); the AUTO WARP describes
how to trace sight across a join; and on the lettered wraparounds
the texts are silent — no grant, no denial. The FAQ's Permawarp
rulings even have area effects counting distance through warps. Where
the texts are silent, the edition's own table breaks the tie, and the
table says the open sides see. Board openings carry sight in every
revision (a permissive change: every stored game's log replays
clean); the brief rev-7 restriction and its legacy flag are gone,
along with the sophistry that justified them. The adjacency geometry
stands. The friend's sticky-wand shot through the C opening was legal
after all.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The cards settle what the morning's feature got wrong. DIMENSIONAL
WARP: "There is no L.O.S. through the warp." The AUTO WARP: "for all
purposes, treat the connected board edges as though they are
adjacent" — an explicit grant, for edges that physically meet at a
corner. The lettered wraparounds get no grant at all: their rule is
about walking. So the pattern is that warps carry movement, not
sight, unless the text says otherwise — and only the aisle corners
say otherwise.
Warps now carry an aisle flag (the 3-player AUTO WARP and the
5-player corner arcs); hasWarpLineOfSight honors only those, with
the adjacency geometry — diagonals through the corner mouth —
unchanged from this morning where it rightfully applies. Games begun
before rev 7 keep the wider sight their logged commands were
validated against, via a legacy flag boardView stamps from the
game's rules revision. Tests pin all three states: lettered mouths
see nothing, aisle mouths see the corner fan, legacy games see
everything they used to.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Playtesting caught the gap with a sticky wand: a target visible
through the opening but one square off the corridor axis was refused.
The colinear-only model was stricter than the rulebook, whose actual
instruction is to treat the connected edges as adjacent boards with a
straight center-to-center line — and a straight line through a
one-cell opening may run diagonally, exactly as through a doorway.
hasWarpLineOfSight now abuts the far side virtually at the mouth
(rotating when the pairing turns a corner, as aisle warps do), finds
where the center-to-center line crosses the rim, requires that
crossing to fall strictly within the open mouth (corner-grazing stays
blocked — the strict reading), and checks the two legs against real
walls on each side of the seam. hasLineOfSight's core became a shared
segmentClear to serve both legs. The colinear corridor cases remain
as the special case they always were; a new test pins that off-axis
squares are visible through mouths.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
"Opportunity Fire isn't letting me use a wand" — the window and the
wand both worked (verified headless); what refused him was the wand's
own first-use rule, which players from wandless editions have never
met: charges are set by a NUMBER card on first use. Selecting an
uncharged wand now says exactly that in the hint strip, before the
engine has to say no.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>