← Prompts

Chess

Read the current prompt
# Task: Build a Chess Game with AI Opponent

Build fully rule-complete chess against a computer opponent (vanilla JS, no external assets, no CDN, no libraries). The top priority is **rules correctness** — every legal move must be accepted, every illegal move rejected, including all the edge cases.

## Core Specification

**Rules Engine (the heart of the app — no shortcuts)**
- Standard 8×8 board, correct initial position, White moves first
- Full move generation for all pieces, including **all special rules**:
  - Castling (both sides), forbidden while in check, through check, or after king/rook has moved
  - En passant — only on the immediately following move
  - Pawn promotion (to Q/R/B/N, via an under-promotion picker UI)
- A move that leaves your own king in check is illegal and must be rejected
- Check, checkmate, and stalemate detection; also draw by insufficient material (K vs K, K+B vs K, K+N vs K) and 50-move rule
- Move validation is **generator-based**: the UI only offers moves produced by the legal-move generator, so illegal states are unreachable

**Interaction**
- Click-to-move (select piece → legal destination squares highlighted with dots; captures ringed) **and** drag-and-drop — both must work
- Last-move highlight; check shown on the king's square (red glow)
- Flip-board button; captured-pieces trays; move list in algebraic notation (e.g. `Nf3`, `O-O`, `exd6 e.p.`, `Qxd8+`, `#` on mate), auto-scrolling
- Undo (takes back both the player and AI move) and New Game
- Sound effects via Web Audio (move, capture, check) with a mute toggle

**AI Opponent**
- Minimax with alpha-beta pruning, iterative-friendly fixed depth chosen for responsiveness (target ≤ ~1s per move), plus quiescence-lite or move ordering (captures first) to avoid tactical blindness
- Evaluation: material + piece-square tables at minimum
- Player chooses White or Black (and optionally plays both sides / analysis mode); the AI must never make an illegal move or freeze the UI — run the search chunked or in small time slices if needed
- Difficulty selector (depth 1 / 2 / 3)

**Persistence**
- Game state (board, turn, castling rights, en-passant square, move list) serializes to `localStorage` and restores on reload mid-game

## Visual Style
- Elegant, classic chess aesthetic: warm wood or slate board palette, crisp Unicode-piece glyphs (♞♟) or clean inline-SVG pieces, subtle square shading
- Board centered; side panel with move list, captured pieces, controls
- Promotion picker as a small overlay on the promotion square
- Clear turn indicator and game-over banner (checkmate/stalemate/draw, with the result stated)

## Technical Requirements
- Vanilla JS, with clear section comments
- Board representation and move generation cleanly separated from rendering (0x88, mailbox, or bitboards — your choice, but make it readable)
- Tunable constants block at the top (colors, AI depths, eval weights)
- Expose a minimal debug interface on `window` (e.g. `game.fen()`, `game.move('e2e4')`, `game.legalMoves()`) so the engine can be probed headlessly

## Quality Bar (must hit all)
- Castling, en passant, and promotion all work from the UI
- You cannot move into check, and pinned pieces cannot abandon their pin
- Checkmate and stalemate are correctly announced (Fool's mate and a simple back-rank mate both detected)
- The AI at depth 3 does not hang pieces trivially and never returns an illegal move
- A mid-game reload restores the exact position, side to move, castling rights, and en-passant state

## Self-Check Before Finishing
Verify with the browser tools, using the debug interface:
- Fool's mate: `f3 e5 g4 Qh4#` → checkmate announced, no further moves accepted
- Set up an en-passant opportunity and confirm the capture is generated exactly once (only on the immediately following move)
- Attempt a move that exposes the king → rejected by `legalMoves()`
- Play ~10 moves against the AI, reload, confirm identical state
- Position count sanity check: from the start position, `legalMoves()` returns 20