Skip to content

Game Mechanics

Band Game is a band name chain game where players take turns naming bands. Each band name must start with the last letter of the previous band's canonical name. Names are validated live against the Spotify catalog.

Core Concept

text
Player 1: "Radiohead"       (ends in D)
Player 2: "Deep Purple"     (starts with D, ends in E)
Player 1: "Eagles"          (starts with E, ends in S)
Player 2: "Slayer"          (starts with S, ends in R)
...

A player loses when they submit an invalid band, run out of time, or abandon the match.

Game Modes

ModegameMode valueTurn timeNotes
Default multiplayer'default'20 000 msMatchmaking queue or direct challenge
Lite'lite'liteRoundLengthMs from config (default 20 000 ms)Shorter rounds via admin config
Singleplayer'singleplayer'20 000 msHuman vs bot (BOT_ID = 'bot'), timer skipped for bot turns

Match Flow

  1. Match creation — via matchmaking queue, direct challenge, or singleplayer endpoint
  2. Turn 1 — challenger / first-queued player submits a band (always valid on letter-chain; other rules still apply)
  3. Band revealed — opponent sees the band was played (name hidden until they reveal it); revealing starts the turn timer
  4. Turn alternation — players alternate; currentTurn advances on each valid move
  5. Invalid move — game ends immediately; the player who submitted the invalid move loses
  6. Timeout — game ends; the player who timed out loses
  7. Post-game — XP awarded, stats updated, rematch offered

Game State Structure

typescript
{
  id: string;
  status: 'waiting' | 'active' | 'completed' | 'abandoned';
  gameMode: string;
  players: { id: string; name: string; socketId: string }[];
  currentTurn: string;         // player ID
  moves: GameMove[];
  currentRound: number;        // 1-based; increments when all players have played once
  maxTurnTimeMs: number;       // set at creation, default 20 000
  lastBandName?: string;
  currentTimer?: TurnTimer;
  winner?: string;             // player ID
  createdAt: Date;
  completedAt?: Date;
  powerupsUsed?: Record<string, PowerupType[]>;  // playerId → used types
  activeScramblerLetter?: string;                // set while Scrambler is pending
  zappedBands?: string[];                        // bands excluded from dupe check
}

Win / Loss Conditions

EventLoser
Player submits invalid band (wrong letter, not on Spotify, duplicate, < 500 followers)That player
Turn timer expiresPlayer whose turn it was
Player sends abandonGameThat player
Player sends clientTimeout (validated server-side)That player

Band Visibility (Reveal System)

Bands are not immediately visible to the opponent. This is intentional — the opponent must choose to reveal the band, which simultaneously starts their turn timer.

BandVisible to
Your own bandsAlways visible to you
Opponent's valid band (not yet revealed)Hidden — bandName returned as null
Opponent's valid band (after revealBand)Visible
Opponent's invalid bandAuto-revealed after you make a subsequent valid move

Typing Indicator

  • Client sends playerTyping { gameId, playerId, isTyping } while composing
  • Server relays to opponent only via opponentTyping
  • Cleared automatically on move submission or band reveal
  • Not persisted anywhere

Rematch

  • Available after status is 'completed' or 'abandoned'
  • Requester goes first in the new match
  • Same gameMode as original
  • New match ID generated; original match untouched

Sub-pages

  • Band Name Validation — letter-chain rules, Spotify lookup, duplicate detection, follower threshold
  • Timers & Abandonment — how the turn timer works, timeout handling, grace period
  • XP & Ranks — XP formula, bonuses, rank progression
  • Powerups — Add Time, Zapper, Mirror, Scrambler — rules, UI, and technical reference