@maxr0ssi/chaos-chess 0.1.7 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +54 -0
- package/README.md +44 -60
- package/THIRD_PARTY_NOTICES.md +36 -0
- package/dist/chaos-chess.css +1 -1
- package/dist/chaos-chess.js +1049 -678
- package/dist/chaos-chess.js.map +1 -1
- package/dist/index.d.ts +18 -1
- package/package.json +4 -2
package/dist/chaos-chess.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chaos-chess.js","sources":["../src/hooks/useChessGame.ts","../src/engine/stockfishWorker.ts","../src/hooks/useStockfish.ts","../src/types/chess.ts","../src/engine/fenManipulator.ts","../src/engine/chaosEngine.ts","../src/hooks/useChaosEngine.ts","../src/components/PieceIcon.tsx","../src/components/Square.tsx","../src/components/ChessBoard.tsx","../src/components/PromotionDialog.tsx","../src/components/GameOverBanner.tsx","../src/components/ChaosTimer.tsx","../src/components/ChaosToast.tsx","../src/components/DifficultySelector.tsx","../src/components/StupidLevel.tsx","../src/components/SidePicker.tsx","../src/components/MuteButton.tsx","../src/utils/sounds.ts","../src/ChessGame.tsx"],"sourcesContent":["import { useState, useRef, useCallback } from 'react';\nimport { Chess } from 'chess.js';\nimport type { Square as ChessSquare, Move, Piece } from 'chess.js';\nimport type { GameStatus, PromotionPending, MoveHistoryEntry, Color } from '../types/chess.ts';\n\ninterface LastMove {\n from: ChessSquare;\n to: ChessSquare;\n}\n\nexport interface LastMoveDetail {\n captured: boolean;\n check: boolean;\n}\n\nexport interface UseChessGameReturn {\n fen: string;\n turn: 'w' | 'b';\n selectedSquare: ChessSquare | null;\n legalMoves: ChessSquare[];\n gameStatus: GameStatus;\n promotionPending: PromotionPending | null;\n moveHistory: MoveHistoryEntry[];\n lastMove: LastMove | null;\n lastMoveDetail: LastMoveDetail | null;\n handleSquareClick: (square: ChessSquare) => void;\n handlePromotion: (piece: 'q' | 'r' | 'b' | 'n') => void;\n applyFen: (newFen: string) => void;\n board: (Piece | null)[][];\n handleRestart: () => void;\n}\n\nfunction getGameStatus(chess: Chess): GameStatus {\n if (!chess.isGameOver()) {\n const inCheck = chess.inCheck() ? chess.turn() : null;\n return { isGameOver: false, result: null, winner: null, inCheck };\n }\n\n if (chess.isCheckmate()) {\n const winner: Color = chess.turn() === 'w' ? 'b' : 'w';\n return { isGameOver: true, result: 'checkmate', winner, inCheck: chess.turn() };\n }\n if (chess.isStalemate()) {\n return { isGameOver: true, result: 'stalemate', winner: null, inCheck: null };\n }\n if (chess.isInsufficientMaterial()) {\n return { isGameOver: true, result: 'insufficient', winner: null, inCheck: null };\n }\n if (chess.isThreefoldRepetition()) {\n return { isGameOver: true, result: 'threefold', winner: null, inCheck: null };\n }\n // 50-move rule or other draw\n return { isGameOver: true, result: 'draw', winner: null, inCheck: null };\n}\n\nexport function useChessGame() {\n const chessRef = useRef(new Chess());\n const [fen, setFen] = useState(chessRef.current.fen());\n const [turn, setTurn] = useState<'w' | 'b'>(chessRef.current.turn());\n const [selectedSquare, setSelectedSquare] = useState<ChessSquare | null>(null);\n const [legalMoves, setLegalMoves] = useState<ChessSquare[]>([]);\n const [gameStatus, setGameStatus] = useState<GameStatus>(getGameStatus(chessRef.current));\n const [promotionPending, setPromotionPending] = useState<PromotionPending | null>(null);\n const [moveHistory, setMoveHistory] = useState<MoveHistoryEntry[]>([]);\n const [lastMove, setLastMove] = useState<LastMove | null>(null);\n const [lastMoveDetail, setLastMoveDetail] = useState<LastMoveDetail | null>(null);\n const [board, setBoard] = useState<(Piece | null)[][]>(chessRef.current.board());\n\n const clearSelection = useCallback(() => {\n setSelectedSquare(null);\n setLegalMoves([]);\n }, []);\n\n const syncState = useCallback(() => {\n setFen(chessRef.current.fen());\n setTurn(chessRef.current.turn());\n setBoard(chessRef.current.board());\n setGameStatus(getGameStatus(chessRef.current));\n }, []);\n\n const handleSquareClick = useCallback((square: ChessSquare) => {\n const chess = chessRef.current;\n const turn = chess.turn();\n\n // Ignore clicks during promotion or game over\n if (promotionPending || getGameStatus(chess).isGameOver) {\n return;\n }\n\n // If we have a selected square and this click is a legal move destination\n if (selectedSquare && legalMoves.includes(square)) {\n // Check if this is a pawn promotion\n const piece = chess.get(selectedSquare);\n if (\n piece?.type === 'p' &&\n ((piece.color === 'w' && square[1] === '8') ||\n (piece.color === 'b' && square[1] === '1'))\n ) {\n setPromotionPending({ from: selectedSquare, to: square });\n clearSelection();\n return;\n }\n\n // Execute the move\n try {\n const move = chess.move({ from: selectedSquare, to: square });\n if (move) {\n setLastMove({ from: move.from, to: move.to });\n setLastMoveDetail({ captured: !!move.captured, check: move.san.includes('+') || move.san.includes('#') });\n setMoveHistory((prev) => [\n ...prev,\n { san: move.san, fen: chess.fen(), color: move.color },\n ]);\n }\n } catch {\n // Invalid move, just deselect\n }\n clearSelection();\n syncState();\n return;\n }\n\n // If clicking on a piece belonging to the side-to-move, select it\n const piece = chess.get(square);\n if (piece && piece.color === turn) {\n if (square === selectedSquare) {\n clearSelection();\n return;\n }\n setSelectedSquare(square);\n const moves = chess.moves({ square, verbose: true }) as Move[];\n setLegalMoves(moves.map((m) => m.to));\n return;\n }\n\n // Clicking empty square or opponent piece without selection\n clearSelection();\n }, [selectedSquare, legalMoves, promotionPending, clearSelection, syncState]);\n\n const handlePromotion = useCallback((piece: 'q' | 'r' | 'b' | 'n') => {\n if (!promotionPending) return;\n const chess = chessRef.current;\n try {\n const move = chess.move({\n from: promotionPending.from,\n to: promotionPending.to,\n promotion: piece,\n });\n if (move) {\n setLastMove({ from: move.from, to: move.to });\n setLastMoveDetail({ captured: !!move.captured, check: move.san.includes('+') || move.san.includes('#') });\n setMoveHistory((prev) => [\n ...prev,\n { san: move.san, fen: chess.fen(), color: move.color },\n ]);\n }\n } catch {\n // Invalid promotion, ignore\n }\n setPromotionPending(null);\n clearSelection();\n syncState();\n }, [promotionPending, clearSelection, syncState]);\n\n const applyFen = useCallback((newFen: string) => {\n const chess = chessRef.current;\n try {\n chess.load(newFen);\n clearSelection();\n syncState();\n } catch {\n // Invalid FEN, ignore\n }\n }, [clearSelection, syncState]);\n\n const handleRestart = useCallback(() => {\n const chess = chessRef.current;\n chess.reset();\n clearSelection();\n setMoveHistory([]);\n setLastMove(null);\n setLastMoveDetail(null);\n setPromotionPending(null);\n syncState();\n }, [clearSelection, syncState]);\n\n return {\n fen,\n turn,\n selectedSquare,\n legalMoves,\n gameStatus,\n promotionPending,\n moveHistory,\n lastMove,\n lastMoveDetail,\n board,\n handleSquareClick,\n handlePromotion,\n applyFen,\n handleRestart,\n } satisfies UseChessGameReturn;\n}\n","/**\n * Wraps the Stockfish WASM Web Worker with a promise-based API.\n *\n * Uses the UCI protocol's `isready`/`readyok` handshake to flush stale\n * `bestmove` responses after `stop`, preventing a new search's listener\n * from picking up results from a cancelled search.\n */\nexport class StockfishEngine {\n private worker: Worker | null = null;\n private resolveMove: ((move: string | null) => void) | null = null;\n private rejectMove: ((reason: Error) => void) | null = null;\n private currentListener: ((e: MessageEvent) => void) | null = null;\n private timeoutId: ReturnType<typeof setTimeout> | null = null;\n private searchId = 0;\n private workerPath: string;\n\n constructor(workerPath = '/stockfish/stockfish-18-lite-single.js') {\n this.workerPath = workerPath;\n }\n\n async init(): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n try {\n this.worker = new Worker(this.workerPath);\n const onReady = (e: MessageEvent) => {\n const msg = typeof e.data === 'string' ? e.data : '';\n if (msg.includes('uciok')) {\n this.worker?.removeEventListener('message', onReady);\n resolve();\n }\n };\n this.worker.addEventListener('message', onReady);\n this.worker.addEventListener('error', (e) => {\n reject(new Error(`Stockfish worker error: ${e.message}`));\n });\n this.worker.postMessage('uci');\n } catch (err) {\n reject(err);\n }\n });\n }\n\n /** Cancel any in-flight search and clean up its listener/promise/timer. */\n private cancelPending(): void {\n if (this.timeoutId !== null) {\n clearTimeout(this.timeoutId);\n this.timeoutId = null;\n }\n if (this.currentListener && this.worker) {\n this.worker.removeEventListener('message', this.currentListener);\n this.currentListener = null;\n }\n if (this.rejectMove) {\n this.rejectMove(new Error('Search cancelled'));\n this.resolveMove = null;\n this.rejectMove = null;\n }\n this.stop();\n }\n\n /**\n * Send `isready` and wait for `readyok`.\n * This flushes any stale `bestmove` from a prior `stop` command,\n * guaranteeing the message queue is clean before a new search starts.\n */\n private waitReady(): Promise<void> {\n return new Promise<void>((resolve) => {\n if (!this.worker) { resolve(); return; }\n\n const onMessage = (e: MessageEvent) => {\n const msg = typeof e.data === 'string' ? e.data : '';\n if (msg === 'readyok') {\n this.worker?.removeEventListener('message', onMessage);\n resolve();\n }\n // Silently consume any other messages (including stale bestmove)\n };\n\n this.worker.addEventListener('message', onMessage);\n this.worker.postMessage('isready');\n });\n }\n\n /**\n * Get the best move for a given FEN position at the specified depth.\n * Returns a UCI move string like \"e2e4\".\n * Calling this while a search is in-flight cancels the previous search.\n */\n async getBestMove(fen: string, depth: number, timeoutMs = 10000): Promise<string | null> {\n // Cancel any in-flight search before starting a new one\n this.cancelPending();\n\n // Flush stale bestmove from the stopped search via UCI isready/readyok\n await this.waitReady();\n\n const mySearchId = ++this.searchId;\n\n return new Promise<string | null>((resolve, reject) => {\n if (!this.worker) {\n reject(new Error('Stockfish not initialized'));\n return;\n }\n\n this.resolveMove = resolve;\n this.rejectMove = reject;\n\n this.timeoutId = setTimeout(() => {\n // Only cancel if this timeout belongs to the current search\n if (this.searchId === mySearchId) {\n this.cancelPending();\n }\n }, timeoutMs);\n\n const onMessage = (e: MessageEvent) => {\n const msg = typeof e.data === 'string' ? e.data : '';\n if (msg.startsWith('bestmove')) {\n if (this.timeoutId !== null) {\n clearTimeout(this.timeoutId);\n this.timeoutId = null;\n }\n this.worker?.removeEventListener('message', onMessage);\n this.currentListener = null;\n const move = msg.split(' ')[1];\n if (this.resolveMove) {\n // \"(none)\" means no legal move exists — resolve with null instead of rejecting.\n // This is expected in chaos chess where piece mutations can create such positions.\n this.resolveMove(move && move !== '(none)' ? move : null);\n this.resolveMove = null;\n this.rejectMove = null;\n }\n }\n };\n\n this.currentListener = onMessage;\n this.worker.addEventListener('message', onMessage);\n // Clear transposition table so chaos-mutated boards start from a clean slate\n this.worker.postMessage('ucinewgame');\n this.worker.postMessage(`position fen ${fen}`);\n this.worker.postMessage(`go depth ${depth}`);\n });\n }\n\n /**\n * Stop any current search.\n */\n stop(): void {\n this.worker?.postMessage('stop');\n }\n\n /**\n * Terminate the worker.\n */\n destroy(): void {\n this.cancelPending();\n this.worker?.postMessage('quit');\n this.worker?.terminate();\n this.worker = null;\n }\n}\n","import { useState, useRef, useEffect, useCallback } from 'react';\nimport { StockfishEngine } from '../engine/stockfishWorker.ts';\n\ninterface UseStockfishReturn {\n isReady: boolean;\n isThinking: boolean;\n getBestMove: (fen: string, depth: number) => Promise<string | null>;\n}\n\nexport function useStockfish(workerPath?: string): UseStockfishReturn {\n const engineRef = useRef<StockfishEngine | null>(null);\n const [isReady, setIsReady] = useState(false);\n const [isThinking, setIsThinking] = useState(false);\n // Track in-flight calls so only the latest one controls isThinking\n const callIdRef = useRef(0);\n\n useEffect(() => {\n const engine = new StockfishEngine(workerPath);\n engineRef.current = engine;\n\n engine\n .init()\n .then(() => setIsReady(true))\n .catch((err) => {\n console.warn('Stockfish failed to load:', err.message);\n });\n\n return () => {\n engine.destroy();\n engineRef.current = null;\n };\n }, []);\n\n const getBestMove = useCallback(\n async (fen: string, depth: number): Promise<string | null> => {\n if (!engineRef.current || !isReady) return null;\n const myCallId = ++callIdRef.current;\n setIsThinking(true);\n\n // Safety timeout: clear isThinking if getBestMove hasn't resolved in 15s\n const safetyTimeout = setTimeout(() => {\n if (callIdRef.current === myCallId) {\n console.warn('[ChaosChess] Safety timeout: clearing isThinking after 15s');\n setIsThinking(false);\n }\n }, 15000);\n\n try {\n // Resolves a move string, or null only when the engine reports \"(none)\"\n // (a genuinely dead position). A cancelled/superseded or timed-out search\n // REJECTS instead, so callers can tell \"no legal move\" apart from\n // \"interrupted, try again\" and avoid permanently giving up on a position.\n const move = await engineRef.current.getBestMove(fen, depth);\n return move;\n } finally {\n clearTimeout(safetyTimeout);\n // Only clear isThinking if no newer call has started\n if (callIdRef.current === myCallId) {\n setIsThinking(false);\n }\n }\n },\n [isReady]\n );\n\n return { isReady, isThinking, getBestMove };\n}\n","import type { Square as ChessSquare, PieceSymbol, Color } from 'chess.js';\n\nexport type { ChessSquare, PieceSymbol, Color };\n\nexport type GameResult = 'checkmate' | 'stalemate' | 'draw' | 'insufficient' | 'threefold' | 'fifty-move';\n\nexport interface GameStatus {\n isGameOver: boolean;\n result: GameResult | null;\n winner: Color | null;\n inCheck: Color | null;\n}\n\nexport type ChaosActionType = 'add' | 'remove';\nexport type ChaosTarget = 'help_white' | 'help_black';\n\nexport interface ChaosAction {\n type: ChaosActionType;\n target: ChaosTarget;\n square: ChessSquare;\n piece?: PieceSymbol;\n color?: Color;\n whiteMaterial: number;\n blackMaterial: number;\n}\n\nexport interface PromotionPending {\n from: ChessSquare;\n to: ChessSquare;\n}\n\nexport interface MoveHistoryEntry {\n san: string;\n fen: string;\n color: Color;\n}\n\nexport interface MaterialCount {\n white: number;\n black: number;\n}\n\nexport const PIECE_VALUES: Record<PieceSymbol, number> = {\n p: 1,\n n: 3,\n b: 3,\n r: 5,\n q: 9,\n k: 0,\n};\n\n// Filled symbols for white (bright on dark bg), outlines for black\n// \\uFE0E = Variation Selector 15 — forces text presentation on iOS\n// (without it, iOS renders some glyphs as color emoji)\nexport const PIECE_UNICODE: Record<string, string> = {\n wk: '\\u265A\\uFE0E',\n wq: '\\u265B\\uFE0E',\n wr: '\\u265C\\uFE0E',\n wb: '\\u265D\\uFE0E',\n wn: '\\u265E\\uFE0E',\n wp: '\\u265F\\uFE0E',\n bk: '\\u2654\\uFE0E',\n bq: '\\u2655\\uFE0E',\n br: '\\u2656\\uFE0E',\n bb: '\\u2657\\uFE0E',\n bn: '\\u2658\\uFE0E',\n bp: '\\u2659\\uFE0E',\n};\n","import type { PieceSymbol, Color, ChessSquare, MaterialCount } from '../types/chess.ts';\nimport { PIECE_VALUES } from '../types/chess.ts';\n\nexport interface FenPiece {\n type: PieceSymbol;\n color: Color;\n}\n\nexport type Board8x8 = (FenPiece | null)[][];\n\nconst FILES = 'abcdefgh';\n\n/**\n * Parse a FEN string into its components.\n */\nexport function parseFen(fen: string) {\n const parts = fen.split(' ');\n return {\n position: parts[0],\n activeColor: parts[1] as Color,\n castling: parts[2],\n enPassant: parts[3],\n halfmove: parts[4],\n fullmove: parts[5],\n };\n}\n\n/**\n * Convert the position segment of a FEN into an 8x8 board array.\n * board[rank][file] where rank 0 = rank 8 (top), rank 7 = rank 1 (bottom).\n */\nexport function positionToBoard(position: string): Board8x8 {\n const board: Board8x8 = [];\n const ranks = position.split('/');\n for (const rank of ranks) {\n const row: (FenPiece | null)[] = [];\n for (const ch of rank) {\n const emptyCount = parseInt(ch);\n if (!isNaN(emptyCount)) {\n for (let i = 0; i < emptyCount; i++) row.push(null);\n } else {\n const color: Color = ch === ch.toUpperCase() ? 'w' : 'b';\n const type = ch.toLowerCase() as PieceSymbol;\n row.push({ type, color });\n }\n }\n board.push(row);\n }\n return board;\n}\n\n/**\n * Convert an 8x8 board array back to a FEN position string.\n */\nexport function boardToPosition(board: Board8x8): string {\n return board\n .map((row) => {\n let rankStr = '';\n let emptyCount = 0;\n for (const cell of row) {\n if (cell === null) {\n emptyCount++;\n } else {\n if (emptyCount > 0) {\n rankStr += emptyCount;\n emptyCount = 0;\n }\n const ch = cell.color === 'w' ? cell.type.toUpperCase() : cell.type;\n rankStr += ch;\n }\n }\n if (emptyCount > 0) rankStr += emptyCount;\n return rankStr;\n })\n .join('/');\n}\n\n/**\n * Serialize FEN components back into a FEN string.\n */\nexport function serializeFen(parts: ReturnType<typeof parseFen>): string {\n return `${parts.position} ${parts.activeColor} ${parts.castling} ${parts.enPassant} ${parts.halfmove} ${parts.fullmove}`;\n}\n\n/**\n * Calculate material values for both sides from a FEN string.\n */\nexport function calculateMaterial(fen: string): MaterialCount {\n const { position } = parseFen(fen);\n const board = positionToBoard(position);\n let white = 0;\n let black = 0;\n for (const row of board) {\n for (const cell of row) {\n if (cell) {\n const value = PIECE_VALUES[cell.type];\n if (cell.color === 'w') white += value;\n else black += value;\n }\n }\n }\n return { white, black };\n}\n\n/**\n * Get all empty squares on the board.\n */\nexport function getEmptySquares(fen: string): ChessSquare[] {\n const { position } = parseFen(fen);\n const board = positionToBoard(position);\n const squares: ChessSquare[] = [];\n for (let rank = 0; rank < 8; rank++) {\n for (let file = 0; file < 8; file++) {\n if (board[rank][file] === null) {\n squares.push(`${FILES[file]}${8 - rank}` as ChessSquare);\n }\n }\n }\n return squares;\n}\n\n/**\n * Get all squares occupied by pieces of a given color (optionally excluding king).\n */\nexport function getPieceSquares(\n fen: string,\n color: Color,\n excludeKing = true\n): ChessSquare[] {\n const { position } = parseFen(fen);\n const board = positionToBoard(position);\n const squares: ChessSquare[] = [];\n for (let rank = 0; rank < 8; rank++) {\n for (let file = 0; file < 8; file++) {\n const cell = board[rank][file];\n if (cell && cell.color === color) {\n if (excludeKing && cell.type === 'k') continue;\n squares.push(`${FILES[file]}${8 - rank}` as ChessSquare);\n }\n }\n }\n return squares;\n}\n\n/**\n * Convert a square name (e.g. 'e4') to board array indices [rank, file].\n */\nexport function squareToIndices(square: ChessSquare): [number, number] {\n const file = FILES.indexOf(square[0]);\n const rank = 8 - parseInt(square[1]);\n return [rank, file];\n}\n\n/**\n * Add a piece to the board at a given square, returning a new FEN.\n */\nexport function addPieceToFen(\n fen: string,\n square: ChessSquare,\n piece: PieceSymbol,\n color: Color\n): string {\n const parts = parseFen(fen);\n const board = positionToBoard(parts.position);\n const [rank, file] = squareToIndices(square);\n board[rank][file] = { type: piece, color };\n parts.position = boardToPosition(board);\n return serializeFen(parts);\n}\n\n/**\n * Remove a piece from the board at a given square, returning a new FEN.\n */\nexport function removePieceFromFen(\n fen: string,\n square: ChessSquare\n): string {\n const parts = parseFen(fen);\n const board = positionToBoard(parts.position);\n const [rank, file] = squareToIndices(square);\n board[rank][file] = null;\n parts.position = boardToPosition(board);\n return serializeFen(parts);\n}\n","import { Chess } from 'chess.js';\nimport type { PieceSymbol, Color, ChessSquare, ChaosAction, ChaosTarget } from '../types/chess.ts';\nimport {\n calculateMaterial,\n getEmptySquares,\n getPieceSquares,\n addPieceToFen,\n removePieceFromFen,\n} from './fenManipulator.ts';\n\nconst ADDABLE_PIECES: PieceSymbol[] = ['p', 'n', 'b', 'r', 'q'];\nconst MAX_RETRIES = 3;\n\n/**\n * Determine which side to help based on material balance.\n * 70% chance to help the losing side, 30% chance to help the winning side.\n * Equal material = 50/50.\n */\nexport function getChaosTarget(whiteMaterial: number, blackMaterial: number): ChaosTarget {\n if (whiteMaterial > blackMaterial) {\n return Math.random() < 0.7 ? 'help_black' : 'help_white';\n } else if (blackMaterial > whiteMaterial) {\n return Math.random() < 0.7 ? 'help_white' : 'help_black';\n }\n return Math.random() < 0.5 ? 'help_white' : 'help_black';\n}\n\n/**\n * Pick a random element from an array.\n */\nfunction randomChoice<T>(arr: T[]): T {\n return arr[Math.floor(Math.random() * arr.length)];\n}\n\n/**\n * Choose a random piece type to add.\n * If the target square is on rank 1 or 8, avoid pawns.\n */\nfunction chooseRandomPiece(square: ChessSquare): PieceSymbol {\n const rank = parseInt(square[1]);\n if (rank === 1 || rank === 8) {\n // No pawns on first/last rank\n const noPawns: PieceSymbol[] = ['n', 'b', 'r', 'q'];\n return randomChoice(noPawns);\n }\n return randomChoice(ADDABLE_PIECES);\n}\n\n/**\n * Validate that a FEN can be loaded by chess.js (position is legal enough to continue).\n */\nexport function isValidChaosPosition(fen: string): boolean {\n try {\n const test = new Chess();\n test.load(fen);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Try to add a random piece for the given color.\n * Returns { newFen, action } or null if impossible.\n */\nexport function addRandomPiece(\n fen: string,\n color: Color\n): { newFen: string; square: ChessSquare; piece: PieceSymbol } | null {\n const emptySquares = getEmptySquares(fen);\n if (emptySquares.length === 0) return null;\n\n for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {\n const square = randomChoice(emptySquares);\n const piece = chooseRandomPiece(square);\n const newFen = addPieceToFen(fen, square, piece, color);\n if (isValidChaosPosition(newFen)) {\n return { newFen, square, piece };\n }\n }\n return null;\n}\n\n/**\n * Try to remove a random piece of the given color (excluding king).\n * Returns { newFen, square } or null if impossible.\n */\nexport function removeRandomPiece(\n fen: string,\n color: Color\n): { newFen: string; square: ChessSquare } | null {\n const pieceSquares = getPieceSquares(fen, color, true);\n if (pieceSquares.length === 0) return null;\n\n for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {\n const square = randomChoice(pieceSquares);\n // Extra safety: don't remove a piece on rank 1/8 if it's the only defender...\n // Actually, the Python version doesn't check this. Just remove and validate.\n const newFen = removePieceFromFen(fen, square);\n if (isValidChaosPosition(newFen)) {\n return { newFen, square };\n }\n }\n return null;\n}\n\n/**\n * Execute one chaos action: evaluate material, pick target side, randomly add or remove.\n * Returns the action details and new FEN, or null if no valid action was found.\n */\nexport function executeChaosAction(fen: string): { newFen: string; action: ChaosAction } | null {\n const { white: whiteMaterial, black: blackMaterial } = calculateMaterial(fen);\n const target = getChaosTarget(whiteMaterial, blackMaterial);\n const operation = Math.random() < 0.5 ? 'add' : 'remove';\n\n // Determine which color to add to / remove from\n const addColor: Color = target === 'help_white' ? 'w' : 'b';\n const removeColor: Color = target === 'help_white' ? 'b' : 'w';\n\n if (operation === 'add') {\n const result = addRandomPiece(fen, addColor);\n if (result) {\n return {\n newFen: result.newFen,\n action: {\n type: 'add',\n target,\n square: result.square,\n piece: result.piece,\n color: addColor,\n whiteMaterial,\n blackMaterial,\n },\n };\n }\n // Fallback: try remove instead\n const fallback = removeRandomPiece(fen, removeColor);\n if (fallback) {\n return {\n newFen: fallback.newFen,\n action: {\n type: 'remove',\n target,\n square: fallback.square,\n whiteMaterial,\n blackMaterial,\n },\n };\n }\n } else {\n const result = removeRandomPiece(fen, removeColor);\n if (result) {\n return {\n newFen: result.newFen,\n action: {\n type: 'remove',\n target,\n square: result.square,\n whiteMaterial,\n blackMaterial,\n },\n };\n }\n // Fallback: try add instead\n const fallback = addRandomPiece(fen, addColor);\n if (fallback) {\n return {\n newFen: fallback.newFen,\n action: {\n type: 'add',\n target,\n square: fallback.square,\n piece: fallback.piece,\n color: addColor,\n whiteMaterial,\n blackMaterial,\n },\n };\n }\n }\n\n return null;\n}\n\n/**\n * Uniform distribution for chaos interval, parameterized by stupid level (1-5).\n *\n * Level 1: 12–20s (chill)\n * Level 2: 8–15s (moderate)\n * Level 3: 5–12s (default)\n * Level 4: 3–7s (chaotic)\n * Level 5: 1–4s (insane)\n */\nconst STUPID_BOUNDS: [number, number][] = [\n [12, 20], // level 1\n [8, 15], // level 2\n [5, 12], // level 3\n [3, 7], // level 4\n [1, 4], // level 5\n];\n\nexport function getRandomChaosInterval(stupidLevel: number = 3): number {\n const idx = Math.max(0, Math.min(4, stupidLevel - 1));\n const [lo, hi] = STUPID_BOUNDS[idx];\n const seconds = lo + Math.random() * (hi - lo);\n return seconds * 1000;\n}\n","import { useState, useEffect, useRef, useCallback } from 'react';\nimport { executeChaosAction, getRandomChaosInterval } from '../engine/chaosEngine.ts';\nimport type { ChaosAction, ChessSquare } from '../types/chess.ts';\n\ninterface UseChaosEngineParams {\n fen: string;\n isPaused: boolean;\n stupidLevel: number;\n onChaosAction: (newFen: string) => void;\n}\n\ninterface UseChaosEngineReturn {\n countdown: number;\n maxCountdown: number;\n lastAction: ChaosAction | null;\n chaosSquare: ChessSquare | null;\n}\n\nexport function useChaosEngine({\n fen,\n isPaused,\n stupidLevel,\n onChaosAction,\n}: UseChaosEngineParams): UseChaosEngineReturn {\n const [countdown, setCountdown] = useState(0);\n const [maxCountdown, setMaxCountdown] = useState(0);\n const [lastAction, setLastAction] = useState<ChaosAction | null>(null);\n const [chaosSquare, setChaosSquare] = useState<ChessSquare | null>(null);\n\n const fenRef = useRef(fen);\n const isPausedRef = useRef(isPaused);\n const stupidLevelRef = useRef(stupidLevel);\n const onChaosActionRef = useRef(onChaosAction);\n const targetTimeRef = useRef<number>(0);\n const intervalIdRef = useRef<ReturnType<typeof setInterval> | null>(null);\n\n fenRef.current = fen;\n isPausedRef.current = isPaused;\n stupidLevelRef.current = stupidLevel;\n onChaosActionRef.current = onChaosAction;\n\n const scheduleNext = useCallback(() => {\n const intervalMs = getRandomChaosInterval(stupidLevelRef.current);\n const seconds = Math.ceil(intervalMs / 1000);\n setMaxCountdown(seconds);\n setCountdown(seconds);\n targetTimeRef.current = Date.now() + intervalMs;\n }, []);\n\n useEffect(() => {\n // Initial schedule\n scheduleNext();\n\n intervalIdRef.current = setInterval(() => {\n if (isPausedRef.current) return;\n\n const remaining = Math.max(0, Math.ceil((targetTimeRef.current - Date.now()) / 1000));\n setCountdown(remaining);\n\n if (remaining <= 0) {\n if (isPausedRef.current) {\n scheduleNext();\n return;\n }\n // Fire chaos action\n const result = executeChaosAction(fenRef.current);\n if (result) {\n setLastAction(result.action);\n setChaosSquare(result.action.square);\n onChaosActionRef.current(result.newFen);\n\n // Clear chaos square highlight after animation\n setTimeout(() => setChaosSquare(null), 600);\n }\n scheduleNext();\n }\n }, 200);\n\n return () => {\n if (intervalIdRef.current) clearInterval(intervalIdRef.current);\n };\n }, [scheduleNext]);\n\n // Pause: push target time forward so countdown freezes\n const lastPauseRef = useRef<number | null>(null);\n useEffect(() => {\n if (isPaused) {\n lastPauseRef.current = Date.now();\n } else if (lastPauseRef.current !== null) {\n const pausedDuration = Date.now() - lastPauseRef.current;\n targetTimeRef.current += pausedDuration;\n lastPauseRef.current = null;\n }\n }, [isPaused]);\n\n return { countdown, maxCountdown, lastAction, chaosSquare };\n}\n","import type { PieceSymbol, Color } from '../types/chess.ts';\nimport { PIECE_UNICODE } from '../types/chess.ts';\nimport styles from '../styles/Square.module.css';\n\ninterface PieceIconProps {\n type: PieceSymbol;\n color: Color;\n className?: string;\n}\n\nexport function PieceIcon({ type, color, className }: PieceIconProps) {\n const key = `${color}${type}`;\n const symbol = PIECE_UNICODE[key];\n if (!symbol) return null;\n const colorClass = color === 'w' ? styles.pieceWhite : styles.pieceBlack;\n return <span className={`${className ?? ''} ${colorClass}`}>{symbol}</span>;\n}\n","import type { Square as ChessSquare, Piece } from 'chess.js';\nimport { PieceIcon } from './PieceIcon.tsx';\nimport styles from '../styles/Square.module.css';\nimport boardStyles from '../styles/ChessBoard.module.css';\n\ninterface SquareProps {\n square: ChessSquare;\n piece: Piece | null;\n isLight: boolean;\n isSelected: boolean;\n isLegalMove: boolean;\n isCheck: boolean;\n isLastMoveFrom: boolean;\n isLastMoveTo: boolean;\n isChaosFlash: boolean;\n rankLabel?: string | number;\n fileLabel?: string;\n onClick: (square: ChessSquare) => void;\n}\n\nexport function Square({\n square,\n piece,\n isLight,\n isSelected,\n isLegalMove,\n isCheck,\n isLastMoveFrom,\n isLastMoveTo,\n isChaosFlash,\n rankLabel,\n fileLabel,\n onClick,\n}: SquareProps) {\n const classNames = [\n styles.square,\n isLight ? styles.light : styles.dark,\n isSelected && styles.selected,\n isLegalMove && (piece ? styles.legalCapture : styles.legalMove),\n isCheck && styles.check,\n !isSelected && !isCheck && isLastMoveFrom && styles.lastMoveFrom,\n !isSelected && !isCheck && isLastMoveTo && styles.lastMoveTo,\n isChaosFlash && styles.chaosFlash,\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <div className={classNames} onClick={() => onClick(square)}>\n {piece && (\n <PieceIcon\n type={piece.type}\n color={piece.color}\n className={styles.piece}\n />\n )}\n {rankLabel != null && (\n <span className={boardStyles.rankLabel}>{rankLabel}</span>\n )}\n {fileLabel != null && (\n <span className={boardStyles.fileLabel}>{fileLabel}</span>\n )}\n </div>\n );\n}\n","import React from 'react';\nimport type { Square as ChessSquare, Piece } from 'chess.js';\nimport { Square } from './Square.tsx';\nimport styles from '../styles/ChessBoard.module.css';\n\ninterface LastMove {\n from: ChessSquare;\n to: ChessSquare;\n}\n\ninterface ChessBoardProps {\n board: (Piece | null)[][];\n selectedSquare: ChessSquare | null;\n legalMoves: ChessSquare[];\n inCheck: 'w' | 'b' | null;\n lastMove: LastMove | null;\n chaosSquare: ChessSquare | null;\n flipped: boolean;\n locked: boolean;\n onSquareClick: (square: ChessSquare) => void;\n}\n\nconst FILES = 'abcdefgh';\n\nfunction getSquareName(rank: number, file: number): ChessSquare {\n // board[0] = rank 8, board[7] = rank 1 (white at bottom)\n return `${FILES[file]}${8 - rank}` as ChessSquare;\n}\n\nfunction isLightSquare(rank: number, file: number): boolean {\n return (rank + file) % 2 === 0;\n}\n\nexport const ChessBoard = React.memo(function ChessBoard({\n board,\n selectedSquare,\n legalMoves,\n inCheck,\n lastMove,\n chaosSquare,\n flipped,\n locked,\n onSquareClick,\n}: ChessBoardProps) {\n // Find king squares for check highlighting\n let checkSquare: ChessSquare | null = null;\n if (inCheck) {\n for (let r = 0; r < 8; r++) {\n for (let f = 0; f < 8; f++) {\n const piece = board[r][f];\n if (piece?.type === 'k' && piece.color === inCheck) {\n checkSquare = getSquareName(r, f);\n }\n }\n }\n }\n\n // Build iteration order based on flipped state\n const rankOrder = flipped ? [7, 6, 5, 4, 3, 2, 1, 0] : [0, 1, 2, 3, 4, 5, 6, 7];\n const fileOrder = flipped ? [7, 6, 5, 4, 3, 2, 1, 0] : [0, 1, 2, 3, 4, 5, 6, 7];\n\n return (\n <div className={`${styles.board}${locked ? ` ${styles.boardLocked}` : ''}`}>\n {rankOrder.map((rankIdx) =>\n fileOrder.map((fileIdx) => {\n const square = getSquareName(rankIdx, fileIdx);\n const piece = board[rankIdx][fileIdx];\n\n // Display row/col indices for labels\n const displayRow = rankOrder.indexOf(rankIdx);\n const displayCol = fileOrder.indexOf(fileIdx);\n\n return (\n <Square\n key={square}\n square={square}\n piece={piece}\n isLight={isLightSquare(rankIdx, fileIdx)}\n isSelected={square === selectedSquare}\n isLegalMove={legalMoves.includes(square)}\n isCheck={square === checkSquare}\n isLastMoveFrom={lastMove?.from === square}\n isLastMoveTo={lastMove?.to === square}\n isChaosFlash={chaosSquare === square}\n rankLabel={displayCol === 0 ? 8 - rankIdx : undefined}\n fileLabel={displayRow === 7 ? FILES[fileIdx] : undefined}\n onClick={onSquareClick}\n />\n );\n })\n )}\n </div>\n );\n});\n","import { PieceIcon } from './PieceIcon.tsx';\nimport styles from '../styles/components.module.css';\n\ninterface PromotionDialogProps {\n color: 'w' | 'b';\n onSelect: (piece: 'q' | 'r' | 'b' | 'n') => void;\n}\n\nconst PROMOTION_PIECES: { type: 'q' | 'r' | 'b' | 'n'; label: string }[] = [\n { type: 'q', label: 'Queen' },\n { type: 'r', label: 'Rook' },\n { type: 'b', label: 'Bishop' },\n { type: 'n', label: 'Knight' },\n];\n\nexport function PromotionDialog({ color, onSelect }: PromotionDialogProps) {\n return (\n <div className={styles.promotionOverlay}>\n <div className={styles.promotionDialog}>\n <h3 className={styles.promotionTitle}>Promote pawn</h3>\n <div className={styles.promotionOptions}>\n {PROMOTION_PIECES.map(({ type, label }) => (\n <button\n key={type}\n className={styles.promotionBtn}\n onClick={() => onSelect(type)}\n title={label}\n >\n <PieceIcon type={type} color={color} />\n </button>\n ))}\n </div>\n </div>\n </div>\n );\n}\n","import type { GameStatus } from '../types/chess.ts';\nimport styles from '../styles/components.module.css';\n\ninterface GameOverBannerProps {\n status: GameStatus;\n humanColor: 'w' | 'b';\n onRestart: () => void;\n}\n\nfunction getResultText(status: GameStatus, humanColor: 'w' | 'b'): { title: string; detail: string } {\n if (status.result === 'checkmate') {\n if (status.winner === humanColor) {\n return { title: 'You Win!', detail: 'Checkmate' };\n }\n return { title: 'You Lose', detail: 'Checkmate' };\n }\n if (status.result === 'stalemate') {\n return { title: 'Draw', detail: 'Stalemate' };\n }\n if (status.result === 'insufficient') {\n return { title: 'Draw', detail: 'Insufficient material' };\n }\n if (status.result === 'threefold') {\n return { title: 'Draw', detail: 'Threefold repetition' };\n }\n return { title: 'Draw', detail: 'Game over' };\n}\n\nexport function GameOverBanner({ status, humanColor, onRestart }: GameOverBannerProps) {\n const { title, detail } = getResultText(status, humanColor);\n\n return (\n <div className={styles.gameOverOverlay}>\n <div className={styles.gameOverBanner}>\n <h2 className={styles.gameOverResult}>{title}</h2>\n <p className={styles.gameOverDetail}>{detail}</p>\n <button className={styles.restartBtn} onClick={onRestart}>\n Play Again\n </button>\n </div>\n </div>\n );\n}\n","import styles from '../styles/components.module.css';\n\ninterface ChaosTimerProps {\n countdown: number;\n maxCountdown: number;\n}\n\nexport function ChaosTimer({ countdown, maxCountdown }: ChaosTimerProps) {\n const progress = maxCountdown > 0 ? ((maxCountdown - countdown) / maxCountdown) * 100 : 0;\n const glow = 1 - (countdown / maxCountdown || 0); // 0 at full, 1 at empty\n\n return (\n <div className={styles.chaosBar}>\n <span className={styles.chaosBarLabel}>STUPIDITY</span>\n <div className={styles.chaosBarTrack}>\n <div\n className={styles.chaosBarFill}\n style={{\n width: `${progress}%`,\n '--glow': glow,\n } as React.CSSProperties}\n />\n </div>\n </div>\n );\n}\n","import { useState, useEffect, useRef } from 'react';\nimport { PIECE_UNICODE } from '../types/chess.ts';\nimport type { ChaosAction } from '../types/chess.ts';\nimport styles from '../styles/components.module.css';\n\ninterface ChaosToastProps {\n action: ChaosAction | null;\n}\n\nexport function ChaosToast({ action }: ChaosToastProps) {\n const [visible, setVisible] = useState(false);\n const [fading, setFading] = useState(false);\n const [displayAction, setDisplayAction] = useState<ChaosAction | null>(null);\n const timeoutRef = useRef<ReturnType<typeof setTimeout>>(undefined);\n\n useEffect(() => {\n if (!action) return;\n\n // Clear any existing timeout\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\n\n setDisplayAction(action);\n setFading(false);\n setVisible(true);\n\n // Start fade-out after 1.6s\n timeoutRef.current = setTimeout(() => {\n setFading(true);\n // Remove after fade animation completes\n timeoutRef.current = setTimeout(() => {\n setVisible(false);\n setFading(false);\n }, 400);\n }, 1600);\n\n return () => {\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\n };\n }, [action]);\n\n if (!visible || !displayAction) return null;\n\n const message =\n displayAction.type === 'add' && displayAction.piece && displayAction.color\n ? `A ${PIECE_UNICODE[`${displayAction.color}${displayAction.piece}`]} appeared on ${displayAction.square}!`\n : `The piece on ${displayAction.square} vanished!`;\n\n return (\n <div className={`${styles.chaosToast} ${fading ? styles.chaosToastFading : ''}`}>\n {message}\n </div>\n );\n}\n","import styles from '../styles/components.module.css';\n\ninterface DifficultySelectorProps {\n depth: number;\n onChange: (depth: number) => void;\n}\n\nexport function DifficultySelector({ depth, onChange }: DifficultySelectorProps) {\n return (\n <div className={styles.difficultySelector}>\n <span className={styles.difficultyLabel}>\n AI Depth: <span className={styles.difficultyValue}>{depth}</span>\n </span>\n <input\n className={styles.difficultySlider}\n type=\"range\"\n min={1}\n max={20}\n value={depth}\n onChange={(e) => onChange(parseInt(e.target.value))}\n />\n </div>\n );\n}\n","import styles from '../styles/components.module.css';\n\ninterface StupidLevelProps {\n level: number; // 0 = off, 1-5\n onChange: (level: number) => void;\n}\n\nconst LABELS = ['OFF', 'CHILL', 'MID', 'STUPID', 'CHAOS', 'LOL'];\n\nexport function StupidLevel({ level, onChange }: StupidLevelProps) {\n return (\n <div className={styles.stupidLevel}>\n <div className={styles.stupidLevelHeader}>\n <span className={styles.stupidLevelLabel}>STUPID</span>\n <span className={styles.stupidLevelValue}>{LABELS[level]}</span>\n </div>\n <input\n type=\"range\"\n min={0}\n max={5}\n step={1}\n value={level}\n onChange={(e) => onChange(Number(e.target.value))}\n className={styles.stupidLevelSlider}\n />\n </div>\n );\n}\n","import { PIECE_UNICODE } from '../types/chess.ts';\nimport { DifficultySelector } from './DifficultySelector.tsx';\nimport { StupidLevel } from './StupidLevel.tsx';\nimport styles from '../styles/components.module.css';\n\ninterface SidePickerProps {\n depth: number;\n onDepthChange: (depth: number) => void;\n stupidLevel: number;\n onStupidLevelChange: (level: number) => void;\n onSelectSide: (color: 'w' | 'b') => void;\n}\n\nexport function SidePicker({ depth, onDepthChange, stupidLevel, onStupidLevelChange, onSelectSide }: SidePickerProps) {\n return (\n <div className={styles.sidePickerOverlay}>\n <div className={styles.sidePickerCard}>\n <h2 className={styles.sidePickerTitle}>Choose Your Side</h2>\n <div className={styles.sidePickerOptions}>\n <button\n className={styles.sidePickerBtn}\n onClick={() => onSelectSide('w')}\n >\n <span className={`${styles.sidePickerIcon} ${styles.sidePickerWhite}`}>{PIECE_UNICODE.wk}</span>\n <span className={styles.sidePickerLabel}>White</span>\n </button>\n <button\n className={styles.sidePickerBtn}\n onClick={() => onSelectSide('b')}\n >\n <span className={`${styles.sidePickerIcon} ${styles.sidePickerBlack}`}>{PIECE_UNICODE.bk}</span>\n <span className={styles.sidePickerLabel}>Black</span>\n </button>\n </div>\n <div className={styles.sidePickerSettings}>\n <DifficultySelector depth={depth} onChange={onDepthChange} />\n <StupidLevel level={stupidLevel} onChange={onStupidLevelChange} />\n </div>\n </div>\n </div>\n );\n}\n","import styles from '../styles/components.module.css';\n\ninterface MuteButtonProps {\n muted: boolean;\n onToggle: () => void;\n}\n\nexport function MuteButton({ muted, onToggle }: MuteButtonProps) {\n return (\n <button\n className={`${styles.muteBtn} ${muted ? styles.muteBtnMuted : ''}`}\n onClick={onToggle}\n title={muted ? 'Unmute' : 'Mute'}\n >\n {muted ? '\\u{1F507}' : '\\u{1F50A}'}\n </button>\n );\n}\n","class SoundManager {\n private ctx: AudioContext | null = null;\n private muted = false;\n\n private getCtx(): AudioContext | null {\n if (this.muted) return null;\n if (!this.ctx) {\n try {\n this.ctx = new AudioContext();\n } catch {\n return null;\n }\n }\n if (this.ctx.state === 'suspended') {\n this.ctx.resume();\n }\n return this.ctx;\n }\n\n setMuted(muted: boolean) {\n this.muted = muted;\n }\n\n playMove() {\n const ctx = this.getCtx();\n if (!ctx) return;\n const osc = ctx.createOscillator();\n const gain = ctx.createGain();\n osc.type = 'sine';\n osc.frequency.value = 200;\n gain.gain.setValueAtTime(0.15, ctx.currentTime);\n gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.08);\n osc.connect(gain).connect(ctx.destination);\n osc.start();\n osc.stop(ctx.currentTime + 0.08);\n }\n\n playCapture() {\n const ctx = this.getCtx();\n if (!ctx) return;\n // Metallic clack: noise burst filtered to high-mid band\n const bufferSize = ctx.sampleRate * 0.1;\n const buffer = ctx.createBuffer(1, bufferSize, ctx.sampleRate);\n const data = buffer.getChannelData(0);\n for (let i = 0; i < bufferSize; i++) {\n data[i] = (Math.random() * 2 - 1) * Math.exp(-i / (ctx.sampleRate * 0.015));\n }\n const noise = ctx.createBufferSource();\n noise.buffer = buffer;\n const bandpass = ctx.createBiquadFilter();\n bandpass.type = 'bandpass';\n bandpass.frequency.value = 3000;\n bandpass.Q.value = 2;\n const gain = ctx.createGain();\n gain.gain.setValueAtTime(0.35, ctx.currentTime);\n gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.1);\n noise.connect(bandpass).connect(gain).connect(ctx.destination);\n noise.start();\n noise.stop(ctx.currentTime + 0.1);\n }\n\n playCheck() {\n const ctx = this.getCtx();\n if (!ctx) return;\n const osc = ctx.createOscillator();\n const gain = ctx.createGain();\n osc.type = 'triangle';\n osc.frequency.value = 800;\n gain.gain.setValueAtTime(0.18, ctx.currentTime);\n gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.12);\n osc.connect(gain).connect(ctx.destination);\n osc.start();\n osc.stop(ctx.currentTime + 0.12);\n }\n\n playChaos() {\n const ctx = this.getCtx();\n if (!ctx) return;\n // Soft shimmer: quiet sine blip with a gentle pitch drop\n const osc = ctx.createOscillator();\n const gain = ctx.createGain();\n osc.type = 'sine';\n osc.frequency.setValueAtTime(520, ctx.currentTime);\n osc.frequency.exponentialRampToValueAtTime(320, ctx.currentTime + 0.18);\n gain.gain.setValueAtTime(0.07, ctx.currentTime);\n gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.18);\n osc.connect(gain).connect(ctx.destination);\n osc.start();\n osc.stop(ctx.currentTime + 0.18);\n }\n\n playGameOver() {\n const ctx = this.getCtx();\n if (!ctx) return;\n // C major chord: C4 + E4 + G4\n const freqs = [261.63, 329.63, 392.0];\n for (const freq of freqs) {\n const osc = ctx.createOscillator();\n const gain = ctx.createGain();\n osc.type = 'sine';\n osc.frequency.value = freq;\n gain.gain.setValueAtTime(0.1, ctx.currentTime);\n gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.4);\n osc.connect(gain).connect(ctx.destination);\n osc.start();\n osc.stop(ctx.currentTime + 0.4);\n }\n }\n}\n\nexport const soundManager = new SoundManager();\n","import { useState, useCallback, useEffect, useRef } from 'react';\nimport { Chess } from 'chess.js';\nimport type { Square as ChessSquare } from 'chess.js';\nimport type { ChaosChessProps } from './types/props.ts';\nimport { useChessGame } from './hooks/useChessGame.ts';\nimport { useStockfish } from './hooks/useStockfish.ts';\nimport { useChaosEngine } from './hooks/useChaosEngine.ts';\nimport { ChessBoard } from './components/ChessBoard.tsx';\nimport { PromotionDialog } from './components/PromotionDialog.tsx';\nimport { GameOverBanner } from './components/GameOverBanner.tsx';\nimport { ChaosTimer } from './components/ChaosTimer.tsx';\nimport { ChaosToast } from './components/ChaosToast.tsx';\nimport { DifficultySelector } from './components/DifficultySelector.tsx';\nimport { SidePicker } from './components/SidePicker.tsx';\nimport { StupidLevel } from './components/StupidLevel.tsx';\nimport { MuteButton } from './components/MuteButton.tsx';\nimport { soundManager } from './utils/sounds.ts';\nimport styles from './styles/ChessGame.module.css';\nimport './styles/theme.css';\nimport './styles/animations.css';\n\ntype GamePhase = 'setup' | 'playing';\n\nexport function ChessGame(props: ChaosChessProps) {\n const {\n defaultDepth = 10,\n defaultStupidLevel = 3,\n defaultHumanColor,\n defaultMuted = false,\n depth: controlledDepth,\n onDepthChange,\n stupidLevel: controlledStupidLevel,\n onStupidLevelChange,\n stockfishWorkerPath,\n skipSetup = false,\n showControls = true,\n showMuteButton = true,\n onGameOver,\n onMove,\n onChaosAction: onChaosActionCb,\n onRestart: onRestartCb,\n className,\n } = props;\n\n // --- Controlled / uncontrolled state ---\n const [internalDepth, setInternalDepth] = useState(defaultDepth);\n const depth = controlledDepth ?? internalDepth;\n const setDepth = onDepthChange ?? setInternalDepth;\n\n const [internalStupidLevel, setInternalStupidLevel] = useState(defaultStupidLevel);\n const stupidLevel = controlledStupidLevel ?? internalStupidLevel;\n const setStupidLevel = onStupidLevelChange ?? setInternalStupidLevel;\n\n const [internalHumanColor, setInternalHumanColor] = useState<'w' | 'b'>(defaultHumanColor ?? 'w');\n const humanColor = internalHumanColor;\n\n const [soundMuted, setSoundMuted] = useState(defaultMuted);\n\n // If skipSetup or defaultHumanColor is given, go straight to playing\n const [gamePhase, setGamePhase] = useState<GamePhase>(\n (skipSetup || defaultHumanColor) ? 'playing' : 'setup'\n );\n\n const {\n fen,\n turn,\n selectedSquare,\n legalMoves,\n gameStatus,\n promotionPending,\n lastMove,\n lastMoveDetail,\n moveHistory,\n board,\n handleSquareClick,\n handlePromotion,\n applyFen,\n handleRestart: resetGame,\n } = useChessGame();\n\n const { isReady: stockfishReady, isThinking, getBestMove } = useStockfish(stockfishWorkerPath);\n\n const aiEnabled = stockfishReady;\n const isHumanTurn = turn === humanColor;\n\n // Chaos engine: pause during setup, when off, AI's turn, promotion, or game over\n const chaosEnabled = stupidLevel > 0;\n const chaosPaused = gamePhase !== 'playing' || !chaosEnabled || !isHumanTurn || isThinking || !!promotionPending || gameStatus.isGameOver;\n const { countdown, maxCountdown, lastAction, chaosSquare } = useChaosEngine({\n fen,\n isPaused: chaosPaused,\n stupidLevel: Math.max(1, stupidLevel),\n onChaosAction: useCallback((newFen: string) => {\n // Guard: if the game has moved past the human's turn, skip this chaos event.\n // This catches the race where the interval fires before isPausedRef updates.\n const chess = new Chess(currentFenRef.current);\n if (chess.turn() !== humanColorRef.current) return;\n if (chess.isGameOver()) return;\n applyFen(newFen);\n }, [applyFen]),\n });\n\n // Fire onChaosAction callback\n const prevLastActionRef = useRef(lastAction);\n useEffect(() => {\n if (lastAction && lastAction !== prevLastActionRef.current) {\n onChaosActionCb?.(lastAction, fen);\n }\n prevLastActionRef.current = lastAction;\n }, [lastAction, fen, onChaosActionCb]);\n\n // Refs that always point to latest values (for use in async callbacks)\n const currentFenRef = useRef(fen);\n currentFenRef.current = fen;\n const humanColorRef = useRef(humanColor);\n humanColorRef.current = humanColor;\n\n // Track last FEN where Stockfish returned no move to avoid infinite retries\n const noMoveFenRef = useRef<string | null>(null);\n\n const executeStockfishMove = useCallback((uciMove: string) => {\n const from = uciMove.slice(0, 2) as ChessSquare;\n const to = uciMove.slice(2, 4) as ChessSquare;\n const promotion = uciMove.length > 4 ? uciMove[4] : undefined;\n try {\n const tempChess = new Chess(currentFenRef.current);\n const moveOpts: { from: ChessSquare; to: ChessSquare; promotion?: string } = { from, to };\n if (promotion) moveOpts.promotion = promotion;\n const move = tempChess.move(moveOpts);\n if (move) {\n applyFen(tempChess.fen());\n } else {\n // Move invalid for current position — board changed since Stockfish started.\n // The main effect will re-trigger via isThinking becoming false.\n console.warn('[ChaosChess] Stockfish move invalid for current position, will retry');\n }\n } catch {\n console.warn('[ChaosChess] Stockfish move threw, will retry');\n }\n }, [applyFen]);\n\n // --- Side selection ---\n const handleSideSelect = useCallback((color: 'w' | 'b') => {\n setInternalHumanColor(color);\n setGamePhase('playing');\n }, []);\n\n const handleRestart = useCallback(() => {\n resetGame();\n setGamePhase((skipSetup || defaultHumanColor) ? 'playing' : 'setup');\n onRestartCb?.();\n }, [resetGame, skipSetup, defaultHumanColor, onRestartCb]);\n\n // --- Sound mute sync ---\n useEffect(() => {\n soundManager.setMuted(soundMuted);\n }, [soundMuted]);\n\n // --- Sound: move / capture / check + onMove callback ---\n const prevMoveCountRef = useRef(moveHistory.length);\n useEffect(() => {\n if (moveHistory.length > prevMoveCountRef.current) {\n // Sound\n if (lastMoveDetail) {\n if (lastMoveDetail.check) {\n soundManager.playCheck();\n } else if (lastMoveDetail.captured) {\n soundManager.playCapture();\n } else {\n soundManager.playMove();\n }\n }\n // Fire onMove callback for the new entry\n const latest = moveHistory[moveHistory.length - 1];\n if (latest) {\n onMove?.(latest.fen, latest.san, latest.color);\n }\n }\n prevMoveCountRef.current = moveHistory.length;\n }, [moveHistory.length, lastMoveDetail, moveHistory, onMove]);\n\n // --- Sound: chaos ---\n useEffect(() => {\n if (chaosSquare) {\n soundManager.playChaos();\n }\n }, [chaosSquare]);\n\n // --- Sound + callback: game over ---\n const prevGameOverRef = useRef(false);\n useEffect(() => {\n if (gameStatus.isGameOver && !prevGameOverRef.current) {\n soundManager.playGameOver();\n onGameOver?.(gameStatus);\n }\n prevGameOverRef.current = gameStatus.isGameOver;\n }, [gameStatus, onGameOver]);\n\n // Single effect to trigger Stockfish when it's the AI's turn.\n // Covers: FEN changes, initial move as black, and Stockfish becoming ready.\n // The engine's cancelPending() handles deduplication at the worker level.\n const initialMoveTriggered = useRef(false);\n useEffect(() => {\n if (gamePhase !== 'playing') {\n initialMoveTriggered.current = false;\n return;\n }\n if (isHumanTurn || gameStatus.isGameOver || !stockfishReady || isThinking) return;\n\n // Don't retry a FEN that already returned no move\n if (noMoveFenRef.current === fen) return;\n\n // For initial position when playing as black, mark as triggered\n if (humanColor === 'b' && !initialMoveTriggered.current) {\n initialMoveTriggered.current = true;\n }\n\n getBestMove(fen, depth).then((uciMove) => {\n if (!uciMove) {\n // Genuine \"(none)\": no legal move for this exact position. Pin it so we\n // don't tight-loop. (On the AI's turn this lines up with game-over.)\n noMoveFenRef.current = fen;\n return;\n }\n noMoveFenRef.current = null;\n executeStockfishMove(uciMove);\n }).catch(() => {\n // Search was cancelled/superseded or timed out — not a dead position.\n // Leave noMoveFenRef clear so this effect (or the watchdog) retries.\n });\n }, [gamePhase, fen, isHumanTurn, gameStatus.isGameOver, stockfishReady, isThinking, humanColor, getBestMove, depth, executeStockfishMove]);\n\n // Retry watchdog: if it's the AI's turn but Stockfish isn't thinking, retry after 3s.\n // This catches edge cases where the above effect's move was invalid for the current position.\n useEffect(() => {\n if (gamePhase !== 'playing' || isHumanTurn || isThinking || gameStatus.isGameOver || !stockfishReady) return;\n\n // Don't retry a FEN that already returned no move\n if (noMoveFenRef.current === fen) return;\n\n const timer = setTimeout(() => {\n getBestMove(fen, depth).then((uciMove) => {\n if (!uciMove) {\n noMoveFenRef.current = fen;\n return;\n }\n noMoveFenRef.current = null;\n executeStockfishMove(uciMove);\n }).catch(() => {\n // Cancelled/timed-out — let a later tick retry.\n });\n }, 3000);\n\n return () => clearTimeout(timer);\n }, [gamePhase, isHumanTurn, isThinking, gameStatus.isGameOver, stockfishReady, fen, depth, getBestMove, executeStockfishMove]);\n\n // Lock board during AI turn\n const onSquareClick = useCallback(\n (square: ChessSquare) => {\n if (aiEnabled && turn !== humanColor) return;\n handleSquareClick(square);\n },\n [aiEnabled, turn, humanColor, handleSquareClick]\n );\n\n const statusText = gameStatus.isGameOver\n ? 'Game Over'\n : isThinking\n ? ''\n : !aiEnabled\n ? `${turn === 'w' ? 'White' : 'Black'} to move`\n : isHumanTurn\n ? 'Your turn'\n : 'Opponent thinking...';\n\n const rootClassName = [styles.container, className].filter(Boolean).join(' ');\n\n // --- Setup phase ---\n if (gamePhase === 'setup') {\n return (\n <div className={rootClassName} data-chaos-chess=\"\">\n <SidePicker\n depth={depth}\n onDepthChange={setDepth}\n stupidLevel={stupidLevel}\n onStupidLevelChange={setStupidLevel}\n onSelectSide={handleSideSelect}\n />\n </div>\n );\n }\n\n // --- Playing phase ---\n return (\n <div className={rootClassName} data-chaos-chess=\"\">\n <div className={styles.topBar}>\n <div className={styles.topBarLeft}>\n <span className={styles.statusText}>{statusText}</span>\n {isThinking && (\n <span className={styles.thinking}>AI thinking...</span>\n )}\n </div>\n {showMuteButton && (\n <MuteButton muted={soundMuted} onToggle={() => setSoundMuted((m) => !m)} />\n )}\n </div>\n\n {chaosEnabled && (\n <ChaosTimer countdown={countdown} maxCountdown={maxCountdown} />\n )}\n\n <ChessBoard\n board={board}\n selectedSquare={selectedSquare}\n legalMoves={legalMoves}\n inCheck={gameStatus.inCheck}\n lastMove={lastMove}\n chaosSquare={chaosSquare}\n flipped={humanColor === 'b'}\n locked={aiEnabled && !isHumanTurn}\n onSquareClick={onSquareClick}\n />\n\n {showControls && (\n <div className={styles.bottomBar}>\n <DifficultySelector depth={depth} onChange={setDepth} />\n <StupidLevel level={stupidLevel} onChange={setStupidLevel} />\n </div>\n )}\n\n <ChaosToast action={lastAction} />\n {promotionPending && <PromotionDialog color={turn} onSelect={handlePromotion} />}\n {gameStatus.isGameOver && (\n <GameOverBanner status={gameStatus} humanColor={humanColor} onRestart={handleRestart} />\n )}\n </div>\n );\n}\n"],"names":["getGameStatus","chess","useChessGame","chessRef","useRef","Chess","fen","setFen","useState","turn","setTurn","selectedSquare","setSelectedSquare","legalMoves","setLegalMoves","gameStatus","setGameStatus","promotionPending","setPromotionPending","moveHistory","setMoveHistory","lastMove","setLastMove","lastMoveDetail","setLastMoveDetail","board","setBoard","clearSelection","useCallback","syncState","handleSquareClick","square","piece","move","prev","moves","m","handlePromotion","applyFen","newFen","handleRestart","StockfishEngine","workerPath","resolve","reject","onReady","e","err","onMessage","depth","timeoutMs","mySearchId","msg","useStockfish","engineRef","isReady","setIsReady","isThinking","setIsThinking","callIdRef","useEffect","engine","getBestMove","myCallId","safetyTimeout","PIECE_VALUES","PIECE_UNICODE","FILES","parseFen","parts","positionToBoard","position","ranks","rank","row","ch","emptyCount","color","type","boardToPosition","rankStr","cell","serializeFen","calculateMaterial","white","black","value","getEmptySquares","squares","file","getPieceSquares","excludeKing","squareToIndices","addPieceToFen","removePieceFromFen","ADDABLE_PIECES","MAX_RETRIES","getChaosTarget","whiteMaterial","blackMaterial","randomChoice","arr","chooseRandomPiece","isValidChaosPosition","addRandomPiece","emptySquares","attempt","removeRandomPiece","pieceSquares","executeChaosAction","target","operation","addColor","removeColor","result","fallback","STUPID_BOUNDS","getRandomChaosInterval","stupidLevel","idx","lo","hi","useChaosEngine","isPaused","onChaosAction","countdown","setCountdown","maxCountdown","setMaxCountdown","lastAction","setLastAction","chaosSquare","setChaosSquare","fenRef","isPausedRef","stupidLevelRef","onChaosActionRef","targetTimeRef","intervalIdRef","scheduleNext","intervalMs","seconds","remaining","lastPauseRef","pausedDuration","PieceIcon","className","key","symbol","colorClass","styles","jsx","Square","isLight","isSelected","isLegalMove","isCheck","isLastMoveFrom","isLastMoveTo","isChaosFlash","rankLabel","fileLabel","onClick","classNames","jsxs","boardStyles","getSquareName","isLightSquare","ChessBoard","React","inCheck","flipped","locked","onSquareClick","checkSquare","r","f","rankOrder","fileOrder","rankIdx","fileIdx","displayRow","displayCol","PROMOTION_PIECES","PromotionDialog","onSelect","label","getResultText","status","humanColor","GameOverBanner","onRestart","title","detail","ChaosTimer","progress","glow","ChaosToast","action","visible","setVisible","fading","setFading","displayAction","setDisplayAction","timeoutRef","message","DifficultySelector","onChange","LABELS","StupidLevel","level","SidePicker","onDepthChange","onStupidLevelChange","onSelectSide","MuteButton","muted","onToggle","SoundManager","ctx","osc","gain","bufferSize","buffer","data","i","noise","bandpass","freqs","freq","soundManager","ChessGame","props","defaultDepth","defaultStupidLevel","defaultHumanColor","defaultMuted","controlledDepth","controlledStupidLevel","stockfishWorkerPath","skipSetup","showControls","showMuteButton","onGameOver","onMove","onChaosActionCb","onRestartCb","internalDepth","setInternalDepth","setDepth","internalStupidLevel","setInternalStupidLevel","setStupidLevel","internalHumanColor","setInternalHumanColor","soundMuted","setSoundMuted","gamePhase","setGamePhase","resetGame","stockfishReady","aiEnabled","isHumanTurn","chaosEnabled","chaosPaused","currentFenRef","humanColorRef","prevLastActionRef","noMoveFenRef","executeStockfishMove","uciMove","from","to","promotion","tempChess","moveOpts","handleSideSelect","prevMoveCountRef","latest","prevGameOverRef","initialMoveTriggered","timer","statusText","rootClassName"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"chaos-chess.js","sources":["../src/types/chess.ts","../src/engine/fenManipulator.ts","../src/hooks/useChessGame.ts","../src/engine/stockfishWorker.ts","../src/engine/enginePool.ts","../src/hooks/useStockfish.ts","../src/engine/chaosEngine.ts","../src/hooks/useChaosEngine.ts","../src/components/pieceArt.ts","../src/components/PieceIcon.tsx","../src/components/Square.tsx","../src/components/ChessBoard.tsx","../src/components/PromotionDialog.tsx","../src/components/GameOverBanner.tsx","../src/components/ChaosTimer.tsx","../src/components/ChaosToast.tsx","../src/components/DifficultySelector.tsx","../src/components/StupidLevel.tsx","../src/components/SidePicker.tsx","../src/components/MuteButton.tsx","../src/utils/sounds.ts","../src/utils/state.ts","../src/ChessGame.tsx"],"sourcesContent":["import type { Square as ChessSquare, PieceSymbol, Color } from 'chess.js';\n\nexport type { ChessSquare, PieceSymbol, Color };\n\nexport type GameResult = 'checkmate' | 'stalemate' | 'draw' | 'insufficient' | 'threefold' | 'fifty-move' | 'king-captured';\n\nexport interface GameStatus {\n isGameOver: boolean;\n result: GameResult | null;\n winner: Color | null;\n inCheck: Color | null;\n}\n\nexport type ChaosActionType = 'add' | 'remove';\nexport type ChaosTarget = 'help_white' | 'help_black';\n\nexport interface ChaosAction {\n type: ChaosActionType;\n target: ChaosTarget;\n square: ChessSquare;\n piece?: PieceSymbol;\n color?: Color;\n whiteMaterial: number;\n blackMaterial: number;\n}\n\nexport interface PromotionPending {\n from: ChessSquare;\n to: ChessSquare;\n}\n\nexport interface MoveHistoryEntry {\n san: string;\n fen: string;\n color: Color;\n}\n\nexport interface MaterialCount {\n white: number;\n black: number;\n}\n\nexport const PIECE_VALUES: Record<PieceSymbol, number> = {\n p: 1,\n n: 3,\n b: 3,\n r: 5,\n q: 9,\n k: 0,\n};\n\n// Filled symbols for white (bright on dark bg), outlines for black\n// \\uFE0E = Variation Selector 15 — forces text presentation on iOS\n// (without it, iOS renders some glyphs as color emoji)\nexport const PIECE_UNICODE: Record<string, string> = {\n wk: '\\u265A\\uFE0E',\n wq: '\\u265B\\uFE0E',\n wr: '\\u265C\\uFE0E',\n wb: '\\u265D\\uFE0E',\n wn: '\\u265E\\uFE0E',\n wp: '\\u265F\\uFE0E',\n bk: '\\u2654\\uFE0E',\n bq: '\\u2655\\uFE0E',\n br: '\\u2656\\uFE0E',\n bb: '\\u2657\\uFE0E',\n bn: '\\u2658\\uFE0E',\n bp: '\\u2659\\uFE0E',\n};\n","import type { PieceSymbol, Color, ChessSquare, MaterialCount } from '../types/chess.ts';\nimport { PIECE_VALUES } from '../types/chess.ts';\n\nexport interface FenPiece {\n type: PieceSymbol;\n color: Color;\n}\n\nexport type Board8x8 = (FenPiece | null)[][];\n\nconst FILES = 'abcdefgh';\n\n/**\n * Parse a FEN string into its components.\n * Missing trailing fields get their usual defaults, so a 4-field FEN\n * (no move counters) still serializes to a valid 6-field FEN.\n */\nexport function parseFen(fen: string) {\n const parts = fen.trim().split(/\\s+/);\n return {\n position: parts[0],\n activeColor: (parts[1] ?? 'w') as Color,\n castling: parts[2] ?? '-',\n enPassant: parts[3] ?? '-',\n halfmove: parts[4] ?? '0',\n fullmove: parts[5] ?? '1',\n };\n}\n\n/**\n * Convert the position segment of a FEN into an 8x8 board array.\n * board[rank][file] where rank 0 = rank 8 (top), rank 7 = rank 1 (bottom).\n */\nexport function positionToBoard(position: string): Board8x8 {\n const board: Board8x8 = [];\n const ranks = position.split('/');\n for (const rank of ranks) {\n const row: (FenPiece | null)[] = [];\n for (const ch of rank) {\n const emptyCount = parseInt(ch);\n if (!isNaN(emptyCount)) {\n for (let i = 0; i < emptyCount; i++) row.push(null);\n } else {\n const color: Color = ch === ch.toUpperCase() ? 'w' : 'b';\n const type = ch.toLowerCase() as PieceSymbol;\n row.push({ type, color });\n }\n }\n board.push(row);\n }\n return board;\n}\n\n/**\n * Convert an 8x8 board array back to a FEN position string.\n */\nexport function boardToPosition(board: Board8x8): string {\n return board\n .map((row) => {\n let rankStr = '';\n let emptyCount = 0;\n for (const cell of row) {\n if (cell === null) {\n emptyCount++;\n } else {\n if (emptyCount > 0) {\n rankStr += emptyCount;\n emptyCount = 0;\n }\n const ch = cell.color === 'w' ? cell.type.toUpperCase() : cell.type;\n rankStr += ch;\n }\n }\n if (emptyCount > 0) rankStr += emptyCount;\n return rankStr;\n })\n .join('/');\n}\n\n/**\n * Serialize FEN components back into a FEN string.\n */\nexport function serializeFen(parts: ReturnType<typeof parseFen>): string {\n return `${parts.position} ${parts.activeColor} ${parts.castling} ${parts.enPassant} ${parts.halfmove} ${parts.fullmove}`;\n}\n\n/**\n * Calculate material values for both sides from a FEN string.\n */\nexport function calculateMaterial(fen: string): MaterialCount {\n const { position } = parseFen(fen);\n const board = positionToBoard(position);\n let white = 0;\n let black = 0;\n for (const row of board) {\n for (const cell of row) {\n if (cell) {\n const value = PIECE_VALUES[cell.type];\n if (cell.color === 'w') white += value;\n else black += value;\n }\n }\n }\n return { white, black };\n}\n\n/**\n * Get all empty squares on the board.\n */\nexport function getEmptySquares(fen: string): ChessSquare[] {\n const { position } = parseFen(fen);\n const board = positionToBoard(position);\n const squares: ChessSquare[] = [];\n for (let rank = 0; rank < 8; rank++) {\n for (let file = 0; file < 8; file++) {\n if (board[rank][file] === null) {\n squares.push(`${FILES[file]}${8 - rank}` as ChessSquare);\n }\n }\n }\n return squares;\n}\n\n/**\n * Get all squares occupied by pieces of a given color (optionally excluding king).\n */\nexport function getPieceSquares(\n fen: string,\n color: Color,\n excludeKing = true\n): ChessSquare[] {\n const { position } = parseFen(fen);\n const board = positionToBoard(position);\n const squares: ChessSquare[] = [];\n for (let rank = 0; rank < 8; rank++) {\n for (let file = 0; file < 8; file++) {\n const cell = board[rank][file];\n if (cell && cell.color === color) {\n if (excludeKing && cell.type === 'k') continue;\n squares.push(`${FILES[file]}${8 - rank}` as ChessSquare);\n }\n }\n }\n return squares;\n}\n\n/**\n * Convert a square name (e.g. 'e4') to board array indices [rank, file].\n */\nexport function squareToIndices(square: ChessSquare): [number, number] {\n const file = FILES.indexOf(square[0]);\n const rank = 8 - parseInt(square[1]);\n return [rank, file];\n}\n\n/**\n * Add a piece to the board at a given square, returning a new FEN.\n * Castling and en passant fields are re-checked against the new board.\n */\nexport function addPieceToFen(\n fen: string,\n square: ChessSquare,\n piece: PieceSymbol,\n color: Color\n): string {\n const parts = parseFen(fen);\n const board = positionToBoard(parts.position);\n const [rank, file] = squareToIndices(square);\n board[rank][file] = { type: piece, color };\n parts.position = boardToPosition(board);\n return sanitizeFen(serializeFen(parts));\n}\n\n/**\n * Remove a piece from the board at a given square, returning a new FEN.\n * Castling and en passant fields are re-checked against the new board.\n */\nexport function removePieceFromFen(\n fen: string,\n square: ChessSquare\n): string {\n const parts = parseFen(fen);\n const board = positionToBoard(parts.position);\n const [rank, file] = squareToIndices(square);\n board[rank][file] = null;\n parts.position = boardToPosition(board);\n return sanitizeFen(serializeFen(parts));\n}\n\n/** Home squares a castling flag depends on: [king square, rook square, color]. */\nconst CASTLING_HOMES: Record<string, [ChessSquare, ChessSquare, Color]> = {\n K: ['e1', 'h1', 'w'],\n Q: ['e1', 'a1', 'w'],\n k: ['e8', 'h8', 'b'],\n q: ['e8', 'a8', 'b'],\n};\n\nfunction pieceAt(board: Board8x8, square: ChessSquare): FenPiece | null {\n const [rank, file] = squareToIndices(square);\n return board[rank]?.[file] ?? null;\n}\n\n/**\n * Drop castling flags whose king or rook is no longer on its home square.\n * chess.js keeps stale flags on load(), and Stockfish can hang on them.\n * The result is in the standard KQkq order, without duplicates.\n */\nexport function sanitizeCastling(castling: string, board: Board8x8): string {\n if (!castling || castling === '-') return '-';\n const kept = ['K', 'Q', 'k', 'q']\n .filter((flag) => {\n if (!castling.includes(flag)) return false;\n const home = CASTLING_HOMES[flag];\n const [kingSq, rookSq, color] = home;\n const king = pieceAt(board, kingSq);\n const rook = pieceAt(board, rookSq);\n return king?.type === 'k' && king.color === color && rook?.type === 'r' && rook.color === color;\n })\n .join('');\n return kept || '-';\n}\n\n/**\n * Drop an en passant square that no longer matches the board\n * (the double-pushed pawn is gone or the squares it crossed are occupied).\n */\nexport function sanitizeEnPassant(enPassant: string, activeColor: Color, board: Board8x8): string {\n if (!enPassant || enPassant === '-') return '-';\n const file = enPassant[0];\n const rank = parseInt(enPassant[1]);\n // White to move → black just pushed to rank 5 through rank 6, and vice versa.\n const expectedRank = activeColor === 'w' ? 6 : 3;\n if (!FILES.includes(file) || rank !== expectedRank) return '-';\n const pawnRank = activeColor === 'w' ? 5 : 4;\n const startRank = activeColor === 'w' ? 7 : 2;\n const pawn = pieceAt(board, `${file}${pawnRank}` as ChessSquare);\n const pawnColor: Color = activeColor === 'w' ? 'b' : 'w';\n if (\n pawn?.type !== 'p' ||\n pawn.color !== pawnColor ||\n pieceAt(board, enPassant as ChessSquare) !== null ||\n pieceAt(board, `${file}${startRank}` as ChessSquare) !== null\n ) {\n return '-';\n }\n return enPassant;\n}\n\n/**\n * Make the castling and en passant fields consistent with the board.\n */\nexport function sanitizeFen(fen: string): string {\n const parts = parseFen(fen);\n const board = positionToBoard(parts.position);\n parts.castling = sanitizeCastling(parts.castling, board);\n parts.enPassant = sanitizeEnPassant(parts.enPassant, parts.activeColor, board);\n return serializeFen(parts);\n}\n","import { useState, useRef, useCallback } from 'react';\nimport { Chess } from 'chess.js';\nimport type { Square as ChessSquare, Move, Piece } from 'chess.js';\nimport type { GameStatus, PromotionPending, MoveHistoryEntry, Color } from '../types/chess.ts';\nimport { sanitizeFen } from '../engine/fenManipulator.ts';\n\ninterface LastMove {\n from: ChessSquare;\n to: ChessSquare;\n}\n\nexport interface MoveInput {\n from: ChessSquare;\n to: ChessSquare;\n promotion?: string;\n}\n\nexport interface LastMoveDetail {\n captured: boolean;\n check: boolean;\n}\n\nexport interface UseChessGameReturn {\n fen: string;\n turn: 'w' | 'b';\n selectedSquare: ChessSquare | null;\n legalMoves: ChessSquare[];\n gameStatus: GameStatus;\n promotionPending: PromotionPending | null;\n moveHistory: MoveHistoryEntry[];\n lastMove: LastMove | null;\n lastMoveDetail: LastMoveDetail | null;\n handleSquareClick: (square: ChessSquare) => void;\n handlePromotion: (piece: 'q' | 'r' | 'b' | 'n') => void;\n applyFen: (newFen: string) => void;\n applyMove: (move: MoveInput, expectedFen?: string) => boolean;\n board: (Piece | null)[][];\n handleRestart: () => void;\n}\n\nexport function getGameStatus(chess: Chess): GameStatus {\n // Chaos should never allow it, but if a king has been captured the game is over\n const whiteKing = chess.findPiece({ type: 'k', color: 'w' }).length > 0;\n const blackKing = chess.findPiece({ type: 'k', color: 'b' }).length > 0;\n if (!whiteKing || !blackKing) {\n const winner: Color | null = whiteKing ? 'w' : blackKing ? 'b' : null;\n return { isGameOver: true, result: 'king-captured', winner, inCheck: null };\n }\n\n if (!chess.isGameOver()) {\n const inCheck = chess.inCheck() ? chess.turn() : null;\n return { isGameOver: false, result: null, winner: null, inCheck };\n }\n\n if (chess.isCheckmate()) {\n const winner: Color = chess.turn() === 'w' ? 'b' : 'w';\n return { isGameOver: true, result: 'checkmate', winner, inCheck: chess.turn() };\n }\n if (chess.isStalemate()) {\n return { isGameOver: true, result: 'stalemate', winner: null, inCheck: null };\n }\n if (chess.isInsufficientMaterial()) {\n return { isGameOver: true, result: 'insufficient', winner: null, inCheck: null };\n }\n if (chess.isThreefoldRepetition()) {\n return { isGameOver: true, result: 'threefold', winner: null, inCheck: null };\n }\n if (chess.isDrawByFiftyMoves()) {\n return { isGameOver: true, result: 'fifty-move', winner: null, inCheck: null };\n }\n return { isGameOver: true, result: 'draw', winner: null, inCheck: null };\n}\n\n/** Load a FEN for a new game, falling back to the start position if it is unusable. */\nfunction createChess(initialFen?: string): Chess {\n if (initialFen) {\n try {\n return new Chess(sanitizeFen(initialFen));\n } catch {\n // Fall through to the start position\n }\n }\n return new Chess();\n}\n\nexport function useChessGame(initialFen?: string) {\n const [initialChess] = useState(() => createChess(initialFen));\n const chessRef = useRef(initialChess);\n const [fen, setFen] = useState(() => initialChess.fen());\n const [turn, setTurn] = useState<'w' | 'b'>(() => initialChess.turn());\n const [selectedSquare, setSelectedSquare] = useState<ChessSquare | null>(null);\n const [legalMoves, setLegalMoves] = useState<ChessSquare[]>([]);\n const [gameStatus, setGameStatus] = useState<GameStatus>(() => getGameStatus(initialChess));\n const [promotionPending, setPromotionPending] = useState<PromotionPending | null>(null);\n const [moveHistory, setMoveHistory] = useState<MoveHistoryEntry[]>([]);\n const [lastMove, setLastMove] = useState<LastMove | null>(null);\n const [lastMoveDetail, setLastMoveDetail] = useState<LastMoveDetail | null>(null);\n const [board, setBoard] = useState<(Piece | null)[][]>(() => initialChess.board());\n\n const clearSelection = useCallback(() => {\n setSelectedSquare(null);\n setLegalMoves([]);\n }, []);\n\n const syncState = useCallback(() => {\n setFen(chessRef.current.fen());\n setTurn(chessRef.current.turn());\n setBoard(chessRef.current.board());\n setGameStatus(getGameStatus(chessRef.current));\n }, []);\n\n /** Update highlight, sound detail and history for a move already made on chessRef. */\n const recordMove = useCallback((move: Move) => {\n setLastMove({ from: move.from, to: move.to });\n setLastMoveDetail({ captured: !!move.captured, check: move.san.includes('+') || move.san.includes('#') });\n setMoveHistory((prev) => [\n ...prev,\n { san: move.san, fen: chessRef.current.fen(), color: move.color },\n ]);\n }, []);\n\n const handleSquareClick = useCallback((square: ChessSquare) => {\n const chess = chessRef.current;\n const turn = chess.turn();\n\n // Ignore clicks during promotion or game over\n if (promotionPending || getGameStatus(chess).isGameOver) {\n return;\n }\n\n // If we have a selected square and this click is a legal move destination\n if (selectedSquare && legalMoves.includes(square)) {\n // Check if this is a pawn promotion\n const piece = chess.get(selectedSquare);\n if (\n piece?.type === 'p' &&\n ((piece.color === 'w' && square[1] === '8') ||\n (piece.color === 'b' && square[1] === '1'))\n ) {\n setPromotionPending({ from: selectedSquare, to: square });\n clearSelection();\n return;\n }\n\n // Execute the move\n try {\n const move = chess.move({ from: selectedSquare, to: square });\n if (move) recordMove(move);\n } catch {\n // Invalid move, just deselect\n }\n clearSelection();\n syncState();\n return;\n }\n\n // If clicking on a piece belonging to the side-to-move, select it\n const piece = chess.get(square);\n if (piece && piece.color === turn) {\n if (square === selectedSquare) {\n clearSelection();\n return;\n }\n setSelectedSquare(square);\n const moves = chess.moves({ square, verbose: true }) as Move[];\n setLegalMoves(moves.map((m) => m.to));\n return;\n }\n\n // Clicking empty square or opponent piece without selection\n clearSelection();\n }, [selectedSquare, legalMoves, promotionPending, clearSelection, syncState, recordMove]);\n\n const handlePromotion = useCallback((piece: 'q' | 'r' | 'b' | 'n') => {\n if (!promotionPending) return;\n const chess = chessRef.current;\n try {\n const move = chess.move({\n from: promotionPending.from,\n to: promotionPending.to,\n promotion: piece,\n });\n if (move) recordMove(move);\n } catch {\n // Invalid promotion, ignore\n }\n setPromotionPending(null);\n clearSelection();\n syncState();\n }, [promotionPending, clearSelection, syncState, recordMove]);\n\n /**\n * Replace the position (used by chaos). This starts a new chess.js history,\n * so repetition counting restarts. Castling and en passant fields are made\n * consistent with the board first, because chess.js keeps stale ones.\n */\n const applyFen = useCallback((newFen: string) => {\n const chess = chessRef.current;\n try {\n chess.load(sanitizeFen(newFen));\n clearSelection();\n syncState();\n } catch {\n // Invalid FEN, ignore\n }\n }, [clearSelection, syncState]);\n\n /**\n * Play a move for the side to move (used for the AI) and record it like a\n * human move. Returns false if the move is illegal, or if the position is no\n * longer `expectedFen`.\n */\n const applyMove = useCallback((input: MoveInput, expectedFen?: string): boolean => {\n const chess = chessRef.current;\n if (expectedFen !== undefined && chess.fen() !== expectedFen) return false;\n let move: Move;\n try {\n move = chess.move(input);\n } catch {\n return false;\n }\n recordMove(move);\n clearSelection();\n syncState();\n return true;\n }, [recordMove, clearSelection, syncState]);\n\n const handleRestart = useCallback(() => {\n const chess = chessRef.current;\n chess.reset();\n clearSelection();\n setMoveHistory([]);\n setLastMove(null);\n setLastMoveDetail(null);\n setPromotionPending(null);\n syncState();\n }, [clearSelection, syncState]);\n\n return {\n fen,\n turn,\n selectedSquare,\n legalMoves,\n gameStatus,\n promotionPending,\n moveHistory,\n lastMove,\n lastMoveDetail,\n board,\n handleSquareClick,\n handlePromotion,\n applyFen,\n applyMove,\n handleRestart,\n } satisfies UseChessGameReturn;\n}\n","import { sanitizeFen } from './fenManipulator.ts';\n\n// The first start includes downloading the engine; later restarts load it from cache\nconst INIT_TIMEOUT_MS = 20000;\nconst RESTART_INIT_TIMEOUT_MS = 8000;\n// Failed starts in a row before the engine reports itself unavailable\nexport const MAX_INIT_FAILURES = 3;\nconst READY_TIMEOUT_MS = 5000;\nconst SEARCH_TIMEOUT_MS = 10000;\n// After `stop`, how long to wait for the engine's bestmove before giving up on it\nconst STOP_GRACE_MS = 2000;\n\n/** A newer search replaced this one. The caller should not act on it. */\nexport class StockfishCancelledError extends Error {\n constructor() {\n super('Search cancelled');\n this.name = 'StockfishCancelledError';\n }\n}\n\n/**\n * The worker was replaced while this search was waiting, because of another\n * search's timeout. Not a failure of this search; ask again.\n */\nexport class StockfishRestartedError extends Error {\n constructor() {\n super('Stockfish worker restarted');\n this.name = 'StockfishRestartedError';\n }\n}\n\n/** Stockfish failed to start too many times in a row. Play without the AI. */\nexport class StockfishUnavailableError extends Error {\n constructor() {\n super('Stockfish is unavailable');\n this.name = 'StockfishUnavailableError';\n }\n}\n\n/** The engine did not answer in time. The worker has been replaced. */\nexport class StockfishTimeoutError extends Error {\n constructor(stage: string) {\n super(`Stockfish timed out during ${stage}`);\n this.name = 'StockfishTimeoutError';\n }\n}\n\ninterface PendingSearch {\n resolve: (move: string | null) => void;\n reject: (reason: Error) => void;\n timer: ReturnType<typeof setTimeout> | null;\n}\n\ninterface Waiter {\n match: (msg: string) => boolean;\n resolve: (msg: string) => void;\n reject: (reason: Error) => void;\n}\n\n/**\n * Wraps the Stockfish WASM Web Worker with a promise-based API.\n *\n * One search runs at a time. When a search is cancelled, the engine is sent\n * `stop`, and the next search waits for that search's `bestmove` before it\n * starts. (The real engine can answer `isready` before that `bestmove`, so\n * `isready` alone does not flush it.)\n *\n * Every wait has a timeout. A search that runs too long is stopped and its\n * best move so far is used. When the worker stops answering or reports an\n * error, it is terminated and the next search starts a fresh one.\n */\nexport class StockfishEngine {\n private worker: Worker | null = null;\n private ready: Promise<void> | null = null;\n private pending: PendingSearch | null = null;\n private waiters: Waiter[] = [];\n /** True from `go` until its `bestmove`, including after `stop`. */\n private searching = false;\n private searchId = 0;\n private destroyed = false;\n private initFailures = 0;\n private hasStarted = false;\n private workerPath: string;\n\n constructor(workerPath = '/stockfish/stockfish-18-lite-single.js') {\n this.workerPath = workerPath;\n }\n\n get isDestroyed(): boolean {\n return this.destroyed;\n }\n\n /** True after MAX_INIT_FAILURES failed starts in a row. */\n get isUnavailable(): boolean {\n return this.initFailures >= MAX_INIT_FAILURES;\n }\n\n /**\n * Start the worker and wait for `uciok`. Concurrent calls share one start.\n * Rejects with StockfishUnavailableError once starting has failed\n * MAX_INIT_FAILURES times in a row.\n */\n init(timeoutMs?: number): Promise<void> {\n if (this.destroyed) return Promise.reject(new Error('Stockfish engine destroyed'));\n if (this.isUnavailable) return Promise.reject(new StockfishUnavailableError());\n if (!this.ready) {\n const timeout = timeoutMs ?? (this.hasStarted ? RESTART_INIT_TIMEOUT_MS : INIT_TIMEOUT_MS);\n const ready: Promise<void> = this.spawn(timeout).then(\n () => {\n this.initFailures = 0;\n this.hasStarted = true;\n },\n (err) => {\n this.initFailures++;\n // A newer start may already be under way; leave it alone\n if (this.ready === ready) this.ready = null;\n throw this.isUnavailable ? new StockfishUnavailableError() : err;\n }\n );\n this.ready = ready;\n }\n return this.ready;\n }\n\n private async spawn(timeoutMs: number): Promise<void> {\n const worker = new Worker(this.workerPath);\n this.worker = worker;\n this.searching = false;\n\n // Both listeners stay attached for the worker's whole life\n worker.addEventListener('message', (e: MessageEvent) => this.handleMessage(worker, e));\n worker.addEventListener('error', (e: ErrorEvent) => this.handleWorkerError(worker, e));\n\n worker.postMessage('uci');\n try {\n await this.waitFor((msg) => msg.includes('uciok'), timeoutMs, 'init');\n } catch (err) {\n this.terminate(worker);\n throw err;\n }\n }\n\n private handleMessage(worker: Worker, e: MessageEvent): void {\n if (worker !== this.worker) return;\n const msg = typeof e.data === 'string' ? e.data : '';\n\n if (msg.startsWith('bestmove')) {\n this.searching = false;\n const pending = this.pending;\n if (pending) {\n this.pending = null;\n if (pending.timer !== null) clearTimeout(pending.timer);\n const move = msg.split(' ')[1];\n // \"(none)\" means Stockfish found no move. Resolve with null so the\n // caller can decide what to do.\n pending.resolve(move && move !== '(none)' ? move : null);\n }\n }\n\n for (const waiter of [...this.waiters]) {\n if (waiter.match(msg)) {\n this.waiters = this.waiters.filter((w) => w !== waiter);\n waiter.resolve(msg);\n }\n }\n }\n\n private handleWorkerError(worker: Worker, e: ErrorEvent): void {\n if (worker !== this.worker) return;\n const error = new Error(`Stockfish worker error: ${e.message}`);\n console.warn('[ChaosChess] Stockfish worker error, restarting:', e.message);\n this.failPending(error);\n this.terminate(worker, error);\n }\n\n /** Wait for a message from the current worker, with a timeout. */\n private waitFor(match: (msg: string) => boolean, timeoutMs: number, stage: string): Promise<string> {\n return new Promise<string>((resolve, reject) => {\n const timer = setTimeout(() => {\n this.waiters = this.waiters.filter((w) => w !== waiter);\n reject(new StockfishTimeoutError(stage));\n }, timeoutMs);\n const waiter: Waiter = {\n match,\n resolve: (msg) => {\n clearTimeout(timer);\n resolve(msg);\n },\n // Called when the worker is terminated, so callers fail fast\n reject: (err) => {\n clearTimeout(timer);\n reject(err);\n },\n };\n this.waiters.push(waiter);\n });\n }\n\n /** Terminate a worker. If it is the current one, the next search starts a new one. */\n private terminate(worker: Worker, reason: Error = new StockfishRestartedError()): void {\n try {\n worker.terminate();\n } catch {\n // Already gone\n }\n if (worker !== this.worker) return;\n this.worker = null;\n this.ready = null;\n this.searching = false;\n const waiters = this.waiters;\n this.waiters = [];\n for (const waiter of waiters) waiter.reject(reason);\n }\n\n /** Reject the in-flight search and clear its timer. */\n private failPending(reason: Error): void {\n const pending = this.pending;\n if (!pending) return;\n this.pending = null;\n if (pending.timer !== null) clearTimeout(pending.timer);\n pending.reject(reason);\n }\n\n /** Cancel any in-flight search. Its bestmove is drained before the next search. */\n private cancelPending(): void {\n this.failPending(new StockfishCancelledError());\n if (this.searching) this.stop();\n }\n\n /**\n * Cancel whatever this engine is doing, including a search that is still\n * waiting to start. The engine stays usable.\n */\n cancel(): void {\n this.searchId++;\n this.cancelPending();\n }\n\n /**\n * Get the best move for a given FEN position at the specified depth.\n * Returns a UCI move string like \"e2e4\", or null when Stockfish reports\n * no move (\"(none)\").\n *\n * Calling this while a search is in-flight cancels the previous search,\n * which rejects with StockfishCancelledError. A search that passes\n * `timeoutMs` is stopped and resolves with the best move found so far. If\n * the engine does not answer even then, the worker is replaced and the\n * search rejects with StockfishTimeoutError.\n */\n async getBestMove(fen: string, depth: number, timeoutMs = SEARCH_TIMEOUT_MS): Promise<string | null> {\n // `go depth 0` or `go depth NaN` never returns\n const searchDepth = Number.isFinite(depth) ? Math.min(20, Math.max(1, Math.round(depth))) : 10;\n const mySearchId = ++this.searchId;\n this.cancelPending();\n\n await this.init();\n const worker = this.worker;\n if (!worker) throw new Error('Stockfish not initialized');\n if (mySearchId !== this.searchId) throw new StockfishCancelledError();\n\n try {\n // A stopped search still sends its bestmove. Wait for it so it can't be\n // taken as the answer to this search.\n if (this.searching) {\n await this.waitFor((msg) => msg.startsWith('bestmove'), STOP_GRACE_MS, 'stop');\n }\n worker.postMessage('isready');\n await this.waitFor((msg) => msg === 'readyok', READY_TIMEOUT_MS, 'isready');\n } catch (err) {\n // A newer search owns the worker now. Let its own timeouts decide\n // whether the worker is stuck, instead of killing it under that search.\n if (mySearchId !== this.searchId) throw new StockfishCancelledError();\n if (err instanceof StockfishTimeoutError) this.terminate(worker);\n throw err;\n }\n // A newer call started while we waited\n if (mySearchId !== this.searchId) throw new StockfishCancelledError();\n if (worker !== this.worker || this.searching) throw new StockfishRestartedError();\n\n return new Promise<string | null>((resolve, reject) => {\n const pending: PendingSearch = { resolve, reject, timer: null };\n\n pending.timer = setTimeout(() => {\n if (this.pending !== pending) return;\n // Too slow: ask for the best move so far\n worker.postMessage('stop');\n pending.timer = setTimeout(() => {\n if (this.pending !== pending) return;\n // No answer even to `stop`: Stockfish is stuck inside `position` or `go`\n this.failPending(new StockfishTimeoutError('search'));\n this.terminate(worker);\n }, STOP_GRACE_MS);\n }, timeoutMs);\n\n this.pending = pending;\n this.searching = true;\n // Clear transposition table so chaos-mutated boards start from a clean slate\n worker.postMessage('ucinewgame');\n // Stale castling flags can freeze Stockfish, so fix them before sending\n worker.postMessage(`position fen ${sanitizeFen(fen)}`);\n worker.postMessage(`go depth ${searchDepth}`);\n });\n }\n\n /**\n * Stop any current search.\n */\n stop(): void {\n this.worker?.postMessage('stop');\n }\n\n /**\n * Terminate the worker.\n */\n destroy(): void {\n this.destroyed = true;\n this.cancel();\n const worker = this.worker;\n if (worker) {\n worker.postMessage('quit');\n this.terminate(worker, new Error('Stockfish engine destroyed'));\n }\n }\n}\n","import { StockfishEngine } from './stockfishWorker.ts';\n\n/**\n * Keeps released engines alive for a while, so a game that is unmounted and\n * mounted again (a tab switch, React StrictMode) reuses the loaded worker\n * instead of downloading and starting Stockfish again.\n *\n * Each mounted game gets its own engine. Two games on screen at once never\n * share one, because their searches would cancel each other.\n */\nconst IDLE_TTL_MS = 5 * 60 * 1000;\n\ninterface IdleEngine {\n engine: StockfishEngine;\n timer: ReturnType<typeof setTimeout>;\n}\n\nconst idle = new Map<string, IdleEngine[]>();\n\nfunction poolKey(workerPath?: string): string {\n return workerPath ?? '';\n}\n\n/** Take an idle engine for this worker path, or create one. */\nexport function acquireEngine(workerPath?: string): StockfishEngine {\n const key = poolKey(workerPath);\n const list = idle.get(key);\n while (list && list.length > 0) {\n const entry = list.pop()!;\n clearTimeout(entry.timer);\n if (!entry.engine.isDestroyed && !entry.engine.isUnavailable) return entry.engine;\n entry.engine.destroy();\n }\n return new StockfishEngine(workerPath);\n}\n\n/** Stop the engine's search and keep it for reuse until the idle time runs out. */\nexport function releaseEngine(engine: StockfishEngine, workerPath?: string): void {\n engine.cancel();\n const key = poolKey(workerPath);\n const list = idle.get(key) ?? [];\n // Releasing twice must not let two games acquire the same engine\n if (list.some((entry) => entry.engine === engine)) return;\n const entry: IdleEngine = {\n engine,\n timer: setTimeout(() => {\n const current = idle.get(key);\n if (current) idle.set(key, current.filter((e) => e !== entry));\n engine.destroy();\n }, IDLE_TTL_MS),\n };\n list.push(entry);\n idle.set(key, list);\n}\n\n/** Destroy all idle engines. For tests. */\nexport function clearEnginePool(): void {\n for (const list of idle.values()) {\n for (const entry of list) {\n clearTimeout(entry.timer);\n entry.engine.destroy();\n }\n }\n idle.clear();\n}\n","import { useState, useRef, useEffect, useCallback } from 'react';\nimport { StockfishUnavailableError, MAX_INIT_FAILURES } from '../engine/stockfishWorker.ts';\nimport type { StockfishEngine } from '../engine/stockfishWorker.ts';\nimport { acquireEngine, releaseEngine } from '../engine/enginePool.ts';\n\nexport type EngineStatus = 'loading' | 'ready' | 'failed';\n\ninterface UseStockfishReturn {\n status: EngineStatus;\n isReady: boolean;\n isThinking: boolean;\n getBestMove: (fen: string, depth: number) => Promise<string | null>;\n /** Cancel the current search, if any. Its promise rejects with StockfishCancelledError. */\n cancel: () => void;\n}\n\nconst INIT_RETRY_DELAY_MS = 2000;\n// Longer than the engine's worst case (restart + isready + search + stop grace),\n// so this only fires if a promise is somehow never settled.\nconst SAFETY_TIMEOUT_MS = 45000;\n\nexport function useStockfish(workerPath?: string): UseStockfishReturn {\n const engineRef = useRef<StockfishEngine | null>(null);\n const [status, setStatus] = useState<EngineStatus>('loading');\n const [isThinking, setIsThinking] = useState(false);\n // Track in-flight calls so only the latest one controls isThinking\n const callIdRef = useRef(0);\n\n useEffect(() => {\n // Reuses a worker left by an earlier mount when there is one\n const engine = acquireEngine(workerPath);\n engineRef.current = engine;\n let cancelled = false;\n let retryTimer: ReturnType<typeof setTimeout> | null = null;\n setStatus('loading');\n\n // A failed or timed-out start terminates its worker, so retrying\n // does not leave old workers or listeners behind.\n const start = (attempt: number) => {\n engine\n .init()\n .then(() => {\n if (!cancelled) setStatus('ready');\n })\n .catch((err) => {\n if (cancelled) return;\n console.warn(`Stockfish failed to load (attempt ${attempt}/${MAX_INIT_FAILURES}):`, err.message);\n if (engine.isUnavailable) {\n setStatus('failed');\n } else {\n retryTimer = setTimeout(() => start(attempt + 1), INIT_RETRY_DELAY_MS);\n }\n });\n };\n start(1);\n\n return () => {\n cancelled = true;\n if (retryTimer) clearTimeout(retryTimer);\n // Cancels any search, which clears isThinking through getBestMove's finally\n releaseEngine(engine, workerPath);\n engineRef.current = null;\n };\n }, [workerPath]);\n\n const isReady = status === 'ready';\n\n const getBestMove = useCallback(\n async (fen: string, depth: number): Promise<string | null> => {\n if (!engineRef.current || !isReady) return null;\n const myCallId = ++callIdRef.current;\n setIsThinking(true);\n\n const safetyTimeout = setTimeout(() => {\n if (callIdRef.current === myCallId) {\n console.warn(`[ChaosChess] Safety timeout: clearing isThinking after ${SAFETY_TIMEOUT_MS / 1000}s`);\n setIsThinking(false);\n }\n }, SAFETY_TIMEOUT_MS);\n\n try {\n // Resolves a move string, or null when the engine reports \"(none)\".\n // A cancelled/superseded search rejects with StockfishCancelledError;\n // a timeout or worker crash rejects too, after the engine has replaced\n // its worker, so the next call gets a working engine.\n const move = await engineRef.current.getBestMove(fen, depth);\n return move;\n } catch (err) {\n // The worker keeps failing to restart: switch to two-player mode\n if (err instanceof StockfishUnavailableError) setStatus('failed');\n throw err;\n } finally {\n clearTimeout(safetyTimeout);\n // Only clear isThinking if no newer call has started\n if (callIdRef.current === myCallId) {\n setIsThinking(false);\n }\n }\n },\n [isReady]\n );\n\n const cancel = useCallback(() => {\n engineRef.current?.cancel();\n }, []);\n\n return { status, isReady, isThinking, getBestMove, cancel };\n}\n","import { Chess } from 'chess.js';\nimport type { PieceSymbol, Color, ChessSquare, ChaosAction, ChaosTarget } from '../types/chess.ts';\nimport {\n calculateMaterial,\n getEmptySquares,\n getPieceSquares,\n addPieceToFen,\n removePieceFromFen,\n parseFen,\n positionToBoard,\n sanitizeCastling,\n sanitizeEnPassant,\n} from './fenManipulator.ts';\n\nconst ADDABLE_PIECES: PieceSymbol[] = ['p', 'n', 'b', 'r', 'q'];\nconst MAX_RETRIES = 10;\n\n// Stockfish answers `bestmove (none)` for positions outside these limits,\n// so chaos must never produce them.\nexport const MAX_PIECES_PER_SIDE = 16;\nexport const MAX_PAWNS_PER_SIDE = 8;\n\n/**\n * Determine which side to help based on material balance.\n * 70% chance to help the losing side, 30% chance to help the winning side.\n * Equal material = 50/50.\n */\nexport function getChaosTarget(whiteMaterial: number, blackMaterial: number): ChaosTarget {\n if (whiteMaterial > blackMaterial) {\n return Math.random() < 0.7 ? 'help_black' : 'help_white';\n } else if (blackMaterial > whiteMaterial) {\n return Math.random() < 0.7 ? 'help_white' : 'help_black';\n }\n return Math.random() < 0.5 ? 'help_white' : 'help_black';\n}\n\n/**\n * Pick a random element from an array.\n */\nfunction randomChoice<T>(arr: T[]): T {\n return arr[Math.floor(Math.random() * arr.length)];\n}\n\n/**\n * Return a shuffled copy of an array.\n */\nfunction shuffled<T>(arr: T[]): T[] {\n const out = [...arr];\n for (let i = out.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n [out[i], out[j]] = [out[j], out[i]];\n }\n return out;\n}\n\n/**\n * Choose a random piece type to add.\n * Pawns are excluded on rank 1 or 8, and when the side already has 8 pawns.\n */\nfunction chooseRandomPiece(square: ChessSquare, allowPawn: boolean): PieceSymbol {\n const rank = parseInt(square[1]);\n if (!allowPawn || rank === 1 || rank === 8) {\n const noPawns: PieceSymbol[] = ['n', 'b', 'r', 'q'];\n return randomChoice(noPawns);\n }\n return randomChoice(ADDABLE_PIECES);\n}\n\n/**\n * Count all pieces (king included) and pawns for one side.\n */\nfunction countPieces(fen: string, color: Color): { total: number; pawns: number } {\n const board = positionToBoard(parseFen(fen).position);\n let total = 0;\n let pawns = 0;\n for (const row of board) {\n for (const cell of row) {\n if (cell && cell.color === color) {\n total++;\n if (cell.type === 'p') pawns++;\n }\n }\n }\n return { total, pawns };\n}\n\n/**\n * Validate that a FEN is a position both chess.js and Stockfish will play from:\n * - chess.js can load it\n * - each side has exactly one king, at most 16 pieces and at most 8 pawns\n * - no pawns on rank 1 or 8\n * - the side not to move is not in check\n * - the castling and en passant fields agree with the board\n */\nexport function isValidChaosPosition(fen: string): boolean {\n let chess: Chess;\n try {\n chess = new Chess(fen);\n } catch {\n return false;\n }\n\n const { position, activeColor, castling, enPassant } = parseFen(fen);\n const board = positionToBoard(position);\n const totals = { w: 0, b: 0 };\n const pawns = { w: 0, b: 0 };\n const kings: Record<Color, ChessSquare[]> = { w: [], b: [] };\n\n for (let rank = 0; rank < 8; rank++) {\n for (let file = 0; file < 8; file++) {\n const cell = board[rank][file];\n if (!cell) continue;\n totals[cell.color]++;\n if (cell.type === 'p') {\n if (rank === 0 || rank === 7) return false;\n pawns[cell.color]++;\n }\n if (cell.type === 'k') {\n kings[cell.color].push(`${'abcdefgh'[file]}${8 - rank}` as ChessSquare);\n }\n }\n }\n\n for (const color of ['w', 'b'] as const) {\n if (kings[color].length !== 1) return false;\n if (totals[color] > MAX_PIECES_PER_SIDE) return false;\n if (pawns[color] > MAX_PAWNS_PER_SIDE) return false;\n }\n\n if (sanitizeCastling(castling, board) !== castling) return false;\n if (sanitizeEnPassant(enPassant, activeColor, board) !== enPassant) return false;\n\n const sideNotToMove: Color = chess.turn() === 'w' ? 'b' : 'w';\n if (chess.isAttacked(kings[sideNotToMove][0], chess.turn())) return false;\n\n return true;\n}\n\n/**\n * Try to add a random piece for the given color.\n * Returns { newFen, action } or null if impossible.\n */\nexport function addRandomPiece(\n fen: string,\n color: Color\n): { newFen: string; square: ChessSquare; piece: PieceSymbol } | null {\n const emptySquares = getEmptySquares(fen);\n if (emptySquares.length === 0) return null;\n\n const { total, pawns } = countPieces(fen, color);\n if (total >= MAX_PIECES_PER_SIDE) return null;\n const allowPawn = pawns < MAX_PAWNS_PER_SIDE;\n\n for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {\n const square = randomChoice(emptySquares);\n const piece = chooseRandomPiece(square, allowPawn);\n const newFen = addPieceToFen(fen, square, piece, color);\n if (isValidChaosPosition(newFen)) {\n return { newFen, square, piece };\n }\n }\n return null;\n}\n\n/**\n * Try to remove a random piece of the given color (excluding king).\n * Returns { newFen, square } or null if impossible.\n */\nexport function removeRandomPiece(\n fen: string,\n color: Color\n): { newFen: string; square: ChessSquare } | null {\n const pieceSquares = getPieceSquares(fen, color, true);\n if (pieceSquares.length === 0) return null;\n\n for (const square of shuffled(pieceSquares).slice(0, MAX_RETRIES)) {\n // Removing a blocker can expose a king, so every result is validated\n const newFen = removePieceFromFen(fen, square);\n if (isValidChaosPosition(newFen)) {\n return { newFen, square };\n }\n }\n return null;\n}\n\n/**\n * Execute one chaos action: evaluate material, pick target side, randomly add or remove.\n * Returns the action details and new FEN, or null if no valid action was found.\n */\nexport function executeChaosAction(fen: string): { newFen: string; action: ChaosAction } | null {\n const { white: whiteMaterial, black: blackMaterial } = calculateMaterial(fen);\n const target = getChaosTarget(whiteMaterial, blackMaterial);\n const operation = Math.random() < 0.5 ? 'add' : 'remove';\n\n // Determine which color to add to / remove from\n const addColor: Color = target === 'help_white' ? 'w' : 'b';\n const removeColor: Color = target === 'help_white' ? 'b' : 'w';\n\n if (operation === 'add') {\n const result = addRandomPiece(fen, addColor);\n if (result) {\n return {\n newFen: result.newFen,\n action: {\n type: 'add',\n target,\n square: result.square,\n piece: result.piece,\n color: addColor,\n whiteMaterial,\n blackMaterial,\n },\n };\n }\n // Fallback: try remove instead\n const fallback = removeRandomPiece(fen, removeColor);\n if (fallback) {\n return {\n newFen: fallback.newFen,\n action: {\n type: 'remove',\n target,\n square: fallback.square,\n whiteMaterial,\n blackMaterial,\n },\n };\n }\n } else {\n const result = removeRandomPiece(fen, removeColor);\n if (result) {\n return {\n newFen: result.newFen,\n action: {\n type: 'remove',\n target,\n square: result.square,\n whiteMaterial,\n blackMaterial,\n },\n };\n }\n // Fallback: try add instead\n const fallback = addRandomPiece(fen, addColor);\n if (fallback) {\n return {\n newFen: fallback.newFen,\n action: {\n type: 'add',\n target,\n square: fallback.square,\n piece: fallback.piece,\n color: addColor,\n whiteMaterial,\n blackMaterial,\n },\n };\n }\n }\n\n return null;\n}\n\n/**\n * Uniform distribution for chaos interval, parameterized by stupid level (1-5).\n *\n * Level 1: 12–20s (chill)\n * Level 2: 8–15s (moderate)\n * Level 3: 5–12s (default)\n * Level 4: 3–7s (chaotic)\n * Level 5: 1–4s (insane)\n */\nconst STUPID_BOUNDS: [number, number][] = [\n [12, 20], // level 1\n [8, 15], // level 2\n [5, 12], // level 3\n [3, 7], // level 4\n [1, 4], // level 5\n];\n\nexport function getRandomChaosInterval(stupidLevel: number = 3): number {\n const level = Number.isFinite(stupidLevel) ? Math.round(stupidLevel) : 3;\n const idx = Math.max(0, Math.min(4, level - 1));\n const [lo, hi] = STUPID_BOUNDS[idx];\n const seconds = lo + Math.random() * (hi - lo);\n return seconds * 1000;\n}\n","import { useState, useEffect, useLayoutEffect, useRef, useCallback } from 'react';\nimport { executeChaosAction, getRandomChaosInterval } from '../engine/chaosEngine.ts';\nimport type { ChaosAction, ChessSquare } from '../types/chess.ts';\n\ninterface UseChaosEngineParams {\n fen: string;\n isPaused: boolean;\n stupidLevel: number;\n onChaosAction: (newFen: string) => ChaosApplyResult;\n /** Changing this starts a fresh countdown and clears the last action (new game). */\n resetKey?: number;\n}\n\n/** Whether the game accepted the chaos position. */\nexport type ChaosApplyResult = boolean | void;\n\ninterface UseChaosEngineReturn {\n countdown: number;\n maxCountdown: number;\n lastAction: ChaosAction | null;\n chaosSquare: ChessSquare | null;\n}\n\nconst TICK_MS = 200;\n// After a pause (the AI's turn, a hidden tab), give the human at least this\n// long before chaos can fire, so it never lands on the same frame as the AI's move.\nconst MIN_RESUME_MS = 1000;\n\nfunction isDocumentHidden(): boolean {\n return typeof document !== 'undefined' && document.visibilityState === 'hidden';\n}\n\nexport function useChaosEngine({\n fen,\n isPaused,\n stupidLevel,\n onChaosAction,\n resetKey = 0,\n}: UseChaosEngineParams): UseChaosEngineReturn {\n const [countdown, setCountdown] = useState(0);\n const [maxCountdown, setMaxCountdown] = useState(0);\n const [lastAction, setLastAction] = useState<ChaosAction | null>(null);\n const [chaosSquare, setChaosSquare] = useState<ChessSquare | null>(null);\n\n const fenRef = useRef(fen);\n const isPausedRef = useRef(isPaused);\n const stupidLevelRef = useRef(stupidLevel);\n const onChaosActionRef = useRef(onChaosAction);\n // Time left on the countdown. It only runs down while the game is unpaused\n // and the tab is visible, so pauses never need to be \"caught up\".\n const remainingMsRef = useRef(0);\n const lastTickRef = useRef(0);\n const wasPausedRef = useRef(false);\n const hiddenRef = useRef(false);\n\n fenRef.current = fen;\n isPausedRef.current = isPaused;\n stupidLevelRef.current = stupidLevel;\n onChaosActionRef.current = onChaosAction;\n\n const scheduleNext = useCallback(() => {\n const intervalMs = getRandomChaosInterval(stupidLevelRef.current);\n const seconds = Math.ceil(intervalMs / 1000);\n setMaxCountdown(seconds);\n setCountdown(seconds);\n remainingMsRef.current = intervalMs;\n }, []);\n\n // Record every pause as soon as it is committed. A fast AI move can start\n // and end between two ticks, and the tick alone would miss it.\n useLayoutEffect(() => {\n if (isPaused) wasPausedRef.current = true;\n }, [isPaused]);\n\n // New game or new STUPID level: start a fresh countdown now\n useEffect(() => {\n scheduleNext();\n }, [stupidLevel, scheduleNext]);\n\n const isFirstReset = useRef(true);\n useEffect(() => {\n if (isFirstReset.current) {\n isFirstReset.current = false;\n return;\n }\n setLastAction(null);\n setChaosSquare(null);\n scheduleNext();\n }, [resetKey, scheduleNext]);\n\n // Pause while the tab is hidden; browsers throttle timers there anyway\n useEffect(() => {\n hiddenRef.current = isDocumentHidden();\n const onVisibility = () => {\n hiddenRef.current = isDocumentHidden();\n lastTickRef.current = Date.now();\n if (hiddenRef.current) wasPausedRef.current = true;\n };\n document.addEventListener('visibilitychange', onVisibility);\n return () => document.removeEventListener('visibilitychange', onVisibility);\n }, []);\n\n useEffect(() => {\n lastTickRef.current = Date.now();\n let flashTimer: ReturnType<typeof setTimeout> | null = null;\n\n const intervalId = setInterval(() => {\n const now = Date.now();\n const elapsed = now - lastTickRef.current;\n lastTickRef.current = now;\n\n if (isPausedRef.current || hiddenRef.current) {\n wasPausedRef.current = true;\n return;\n }\n if (wasPausedRef.current) {\n wasPausedRef.current = false;\n remainingMsRef.current = Math.max(remainingMsRef.current, MIN_RESUME_MS);\n setCountdown(Math.ceil(remainingMsRef.current / 1000));\n return;\n }\n\n remainingMsRef.current -= elapsed;\n setCountdown(Math.max(0, Math.ceil(remainingMsRef.current / 1000)));\n if (remainingMsRef.current > 0) return;\n\n // Fire chaos action\n const result = executeChaosAction(fenRef.current);\n if (result && onChaosActionRef.current(result.newFen) !== false) {\n setLastAction(result.action);\n setChaosSquare(result.action.square);\n\n // Clear chaos square highlight after animation\n if (flashTimer) clearTimeout(flashTimer);\n flashTimer = setTimeout(() => setChaosSquare(null), 600);\n }\n scheduleNext();\n }, TICK_MS);\n\n return () => {\n clearInterval(intervalId);\n if (flashTimer) clearTimeout(flashTimer);\n };\n }, [scheduleNext]);\n\n return { countdown, maxCountdown, lastAction, chaosSquare };\n}\n","// Piece artwork: the \"Cburnett\" set by Colin M.L. Burnett, used under the\n// BSD 3-clause licence (one of the licences it is offered under on Wikimedia\n// Commons). See THIRD_PARTY_NOTICES.md. Colours are CSS variables so hosts\n// can theme them: --cc-pw-body/--cc-pw-line for white, --cc-pb-body,\n// --cc-pb-line and --cc-pb-detail for black. Inner markup of a 45x45 viewBox.\n\nexport const PIECE_ART: Record<string, string> = {\n wk: \"<g style=\\\"stroke:var(--cc-pw-line)\\\" fill=\\\"none\\\" fill-rule=\\\"evenodd\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" stroke-width=\\\"1.5\\\"><path stroke-linejoin=\\\"miter\\\" d=\\\"M22.5 11.63V6M20 8h5\\\"/><path style=\\\"fill:var(--cc-pw-body)\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" d=\\\"M22.5 25s4.5-7.5 3-10.5c0 0-1-2.5-3-2.5s-3 2.5-3 2.5c-1.5 3 3 10.5 3 10.5\\\"/><path style=\\\"fill:var(--cc-pw-body)\\\" d=\\\"M12.5 37c5.5 3.5 14.5 3.5 20 0v-7s9-4.5 6-10.5c-4-6.5-13.5-3.5-16 4V27v-3.5c-2.5-7.5-12-10.5-16-4-3 6 6 10.5 6 10.5v7\\\"/><path d=\\\"M12.5 30c5.5-3 14.5-3 20 0m-20 3.5c5.5-3 14.5-3 20 0m-20 3.5c5.5-3 14.5-3 20 0\\\"/></g>\",\n wq: \"<g style=\\\"fill:var(--cc-pw-body);stroke:var(--cc-pw-line)\\\" stroke-width=\\\"1.5\\\" stroke-linejoin=\\\"round\\\"><path d=\\\"M 9,26 C 17.5,24.5 30,24.5 36,26 L 38.5,13.5 L 31,25 L 30.7,10.9 L 25.5,24.5 L 22.5,10 L 19.5,24.5 L 14.3,10.9 L 14,25 L 6.5,13.5 L 9,26 z\\\"/><path d=\\\"M 9,26 C 9,28 10.5,28 11.5,30 C 12.5,31.5 12.5,31 12,33.5 C 10.5,34.5 11,36 11,36 C 9.5,37.5 11,38.5 11,38.5 C 17.5,39.5 27.5,39.5 34,38.5 C 34,38.5 35.5,37.5 34,36 C 34,36 34.5,34.5 33,33.5 C 32.5,31 32.5,31.5 33.5,30 C 34.5,28 36,28 36,26 C 27.5,24.5 17.5,24.5 9,26 z\\\"/><path d=\\\"M 11.5,30 C 15,29 30,29 33.5,30\\\" fill=\\\"none\\\"/><path d=\\\"M 12,33.5 C 18,32.5 27,32.5 33,33.5\\\" fill=\\\"none\\\"/><circle cx=\\\"6\\\" cy=\\\"12\\\" r=\\\"2\\\" /><circle cx=\\\"14\\\" cy=\\\"9\\\" r=\\\"2\\\" /><circle cx=\\\"22.5\\\" cy=\\\"8\\\" r=\\\"2\\\" /><circle cx=\\\"31\\\" cy=\\\"9\\\" r=\\\"2\\\" /><circle cx=\\\"39\\\" cy=\\\"12\\\" r=\\\"2\\\" /></g>\",\n wr: \"<g style=\\\"fill:var(--cc-pw-body);stroke:var(--cc-pw-line)\\\" fill-rule=\\\"evenodd\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" transform=\\\"translate(0,0.3)\\\"><path d=\\\"M 9,39 L 36,39 L 36,36 L 9,36 L 9,39 z \\\" stroke-linecap=\\\"butt\\\" /><path d=\\\"M 12,36 L 12,32 L 33,32 L 33,36 L 12,36 z \\\" stroke-linecap=\\\"butt\\\" /><path d=\\\"M 11,14 L 11,9 L 15,9 L 15,11 L 20,11 L 20,9 L 25,9 L 25,11 L 30,11 L 30,9 L 34,9 L 34,14\\\" stroke-linecap=\\\"butt\\\" /><path d=\\\"M 34,14 L 31,17 L 14,17 L 11,14\\\" /><path d=\\\"M 31,17 L 31,29.5 L 14,29.5 L 14,17\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" /><path d=\\\"M 31,29.5 L 32.5,32 L 12.5,32 L 14,29.5\\\" /><path style=\\\"stroke:var(--cc-pw-line)\\\" d=\\\"M 11,14 L 34,14\\\" fill=\\\"none\\\" stroke-linejoin=\\\"miter\\\" /></g>\",\n wb: \"<g style=\\\"stroke:var(--cc-pw-line)\\\" fill=\\\"none\\\" fill-rule=\\\"evenodd\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" transform=\\\"translate(0,0.6)\\\"><g style=\\\"fill:var(--cc-pw-body);stroke:var(--cc-pw-line)\\\" stroke-linecap=\\\"butt\\\"><path d=\\\"M 9,36 C 12.39,35.03 19.11,36.43 22.5,34 C 25.89,36.43 32.61,35.03 36,36 C 36,36 37.65,36.54 39,38 C 38.32,38.97 37.35,38.99 36,38.5 C 32.61,37.53 25.89,38.96 22.5,37.5 C 19.11,38.96 12.39,37.53 9,38.5 C 7.65,38.99 6.68,38.97 6,38 C 7.35,36.54 9,36 9,36 z\\\"/><path d=\\\"M 15,32 C 17.5,34.5 27.5,34.5 30,32 C 30.5,30.5 30,30 30,30 C 30,27.5 27.5,26 27.5,26 C 33,24.5 33.5,14.5 22.5,10.5 C 11.5,14.5 12,24.5 17.5,26 C 17.5,26 15,27.5 15,30 C 15,30 14.5,30.5 15,32 z\\\"/><path d=\\\"M 25 8 A 2.5 2.5 0 1 1 20,8 A 2.5 2.5 0 1 1 25 8 z\\\"/></g><path style=\\\"stroke:var(--cc-pw-line)\\\" d=\\\"M 17.5,26 L 27.5,26 M 15,30 L 30,30 M 22.5,15.5 L 22.5,20.5 M 20,18 L 25,18\\\" fill=\\\"none\\\" stroke-linejoin=\\\"miter\\\"/></g>\",\n wn: \"<g style=\\\"stroke:var(--cc-pw-line)\\\" fill=\\\"none\\\" fill-rule=\\\"evenodd\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" transform=\\\"translate(0,0.3)\\\"><path style=\\\"fill:var(--cc-pw-body);stroke:var(--cc-pw-line)\\\" d=\\\"M 22,10 C 32.5,11 38.5,18 38,39 L 15,39 C 15,30 25,32.5 23,18\\\" /><path style=\\\"fill:var(--cc-pw-body);stroke:var(--cc-pw-line)\\\" d=\\\"M 24,18 C 24.38,20.91 18.45,25.37 16,27 C 13,29 13.18,31.34 11,31 C 9.958,30.06 12.41,27.96 11,28 C 10,28 11.19,29.23 10,30 C 9,30 5.997,31 6,26 C 6,24 12,14 12,14 C 12,14 13.89,12.1 14,10.5 C 13.27,9.506 13.5,8.5 13.5,7.5 C 14.5,6.5 16.5,10 16.5,10 L 18.5,10 C 18.5,10 19.28,8.008 21,7 C 22,7 22,10 22,10\\\" /><path style=\\\"fill:var(--cc-pw-line);stroke:var(--cc-pw-line)\\\" d=\\\"M 9.5 25.5 A 0.5 0.5 0 1 1 8.5,25.5 A 0.5 0.5 0 1 1 9.5 25.5 z\\\" /><path style=\\\"fill:var(--cc-pw-line);stroke:var(--cc-pw-line)\\\" d=\\\"M 15 15.5 A 0.5 1.5 0 1 1 14,15.5 A 0.5 1.5 0 1 1 15 15.5 z\\\" transform=\\\"matrix(0.866,0.5,-0.5,0.866,9.693,-5.173)\\\" /></g>\",\n wp: \"<path style=\\\"fill:var(--cc-pw-body);stroke:var(--cc-pw-line)\\\" d=\\\"m 22.5,9 c -2.21,0 -4,1.79 -4,4 0,0.89 0.29,1.71 0.78,2.38 C 17.33,16.5 16,18.59 16,21 c 0,2.03 0.94,3.84 2.41,5.03 C 15.41,27.09 11,31.58 11,39.5 H 34 C 34,31.58 29.59,27.09 26.59,26.03 28.06,24.84 29,23.03 29,21 29,18.59 27.67,16.5 25.72,15.38 26.21,14.71 26.5,13.89 26.5,13 c 0,-2.21 -1.79,-4 -4,-4 z\\\" fill-rule=\\\"nonzero\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"miter\\\"/>\",\n bk: \"<g style=\\\"stroke:var(--cc-pb-line)\\\" fill=\\\"none\\\" fill-rule=\\\"evenodd\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"><path style=\\\"stroke:var(--cc-pb-line)\\\" d=\\\"M 22.5,11.63 L 22.5,6\\\" fill=\\\"none\\\" stroke-linejoin=\\\"miter\\\" id=\\\"path6570\\\"/><path style=\\\"fill:var(--cc-pb-body)\\\" d=\\\"M 22.5,25 C 22.5,25 27,17.5 25.5,14.5 C 25.5,14.5 24.5,12 22.5,12 C 20.5,12 19.5,14.5 19.5,14.5 C 18,17.5 22.5,25 22.5,25\\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\"/><path style=\\\"fill:var(--cc-pb-body);stroke:var(--cc-pb-line)\\\" d=\\\"M 12.5,37 C 18,40.5 27,40.5 32.5,37 L 32.5,30 C 32.5,30 41.5,25.5 38.5,19.5 C 34.5,13 25,16 22.5,23.5 L 22.5,27 L 22.5,23.5 C 20,16 10.5,13 6.5,19.5 C 3.5,25.5 12.5,30 12.5,30 L 12.5,37\\\"/><path style=\\\"stroke:var(--cc-pb-line)\\\" d=\\\"M 20,8 L 25,8\\\" fill=\\\"none\\\" stroke-linejoin=\\\"miter\\\"/><path style=\\\"stroke:var(--cc-pb-detail)\\\" d=\\\"M 32,29.5 C 32,29.5 40.5,25.5 38.03,19.85 C 34.15,14 25,18 22.5,24.5 L 22.5,26.6 L 22.5,24.5 C 20,18 10.85,14 6.97,19.85 C 4.5,25.5 13,29.5 13,29.5\\\" fill=\\\"none\\\"/><path style=\\\"stroke:var(--cc-pb-detail)\\\" d=\\\"M 12.5,30 C 18,27 27,27 32.5,30 M 12.5,33.5 C 18,30.5 27,30.5 32.5,33.5 M 12.5,37 C 18,34 27,34 32.5,37\\\" fill=\\\"none\\\"/></g>\",\n bq: \"<g style=\\\"fill:var(--cc-pb-body);stroke:var(--cc-pb-line)\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"><path style=\\\"fill:var(--cc-pb-body)\\\" d=\\\"M 9,26 C 17.5,24.5 30,24.5 36,26 L 38.5,13.5 L 31,25 L 30.7,10.9 L 25.5,24.5 L 22.5,10 L 19.5,24.5 L 14.3,10.9 L 14,25 L 6.5,13.5 L 9,26 z\\\" stroke-linecap=\\\"butt\\\" /><path d=\\\"m 9,26 c 0,2 1.5,2 2.5,4 1,1.5 1,1 0.5,3.5 -1.5,1 -1,2.5 -1,2.5 -1.5,1.5 0,2.5 0,2.5 6.5,1 16.5,1 23,0 0,0 1.5,-1 0,-2.5 0,0 0.5,-1.5 -1,-2.5 -0.5,-2.5 -0.5,-2 0.5,-3.5 1,-2 2.5,-2 2.5,-4 -8.5,-1.5 -18.5,-1.5 -27,0 z\\\" /><path d=\\\"M 11.5,30 C 15,29 30,29 33.5,30\\\" /><path d=\\\"m 12,33.5 c 6,-1 15,-1 21,0\\\" /><circle cx=\\\"6\\\" cy=\\\"12\\\" r=\\\"2\\\" /><circle cx=\\\"14\\\" cy=\\\"9\\\" r=\\\"2\\\" /><circle cx=\\\"22.5\\\" cy=\\\"8\\\" r=\\\"2\\\" /><circle cx=\\\"31\\\" cy=\\\"9\\\" r=\\\"2\\\" /><circle cx=\\\"39\\\" cy=\\\"12\\\" r=\\\"2\\\" /><path style=\\\"stroke:var(--cc-pb-line)\\\" d=\\\"M 11,38.5 A 35,35 1 0 0 34,38.5\\\" fill=\\\"none\\\" stroke-linecap=\\\"butt\\\" /><g style=\\\"stroke:var(--cc-pb-detail)\\\" fill=\\\"none\\\"><path d=\\\"M 11,29 A 35,35 1 0 1 34,29\\\" /><path d=\\\"M 12.5,31.5 L 32.5,31.5\\\" /><path d=\\\"M 11.5,34.5 A 35,35 1 0 0 33.5,34.5\\\" /><path d=\\\"M 10.5,37.5 A 35,35 1 0 0 34.5,37.5\\\" /></g></g>\",\n br: \"<g style=\\\"fill:var(--cc-pb-body);stroke:var(--cc-pb-line)\\\" fill-rule=\\\"evenodd\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" transform=\\\"translate(0,0.3)\\\"><path d=\\\"M 9,39 L 36,39 L 36,36 L 9,36 L 9,39 z \\\" stroke-linecap=\\\"butt\\\" /><path d=\\\"M 12.5,32 L 14,29.5 L 31,29.5 L 32.5,32 L 12.5,32 z \\\" stroke-linecap=\\\"butt\\\" /><path d=\\\"M 12,36 L 12,32 L 33,32 L 33,36 L 12,36 z \\\" stroke-linecap=\\\"butt\\\" /><path d=\\\"M 14,29.5 L 14,16.5 L 31,16.5 L 31,29.5 L 14,29.5 z \\\" stroke-linecap=\\\"butt\\\" stroke-linejoin=\\\"miter\\\" /><path d=\\\"M 14,16.5 L 11,14 L 34,14 L 31,16.5 L 14,16.5 z \\\" stroke-linecap=\\\"butt\\\" /><path d=\\\"M 11,14 L 11,9 L 15,9 L 15,11 L 20,11 L 20,9 L 25,9 L 25,11 L 30,11 L 30,9 L 34,9 L 34,14 L 11,14 z \\\" stroke-linecap=\\\"butt\\\" /><path style=\\\"stroke:var(--cc-pb-detail)\\\" d=\\\"M 12,35.5 L 33,35.5 L 33,35.5\\\" fill=\\\"none\\\" stroke-width=\\\"1\\\" stroke-linejoin=\\\"miter\\\" /><path style=\\\"stroke:var(--cc-pb-detail)\\\" d=\\\"M 13,31.5 L 32,31.5\\\" fill=\\\"none\\\" stroke-width=\\\"1\\\" stroke-linejoin=\\\"miter\\\" /><path style=\\\"stroke:var(--cc-pb-detail)\\\" d=\\\"M 14,29.5 L 31,29.5\\\" fill=\\\"none\\\" stroke-width=\\\"1\\\" stroke-linejoin=\\\"miter\\\" /><path style=\\\"stroke:var(--cc-pb-detail)\\\" d=\\\"M 14,16.5 L 31,16.5\\\" fill=\\\"none\\\" stroke-width=\\\"1\\\" stroke-linejoin=\\\"miter\\\" /><path style=\\\"stroke:var(--cc-pb-detail)\\\" d=\\\"M 11,14 L 34,14\\\" fill=\\\"none\\\" stroke-width=\\\"1\\\" stroke-linejoin=\\\"miter\\\" /></g>\",\n bb: \"<g style=\\\"stroke:var(--cc-pb-line)\\\" fill=\\\"none\\\" fill-rule=\\\"evenodd\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" transform=\\\"translate(0,0.6)\\\"><g style=\\\"fill:var(--cc-pb-body);stroke:var(--cc-pb-line)\\\" stroke-linecap=\\\"butt\\\"><path d=\\\"M 9,36 C 12.39,35.03 19.11,36.43 22.5,34 C 25.89,36.43 32.61,35.03 36,36 C 36,36 37.65,36.54 39,38 C 38.32,38.97 37.35,38.99 36,38.5 C 32.61,37.53 25.89,38.96 22.5,37.5 C 19.11,38.96 12.39,37.53 9,38.5 C 7.65,38.99 6.68,38.97 6,38 C 7.35,36.54 9,36 9,36 z\\\"/><path d=\\\"M 15,32 C 17.5,34.5 27.5,34.5 30,32 C 30.5,30.5 30,30 30,30 C 30,27.5 27.5,26 27.5,26 C 33,24.5 33.5,14.5 22.5,10.5 C 11.5,14.5 12,24.5 17.5,26 C 17.5,26 15,27.5 15,30 C 15,30 14.5,30.5 15,32 z\\\"/><path d=\\\"M 25 8 A 2.5 2.5 0 1 1 20,8 A 2.5 2.5 0 1 1 25 8 z\\\"/></g><path style=\\\"stroke:var(--cc-pb-detail)\\\" d=\\\"M 17.5,26 L 27.5,26 M 15,30 L 30,30 M 22.5,15.5 L 22.5,20.5 M 20,18 L 25,18\\\" fill=\\\"none\\\" stroke-linejoin=\\\"miter\\\"/></g>\",\n bn: \"<g style=\\\"stroke:var(--cc-pb-line)\\\" fill=\\\"none\\\" fill-rule=\\\"evenodd\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" transform=\\\"translate(0,0.3)\\\"><path style=\\\"fill:var(--cc-pb-body);stroke:var(--cc-pb-line)\\\" d=\\\"M 22,10 C 32.5,11 38.5,18 38,39 L 15,39 C 15,30 25,32.5 23,18\\\" /><path style=\\\"fill:var(--cc-pb-body);stroke:var(--cc-pb-line)\\\" d=\\\"M 24,18 C 24.38,20.91 18.45,25.37 16,27 C 13,29 13.18,31.34 11,31 C 9.958,30.06 12.41,27.96 11,28 C 10,28 11.19,29.23 10,30 C 9,30 5.997,31 6,26 C 6,24 12,14 12,14 C 12,14 13.89,12.1 14,10.5 C 13.27,9.506 13.5,8.5 13.5,7.5 C 14.5,6.5 16.5,10 16.5,10 L 18.5,10 C 18.5,10 19.28,8.008 21,7 C 22,7 22,10 22,10\\\" /><path style=\\\"fill:var(--cc-pb-detail);stroke:var(--cc-pb-detail)\\\" d=\\\"M 9.5 25.5 A 0.5 0.5 0 1 1 8.5,25.5 A 0.5 0.5 0 1 1 9.5 25.5 z\\\" /><path style=\\\"fill:var(--cc-pb-detail);stroke:var(--cc-pb-detail)\\\" d=\\\"M 15 15.5 A 0.5 1.5 0 1 1 14,15.5 A 0.5 1.5 0 1 1 15 15.5 z\\\" transform=\\\"matrix(0.866,0.5,-0.5,0.866,9.693,-5.173)\\\" /><path style=\\\"fill:var(--cc-pb-detail)\\\" d=\\\"M 24.55,10.4 L 24.1,11.85 L 24.6,12 C 27.75,13 30.25,14.49 32.5,18.75 C 34.75,23.01 35.75,29.06 35.25,39 L 35.2,39.5 L 37.45,39.5 L 37.5,39 C 38,28.94 36.62,22.15 34.25,17.66 C 31.88,13.17 28.46,11.02 25.06,10.5 L 24.55,10.4 z \\\" stroke=\\\"none\\\" /></g>\",\n bp: \"<path style=\\\"fill:var(--cc-pb-body);stroke:var(--cc-pb-line)\\\" d=\\\"m 22.5,9 c -2.21,0 -4,1.79 -4,4 0,0.89 0.29,1.71 0.78,2.38 C 17.33,16.5 16,18.59 16,21 c 0,2.03 0.94,3.84 2.41,5.03 C 15.41,27.09 11,31.58 11,39.5 H 34 C 34,31.58 29.59,27.09 26.59,26.03 28.06,24.84 29,23.03 29,21 29,18.59 27.67,16.5 25.72,15.38 26.21,14.71 26.5,13.89 26.5,13 c 0,-2.21 -1.79,-4 -4,-4 z\\\" fill-rule=\\\"nonzero\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"miter\\\"/>\",\n};\n","import type { PieceSymbol, Color } from '../types/chess.ts';\nimport { PIECE_ART } from './pieceArt.ts';\nimport styles from '../styles/Square.module.css';\n\ninterface PieceIconProps {\n type: PieceSymbol;\n color: Color;\n className?: string;\n}\n\nconst NAMES: Record<PieceSymbol, string> = {\n k: 'king', q: 'queen', r: 'rook', b: 'bishop', n: 'knight', p: 'pawn',\n};\n\nexport function pieceName(type: PieceSymbol, color: Color): string {\n return `${color === 'w' ? 'white' : 'black'} ${NAMES[type]}`;\n}\n\nexport function PieceIcon({ type, color, className }: PieceIconProps) {\n const art = PIECE_ART[`${color}${type}`];\n if (!art) return null;\n const colorClass = color === 'w' ? styles.pieceWhite : styles.pieceBlack;\n return (\n <svg\n viewBox=\"0 0 45 45\"\n role=\"img\"\n aria-label={pieceName(type, color)}\n className={`${styles.pieceArt} ${className ?? ''} ${colorClass}`}\n dangerouslySetInnerHTML={{ __html: art }}\n />\n );\n}\n","import type { Square as ChessSquare, Piece } from 'chess.js';\nimport { PieceIcon } from './PieceIcon.tsx';\nimport styles from '../styles/Square.module.css';\nimport boardStyles from '../styles/ChessBoard.module.css';\n\ninterface SquareProps {\n square: ChessSquare;\n piece: Piece | null;\n isLight: boolean;\n isSelected: boolean;\n isLegalMove: boolean;\n isCheck: boolean;\n isLastMoveFrom: boolean;\n isLastMoveTo: boolean;\n isChaosFlash: boolean;\n rankLabel?: string | number;\n fileLabel?: string;\n onClick: (square: ChessSquare) => void;\n}\n\nexport function Square({\n square,\n piece,\n isLight,\n isSelected,\n isLegalMove,\n isCheck,\n isLastMoveFrom,\n isLastMoveTo,\n isChaosFlash,\n rankLabel,\n fileLabel,\n onClick,\n}: SquareProps) {\n const classNames = [\n styles.square,\n isLight ? styles.light : styles.dark,\n isSelected && styles.selected,\n isLegalMove && (piece ? styles.legalCapture : styles.legalMove),\n isCheck && styles.check,\n !isSelected && !isCheck && isLastMoveFrom && styles.lastMoveFrom,\n !isSelected && !isCheck && isLastMoveTo && styles.lastMoveTo,\n isChaosFlash && styles.chaosFlash,\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <div className={classNames} onClick={() => onClick(square)}>\n {piece && (\n <PieceIcon\n type={piece.type}\n color={piece.color}\n className={styles.piece}\n />\n )}\n {rankLabel != null && (\n <span className={boardStyles.rankLabel}>{rankLabel}</span>\n )}\n {fileLabel != null && (\n <span className={boardStyles.fileLabel}>{fileLabel}</span>\n )}\n </div>\n );\n}\n","import React from 'react';\nimport type { Square as ChessSquare, Piece } from 'chess.js';\nimport { Square } from './Square.tsx';\nimport styles from '../styles/ChessBoard.module.css';\n\ninterface LastMove {\n from: ChessSquare;\n to: ChessSquare;\n}\n\ninterface ChessBoardProps {\n board: (Piece | null)[][];\n selectedSquare: ChessSquare | null;\n legalMoves: ChessSquare[];\n inCheck: 'w' | 'b' | null;\n lastMove: LastMove | null;\n chaosSquare: ChessSquare | null;\n flipped: boolean;\n locked: boolean;\n onSquareClick: (square: ChessSquare) => void;\n}\n\nconst FILES = 'abcdefgh';\n\nfunction getSquareName(rank: number, file: number): ChessSquare {\n // board[0] = rank 8, board[7] = rank 1 (white at bottom)\n return `${FILES[file]}${8 - rank}` as ChessSquare;\n}\n\nfunction isLightSquare(rank: number, file: number): boolean {\n return (rank + file) % 2 === 0;\n}\n\nexport const ChessBoard = React.memo(function ChessBoard({\n board,\n selectedSquare,\n legalMoves,\n inCheck,\n lastMove,\n chaosSquare,\n flipped,\n locked,\n onSquareClick,\n}: ChessBoardProps) {\n // Find king squares for check highlighting\n let checkSquare: ChessSquare | null = null;\n if (inCheck) {\n for (let r = 0; r < 8; r++) {\n for (let f = 0; f < 8; f++) {\n const piece = board[r][f];\n if (piece?.type === 'k' && piece.color === inCheck) {\n checkSquare = getSquareName(r, f);\n }\n }\n }\n }\n\n // Build iteration order based on flipped state\n const rankOrder = flipped ? [7, 6, 5, 4, 3, 2, 1, 0] : [0, 1, 2, 3, 4, 5, 6, 7];\n const fileOrder = flipped ? [7, 6, 5, 4, 3, 2, 1, 0] : [0, 1, 2, 3, 4, 5, 6, 7];\n\n return (\n <div className={`${styles.board}${locked ? ` ${styles.boardLocked}` : ''}`}>\n {rankOrder.map((rankIdx) =>\n fileOrder.map((fileIdx) => {\n const square = getSquareName(rankIdx, fileIdx);\n const piece = board[rankIdx][fileIdx];\n\n // Display row/col indices for labels\n const displayRow = rankOrder.indexOf(rankIdx);\n const displayCol = fileOrder.indexOf(fileIdx);\n\n return (\n <Square\n key={square}\n square={square}\n piece={piece}\n isLight={isLightSquare(rankIdx, fileIdx)}\n isSelected={square === selectedSquare}\n isLegalMove={legalMoves.includes(square)}\n isCheck={square === checkSquare}\n isLastMoveFrom={lastMove?.from === square}\n isLastMoveTo={lastMove?.to === square}\n isChaosFlash={chaosSquare === square}\n rankLabel={displayCol === 0 ? 8 - rankIdx : undefined}\n fileLabel={displayRow === 7 ? FILES[fileIdx] : undefined}\n onClick={onSquareClick}\n />\n );\n })\n )}\n </div>\n );\n});\n","import { PieceIcon } from './PieceIcon.tsx';\nimport styles from '../styles/components.module.css';\n\ninterface PromotionDialogProps {\n color: 'w' | 'b';\n onSelect: (piece: 'q' | 'r' | 'b' | 'n') => void;\n}\n\nconst PROMOTION_PIECES: { type: 'q' | 'r' | 'b' | 'n'; label: string }[] = [\n { type: 'q', label: 'Queen' },\n { type: 'r', label: 'Rook' },\n { type: 'b', label: 'Bishop' },\n { type: 'n', label: 'Knight' },\n];\n\nexport function PromotionDialog({ color, onSelect }: PromotionDialogProps) {\n return (\n <div className={styles.promotionOverlay}>\n <div className={styles.promotionDialog}>\n <h3 className={styles.promotionTitle}>Promote pawn</h3>\n <div className={styles.promotionOptions}>\n {PROMOTION_PIECES.map(({ type, label }) => (\n <button type=\"button\"\n key={type}\n className={styles.promotionBtn}\n onClick={() => onSelect(type)}\n title={label}\n >\n <PieceIcon type={type} color={color} />\n </button>\n ))}\n </div>\n </div>\n </div>\n );\n}\n","import type { GameStatus } from '../types/chess.ts';\nimport styles from '../styles/components.module.css';\n\ninterface GameOverBannerProps {\n status: GameStatus;\n humanColor: 'w' | 'b';\n onRestart: () => void;\n}\n\nfunction getResultText(status: GameStatus, humanColor: 'w' | 'b'): { title: string; detail: string } {\n if (status.result === 'checkmate') {\n if (status.winner === humanColor) {\n return { title: 'You Win!', detail: 'Checkmate' };\n }\n return { title: 'You Lose', detail: 'Checkmate' };\n }\n if (status.result === 'stalemate') {\n return { title: 'Draw', detail: 'Stalemate' };\n }\n if (status.result === 'insufficient') {\n return { title: 'Draw', detail: 'Insufficient material' };\n }\n if (status.result === 'threefold') {\n return { title: 'Draw', detail: 'Threefold repetition' };\n }\n if (status.result === 'fifty-move') {\n return { title: 'Draw', detail: 'Fifty-move rule' };\n }\n if (status.result === 'king-captured') {\n return { title: status.winner === humanColor ? 'You Win!' : 'You Lose', detail: 'King captured' };\n }\n return { title: 'Draw', detail: 'Game over' };\n}\n\nexport function GameOverBanner({ status, humanColor, onRestart }: GameOverBannerProps) {\n const { title, detail } = getResultText(status, humanColor);\n\n return (\n <div className={styles.gameOverOverlay}>\n <div className={styles.gameOverBanner}>\n <h2 className={styles.gameOverResult}>{title}</h2>\n <p className={styles.gameOverDetail}>{detail}</p>\n <button type=\"button\" className={styles.restartBtn} onClick={onRestart}>\n Play Again\n </button>\n </div>\n </div>\n );\n}\n","import styles from '../styles/components.module.css';\n\ninterface ChaosTimerProps {\n countdown: number;\n maxCountdown: number;\n}\n\nexport function ChaosTimer({ countdown, maxCountdown }: ChaosTimerProps) {\n const progress = maxCountdown > 0 ? ((maxCountdown - countdown) / maxCountdown) * 100 : 0;\n const glow = 1 - (countdown / maxCountdown || 0); // 0 at full, 1 at empty\n\n return (\n <div className={styles.chaosBar}>\n <span className={styles.chaosBarLabel}>STUPIDITY</span>\n <div className={styles.chaosBarTrack}>\n <div\n className={styles.chaosBarFill}\n style={{\n width: `${progress}%`,\n '--glow': glow,\n } as React.CSSProperties}\n />\n </div>\n </div>\n );\n}\n","import { useState, useEffect, useRef } from 'react';\nimport { pieceName } from './PieceIcon.tsx';\nimport type { ChaosAction } from '../types/chess.ts';\nimport styles from '../styles/components.module.css';\n\ninterface ChaosToastProps {\n action: ChaosAction | null;\n}\n\nexport function ChaosToast({ action }: ChaosToastProps) {\n const [visible, setVisible] = useState(false);\n const [fading, setFading] = useState(false);\n const [displayAction, setDisplayAction] = useState<ChaosAction | null>(null);\n const timeoutRef = useRef<ReturnType<typeof setTimeout>>(undefined);\n\n useEffect(() => {\n if (!action) return;\n\n // Clear any existing timeout\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\n\n setDisplayAction(action);\n setFading(false);\n setVisible(true);\n\n // Start fade-out after 1.6s\n timeoutRef.current = setTimeout(() => {\n setFading(true);\n // Remove after fade animation completes\n timeoutRef.current = setTimeout(() => {\n setVisible(false);\n setFading(false);\n }, 400);\n }, 1600);\n\n return () => {\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\n };\n }, [action]);\n\n if (!visible || !displayAction) return null;\n\n const message =\n displayAction.type === 'add' && displayAction.piece && displayAction.color\n ? `A ${pieceName(displayAction.piece, displayAction.color)} appeared on ${displayAction.square}!`\n : `The piece on ${displayAction.square} vanished!`;\n\n return (\n <div className={`${styles.chaosToast} ${fading ? styles.chaosToastFading : ''}`}>\n {message}\n </div>\n );\n}\n","import styles from '../styles/components.module.css';\n\ninterface DifficultySelectorProps {\n depth: number;\n onChange: (depth: number) => void;\n}\n\nexport function DifficultySelector({ depth, onChange }: DifficultySelectorProps) {\n return (\n <div className={styles.difficultySelector}>\n <span className={styles.difficultyLabel}>\n AI Depth: <span className={styles.difficultyValue}>{depth}</span>\n </span>\n <input\n className={styles.difficultySlider}\n type=\"range\"\n min={1}\n max={20}\n value={depth}\n onChange={(e) => onChange(parseInt(e.target.value))}\n />\n </div>\n );\n}\n","import styles from '../styles/components.module.css';\n\ninterface StupidLevelProps {\n level: number; // 0 = off, 1-5\n onChange: (level: number) => void;\n}\n\nconst LABELS = ['OFF', 'CHILL', 'MID', 'STUPID', 'CHAOS', 'LOL'];\n\nexport function StupidLevel({ level, onChange }: StupidLevelProps) {\n return (\n <div className={styles.stupidLevel}>\n <div className={styles.stupidLevelHeader}>\n <span className={styles.stupidLevelLabel}>Stupid level</span>\n <span className={styles.stupidLevelValue}>{LABELS[level]}</span>\n </div>\n <input\n type=\"range\"\n min={0}\n max={5}\n step={1}\n value={level}\n onChange={(e) => onChange(Number(e.target.value))}\n className={styles.stupidLevelSlider}\n />\n </div>\n );\n}\n","import { PieceIcon } from './PieceIcon.tsx';\nimport { DifficultySelector } from './DifficultySelector.tsx';\nimport { StupidLevel } from './StupidLevel.tsx';\nimport styles from '../styles/components.module.css';\n\ninterface SidePickerProps {\n depth: number;\n onDepthChange: (depth: number) => void;\n stupidLevel: number;\n onStupidLevelChange: (level: number) => void;\n onSelectSide: (color: 'w' | 'b') => void;\n}\n\nexport function SidePicker({ depth, onDepthChange, stupidLevel, onStupidLevelChange, onSelectSide }: SidePickerProps) {\n return (\n <div className={styles.sidePickerOverlay}>\n <div className={styles.sidePickerCard}>\n <h2 className={styles.sidePickerTitle}>Choose Your Side</h2>\n <div className={styles.sidePickerOptions}>\n <button type=\"button\"\n className={styles.sidePickerBtn}\n onClick={() => onSelectSide('w')}\n >\n <PieceIcon type=\"k\" color=\"w\" className={styles.sidePickerIcon} />\n <span className={styles.sidePickerLabel}>White</span>\n </button>\n <button type=\"button\"\n className={styles.sidePickerBtn}\n onClick={() => onSelectSide('b')}\n >\n <PieceIcon type=\"k\" color=\"b\" className={styles.sidePickerIcon} />\n <span className={styles.sidePickerLabel}>Black</span>\n </button>\n </div>\n <div className={styles.sidePickerSettings}>\n <DifficultySelector depth={depth} onChange={onDepthChange} />\n <StupidLevel level={stupidLevel} onChange={onStupidLevelChange} />\n </div>\n </div>\n </div>\n );\n}\n","import styles from '../styles/components.module.css';\n\ninterface MuteButtonProps {\n muted: boolean;\n onToggle: () => void;\n}\n\nexport function MuteButton({ muted, onToggle }: MuteButtonProps) {\n const label = muted ? 'Unmute' : 'Mute';\n return (\n <button type=\"button\"\n className={`${styles.muteBtn} ${muted ? styles.muteBtnMuted : ''}`}\n onClick={onToggle}\n title={label}\n aria-label={label}\n aria-pressed={muted}\n >\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" fill=\"none\" stroke=\"currentColor\"\n strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M11 5 6 9H3v6h3l5 4V5z\" />\n {muted ? (\n <path d=\"m22 9-6 6M16 9l6 6\" />\n ) : (\n <path d=\"M15.5 8.5a5 5 0 0 1 0 7M18.5 5.5a9 9 0 0 1 0 13\" />\n )}\n </svg>\n </button>\n );\n}\n","// One AudioContext for the page; browsers limit how many can exist.\nlet sharedCtx: AudioContext | null = null;\n\n/**\n * Plays the game's sounds. Each game owns one, so muting one game\n * doesn't mute another on the same page.\n */\nexport class SoundManager {\n private muted: boolean;\n\n constructor(muted = false) {\n this.muted = muted;\n }\n\n private getCtx(): AudioContext | null {\n if (this.muted) return null;\n if (!sharedCtx) {\n try {\n sharedCtx = new AudioContext();\n } catch {\n return null;\n }\n }\n if (sharedCtx.state === 'suspended') {\n sharedCtx.resume();\n }\n return sharedCtx;\n }\n\n setMuted(muted: boolean) {\n this.muted = muted;\n }\n\n get isMuted(): boolean {\n return this.muted;\n }\n\n playMove() {\n const ctx = this.getCtx();\n if (!ctx) return;\n const osc = ctx.createOscillator();\n const gain = ctx.createGain();\n osc.type = 'sine';\n osc.frequency.value = 200;\n gain.gain.setValueAtTime(0.15, ctx.currentTime);\n gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.08);\n osc.connect(gain).connect(ctx.destination);\n osc.start();\n osc.stop(ctx.currentTime + 0.08);\n }\n\n playCapture() {\n const ctx = this.getCtx();\n if (!ctx) return;\n // Metallic clack: noise burst filtered to high-mid band\n const bufferSize = ctx.sampleRate * 0.1;\n const buffer = ctx.createBuffer(1, bufferSize, ctx.sampleRate);\n const data = buffer.getChannelData(0);\n for (let i = 0; i < bufferSize; i++) {\n data[i] = (Math.random() * 2 - 1) * Math.exp(-i / (ctx.sampleRate * 0.015));\n }\n const noise = ctx.createBufferSource();\n noise.buffer = buffer;\n const bandpass = ctx.createBiquadFilter();\n bandpass.type = 'bandpass';\n bandpass.frequency.value = 3000;\n bandpass.Q.value = 2;\n const gain = ctx.createGain();\n gain.gain.setValueAtTime(0.35, ctx.currentTime);\n gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.1);\n noise.connect(bandpass).connect(gain).connect(ctx.destination);\n noise.start();\n noise.stop(ctx.currentTime + 0.1);\n }\n\n playCheck() {\n const ctx = this.getCtx();\n if (!ctx) return;\n const osc = ctx.createOscillator();\n const gain = ctx.createGain();\n osc.type = 'triangle';\n osc.frequency.value = 800;\n gain.gain.setValueAtTime(0.18, ctx.currentTime);\n gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.12);\n osc.connect(gain).connect(ctx.destination);\n osc.start();\n osc.stop(ctx.currentTime + 0.12);\n }\n\n playChaos() {\n const ctx = this.getCtx();\n if (!ctx) return;\n // Soft shimmer: quiet sine blip with a gentle pitch drop\n const osc = ctx.createOscillator();\n const gain = ctx.createGain();\n osc.type = 'sine';\n osc.frequency.setValueAtTime(520, ctx.currentTime);\n osc.frequency.exponentialRampToValueAtTime(320, ctx.currentTime + 0.18);\n gain.gain.setValueAtTime(0.07, ctx.currentTime);\n gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.18);\n osc.connect(gain).connect(ctx.destination);\n osc.start();\n osc.stop(ctx.currentTime + 0.18);\n }\n\n playGameOver() {\n const ctx = this.getCtx();\n if (!ctx) return;\n // C major chord: C4 + E4 + G4\n const freqs = [261.63, 329.63, 392.0];\n for (const freq of freqs) {\n const osc = ctx.createOscillator();\n const gain = ctx.createGain();\n osc.type = 'sine';\n osc.frequency.value = freq;\n gain.gain.setValueAtTime(0.1, ctx.currentTime);\n gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.4);\n osc.connect(gain).connect(ctx.destination);\n osc.start();\n osc.stop(ctx.currentTime + 0.4);\n }\n }\n}\n\n","import type { ChaosChessState } from '../types/props.ts';\nimport { isValidChaosPosition } from '../engine/chaosEngine.ts';\nimport { sanitizeFen } from '../engine/fenManipulator.ts';\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value);\n}\n\n/** Round and clamp to the AI depth slider's range (1-20). */\nexport function clampDepth(depth: number): number {\n return isFiniteNumber(depth) ? Math.min(20, Math.max(1, Math.round(depth))) : 10;\n}\n\n/** Round and clamp to the STUPID slider's range (0-5). */\nexport function clampStupidLevel(level: number): number {\n return isFiniteNumber(level) ? Math.min(5, Math.max(0, Math.round(level))) : 3;\n}\n\n/**\n * Check a saved game from `initialState` before using it. Returns a cleaned\n * copy, or null if anything is wrong with it (the game then starts from the\n * defaults). The saved data may come from storage or an older version, so\n * nothing about its shape is trusted.\n */\nexport function normalizeState(raw: unknown): ChaosChessState | null {\n if (!raw || typeof raw !== 'object') return null;\n const state = raw as Record<string, unknown>;\n if (state.version !== 1) return null;\n if (state.phase !== 'setup' && state.phase !== 'playing') return null;\n if (state.humanColor !== 'w' && state.humanColor !== 'b') return null;\n if (!isFiniteNumber(state.depth) || !isFiniteNumber(state.stupidLevel)) return null;\n if (typeof state.fen !== 'string') return null;\n\n let fen: string;\n try {\n fen = sanitizeFen(state.fen);\n } catch {\n return null;\n }\n // The same rules chaos follows, so a restored board can't put the AI's\n // king in check on the human's turn or give Stockfish a board it rejects\n if (!isValidChaosPosition(fen)) return null;\n\n return {\n version: 1,\n phase: state.phase,\n fen,\n humanColor: state.humanColor,\n depth: clampDepth(state.depth),\n stupidLevel: clampStupidLevel(state.stupidLevel),\n muted: state.muted === true,\n };\n}\n","import { useState, useCallback, useEffect, useLayoutEffect, useRef } from 'react';\nimport { Chess } from 'chess.js';\nimport type { Square as ChessSquare } from 'chess.js';\nimport type { ChaosChessProps, ChaosChessState } from './types/props.ts';\nimport { useChessGame, getGameStatus } from './hooks/useChessGame.ts';\nimport { useStockfish } from './hooks/useStockfish.ts';\nimport { useChaosEngine } from './hooks/useChaosEngine.ts';\nimport { isValidChaosPosition } from './engine/chaosEngine.ts';\nimport { sanitizeFen } from './engine/fenManipulator.ts';\nimport { StockfishCancelledError, StockfishRestartedError } from './engine/stockfishWorker.ts';\nimport { ChessBoard } from './components/ChessBoard.tsx';\nimport { PromotionDialog } from './components/PromotionDialog.tsx';\nimport { GameOverBanner } from './components/GameOverBanner.tsx';\nimport { ChaosTimer } from './components/ChaosTimer.tsx';\nimport { ChaosToast } from './components/ChaosToast.tsx';\nimport { DifficultySelector } from './components/DifficultySelector.tsx';\nimport { SidePicker } from './components/SidePicker.tsx';\nimport { StupidLevel } from './components/StupidLevel.tsx';\nimport { MuteButton } from './components/MuteButton.tsx';\nimport { SoundManager } from './utils/sounds.ts';\nimport { normalizeState } from './utils/state.ts';\nimport styles from './styles/ChessGame.module.css';\nimport './styles/theme.css';\nimport './styles/animations.css';\n\ntype GamePhase = 'setup' | 'playing';\n\n// Engine failures (a hung or crashed worker) allowed on one position before\n// the AI plays a random legal move instead. The retry uses a lower depth.\nconst MAX_ENGINE_FAILURES = 2;\n\nexport function ChessGame(props: ChaosChessProps) {\n const {\n defaultDepth = 10,\n defaultStupidLevel = 3,\n defaultHumanColor,\n defaultMuted = false,\n depth: controlledDepth,\n onDepthChange,\n stupidLevel: controlledStupidLevel,\n onStupidLevelChange,\n stockfishWorkerPath,\n skipSetup = false,\n showControls = true,\n showMuteButton = true,\n initialState,\n onStateChange,\n onGameOver,\n onMove,\n onChaosAction: onChaosActionCb,\n onRestart: onRestartCb,\n className,\n } = props;\n\n // A saved game is only used if it passes validation; otherwise start fresh\n const [restored] = useState(() => {\n if (!initialState) return null;\n const state = normalizeState(initialState);\n if (!state) console.warn('[ChaosChess] Ignoring invalid initialState');\n return state;\n });\n\n // --- Controlled / uncontrolled state ---\n const [internalDepth, setInternalDepth] = useState(restored?.depth ?? defaultDepth);\n const depth = controlledDepth ?? internalDepth;\n const setDepth = onDepthChange ?? setInternalDepth;\n\n const [internalStupidLevel, setInternalStupidLevel] = useState(restored?.stupidLevel ?? defaultStupidLevel);\n const stupidLevel = controlledStupidLevel ?? internalStupidLevel;\n const setStupidLevel = onStupidLevelChange ?? setInternalStupidLevel;\n\n const [internalHumanColor, setInternalHumanColor] = useState<'w' | 'b'>(\n restored?.humanColor ?? defaultHumanColor ?? 'w'\n );\n const humanColor = internalHumanColor;\n\n const [soundMuted, setSoundMuted] = useState(restored?.muted ?? defaultMuted);\n // Per game, so muting one game doesn't mute another on the page\n const [sounds] = useState(() => new SoundManager(restored?.muted ?? defaultMuted));\n\n // If skipSetup or defaultHumanColor is given, go straight to playing\n const [gamePhase, setGamePhase] = useState<GamePhase>(\n restored?.phase ?? ((skipSetup || defaultHumanColor) ? 'playing' : 'setup')\n );\n\n // Bumped on restart so the chaos countdown starts over\n const [gameId, setGameId] = useState(0);\n\n const {\n fen,\n turn,\n selectedSquare,\n legalMoves,\n gameStatus,\n promotionPending,\n lastMove,\n lastMoveDetail,\n moveHistory,\n board,\n handleSquareClick,\n handlePromotion,\n applyFen,\n applyMove,\n handleRestart: resetGame,\n } = useChessGame(restored?.fen);\n\n const {\n status: engineStatus,\n isReady: stockfishReady,\n isThinking,\n getBestMove,\n cancel: cancelSearch,\n } = useStockfish(stockfishWorkerPath);\n\n // The AI owns its side unless Stockfish failed to load. While it is still\n // loading, the AI's pieces stay locked.\n const aiEnabled = engineStatus !== 'failed';\n const isHumanTurn = turn === humanColor;\n\n // Refs that always point to latest values (for use in async callbacks).\n // Synced in a layout effect, before any effect or timer can read them.\n const currentFenRef = useRef(fen);\n const humanColorRef = useRef(humanColor);\n const gamePhaseRef = useRef(gamePhase);\n useLayoutEffect(() => {\n currentFenRef.current = fen;\n humanColorRef.current = humanColor;\n gamePhaseRef.current = gamePhase;\n }, [fen, humanColor, gamePhase]);\n // Bumped on every restart. A search result from an earlier game is ignored,\n // even when both games are at the same position (the start).\n const gameCounterRef = useRef(0);\n\n // Chaos engine: pause during setup, when off, AI's turn, promotion, or game over\n const chaosEnabled = stupidLevel > 0;\n const chaosPaused = gamePhase !== 'playing' || !chaosEnabled || !isHumanTurn || isThinking || !!promotionPending || gameStatus.isGameOver;\n const { countdown, maxCountdown, lastAction, chaosSquare } = useChaosEngine({\n fen,\n isPaused: chaosPaused,\n stupidLevel: Math.max(1, stupidLevel),\n resetKey: gameId,\n onChaosAction: useCallback((newFen: string) => {\n // Guard: if the game has moved past the human's turn, skip this chaos event.\n // This catches the race where the interval fires before isPausedRef updates.\n const chess = new Chess(currentFenRef.current);\n if (chess.turn() !== humanColorRef.current) return false;\n if (getGameStatus(chess).isGameOver) return false;\n // Never apply a board Stockfish or chess.js can't play from\n // (for example the AI's king left in check, so the human could take it)\n const safeFen = sanitizeFen(newFen);\n if (!isValidChaosPosition(safeFen)) return false;\n applyFen(safeFen);\n return true;\n }, [applyFen]),\n });\n\n // Fire onChaosAction callback\n const prevLastActionRef = useRef(lastAction);\n useEffect(() => {\n if (lastAction && lastAction !== prevLastActionRef.current) {\n onChaosActionCb?.(lastAction, fen);\n }\n prevLastActionRef.current = lastAction;\n }, [lastAction, fen, onChaosActionCb]);\n\n // Report a serializable snapshot so a host can restore the game after unmounting it\n const onStateChangeRef = useRef(onStateChange);\n useEffect(() => {\n onStateChangeRef.current = onStateChange;\n }, [onStateChange]);\n useEffect(() => {\n const state: ChaosChessState = {\n version: 1,\n phase: gamePhase,\n fen,\n humanColor,\n depth,\n stupidLevel,\n muted: soundMuted,\n };\n onStateChangeRef.current?.(state);\n }, [gamePhase, fen, humanColor, depth, stupidLevel, soundMuted]);\n\n // Track last FEN where no move could be played, to avoid infinite retries\n const noMoveFenRef = useRef<string | null>(null);\n // Engine failures on the current position\n const aiFailuresRef = useRef<{ fen: string; count: number }>({ fen: '', count: 0 });\n\n /** Play a UCI move for the AI on `forFen`. False if it isn't legal there. */\n const playAiMove = useCallback((forFen: string, uciMove: string): boolean => {\n return applyMove(\n {\n from: uciMove.slice(0, 2) as ChessSquare,\n to: uciMove.slice(2, 4) as ChessSquare,\n promotion: uciMove.length > 4 ? uciMove[4] : undefined,\n },\n forFen\n );\n }, [applyMove]);\n\n /**\n * Play a random legal move for the AI when Stockfish can't give one.\n * Returns false if there is nothing to play.\n */\n const playFallbackMove = useCallback((forFen: string, reason: string): boolean => {\n // The board changed while we waited; the trigger effect will run again\n if (currentFenRef.current !== forFen || gamePhaseRef.current !== 'playing') return true;\n const chess = new Chess(forFen);\n if (getGameStatus(chess).isGameOver) return false;\n const moves = chess.moves({ verbose: true });\n if (moves.length === 0) return false;\n const move = moves[Math.floor(Math.random() * moves.length)];\n console.warn(`[ChaosChess] ${reason}; playing random move ${move.lan}`);\n return playAiMove(forFen, move.lan);\n }, [playAiMove]);\n\n /** Ask Stockfish for a move and play it, falling back to a random legal move. */\n const requestAiMove = useCallback((forFen: string) => {\n const game = gameCounterRef.current;\n // The game was restarted (or is back at the side picker) since we asked\n const isStale = () => gameCounterRef.current !== game || gamePhaseRef.current !== 'playing';\n const giveUp = (reason: string) => {\n if (isStale()) return;\n if (!playFallbackMove(forFen, reason)) noMoveFenRef.current = forFen;\n };\n\n if (!isValidChaosPosition(sanitizeFen(forFen))) {\n // Stockfish can't play from this position; don't send it\n giveUp('Position not supported by Stockfish');\n return;\n }\n\n const failures = aiFailuresRef.current.fen === forFen ? aiFailuresRef.current.count : 0;\n if (failures >= MAX_ENGINE_FAILURES) {\n giveUp('Stockfish keeps failing on this position');\n return;\n }\n // After a failure, search less deeply\n const searchDepth = failures > 0 ? Math.max(1, Math.floor(depth / 2)) : depth;\n\n getBestMove(forFen, searchDepth).then((uciMove) => {\n if (isStale()) return;\n // The board changed during the search; the trigger effect will ask again\n if (currentFenRef.current !== forFen) return;\n if (!uciMove) {\n // Stockfish said \"(none)\". If chess.js still has legal moves, play one\n // rather than freezing.\n giveUp('Stockfish returned no move');\n return;\n }\n noMoveFenRef.current = null;\n // Never re-search on a move chess.js rejects; that used to loop\n if (!playAiMove(forFen, uciMove)) giveUp(`Stockfish move ${uciMove} is not legal here`);\n }).catch((err) => {\n if (isStale()) return;\n // A newer search replaced this one, or another search's timeout restarted\n // the worker. Neither is this search's failure; the trigger effect asks again.\n if (err instanceof StockfishCancelledError || err instanceof StockfishRestartedError) return;\n // A hung or crashed worker; the engine has restarted\n aiFailuresRef.current = { fen: forFen, count: failures + 1 };\n if (failures + 1 >= MAX_ENGINE_FAILURES) {\n giveUp(`Stockfish failed (${err?.message ?? err})`);\n }\n // Otherwise isThinking going false re-runs the trigger effect, which retries\n });\n }, [getBestMove, depth, playAiMove, playFallbackMove]);\n\n // --- Side selection ---\n const handleSideSelect = useCallback((color: 'w' | 'b') => {\n setInternalHumanColor(color);\n setGamePhase('playing');\n }, []);\n\n const handleRestart = useCallback(() => {\n gameCounterRef.current++;\n // Don't make the new game wait for the old game's search\n cancelSearch();\n resetGame();\n noMoveFenRef.current = null;\n aiFailuresRef.current = { fen: '', count: 0 };\n setGameId((id) => id + 1);\n setGamePhase((skipSetup || defaultHumanColor) ? 'playing' : 'setup');\n onRestartCb?.();\n }, [resetGame, cancelSearch, skipSetup, defaultHumanColor, onRestartCb]);\n\n // --- Sound mute sync ---\n useEffect(() => {\n sounds.setMuted(soundMuted);\n }, [sounds, soundMuted]);\n\n // --- Sound: move / capture / check + onMove callback ---\n const prevMoveCountRef = useRef(moveHistory.length);\n useEffect(() => {\n if (moveHistory.length > prevMoveCountRef.current) {\n // Sound\n if (lastMoveDetail) {\n if (lastMoveDetail.check) {\n sounds.playCheck();\n } else if (lastMoveDetail.captured) {\n sounds.playCapture();\n } else {\n sounds.playMove();\n }\n }\n // Fire onMove callback for the new entry\n const latest = moveHistory[moveHistory.length - 1];\n if (latest) {\n onMove?.(latest.fen, latest.san, latest.color);\n }\n }\n prevMoveCountRef.current = moveHistory.length;\n }, [moveHistory.length, lastMoveDetail, moveHistory, onMove, sounds]);\n\n // --- Sound: chaos ---\n useEffect(() => {\n if (chaosSquare) {\n sounds.playChaos();\n }\n }, [chaosSquare, sounds]);\n\n // --- Sound + callback: game over ---\n // Starts at the initial status, so restoring a finished game doesn't announce it again\n const prevGameOverRef = useRef(gameStatus.isGameOver);\n useEffect(() => {\n if (gameStatus.isGameOver && !prevGameOverRef.current) {\n sounds.playGameOver();\n onGameOver?.(gameStatus);\n }\n prevGameOverRef.current = gameStatus.isGameOver;\n }, [gameStatus, onGameOver, sounds]);\n\n // Single effect to trigger Stockfish when it's the AI's turn.\n // Covers: FEN changes, initial move as black, and Stockfish becoming ready.\n // The engine cancels a superseded search itself.\n useEffect(() => {\n if (gamePhase !== 'playing') return;\n if (isHumanTurn || gameStatus.isGameOver || !stockfishReady || isThinking) return;\n\n // Don't retry a FEN that already returned no move\n if (noMoveFenRef.current === fen) return;\n\n requestAiMove(fen);\n }, [gamePhase, fen, isHumanTurn, gameStatus.isGameOver, stockfishReady, isThinking, requestAiMove]);\n\n // Retry watchdog: if it's the AI's turn but Stockfish isn't thinking, retry after 3s.\n // This catches edge cases where the above effect's request was dropped.\n useEffect(() => {\n if (gamePhase !== 'playing' || isHumanTurn || isThinking || gameStatus.isGameOver || !stockfishReady) return;\n\n // Don't retry a FEN that already returned no move\n if (noMoveFenRef.current === fen) return;\n\n const timer = setTimeout(() => requestAiMove(fen), 3000);\n\n return () => clearTimeout(timer);\n }, [gamePhase, isHumanTurn, isThinking, gameStatus.isGameOver, stockfishReady, fen, requestAiMove]);\n\n // Lock board during AI turn\n const onSquareClick = useCallback(\n (square: ChessSquare) => {\n if (aiEnabled && turn !== humanColor) return;\n handleSquareClick(square);\n },\n [aiEnabled, turn, humanColor, handleSquareClick]\n );\n\n const statusText = gameStatus.isGameOver\n ? 'Game Over'\n : isThinking\n ? ''\n : !aiEnabled\n ? `${turn === 'w' ? 'White' : 'Black'} to move`\n : isHumanTurn\n ? 'Your turn'\n : engineStatus === 'loading'\n ? 'Loading engine...'\n : 'Opponent thinking...';\n\n const rootClassName = [styles.container, className].filter(Boolean).join(' ');\n\n // --- Setup phase ---\n if (gamePhase === 'setup') {\n return (\n <div className={rootClassName} data-chaos-chess=\"\">\n <SidePicker\n depth={depth}\n onDepthChange={setDepth}\n stupidLevel={stupidLevel}\n onStupidLevelChange={setStupidLevel}\n onSelectSide={handleSideSelect}\n />\n </div>\n );\n }\n\n // --- Playing phase ---\n return (\n <div className={rootClassName} data-chaos-chess=\"\">\n <div className={styles.topBar}>\n <div className={styles.topBarLeft}>\n <span className={styles.statusText}>{statusText}</span>\n {isThinking && (\n <span className={styles.thinking}>AI thinking...</span>\n )}\n {engineStatus === 'failed' && (\n <span className={styles.aiUnavailable} role=\"status\">AI unavailable</span>\n )}\n </div>\n <div className={styles.topBarRight}>\n <button type=\"button\" className={styles.newGameBtn} onClick={handleRestart} title=\"Start a new game\">\n New game\n </button>\n {showMuteButton && (\n <MuteButton muted={soundMuted} onToggle={() => setSoundMuted((m) => !m)} />\n )}\n </div>\n </div>\n\n {chaosEnabled && (\n <ChaosTimer countdown={countdown} maxCountdown={maxCountdown} />\n )}\n\n <ChessBoard\n board={board}\n selectedSquare={selectedSquare}\n legalMoves={legalMoves}\n inCheck={gameStatus.inCheck}\n lastMove={lastMove}\n chaosSquare={chaosSquare}\n flipped={humanColor === 'b'}\n locked={aiEnabled && !isHumanTurn}\n onSquareClick={onSquareClick}\n />\n\n {showControls && (\n <div className={styles.bottomBar}>\n <DifficultySelector depth={depth} onChange={setDepth} />\n <StupidLevel level={stupidLevel} onChange={setStupidLevel} />\n </div>\n )}\n\n <ChaosToast action={lastAction} />\n {promotionPending && <PromotionDialog color={turn} onSelect={handlePromotion} />}\n {gameStatus.isGameOver && (\n <GameOverBanner status={gameStatus} humanColor={humanColor} onRestart={handleRestart} />\n )}\n </div>\n );\n}\n"],"names":["PIECE_VALUES","FILES","parseFen","fen","parts","positionToBoard","position","board","ranks","rank","row","ch","emptyCount","color","type","i","boardToPosition","rankStr","cell","serializeFen","calculateMaterial","white","black","value","getEmptySquares","squares","file","getPieceSquares","excludeKing","squareToIndices","square","addPieceToFen","piece","sanitizeFen","removePieceFromFen","CASTLING_HOMES","pieceAt","sanitizeCastling","castling","flag","home","kingSq","rookSq","king","rook","sanitizeEnPassant","enPassant","activeColor","expectedRank","pawnRank","startRank","pawn","pawnColor","getGameStatus","chess","whiteKing","blackKing","createChess","initialFen","Chess","useChessGame","initialChess","useState","chessRef","useRef","setFen","turn","setTurn","selectedSquare","setSelectedSquare","legalMoves","setLegalMoves","gameStatus","setGameStatus","promotionPending","setPromotionPending","moveHistory","setMoveHistory","lastMove","setLastMove","lastMoveDetail","setLastMoveDetail","setBoard","clearSelection","useCallback","syncState","recordMove","move","prev","handleSquareClick","moves","m","handlePromotion","applyFen","newFen","applyMove","input","expectedFen","handleRestart","INIT_TIMEOUT_MS","RESTART_INIT_TIMEOUT_MS","MAX_INIT_FAILURES","READY_TIMEOUT_MS","SEARCH_TIMEOUT_MS","STOP_GRACE_MS","StockfishCancelledError","StockfishRestartedError","StockfishUnavailableError","StockfishTimeoutError","stage","StockfishEngine","workerPath","timeoutMs","timeout","ready","err","worker","e","msg","pending","waiter","w","error","match","resolve","reject","timer","reason","waiters","depth","searchDepth","mySearchId","IDLE_TTL_MS","idle","poolKey","acquireEngine","key","list","entry","releaseEngine","engine","current","INIT_RETRY_DELAY_MS","SAFETY_TIMEOUT_MS","useStockfish","engineRef","status","setStatus","isThinking","setIsThinking","callIdRef","useEffect","cancelled","retryTimer","start","attempt","isReady","getBestMove","myCallId","safetyTimeout","cancel","ADDABLE_PIECES","MAX_RETRIES","MAX_PIECES_PER_SIDE","MAX_PAWNS_PER_SIDE","getChaosTarget","whiteMaterial","blackMaterial","randomChoice","arr","shuffled","out","j","chooseRandomPiece","allowPawn","countPieces","total","pawns","isValidChaosPosition","totals","kings","sideNotToMove","addRandomPiece","emptySquares","removeRandomPiece","pieceSquares","executeChaosAction","target","operation","addColor","removeColor","result","fallback","STUPID_BOUNDS","getRandomChaosInterval","stupidLevel","level","idx","lo","hi","TICK_MS","MIN_RESUME_MS","isDocumentHidden","useChaosEngine","isPaused","onChaosAction","resetKey","countdown","setCountdown","maxCountdown","setMaxCountdown","lastAction","setLastAction","chaosSquare","setChaosSquare","fenRef","isPausedRef","stupidLevelRef","onChaosActionRef","remainingMsRef","lastTickRef","wasPausedRef","hiddenRef","scheduleNext","intervalMs","seconds","useLayoutEffect","isFirstReset","onVisibility","flashTimer","intervalId","now","elapsed","PIECE_ART","NAMES","pieceName","PieceIcon","className","art","colorClass","styles","jsx","Square","isLight","isSelected","isLegalMove","isCheck","isLastMoveFrom","isLastMoveTo","isChaosFlash","rankLabel","fileLabel","onClick","classNames","jsxs","boardStyles","getSquareName","isLightSquare","ChessBoard","React","inCheck","flipped","locked","onSquareClick","checkSquare","r","f","rankOrder","fileOrder","rankIdx","fileIdx","displayRow","displayCol","PROMOTION_PIECES","PromotionDialog","onSelect","label","getResultText","humanColor","GameOverBanner","onRestart","title","detail","ChaosTimer","progress","glow","ChaosToast","action","visible","setVisible","fading","setFading","displayAction","setDisplayAction","timeoutRef","message","DifficultySelector","onChange","LABELS","StupidLevel","SidePicker","onDepthChange","onStupidLevelChange","onSelectSide","MuteButton","muted","onToggle","sharedCtx","SoundManager","ctx","osc","gain","bufferSize","buffer","data","noise","bandpass","freqs","freq","isFiniteNumber","clampDepth","clampStupidLevel","normalizeState","raw","state","MAX_ENGINE_FAILURES","ChessGame","props","defaultDepth","defaultStupidLevel","defaultHumanColor","defaultMuted","controlledDepth","controlledStupidLevel","stockfishWorkerPath","skipSetup","showControls","showMuteButton","initialState","onStateChange","onGameOver","onMove","onChaosActionCb","onRestartCb","restored","internalDepth","setInternalDepth","setDepth","internalStupidLevel","setInternalStupidLevel","setStupidLevel","internalHumanColor","setInternalHumanColor","soundMuted","setSoundMuted","sounds","gamePhase","setGamePhase","gameId","setGameId","resetGame","engineStatus","stockfishReady","cancelSearch","aiEnabled","isHumanTurn","currentFenRef","humanColorRef","gamePhaseRef","gameCounterRef","chaosEnabled","chaosPaused","safeFen","prevLastActionRef","onStateChangeRef","noMoveFenRef","aiFailuresRef","playAiMove","forFen","uciMove","playFallbackMove","requestAiMove","game","isStale","giveUp","failures","handleSideSelect","id","prevMoveCountRef","latest","prevGameOverRef","statusText","rootClassName"],"mappings":"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"}
|