Hotseat setup round: pick a count, then each wizard names themselves

The comma-separated name field is gone. Hotseat now starts with a
2-6 count picker and "Gather N wizards", which opens a naming round
in the pass-the-device style: "Wizard 1 of 3 — what is your name?",
type it, pass the device on; the last wizard's button reads "Flip the
boards" and starts the game. Duplicate and empty names are refused
in place, the roster-so-far shows beneath, and "never mind" backs
out. Verified end to end: three names entered, game started, opening
handoff went to the die-roll winner.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Eric Wagoner
2026-08-16 01:12:13 -04:00
co-authored by Claude Fable 5
parent ac82c28750
commit 98d7dee5c7
2 changed files with 92 additions and 12 deletions
+27
View File
@@ -35,6 +35,8 @@ function actorId(state: GameState): PlayerId {
class LocalGame {
active = $state(false);
/** Hotseat setup round: players name themselves one by one. */
setup = $state<{ count: number; expansion: boolean; names: PlayerId[] } | null>(null);
gameState = $state<GameState | null>(null);
viewerId = $state<PlayerId | null>(null);
/** Set while the device should be handed to the named player. */
@@ -51,6 +53,31 @@ class LocalGame {
return localStorage.getItem(SAVE_KEY) !== null;
}
beginSetup(count: number, expansion: boolean): void {
this.setup = { count, expansion, names: [] };
}
cancelSetup(): void {
this.setup = null;
}
/** One wizard names themselves; the last name starts the game. */
submitName(raw: string): string | null {
if (!this.setup) return "no setup in progress";
const name = raw.trim();
if (!name) return "every wizard needs a name";
if (this.setup.names.some((n) => n.toLowerCase() === name.toLowerCase())) {
return "that name is already taken at this table";
}
this.setup = { ...this.setup, names: [...this.setup.names, name] };
if (this.setup.names.length === this.setup.count) {
const { names, expansion } = this.setup;
this.setup = null;
return this.start(names, expansion);
}
return null;
}
start(names: PlayerId[], expansion: boolean): string | null {
const cleaned = [...new Set(names.map((n) => n.trim()).filter(Boolean))];
if (cleaned.length < 2 || cleaned.length > 6) return "two to six wizards, each with a name";