Skip to content
aiagentvnPublic

About

Dolphin - a free UCI chess engine in C# (.NET) with a self-trained NNUE neural network, bitboards, modern alpha-beta search, Lazy SMP and a built-in self-play training pipeline. Plays in Arena, Cute Chess and any UCI GUI.

Topics

Resources

Stars

3 stars

Watchers

0 watching

Forks

Latest commit

 

History

17 Commits

Folders and files

Repository files navigation

Dolphin Chess Engine

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.

Contents


Download

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).


Quick start

Requirements

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.

Build

git clone https://github.com/aiagentvn/dolphin.git
cd dolphin
dotnet build -c Release

The 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 NETSDK1138 saying .NET 5 is out of support. This is expected: the build still succeeds and the SDK downloads the .NET 5 reference pack automatically.

Check that it works

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)

Build a ready-to-use release folder (Windows)

powershell -ExecutionPolicy Bypass -File build-release.ps1

This builds into release/Dolphin2/, verifies that the network is embedded correctly, and runs a short test search. Copy that folder wherever you like.


Using Dolphin in a chess GUI

Arena

  1. Engines → Install New Engine...
  2. Select Dolphin2.exe from the unzipped release folder (or from release/Dolphin2/ if you built it yourself) and choose the UCI type.
  3. Optional: Engines → Configure to 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.


Troubleshooting

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.App was 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).


UCI options

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.

Syzygy tablebases

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 tbhits in its info output.

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).


Command-line tools

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.

How the engine works

Board and move generation

  • 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 perft against a reference engine on many tricky positions (see Testing).
  • Zobrist hashing for the transposition table and repetition detection.

Search

  • 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 unsafe C#)

Evaluation

Dolphin has two evaluation functions:

  1. 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.

  2. Hand-written evaluation (used when UseNNUE is 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.


Training your own network

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.nnue

Testing

The 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 of Dolphin2.exe bench is 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.

Changes in version 2.8

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.

Changes in version 2.7

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.

Changes in version 2.6

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.

Changes in version 2.5

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.

Search changes in version 2.3

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.

Search changes in version 2.2

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.

Release testing (version 2.1)

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.


Project layout

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)

License

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.

About

Dolphin - a free UCI chess engine in C# (.NET) with a self-trained NNUE neural network, bitboards, modern alpha-beta search, Lazy SMP and a built-in self-play training pipeline. Plays in Arena, Cute Chess and any UCI GUI.

Topics

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages