JavaScript chess move generator with strictly legal moves. x88 board representation. Integrated check/checkmate/stalemate detection. Tactical analysis. 5.6M NPS performance.
npm install chess-movegen-js> JavaScript chess move generator with strictly legal move generation





English | Espaรฑol
- โ
Strictly legal move generation - No pseudo-moves requiring post-validation
- โ
Integrated check, checkmate, and stalemate detection - During generation, not as a post-processing step
- โ
Two implementations: x88 and Bitboards
- โ
Automatic tactical analysis - Each move includes information about winning captures, hanging pieces, safe squares
- โ
Complete UCI engine - Compatible with standard chess interfaces
- โ
Interactive web interface - Visual demo with drag & drop board
- โ
Web Workers - Calculations without blocking the UI
Or open engine.html in your browser locally.
``bash`
npm install chess-movegen-js
`javascript
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`
`javascript
// 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:
`javascript
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
});
`
`javascript
// Make a move
const move = board.moves[0];
board.makemove(move);
// Unmake
board.undomove();
`
`javascriptNodes: ${nodes}
// Count nodes at depth 5
const nodes = board.perft(5);
console.log(); // 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:
`javascript
// 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
- - Make move (e.g., e2e4)undo
- - Unmake moveperft
- - Move generation test
Perft 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):
- Chrome/Edge: ~3-5M NPS
- Firefox: ~2-4M NPS
> 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:
`javascript`
// pinDirection[side][square] indicates if a piece is pinned
// and in which direction
Each move contains flags indicating:
- If it gives check or checkmate
- If the piece would be hanging
- If it's a winning capture
- If it's a safe square
- โ
En passant capture with horizontal pins
- โ
Discovered checks (including in castling)
- โ
Mate-in-one detection
- โ
Multiple promotions
- 128-position array (16ร8)
- Ultra-fast validation: if (sq & 0x88) continuejs/x88.js
- More readable and easier to understand code
- File:
- 64-bit bitboard representation
- Faster in theory, more complex
- File: js/bitboard.js
For a complete technical analysis of the code, see ANALISIS.md.
The project uses Perft to validate move generation:
`javascript
// 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.
`bashRun quick test suite (depths 1-4, ~1 minute)
node tests/perft-test.js --quick
$3
`bash
node tests/perft-test.js [options]Options:
--generator Select generator to test (default: both)
--position Test only position n (default: all)
--depth Test up to depth n (default: 6)
--quick Quick test mode (depths 1-4)
--help Show help message
`$3
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 |
$3
`
Chess Move Generator - Perft Test SuiteConfiguration:
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)
`$3
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.$3
If tests fail or show errors:
1. Ensure Node.js is installed: The tests require Node.js v14 or higher
2. Check all files are present: Make sure
tests/ directory exists with all test files
3. Verify x88.js modifications: The file should have Node.js compatibility added$3
`javascript
// 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');
`๐ฏ Next Steps
- [x] Automated tests with Perft suite โ
- [x] Publish as NPM package โ
- [ ] Repetition check with Zobrist hashing
- [ ] WebAssembly optimization
- [ ] Add position evaluation
- [ ] Implement full alpha-beta search
โ๏ธ Continuous Integration (GitHub Actions)
- Badge: agregado arriba en este
README.
- Quรฉ ejecuta: el workflow 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:
1. Ve a la pestaรฑa Actions del repositorio.
2. Selecciona el workflow
CI.
3. Pulsa Run workflow, elige la rama (main o master) y ejecuta.Usando la CLI
gh (GitHub CLI) puedes lanzar el workflow asรญ:`bash
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.๐ค Contributing
Contributions are welcome. Please:
1. Fork the project
2. Create a branch for your feature (
git checkout -b feature/AmazingFeature)
3. Commit your changes (git commit -m 'Add some AmazingFeature')
4. Push to the branch (git push origin feature/AmazingFeature`)- Chess Programming Wiki
- 0x88 Board Representation
- Perft Results
- UCI Protocol
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!