No coding experience needed — just copy, paste, and compete!
Your bot must follow these rules to compete successfully
reportMove() before timeout → YOU LOSE!
board.move() - Original board is READ-ONLY!board.undo() - Original board is READ-ONLY!board.load(), board.reset(), board.put()fetch(), eval(), async, awaitboard.moves() - Get legal movesboard.get(square) - Get piece at squareboard.turn() - Get current player ('w' or 'b')board.fen() - Get board positionboard.in_check() - Is in check?board.in_checkmate() - Is checkmate?board.in_stalemate() - Is stalemate?board.in_draw() - Is draw?board.game_over() - Is game over?board.clone() - Creates mutable copy// Create NEW clone for EACH top-level move
function searchBestMove(board, depth) {
const moves = board.moves();
let bestMove = moves[0];
for (const move of moves) {
const clone = board.clone(); // New clone per move!
clone.move(move); // ✅ Safe on clone
const score = -minimax(clone, depth-1);
// Update bestMove if better
}
return bestMove;
}
// Recursion uses move/undo on the SAME clone
function minimax(clone, depth) {
if (depth === 0) return evaluate(clone);
for (const move of clone.moves()) {
clone.move(move); // ✅ Works on clone
const score = -minimax(clone, depth-1);
clone.undo(); // ✅ Works on clone
}
}
function makeMove(board, timeRemaining, reportMove) {
const moves = board.moves();
const stop = Date.now() + timeRemaining - 500;
// Report ANY move immediately!
reportMove(moves[0]);
// Now search for better moves
for (let depth = 1; depth <= 5; depth++) {
if (Date.now() >= stop) break; // Track elapsed time!
const best = search(board, depth);
reportMove(best); // Update with better move
}
}
Three simple steps to get started
Use ChatGPT (chat.openai.com) or Claude (claude.ai)
Create a chess bot for ChessArena.dev following these rules:
🚨 CRITICAL RULES:
1. ⏰ 20-SECOND TIME LIMIT - Must call reportMove() or we LOSE
2. 🔄 ANYTIME ALGORITHM - Call reportMove() IMMEDIATELY, then improve
3. 📦 SHORTER CODE WINS - In draws, shorter code gets 0.6 points
4. 🚫 BOARD IS READ-ONLY - Use board.clone() to explore moves
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📋 FUNCTION SIGNATURE:
function makeMove(board, timeRemaining, reportMove, getMemory) {
// board: Read-only chess board interface
// timeRemaining: Milliseconds available for THIS move (typically 20000ms)
// reportMove: Function to report your chosen move (anytime algorithm!)
// getMemory: Function to check memory usage - returns { heapUsed, heapTotal, rss }
}
💾 MEMORY LIMIT:
Your bot has 256MB of memory per execution. Garbage collection runs automatically
between moves, so each move starts with a clean slate. Monitor with getMemory().heapUsed.
⏱️ TIME MANAGEMENT:
Each move gets 20 seconds. Track elapsed time with Date.now():
const stop = Date.now() + timeRemaining - 500; // Leave 500ms safety margin
while (Date.now() < stop) {
// Search for better moves...
}
🚫 FORBIDDEN:
❌ board.move(move) - CANNOT use on original board!
❌ board.undo() - CANNOT use on original board!
❌ fetch, eval, async, await - No network/dynamic code
❌ Code over 30KB
✅ ALLOWED:
board.moves() → Array of legal moves
board.clone() → Mutable copy (use move/undo on clone!)
board.get(square) → Piece at square
board.turn() → 'w' or 'b'
board.in_check() → Boolean
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
💡 ANYTIME ALGORITHM PATTERN:
function makeMove(board, timeRemaining, reportMove) {
const moves = board.moves();
const stop = Date.now() + timeRemaining - 500; // Safety margin
// STEP 1: Report ANY move immediately (safety!)
reportMove(moves[0]);
// STEP 2: Iterative deepening
for (let depth = 1; depth <= 10; depth++) {
if (Date.now() >= stop) break; // Check elapsed time!
const best = searchAtDepth(board, depth);
reportMove(best); // Update with better move
}
}
🔬 CORRECT CLONE PATTERN FOR MINIMAX:
// Create NEW clone for EACH top-level move
function searchBestMove(board, depth) {
const moves = board.moves();
let bestMove = moves[0];
let bestScore = -Infinity;
for (const move of moves) {
const clone = board.clone(); // New clone per move!
clone.move(move); // ✅ Safe on clone
const score = -minimax(clone, depth-1, -Infinity, Infinity);
if (score > bestScore) {
bestScore = score;
bestMove = move;
}
}
return bestMove;
}
// Recursion uses move/undo on the SAME clone
function minimax(clone, depth, alpha, beta) {
if (depth === 0) return evaluate(clone);
const moves = clone.moves();
if (moves.length === 0) {
return clone.in_checkmate() ? -100000 : 0;
}
let best = -Infinity;
for (const move of moves) {
clone.move(move); // ✅ Works on clone
const score = -minimax(clone, depth-1, -beta, -alpha);
clone.undo(); // ✅ Works on clone
if (score > best) best = score;
if (best > alpha) alpha = best;
if (alpha >= beta) break;
}
return best;
}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🎯 IMPLEMENT:
1. Minimax or alpha-beta pruning
2. Position evaluation (material, piece-square tables)
3. Iterative deepening
4. Early reportMove() call
5. Time management
Keep code compact (shorter wins draws)!
Get inspired and learn winning strategies
function makeMove(board, timeRemaining, reportMove) {
const moves = board.moves();
// Safety: report ANY move immediately
reportMove(moves[0]);
// Try to find captures
for (const move of moves) {
const clone = board.clone();
const result = clone.move(move);
if (result && result.captured) {
reportMove(move);
break;
}
}
}
To update an existing bot:
Your ELO and stats are preserved!
Register your bot in 2 minutes and start climbing the leaderboard!