Generador de movimientos de ajedrez en JavaScript con detección estrictamente legal
| English | Español |
O abre engine.html en tu navegador para ver la demo interactiva.
npm install chess-movegen-js
const { Board } = require('chess-movegen-js');
const board = new Board();
board.loadFEN('rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1');
board.generateMoves();
console.log(`Movimientos legales: ${board.moves.length}`); // 20
// Crear un tablero
const board = new Board();
// Cargar una posición FEN
board.loadFEN('rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1');
// Generar todos los movimientos legales
board.generateMoves();
// Ver los movimientos
console.log(board.moves);
Los movimientos incluyen información táctica:
board.generateMoves();
board.moves.forEach(move => {
const moveStr = board.getMoveStr(move);
console.log(moveStr);
// Información táctica en move.mask:
// - mask_check: Da jaque
// - mask_safe: Casilla segura
// - mask_hanging: Pieza quedaría colgada
// - mask_freecapture: Captura sin defensa
// - mask_winningcapture: Captura ganadora
});
// Hacer un movimiento
const move = board.moves[0];
board.makemove(move);
// Deshacer
board.undomove();
// Contar nodos a profundidad 5
const nodes = board.perft(5);
console.log(`Nodes: ${nodes}`); // 4,865,609 desde posición inicial
// Divide (mostrar nodos por movimiento)
board.divide(4);
movegen/
├── js/
│ ├── x88.js # Generador con representación x88 (1842 líneas)
│ ├── bitboard.js # Generador con bitboards
│ ├── magic-tables.js # Tablas Mágicas para bitboard
│ └── engine.js # Motor UCI con Web Worker
├── assets/ # Estilos css y js para la demo
├── img/ # Recursos gráficos
├── engine.html # Demo interactiva principal
├── ANALISIS.md # Análisis técnico detallado
└── README.es.md # Este archivo
El proyecto incluye un motor UCI completo que se ejecuta en Web Worker:
// Crear motor
const w = new Worker("js/engine.js");
// Comunicación UCI
w.postMessage('uci');
w.postMessage('position fen rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1');
w.postMessage('perft 6');
// Escuchar respuestas
w.onmessage = function(event) {
console.log(event.data);
};
uci - Inicializar motorisready - Verificar disponibilidaducinewgame - Nueva partidaposition [fen|startpos] [moves ...] - Establecer posiciónmove <move> - Hacer movimiento (ej: e2e4)undo - Deshacer movimientoperft <depth> - Test de generación de movimientosPerft desde posición inicial (Node.js v20+, sin debug):
| Depth | Nodos | Tiempo | NPS |
|---|---|---|---|
| 1 | 20 | <1ms | ~25k |
| 2 | 400 | ~1ms | ~268k |
| 3 | 8,902 | ~10ms | ~864k |
| 4 | 197,281 | ~83ms | 2.4M |
| 5 | 4,865,609 | ~871ms | 5.6M |
| 6 | 119,060,324 | ~17s | 7.0M |
En navegador (puede variar según browser y hardware):
Nota: Estos resultados son con el código optimizado (sin llamadas a
debug()). El rendimiento en producción es excelente para JavaScript puro.
Las piezas clavadas se detectan durante la generación. Los movimientos ilegales nunca se generan:
// pinDirection[side][square] indica si una pieza está clavada
// y en qué dirección
Cada movimiento contiene flags que indican:
if (sq & 0x88) continuejs/x88.jsjs/bitboard.jsPara un análisis técnico completo del código, consulta ANALISIS.md.
El proyecto usa Perft para validar la generación de movimientos:
// Desde consola del navegador en engine.html
w.postMessage('perft 5');
// O en código
const board = new Board();
board.loadFEN('rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1');
console.log(board.perft(5)); // Debe ser 4,865,609
El proyecto incluye una suite completa de tests Perft para validar la correctitud de la generación de movimientos y medir el rendimiento.
# Ejecutar suite rápida (profundidades 1-4, ~1 minuto)
node tests/perft-test.js --quick
# Probar posición específica
node tests/perft-test.js --position 0 --depth 5
# Probar solo generador x88 hasta profundidad 6
node tests/perft-test.js --generator x88 --depth 6
node tests/perft-test.js [opciones]
Opciones:
--generator <x88|bb|both> Seleccionar generador a probar (default: both)
--position <n> Probar solo posición n (default: all)
--depth <n> Probar hasta profundidad n (default: 6)
--quick Modo test rápido (profundidades 1-4)
--help Mostrar mensaje de ayuda
La suite de tests incluye 7 posiciones estándar de Chess Programming Wiki:
| Posición | Descripción | Profundidad Máxima |
|---|---|---|
| 0 | Posición inicial | 10 |
| 1 | Kiwipete (medio juego complejo) | 6 |
| 2 | Casos especiales de captura al paso | 8 |
| 3 | Promociones | 6 |
| 4 | Promociones (espejo) | 6 |
| 5 | Posición táctica compleja | 5 |
| 6 | Posición simétrica | 6 |
Chess Move Generator - Perft Test Suite
Configuration:
Generator: x88
Positions: 7
Max depth: 4
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Testing: x88 Generator
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Initial Position
FEN: rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
✓ Depth 1: 20 nodes [1ms, 17,891 NPS]
✓ Depth 2: 400 nodes [2ms, 167,560 NPS]
✓ Depth 3: 8,902 nodes [9ms, 973,343 NPS]
✓ Depth 4: 197,281 nodes [80ms, 2,480,626 NPS]
Kiwipete
FEN: r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 1
✓ Depth 1: 48 nodes [0ms, 302,457 NPS]
✓ Depth 2: 2,039 nodes [2ms, 1,220,008 NPS]
✓ Depth 3: 97,862 nodes [32ms, 3,068,986 NPS]
✓ Depth 4: 4,085,603 nodes [548ms, 7,461,185 NPS]
...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Summary
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Total tests: 28
Passed: 28
Failed: 0
Pass rate: 100.0%
Performance Summary:
Depth 1: 883,697 NPS avg (368 nodes in 2ms)
Depth 2: 2,126,798 NPS avg (13,446 nodes in 10ms)
Depth 3: 3,360,700 NPS avg (561,558 nodes in 170ms)
Depth 4: 4,722,406 NPS avg (22,337,738 nodes in 4.51s)
Medido en Node.js v20+ con generador x88 (optimizado, sin debug):
| Depth | Nodos | Tiempo | NPS |
|---|---|---|---|
| 1 | 20 | <1ms | ~25k |
| 2 | 400 | ~1ms | ~268k |
| 3 | 8,902 | ~10ms | ~864k |
| 4 | 197,281 | ~83ms | 2.4M |
| 5 | 4,865,609 | ~871ms | 5.6M |
| 6 | 119,060,324 | ~17s | 7.0M |
Suite de tests rápida (7 posiciones, profundidades 1-4): ~1.4 segundos
💡 Consejo: El rendimiento es significativamente más rápido con el logging de debug desactivado. Asegúrate de comentar las llamadas a
this.debug()en producción.
Si los tests fallan o muestran errores:
tests/ existe con todos los archivos// Posición Kiwipete
board.loadFEN('r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 1');
console.log(board.perft(5)); // 193,690,690
// Captura al paso compleja
board.loadFEN('8/2p5/3p4/KP5r/1R3p1k/8/4P1P1/8 w - - 0 1');
Las contribuciones son bienvenidas. Por favor:
git checkout -b feature/AmazingFeature)git commit -m 'Add some AmazingFeature')git push origin feature/AmazingFeature)Este proyecto está bajo la Licencia MIT - ver el archivo LICENSE para más detalles.
Mario Raúl Carbonell Martínez
⭐ Si encuentras útil este proyecto, considera darle una estrella en GitHub!