'ANY CARD MAY BE PLAYED WITHOUT A NUMBER CARD, but its power is only 1.'
The wand first-use gate was the engine's one remaining missing-number
refusal — everything else already defaults its power to 1. A wand cast
bare now charges to one, fires once, and crumbles; the client hint says
so. Ungated: the refused casts never reached a ledger.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138A8CjeQRpvzKxuMfz1Bqc
Wiz-War never says hitpoints. Walls and doors quote the rulebook's own
phrasing ('20 points to destroy', '13 of 20 points left'), and the
Mega-Monster boost button says life-points, as its card does.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138A8CjeQRpvzKxuMfz1Bqc
The same 450ms hold that peeks a square now works on walls, doors, and
fire walls: the segment's full description (state, lock, hitpoints, the
fire's burn warning) rises in the peek scrim. Shimmering illusions keep
their richer tap modal.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138A8CjeQRpvzKxuMfz1Bqc
All 45 tokens in both arts — the photographed physical set beside the
hand-drawn contingency — grouped (wizards, treasures, monsters, terrain,
objects & markers), each at board size and close-up. The drawn column
renders through TokenArt, so it previews exactly as the board inlines
it. Cross-linked with the flourish workshop.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138A8CjeQRpvzKxuMfz1Bqc
The owner's idea for teaching novices: a hints button runs all three
temperaments' brains against YOUR view — the same cards and board you
see, nothing hidden — and each says what it would do in your robes.
The Hunter (eyes on the gold), the Berserker (eyes on the blood), the
Worrier (eyes on the exits). Available on your turn and while under
fire (counter advice included); purely advisory, computed client-side,
nothing dispatched. hints.ts translates any Command into plain words.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138A8CjeQRpvzKxuMfz1Bqc
Shedding a single card meant entering discard mode, marking, and
confirming. Now any selected card offers 'Discard it' right in its
action strip — beside 'Drop it here' when the card is an object, so
the drop-or-discard choice sits in one place. The bulk discard flow
stays for multi-card sheds.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138A8CjeQRpvzKxuMfz1Bqc
Per the owner's design — and truer to a real table, where the cast is
public: every illusion wall's location is open knowledge, rendered as a
shimmering wall to any player whose eyes have not yet ruled on it.
Testing is an explicit act: tap the shimmer (or bump into it) and a
modal explains the 50/50 and offers 'Roll to test your eyes' — the new
testIllusion command rolls once, then the wall either hardens or
dissolves for you alone. Nobody's verdict is moved by watching someone
else stroll through (the Q3WZ mystery: an automaton walking through
its own round-1 fake). Untested walls block movement and sight without
consuming RNG; the pre-29 lazy belief roll is preserved for stored
games. Automatons doubt free shimmers on their best crossing before
spending any card on that wall.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138A8CjeQRpvzKxuMfz1Bqc
The name cell was a fixed-height nowrap/ellipsis line, clipping even
plain 'archmage hunter' mid-game. The temper tag now wraps below the
name as one piece and the row grows to fit.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138A8CjeQRpvzKxuMfz1Bqc
FAQ: 'If this gets FULLY REFLECTED, you lose the rest of your turn and
cannot draw cards (in addition to damage).' When the returned bolt
stuns its own caster mid-turn, their remaining actions end at once and
the end-of-turn draw comes up empty (new turn.drawForbidden flag); the
normal stun still costs them the next turn. The affected player sees
'Your own bolt has left you reeling' in place of the usual spent-turn
slip. Older revisions played on and stored games replay so.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138A8CjeQRpvzKxuMfz1Bqc
The carried-treasure chest in the scoresheet is now a button: tapping
it raises the big-peek scrim with the chest at full size and a note
naming whose treasure sits in whose arms.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138A8CjeQRpvzKxuMfz1Bqc
The cast always worked (click a square), but nothing guided it and
nothing marked its arrival. Now: a targeting prompt, eligibility
dimming to the caster's sighted squares (the engine demands LOS to the
aim point), and a flourish — the aiming mark, a shadow gathering, the
die crashing down out of a clear sky with a bounce and flung grit, a
drift line when fate moves it, and every scattered token streaking to
where it lands. In the /?fx gallery as die-drop.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138A8CjeQRpvzKxuMfz1Bqc
'FULL REFLECTION lets the other player decide which objects, if any,
will be swapped' — the reflector's choice now rides their counteract
(params.cardId, reflector's item first), resolved with the roles
swapped when the reflection settles; 'none' or no choice trades
nothing. The client walks the reflector through the same give-and-take
picker, with a 'swap nothing' refusal.
Also from room XRT7: the trade picker now honors each room's own rules
revision (older rooms trade only object-typed cards), so it can no
longer offer a wizardblade a rev-25 engine will quietly refuse — and a
fizzled swap finally says so in the log instead of vanishing.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138A8CjeQRpvzKxuMfz1Bqc
The trade grammar gains a 'treasure' token (never present in stored
ledgers, so no gate needed): a dagger can buy back the treasure in a
thief's arms, or two armfuls of gold can change hands outright. The
one-treasure carry limit and WEAKNESS both hold in a trade as at a
grab — a one-way treasure needs an open slot and an able back. The
picker offers each side's carried treasure alongside displayed items,
withholding theirs when your own arms are already full.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138A8CjeQRpvzKxuMfz1Bqc
The pact fix: a clockwork no longer attacks a wizard it holds a BUDDY
pact on — Eric watched one sign the pact and punch him the next turn.
A pact is torn up for exactly one thing: a kill. And the post-attack
pact is signed only by a wizard who wants OUT of the fight (hauling
gold, bleeding, or with other enemies left) — a healthy duelist keeps
its options, and mutual-pact stalemates stay out of bot wars.
Swap Meet drops the 'name a card' prompt for a real trade picker:
click the other trader, choose one of your carried items, then claim
one of their displayed items. Rules rev 26 widens the engine's match
from object-typed cards to every movable object (daggers, rocks,
wands, stones); older games matched narrowly and replay so.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138A8CjeQRpvzKxuMfz1Bqc
A FULL REFLECTION's returned spell is a fresh attack on its own caster —
who, per the owner's ruling, gets a defender's counteraction window
against it (absorb the blast, shield it, or FULL REFLECTION again: the
ping-pong war ends when the cards run out). The reflection now settles
into a new stack with the roles swapped and the damage pre-priced
(numbers, amplifies, and surviving counters already applied); the blow
returns to its sender unerringly, with no fresh hit rolls. onResolved
effects run with the swapped roles, so a reflected IDIOT now afflicts
its own caster. Earlier revisions land the blow instantly and stored
games replay unchanged.
Automatons price the incoming reflected damage off the stack; the attack
modal announces 'Your own spell comes screaming back!' with the inbound
total.
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
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>
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>
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>
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>
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>
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>
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>
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 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>
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>
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>
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>
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>
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>
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>