JavaScript chess move generator with strictly legal move generation
| English | Espaรฑol |
Or open engine.html in your browser locally.
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(`Legal moves: ${board.moves.length}`); // 20
// Create a board
const board = new Board();
// Load a FEN position
board.loadFEN('rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1');
// Generate all legal moves
board.generateMoves();
// View the moves
console.log(board.moves);
Moves include tactical information:
board.generateMoves();
board.moves.forEach(move => {
const moveStr = board.getMoveStr(move);
console.log(moveStr);
// Tactical information in move.mask:
// - mask_check: Gives check
// - mask_safe: Safe square
// - mask_hanging: Piece would be hanging
// - mask_freecapture: Undefended capture
// - mask_winningcapture: Winning capture
});
// Make a move
const move = board.moves[0];
board.makemove(move);
// Unmake
board.undomove();
// Count nodes at depth 5
const nodes = board.perft(5);
console.log(`Nodes: ${nodes}`); // 4,865,609 from initial position
// Divide (show nodes per move)
board.divide(4);
movegen/
โโโ js/
โ โโโ x88.js # x88 representation generator (1842 lines)
โ โโโ bitboard.js # Bitboard generator
โ โโโ magic-tables.js # Magic tables for bitboard
โ โโโ engine.js # UCI engine with Web Worker
โโโ assets/ # css and js assets for the demo
โโโ img/ # Graphic resources
โโโ engine.html # Main interactive demo
โโโ ANALISIS.md # Detailed technical analysis
โโโ README.md # This file
The project includes a complete UCI engine running in a Web Worker:
// Create engine
const w = new Worker("js/engine.js");
// UCI communication
w.postMessage('uci');
w.postMessage('position fen rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1');
w.postMessage('perft 6');
// Listen for responses
w.onmessage = function(event) {
console.log(event.data);
};
uci - Initialize engineisready - Check availabilityucinewgame - New gameposition [fen|startpos] [moves ...] - Set positionmove <move> - Make move (e.g., e2e4)undo - Unmake moveperft <depth> - Move generation testPerft from initial position (Node.js v20+, no debug):
| Depth | Nodes | Time | 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 |
In browser (may vary by browser and hardware):
Note: These results are with optimized code (no
debug()calls). Production performance is excellent for pure JavaScript.
Pinned pieces are detected during generation. Illegal moves are never generated:
// pinDirection[side][square] indicates if a piece is pinned
// and in which direction
Each move contains flags indicating:
if (sq & 0x88) continuejs/x88.jsjs/bitboard.jsFor a complete technical analysis of the code, see ANALISIS.md.
The project uses Perft to validate move generation:
// From browser console in engine.html
w.postMessage('perft 5');
// Or in code
const board = new Board();
board.loadFEN('rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1');
console.log(board.perft(5)); // Should be 4,865,609
The project includes a comprehensive Perft test suite to validate move generation correctness and measure performance.
# Run quick test suite (depths 1-4, ~1 minute)
node tests/perft-test.js --quick
# Test specific position
node tests/perft-test.js --position 0 --depth 5
# Test only x88 generator up to depth 6
node tests/perft-test.js --generator x88 --depth 6
node tests/perft-test.js [options]
Options:
--generator <x88|bb|both> Select generator to test (default: both)
--position <n> Test only position n (default: all)
--depth <n> Test up to depth n (default: 6)
--quick Quick test mode (depths 1-4)
--help Show help message
The test suite includes 7 standard positions from Chess Programming Wiki:
| Position | Description | Max Depth Tested |
|---|---|---|
| 0 | Initial position | 10 |
| 1 | Kiwipete (complex middle game) | 6 |
| 2 | En passant edge cases | 8 |
| 3 | Promotions | 6 |
| 4 | Promotions (mirrored) | 6 |
| 5 | Complex tactical position | 5 |
| 6 | Symmetrical position | 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)
Measured on Node.js v20+ with x88 generator (optimized, no debug):
| Depth | Nodes | Time | 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 |
Quick test suite (all 7 positions, depths 1-4): ~1.4 seconds
๐ก Tip: Performance is significantly faster with debug logging disabled. Make sure to comment out
this.debug()calls in production.
If tests fail or show errors:
tests/ directory exists with all test files// Kiwipete position
board.loadFEN('r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 1');
console.log(board.perft(5)); // 193,690,690
// Complex en passant capture
board.loadFEN('8/2p5/3p4/KP5r/1R3p1k/8/4P1P1/8 w - - 0 1');
README.CI corre los tests rรกpidos (npm test) automรกticamente en push y pull_request. El job de tests completos de bitboard (npm run test:bb) estรก configurado como ejecuciรณn manual para evitar ejecuciones largas en cada push.Cรณmo lanzar el test completo desde GitHub UI:
CI.main o master) y ejecuta.Usando la CLI gh (GitHub CLI) puedes lanzar el workflow asรญ:
gh workflow run ci.yml --ref main
Nota: el workflow CI incluye matrix de versiones Node para los tests rรกpidos y reserva un job manual (test-bitboard-full) con mayor timeout para las pruebas intensivas.
Contributions are welcome. Please:
git checkout -b feature/AmazingFeature)git commit -m 'Add some AmazingFeature')git push origin feature/AmazingFeature)This project is under the MIT License - see the LICENSE file for details.
Mario Raรบl Carbonell Martรญnez
โญ If you find this project useful, consider giving it a star on GitHub!