- Overview
- Project layout
- Implemented techniques
- Engine strength
- Build and run
- Using the engine
- Scripts
- Sources
- Author
Akerbeltz is a UCI chess engine written in C++23. This project started out of interest in putting key techniques into practice in a chess engine: performance, efficiency, and strategy. My goal has been to progress incrementally, implementing and documenting each improvement to measure its impact gradually, rather than building a “powerful” engine from day one.
Core layout and where to look for each subsystem:
src/engine core (position, movegen, search, eval, TT, UCI, time manager).test/unit and integration tests (GoogleTest v1.14.0).scripts/utilities for perft, SPRT/smoke runs, and logs/results.img/logo and other static assets.CMakeLists.txtandsrc/CMakeLists.txtfor the main build;test/CMakeLists.txtfor tests.README.mdproject overview and usage.
- Iterative Deepening to refine the PV starting at depth 1.
- Alpha-Beta with full windows.
- Quiescence Search at leaf nodes to reduce tactical noise.
- Check Extensions that extend depth when the side to move is in check.
- Null Move Pruning in non-endgames for aggressive cutoffs.
- Transposition Table to cache scores and PV lines.
- Hash Move from the TT.
- MVV-LVA to prioritize captures.
- Killer Move per ply to accelerate beta cutoffs.
- History Heuristic for quiet moves.
- Piece-Square Tables for MG/EG positional values.
- Material with MG/EG piece values and tempo bonus.
- Tapered Eval based on game phase.
- Tempo bonus for the side to move.
- Bitboards per color and piece type, plus occupancy for white/black/all.
- Mailbox array for piece-on-square lookups and FEN I/O.
- Zobrist Hashing incremental key for TT/repetition (piece-square, castling, en passant, side).
- Move Generation uses pseudo-legal generation per side; legality is verified by make/unmake in search.
- Attack Tables for pawn, knight, and king attacks.
- Magic Bitboards for sliding piece attacks (rook/bishop/queen).
- Time Management with budgets for increment/movetime and iteration prediction.
- UCI with
Hash,ucinewgame,stop,quit, and FEN support. - Perft via
go perftto validate move generation.
These results are from internal matches and are meant as a quick reference. Opponents are selected from the CCRL (Computer Chess Rating Lists). CCRL is a community rating list that benchmarks engines under standardized conditions and publishes multiple lists for different time controls (e.g., 40/4, 40/15, blitz). The table uses the 40/4 list as of 2025-12-20; 40/4 means 40 moves in 4 minutes. The tests were run on Ubuntu 24.04.3 LTS, Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz, 16 GB RAM. Locally, the matches were run with the smoke test script (scripts/smoke_test_ab.sh) using cutechess time control --tc 40/4 and the UHO 2024 opening book, specifically the 8‑move positions set in the 085–094 Elo band (EPD). The estimated Elo difference (Akerbeltz-1.0.0 minus opponent) and +/- values are taken from the match summary and should be read as rough indicators for this run.
| Engine | Version | Elo | Akerbeltz-1.0.0 vs (W-L-D) | Score | Elo diff (Akerbeltz-1.0.0 +/-) |
|---|---|---|---|---|---|
| Snowy | 0.2 64-bit | 1871 (+20/-20) | 69-287-44 | 0.228 | -212.4 +/- 37.5 |
| Apollo | 1.2.1 64-bit | 1665 (+19/-19) | 119-234-47 | 0.356 | -102.8 +/- 33.3 |
| Shallow Blue | 2.0.0 64-bit | 1572 (+20/-20) | 178-174-48 | 0.505 | 3.5 +/- 32.0 |
| CookieCat | 2012.10.10 64-bit | 1564 (+20/-20) | 205-125-70 | 0.600 | 70.4 +/- 31.5 |
| Athena | 1.0.1 | 1529 (+19/-19) | 215-39-146 | 0.720 | 164.1 +/- 28.1 |
| Minnow | no version | 1446 (+19/-19) | 241-103-56 | 0.672 | 125.0 +/- 33.4 |
Based on these matches, Akerbeltz-1.0.0 lands around ~1615 Elo for this specific pool and time control, which is the key takeaway from the table.
Optional CPU tuning: by default builds are generic. You can pass -DAKERBELTZ_ARCH=native (or e.g. -DAKERBELTZ_ARCH=x86-64-v3) to add -march=<value>.
Note: other toolchains/compilers may work, but the ones listed below are the ones tested.
- Prerequisites: CMake ≥ 3.20, a C++23 compiler (e.g., GCC 13+ or Clang 16+), and a build tool such as
makeorninja. - Configure and build (Release by default):
cmake -S . -B build cmake --build build - Run the engine (UCI). The binary is named
Akerbeltz-<version>(defaultAkerbeltz-1.0.0, override with-DAKERBELTZ_ENGINE_VERSION=...):./build/Akerbeltz-1.0.0
- Tests are OFF by default; enable them with
-DAKERBELTZ_BUILD_TESTS=ONwhen configuring (GoogleTest is fetched automatically).cmake -S . -B build -DAKERBELTZ_BUILD_TESTS=ON cmake --build build - Run tests:
ctest --test-dir build --output-on-failure
- Prerequisites: MSYS2 MINGW64 with GCC (mingw-w64-x86_64-gcc), CMake >= 3.20, and Ninja.
- Configure and build (Release by default):
cmake -S . -B build -G Ninja -DCMAKE_CXX_COMPILER=x86_64-w64-mingw32-g++ cmake --build build - Run the engine (UCI). The binary is named
Akerbeltz-<version>.exe(defaultAkerbeltz-1.0.0.exe, override with-DAKERBELTZ_ENGINE_VERSION=...):./build/Akerbeltz-1.0.0.exe
- Tests are OFF by default; enable them with
-DAKERBELTZ_BUILD_TESTS=ONwhen configuring:cmake -S . -B build -G Ninja -DAKERBELTZ_BUILD_TESTS=ON DCMAKE_CXX_COMPILER=x86_64-w64-mingw32-g++ cmake --build build - Run tests:
ctest --test-dir build --output-on-failure
- UCI (Universal Chess Interface) Protocol is a text protocol used to connect engines with GUIs and tournament tools.
- Implemented UCI commands:
uci: identifies the engine and supported options.isready: synchronization point; repliesreadyok.setoption name Hash value <MB>: sets TT size in MB.ucinewgame: resets internal state for a new game.position: sets the current position and optional move list.position startpos [moves ...]: loads the start position and applies optional moves.position fen <FEN> [moves ...]: loads a FEN and applies optional moves.
go: starts a search with the specified limits.go depth <N>: searches to a fixed depth.go wtime <ms> btime <ms> winc <ms> binc <ms> movestogo <n>: searches with time control.go movetime <ms>: searches for a fixed time per move.go infinite: searches untilstop.
stop: stops the current search.quit: exits the engine.
- Extra commands (non-UCI):
go perft <N>: runs perft and prints the node count at depth N.d: prints the board state (debug helper).
- Examples (UCI):
./build/Akerbeltz-1.0.0 uci isready position startpos go depth 10
position fen r1bqkbnr/pppppppp/2n5/8/3P4/5N2/PPP1PPPP/RNBQKB1R w KQkq - 2 2 moves d4d5 go wtime 300000 btime 300000 winc 2000 binc 2000 movestogo 40
- Example (perft):
position startpos go perft 5
- The engine speaks UCI, so it can be used with any UCI-compatible GUI. The tools listed below are just examples.
- Arena (Windows/Linux):
- Open Arena.
- Go to
Engines → Install New Engine.... - Select
Akerbeltz-<version>(Linux) orAkerbeltz-<version>.exe(Windows) from your build folder. - When prompted, choose UCI as the protocol.
- Configure options like
HashunderEngines → Manage...if needed. - Start a new game and select Akerbeltz as the engine.
- Cute Chess (Linux/Windows/macOS):
- Open Cute Chess and go to the engine manager.
- Add a new engine and point it to
Akerbeltz-<version>(Linux/macOS) orAkerbeltz-<version>.exe(Windows). - Select UCI as the protocol and save the engine.
- Start a game or tournament and pick Akerbeltz as one of the engines.
- Other UCI GUIs (e.g., Banksia, SCID vs. PC) are available on Linux/macOS/Windows:
- Add a new engine and point it to
Akerbeltz-<version>(Linux/macOS) orAkerbeltz-<version>.exe(Windows). - Select UCI as the protocol and adjust options (e.g.,
Hash) if available.
- Add a new engine and point it to
- The shell scripts (
smoke_test_ab.sh,sprt_ci.sh,confirm_ltc.sh) are Bash-based. On Windows, run them via WSL2 or a similar environment. - Those three scripts read engine definitions from
scripts/engines.tsvand write logs toscripts/logs/and PGNs toscripts/pgn/. scripts/engines.tsvis semicolon-separated with columns:name,cmd,proto(optional:uciorxboard/winboard),hash. Ifprotois omitted/blank, it defaults touci. If you want a hash but no proto, keep the empty field:name;cmd;;hash.- Note: Scripts and utilities tested on Ubuntu 22.04.
- Purpose: fast A/B smoke test with cutechess-cli using EPD openings and both colors per position.
- Requirements:
bash,cutechess-cli, standard Unix tools (awk,sed,grep,nproc,stdbuf,tee),scripts/engines.tsv, and an EPD openings file. - Tip: running without parameters prints the script usage/help.
- Usage example:
./scripts/smoke_test_ab.sh --engines scripts/engines.tsv \ --openings scripts/utils/UHO_2024/UHO_2024_+090_+099/UHO_2024_8mvs_+090_+099.epd \ --rounds 10 --tc 3+0.05
- Purpose: A/B SPRT test with cutechess-cli (EPD or PGN openings).
- Requirements:
bash,cutechess-cli, standard Unix tools (awk,nproc,stdbuf,tee),scripts/engines.tsv, and an EPD/PGN openings file. - Tip: running without parameters prints the script usage/help.
- Usage example:
./scripts/sprt_ci.sh --engines scripts/engines.tsv \ --openings scripts/utils/UHO_2024/UHO_2024_+090_+099/UHO_2024_8mvs_+090_+099.epd \ --sprt-elo0 0 --sprt-elo1 5 --tc 10+0.1
- Purpose: long time control confirmation (pairwise or round-robin) with cutechess-cli.
- Requirements:
bash,cutechess-cli, standard Unix tools (awk,sed,grep,nproc,stdbuf,tee),scripts/engines.tsv, and a PGN openings file. - Tip: running without parameters prints the script usage/help.
- Usage example:
./scripts/confirm_ltc.sh --engines scripts/engines.tsv \ --openings scripts/utils/UHO_2024/UHO_2024_+090_+099/UHO_2024_8mvs_+090_+099.pgn \ --rounds 10 --tc 40/300+3
- Purpose: run perft checks against an EPD suite and compare expected node counts.
- Requirements:
python3, a built engine binary that supportsgo perft, and an EPD file (format includes FEN plusD<depth> <nodes>pairs). - Note: you can use
scripts/utils/perftsuite.epd. I did not create this file; I found it online and could not identify the original author, apologies. - Output: prints per-depth results (
OK/ERR), the FEN, a summary with totals, and the log path; writes a timestamped log inresults/. - Input format: EPD lines with a FEN followed by depth/node pairs (e.g.,
... D1 20; D2 400; D3 8902;). - Example EPD lines:
rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1; D1 20; D2 400; D3 8902; r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 1; D1 48; D2 2039; D3 97862; - Usage example:
python3 scripts/perft_suite.py --engine ./build/Akerbeltz-1.0.0 \ --epd path/to/your_suite.epd --depths 1,2,3 --max-positions 20
- Chess Programming Wiki
- Stockfish
- Bluefever Chess Programming in C (YouTube playlist)
- Rustic Chess Engine (Marcel Vanthoor)
- Fast Chess Move Generation with Magic Bitboards (Marcel Vanthoor)
- PeSTO's Evaluation Function (Ronald Friederich)
- Name: Julen Aristondo
- Email: julen_aristondo@hotmail.com
- GitHub
