-
-
Notifications
You must be signed in to change notification settings - Fork 200
Understanding the code
To understand the code base of this project it is a very good start if you already have some understanding of chess engine programming in general or specifically the code base of Stockfish, which is the chess engine this project is based on.
As a starting point to understand the code of Stockfish you can check out the resources listed in its readme. The chess programming wiki contains a lot of information about the techniques used in Stockfish and about Stockfish itself.
Fairy-Stockfish is based on Stockfish and extends it with the support for chess variants in order to get a chess variant engine that can make use of all the search techniques that make Stockfish the strongest chess engine. It is the result of several projects to create Stockfish forks for specific variants like Makruk, Shatranj, and S-Chess, and the desire to merge them into one in order to simplify development and to make the addition of new variants as easy as possible.
The fundamental design decision for the variant support was to make the rule implementation rule/feature-centric and not variant-centric (like the Stockfish fork for lichess), which means that the position representation and move generation consider the individual rules of a chess variant independently so that a variant can simply be defined as a set of such rules like board size, piece types, etc. This generality of course comes at the expense of performance, but on the upside allows very fast implementation of new variants and even the addition of variants at runtime through a variant configuration file.
Furthermore, the generality allows the search and evaluation code to share features between variants with similar rules, e.g., drop variants like crazyhouse and shogi, so that improvements in playing strength usually apply to many variants and do not need to be implemented separately for every one of them. Therefore, and due to making use of Stockfish's powerful search algorithm, Fairy-Stockfish usually is able to play variants at master or even super-human level even if the rules of the variant were user-defined and not known during development, since it can re-use its knowledge from variants with similar rules.
Depending on what you are mostly interested in, there are several areas of the code base that can be clustered topic-wise.
-
variant.h
contains the class definition of a variant object and as such defines the set of available rule options. -
variant.cpp
contains the concrete definition of the built-in variants. -
variants.ini
is an example of a variant configuration file and also contains documentation of the meaning of the variant attributes defined invariant.h
. -
parser.h
/parser.cpp
contain the code for parsing of variant configuration files. -
piece.h
/piece.cpp
define the movements of the piece types.
-
position.h
defines the position object and wraps the access to the variant attributes (seevariant.h
) of a position. -
position.cpp
contains most of the logic for FEN parsing and generation, legality checking and doing/undoing of moves, as well as the variant-specific game end criteria. -
movegen.cpp
generates the pseudo-legal moves for all pieces and therefore also is core part of the variant rule implementations.
The implementation of bitboards and magics for fairy pieces and larger board sizes can be found in:
-
types.h
defines theBitboard
data type as 64 or 128 bit. -
bitboard.h
/bitboard.cpp
implement operations on bitboards and the generation and access of magics for slider move generation. -
magic.h
contains precomputed magics to speed up the startup for architectures without pext support where the computation of magics on the 12x10 board can be slow.
The supported UCI dialects (UCI, UCCI, USI) and the CECP/XBoard protocol are implemented in:
-
uci.h
/uci.cpp
/ucioption.cpp
-
xboard.h
/xboard.cpp
-
partner.h
/partner.cpp
for the partner communication in the CECP protocol for four-player variants (e.g., bughouse).
Code related to position evaluation:
-
evaluate.cpp
is the central place for position evaluation. -
psqt.cpp
modifies the piece values based on variant rules and initializes the piece-square tables. -
pawns.cpp
evaluates pawn structures, also in regards to king safety -
material.cpp
andendgame.cpp
contain code for evaluation of material imbalances and specific endgames.
The search is mostly the same as official Stockfish, but some search techniques are modified or skipped in variants where they do not work well in the way they are used for chess.
-
search.cpp
is the central place for the tree search algorithm. -
movepick.cpp
,tt.cpp
, andtimeman.cpp
are mostly unchanged compared to official Stockfish, but contain some minor tweaks for variants.
In tests/perft.sh
some perft data for variants can be found that is used for CI testing.
Originally started as a separate fork, a python binding is now developed as part of the main repository. It can be used as a python chess variant library for move generation, etc., see, e.g., https://github.com/gbtami/pychess-variants and https://github.com/ianfab/fairyfishtest.
-
pyffish.cpp
contains the python binding code along with a few additional features like SAN/notation generation. -
setup.py
/test.py
(in the root directory) for package installation and testing