570 Commits
Author SHA1 Message Date
Eric WagonerandClaude Opus 5.5 ceb22a9898 A stale tab's reload no longer throws: a retired chunk resolves to nothing, and nothing is mounted
The preload-error handler claims the failed import and reloads; the import
then resolves empty, and destructuring its default threw (WIZWAR-X).

Fixes WIZWAR-X

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016ZtFMp1AtjXPBY4Z69Tx81
2026-09-30 12:06:34 -04:00
Eric WagonerandClaude Opus 5.5 cbf897ff13 Pages show the hall-wide notice, when there is one, at the top
The keeper's hall-announce writes one file on the shared host; the site
serves it at /hall/announcement.json, and the banner shows it with the time
in the reader's own clock, dismissable one notice at a time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-29 13:03:37 -04:00
Eric WagonerandClaude Opus 5.5 397c68a1c8 Wiz-War lives on the shared hall host: its scripts, skills and docs name it
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-29 12:52:36 -04:00
Eric WagonerandClaude Opus 5.5 56ea593e07 A deploy ships the engine's own data: only the top-level ledger folder is left behind
The exclusion for local game data matched any folder named data, so the
cards and boards the server reads never shipped after the droplet's first
setup; the live copy of cards.json had drifted to August's (text of FAQ
rulings, and rows of a set this edition does not deal). All 198 production
ledgers replay clean with the current data.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-29 12:48:04 -04:00
Eric WagonerandClaude Opus 5.5 811d5f84cb Wiz-War's host follows the hall's shared layout: its own Caddy site file, its own access log, a memory cap for a shared box
The host's Caddyfile gathers each game's site from /etc/caddy/sites/;
Wiz-War's is rendered from deploy/Caddyfile.tmpl and logs to
wizwar-access.log, which the rollup and the pulse read. The server's memory
cap drops from 700M to 350M (it runs in about 125M), so a runaway cannot
starve other games sharing the box. Applied on the live droplet with its
logs renamed in place.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-29 12:37:06 -04:00
Eric WagonerandClaude Opus 5.5 d5b92d9a63 The about panel no longer credits its making
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-27 20:58:56 -04:00
Eric WagonerandClaude Opus 5.5 a4196480ce A socket's own error closes that socket, not the server
A message over the size limit or a malformed frame raised an error on
the socket, which had no listener, and Node ended the process: one
message from anyone could take the server down until systemd restarted
it. The socket is terminated instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-27 01:21:45 -04:00
Eric WagonerandClaude Opus 5.5 3a6b0ff43e Credibility pass: the illusion tests roll both ways, and the seams from the last batch are sanded
Scope: 66b5c06..HEAD.

- The rev-27 illusion tests search seeds for a believed and a doubted
  roll and assert fixed life totals; seed 42 alone never believed, so
  the BLUNT pricing went unchecked.
- Three docblocks stranded above newly inserted functions are back on
  their own (openCreatureStack, resolvedBlow, castTrace).
- POWER ATTACK's life trade is one helper instead of three copies; the
  goat's charge distance is one helper for its validator, its ram and
  its pricing.
- The family list loads once into a shared store; the lobby and gallery
  share one talk filter; Board uses the engine's neighbor().
- A creature's blow shows the card that summoned it by the creature's
  kind, not by matching the blow's display name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-26 00:22:20 -04:00
Eric WagonerandClaude Fable 5.1 e97deb8d6f A commanded troll lights only the walls and doors beside it, and so does a punching wizard
Every interior line lit whenever an edge was wanted; the troll can strike
only the four sides of its own square, so only those light now.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-24 21:37:13 -04:00
Eric WagonerandClaude Fable 5.1 7a0a972452 A creature's blow is named on the stack: the counter is played against the fire imp's scorch, not a punch (SC59)
The caster whose creature is countered now sees "your attack, answered"
and the name of their own blow, instead of an incoming punch with the
opponent's counter card standing in the attack slot.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-24 21:32:34 -04:00
Eric WagonerandClaude Fable 5.1 c3f63d4eb7 Rev 27: an ILLUSIONARY ATTACK is priced as the spell it fakes, so BLUNT and the rest meet it (UPJE)
The believed illusion was dealt after the counter trail had already
spoken over a zero, so a BLUNT trailed for nothing and the full points
landed. Now the fake carries its spell's points through the pipeline and
the belief roll decides whether the weighed blow lands. Games dealt under
rev 26 and before replay as they were.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-24 20:40:47 -04:00
Eric WagonerandClaude Fable 5.1 991a6a0443 ROTATE SECTOR asks which way: the tap marks the sector, a button turns it (UPJE)
The clockwise checkbox sat in the hint strip and defaulted on, so a
sector could spin the way nobody meant. The turn is now its own decision,
in the dock beside the board like the teleport confirm.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-24 20:30:37 -04:00
Eric WagonerandClaude Fable 5.1 6c29f750fc A waterwall tapped onto a slime washes it: the tap picks the face across the caster's approach (B8G9)
The flash for a corridor-line card no longer names wizards, bushes and
slimes as its targets; it gives the card's own line hint.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-23 22:59:14 -04:00
Eric WagonerandClaude Fable 5.1 0244cffb4b The family list knows the hall: about panels link to gamehall.kestrelsnest.social, and a new game gets a card there
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-23 21:04:31 -04:00
Eric WagonerandClaude Fable 5.1 9f1358496d The about panel says the games are free and where the hosting tip jar is
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-23 20:25:05 -04:00
Eric WagonerandClaude Fable 5.1 c79fdb4adb The collection is Kestrel's Hall
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-23 19:51:06 -04:00
Eric WagonerandClaude Fable 5.1 9d087ccaa1 The front page and the about page point to the other games of the Kestrel's Nest
The list is the kit's family.json, shipped as /family.json and refreshed
at deploy when the kit is beside this checkout.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-23 12:26:49 -04:00
Eric WagonerandClaude Fable 5.1 13a6fc2603 The host may let the Peanut Gallery talk
A gallery line wears the eye and a name that no wizard at the table
holds; the host opens or hushes it from the lobby or the mast, on the
ledger, and the gallery is reined per address.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-23 09:47:26 -04:00
Eric WagonerandClaude Fable 5.1 f68b3cef06 The desk's replies no longer ring the bell: reports and players' answers do, the desk's own mail does not
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-23 08:54:08 -04:00
Eric WagonerandClaude Fable 5.1 35d805fda3 The lobby tells a caller what hour it is where the keeper lives, and that other games can go on in another tab
WIZWAR_KEEPER_TZ names the zone (Eastern by default); the room carries it
and the client words the hour by the minute.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-23 08:49:37 -04:00
Eric WagonerandClaude Fable 5.1 31bfcf7bc0 Rev 26: BUTT-HEAD's ram is priced into the blow, so STRENGTH, AMPLIFY, and the counters weigh it (KWUZ)
Ramses cast STRENGTH, then an amplified BUTT-HEAD three squares off, and
the goat dealt three: the ram was applied in onResolved, past the pipe
that doubles, soaks, and adds. Older games keep the bare distance.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-23 08:16:30 -04:00
Eric WagonerandClaude Fable 5.1 5193b12b8e Rev 25: a bush or the ooze is attacked like a wall — POWER ATTACK counts, thrown weapons land at its foot
Older games took neither; both sides pinned.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-22 12:19:15 -04:00
Eric WagonerandClaude Fable 5.1 66b5c06f17 Credibility pass: one teleport step, one bell, one step type, and the comments that argued are gone
Since 6e49fc9. Engine: the teleport BFS in the view and the engine's
wallIgnoringDistance share teleportStep; the counter trail is weighed
between steps instead of on six arms; the bush attack takes its
adjacency from SIDES like the wall does; a dead redirected clause, a
one-member set, an identity ternary, and a stray try/catch are gone;
two tests now assert what their names promise. Server: KEEPER and
MAX_SEATS live in rooms.ts, the three Sentry bells ring through one
helper, the unread reply field is dropped, actingSeat comes from the
engine, and the protocol header names every message. Web: ReplayStep
is one type, cardName one helper, the say box and the reference section
one snippet each, the keeper's name arrives from the server rather than
the source, and the lifesaver ruling that ruled nothing is out.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-22 09:56:49 -04:00
Eric WagonerandClaude Fable 5.1 c4a555f8df Fuller banter pools, and the blow's own names decide who dealt pain and who killed
Damage lands on the defender's step, so a trigger keyed to the actor
never credited the attacker: across thirty three-bot games the kill line
fired zero times and the dealt-pain line five, against 328 takes. Both
now read the attackResolved, punched, and died events themselves.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-22 09:39:05 -04:00
Eric WagonerandClaude Fable 5.1 be96dd6047 The archmage cuts off a winning delivery and aims at the leader when no kill is on the table
Reuben's three wins today were walked home unseen: the clockwork
fought whoever stood in front of it. Now a delivery that would end the
game pulls every automaton toward that wizard's home (where the banked
gold is lifted off the doorstep) or the road to it, and among visible
targets the thief still dies first, a kill is still taken, and only then
does the aim shift to whoever has more treasures banked. Measured with
deploy/brain-trial.mjs, which seats the working tree's brain against an
older checkout's at one table.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-22 09:11:34 -04:00
Eric WagonerandClaude Fable 5.1 1b18dffd28 sentry-slack-alert.sh parses again
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-21 15:26:42 -04:00
Eric WagonerandClaude Fable 5.1 46c345dff4 deploy/sentry-slack-alert.sh routes every wizwar issue to a Slack channel, token from the shell
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-21 15:18:08 -04:00
Eric WagonerandClaude Fable 5.1 11e9f950c6 Reports are threads, and every turn of one rings the desk's bell
A player answers the desk under its reply from their lobby, proven by
the seat the report was filed from; the lobby shows the exchange in
order and says whose word is pending. A new report, a player's answer,
and a desk reply each raise a Sentry issue on the keeper's phone — the
first two from the server, the last from the reply script itself,
straight to Sentry from the droplet. The Desktop digest lists the
answers, and the desk's rule reads a report as reopened when the last
word is the player's.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-21 12:08:55 -04:00
Eric WagonerandClaude Fable 5.1 ffbca5bfb9 deploy/pull-feedback.sh mirrors reports, replies, and screenshots to the Desktop with a digest
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-21 11:11:42 -04:00
Eric WagonerandClaude Fable 5.1 071e7ce988 A permanent spell settles 'for good' in the chronicle and the receipt, not for a billion turns
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-21 11:09:01 -04:00
Eric WagonerandClaude Fable 5.1 48350a3686 A report may carry a screenshot
The 🐞 form takes a picture beside its words — PNG, JPEG, or WebP, under
2.5 MB, previewed before sending. The socket's message cap is far too
small for one, so the picture goes through a plain HTTP door after the
report is filed, addressed to the report's id, one per report within
the hour, checked by its own first bytes, and kept in feedback-images/
beside the reports with a line on the report saying so. The desk's
skill knows where to look.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-21 11:02:59 -04:00
Eric WagonerandClaude Fable 5.1 d76a18d5e6 A seated wizard leaves the room's expected list, live and on rebuild
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-17 23:45:36 -04:00
Eric WagonerandClaude Fable 5.1 1ebd6dbe47 A refused seat is logged, and the wallet drops a seat only on the second refusal in a row
A lost seat mid-game is the costliest quiet failure this table has: one
refusal around a restart cost Kestrel PRPM's seat with nothing in the
journal to say why.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-17 23:22:00 -04:00
Eric WagonerandClaude Fable 5.1 f738957100 Rev 24: a REFLECTION against a permanent curse afflicts both wizards
"If this spell is REFLECTed, both players take 1/2 point of damage per
space moved" (WALKING DEAD); "In case of REFLECTION, both players are
affected" (IDIOT); SLOW DEATH follows REFLECTION's own rule that a
spell works for both parties. A permanent curse has no duration for
the reflection's split to halve, so the caster went untouched; the
curse is now laid on them as well, as if cast back. Older games replay
as they were; PRPM, reflected at seq 108 with no move since, was
re-stamped to 24 at its table's request.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-17 23:07:41 -04:00
Eric WagonerandClaude Fable 5.1 f26893f45b The reel measures its padding inside its width, so it stays within the share page on a phone
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-17 21:18:35 -04:00
Eric WagonerandClaude Fable 5.1 942e04c821 The reel fits a phone: title on its own line, a smaller caption, controls that stay on screen
The shared replay page had no rules for a narrow screen: the reel's
header stacked into a column, the caption ran large, and the controls
ran off the right edge. Under 640px the title takes its own line with
the count and buttons beneath, the caption reads smaller, and the
controls wrap. The share page also pins its text size against
Safari's inflation.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-17 21:11:48 -04:00
Eric WagonerandClaude Fable 5.1 11dff428f4 The leading casting panel sizes to its card instead of scrolling inside a sliver
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-17 20:49:55 -04:00
Eric WagonerandClaude Fable 5.1 1019cb5a38 The casting panel leads the right column, and a number's movement button sits in the dock
On a laptop the right column scrolls in place, and the turn banner,
the coaching, and the scoresheet pushed the casting panel — where an
attack is answered and a number is played for movement — below the
fold, showing as a sliver. The panel now leads the column while a card
is aimed or a blow answered, and a number's "Play for +N movement"
also stands in the dock beneath the board.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-17 20:48:47 -04:00
Eric WagonerandClaude Fable 5.1 e6ede1aa48 The pulse reads a challenge issue as a caller, not an error
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-17 00:56:06 -04:00
Eric WagonerandClaude Fable 5.1 ba1d1d297f The keeper's bell rings at error level, so Sentry files it as high priority and alerts
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-17 00:36:51 -04:00
Eric WagonerandClaude Fable 5.1 3c10e0463f The raven sets expectations; Create and Join say so when the table is not yet reached
The lobby tells a challenger what to expect in the table's own voice:
the keeper answers every raven, sometimes within the minute, sometimes
after a night's sleep; the seat is held either way, and the table is
theirs meanwhile. A Create or Join tried before the socket is open
used to vanish; it now says the table is still being reached.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-17 00:34:45 -04:00
Eric WagonerandClaude Fable 5.1 1be1cf7d1b A lobby may challenge the keeper, and the table can talk before the boards flip
"Challenge Kestrel, the keeper" holds a seat under the keeper's name,
writes the call to the ledger, says so at the table, and raises a
Sentry issue fingerprinted to the room — one ring per call, with the
room's link in the message — which is the alarm the keeper's phone
listens for. The keeper answers by the link: taking the seat, and
leaving a word if the game must wait. For that word, and for any table
to settle when to start, the lobby now shows its talk and carries a
composer; a joiner sees what was said before they sat. Three calls per
address per hour, one per room.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-17 00:30:49 -04:00
Eric WagonerandClaude Fable 5.1 de279364ce The table-talk count is reactive, so your own words never show as unread
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-17 00:25:07 -04:00
Eric WagonerandClaude Fable 5.1 8582b7feb7 What you missed, in facts; a timeline on the reel; room for table talk
A returning player's slip now lists what happened while they were away
— "Automaton took your treasure.", "You lost 3 life.", "It's your
turn." — each fact opening the catch-up reel at its moment, read from
the missed steps as the server redacted them for that seat; when
nothing touched them it says what each wizard was up to instead. The
reel gains a timeline: a tick per move in the mover's color, taller
where a turn begins, a blow lands, or gold changes hands, and any tick
jumps the reel there.

The chronicle takes a filter — All, Game, Table talk — with an unread
count on the talk that arrived while the casting panel covered it (a
wizard's own words never count), a peek at the latest line above the
composer while the panel is up, and the composer itself no longer
leaves when a response is owed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-17 00:22:54 -04:00
Eric WagonerandClaude Fable 5.1 80dd7a7865 Rev 23: POWER DRAIN drains the number played; the troll punches walls; the first-person stack fits
POWER DRAIN's gain is the number played, BLUNTed or ABSORBed or not
(FAQ: the counter blunts the damage done, not the drain), and a wall
drained for its points gives them up too. Older games gave only what
the opponent lost and nothing from a wall, and replay so.

"This rock-hard beast can punch a player (or a wall, etc.)": a commanded
troll now punches a wall line beside it for a D4, once a turn — a new
command, so no old game changes.

Under the first-person pane the board strip could run into the dock on
a short or tall window; the pane now takes no more height than the row
can spare and the strip shrinks beneath it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-17 00:07:34 -04:00
Eric WagonerandClaude Fable 5.1 803c51415e Rev 22: TELEPORT crosses the maze's outer edge anywhere
A teleporter ignores walls, and the outer edge is no more than a wall
to it: a line leaving the maze at any square's edge re-enters at the
opposite edge on the same row or column, one space on. The lettered
openings connect as they always did. Older games crossed the edge only
at the openings, and replay so; U3U2, dealt at rev 21 with no teleport
yet cast, was re-stamped to 22 at its table's request.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-16 23:56:13 -04:00
Eric WagonerandClaude Fable 5.1 7a6aa3d2a1 View controls above the board, decisions below it, the account beside it
The board's controls had three homes: zoom in the corner, the eyes
toggle floating above it, and the turn's actions wrapping into rows
beneath. Now a toolbar hugs the board's top — First-person at the
left; − · level · + · Fit at the right — and a dock sits beneath it in
three groups: what the square offers, the tools (punch a wall, hints,
discard) set quieter, and draw beside End turn pinned at the right.
While a card is aimed the dock leads with the decision in a line —
"Choose a destination · lit squares are within 4 · ends your movement"
— and a cancel, so the lit squares always say what they mean. The
panel beside the board keeps the card and the full account, now with
the instruction first and discarding demoted to a quiet last resort.
A phone keeps the offers and End turn in view and its tools behind
More. With the hand at the left, the columns grow with the cards so
they no longer overlap.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-16 23:47:10 -04:00
Eric WagonerandClaude Fable 5.1 648f6ab8cd Receipts under resolved attacks; the cast line clears; the table holds still; teleport wraps
Each resolved attack now folds a receipt under its line, read off the
engine's own record: the blow as it came in, what each counter left of
it in the order they were weighed, what landed, and whose life moved.
The resolution event carries the incoming damage and duration and the
trail of counters for it. Hotseat chronicles carry the same.

The line a cast was accepted on stayed on the board: its timer compared
a reactive proxy to the object it held. Kept raw, it clears.

The board jumped while walking. The "sending" note added a line beside
End turn and took it away again, and the refusal toast stood in the
flow above the table for five seconds; both now float and move
nothing.

Teleport reaches through the lettered openings in the engine, but the
board dimmed the squares beyond them. The eligibility map follows the
warps as the engine does.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-16 23:32:34 -04:00
Eric WagonerandClaude Fable 5.1 7d0c1c68a3 A cast that resolved at once draws the sight line it was accepted on
The attack on the stack has always shown its line; a creation or a
curse resolved in the same breath showed nothing, so a legal aim
through a Visionstone and out a lettered opening (PPL7, move 309)
looked like a cheat. The line a cast was accepted on — plain, through
the one wall a VISIONSTONE dissolves, or AROUND THE CORNER's two legs —
now draws on the live board for a few seconds and on that move of any
reel, traced after the fact so the cast's own dust cloud cannot blind it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-16 23:05:32 -04:00
Eric WagonerandClaude Fable 5.1 12a655868b The table says when it is out of reach, a finished table can call a rematch, and spells and treasure read plainly
Connection: while the socket is down a notice says so, the hand, board,
and action buttons go quiet, a card left selected stays selected, and
table talk stays in its box. A command that could not leave is named
as not sent; one that left before the drop is named as unconfirmed
until the board answers. A command on its way shows as sending beside
End turn and confirms when the table replies. Talk shows as sending
until the table echoes it, and comes back to the composer if the
socket drops first.

Rematch: anyone at a finished table may call one. The server makes a
new room hosted by the caller, with the same clockwork at the same
tiers and moods (a mystery stays a mystery) and the same expansion
setting, and keeps seats for the last table's other wizards, who find
the call on the finished table and in their lobby ledger and sit with
one click. The old table's replay stays where it was. A solo table
against the clockwork keeps "play again".

Reading the table: an ongoing spell's chip opens its card with a plain
account — what it does, who cast it on whom, and when it ends, in the
rulebook's own terms. Each score row counts the treasures a wizard has
carried home, and marks a wizard one carry from winning.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-16 22:52:55 -04:00