Hi everyone,
After some years away from chess programming, I've published a JavaScript move
generator that I've been working on. It's now available on GitHub and NPM.
GitHub: https://github.com/mcarbonell/chess-movegen-js
NPM: npm install chess-movegen-js
Live Demo: https://mcarbonell.github.io/chess-movegen-js/
Key Features:
• Strictly legal move generation (no pseudo-moves requiring make/unmake validation)
• Integrated pin detection during generation
• Check, checkmate, and stalemate detection as part of move generation
• Tactical move enrichment (safe squares, hanging pieces, winning captures, discovered checks)
• Two implementations: 0x88 and Bitboards with magic tables
• UCI engine with Web Worker support
Performance (Node.js v20, x88 implementation):
- Depth 4: 197,281 nodes in 83ms (2.4M NPS)
- Depth 5: 4,865,609 nodes in 871ms (5.6M NPS)
- Depth 6: 119,060,324 nodes in ~17s (7.0M NPS)
All standard Perft positions pass correctly.
Technical Approach:
The main difference from typical move generators is that pins are detected
upfront and moves are filtered during generation, not after. This means:
1. Calculate all checking squares before generating moves
2. Detect pinned pieces and pin directions
3. Generate only moves that respect pin constraints
4. For king moves, only generate to pre-calculated safe squares
5. When in check, only generate moves to valid escape squares
This eliminates the need for make/unmake validation cycles entirely.
Interesting Finding:
In JavaScript, the 0x88 implementation significantly outperforms bitboards
(~40% faster). I suspect this is due to:
- JavaScript's 53-bit integer limitation requiring BigInt for 64-bit operations
- BigInt operations being slower than regular integer arithmetic
- Better cache locality with the simpler 0x88 array structure
Both implementations are included in the repo for educational comparison.
The project includes:
- Complete source code (MIT license)
- Interactive web demo with drag & drop board
- Comprehensive Perft test suite
- UCI engine implementation
- CI/CD with GitHub Actions
I'd appreciate any feedback, especially on:
- Performance optimization opportunities
- Edge cases I might have missed
- Comparison with other JavaScript chess libraries
The code is well-commented and might be useful for anyone learning chess
programming or needing a move generator for web-based chess projects.
Cheers,
Mario
JavaScript Move Generator with Strictly Legal Move Generation (x88 & Bitboards)
Moderator: Ras
-
mario carbonell
- Posts: 22
- Joined: Tue Dec 12, 2017 7:14 pm
-
op12no2
- Posts: 554
- Joined: Tue Feb 04, 2014 12:25 pm
- Location: Gower, Wales
- Full name: Colin Jenkins
Re: JavaScript Move Generator with Strictly Legal Move Generation (x88 & Bitboards)
Very nice Mario. It's a shame that BitInts are still so slow; but they are getting quicker over time. The other option is using 2 x Uint32Array elements, but I found that is still slower than mailbox; and ugly. You'll be pleased to know PERFT 6 from startpos achieved 12M nps on my 7950x (using the web demo UI). Good luck with your developments...
-
Aleks Peshkov
- Posts: 967
- Joined: Sun Nov 19, 2006 9:16 pm
- Location: Russia
- Full name: Aleks Peshkov
Re: JavaScript Move Generator with Strictly Legal Move Generation (x88 & Bitboards)
Nice to see non-bitboard development. All bitboard engines look very similar in their basics.
-
mario carbonell
- Posts: 22
- Joined: Tue Dec 12, 2017 7:14 pm
Re: JavaScript Move Generator with Strictly Legal Move Generation (x88 & Bitboards)
Thanks op12no2 and Aleks!
@op12no2: 12M NPS on your 7950x is fantastic! That's nearly 2x what I'm seeing on my machine. The BigInt limitation is indeed the main bottleneck for bitboards in JS - that's why I'm publishing the x88 implementation for the NPM package.
@Aleks: Thanks for sharing Petrel! I agree that x88 offers more room for
creative approaches.
I'm now trying to implement a wasm version of the bitboards with Rust, and try to measure the improvement.
Cheers,
Mario
@op12no2: 12M NPS on your 7950x is fantastic! That's nearly 2x what I'm seeing on my machine. The BigInt limitation is indeed the main bottleneck for bitboards in JS - that's why I'm publishing the x88 implementation for the NPM package.
@Aleks: Thanks for sharing Petrel! I agree that x88 offers more room for
creative approaches.
I'm now trying to implement a wasm version of the bitboards with Rust, and try to measure the improvement.
Cheers,
Mario