Photon is a UCI-compliant chess engine written from scratch in C++! It uses Principal-Variation Search, tapered piece-square table static evaluation, and the following search optimizations:
- Iterative Deepening
- Transposition Table (also for move ordering)
- Quiescence Search
- Null-Move Pruning
- Aspiration Windows
- MVV-LVA capture move ordering
- Killer Heuristic
- History Heuristic (with history gravity and malus)
- Static Exchange Evaluation (for move ordering and quiescence search pruning)
- Soft/Hard Time Management
- Lazy Legal Move Filtering
- Late Move Reduction
- Pondering
- Reverse Futility Pruning
Play against it in your browser here!
The following environment variables can be used to configure non-search behavior.
| Variable | Description | Default |
|---|---|---|
PHOTON_DISABLE_LOGGING |
If set (to any value), disables writing logs to a file. | unset (logging on) |
PHOTON_LOG_FILE |
Path to the log file. Ignored when PHOTON_DISABLE_LOGGING is set. |
photonlog.txt |
PHOTON_PROFILE_FILE |
Path to the profiler output file. Only used in builds configured with -DPHOTON_PROFILING_ENABLED=ON. |
photon_profile.txt |
PhotonChess can compile to WASM and run in your browser. Check it out here! The web version of PhotonChess runs at a slightly reduced strength, compile and play locally for full strength.
You can play against Photon in a GUI with cutechess. Install it or build it from source, add Photon as an engine in the preferences (after building Photon), and then start a new game!
Photon is developed with C++20. To configure and build:
mkdir -p build ; cd build
cmake ..
cmake --build . -jBy default, photon is compiled in release mode with compiler optimizations enabled. To compile in debug mode with debug symbols, add -DCMAKE_BUILD_TYPE=Debug.
The following flags can be passed to the CMake configure command (e.g. cmake .. -DPHOTON_TTABLE_SIZE=24).
| Flag | Description | Default |
|---|---|---|
PHOTON_PROFILING_ENABLED |
Enable the built-in scoped profiler. Adds per-scope timing overhead. | OFF |
PHOTON_TTABLE_SIZE |
Log2 of the number of transposition-table entries (2^N entries). |
22 native, 20 WebAssembly |
Photon is tested at several levels, from fast unit tests to full engine-vs-engine matches.
Unit tests are written with Catch2 and compiled into a single tests executable as part of the normal build. From the build directory, run all tests with:
./testsYou can filter by test name or tag, e.g. ./tests "[core]" to run only the core tests.
Perft (performance test) counts the number of leaf nodes reachable at a given depth from a set of known positions, validating both move generation correctness and speed. The correctness tests run as part of the normal ./tests run, while the timing benchmarks are tagged [!benchmark] and are hidden by default. Run them explicitly with:
./tests "[perft]" --benchmark-samples 10The Eigenmann Rapid Engine Test (ERET) measures engine strength by having Photon solve a suite of tactical/positional puzzles over UCI. See tools/README.md for setup and usage.
An SPRT (Sequential Probability Ratio Test) plays many games between two commits to determine, with statistical confidence, whether one is stronger than the other. See tools/README.md for setup and usage.
Photon can be built with profiling enabled, for debugging. To do so, add -DPHOTON_PROFILING_ENABLED=ON to the configure command. When running, the profiler output will be saved to photon_profile.txt by default.
See .clang-format for style rules. Code can be automatically formated with clang-format, or running ./format.sh. Note that clang-format v16 or greater is required.
Photon can also be compiled to WebAssembly so you can play it in a browser. The web UI talks to the engine over UCI (including pondering) and is built as a static site.
The WASM engine requires the Emscripten SDK (emcmake / emcc) and Node.js. Install Emscripten if you do not already have it:
git clone https://github.com/emscripten-core/emsdk.git ~/emsdk
cd ~/emsdk
./emsdk install latest
./emsdk activate latest
source ~/emsdk/emsdk_env.shsource ~/emsdk/emsdk_env.sh must be run in each new shell (or added to ~/.bashrc). Then from the repository root:
./scripts/build-web.shThis compiles the engine to web/public/engine/ and the site to web/dist/.
After compiling the WASM engine at least once:
cd web
npm install
npm run devWhen running locally, the Vite dev server sends Cross-Origin Isolation headers (COOP/COEP) so SharedArrayBuffer and pthreads work locally. When hosting on a server, some providers (e.g. GitHub Pages) do not send Cross-Origin Isolation headers, so the frontend uses coi-serviceworker to add them.