Simbelmyne is a UCI-compliant chess engine. It uses a bitboard-based board representation, a traditional hand-crafted evaluation function, and is powered by an optimized alpha-beta search. See Details for more information on the optimizations that are performed.
A main motivation for this project was to get more familiar with writing Rust, so let that be a warning that anyone reading the code might find the odd non-idiomatic, or downright stupid implementation.
Assigning an objective rating to a chess engine is tough. Values will change wildly depending on the machine the engine is running on or what time control is used.
Below is a table of different Elo estimates obtained by having Simbelmyne play against other engines. The used time-controls are listed, as time / increment
, in seconds.
Version | Estimate (10/0.1) | MCERL (60/0.6) | CEDR (180/3) | CCRL (40/15) | CCRL Blitz (2/1) |
---|---|---|---|---|---|
v1.0.0 | 2000 | 2247 | |||
v1.1.0 | 2100 | 2293 | |||
v1.2.0 | 2350 | 2457 | 2393 | ||
v1.3.0 | 2500 | 2567 | 2505 | ||
v1.3.1 | 2500 | 2465 | |||
v1.4.0 | 2650 | ||||
v1.5.0 | 2700 | ||||
v1.5.1 | 2700 | 2708* | 2702 | ||
v1.6.0 | 2760 | 2796* | 2769 | ||
v1.7.0 | 2900 | 2913 | 2926 | ||
v1.8.0 | 3050 | 2997* |
(* Provisional rating, not enough games played so the error bars are rather large.)
A huge thank you goes out to the people kind enough to have gone out of their way to test Simbelmyne!
Like most chess engines, Simbelmyne is mostly designed to be used through the
UCI protocol. Simply running simbelmyne
from the command line will drop you
into a UCI prompt that you can use to interact with the engine, if you so want.
The saner option is to use a dedicated UCI-compatible frontend. Some examples
are:
If that feels like too much effort, Simbelmyne is also available for play as a lichess bot.
Simbelmyne is developed with Rust v1.73, and most easily built using the Cargo toolchain.
From the project root, run cargo build --release
, and the resulting binary
will be found at target/release/simbelmyne
Simbelmyne follows a fairly traditional chess engine architecture. The two main pillars underpinning everything are the Search and Evaluation.
The search subsystem is all about visiting as many board positions as possible, and looking as many moves ahead as possible, in the least amount of time. The algorithm used for this is a classical [Negamax search][negamax]. The following optimizations are added on top to improve the search speed and quality:
- Legal move generation
- Bitboard representation
- Magic bitboards
- PEXT bitboards (when supported)
- Iterative deepening
- Aspiration windows
- Alpha-beta pruning
- Principal-variation search
- Check extensions
- Improving heuristic
- Transposition table
- Internal iterative reduction
- Reverse futility pruning
- Null-move pruning
- Futility pruning
- Static Exchange Evaluation pruning
- Late move pruning
- Late move reductions
- Quiescence search
- Delta pruning
- Singular extensions
- Double extensions
- Hash move
- MVV + Capture history
- Static exchange evaluation for splitting captures into good/bad
- Killer Moves
- Countermoves
- Threat-based quiet history
- 1 ply continuation history
- 2 ply continuation history
- 4 ply continuation history
If the search part of the engine is all about "try and search as deep as possible", then the evaluation is all about making sense of what is found there. The engine needs to figure out, by some metric, what board positions are more favorable than others. This is where a lot of the hard-earned experience of chess-players throughout the ages gets codified into computer-understandable heuristics.
As much as possible, the evaluation function tries to compute evaluation terms incrementally, and retrieving non-incremental values from the Transposition table when possible.
- Material counting
- Piece-square tables
- Pawn structure
- Passed pawns
- Isolated pawns
- Protected pawns
- Phalanx pawns
- passed pawn distance to friendly king
- passed pawn distance to enemy king
- Minor piece outposts
- Bishop pair
- Rook on (semi-) open file
- Connected rooks
- Queen on (semi-) open file
- Major piece on 7th rank
- Mobility, taking into consideration pawn attacks and pins
- Threats
- King safety
- Virtual mobility
- King zone attacks
- Pawn shield
- Pawn storm
Simbelmyne was inspired, and has drawn a lot from many different people, resources and codebases, so it is only proper to give thanks where thanks are due.
- Carp: especially when starting off, it was good to have a reference implementation in Rust to compare notes with
- Viridithas: Same. Especially appreciated the viri wiki that briefly outlines the high-level features of the engine.
- Rustic: Especially starting out, the Rustic book was a great resource. Far more coherent and digestible, if less comprehensive, than the CPW.
- Stockfish: Of course, the uber-reference. When in doubt, do as Stockfish does.