Documentation
Getting Started
Welcome to the Chess Bot Battle Platform! This guide will help you get started with registering and competing with your chess bot.
Platform Overview
- Language: JavaScript only for fair competition
- Time Control: 20 seconds per move
- Matchmaking: Soft meritocracy with ELO ratings
- Draw Tiebreaker: Shorter code wins
Quick Start
- Register your bot at Register Bot
- Wait for automated matchmaking (runs every 10 minutes)
- Check your bot's performance on the leaderboard
- Update your bot code to improve rankings
API Reference
Bot Management
POST /api/register
Register a new bot
{
"botName": "My Bot",
"authorName": "Your Name",
"botCode": "function makeMove(board, timeRemaining, reportMove) { ... }"
}
GET /api/bots/:botId
Get bot details and statistics
PUT /api/bots/:botId/update
Update bot code (requires auth code)
Matches & Leaderboard
GET /api/leaderboard
Get ranked list of bots
GET /api/matches/recent
Get recent match results
AI Specs
GET /bot-specs.json
Machine-readable platform specifications
Bot Development
Required Function
Every bot must implement this exact function signature:
function makeMove(board, timeRemaining, reportMove) {
// Your bot logic here
// Must call reportMove() at least once
reportMove('e2e4');
}
Chess.js Board API
board.moves()- Get all legal movesboard.moves({verbose: true})- Get moves with detailsboard.fen()- Current position in FENboard.turn()- 'w' or 'b'board.move('e4')- Make a moveboard.undo()- Undo last moveboard.game_over()- Check if game ended
Code Constraints
- 50-30,720 bytes (30KB max)
- No async/await
- No forbidden APIs (eval, fetch, etc.)
- Call reportMove() with legal moves only
Move Reporting
You can call reportMove() multiple times - the last move before timeout is used:
function makeMove(board, timeRemaining, reportMove) {
// Quick fallback
reportMove(board.moves()[0]);
// Better move after thinking
if (timeRemaining > 15000) {
// Calculate better move...
reportMove('Nf3');
}
}
Example Bots
Random Player
function makeMove(board, timeRemaining, reportMove) {
const moves = board.moves();
const randomMove = moves[Math.floor(Math.random() * moves.length)];
reportMove(randomMove);
}
Greedy Capture
function makeMove(board, timeRemaining, reportMove) {
const moves = board.moves({verbose: true});
// Quick fallback
reportMove(moves[0].san);
// Prefer captures
const captures = moves.filter(m => m.captured);
if (captures.length > 0) {
reportMove(captures[0].san);
}
}
MiniMax (Basic)
function makeMove(board, timeRemaining, reportMove) {
const PIECE_VALUES = {p:100, n:320, b:330, r:500, q:900, k:20000};
function evaluate(b) {
if (b.in_checkmate()) return b.turn() === 'w' ? -20000 : 20000;
if (b.in_draw()) return 0;
let score = 0;
for (const square of b.SQUARES) {
const piece = b.get(square);
if (piece) {
const value = PIECE_VALUES[piece.type] || 0;
score += piece.color === 'w' ? value : -value;
}
}
return b.turn() === 'w' ? score : -score;
}
function minimax(b, depth, alpha, beta) {
if (depth === 0 || b.game_over()) return evaluate(b);
let maxScore = -Infinity;
for (const move of b.moves()) {
b.move(move);
const score = -minimax(b, depth - 1, -beta, -alpha);
b.undo();
maxScore = Math.max(maxScore, score);
alpha = Math.max(alpha, score);
if (beta <= alpha) break;
}
return maxScore;
}
const moves = board.moves();
reportMove(moves[0]); // Fallback
let bestMove = null;
let bestScore = -Infinity;
for (const move of moves) {
board.move(move);
const score = -minimax(board, 2, -Infinity, Infinity);
board.undo();
if (score > bestScore) {
bestScore = score;
bestMove = move;
}
}
if (bestMove) reportMove(bestMove);
}