A 2625 Elo UCI-compatible chess engine written in Rust. Self-contained single binary with embedded NNUE evaluation.
Note: Previously named Oxide. Renamed to Oxid' after discovering another chess engine already uses that name.
Run directly from source:
cargo run -r -- <command>Or build and run the executable:
cargo build -r
./target/release/oxid <command>The binary is fully self-contained — the NNUE network is embedded at compile time, no external files needed.
cargo run -r -- bench # Default: depth 13, 16 MB hash
cargo run -r -- bench 32 1 15 # Custom: 32 MB hash, 1 thread, depth 15| Option | Type | Default | Description |
|---|---|---|---|
Hash |
spin | 16 | Transposition table size in MB (1-512) |
EvalFile |
string | <embedded> |
Load a different NNUE net at runtime |
SyzygyPath |
string | <empty> |
Colon-separated paths to Syzygy tablebase files |
It does not come with a GUI. You can use Cute Chess or Arena.
On a benchmark of 46 positions search at depth 13:
Total time (ms) : 61047
Nodes searched : 46575003
Nodes/second : 762936
and for pure perft on 1 thread without any movegen hashing:
Perft aggregate: 18652422582 146567ms 127.26 MNodes/s
- Magic bitboards for sliding piece attacks
- Bitboards with Little-Endian Rank-File (LERF) mapping
- Hybrid mailbox + bitboard representation
- Incremental Zobrist hashing
- Negamax with alpha-beta pruning
- Iterative deepening with aspiration windows
- Principal Variation Search (PVS)
- Transposition table with age-based replacement, best move, depth, and node type
- Mate score adjustment for TT storage
- Correction history (pawn-hash indexed static eval error tracking)
- Quiescence search (captures, en passant, promotions)
- Check extensions
- Null move pruning
- Reverse futility pruning
- Razoring
- Futility pruning
- Late move pruning (LMP)
- Late move reductions (LMR)
- SEE pruning (static exchange evaluation)
- Probcut (shallow verification search at depth >= 5)
- Delta pruning in quiescence
- Staged move generation (MovePicker) with lazy legality checking — fully integrated
- Move ordering: TT move > captures (MVV-LVA + capture history) > killers > countermove > quiets (history + continuation history)
- Continuation history (1-ply + 2-ply) for quiet move ordering
- Capture history for capture move ordering
- History malus for quiet/capture moves tried before beta cutoffs
- Syzygy endgame tablebases (root DTZ probe, in-search WDL probe via pyrrhic-rs)
- NNUE evaluation (8-bucket king-bucketed 768->384x2->32->1 SCReLU architecture, integer quantized)
- King bucketing with horizontal mirroring (8 buckets by rank, files e-h mirrored to a-d)
- Incremental accumulator updates with per-perspective bucket-change refresh
- Optimized forward pass: pre-computed SCReLU activations, transposed L1 weights
- Embedded net via
include_bytes!— no external files at runtime - Runtime net loading via
EvalFileUCI option for SPRT testing
Nets use SHA256-based naming: nn-{first 12 hex chars}.nnue. Only the active (promoted) net is committed to git; all others are gitignored.
scripts/convert_checkpoints.sh— converts training checkpoints to.nnueformatscripts/promote_net.sh <path>— promotes a net as the new embedded default
Detailed documentation is available in the docs/ directory:
- Architecture — Module overview, component wiring, core types
- Search — All search techniques, pruning, reductions, move ordering
- Evaluation — NNUE architecture, handcrafted eval fallback
- UCI Protocol — Supported commands and options
- A huge thanks to @mvanthoor for his work on Rustic that helped me understand a lot of concepts in Rust.
- Also a big part of my way of thinking was influenced by Stockfish. It was also a great tool to debug my code.
