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>
The home-base star polygon had no pointer-events rule, so clicking
the middle of a home square hit the star instead of the floor — you
had to aim around its points to move or target there. The star and
every other decorative vector (terrain fallbacks, treasure circles,
dim warp rings) are now click-transparent; the floor rect beneath
owns every tap, as the token-art images always did.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Tom Jolly's 2002 Rules FAQ settled three table disputes this week
from a text file only I could read. Now it lives in the game: 95
cards gained their FAQ sections (extracted verbatim from the official
document, alias-matched — Slime, Mistbody, Buck and friends resolved
to their proper cards), joining the handful already present for 102
cards with rulings in all. The card faces stay pure card text; an
"Official FAQ" button appears under any enlarged card that has
rulings — the hand inspector, the peek overlay, and as an FAQ chip in
the card library — opening a booklet modal with the rulings and their
provenance: "the cards overrule the rules, and the designer overrules
the table."
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Long card texts were clamped at nine lines and cut off mid-rule,
which is how the Speed argument started: the deciding sentence was
in the hidden part. The type now sizes itself to the text length in
six steps (0.6rem down to 0.375rem for the 550-char Firefly Stick),
and the line clamp is gone. Verified against Fear, the longest card
in play at 482 characters: every word on the face.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
"It's not letting me cast Absorb Spell on your Full Shield" — and
Jolly's FAQ says exactly why: "ABSORB SPELL will work on FULL
REFLECTION or REFLECTION, but not FULL SHIELD, as that is not used
against you, but cast upon the player using it." The refusal stands,
now with that reason in the error — and the neighboring case the
engine wrongly refused is fixed: an attacker may answer a reflection
with ABSORB SPELL, nullifying it and taking the reflection card into
their hand, with the original spell then landing unturned.
And the card face corrects my own hours-old work: ANTI-ANTI "does not
work against escape, such as SHRINK, TELEPORT, or INVISIBLE" — so
under rules rev 6 it can no longer pin a teleport escape. Earlier
games keep their stored chains.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
"When I cast Speed, it doesn't seem to do anything" — the engine had
refused correctly (actions end when you pick up an object) and said
so in a toast, but a toast fades in five seconds and leaves no trace.
Refusals now also land in the chronicle as "— reason —" lines, the
way hotseat games always recorded them, so the answer to "why did
nothing happen" survives long enough to be read.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A say-box under the chronicle sends table talk to the room; messages
land in the event log itself, styled as parchment asides — banter
between the battle lines, the way it happens at a real table. Talk is
seat-authenticated, stripped and capped at 300 chars, rate-limited by
the existing bucket, persisted as chat lines in the room file (the
game replay ignores them; the room keeps its last 500), and replayed
to anyone joining. Async games get unread badges in the lobby ledger
(💬3), cleared by watching the table, and catch-up replays speak the
lines at the step where they were said. Public to the whole room, no
whispers — and no chat in hotseat, where the table talks for itself.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
moves like a giant, and the boards are diagram-verified
TELEPORT as a counteraction (official FAQ: "the attack has no chance
of hitting you"): the defender names an escape square within four
spaces, the escape resolves before anything lands, and an ANTI-ANTI
pins their boots to the floor. Additive — no revision gate needed.
FILL SQUARE WITH SLIME holds spells now: an attack cast at the slime
sticks in the gel (leaving the discard pile), springs once at whoever
is inside or next enters, and counteractions against the trapped
blast cannot touch its caster — reflections vanish into the ooze. A
five-point waterbolt washes the slime and its cargo away, and the
waterwall waves clear slime from their path.
BIG MAN, under rules rev 5, finally moves like the card says: he
pushes players and monsters down the corridor ahead of him (stuck or
unpushable occupants block his advance), steps over a pit, tacks, or
killer ooze for two movement points without ever entering the square
(click two cells beyond the hazard), and monsters may not enter his
square. All gated so stored games replay under their own rules.
The boards were never wrong — the rulebook's Set-Up Diagram photo
confirms every pairing the code already had: 2p crossed, 3p stair
with the Aisle Warp arc, 4p/6p straight-across, 5p plus with all four
corner arcs. The stale TODOs are gone, replaced by tests pinning each
letter pair, and relocation's "only opposite board edges connect"
(which discards the aisle warp) is pinned too. Wall of Fire vs
Waterbolt turned out to be implemented and tested all along — its
TODO comment was the only thing wrong.
Also: hotseat saves now request durable storage (iOS evicts
unprotected origins under pressure).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
makeRoomCode checked only the in-memory map, which covers every live
and restored room — but a file that failed to restore stays on disk
with no map entry, and a new room taking its code would append a
second game into the orphaned file, corrupting both. The generator
now rerolls on disk presence too.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The static server sent no Cache-Control at all, so browsers
heuristically cached index.html — and a stale index.html pins its
user to last deploy's hashed assets no matter how often they reload.
That is how "watch the whole game" could show someone an app without
the feature minutes after it shipped. Hashed assets now cache forever
(immutable); everything else revalidates.
And per playtesting: a finished game offers no actions — isYourTurn
now requires the playing phase, which retires the pick-up/drop/punch/
discard/end-turn row the moment the trophy drops.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The seed + command log has been the whole game all along; now it can
be watched. Finished games offer "⟲ Watch the whole game" beside the
face-up hands: the server replays every command from seq 0 through
the same redacted catch-up pipeline (the 200-step window remains a
live-game courtesy; full replays wait for the game to finish), and
the reel plays it titled "The whole tale, from the deal" with new
1×/2×/4× speed controls for the long tellings. Each viewer rewatches
from their own seat — hidden information stays hidden in the retelling
exactly as it was at the table.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
142 "moves" was really 142 logged commands — steps, spells, passes,
end-turns alike. The line now says so.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
"The creature-1 takes 2 damage" — the creature events carried only
internal ids, so the log printed them. creatureAttacked, Touched, and
Damaged now carry the creature's kind, and the lines read like a
table: "The Wraith strikes!", "The Troll swings (rolled 3)!", "The
Skeleton takes 2 damage."
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
At the table the discards sit face-up for anyone to leaf through. The
view now carries the pile (deck order stays secret), the "discards N"
count in the rail became a link, and it opens a booklet-styled reader:
every cast-away card newest first, tap any to enlarge. And the
chronicle stops mumbling "discards 1 card(s)" — it names names, so a
wraith's theft reads "bob discards Fireball," exactly what a table
would see as the card hits the pile.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The WRAITH card assumes the window exists — "REFLECTIONs used on the
wraith's touch will damage the wraith" — but creature damage applied
instantly, so BLUNT had nothing to catch, as playtesting found. Under
revision 4 every creature blow against a wizard opens the same
counteraction stack a spell does: the wraith's entry touch, the
democratic monster's claw, and commanded troll/skeleton/shadow
attacks. The blow's damage rides the stack; BLUNT halves it (round
up); reflections work by name against creatures — half back for
REFLECTION, the whole blow for FULL REFLECTION — landing on the
creature, not its controller; FULL SHIELD correctly does nothing
("does not stop any physical attack"); the wraith's card theft is a
secondary effect that lands only if damage does. No aim-miss rolls
against invisible or shrunk defenders — the creature is already in
the square. The attack fanfare shows the creature's own card.
Earlier revisions keep the instant touch so every stored game — and
the live one that found this — replays unchanged.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The Sticky Wand attaches its webs as a sustained effect with the
engine-internal id "sticky-web", which is not a printed card — and
cardDef throws on unknown ids. The scoresheet's new spell chips and
the chronicle's settles-over/wears-off lines both called it on
sustained ids, so the first webbing killed every render: mid-game the
actions bar died, and after a reload the whole table came up blank.
A spellName lookup now names synthetic effects properly ("Sticky
Wand webs") and falls back to the raw id rather than ever throwing,
and the chip peek only opens ids the card library can actually show.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Interrupt and Opportunity Fire were fully playable out of turn — tap
the card while another wizard acts — but nothing said so, and cards
are otherwise inert out of turn, so playtesters never tried. Now,
whenever the moment is live (someone else's turn, no attack or chaos
pending, past round one, not hotseat), those cards wear a pulsing
golden glow in your hand and the rail says to tap one. The glow
respects prefers-reduced-motion.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
DROP OBJECT resolved correctly — the treasure fell — but the
chronicle announced "The attack is completely stopped," because the
attackResolved event branded any attack that dealt zero damage as
stopped. Utility attacks deal zero by design; only an attack that was
TRYING to wound counts as stopped when nothing lands. Tests pin both
sides: uncountered DROP OBJECT reports unstopped and drops the
treasure; FULL SHIELD reports stopped and the treasure stays carried.
Not deployed — a live game is in progress.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
WARD's text says "you may play at that time" — under rules revision 3
the choice is made by setting the trap: an armWard command toggles it
on your own turn (your secret; a private wardSet event and a rail
note), and the spring fires only while set, consuming the card and
the arming together. Async games keep their agency without an
interrupt window, exactly as the ambush system solved this before.
CHAOS gains its printed interactions: "FULL SHIELD removes a player
from participation" — a defender's shield sits them out instead of
stopping the spell, and after the counter chain every bystander gets
a shield window in seat order (chaosPending; queue head owes a
response in lobby summaries, the rail says whose hand hangs in the
balance) before the pile forms among the unshielded. "REFLECTIONS
have no effect" — both reflections are refused as counters. ABSORB
SPELL still eats the whole thing through the existing absorb path.
Both changes are frozen behind deckRev 3 so every stored game — and
the live one — replays byte-for-byte under its own rules. Five new
tests cover armed/unarmed wards, shielded defenders and bystanders,
the reflection refusal, and the legacy auto-ward.
Not deployed — a live game is in progress.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
"It is possible, though time-consuming, to punch a wall down. A wall
takes 20 points of damage to destroy; a door takes 15. Any attack
against an inanimate object counts as your one attack for the turn."
Damage accumulates per edge in wallDamage (remapped through sector
rotations, public in the view), fed two ways: a punchWall command for
the bare-fisted (1 point, from a square touching the edge) and attack
spells cast at an edge target — LOS to the wall for L.O.S. cards,
touching it for same-square cards, amplify and power-attack honored,
wand charges spent, no counteractions since stonework plays none.
Thrown daggers and rocks clatter to the floor at the foot of the
wall. At the threshold the edge opens through the same override path
destroy-wall uses.
On the table: damaged walls wear spreading cracks, an attack card's
hint offers "or a wall line to batter it" with the edge layer live,
and a "Punch a wall…" stamp arms a click-the-wall mode. The chronicle
counts the blows: "alice batters the wall with bare fists — 3/20."
Not deployed — a live game is in progress.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
"If casting a spell, or checking line of sight through the AUTO WARP,
treat it as a straight line, and the two connected boards as though
they were adjacent" — and the lettered openings reconnect edges the
same way. hasWarpLineOfSight models it: the line must run straight
down the corridor, out one mouth, and in through the paired mouth,
with both corridor legs clear and neither mouth filled solid. The new
sightBetween (direct or through-a-warp) is now the game's LOS check
everywhere — spells, ambush triggers, Around The Corner, the
visionstone sweep, and the targeting dim on the client.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A "Send word" section with the keeper's addresses: email, Bluesky,
Mastodon, and the home roost at kestrelsnest.social — for feedback,
bug reports, and faint praise alike.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
"Not applicable in a 2-player game." — the card face. New games deal
from deck revision 2, which removes it when exactly two wizards sit
down; three or more keep it. The revision travels in GameConfig and
the persisted start line, and stored games without one replay against
the original build — changing an existing game's deck composition
would scramble its deterministic replay. Test pins all three cases:
removed at two, present at three, present in legacy two-player games.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The Hover A record resolves, so og:image and twitter:image move from
the sslip.io fallback to wizwar.kestrelsnest.social.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A three-reviewer sweep for tells of piecemeal machine generation,
every finding verified against the code before touching it. No
behavior changes; the full suite passes unchanged (plus two
strengthened pins).
Engine: removed four void-silenced fossils (a parseEdgeKey call
voided where it stood, stoneEffect's ignored cardId parameter, the
actualTarget remnant in doCast, a voided loop variable in shadow
upkeep); fixed the initialize-then-overwrite narration in
spawnCreature; replaced a filter(() => false) no-op; waterwall now
rides waveFromEdge instead of carrying its own verbatim copy (and the
single-caller washBack wrapper went with it); blind wall-bumps and
LOS blockers each collapsed to one implementation; the wand-id list
and the "permanent" duration sentinel became named constants; the
ambush number local no longer shadows the imported numberValue
function; assorted reviewer-aimed phrasings rewritten as the
constraints they guard.
Server/deploy: the protocol header now documents all eleven message
types; dropped an eslint pragma with no eslint, a test script with no
tests, and an rsync exclude anchored at a path that never existed
(the real data/ dir now excluded); the Caddy vhost has one source of
truth; stale "pending DNS" note removed — the record resolves.
Web: ~90 lines of CSS swallowed verbatim into a mobile media query
deduplicated; the reduced-motion guard on the board now actually
stops the marked-cell pulse; one shared color module replaces two
drifted palettes; an orphaned doc comment rejoined its function.
Tests: the ten-times-pasted helper block became test/helpers.ts;
wave-numbered files renamed for the behaviors they pin; deliberation
comments and void-ed corpses of unwritten assertions deleted; silent
seed-dependent early-returns now fail loudly; one assertion that
compared a value to itself now pins the home-translation it meant to;
the stored-log single-number command form gained the explicit
compatibility test it deserved.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Security review of the accumulator commit found three holes, all in
the unauthenticated hotseat ping. Worst: Number(undefined) is NaN,
and NaN survives Math.min/max — one malformed report would have
poisoned commandsPlayed and friends permanently (NaN serializes to
null). All numeric fields now pass through a NaN-proof clamp with a
fallback. The dedupe ledger caps at 50k hotseat entries so spammed
random ids cannot grow stats.json without bound, and each connection
may deliver at most 20 reports — a real device finishes a handful of
games; a firehose is abuse.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The rulebook tab had it, but the quick how-to never stated the most
basic number in the game. The movement section now opens with it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Instead of re-scanning every room's log on demand, stats.json now
accumulates beside the room files: each room is remembered at its
highest counted stage (created → started → finished), so boots and
replays reconcile without double-counting, and the tally will survive
any future pruning of old rooms. Finished games contribute their
moves, table-time, and manner of victory exactly once, at the moment
of victory.
And with an accumulator to receive them, hotseat games finally count:
each local game mints an anonymous id, pings "started" with its
player count, tracks its own between-moves clock, and on the final
move reports counts only — commands, minutes, players, win reason.
No names, no moves leave the device. The server dedupes by id, clamps
everything to sane ranges, and the booklet's tally now shows how many
of the games were hotseat tables.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A new tab in the help booklet answers "how much is this getting
played?" from the ledgers themselves: games chronicled (begun and
fought to a finish), distinct wizards seated, every spell, step, and
punch recorded, time at the table estimated by the clock between
moves (gaps over ten minutes don't count — async games tell the
truth), victories split by treasure-theft versus last standing, the
longest game, the fullest table, and the date the first game was
dealt. Computed server-side over the in-memory rooms with a 60-second
cache, fetched over the socket when the tab opens.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sharing the game's URL now unfurls a proper card: Open Graph and
Twitter meta tags with a 1200x630 preview composed from the physical
set's own counter art — WIZ-WAR in tall caps over the parchment, the
tagline in script, a row of wizard, troll, and treasure tokens, and
the fan-project line beneath. The favicon becomes the purple wizard
in his black hat, cropped from the counter sheet; the your-turn
variant wears a red badge, replacing the old lettered SVGs.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Elimination destroys the evidence: a killed wizard's cards pass to
the killer, a treasure-lost wizard's go to the discard — so the
post-game reveal showed "empty-handed" for exactly the player whose
hand everyone wants to see. Both elimination paths now snapshot the
hand at the moment of death (finalHand), the finished view serves it,
and the gallery marks those rows "as they fell" in script. Because
rooms replay from the command log, already-finished games show their
fallen hands too. Test kills a wizard holding a Fireball and a 6 and
finds them in the reveal.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Once the game is won, the view stops keeping secrets: revealedHands
carries every player's cards, and the table replaces your hand row
with a face-up gallery — each wizard's name (trophy on the winner)
beside their final hand, tap any card to enlarge, "empty-handed"
written in script for those who died with nothing. In hotseat this is
the thing the winner passes around after dismissing the fanfare; in
async games it greets each player when they open the finished game.
Redaction still guards every phase before "finished."
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Winning showed only as a small slip in the rail — anticlimactic, as
playtesting put it. The engine now records HOW the game was won
(winReason: treasures carried home, or last wizard standing) alongside
the winner, the view carries it, and the finish opens a gold-ringed
modal: trophy, the winner's name in tall caps, and the manner of
victory in a handwritten line. "Behold the final board" dismisses it
to the finished table. In hotseat the one screen proclaims to the
whole table at once; in async games each player is greeted by it when
they next open the game.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Illusionary Attack, Deja-Vu, Card Erasure, and the other name-a-card
spells asked for exact spell names from memory. The field is now a
native datalist: type a few letters and matching card names appear,
tuned per card — Illusionary Attack offers only attack spells (it can
only pretend to be one), Drop Object offers only the movable objects
plus Treasure, and the rest offer the whole playable pool.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The engine has always accepted it — edge target, line of sight to the
edge, open corridor only — but the client's EDGE_CARDS list never
included illusion-wall, so selecting it offered no clickable wall
lines and the card was simply uncastable. The LOS dimming that
appears alongside is correct and stays: placement requires sight of
the wall line, so the lit squares show where the shimmering can go.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
view.sustained was never rendered — every duration spell in play was
invisible, Big Man included, as playtesting found. Now each player's
scoresheet row lists the spells on them as violet chips (name and
turns remaining, tap to read the card), beside their displayed cards.
And on the board itself, Big Man makes the wizard token tower half
again as large, Shrink dwindles it — the exact at-a-glance "I have
become big" the table owes you.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Tapping a creature you command now does both things at once: selects
it for orders AND opens its card in the inspector corner, with a
stats line pinned beneath — hits left, moves left, attack ready or
spent (or barred on the turn it appears; the shadow reports itself
unharmed by ordinary damage). The same stats ride along on any
hold-to-peek of a creature, and they are derived live, so marching
the monster updates the numbers as you spend its moves. While
commanding, the hint strip carries the same line beside the hand,
with a "done" to dismiss. Deselecting closes the card.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The press-and-hold card peek lived only on the floor rects, and any
creature or wizard token sitting there swallowed the pointer events —
so the democratic monster, whose plain tap selects it for commands,
had no path to its card at all. The hold gesture now lives on the
tokens too (a fired hold swallows the tap so nothing double-fires),
and the board suppresses the mobile long-press callout so the gesture
stays clean on phones.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The engine always warped a creature marched off a lettered opening —
verified headless — but the table offered no way to ask for it: cell
clicks for a selected creature matched only geometric neighbors, and
the warp arrows moved only your wizard. Now a selected creature
standing on an opening lights the arrow (and, per the existing cue,
its destination), the arrow marches the creature through, and
clicking the far mouth directly does the same.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Summoned monsters act during their controller's turn, but nothing
reminded you — a democratic monster in play was invisibly waiting on
every single player. Now each creature you may command this turn gets
a moss-green slip in the paper rail: name, moves remaining, whether
its attack is ready (respecting no-attack-on-creation and the
democratic monster's one-attack-per-round), and the tap-to-command
hint. The democratic monster reminds every player on their turn,
since all players get to move it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
"What does a rosebush do again?" now has an in-game answer: press and
hold any square (450ms) to open the card behind whatever occupies it —
creature, terrain, dropped object, warp token, or boobytrap marker —
in the view-only inspector corner. A plain click that claims no game
action peeks too: out of turn, every tap reads; on your turn, taps
beyond your reach read instead of doing nothing, and clicking an
opponent's creature with nothing selected reads its card. Priority
when a square holds several stories: creature, then terrain, then the
topmost dropped object.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
At the table, a displayed card sits in front of its wizard for all to
see — Master Key, Wizardblade, the stones, wands. The view always
carried every player's displayed cards, but only your own hand marked
them. Now each scoresheet row lists that player's face-up cards as
parchment chips, wands with their remaining charges as pips, and
tapping a chip enlarges the card in the inspector corner, view-only.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Selecting an L.O.S. card now drops every square you cannot see into
shadow, leaving eligible targets lit — computed by the engine's own
hasLineOfSight over the player's VIEW, so illusion walls you still
believe in block your aim, stone and bushes and the Big Man block
everyone's, and Around The Corner widens the light one bend when
attached. ADJACENT cards light just your square and its four
neighbors. The shade paints over tokens and wizards alike, and
switches off while arming an ambush, since ambushes aim at the
future. A new sightedCellsFor lives in the engine view module so the
client can never disagree with the rules.
Speedstone, meanwhile, only took effect at next turn's allowance
recompute — displaying it mid-turn granted nothing, as playtesting
found. It now bumps the current allowance by one on display (a delta,
so number-card movement already played survives), unless SLOW or a
zeroed allowance says otherwise. Test covers the immediate grant and
the persistence into later turns.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Being attacked was announced only by a slip in the paper rail, easy
to miss mid-turn — the playtest complaint was real. Now an attack on
you (or a counter to your spell) opens a modal: the attacker's name
in red Oswald caps, the actual card face enlarged, the number backing
it if any, a bare 👊 for a punch, and a single "To arms!" stamp.
Dismissing it leaves the actionable prompt in the hint strip beside
your hand — where the counteraction cards you would tap actually
live — with the "let it resolve" escape. The rail keeps a one-line
reminder. Each new decision point in a counter-chain re-announces.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Placing the two tokens worked, but using them asked too much: the
only affordance was a "Step through the warp" button in the actions
row, easy to miss and far from the board. Now standing on a warp
token pulses its twin with the same green dashed ring the lettered
edge openings use, and clicking the twin steps you through — one
gesture, learned once, working for both kinds of warp. The button
stays for those who found it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Dimensional Warp, Trader, Redirection, and Relocate Sector all take
two clicks, but only the hint bar acknowledged the first — the board
itself sat unchanged until the second click landed. The first chosen
square now wears a pulsing amber dashed ring (same rhythm as the warp
destination ring, still under prefers-reduced-motion) until the spell
completes or is cancelled.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>