Dolphin is a free, open-source UCI chess engine written in C#. It uses bitboards, a modern alpha-beta search and an NNUE neural-network evaluation that was trained from scratch on Dolphin's own self-play games.
You can load it into any chess GUI that speaks UCI (Arena, Cute Chess, BanksiaGUI, ...) and play against it, analyse with it, or run engine-vs-engine matches.
- Author: Nguyễn Viết Huy (Vietnam)
- Language: C# (.NET), single project. Optional Syzygy tablebase support uses the Fathom library (C, MIT), included in
native/ - Protocol: UCI
- License: MIT
- Rating: CCRL Blitz 3448 (±21) for Dolphin 2.2, rank 124 at the time of writing (October 2026, 575 games). See the CCRL Blitz rating list and the Dolphin 2.2 details. Version 2.2.1 plays exactly like 2.2; it only fixes a startup problem in some GUIs.
- Download
- Quick start
- Using Dolphin in a chess GUI
- Troubleshooting
- UCI options
- Command-line tools
- How the engine works
- Training your own network
- Testing
- Project layout
- License
Ready-to-run Windows builds are on the Releases page:
| File | What it is |
|---|---|
Dolphin-<version>-windows-x64.zip |
Recommended. Self-contained: includes its own .NET runtime, nothing to install. Keep all files of the folder together. |
Dolphin-<version>-windows-x64-requires-dotnet.zip |
Small package for machines that already have the .NET Runtime 5.0 or newer. Keep the four files Dolphin2.exe, Dolphin2.dll, Dolphin2.deps.json, Dolphin2.runtimeconfig.json together. |
In both packages the neural network is embedded in the program, so no separate network file is needed. Unzip, then load Dolphin2.exe into your GUI as a UCI engine.
On Linux or macOS, build from source (see below).
| What | Version |
|---|---|
| .NET SDK | 5.0 or newer (to build) |
| .NET runtime | 5.0 or newer, to run a framework-dependent build (it rolls forward to newer runtimes automatically). Not needed for the self-contained release package. |
| CPU | 64-bit x86 (x64). CPUs with AVX2 get a fast NNUE path; older x64 CPUs fall back to a slower scalar path. |
| OS | Windows (tested). Linux and macOS on x64 should also work through dotnet, but have not been tested yet. |
git clone https://github.com/aiagentvn/dolphin.git
cd dolphin
dotnet build -c ReleaseThe engine is created at:
bin/Release/net5.0/Dolphin2.exe (Windows)
bin/Release/net5.0/Dolphin2.dll (any OS: run with "dotnet Dolphin2.dll")
The neural network file dolphin.nnue in the repository root is embedded into the program during the build, so the executable works on its own. You do not need to copy the network next to it.
Note: the project targets .NET 5. If you build with a newer SDK (6, 7, 8, ...), you may see warning
NETSDK1138saying .NET 5 is out of support. This is expected: the build still succeeds and the SDK downloads the .NET 5 reference pack automatically.
cd bin/Release/net5.0
Dolphin2.exe perft 5 # move generator self-check, must print "Nodes searched: 4865609"
Dolphin2.exe bench # fixed search benchmark, prints node count and speed (nodes/second)powershell -ExecutionPolicy Bypass -File build-release.ps1This builds into release/Dolphin2/, verifies that the network is embedded correctly, and runs a short test search. Copy that folder wherever you like.
Arena
Engines→Install New Engine...- Select
Dolphin2.exefrom the unzipped release folder (or fromrelease/Dolphin2/if you built it yourself) and choose the UCI type. - Optional:
Engines→Configureto change Hash, Threads, etc. (see below).
Cute Chess (GUI or cutechess-cli)
Add a new engine, set the command to the path of Dolphin2.exe and the protocol to UCI.
Dolphin has no built-in opening book. Use your GUI's book if you want varied openings.
The engine does not move and loses on time from the first move.
Open a command prompt in the engine folder, run Dolphin2.exe and type uci. You should see uciok.
The library 'hostpolicy.dll' ... runtimeconfig.json was not found: you are using the package that requires .NET and one of its four files is missing. Copy the whole folder again.- A message that the framework
Microsoft.NETCore.Appwas not found: the .NET Runtime is not installed. Install it, or use the self-contained package. - Windows reports a missing DLL: you are using the self-contained package and not all files were copied. Copy the whole folder again.
The GUI adds the engine without its name, author or options (for example in ChessGUI). Versions up to 2.2.0 crashed at startup when a GUI started the engine without a console window. This is fixed in 2.2.1; please update.
The engine loses on time in very fast games.
Increase the UCI option Move Overhead (for example to 100–200 ms).
| Option | Default | Description |
|---|---|---|
Hash |
64 (MB) | Size of the transposition table. 256–1024 MB is a good choice for long games. |
Threads |
1 | Number of search threads (Lazy SMP). Set it to the number of physical CPU cores. When two engines play each other on one machine, keep the total threads of both engines at or below the number of cores. |
Move Overhead |
50 (ms) | Time reserved per move for GUI/communication delays. Increase to 100–200 if the engine loses on time. |
Ponder |
false | Think on the opponent's time (supports go ponder / ponderhit). |
Clear Hash |
– | Empties the transposition table. |
UseNNUE |
true | Use the neural network. When off, Dolphin uses its hand-written evaluation (much weaker). |
EvalFile |
dolphin.nnue |
Load a different network file. The default network is embedded in the program. |
SyzygyPath |
<empty> |
Folder(s) with Syzygy endgame tablebases (.rtbw/.rtbz files). Separate several folders with ; on Windows. Empty = no tablebases. |
SyzygyProbeDepth |
1 | Probe the tablebases in the search only at this depth or more. Raise it if the tables are on a slow disk. |
From version 2.4 Dolphin can use Syzygy endgame tablebases. With up to 5 pieces the tables take about 1 GB; with 6 pieces, about 150 GB. Download them (for example from https://tablebase.sesse.net/syzygy/) and set SyzygyPath to the folder. The engine then:
- picks root moves that keep the theoretical result (winning moves that make progress, drawing moves, or the longest defence);
- uses win/draw/loss results inside the search after captures and pawn moves;
- reports
tbhitsin itsinfooutput.
Probing goes through fathom.dll, which is included in the Windows packages and in native/win-x64/. If the library is missing, Dolphin still plays normally without tablebases. To rebuild the library: native/build-fathom.ps1 (Visual Studio / Build Tools), or native/build-fathom.sh on Linux (not tested yet).
Besides the normal UCI mode, the executable accepts a few commands. They can be given as program arguments (Dolphin2.exe bench) or typed in UCI mode.
| Command | What it does |
|---|---|
bench [depth] |
Searches a fixed set of positions (default depth 13). Prints total nodes and speed. Used as a regression check: the node count only changes when the search changes. |
perft <depth> |
Counts all legal move sequences from the current position and prints a per-move breakdown. Verifies the move generator. |
d |
Prints the current board (UCI mode). |
eval |
Prints the hand-written and NNUE evaluation of the current position (UCI mode). |
nnuecheck |
Verifies that the incrementally updated NNUE matches a full recomputation (UCI mode). |
datagen ... |
Generates self-play training data (see below). |
train ... |
Trains an NNUE network (see below). |
export <in.f32> <out.nnue> |
Converts a float network checkpoint into the quantized .nnue format the engine loads. |
- 64-bit bitboards, with magic bitboards for sliding pieces (the magic numbers are generated at start-up).
- Full legal move generation, including castling, en passant and promotions. Verified with
perftagainst a reference engine on many tricky positions (see Testing). - Zobrist hashing for the transposition table and repetition detection.
- Principal Variation Search (alpha-beta) with iterative deepening and aspiration windows
- Lock-free shared transposition table
- Quiescence search; Static Exchange Evaluation (SEE) for move ordering and pruning
- Pruning: null-move pruning, reverse futility pruning, razoring, futility pruning, late move pruning, ProbCut
- Reductions and extensions: late move reductions (LMR), singular extensions, internal iterative reduction (IIR)
- Move ordering: hash move, SEE-sorted captures, killer moves, history, countermove and continuation history
- Correction history: the static evaluation is corrected by what earlier searches found in similar positions (pawn structure, each side's other pieces, recent moves)
- Multi-threading with Lazy SMP
- Time management for all common time controls, plus pondering
- Designed to avoid memory allocation during search (the hot code uses
unsafeC#)
Dolphin has two evaluation functions:
-
NNUE (default). A small neural network:
- input: 768 features (12 piece types × 64 squares), seen from both sides' perspectives
- one hidden layer of 384 neurons per perspective, SCReLU activation
- 8 output buckets, selected by the number of pieces on the board
- updated incrementally as moves are made, with an AVX2 fast path
The network was trained only on positions from Dolphin's own self-play games. No network or code from other engines was used.
-
Hand-written evaluation (used when
UseNNUEis off, and to generate the very first training data). Tapered middlegame/endgame scores with piece-square tables, mobility, knight and bishop outposts, rooks on open/half-open files and the 7th rank, pawn structure (isolated, doubled, backward, connected and passed pawns, cached in a pawn hash table), king safety (pawn shelter, attacks near the king) and king activity in the endgame.
The complete training pipeline is built into the engine. Nothing else needs to be installed.
1. Generate self-play data
Dolphin2.exe datagen threads=14 nodes=5000 games=100000 out=data/gen1.bin book=tools/openings8.epd| Argument | Meaning |
|---|---|
threads |
Number of games played in parallel |
nodes |
Search nodes per move (5000 is a good speed/quality balance) |
games |
How many games to play |
out |
Output file (positions + game results) |
book |
Starting positions in EPD format, for variety |
seed, hash |
Random seed and hash size per game (optional) |
hours |
Stop by itself after this many hours (optional) |
softnodes |
Soft node limit: each move finishes the current search iteration once this many nodes are reached (hard limit hardnodes, default 20× softnodes). Without it, nodes is a hard limit |
verify |
Nodes used to check that a starting position is balanced (default: the node limit) |
book2 |
A second file of starting positions (EPD), for example positions taken from real games; then a third of the games start from it |
weighted |
weighted=1: the random opening moves pick a piece type first (pawns most often), so random openings look more natural |
Data is appended to the output file, so a stopped run can simply be started again. Ctrl+C stops after the games in progress; an incomplete record left by a killed run is removed at the next start, and the run also stops when less than 2 GB of disk space is left.
The first round of data for the bundled network was generated with the hand-written evaluation. Later rounds used the newest network, so each generation of data is of higher quality than the previous one.
2. Train
Dolphin2.exe train data=data/gen1.bin,data/gen2.bin hidden=384 epochs=25 threads=8 lambda=0 out=nets/my.nnue| Argument | Default | Meaning |
|---|---|---|
data |
– | One or more data files, comma separated |
hidden |
256 | Hidden layer size (the bundled network uses 384) |
epochs |
30 | Training passes over the data |
batch |
16384 | Batch size |
lr |
0.001 | Learning rate |
lambda |
0.3 | Blend between search score (0) and game result (1) as the training target |
threads |
CPU count − 2 | Training threads |
max |
all | Use at most this many positions |
resume |
– | Continue from a .f32 checkpoint |
mirror |
0 | mirror=1 adds horizontally mirrored positions |
out |
dolphin.nnue |
Output network. A float checkpoint <out>.f32 is saved too. |
The bundled dolphin.nnue was trained this way: about 175 million self-play positions from eight generations of data, each generation played with the best network available at the time, hidden size 384, 25 epochs, lambda=0 (the target is the search score only), mirror=1. The networks up to version 2.7 used lambda=0.35; with the same data and settings, lambda=0 scored +32.3 ± 14.1 Elo at 20,000 nodes per move and +24.7 ± 12.8 Elo at 10+0.1. Generations one to six, and the first part of the seventh, were searched at 5000 nodes per move. The sixth to eighth generations were played with the environment variable DOLPHIN_P_MATSCALE=0, which turns off the material scaling of the evaluation, so the stored scores are not scaled twice. Part of the seventh generation (36.7 million positions, version 2.6) and all of the eighth generation (84.5 million positions, version 2.7) used softnodes=2500 verify=50000 weighted=1 and a book2 file of starting positions taken from Dolphin's own games on the CCRL rating lists.
3. Use the network
Either set the UCI option EvalFile to your file, or copy it over dolphin.nnue in the repository root and rebuild, so it gets embedded in the executable:
powershell -ExecutionPolicy Bypass -File build-release.ps1 -Net nets/my.nnueThe tools/ folder contains the Python scripts used during development (they need pip install python-chess). See tools/README.md.
perft_check.py: compares Dolphin's perft counts with a reference engine (Stockfish) on 20 difficult positions (en passant pins, castling through check, promotions, ...).match.py: plays engine-vs-engine matches in parallel and reports the Elo difference with error bars, LOS and an SPRT result. Search and evaluation changes were tested with matches like this before they were kept.bench: the node count ofDolphin2.exe benchis a quick check that a change did not alter the search by accident.
Stockfish was used only as an external tool (reference perft results and a sparring partner). Dolphin does not contain any Stockfish code or networks.
Version 2.8 has a new network trained on the same 175 million self-play positions as 2.7, with one change in training: the target is now the search score alone (lambda=0) instead of a blend of search score and game result (lambda=0.35). The network size and the search are unchanged from 2.7, and every training position was played and scored by Dolphin itself. Against the 2.7 network in the same engine it scored +32.3 ± 14.1 Elo at 20,000 nodes per move (1403 games, SPRT) and +24.7 ± 12.8 Elo at 10+0.1 (1000 games). Against the 2.7 release package in cutechess-cli at 10+0.1 it scored 105-90-305, +10.4 ± 19.0 Elo (500 games, both with Syzygy 3-4-5 piece tablebases). In 820 games there were no time losses, crashes or illegal moves. The bench node count of 2.8 is 1603861. Full numbers are in the release notes.
Version 2.7 has a new network trained on about 175 million self-play positions (eight generations). It is the same size as before, and every training position was played and scored by Dolphin itself. The search is unchanged from 2.6. Against the 2.6 network in the same engine it scored +25.3 ± 12.1 Elo at 20,000 nodes per move (1829 games) and +20.5 ± 12.7 Elo at 10+0.1 (1000 games). Against the 2.6 release package in cutechess-cli at 10+0.1 it scored 109-93-298, +11.1 ± 19.3 Elo (500 games, both with Syzygy 3-4-5 piece tablebases). In 820 games there were no time losses, crashes or illegal moves. The bench node count of 2.7 is 1410872. Full numbers are in the release notes.
Version 2.6 has a new network trained on about 91 million self-play positions (seven generations). It is the same size as before, and every training position was played and scored by Dolphin itself. The search is unchanged from 2.5. Against the 2.5 network in the same engine it scored +25.2 ± 12.4 Elo at 20,000 nodes per move (1795 games) and +30.2 ± 13.6 Elo at 10+0.1 (981 games). Against the 2.5 release package in cutechess-cli at 10+0.1 it scored 130-89-281, +28.6 ± 20.1 Elo (500 games, both with Syzygy 3-4-5 piece tablebases). In 1020 games there were no crashes or illegal moves; 2.6 lost 3 games on time in one 5+0.05 run (games 51, 52 and 54 of 100, each with less than 0.2 s left), and two repeats of that run (300 games) had none. The bench node count of 2.6 is 1856356. Full numbers are in the release notes.
Version 2.5 has a new network trained on about 54 million self-play positions. It is the same size as before and no data from other engines was used. The search is unchanged from 2.4. Against the 2.4 network in the same engine it scored +16.2 ± 11.7 Elo at 20,000 nodes per move (2000 games) and +18.8 ± 12.9 Elo at 10+0.1 (1000 games). Against the 2.4 release package in cutechess-cli at 10+0.1 it scored 119-91-290, +19.5 ± 19.7 Elo (500 games, both with Syzygy 3-4-5 piece tablebases). In 720 games there were no time losses, crashes or illegal moves. The bench node count of 2.5 is 1551453. Full numbers are in the release notes.
Version 2.3 keeps the same network and changes only the search. It adds five things:
- a correction history from five sources;
- no reverse futility pruning at TT-PV nodes or when the hash move is quiet;
- an evaluation that is scaled down as material comes off the board;
- fail-high scores pulled toward beta at non-PV nodes;
- a penalty for the opponent's previous move when it is refuted at once.
Each change was kept only after a self-play SPRT test at a fixed 40,000 nodes per move; about fifteen other ideas were tested and rejected. In cutechess-cli against the 2.2.1 release package:
| Time control | Games | Result (W-L-D) | Elo |
|---|---|---|---|
| 10+0.1 | 500 | 145-56-299 | +62.5 ± 19.1 |
| 40 moves / 30 s | 100 | 22-13-65 | |
| 5+0.05, engine restarted every game | 100 | 31-19-50 | |
| 10+0.1, 4 threads, 1 GB hash | 20 | 2-3-15 |
In 820 games, including a self-contained vs framework-dependent check, there were no time losses, crashes or illegal moves. The bench node count of 2.3 is 1717319. Full numbers are in the release notes.
Version 2.2 keeps the 2.1 network and changes only the search: the opponent's previous quiet move is rewarded or penalised by how much it changed the static evaluation, refuted moves receive heavier history penalties, and the transposition table is prefetched after every move. Each change was kept only after a self-play SPRT test at fixed nodes; three further ideas were tested and rejected. The combined build scored +48.5 ± 17.1 Elo against 2.1 at 8+0.08 (519 games, 1 thread, tools/match.py), and in cutechess-cli against the 2.1.0 release package: 10+0.1 160-62-278, +69.0 ± 20.2 Elo (500 games), 40 moves/30 s 19-15-66 (100 games), 5+0.05 with the engine restarted every game 42-11-47 (100 games), 10+0.1 with 4 threads and 1 GB hash 6-2-12 (20 games). No time losses, crashes or illegal moves. The bench node count of 2.2 is 1627584. Full numbers are in the release notes.
Before release, the downloadable packages were played against Dolphin 2.0 with cutechess-cli 1.5.1 on an Intel i7-11800H: 1460 games at 10+0.1, 40 moves in 30 s, 2 min + 1 s, with 4 threads and 1 GB hash, and with the engine restarted for every game. There were no time losses, crashes or illegal moves. At 10+0.1 (1000 games, 1 thread) version 2.1 scored +47.9 ± 16.2 Elo against 2.0. Full numbers are in the release notes.
Dolphin2.csproj project file (builds the engine, embeds dolphin.nnue)
dolphin.nnue the default neural network
build-release.ps1 builds a ready-to-use release folder
src/
Uci.cs UCI protocol and command-line commands
Types.cs basic types and constants
Bitboards.cs bitboard helpers, magic bitboard attacks
Position.cs board state, make/unmake move, Zobrist keys
MoveGen.cs legal move generation
MovePicker.cs staged move ordering
SEE.cs static exchange evaluation
Search.cs the alpha-beta search
SearchManager.cs threads (Lazy SMP), time management, pondering
TT.cs transposition table
Eval.cs hand-written evaluation
NNUE.cs neural network evaluation
DataGen.cs self-play data generation
Trainer.cs network training and export
Bench.cs, Perft.cs benchmark and perft
Tune.cs lets search parameters be overridden by DOLPHIN_P_<NAME>
environment variables, for A/B testing without rebuilding
Syzygy.cs Syzygy tablebase probing (through the Fathom library)
native/ Fathom (unmodified, MIT, see native/fathom/LICENSE), a small C wrapper,
build scripts and the prebuilt Windows library win-x64/fathom.dll
tools/ development scripts (perft check, matches, opening set)
Dolphin is released under the MIT License. You are free to use, modify and redistribute it, including in your own projects, as long as the copyright notice is kept.
The Syzygy probing code in native/fathom/ is Fathom by Ronald de Man, basil00 and Jon Dart, also under the MIT License (see native/fathom/LICENSE).
Contributions, bug reports and match results are welcome. Please open an issue or a pull request.