This project started as a way to get familiar with Rust around two years go — and then, as these things tend to go, it got a little bit out of hand. What began as tinkering with search algorithms has grown into a reasonably capable chess engine with NNUE evaluation, multithreading, and pondering support. This is currently my third attempt to make a chess engine and again I should've done a lot of things differently, but I think it is at a stage where it is release worthy.
Move generation and board representation are handled by the shakmaty library. As a Rust beginner, I wanted to focus on search and evaluation first rather than getting bogged down in the details of legal move generation. Writing my own move generator is on the roadmap and maybe the start of my fourth attempt to make an engine?
I'm currently training two NNUEs from scratch. One with a big empty brain (768 -> 1536)x2 -> 1x8 and one small brain (768 -> 64)x2 -> 1. They train by constantly playing against eachother and learning from both views of the board. For more information about this progression see the CHANGELOG.md. You can play the latest generations of my networks on lichess : Big brain, Small brain.
- Negamax with Principal Variation Search
- Aspiration windows
- Transposition table (lockless)
- Lazy SMP multithreading
- Pondering (~90% complete)
- Reverse futility pruning / Static null move pruning
- Null move pruning
- Razoring
- Futility pruning
- History pruning
- Hanging piece pruning
- Late move pruning
- Late move reductions
- Internal iterative reduction
- Singular extensions
- Double & triple extensions
- Static Exchange Evaluation (SEE)
- Killer moves
- History heuristic
- 1, 2, 4 ply continuation history
- Improving heuristic
- Quiescence search with SEE
- Time management based on move and eval stability
- NNUE with architecture
(768 → 1536) × 2 → 1 × 8trained with the excellent Bullet crate - SPSA trainer (work in progress)
The following UCI commands are implemented:
| Command | Notes |
|---|---|
uci |
Done |
isready |
Done |
ucinewgame |
Done |
position <fen|startpos> [moves ...] |
Done |
go <wtime, btime, winc, binc, movetime, depth, ponder> |
Need to implement movestogo |
ponderhit |
90% done |
stop |
Done |
quit |
Done |
setoption name <Hash | Threads | Ponder | Move Overhead> |
Done |
perft <depth> |
Done |
Below is a table of Elo estimates from having the engine play against other engines and itself. Time controls are listed as time / increment, in seconds.
Stash (and all its versions) have been used to estimate the rating of this engine.
| Version | Estimate (5/0.1) | CCRL (40/15) | CCRL Blitz (2/1) |
|---|---|---|---|
| v1.0 | None yet | None yet | None yet |
Pea is made with Rust v1.93.1 and easily build with Cargo. Clone the repository and build from the project root.
git clone https://github.com/WGCodings/Pea.gitStandard build:
cargo build --releaseRecommended — optimized for your CPU:
# Linux / macOS
RUSTFLAGS="-C target-cpu=native -C target-feature=+avx2,+bmi2" cargo build --release
# Windows (PowerShell)
$env:RUSTFLAGS="-C target-cpu=native -C target-feature=+avx2,+bmi2"; cargo build --releaseThe native build enables AVX2 and BMI2 instructions and runs noticeably faster. It is strongly recommended unless you are distributing the binary to other machines.
Running the binary directly drops you into a UCI prompt. In practice, you'll want to use a UCI-compatible frontend:
- IN PROGRESS : Solve NNUE bias towards White
- IN PROGRESS : Investigate better NNUE architectures (two adversarial networks from scratch?)
- IN PROGRESS : Data generator for NNUE training
- Self-made move generation and board representation
- Correction history
- Successful run of SPSA
- Clean up code, especially datatypes (too many
ascasts) - Better time manager
- Integration with OpenBench
- Capture history
- Fix missing PV lines due to cutoffs
- Store evals in TT before recursive search
- Mate Distance Pruning
- Threat moves and extensions in NMP
- Probcut
- Try improving heuristic in LMR
- Contempt
- WDL normalization
- Variable window choice in Asp Window
Simbelmyne by Sam Roelants was a major source of inspiration and learning throughout this project. A lot of ideas and how to implement them in Rust came from there.
Thanks to the communities at the Engine Programming Discord servers, the Chess Programming Wiki and TalkChess forum where an enormous amount of collective knowledge lives out in the open.
This project is licensed under the GNU General Public License v3.0.
