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
This commit is contained in:
Eric Wagoner
2026-09-16 22:52:55 -04:00
co-authored by Claude Fable 5.1
parent bc99ee3eb7
commit 12a655868b
5 changed files with 312 additions and 23 deletions
+14 -1
View File
@@ -16,6 +16,19 @@ export interface RoomMetaLine {
hostToken?: string;
seed: number;
createdAt: string;
/** A rematch: the finished room it follows, and the wizards it waits for. */
rematchOf?: string;
expected?: string[];
/** The lobby's expansion default, carried over from the last table. */
expansion?: boolean;
}
/** The finished table called for a rematch: the new room it moved to. */
export interface RematchLine {
kind: "rematch";
to: string;
by: string;
at: string;
}
export interface JoinLine {
@@ -71,7 +84,7 @@ export interface AbandonLine {
at: string;
}
export type RoomLine = RoomMetaLine | JoinLine | StartLine | CommandLine | ChatLine | KickLine | AbandonLine;
export type RoomLine = RoomMetaLine | JoinLine | StartLine | CommandLine | ChatLine | KickLine | AbandonLine | RematchLine;
const DATA_DIR = process.env.WIZWAR_DATA_DIR ?? join(process.cwd(), "data", "rooms");