diff --git a/Fairy-Stockfish-master/.gitattributes b/Fairy-Stockfish-master/.gitattributes
new file mode 100644
index 0000000000000000000000000000000000000000..b0ff81123acece91bf17d3254b245b0fad95ea29
--- /dev/null
+++ b/Fairy-Stockfish-master/.gitattributes
@@ -0,0 +1 @@
+README.md merge=ours
diff --git a/Fairy-Stockfish-master/.github/FUNDING.yml b/Fairy-Stockfish-master/.github/FUNDING.yml
new file mode 100644
index 0000000000000000000000000000000000000000..6c865b035be6d4bc9fd684b27d749a53b453a26c
--- /dev/null
+++ b/Fairy-Stockfish-master/.github/FUNDING.yml
@@ -0,0 +1,2 @@
+# These are supported funding model platforms
+github: ianfab
diff --git a/Fairy-Stockfish-master/.github/dependabot.yml b/Fairy-Stockfish-master/.github/dependabot.yml
new file mode 100644
index 0000000000000000000000000000000000000000..be006de9a1ae3b9628e796c74277cd6d61e0a34a
--- /dev/null
+++ b/Fairy-Stockfish-master/.github/dependabot.yml
@@ -0,0 +1,13 @@
+# Keep GitHub Actions up to date with GitHub's Dependabot...
+# https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot
+# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#package-ecosystem
+version: 2
+updates:
+ - package-ecosystem: github-actions
+ directory: /
+ groups:
+ github-actions:
+ patterns:
+ - "*" # Group all Actions updates into a single larger pull request
+ schedule:
+ interval: weekly
diff --git a/Fairy-Stockfish-master/.github/workflows/fairy.yml b/Fairy-Stockfish-master/.github/workflows/fairy.yml
new file mode 100644
index 0000000000000000000000000000000000000000..3dfb53ca6b894818ce2954315645520b92e7f728
--- /dev/null
+++ b/Fairy-Stockfish-master/.github/workflows/fairy.yml
@@ -0,0 +1,93 @@
+name: fairy
+on:
+ push:
+ branches:
+ - master
+ pull_request:
+ branches:
+ - master
+jobs:
+ fairy:
+ name: ${{ matrix.config.name }}
+ runs-on: ${{ matrix.config.os }}
+ env:
+ COMPILER: ${{ matrix.config.compiler }}
+ COMP: ${{ matrix.config.comp }}
+ CXXFLAGS: "-Werror"
+ strategy:
+ matrix:
+ config:
+ - {
+ name: "Ubuntu 24.04 GCC",
+ os: ubuntu-24.04,
+ compiler: g++,
+ comp: gcc,
+ run_expensive_tests: true
+ }
+ - {
+ name: "Ubuntu 24.04 Clang",
+ os: ubuntu-24.04,
+ compiler: clang++,
+ comp: clang,
+ run_expensive_tests: false
+ }
+
+ defaults:
+ run:
+ working-directory: src
+ steps:
+ - uses: actions/checkout@v6
+ with:
+ fetch-depth: 0
+
+ - name: Download required packages
+ run: |
+ sudo apt update
+ sudo apt install expect valgrind g++-multilib
+
+ - name: Download the used network from the fishtest framework
+ run: |
+ make net
+
+ - name: Test NNUE
+ run: |
+ make clean
+ make -j2 ARCH=x86-64 nnue=yes debug=yes build
+ ./stockfish bench
+
+ - name: Test NNUE largeboards
+ run: |
+ make clean
+ make -j2 ARCH=x86-64 largeboards=yes nnue=yes debug=yes build
+ ./stockfish bench
+
+ - name: Build all variants
+ run: |
+ make clean
+ make -j2 ARCH=x86-64 largeboards=yes all=yes debug=yes build
+
+ - name: Test protocols
+ run: |
+ ../tests/protocol.sh
+
+ - name: Test variants.ini
+ run: |
+ ! ./stockfish check variants.ini 2>&1 >/dev/null | grep -v "Parsing variant"
+
+ - name: Test variant perft
+ run: |
+ ../tests/perft.sh all
+
+ - name: Test variant bench
+ run: |
+ ./stockfish bench xiangqi
+ ./stockfish bench shogi
+ ./stockfish bench capablanca
+ ./stockfish bench sittuyin
+
+ - name: Test 32bit largeboards
+ run: |
+ if [[ "$COMP" == "gcc" ]]; then export EXTRACXXFLAGS=-Wno-class-memaccess; fi
+ make clean
+ make -j2 ARCH=x86-32 largeboards=yes build
+ ../tests/perft.sh largeboard
diff --git a/Fairy-Stockfish-master/.github/workflows/ffishjs.yml b/Fairy-Stockfish-master/.github/workflows/ffishjs.yml
new file mode 100644
index 0000000000000000000000000000000000000000..a7644db3b1a96e872eb1fc4dd60867c4f16e8bc5
--- /dev/null
+++ b/Fairy-Stockfish-master/.github/workflows/ffishjs.yml
@@ -0,0 +1,90 @@
+name: ffishjs
+
+on:
+ push:
+ branches: [ master ]
+ pull_request:
+ branches: [ master ]
+
+env:
+ EM_VERSION: 1.39.16
+ EM_CACHE_FOLDER: 'emsdk-cache'
+
+jobs:
+ test:
+ runs-on: ubuntu-24.04
+
+ strategy:
+ matrix:
+ node-version: [12.x]
+
+ steps:
+ - uses: actions/checkout@v6
+ - name: Setup cache
+ id: cache-system-libraries
+ uses: actions/cache@v5
+ with:
+ path: ${{env.EM_CACHE_FOLDER}}
+ key: emsdk-${{env.EM_VERSION}}-${{ runner.os }}
+ - uses: mymindstorm/setup-emsdk@v16
+ with:
+ version: ${{env.EM_VERSION}}
+ actions-cache-folder: ${{env.EM_CACHE_FOLDER}}
+ - name: Use Node.js ${{ matrix.node-version }}
+ uses: actions/setup-node@v6
+ with:
+ node-version: ${{ matrix.node-version }}
+ - name: Build ffishjs
+ working-directory: src
+ run: make -f Makefile_js build debug=yes
+ - name: Install dependencies
+ working-directory: tests/js
+ run: npm install
+ - name: Run unit tests
+ working-directory: tests/js
+ run: npm test
+
+ build:
+ runs-on: ubuntu-24.04
+ needs: [test] #Building process must start after successful testing process
+
+ strategy:
+ matrix:
+ node-version: [12.x]
+
+ steps:
+ - uses: actions/checkout@v6
+ - name: Setup cache
+ id: cache-system-libraries
+ uses: actions/cache@v5
+ with:
+ path: ${{env.EM_CACHE_FOLDER}}
+ key: emsdk-${{env.EM_VERSION}}-${{ runner.os }}
+ - uses: mymindstorm/setup-emsdk@v16
+ with:
+ version: ${{env.EM_VERSION}}
+ actions-cache-folder: ${{env.EM_CACHE_FOLDER}}
+ - name: Use Node.js ${{ matrix.node-version }}
+ uses: actions/setup-node@v6
+ with:
+ node-version: ${{ matrix.node-version }}
+ - name: Build ffish.js ES6/ES2015 module
+ working-directory: src
+ run: rm -f ../tests/js/ffish.js & rm -f ../tests/js/ffish.wasm & make -f Makefile_js build es6=yes
+ - name: Upload ffish.js ES6/ES2015 module ZIP archive
+ uses: actions/upload-artifact@v7
+ with:
+ name: ffishjs-es6
+ path: tests/js/*
+ if-no-files-found: error
+ compression-level: 9
+ - name: Build ffish.js standard module
+ working-directory: src
+ run: rm -f ../tests/js/ffish.js & rm -f ../tests/js/ffish.wasm & make -f Makefile_js build
+ - name: Upload ffish.js standard module ZIP archive
+ uses: actions/upload-artifact@v7
+ with:
+ name: ffishjs-standard
+ path: tests/js/*
+ if-no-files-found: error
+ compression-level: 9
diff --git a/Fairy-Stockfish-master/.github/workflows/release.yml b/Fairy-Stockfish-master/.github/workflows/release.yml
new file mode 100644
index 0000000000000000000000000000000000000000..7c037ac05fdb50bdd870a2b5599f52883016731d
--- /dev/null
+++ b/Fairy-Stockfish-master/.github/workflows/release.yml
@@ -0,0 +1,116 @@
+name: Release
+
+on:
+ push:
+ branches: [ master ]
+ pull_request:
+ branches: [ master ]
+
+jobs:
+ windows:
+ strategy:
+ matrix:
+ arch: ["x86-64-bmi2", "x86-64-modern", "x86-64"]
+ runs-on: windows-2022
+
+ steps:
+ - uses: al-cheb/configure-pagefile-action@v1.5
+ with:
+ minimum-size: 16GB
+ maximum-size: 16GB
+ disk-root: "C:"
+
+ - uses: actions/checkout@v6
+
+ - name: make
+ run: cd src && make clean && make -j build COMP=mingw ARCH=${{ matrix.arch }} EXE=fairy-stockfish_${{ matrix.arch }}.exe && strip fairy-stockfish_${{ matrix.arch }}.exe
+
+ - name: make largeboards
+ run: cd src && make clean && make -j build COMP=mingw ARCH=${{ matrix.arch }} EXE=fairy-stockfish-largeboards_${{ matrix.arch }}.exe largeboards=yes && strip fairy-stockfish-largeboards_${{ matrix.arch }}.exe
+
+ - name: make all
+ if: ${{ matrix.arch == 'x86-64' }}
+ run: cd src && make clean && make -j build COMP=mingw ARCH=${{ matrix.arch }} EXE=fairy-stockfish-all_${{ matrix.arch }}.exe largeboards=yes all=yes && strip fairy-stockfish-all_${{ matrix.arch }}.exe
+
+ - uses: actions/upload-artifact@v7
+ with:
+ name: fairy-stockfish-windows-${{ matrix.arch }}
+ path: src/fairy-stockfish*.exe
+ if-no-files-found: error
+ compression-level: 9
+
+ linux:
+ strategy:
+ matrix:
+ arch: ["x86-64-bmi2", "x86-64-modern", "x86-64"]
+ runs-on: ubuntu-24.04
+
+ steps:
+ - uses: actions/checkout@v6
+
+ - name: make
+ run: cd src && make clean && make -j build COMP=gcc ARCH=${{ matrix.arch }} EXE=fairy-stockfish_${{ matrix.arch }} && strip fairy-stockfish_${{ matrix.arch }}
+
+ - name: make largeboards
+ run: cd src && make clean && make -j build COMP=gcc ARCH=${{ matrix.arch }} EXE=fairy-stockfish-largeboards_${{ matrix.arch }} largeboards=yes && strip fairy-stockfish-largeboards_${{ matrix.arch }}
+
+ - name: make all
+ if: ${{ matrix.arch == 'x86-64' }}
+ run: cd src && make clean && make -j build COMP=gcc ARCH=${{ matrix.arch }} EXE=fairy-stockfish-all_${{ matrix.arch }} largeboards=yes all=yes && strip fairy-stockfish-all_${{ matrix.arch }}
+
+ - uses: actions/upload-artifact@v7
+ with:
+ name: fairy-stockfish-linux-${{ matrix.arch }}
+ path: src/fairy-stockfish*
+ if-no-files-found: error
+ compression-level: 9
+
+ macos:
+ strategy:
+ matrix:
+ arch: ["x86-64"]
+ runs-on: macos-15-intel
+
+ steps:
+ - uses: actions/checkout@v6
+
+ - name: make
+ run: cd src && make clean && make -j build COMP=clang ARCH=${{ matrix.arch }} EXE=fairy-stockfish_${{ matrix.arch }} && strip fairy-stockfish_${{ matrix.arch }}
+
+ - name: make largeboards
+ run: cd src && make clean && make -j build COMP=clang ARCH=${{ matrix.arch }} EXE=fairy-stockfish-largeboards_${{ matrix.arch }} largeboards=yes && strip fairy-stockfish-largeboards_${{ matrix.arch }}
+
+ - name: make all
+ run: cd src && make clean && make -j build COMP=clang ARCH=${{ matrix.arch }} EXE=fairy-stockfish-all_${{ matrix.arch }} largeboards=yes all=yes && strip fairy-stockfish-all_${{ matrix.arch }}
+
+ - uses: actions/upload-artifact@v7
+ with:
+ name: fairy-stockfish-macos-${{ matrix.arch }}
+ path: src/fairy-stockfish*
+ if-no-files-found: error
+ compression-level: 9
+
+ macos-m1:
+ strategy:
+ matrix:
+ arch: ["apple-silicon"]
+ runs-on: macos-14
+
+ steps:
+ - uses: actions/checkout@v6
+
+ - name: make
+ run: cd src && make clean && make -j build COMP=clang ARCH=${{ matrix.arch }} EXE=fairy-stockfish_${{ matrix.arch }} && strip fairy-stockfish_${{ matrix.arch }}
+
+ - name: make largeboards
+ run: cd src && make clean && make -j build COMP=clang ARCH=${{ matrix.arch }} EXE=fairy-stockfish-largeboards_${{ matrix.arch }} largeboards=yes && strip fairy-stockfish-largeboards_${{ matrix.arch }}
+
+ - name: make all
+ run: cd src && make clean && make -j build COMP=clang ARCH=${{ matrix.arch }} EXE=fairy-stockfish-all_${{ matrix.arch }} largeboards=yes all=yes && strip fairy-stockfish-all_${{ matrix.arch }}
+
+ - uses: actions/upload-artifact@v7
+ with:
+ name: fairy-stockfish-macos-m1-${{ matrix.arch }}
+ path: src/fairy-stockfish*
+ if-no-files-found: error
+ compression-level: 9
diff --git a/Fairy-Stockfish-master/.github/workflows/stockfish.yml b/Fairy-Stockfish-master/.github/workflows/stockfish.yml
new file mode 100644
index 0000000000000000000000000000000000000000..bc2f5676a2a74156e2d58e7ca0a92f082b22fa9c
--- /dev/null
+++ b/Fairy-Stockfish-master/.github/workflows/stockfish.yml
@@ -0,0 +1,213 @@
+name: Stockfish
+on:
+ push:
+ branches:
+ - master
+ - tools
+ - github_ci
+ pull_request:
+ branches:
+ - master
+ - tools
+jobs:
+ Stockfish:
+ name: ${{ matrix.config.name }}
+ runs-on: ${{ matrix.config.os }}
+ env:
+ COMPILER: ${{ matrix.config.compiler }}
+ COMP: ${{ matrix.config.comp }}
+ CXXFLAGS: "-Werror"
+ strategy:
+ matrix:
+ config:
+ - {
+ name: "Ubuntu 24.04 GCC",
+ os: ubuntu-24.04,
+ compiler: g++,
+ comp: gcc,
+ run_expensive_tests: true
+ }
+ - {
+ name: "Ubuntu 24.04 Clang",
+ os: ubuntu-24.04,
+ compiler: clang++,
+ comp: clang,
+ run_expensive_tests: false
+ }
+
+ defaults:
+ run:
+ working-directory: src
+ steps:
+ - uses: actions/checkout@v6
+ with:
+ fetch-depth: 0
+
+ - name: Download required packages
+ run: |
+ sudo apt update
+ sudo apt install expect valgrind g++-multilib llvm
+
+ - name: Download the used network from the fishtest framework
+ run: |
+ make net
+
+ - name: Extract the bench number from the commit history
+ run: |
+ git log HEAD | grep "\b[Bb]ench[ :]\+[0-9]\{7\}" | head -n 1 | sed "s/[^0-9]*\([0-9]*\).*/\1/g" > git_sig
+ [ -s git_sig ] && echo "benchref=$(cat git_sig)" >> $GITHUB_ENV && echo "Reference bench:" $(cat git_sig) || echo "No bench found"
+
+ - name: Check compiler
+ run: |
+ $COMPILER -v
+
+ - name: Test help target
+ run: |
+ make help
+
+ # x86-32 tests
+
+ - name: Test debug x86-32 build
+ run: |
+ export CXXFLAGS="-Werror -D_GLIBCXX_DEBUG"
+ make clean
+ make -j2 ARCH=x86-32 optimize=no debug=yes build
+ ../tests/signature.sh $benchref
+
+ - name: Test debug x86-32 profile build (Optimization on, All features)
+ run: |
+ export CXXFLAGS=""
+ make clean
+ make -j2 ARCH=x86-32 optimize=yes all=yes largeboards=yes debug=yes profile-build
+
+ - name: Test x86-32 build
+ run: |
+ make clean
+ make -j2 ARCH=x86-32 build
+ ../tests/signature.sh $benchref
+
+ - name: Test x86-32-sse41-popcnt build
+ run: |
+ make clean
+ make -j2 ARCH=x86-32-sse41-popcnt build
+ ../tests/signature.sh $benchref
+
+ - name: Test x86-32-sse2 build
+ run: |
+ make clean
+ make -j2 ARCH=x86-32-sse2 build
+ ../tests/signature.sh $benchref
+
+ - name: Test general-32 build
+ run: |
+ make clean
+ make -j2 ARCH=general-32 build
+ ../tests/signature.sh $benchref
+
+ # x86-64 tests
+
+ - name: Test debug x86-64-modern build
+ run: |
+ export CXXFLAGS="-Werror -D_GLIBCXX_DEBUG"
+ make clean
+ make -j2 ARCH=x86-64-modern optimize=no debug=yes build
+ ../tests/signature.sh $benchref
+
+ - name: Test debug x86-64-modern profile build (Optimization on, All features)
+ run: |
+ export CXXFLAGS=""
+ make clean
+ make -j2 ARCH=x86-64-modern optimize=yes all=yes largeboards=yes debug=yes profile-build
+
+ - name: Test x86-64-modern build
+ run: |
+ make clean
+ make -j2 ARCH=x86-64-modern build
+ ../tests/signature.sh $benchref
+
+ - name: Test x86-64-ssse3 build
+ run: |
+ make clean
+ make -j2 ARCH=x86-64-ssse3 build
+ ../tests/signature.sh $benchref
+
+ - name: Test x86-64-sse3-popcnt build
+ run: |
+ make clean
+ make -j2 ARCH=x86-64-sse3-popcnt build
+ ../tests/signature.sh $benchref
+
+ - name: Test x86-64 build
+ run: |
+ make clean
+ make -j2 ARCH=x86-64 build
+ ../tests/signature.sh $benchref
+
+ - name: Test general-64 build
+ run: |
+ make clean
+ make -j2 ARCH=general-64 build
+ ../tests/signature.sh $benchref
+
+ # x86-64 with newer extensions tests
+
+ - name: Compile x86-64-avx2 build
+ run: |
+ make clean
+ make -j2 ARCH=x86-64-avx2 build
+
+ - name: Compile x86-64-bmi2 build
+ run: |
+ make clean
+ make -j2 ARCH=x86-64-bmi2 build
+
+ - name: Compile x86-64-avx512 build
+ run: |
+ make clean
+ make -j2 ARCH=x86-64-avx512 build
+
+ - name: Compile x86-64-vnni512 build
+ run: |
+ make clean
+ make -j2 ARCH=x86-64-vnni512 build
+
+ - name: Compile x86-64-vnni256 build
+ run: |
+ make clean
+ make -j2 ARCH=x86-64-vnni256 build
+
+ # Other tests
+
+ - name: Check perft and search reproducibility
+ run: |
+ make clean
+ make -j2 ARCH=x86-64-modern build
+ ../tests/perft.sh
+ ../tests/reprosearch.sh
+
+ # Sanitizers
+
+ - name: Run under valgrind
+ if: ${{ matrix.config.run_expensive_tests }}
+ run: |
+ export CXXFLAGS="-O1 -fno-inline"
+ make clean
+ make -j2 ARCH=x86-64-modern debug=yes optimize=no build > /dev/null
+ ../tests/instrumented.sh --valgrind
+ ../tests/instrumented.sh --valgrind-thread
+
+ - name: Run with UB sanitizer
+ if: ${{ matrix.config.run_expensive_tests }}
+ run: |
+ export CXXFLAGS="-O1 -fno-inline"
+ make clean
+ make -j2 ARCH=x86-64-modern sanitize=undefined optimize=no debug=yes build > /dev/null
+ ../tests/instrumented.sh --sanitizer-undefined
+
+ - name: Run with thread sanitizer
+ if: ${{ matrix.config.run_expensive_tests }}
+ run: |
+ export CXXFLAGS="-O1 -fno-inline"
+ make clean
+ make -j2 ARCH=x86-64-modern sanitize=thread optimize=no debug=yes build > /dev/null
+ ../tests/instrumented.sh --sanitizer-thread
diff --git a/Fairy-Stockfish-master/.github/workflows/wheels.yml b/Fairy-Stockfish-master/.github/workflows/wheels.yml
new file mode 100644
index 0000000000000000000000000000000000000000..184f3d22e2ed7f9a14ac30f56bb6ea4c50df0ef7
--- /dev/null
+++ b/Fairy-Stockfish-master/.github/workflows/wheels.yml
@@ -0,0 +1,57 @@
+name: Wheels
+
+on:
+ push:
+ branches:
+ - master
+ pull_request:
+ branches:
+ - master
+
+jobs:
+ build_wheels:
+ name: Build wheels on ${{ matrix.os }}
+ runs-on: ${{ matrix.os }}
+ strategy:
+ matrix:
+ os: [ubuntu-24.04, windows-2022, macos-14]
+
+ steps:
+ - uses: actions/checkout@v6
+
+ # Used to host cibuildwheel
+ - uses: actions/setup-python@v6
+
+ - name: Install cibuildwheel
+ run: python -m pip install cibuildwheel==3.4.0
+
+ - name: Build wheels
+ run: python -m cibuildwheel --output-dir wheelhouse
+ # to supply options, put them in 'env', like:
+ env:
+ MACOSX_DEPLOYMENT_TARGET: "10.14"
+ CIBW_ARCHS_MACOS: "x86_64 arm64"
+ CIBW_SKIP: "pp* *-win32 *-manylinux_i686 *-musllinux_* cp36-* cp37-* cp38"
+ CIBW_TEST_COMMAND: python {project}/test.py
+
+ - uses: actions/upload-artifact@v7
+ with:
+ name: dist-wheel-${{ matrix.os }}
+ path: ./wheelhouse/*.whl
+
+ build_sdist:
+ name: Build source distribution
+ runs-on: ubuntu-24.04
+ steps:
+ - uses: actions/checkout@v6
+ - uses: actions/setup-python@v6
+ with:
+ python-version: '3.9'
+
+ - name: Build sdist
+ run: python setup.py sdist
+
+ - uses: actions/upload-artifact@v7
+ with:
+ name: dist-source
+ path: dist/*.tar.gz
diff --git a/Fairy-Stockfish-master/.gitignore b/Fairy-Stockfish-master/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..ebfe03307acf816fc005d645927f00da8f5d3704
--- /dev/null
+++ b/Fairy-Stockfish-master/.gitignore
@@ -0,0 +1,43 @@
+# Ignore binaries in src/ that have no extension
+/src/*
+!/src/*.*
+!/src/*/
+
+# Files from build
+**/*.o
+**/*.s
+src/.depend
+
+# Built binary
+src/stockfish*
+src/-lstdc++.res
+
+# Neural network for the NNUE evaluation
+**/*.nnue
+
+
+# Build/test artifacts
+*.exe
+tests/syzygy
+
+# ffishjs
+tests/js/node_modules
+ffish.js
+*.wasm
+
+# pyffish
+venv
+*.so
+pyffish.egg-info
+__pycache__
+*.pyc
+
+# test artifacts
+tests/*.exp
+src/*.log
+src/*.epd
+src/*.txt
+
+# IDEs
+.vscode
+.idea
\ No newline at end of file
diff --git a/Fairy-Stockfish-master/AGENTS.md b/Fairy-Stockfish-master/AGENTS.md
new file mode 100644
index 0000000000000000000000000000000000000000..611774a0b8b2935999b269fb55867f20c11700d7
--- /dev/null
+++ b/Fairy-Stockfish-master/AGENTS.md
@@ -0,0 +1,158 @@
+# Fairy-Stockfish Development Guide
+
+## Repository Overview
+
+**Fairy-Stockfish** is a chess variant engine derived from Stockfish, designed to support numerous chess variants and protocols. Written primarily in C++17, it includes Python and JavaScript bindings for library use.
+
+**Repository Statistics:**
+- **Languages:** C++17 (primary), Python, JavaScript, Shell scripts
+- **Architecture:** Multi-protocol chess engine (UCI, UCCI, USI, XBoard/CECP)
+- **Target Platforms:** Windows, Linux, macOS, Android, WebAssembly
+- **Supported Variants:** 90+ chess variants including regional, historical, and modern variants
+
+## Build System & Requirements
+
+### Prerequisites
+- **Compiler:** GCC, Clang, or MSVC with C++17 support
+- **Build Tool:** GNU Make (required for C++ engine)
+- **Python:** 3.7+ (for Python bindings)
+- **Node.js:** (for JavaScript bindings)
+- **Additional Tools:** expect utility (for testing)
+
+### Core Build Process
+
+Note: Run engine and test commands from the `src/` directory unless specified otherwise.
+
+#### Basic Build Commands
+```bash
+# Standard release build (recommended for most users)
+make -j2 ARCH=x86-64 build
+
+# Debug build (for development)
+make -j2 ARCH=x86-64 debug=yes build
+
+# All variants including ones with large boards (up to 12x10) and large branching factor (all)
+make -j2 ARCH=x86-64 largeboards=yes all=yes build
+```
+
+### Python Bindings (pyffish)
+```bash
+# Build Python bindings (from repository root)
+python3 setup.py install
+
+# Alternative: Install from PyPI
+pip install pyffish
+```
+
+### JavaScript Bindings (ffish.js)
+Also see the `tests/js/README.md`.
+```bash
+cd src/
+
+# Build JavaScript bindings (requires emscripten)
+make -f Makefile_js build
+
+# Alternative: Install from npm
+npm install ffish
+```
+
+## Testing & Validation
+
+All test commands below assume the current directory is `src/`.
+
+### Core Engine Tests
+```bash
+# Basic functionality test
+./stockfish bench
+
+# Variant-specific benchmarks
+./stockfish bench xiangqi
+./stockfish bench shogi
+./stockfish bench capablanca
+
+# Validate variants configuration
+./stockfish check variants.ini
+```
+
+### Comprehensive Test Suite
+```bash
+# Protocol compliance tests
+../tests/protocol.sh
+
+# Move generation validation
+../tests/perft.sh all
+../tests/perft.sh chess # Chess only
+../tests/perft.sh largeboard # Large board variants only
+
+# Regression testing
+../tests/regression.sh
+
+# Reproducible search test
+../tests/reprosearch.sh
+
+# Build signature verification
+../tests/signature.sh
+```
+
+
+## Project Architecture
+
+### Directory Structure
+```
+src/ # Core C++ engine source
+tests/ # Test scripts and data
+.github/workflows/ # CI/CD configurations
+```
+
+### Configuration Files
+- **`src/variants.ini`**: Defines examples for configuration of chess variants
+- **`setup.py`**: Python package build configuration
+- **`tests/js/package.json`**: JavaScript bindings configuration
+
+### Key Source Files in `src/`
+- **`variant.h`**: Variant rule properties
+- **`variant.cpp`**: Variant-specific game rules
+- **`variant.ini`**: Variant rule configuration examples and documentation of variant properties
+- **`position.h`**: Position representation
+- **`position.cpp`**: Board logic
+- **`movegen.cpp`**: Move generation logic
+- **`parser.cpp`**: Variant rule configuration parsing
+- **`piece.cpp`**: Piece type definitions and behavior
+- **`pyffish.cpp`**: Python bindings
+- **`ffishjs.cpp`**: JavaScript bindings
+
+## Continuous Integration
+
+### GitHub Actions Workflows
+- **`fairy.yml`**: Core engine testing (perft, protocols, variants)
+- **`stockfish.yml`**: Standard Stockfish compatibility tests
+- **`release.yml`**: Binary releases for multiple platforms
+- **`wheels.yml`**: Python package builds
+- **`ffishjs.yml`**: JavaScript binding builds
+
+## Common Development Patterns
+
+### Making Engine Changes
+1. **Always test basic functionality:** `./stockfish bench` after changes
+2. **Validate variant compatibility:** `./stockfish check variants.ini`
+3. **Run relevant tests:** `../tests/perft.sh all` for move generation changes
+
+### Adding New Configurable Variants
+1. **Edit `src/variants.ini`**: Add variant configuration
+2. **Test parsing:** `./stockfish check variants.ini`
+
+### Relevant websites for researching chess variant rules
+- [Chess Variants on Wikipedia](https://en.wikipedia.org/wiki/List_of_chess_variants)
+- [Chess Variants Wiki](https://www.chessvariants.com/)
+- [Variant Chess on BoardGameGeek](https://boardgamegeek.com/boardgamefamily/4024/traditional-games-chess)
+- [PyChess Variants](https://www.pychess.org/variants)
+- [Ludii](https://ludii.games/library.php)
+- [Lichess.org Variants](https://lichess.org/variant)
+- [Greenchess](https://greenchess.net/variants.php)
+- [Chess Variants on Chess.com](https://www.chess.com/variants)
+
+### Development Best Practices
+* Make sure to only stage and commit changes that were changed as part of the task, do not simply add all changes.
+* Keep changes minimal and focused on the task at hand.
+* After applying changes make sure that all places related to the task have been identified.
+* Stay consistent with the existing code style and conventions.
diff --git a/Fairy-Stockfish-master/AUTHORS b/Fairy-Stockfish-master/AUTHORS
new file mode 100644
index 0000000000000000000000000000000000000000..a0f09c8c5068bcfeb940fe150f39406fc87ef857
--- /dev/null
+++ b/Fairy-Stockfish-master/AUTHORS
@@ -0,0 +1,231 @@
+# Fairy-Stockfish authors
+
+# Main author
+Fabian Fichter (ianfab)
+
+# Contributors in alphabetical order
+alwey
+Belzedar94
+cloudfish
+CouchTomato87
+dpldgr
+Fulmene
+gbtami
+gnunicode
+johndoknjas
+kz04px
+majormink
+mtaktikos
+QueensGambit
+RainRat
+rkb97
+romstad
+Snowmoondaphne
+SriMethan
+thearst3rd
+TheYoBots
+tttak
+yjf2002ghty
+yoav-rozin
+ydirson
+
+
+
+# List of authors for Stockfish, as of June 14, 2021
+
+# Founders of the Stockfish project and fishtest infrastructure
+Tord Romstad (romstad)
+Marco Costalba (mcostalba)
+Joona Kiiski (zamar)
+Gary Linscott (glinscott)
+
+# Authors and inventors of NNUE, training, NNUE port
+Yu Nasu (ynasu87)
+Motohiro Isozaki (yaneurao)
+Hisayori Noda (nodchip)
+
+# all other authors of the code in alphabetical order
+Aditya (absimaldata)
+Adrian Petrescu (apetresc)
+Ajith Chandy Jose (ajithcj)
+Alain Savard (Rocky640)
+Alayan Feh (Alayan-stk-2)
+Alexander Kure
+Alexander Pagel (Lolligerhans)
+Alfredo Menezes (lonfom169)
+Ali AlZhrani (Cooffe)
+Andrew Grant (AndyGrant)
+Andrey Neporada (nepal)
+Andy Duplain
+Antoine Champion (antoinechampion)
+Aram Tumanian (atumanian)
+Arjun Temurnikar
+Artem Solopiy (EntityFX)
+Auguste Pop
+Balint Pfliegel
+Ben Koshy (BKSpurgeon)
+Bill Henry (VoyagerOne)
+Bojun Guo (noobpwnftw, Nooby)
+braich
+Brian Sheppard (SapphireBrand, briansheppard-toast)
+Bruno de Melo Costa (BM123499)
+Bryan Cross (crossbr)
+candirufish
+Chess13234
+Chris Cain (ceebo)
+Dale Weiler (graphitemaster)
+Dan Schmidt (dfannius)
+Daniel Axtens (daxtens)
+Daniel Dugovic (ddugovic)
+Dariusz Orzechowski (dorzechowski)
+David Zar
+Daylen Yang (daylen)
+Deshawn Mohan-Smith (GoldenRare)
+Dieter Dobbelaere (ddobbelaere)
+DiscanX
+Dominik Schlösser (domschl)
+double-beep
+Douglas Matos Gomes (dsmsgms)
+Eduardo Cáceres (eduherminio)
+Eelco de Groot (KingDefender)
+Elvin Liu (solarlight2)
+erbsenzaehler
+Ernesto Gatti
+Linmiao Xu (linrock)
+Fabian Beuke (madnight)
+Fabian Fichter (ianfab)
+Fanael Linithien (Fanael)
+fanon
+Fauzi Akram Dabat (FauziAkram)
+Felix Wittmann
+gamander
+Gary Heckman (gheckman)
+George Sobala (gsobala)
+gguliash
+Gian-Carlo Pascutto (gcp)
+Gontran Lemaire (gonlem)
+Goodkov Vasiliy Aleksandrovich (goodkov)
+Gregor Cramer
+GuardianRM
+Günther Demetz (pb00067, pb00068)
+Guy Vreuls (gvreuls)
+Henri Wiechers
+Hiraoka Takuya (HiraokaTakuya)
+homoSapiensSapiens
+Hongzhi Cheng
+Ivan Ivec (IIvec)
+Jacques B. (Timshel)
+Jan Ondruš (hxim)
+Jared Kish (Kurtbusch)
+Jarrod Torriero (DU-jdto)
+Jean Gauthier (OuaisBla)
+Jean-Francois Romang (jromang)
+Jekaa
+Jerry Donald Watson (jerrydonaldwatson)
+jjoshua2
+Jonathan Calovski (Mysseno)
+Jonathan Buladas Dumale (SFisGOD)
+Joost VandeVondele (vondele)
+Jörg Oster (joergoster)
+Joseph Ellis (jhellis3)
+Joseph R. Prostko
+Julian Willemer (NightlyKing)
+jundery
+Justin Blanchard (UncombedCoconut)
+Kelly Wilson
+Ken Takusagawa
+kinderchocolate
+Kiran Panditrao (Krgp)
+Kojirion
+Krystian Kuzniarek (kuzkry)
+Leonardo Ljubičić (ICCF World Champion)
+Leonid Pechenik (lp--)
+Linus Arver (listx)
+loco-loco
+Lub van den Berg (ElbertoOne)
+Luca Brivio (lucabrivio)
+Lucas Braesch (lucasart)
+Lyudmil Antonov (lantonov)
+Maciej Żenczykowski (zenczykowski)
+Malcolm Campbell (xoto10)
+Mark Tenzer (31m059)
+marotear
+Matt Ginsberg (mattginsberg)
+Matthew Lai (matthewlai)
+Matthew Sullivan (Matt14916)
+Maxim Molchanov (Maxim)
+Michael An (man)
+Michael Byrne (MichaelB7)
+Michael Chaly (Vizvezdenec)
+Michael Stembera (mstembera)
+Michael Whiteley (protonspring)
+Michel Van den Bergh (vdbergh)
+Miguel Lahoz (miguel-l)
+Mikael Bäckman (mbootsector)
+Mira
+Miroslav Fontán (Hexik)
+Moez Jellouli (MJZ1977)
+Mohammed Li (tthsqe12)
+Nathan Rugg (nmrugg)
+Nick Pelling (nickpelling)
+Nicklas Persson (NicklasPersson)
+Niklas Fiekas (niklasf)
+Nikolay Kostov (NikolayIT)
+Nguyen Pham (nguyenpham)
+Norman Schmidt (FireFather)
+notruck
+Ondrej Mosnáček (WOnder93)
+Oskar Werkelin Ahlin
+Pablo Vazquez
+Panthee
+Pascal Romaret
+Pasquale Pigazzini (ppigazzini)
+Patrick Jansen (mibere)
+pellanda
+Peter Zsifkovits (CoffeeOne)
+Praveen Kumar Tummala (praveentml)
+Rahul Dsilva (silversolver1)
+Ralph Stößer (Ralph Stoesser)
+Raminder Singh
+renouve
+Reuven Peleg
+Richard Lloyd
+Rodrigo Exterckötter Tjäder
+Ron Britvich (Britvich)
+Ronald de Man (syzygy1, syzygy)
+rqs
+Ryan Schmitt
+Ryan Takker
+Sami Kiminki (skiminki)
+Sebastian Buchwald (UniQP)
+Sergei Antonov (saproj)
+Sergei Ivanov (svivanov72)
+Sergio Vieri (sergiovieri)
+sf-x
+Shane Booth (shane31)
+Shawn Varghese (xXH4CKST3RXx)
+Siad Daboul (Topologist)
+Stefan Geschwentner (locutus2)
+Stefano Cardanobile (Stefano80)
+Steinar Gunderson (sesse)
+Stéphane Nicolet (snicolet)
+Prokop Randáček (ProkopRandacek)
+Thanar2
+thaspel
+theo77186
+Tom Truscott
+Tom Vijlbrief (tomtor)
+Tomasz Sobczyk (Sopel97)
+Torsten Franz (torfranz, tfranzer)
+Tracey Emery (basepr1me)
+tttak
+Unai Corzo (unaiic)
+Uri Blass (uriblass)
+Vince Negri (cuddlestmonkey)
+zz4032
+
+
+# Additionally, we acknowledge the authors and maintainers of fishtest,
+# an amazing and essential framework for the development of Stockfish!
+#
+# https://github.com/glinscott/fishtest/blob/master/AUTHORS
diff --git a/Fairy-Stockfish-master/Copying.txt b/Fairy-Stockfish-master/Copying.txt
new file mode 100644
index 0000000000000000000000000000000000000000..818433ecc0e094a4db1023c68b33f24344643ad8
--- /dev/null
+++ b/Fairy-Stockfish-master/Copying.txt
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/Fairy-Stockfish-master/MANIFEST.in b/Fairy-Stockfish-master/MANIFEST.in
new file mode 100644
index 0000000000000000000000000000000000000000..1265c8117db8540fd5993cd87256eb0db40896a0
--- /dev/null
+++ b/Fairy-Stockfish-master/MANIFEST.in
@@ -0,0 +1,2 @@
+include AUTHORS Copying.txt Readme.md test.py
+recursive-include src *.h *.cpp
diff --git a/Fairy-Stockfish-master/README.md b/Fairy-Stockfish-master/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..b8e87970a24dc8081edb624b098ad7f2d519bbf1
--- /dev/null
+++ b/Fairy-Stockfish-master/README.md
@@ -0,0 +1,126 @@
+# Fairy-Stockfish
+
+## Overview
+
+[](https://github.com/fairy-stockfish/Fairy-Stockfish/actions?query=workflow%3ARelease)
+[](https://github.com/fairy-stockfish/Fairy-Stockfish/actions?query=workflow%3Afairy)
+[](https://ci.appveyor.com/project/ianfab/Fairy-Stockfish/branch/master)
+[](https://badge.fury.io/py/pyffish)
+[](https://www.npmjs.com/package/ffish)
+
+Fairy-Stockfish is a chess variant engine derived from [Stockfish](https://github.com/official-stockfish/Stockfish/) designed for the support of fairy chess variants and easy extensibility with more games. It can play various regional, historical, and modern chess variants as well as [games with user-defined rules](https://github.com/fairy-stockfish/Fairy-Stockfish/wiki/Variant-configuration). For [compatibility with graphical user interfaces](https://github.com/fairy-stockfish/Fairy-Stockfish/wiki/Graphical-user-interfaces) it supports the UCI, UCCI, USI, UCI-cyclone, and CECP/XBoard protocols.
+
+The goal of the project is to create an engine supporting a large variety of chess-like games, equipped with the powerful search of Stockfish. Despite its generality the [playing strength](https://github.com/fairy-stockfish/Fairy-Stockfish/wiki/Playing-strength) is on a very high level in almost all supported variants. Due to its multi-protocol support Fairy-Stockfish works with almost any chess variant GUI.
+
+## Installation
+You can download the [Windows executable](https://github.com/fairy-stockfish/Fairy-Stockfish/releases/latest/download/fairy-stockfish-largeboard_x86-64.exe) or [Linux binary](https://github.com/fairy-stockfish/Fairy-Stockfish/releases/latest/download/fairy-stockfish-largeboard_x86-64) from the [latest release](https://github.com/fairy-stockfish/Fairy-Stockfish/releases/latest) or [compile the program from source](https://github.com/fairy-stockfish/Fairy-Stockfish#compiling-stockfish-yourself-from-the-sources). The program comes without a graphical user interface, so you perhaps want to use it together with a [compatible GUI](https://github.com/fairy-stockfish/Fairy-Stockfish/wiki/Graphical-user-interfaces), or [play against it online](https://github.com/fairy-stockfish/Fairy-Stockfish/wiki/Online) at [pychess](https://www.pychess.org/), [lishogi](https://lishogi.org/@/Fairy-Stockfish), or [lichess](https://lichess.org/@/Fairy-Stockfish). Read more about [how to use](https://github.com/fairy-stockfish/Fairy-Stockfish/wiki/Usage) Fairy-Stockfish in the wiki.
+
+If you want to preview the functionality of Fairy-Stockfish before downloading, you can try it out on the [Fairy-Stockfish playground](https://fairyground.vercel.app/) in the browser.
+
+Optional NNUE evaluation parameter files to improve playing strength for many variants are in the [list of NNUE networks](https://fairy-stockfish.github.io/nnue/#current-best-nnue-networks).
+For the regional variants Xiangqi, Janggi, and Makruk [dedicated releases with built-in NNUE networks](https://github.com/fairy-stockfish/Fairy-Stockfish-NNUE) are available. See the [wiki](https://github.com/fairy-stockfish/Fairy-Stockfish/wiki/NNUE) for more details on NNUE.
+
+## Contributing
+
+If you like this project, please support its development via [patreon](https://www.patreon.com/ianfab), [paypal](https://paypal.me/FairyStockfish), or [github](https://github.com/sponsors/ianfab), or by [contributing to the code](https://github.com/fairy-stockfish/Fairy-Stockfish/wiki/Contributing) or documentation. An [introduction to the code base](https://github.com/fairy-stockfish/Fairy-Stockfish/wiki/Understanding-the-code) can be found in the wiki.
+
+## Supported games
+
+The games currently supported besides chess are listed below. Fairy-Stockfish can also play user-defined variants loaded via a variant configuration file, see the file [`src/variants.ini`](https://github.com/ianfab/Fairy-Stockfish/blob/master/src/variants.ini) and the [wiki](https://github.com/fairy-stockfish/Fairy-Stockfish/wiki/Variant-configuration).
+
+### Regional and historical games
+- [Xiangqi](https://en.wikipedia.org/wiki/Xiangqi), [Manchu](https://en.wikipedia.org/wiki/Manchu_chess), [Minixiangqi](https://www.pychess.org/variants/minixiangqi), [Supply chess](https://en.wikipedia.org/wiki/Xiangqi#Variations)
+- [Shogi](https://en.wikipedia.org/wiki/Shogi), [Shogi variants](https://github.com/fairy-stockfish/Fairy-Stockfish#shogi-variants)
+- [Janggi](https://en.wikipedia.org/wiki/Janggi)
+- [Makruk](https://en.wikipedia.org/wiki/Makruk), [ASEAN](http://hgm.nubati.net/rules/ASEAN.html), Makpong, Ai-Wok
+- [Ouk Chatrang](https://en.wikipedia.org/wiki/Makruk#Cambodian_chess), [Kar Ouk](https://en.wikipedia.org/wiki/Makruk#Cambodian_chess)
+- [Sittuyin](https://en.wikipedia.org/wiki/Sittuyin)
+- [Shatar](https://en.wikipedia.org/wiki/Shatar), [Jeson Mor](https://en.wikipedia.org/wiki/Jeson_Mor)
+- [Shatranj](https://en.wikipedia.org/wiki/Shatranj), [Courier](https://en.wikipedia.org/wiki/Courier_chess)
+- [Raazuvaa](https://www.reddit.com/r/chess/comments/sj7y3n/raazuvaa_the_chess_of_the_maldives)
+
+### Chess variants
+- [Capablanca](https://en.wikipedia.org/wiki/Capablanca_Chess), [Janus](https://en.wikipedia.org/wiki/Janus_Chess), [Modern](https://en.wikipedia.org/wiki/Modern_Chess_(chess_variant)), [Chancellor](https://en.wikipedia.org/wiki/Chancellor_Chess), [Embassy](https://en.wikipedia.org/wiki/Embassy_Chess), [Gothic](https://www.chessvariants.com/large.dir/gothicchess.html), [Capablanca random chess](https://en.wikipedia.org/wiki/Capablanca_Random_Chess)
+- [Grand](https://en.wikipedia.org/wiki/Grand_Chess), [Shako](https://www.chessvariants.com/large.dir/shako.html), [Centaur](https://www.chessvariants.com/large.dir/contest/royalcourt.html), [Tencubed](https://www.chessvariants.com/contests/10/tencubedchess.html), [Opulent](https://www.chessvariants.com/rules/opulent-chess)
+- [Chess960](https://en.wikipedia.org/wiki/Chess960), [Placement/Pre-Chess](https://www.chessvariants.com/link/placement-chess)
+- [Crazyhouse](https://en.wikipedia.org/wiki/Crazyhouse), [Loop](https://en.wikipedia.org/wiki/Crazyhouse#Variations), [Chessgi](https://en.wikipedia.org/wiki/Crazyhouse#Variations), [Pocket Knight](http://www.chessvariants.com/other.dir/pocket.html), Capablanca-Crazyhouse
+- [Bughouse](https://en.wikipedia.org/wiki/Bughouse_chess), [Koedem](http://schachclub-oetigheim.de/wp-content/uploads/2016/04/Koedem-rules.pdf)
+- [Seirawan](https://en.wikipedia.org/wiki/Seirawan_chess), Seirawan-Crazyhouse, [Dragon Chess](https://www.edami.com/dragonchess/)
+- [Amazon](https://www.chessvariants.com/diffmove.dir/amazone.html), [Chigorin](https://www.chessvariants.com/diffsetup.dir/chigorin.html), [Almost chess](https://en.wikipedia.org/wiki/Almost_Chess)
+- [Hoppel-Poppel](http://www.chessvariants.com/diffmove.dir/hoppel-poppel.html), New Zealand
+- [Antichess](https://lichess.org/variant/antichess), [Giveaway](http://www.chessvariants.com/diffobjective.dir/giveaway.old.html), [Suicide](https://www.freechess.org/Help/HelpFiles/suicide_chess.html), [Losers](https://www.chessclub.com/help/Wild17), [Codrus](http://www.binnewirtz.com/Schlagschach1.htm)
+- [Extinction](https://en.wikipedia.org/wiki/Extinction_chess), [Kinglet](https://en.wikipedia.org/wiki/V._R._Parton#Kinglet_chess), Three Kings, [Coregal](https://www.chessvariants.com/winning.dir/coregal.html)
+- [King of the Hill](https://en.wikipedia.org/wiki/King_of_the_Hill_(chess)), [Racing Kings](https://en.wikipedia.org/wiki/V._R._Parton#Racing_Kings)
+- [Three-check](https://en.wikipedia.org/wiki/Three-check_chess), Five-check
+- [Los Alamos](https://en.wikipedia.org/wiki/Los_Alamos_chess), [Gardner's Minichess](https://en.wikipedia.org/wiki/Minichess#5%C3%975_chess)
+- [Atomic](https://en.wikipedia.org/wiki/Atomic_chess)
+- [Horde](https://en.wikipedia.org/wiki/Dunsany%27s_Chess#Horde_Chess), [Maharajah and the Sepoys](https://en.wikipedia.org/wiki/Maharajah_and_the_Sepoys)
+- [Knightmate](https://www.chessvariants.com/diffobjective.dir/knightmate.html), [Nightrider](https://en.wikipedia.org/wiki/Nightrider_(chess)), [Grasshopper](https://en.wikipedia.org/wiki/Grasshopper_chess)
+- [Duck chess](https://duckchess.com/), [Omicron](http://www.eglebbk.dds.nl/program/chess-omicron.html), [Gustav III](https://www.chessvariants.com/play/gustav-iiis-chess)
+- [Berolina Chess](https://en.wikipedia.org/wiki/Berolina_pawn#Berolina_chess), [Pawn-Sideways](https://arxiv.org/abs/2009.04374), [Pawn-Back](https://arxiv.org/abs/2009.04374), [Torpedo](https://arxiv.org/abs/2009.04374), [Legan Chess](https://en.wikipedia.org/wiki/Legan_chess)
+- [Spartan Chess](https://www.chessvariants.com/rules/spartan-chess)
+- [Wolf Chess](https://en.wikipedia.org/wiki/Wolf_chess)
+- [Troitzky Chess](https://www.chessvariants.com/play/troitzky-chess)
+
+### Shogi variants
+- [Minishogi](https://en.wikipedia.org/wiki/Minishogi), [EuroShogi](https://en.wikipedia.org/wiki/EuroShogi), [Judkins shogi](https://en.wikipedia.org/wiki/Judkins_shogi)
+- [Kyoto shogi](https://en.wikipedia.org/wiki/Kyoto_shogi), [Microshogi](https://en.wikipedia.org/wiki/Micro_shogi)
+- [Dobutsu shogi](https://en.wikipedia.org/wiki/Dōbutsu_shōgi), [Goro goro shogi](https://en.wikipedia.org/wiki/D%C5%8Dbutsu_sh%C5%8Dgi#Variation)
+- [Tori shogi](https://en.wikipedia.org/wiki/Tori_shogi)
+- [Yari shogi](https://en.wikipedia.org/wiki/Yari_shogi)
+- [Okisaki shogi](https://en.wikipedia.org/wiki/Okisaki_shogi)
+- [Sho shogi](https://en.wikipedia.org/wiki/Sho_shogi)
+
+### Related games
+- [Amazons](https://en.wikipedia.org/wiki/Game_of_the_Amazons)
+- [Ataxx](https://en.wikipedia.org/wiki/Ataxx)
+- [Breakthrough](https://en.wikipedia.org/wiki/Breakthrough_(board_game))
+- [Clobber](https://en.wikipedia.org/wiki/Clobber)
+- [Cfour](https://en.wikipedia.org/wiki/Connect_Four), [Tic-tac-toe](https://en.wikipedia.org/wiki/Tic-tac-toe)
+- [Five Field Kono](https://en.wikipedia.org/wiki/Five_Field_Kono)
+- [Flipersi](https://en.wikipedia.org/wiki/Reversi), [Flipello](https://en.wikipedia.org/wiki/Reversi#Othello)
+- [Fox and Hounds](https://boardgamegeek.com/boardgame/148180/fox-and-hounds)
+- [Isolation](https://boardgamegeek.com/boardgame/1875/isolation)
+- [Joust](https://www.chessvariants.com/programs.dir/joust.html)
+- [Snailtrail](https://boardgamegeek.com/boardgame/37135/snailtrail)
+
+
+## Help
+
+See the [Fairy-Stockfish Wiki](https://github.com/fairy-stockfish/Fairy-Stockfish/wiki) for more info, or if the required information is not available, open an [issue](https://github.com/fairy-stockfish/Fairy-Stockfish/issues) or join our [discord server](https://discord.gg/FYUGgmCFB4).
+
+## Bindings
+
+Besides the C++ engine, this project also includes bindings for other programming languages in order to be able to use it as a library for chess variants. They support move, SAN, and FEN generation, as well as checking of game end conditions for all variants supported by Fairy-Stockfish. Since the bindings are using the C++ code, they are very performant compared to libraries directly written in the respective target language.
+
+### Python
+
+The python binding [pyffish](https://pypi.org/project/pyffish/) contributed by [@gbtami](https://github.com/gbtami) is implemented in [pyffish.cpp](https://github.com/fairy-stockfish/Fairy-Stockfish/blob/master/src/pyffish.cpp). It is e.g. used in the backend for the [pychess server](https://github.com/gbtami/pychess-variants).
+
+### Javascript
+
+The javascript binding [ffish.js](https://www.npmjs.com/package/ffish) contributed by [@QueensGambit](https://github.com/QueensGambit) is implemented in [ffishjs.cpp](https://github.com/fairy-stockfish/Fairy-Stockfish/blob/master/src/ffishjs.cpp). The compilation/binding to javascript is done using emscripten, see the [readme](https://github.com/fairy-stockfish/Fairy-Stockfish/tree/master/tests/js).
+
+## Ports
+
+### WebAssembly
+
+For in-browser use a [port of Fairy-Stockfish to WebAssembly](https://github.com/fairy-stockfish/fairy-stockfish.wasm) is available at [npm](https://www.npmjs.com/package/fairy-stockfish-nnue.wasm). It is e.g. used for local analysis on [pychess.org](https://www.pychess.org/analysis/chess). Also see the [Fairy-Stockfish WASM demo](https://github.com/ianfab/fairy-stockfish-nnue-wasm-demo) available at https://fairy-stockfish-nnue-wasm.vercel.app/.
+
+## Terms of use
+
+Fairy-Stockfish is free, and distributed under the **GNU General Public License version 3**
+(GPL v3). Essentially, this means you are free to do almost exactly
+what you want with the program, including distributing it among your
+friends, making it available for download from your website, selling
+it (either by itself or as part of some bigger software package), or
+using it as the starting point for a software project of your own.
+
+The only real limitation is that whenever you distribute Fairy-Stockfish in
+some way, you MUST always include the full source code, or a pointer
+to where the source code can be found, to generate the exact binary
+you are distributing. If you make any changes to the source code,
+these changes must also be made available under the GPL.
+
+For full details, read the copy of the GPL v3 found in the file named
+[*Copying.txt*](https://github.com/fairy-stockfish/Fairy-Stockfish/blob/master/Copying.txt).
diff --git a/Fairy-Stockfish-master/Top CPU Contributors.txt b/Fairy-Stockfish-master/Top CPU Contributors.txt
new file mode 100644
index 0000000000000000000000000000000000000000..dacc5781b2ddf47131ff0e72f54922bea29d3d5e
--- /dev/null
+++ b/Fairy-Stockfish-master/Top CPU Contributors.txt
@@ -0,0 +1,205 @@
+Contributors to Fishtest with >10,000 CPU hours, as of Jun 29, 2021.
+Thank you!
+
+Username CPU Hours Games played
+-----------------------------------------------------
+noobpwnftw 27649494 1834734733
+mlang 1426107 89454622
+dew 1380910 82831648
+mibere 703840 46867607
+grandphish2 692707 41737913
+tvijlbrief 669642 42371594
+JojoM 597778 35297180
+TueRens 519226 31823562
+cw 458421 30307421
+fastgm 439667 25950040
+gvreuls 436599 28177460
+crunchy 427035 27344275
+CSU_Dynasty 374765 25106278
+Fisherman 326901 21822979
+ctoks 325477 21767943
+velislav 295343 18844324
+linrock 292789 10624427
+bcross 278584 19488961
+okrout 262818 13803272
+pemo 245982 11376085
+glinscott 217799 13780820
+leszek 212346 12959025
+nordlandia 211692 13484886
+bking_US 198894 11876016
+drabel 196463 13450602
+robal 195473 12375650
+mgrabiak 187226 12016564
+Dantist 183202 10990484
+Thanar 179852 12365359
+vdv 175274 9889046
+spams 157128 10319326
+marrco 150295 9402141
+sqrt2 147963 9724586
+mhoram 141278 8901241
+CoffeeOne 137100 5024116
+vdbergh 137041 8926915
+malala 136182 8002293
+xoto 133702 9156676
+davar 122092 7960001
+dsmith 122059 7570238
+Data 113305 8220352
+BrunoBanani 112960 7436849
+MaZePallas 102823 6633619
+sterni1971 100532 5880772
+ElbertoOne 99028 7023771
+brabos 92118 6186135
+oz 92100 6486640
+psk 89957 5984901
+amicic 89156 5392305
+sunu 88851 6028873
+Vizvezdenec 83761 5344740
+0x3C33 82614 5271253
+BRAVONE 81239 5054681
+racerschmacer 80899 5759262
+cuistot 80300 4606144
+nssy 76497 5259388
+teddybaer 75125 5407666
+Pking_cda 73776 5293873
+jromang 72192 5057715
+solarlight 70517 5028306
+dv8silencer 70287 3883992
+Bobo1239 68515 4652287
+manap 66273 4121774
+skiminki 65088 4023328
+tinker 64333 4268790
+sschnee 60767 3500800
+qurashee 57344 3168264
+robnjr 57262 4053117
+Freja 56938 3733019
+ttruscott 56010 3680085
+rkl 55132 4164467
+renouve 53811 3501516
+finfish 51360 3370515
+eva42 51272 3599691
+rap 49985 3219146
+pb00067 49727 3298270
+ronaldjerum 47654 3240695
+bigpen0r 47653 3335327
+eastorwest 47585 3221629
+biffhero 46564 3111352
+VoyagerOne 45476 3452465
+yurikvelo 44834 3034550
+speedycpu 43842 3003273
+jbwiebe 43305 2805433
+Spprtr 42279 2680153
+DesolatedDodo 42007 2447516
+Antihistamine 41788 2761312
+mhunt 41735 2691355
+homyur 39893 2850481
+gri 39871 2515779
+Fifis 38776 2529121
+oryx 38724 2966648
+SC 37290 2731014
+csnodgrass 36207 2688994
+jmdana 36157 2210661
+strelock 34716 2074055
+rpngn 33951 2057395
+Garf 33922 2751802
+EthanOConnor 33370 2090311
+slakovv 32915 2021889
+manapbk 30987 1810399
+Prcuvu 30377 2170122
+anst 30301 2190091
+jkiiski 30136 1904470
+hyperbolic.tom 29840 2017394
+Pyafue 29650 1902349
+Wolfgang 29260 1658936
+zeryl 28156 1579911
+OuaisBla 27636 1578800
+DMBK 27051 1999456
+chriswk 26902 1868317
+achambord 26582 1767323
+Patrick_G 26276 1801617
+yorkman 26193 1992080
+SFTUser 25182 1675689
+nabildanial 24942 1519409
+Sharaf_DG 24765 1786697
+ncfish1 24411 1520927
+rodneyc 24227 1409514
+agg177 23890 1395014
+JanErik 23408 1703875
+Isidor 23388 1680691
+Norabor 23164 1591830
+cisco2015 22897 1762669
+Zirie 22542 1472937
+team-oh 22272 1636708
+MazeOfGalious 21978 1629593
+sg4032 21947 1643265
+ianh2105 21725 1632562
+xor12 21628 1680365
+dex 21612 1467203
+nesoneg 21494 1463031
+sphinx 21211 1384728
+jjoshua2 21001 1423089
+horst.prack 20878 1465656
+Ente 20865 1477066
+0xB00B1ES 20590 1208666
+j3corre 20405 941444
+Adrian.Schmidt123 20316 1281436
+wei 19973 1745989
+MaxKlaxxMiner 19850 1009176
+rstoesser 19569 1293588
+gopeto 19491 1174952
+eudhan 19274 1283717
+jundery 18445 1115855
+megaman7de 18377 1067540
+iisiraider 18247 1101015
+ville 17883 1384026
+chris 17698 1487385
+purplefishies 17595 1092533
+dju 17353 978595
+DragonLord 17014 1162790
+IgorLeMasson 16064 1147232
+ako027ako 15671 1173203
+chuckstablers 15289 891576
+Nikolay.IT 15154 1068349
+Andrew Grant 15114 895539
+OssumOpossum 14857 1007129
+Karby 14808 867120
+enedene 14476 905279
+bpfliegel 14298 884523
+mpx86 14019 759568
+jpulman 13982 870599
+crocogoat 13803 1117422
+joster 13794 950160
+Nesa92 13786 1114691
+Hjax 13535 915487
+jsys14 13459 785000
+Dark_wizzie 13422 1007152
+mabichito 12903 749391
+thijsk 12886 722107
+AdrianSA 12860 804972
+Flopzee 12698 894821
+fatmurphy 12547 853210
+Rudolphous 12520 832340
+scuzzi 12511 845761
+SapphireBrand 12416 969604
+modolief 12386 896470
+Machariel 12335 810784
+pgontarz 12151 848794
+stocky 11954 699440
+mschmidt 11941 803401
+Maxim 11543 836024
+infinity 11470 727027
+torbjo 11395 729145
+Thomas A. Anderson 11372 732094
+savage84 11358 670860
+d64 11263 789184
+MooTheCow 11237 720174
+snicolet 11106 869170
+ali-al-zhrani 11086 767926
+AndreasKrug 10875 887457
+pirt 10806 836519
+basepi 10637 744851
+michaelrpg 10508 739039
+dzjp 10343 732529
+aga 10302 622975
+ols 10259 570669
+lbraesch 10252 647825
+FormazChar 10059 757283
diff --git a/Fairy-Stockfish-master/appveyor.yml b/Fairy-Stockfish-master/appveyor.yml
new file mode 100644
index 0000000000000000000000000000000000000000..d6f5226e8490658f01737e36c51b3e14d7f67312
--- /dev/null
+++ b/Fairy-Stockfish-master/appveyor.yml
@@ -0,0 +1,91 @@
+version: 1.0.{build}
+clone_depth: 50
+
+branches:
+ only:
+ - master
+ - merge
+ - appveyor
+
+# Operating system (build VM template)
+os: Visual Studio 2019
+
+# Build platform, i.e. x86, x64, AnyCPU. This setting is optional.
+platform:
+ - x86
+ - x64
+
+# build Configuration, i.e. Debug, Release, etc.
+configuration:
+ - Debug
+ - Release
+
+matrix:
+ # The build fail immediately once one of the job fails
+ fast_finish: true
+
+# Scripts that are called at very beginning, before repo cloning
+init:
+ - cmake --version
+ - msbuild /version
+
+before_build:
+ - ps: |
+ # Get sources
+ $src = get-childitem -Path *.cpp -Recurse -Exclude pyffish.cpp,ffishjs.cpp | select -ExpandProperty FullName
+ $src = $src -join ' '
+ $src = $src.Replace("\", "/")
+
+ # Build CMakeLists.txt
+ $t = 'cmake_minimum_required(VERSION 3.17)',
+ 'project(Stockfish)',
+ 'set(CMAKE_CXX_STANDARD 17)',
+ 'set(CMAKE_CXX_STANDARD_REQUIRED ON)',
+ 'set (CMAKE_CXX_EXTENSIONS OFF)',
+ 'set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/src)',
+ 'set(source_files', $src, ')',
+ 'add_compile_definitions(NNUE_EMBEDDING_OFF)',
+ 'add_executable(stockfish ${source_files})'
+
+ # Write CMakeLists.txt without BOM
+ $MyPath = (Get-Item -Path "." -Verbose).FullName + '\CMakeLists.txt'
+ $Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
+ [System.IO.File]::WriteAllLines($MyPath, $t, $Utf8NoBomEncoding)
+
+ # Obtain bench reference from git log
+ $b = git log HEAD | sls "\b[Bb]ench[ :]+[0-9]{7}" | select -first 1
+ $bench = $b -match '\D+(\d+)' | % { $matches[1] }
+ Write-Host "Reference bench:" $bench
+ $g = "Visual Studio 16 2019"
+ If (${env:PLATFORM} -eq 'x64') { $a = "x64" }
+ If (${env:PLATFORM} -eq 'x86') { $a = "Win32" }
+ cmake -G "${g}" -A ${a} .
+ Write-Host "Generated files for: " $g $a
+
+build_script:
+ - cmake --build . --config %CONFIGURATION% -- /verbosity:minimal
+ - ps: |
+ # Download default NNUE net from fishtest
+ $nnuenet = Get-Content -Path src\evaluate.h | Select-String -CaseSensitive -Pattern "EvalFileDefaultName" | Select-String -CaseSensitive -Pattern "nn-[a-z0-9]{12}.nnue"
+ $dummy = $nnuenet -match "(?nn-[a-z0-9]{12}.nnue)"
+ $nnuenet = $Matches.nnuenet
+ Write-Host "Default net:" $nnuenet
+ $nnuedownloadurl = "https://github.com/official-stockfish/networks/raw/master/$nnuenet"
+ $nnuefilepath = "src\${env:CONFIGURATION}\$nnuenet"
+ if (Test-Path -Path $nnuefilepath) {
+ Write-Host "Already available."
+ } else {
+ Write-Host "Downloading $nnuedownloadurl to $nnuefilepath"
+ Invoke-WebRequest -Uri $nnuedownloadurl -OutFile $nnuefilepath
+ }
+
+before_test:
+ - cd src/%CONFIGURATION%
+ - stockfish bench 2> out.txt >NUL
+ - ps: |
+ # Verify bench number
+ $s = (gc "./out.txt" | out-string)
+ $r = ($s -match 'Nodes searched \D+(\d+)' | % { $matches[1] })
+ Write-Host "Engine bench:" $r
+ Write-Host "Reference bench:" $bench
+ If ($r -ne $bench) { exit 1 }
diff --git a/Fairy-Stockfish-master/pyffish.pyi b/Fairy-Stockfish-master/pyffish.pyi
new file mode 100644
index 0000000000000000000000000000000000000000..c955f22b7ecbe379a317e800efa27d9adb472b48
--- /dev/null
+++ b/Fairy-Stockfish-master/pyffish.pyi
@@ -0,0 +1,39 @@
+from typing import Any
+
+FEN_OK: int
+NOTATION_DEFAULT: int
+NOTATION_JANGGI: int
+NOTATION_LAN: int
+NOTATION_SAN: int
+NOTATION_SHOGI_HODGES: int
+NOTATION_SHOGI_HODGES_NUMBER: int
+NOTATION_SHOGI_HOSKING: int
+NOTATION_THAI_LAN: int
+NOTATION_THAI_SAN: int
+NOTATION_XIANGQI_WXF: int
+VALUE_DRAW: int
+VALUE_MATE: int
+
+class error(Exception): ...
+
+def version() -> tuple[int, int, int]: ...
+def info() -> str: ...
+def variants() -> list[str]: ...
+def set_option(name: str, value: Any) -> None: ...
+def load_variant_config(config: str) -> None: ...
+def start_fen(variant: str) -> str: ...
+def two_boards(variant: str) -> bool: ...
+def captures_to_hand(variant: str) -> bool: ...
+def get_san(variant: str, fen: str, move: str, chess960: bool = False, notation: int = NOTATION_DEFAULT) -> str: ...
+def get_san_moves(variant: str, fen: str, movelist: list[str], chess960: bool = False, notation: int = NOTATION_DEFAULT) -> list[str]: ...
+def legal_moves(variant: str, fen: str, movelist: list[str], chess960: bool = False) -> list[str]: ...
+def get_fen(variant: str, fen: str, movelist: list[str], chess960: bool = False, sfen: bool = False, show_promoted: bool = False, count_started: int = 0) -> str: ...
+def gives_check(variant: str, fen: str, movelist: list[str], chess960: bool = False) -> bool: ...
+def is_capture(variant: str, fen: str, movelist: list[str], move: str, chess960: bool = False) -> bool: ...
+def piece_to_partner(variant: str, fen: str, movelist: list[str], chess960: bool = False) -> str: ...
+def game_result(variant: str, fen: str, movelist: list[str], chess960: bool = False) -> int: ...
+def is_immediate_game_end(variant: str, fen: str, movelist: list[str], chess960: bool = False) -> tuple[bool, int]: ...
+def is_optional_game_end(variant: str, fen: str, movelist: list[str], chess960: bool = False, count_started: int = 0) -> tuple[bool, int]: ...
+def has_insufficient_material(variant: str, fen: str, movelist: list[str], chess960: bool = False) -> tuple[bool, bool]: ...
+def validate_fen(fen: str, variant: str, chess960: bool = False) -> int: ...
+def get_fog_fen(fen: str, variant: str, chess960: bool = False) -> str: ...
diff --git a/Fairy-Stockfish-master/setup.py b/Fairy-Stockfish-master/setup.py
new file mode 100644
index 0000000000000000000000000000000000000000..5e1f4967b8c1d5147ccf4f9edc040e7a33ffc2f1
--- /dev/null
+++ b/Fairy-Stockfish-master/setup.py
@@ -0,0 +1,56 @@
+# -*- coding: utf-8 -*-
+
+from setuptools import setup, Extension
+from glob import glob
+import platform
+import io
+import os
+
+
+if platform.python_compiler().startswith("MSC"):
+ args = ["/std:c++17"]
+else:
+ args = ["-std=c++17", "-flto", "-Wno-date-time"]
+
+args.extend(["-DLARGEBOARDS", "-DALLVARS", "-DPRECOMPUTED_MAGICS", "-DNNUE_EMBEDDING_OFF"])
+
+if "64bit" in platform.architecture():
+ args.append("-DIS_64BIT")
+
+CLASSIFIERS = [
+ "Development Status :: 3 - Alpha",
+ "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
+ "Programming Language :: Python :: 3",
+ "Operating System :: OS Independent",
+]
+
+with io.open("README.md", "r", encoding="utf8") as fh:
+ long_description = fh.read().strip()
+
+sources = glob("src/*.cpp") + glob("src/syzygy/*.cpp") + glob("src/nnue/*.cpp") + glob("src/nnue/features/*.cpp")
+headers = glob("src/*.h") + glob("src/syzygy/*.h") + glob("src/nnue/*.h") + glob("src/nnue/features/*.h")
+ffish_source_file = os.path.normcase("src/ffishjs.cpp")
+try:
+ sources.remove(ffish_source_file)
+except ValueError:
+ print(f"ffish_source_file {ffish_source_file} was not found in sources {sources}.")
+
+pyffish_module = Extension(
+ "pyffish",
+ sources=sources,
+ depends=headers,
+ extra_compile_args=args)
+
+setup(name="pyffish", version="0.0.89",
+ description="Fairy-Stockfish Python wrapper",
+ long_description=long_description,
+ long_description_content_type="text/markdown",
+ author="Bajusz Tamás",
+ author_email="gbtami@gmail.com",
+ license="GPL3",
+ classifiers=CLASSIFIERS,
+ url="https://github.com/gbtami/Fairy-Stockfish",
+ python_requires=">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*",
+ ext_modules=[pyffish_module],
+ data_files=[("", ["pyffish.pyi"])]
+ )
diff --git a/Fairy-Stockfish-master/src/Makefile b/Fairy-Stockfish-master/src/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..823649fb389b778d867befd6e7b809bd5fe37f8e
--- /dev/null
+++ b/Fairy-Stockfish-master/src/Makefile
@@ -0,0 +1,982 @@
+# Stockfish, a UCI chess playing engine derived from Glaurung 2.1
+# Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
+#
+# Stockfish is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Stockfish is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+
+### ==========================================================================
+### Section 1. General Configuration
+### ==========================================================================
+
+### Executable name
+ifeq ($(COMP),mingw)
+EXE = stockfish.exe
+else
+EXE = stockfish
+endif
+
+### Installation dir definitions
+PREFIX = /usr/local
+BINDIR = $(PREFIX)/bin
+
+### Built-in benchmark for pgo-builds
+ifeq ($(SDE_PATH),)
+ PGOBENCH = ./$(EXE) bench
+else
+ PGOBENCH = $(SDE_PATH) -- ./$(EXE) bench
+endif
+
+### Source and object files
+SRCS = benchmark.cpp bitbase.cpp bitboard.cpp endgame.cpp evaluate.cpp main.cpp \
+ material.cpp misc.cpp movegen.cpp movepick.cpp pawns.cpp position.cpp psqt.cpp \
+ search.cpp thread.cpp timeman.cpp tt.cpp uci.cpp ucioption.cpp tune.cpp syzygy/tbprobe.cpp \
+ nnue/evaluate_nnue.cpp nnue/features/half_ka_v2.cpp \
+ partner.cpp parser.cpp piece.cpp variant.cpp xboard.cpp \
+ nnue/features/half_ka_v2_variants.cpp
+
+OBJS = $(notdir $(SRCS:.cpp=.o))
+
+VPATH = syzygy:nnue:nnue/features
+
+### Establish the operating system name
+KERNEL = $(shell uname -s)
+ifeq ($(KERNEL),Linux)
+ OS = $(shell uname -o)
+endif
+
+### ==========================================================================
+### Section 2. High-level Configuration
+### ==========================================================================
+#
+# flag --- Comp switch --- Description
+# ----------------------------------------------------------------------------
+#
+# debug = yes/no --- -DNDEBUG --- Enable/Disable debug mode
+# sanitize = none/ ... (-fsanitize )
+# --- ( undefined ) --- enable undefined behavior checks
+# --- ( thread ) --- enable threading error checks
+# --- ( address ) --- enable memory access checks
+# --- ...etc... --- see compiler documentation for supported sanitizers
+# optimize = yes/no --- (-O3/-fast etc.) --- Enable/Disable optimizations
+# arch = (name) --- (-arch) --- Target architecture
+# bits = 64/32 --- -DIS_64BIT --- 64-/32-bit operating system
+# prefetch = yes/no --- -DUSE_PREFETCH --- Use prefetch asm-instruction
+# popcnt = yes/no --- -DUSE_POPCNT --- Use popcnt asm-instruction
+# pext = yes/no --- -DUSE_PEXT --- Use pext x86_64 asm-instruction
+# sse = yes/no --- -msse --- Use Intel Streaming SIMD Extensions
+# mmx = yes/no --- -mmmx --- Use Intel MMX instructions
+# sse2 = yes/no --- -msse2 --- Use Intel Streaming SIMD Extensions 2
+# ssse3 = yes/no --- -mssse3 --- Use Intel Supplemental Streaming SIMD Extensions 3
+# sse41 = yes/no --- -msse4.1 --- Use Intel Streaming SIMD Extensions 4.1
+# avx2 = yes/no --- -mavx2 --- Use Intel Advanced Vector Extensions 2
+# avx512 = yes/no --- -mavx512bw --- Use Intel Advanced Vector Extensions 512
+# vnni256 = yes/no --- -mavx512vnni --- Use Intel Vector Neural Network Instructions 256
+# vnni512 = yes/no --- -mavx512vnni --- Use Intel Vector Neural Network Instructions 512
+# neon = yes/no --- -DUSE_NEON --- Use ARM SIMD architecture
+#
+# Note that Makefile is space sensitive, so when adding new architectures
+# or modifying existing flags, you have to make sure there are no extra spaces
+# at the end of the line for flag values.
+#
+# Example of use for these flags:
+# make build ARCH=x86-64-avx512 debug=on sanitize="address undefined"
+
+
+### 2.1. General and architecture defaults
+largeboards = no
+all = no
+precomputedmagics = yes
+nnue = no
+load_net = $(if $(filter $(nnue),yes),net)
+
+ifeq ($(ARCH),)
+ ARCH = x86-64-modern
+ help_skip_sanity = yes
+endif
+# explicitly check for the list of supported architectures (as listed with make help),
+# the user can override with `make ARCH=x86-32-vnni256 SUPPORTED_ARCH=true`
+ifeq ($(ARCH), $(filter $(ARCH), \
+ x86-64-vnni512 x86-64-vnni256 x86-64-avx512 x86-64-bmi2 x86-64-avx2 \
+ x86-64-sse41-popcnt x86-64-modern x86-64-ssse3 x86-64-sse3-popcnt \
+ x86-64 x86-32-sse41-popcnt x86-32-sse2 x86-32 ppc-64 ppc-32 e2k \
+ armv7 armv7-neon armv8 apple-silicon general-64 general-32))
+ SUPPORTED_ARCH=true
+else
+ SUPPORTED_ARCH=false
+endif
+
+optimize = yes
+debug = no
+sanitize = none
+bits = 64
+prefetch = no
+popcnt = no
+pext = no
+sse = no
+mmx = no
+sse2 = no
+ssse3 = no
+sse41 = no
+avx2 = no
+avx512 = no
+vnni256 = no
+vnni512 = no
+neon = no
+STRIP = strip
+
+### 2.2 Architecture specific
+
+ifeq ($(findstring x86,$(ARCH)),x86)
+
+# x86-32/64
+
+ifeq ($(findstring x86-32,$(ARCH)),x86-32)
+ arch = i386
+ bits = 32
+ sse = yes
+ mmx = yes
+else
+ arch = x86_64
+ sse = yes
+ sse2 = yes
+endif
+
+ifeq ($(findstring -sse,$(ARCH)),-sse)
+ sse = yes
+endif
+
+ifeq ($(findstring -popcnt,$(ARCH)),-popcnt)
+ popcnt = yes
+endif
+
+ifeq ($(findstring -mmx,$(ARCH)),-mmx)
+ mmx = yes
+endif
+
+ifeq ($(findstring -sse2,$(ARCH)),-sse2)
+ sse = yes
+ sse2 = yes
+endif
+
+ifeq ($(findstring -ssse3,$(ARCH)),-ssse3)
+ sse = yes
+ sse2 = yes
+ ssse3 = yes
+endif
+
+ifeq ($(findstring -sse41,$(ARCH)),-sse41)
+ sse = yes
+ sse2 = yes
+ ssse3 = yes
+ sse41 = yes
+endif
+
+ifeq ($(findstring -modern,$(ARCH)),-modern)
+ popcnt = yes
+ sse = yes
+ sse2 = yes
+ ssse3 = yes
+ sse41 = yes
+endif
+
+ifeq ($(findstring -avx2,$(ARCH)),-avx2)
+ popcnt = yes
+ sse = yes
+ sse2 = yes
+ ssse3 = yes
+ sse41 = yes
+ avx2 = yes
+endif
+
+ifeq ($(findstring -bmi2,$(ARCH)),-bmi2)
+ popcnt = yes
+ sse = yes
+ sse2 = yes
+ ssse3 = yes
+ sse41 = yes
+ avx2 = yes
+ pext = yes
+endif
+
+ifeq ($(findstring -avx512,$(ARCH)),-avx512)
+ popcnt = yes
+ sse = yes
+ sse2 = yes
+ ssse3 = yes
+ sse41 = yes
+ avx2 = yes
+ pext = yes
+ avx512 = yes
+endif
+
+ifeq ($(findstring -vnni256,$(ARCH)),-vnni256)
+ popcnt = yes
+ sse = yes
+ sse2 = yes
+ ssse3 = yes
+ sse41 = yes
+ avx2 = yes
+ pext = yes
+ vnni256 = yes
+endif
+
+ifeq ($(findstring -vnni512,$(ARCH)),-vnni512)
+ popcnt = yes
+ sse = yes
+ sse2 = yes
+ ssse3 = yes
+ sse41 = yes
+ avx2 = yes
+ pext = yes
+ avx512 = yes
+ vnni512 = yes
+endif
+
+ifeq ($(sse),yes)
+ prefetch = yes
+endif
+
+# 64-bit pext is not available on x86-32
+ifeq ($(bits),32)
+ pext = no
+endif
+
+else
+
+# all other architectures
+
+ifeq ($(ARCH),general-32)
+ arch = any
+ bits = 32
+endif
+
+ifeq ($(ARCH),general-64)
+ arch = any
+endif
+
+ifeq ($(ARCH),armv7)
+ arch = armv7
+ prefetch = yes
+ bits = 32
+endif
+
+ifeq ($(ARCH),armv7-neon)
+ arch = armv7
+ prefetch = yes
+ popcnt = yes
+ neon = yes
+ bits = 32
+endif
+
+ifeq ($(ARCH),armv8)
+ arch = armv8
+ prefetch = yes
+ popcnt = yes
+ neon = yes
+endif
+
+ifeq ($(ARCH),apple-silicon)
+ arch = arm64
+ prefetch = yes
+ popcnt = yes
+ neon = yes
+endif
+
+ifeq ($(ARCH),ppc-32)
+ arch = ppc
+ bits = 32
+endif
+
+ifeq ($(ARCH),ppc-64)
+ arch = ppc64
+ popcnt = yes
+ prefetch = yes
+endif
+
+ifeq ($(findstring e2k,$(ARCH)),e2k)
+ arch = e2k
+ mmx = yes
+ bits = 64
+ sse = yes
+ sse2 = yes
+ ssse3 = yes
+ sse41 = yes
+ popcnt = yes
+endif
+
+endif
+
+# Disable precomputed magics when 64-bit PEXT is available
+ifeq ($(pext),yes)
+ precomputedmagics = no
+endif
+
+### ==========================================================================
+### Section 3. Low-level Configuration
+### ==========================================================================
+
+### 3.1 Selecting compiler (default = gcc)
+CXXFLAGS += -Wall -Wcast-qual -fno-exceptions -std=c++17 $(EXTRACXXFLAGS)
+DEPENDFLAGS += -std=c++17
+LDFLAGS += $(EXTRALDFLAGS)
+
+# Ignore warning due to missing profile information from unused NNUE features
+CXXFLAGS += -Wno-profile-instr-out-of-date
+
+# Compile version with support for large board variants
+# Use precomputed magics by default if pext is not available
+ifneq ($(largeboards),no)
+ CXXFLAGS += -DLARGEBOARDS
+ ifeq ($(precomputedmagics),yes)
+ CXXFLAGS += -DPRECOMPUTED_MAGICS
+ endif
+endif
+
+# Embed and enable NNUE
+ifeq ($(nnue),no)
+ CXXFLAGS += -DNNUE_EMBEDDING_OFF
+endif
+
+# Enable all variants, even heavyweight ones like duck and amazons
+ifneq ($(all),no)
+ CXXFLAGS += -DALLVARS
+endif
+
+ifeq ($(COMP),)
+ COMP=gcc
+endif
+
+ifeq ($(COMP),gcc)
+ comp=gcc
+ CXX=g++
+ CXXFLAGS += -Wextra -Wshadow
+ ifeq ($(largeboards),no)
+ CXXFLAGS += -pedantic
+ endif
+
+ ifeq ($(arch),$(filter $(arch),armv7 armv8))
+ ifeq ($(OS),Android)
+ CXXFLAGS += -m$(bits)
+ LDFLAGS += -m$(bits)
+ endif
+ else
+ CXXFLAGS += -m$(bits)
+ LDFLAGS += -m$(bits)
+ endif
+
+ ifeq ($(arch),$(filter $(arch),armv7))
+ LDFLAGS += -latomic
+ endif
+
+ ifneq ($(KERNEL),Darwin)
+ LDFLAGS += -Wl,--no-as-needed
+ endif
+endif
+
+ifeq ($(COMP),mingw)
+ comp=mingw
+
+ ifeq ($(KERNEL),Linux)
+ ifeq ($(bits),64)
+ ifeq ($(shell which x86_64-w64-mingw32-c++-posix),)
+ CXX=x86_64-w64-mingw32-c++
+ else
+ CXX=x86_64-w64-mingw32-c++-posix
+ endif
+ else
+ ifeq ($(shell which i686-w64-mingw32-c++-posix),)
+ CXX=i686-w64-mingw32-c++
+ else
+ CXX=i686-w64-mingw32-c++-posix
+ endif
+ endif
+ else
+ CXX=g++
+ endif
+
+ CXXFLAGS += -Wextra -Wshadow
+ LDFLAGS += -static
+endif
+
+ifeq ($(COMP),icc)
+ comp=icc
+ CXX=icpc
+ CXXFLAGS += -diag-disable 1476,10120 -Wcheck -Wabi -Wdeprecated -strict-ansi
+endif
+
+ifeq ($(COMP),clang)
+ comp=clang
+ CXX=clang++
+ CXXFLAGS += -pedantic -Wextra -Wshadow
+
+ ifneq ($(KERNEL),Darwin)
+ ifneq ($(KERNEL),OpenBSD)
+ ifneq ($(KERNEL),FreeBSD)
+ LDFLAGS += -latomic
+ endif
+ endif
+ endif
+
+ ifeq ($(arch),$(filter $(arch),armv7 armv8))
+ ifeq ($(OS),Android)
+ CXXFLAGS += -m$(bits)
+ LDFLAGS += -m$(bits)
+ endif
+ else
+ CXXFLAGS += -m$(bits)
+ LDFLAGS += -m$(bits)
+ endif
+endif
+
+ifeq ($(KERNEL),Darwin)
+ CXXFLAGS += -arch $(arch) -mmacosx-version-min=10.14
+ LDFLAGS += -arch $(arch) -mmacosx-version-min=10.14
+ XCRUN = xcrun
+endif
+
+# To cross-compile for Android, NDK version r21 or later is recommended.
+# In earlier NDK versions, you'll need to pass -fno-addrsig if using GNU binutils.
+# Currently we don't know how to make PGO builds with the NDK yet.
+ifeq ($(COMP),ndk)
+ CXXFLAGS += -stdlib=libc++ -fPIE
+ comp=clang
+ ifeq ($(arch),armv7)
+ CXX=armv7a-linux-androideabi16-clang++
+ CXXFLAGS += -mthumb -march=armv7-a -mfloat-abi=softfp -mfpu=neon
+ STRIP=arm-linux-androideabi-strip
+ endif
+ ifeq ($(arch),armv8)
+ CXX=aarch64-linux-android21-clang++
+ STRIP=aarch64-linux-android-strip
+ endif
+ LDFLAGS += -static-libstdc++ -pie -lm -latomic
+endif
+
+ifeq ($(comp),icc)
+ profile_make = icc-profile-make
+ profile_use = icc-profile-use
+else ifeq ($(comp),clang)
+ profile_make = clang-profile-make
+ profile_use = clang-profile-use
+else
+ profile_make = gcc-profile-make
+ profile_use = gcc-profile-use
+endif
+
+### Travis CI script uses COMPILER to overwrite CXX
+ifdef COMPILER
+ COMPCXX=$(COMPILER)
+endif
+
+### Allow overwriting CXX from command line
+ifdef COMPCXX
+ CXX=$(COMPCXX)
+endif
+
+### Sometimes gcc is really clang
+ifeq ($(COMP),gcc)
+ gccversion = $(shell $(CXX) --version)
+ gccisclang = $(findstring clang,$(gccversion))
+ ifneq ($(gccisclang),)
+ profile_make = clang-profile-make
+ profile_use = clang-profile-use
+ endif
+endif
+
+### On mingw use Windows threads, otherwise POSIX
+ifneq ($(comp),mingw)
+ CXXFLAGS += -DUSE_PTHREADS
+ # On Android Bionic's C library comes with its own pthread implementation bundled in
+ ifneq ($(OS),Android)
+ # Haiku has pthreads in its libroot, so only link it in on other platforms
+ ifneq ($(KERNEL),Haiku)
+ ifneq ($(COMP),ndk)
+ LDFLAGS += -lpthread
+ endif
+ endif
+ endif
+endif
+
+### 3.2.1 Debugging
+ifeq ($(debug),no)
+ CXXFLAGS += -DNDEBUG
+else
+ CXXFLAGS += -g
+endif
+
+### 3.2.2 Debugging with undefined behavior sanitizers
+ifneq ($(sanitize),none)
+ CXXFLAGS += -g3 $(addprefix -fsanitize=,$(sanitize))
+ LDFLAGS += $(addprefix -fsanitize=,$(sanitize))
+endif
+
+### 3.3 Optimization
+ifeq ($(optimize),yes)
+
+ CXXFLAGS += -O3 -fno-strict-aliasing
+
+ ifeq ($(comp),gcc)
+ ifeq ($(OS), Android)
+ CXXFLAGS += -fno-gcse -mthumb -march=armv7-a -mfloat-abi=softfp
+ endif
+ endif
+
+ ifeq ($(comp),$(filter $(comp),gcc clang icc))
+ ifeq ($(KERNEL),Darwin)
+ CXXFLAGS += -mdynamic-no-pic
+ endif
+ endif
+
+ ifeq ($(comp),clang)
+ clangmajorversion = $(shell $(CXX) -dumpversion 2>/dev/null | cut -f1 -d.)
+ ifeq ($(shell expr $(clangmajorversion) \< 16),1)
+ CXXFLAGS += -fexperimental-new-pass-manager
+ endif
+ endif
+endif
+
+### 3.4 Bits
+ifeq ($(bits),64)
+ CXXFLAGS += -DIS_64BIT
+endif
+
+### 3.5 prefetch
+ifeq ($(prefetch),yes)
+ ifeq ($(sse),yes)
+ CXXFLAGS += -msse
+ endif
+else
+ CXXFLAGS += -DNO_PREFETCH
+endif
+
+### 3.6 popcnt
+ifeq ($(popcnt),yes)
+ ifeq ($(arch),$(filter $(arch),ppc64 armv7 armv8 arm64))
+ CXXFLAGS += -DUSE_POPCNT
+ else ifeq ($(comp),icc)
+ CXXFLAGS += -msse3 -DUSE_POPCNT
+ else
+ CXXFLAGS += -msse3 -mpopcnt -DUSE_POPCNT
+ endif
+endif
+
+ifeq ($(avx2),yes)
+ CXXFLAGS += -DUSE_AVX2
+ ifeq ($(comp),$(filter $(comp),gcc clang mingw))
+ CXXFLAGS += -mavx2 -mbmi
+ endif
+endif
+
+ifeq ($(avx512),yes)
+ CXXFLAGS += -DUSE_AVX512
+ ifeq ($(comp),$(filter $(comp),gcc clang mingw))
+ CXXFLAGS += -mavx512f -mavx512bw
+ endif
+endif
+
+ifeq ($(vnni256),yes)
+ CXXFLAGS += -DUSE_VNNI
+ ifeq ($(comp),$(filter $(comp),gcc clang mingw))
+ CXXFLAGS += -mavx512f -mavx512bw -mavx512vnni -mavx512dq -mavx512vl -mprefer-vector-width=256
+ endif
+endif
+
+ifeq ($(vnni512),yes)
+ CXXFLAGS += -DUSE_VNNI
+ ifeq ($(comp),$(filter $(comp),gcc clang mingw))
+ CXXFLAGS += -mavx512vnni -mavx512dq -mavx512vl
+ endif
+endif
+
+ifeq ($(sse41),yes)
+ CXXFLAGS += -DUSE_SSE41
+ ifeq ($(comp),$(filter $(comp),gcc clang mingw))
+ CXXFLAGS += -msse4.1
+ endif
+endif
+
+ifeq ($(ssse3),yes)
+ CXXFLAGS += -DUSE_SSSE3
+ ifeq ($(comp),$(filter $(comp),gcc clang mingw))
+ CXXFLAGS += -mssse3
+ endif
+endif
+
+ifeq ($(sse2),yes)
+ CXXFLAGS += -DUSE_SSE2
+ ifeq ($(comp),$(filter $(comp),gcc clang mingw))
+ CXXFLAGS += -msse2
+ endif
+endif
+
+ifeq ($(mmx),yes)
+ CXXFLAGS += -DUSE_MMX
+ ifeq ($(comp),$(filter $(comp),gcc clang mingw))
+ CXXFLAGS += -mmmx
+ endif
+endif
+
+ifeq ($(neon),yes)
+ CXXFLAGS += -DUSE_NEON
+ ifeq ($(KERNEL),Linux)
+ ifneq ($(COMP),ndk)
+ ifneq ($(arch),armv8)
+ CXXFLAGS += -mfpu=neon
+ endif
+ endif
+ endif
+endif
+
+### 3.7 pext
+ifeq ($(pext),yes)
+ CXXFLAGS += -DUSE_PEXT
+ ifeq ($(comp),$(filter $(comp),gcc clang mingw))
+ CXXFLAGS += -mbmi2
+ endif
+endif
+
+### 3.8 Link Time Optimization
+### This is a mix of compile and link time options because the lto link phase
+### needs access to the optimization flags.
+ifeq ($(optimize),yes)
+ifeq ($(debug), no)
+ ifeq ($(comp),clang)
+ CXXFLAGS += -flto
+ ifneq ($(findstring MINGW,$(KERNEL)),)
+ CXXFLAGS += -fuse-ld=lld
+ else ifneq ($(findstring MSYS,$(KERNEL)),)
+ CXXFLAGS += -fuse-ld=lld
+ endif
+ LDFLAGS += $(CXXFLAGS)
+
+# GCC and CLANG use different methods for parallelizing LTO and CLANG pretends to be
+# GCC on some systems.
+ else ifeq ($(comp),gcc)
+ ifeq ($(gccisclang),)
+ CXXFLAGS += -flto
+ LDFLAGS += $(CXXFLAGS) -flto=jobserver
+ ifneq ($(findstring MINGW,$(KERNEL)),)
+ LDFLAGS += -save-temps
+ else ifneq ($(findstring MSYS,$(KERNEL)),)
+ LDFLAGS += -save-temps
+ endif
+ else
+ CXXFLAGS += -flto
+ LDFLAGS += $(CXXFLAGS)
+ endif
+
+# To use LTO and static linking on windows, the tool chain requires a recent gcc:
+# gcc version 10.1 in msys2 or TDM-GCC version 9.2 are known to work, older might not.
+# So, only enable it for a cross from Linux by default.
+ else ifeq ($(comp),mingw)
+ ifeq ($(KERNEL),Linux)
+ ifneq ($(arch),i386)
+ CXXFLAGS += -flto
+ LDFLAGS += $(CXXFLAGS) -flto=jobserver
+ endif
+ endif
+ endif
+endif
+endif
+
+### 3.9 Android 5 can only run position independent executables. Note that this
+### breaks Android 4.0 and earlier.
+ifeq ($(OS), Android)
+ CXXFLAGS += -fPIE
+ LDFLAGS += -fPIE -pie
+endif
+
+### ==========================================================================
+### Section 4. Public Targets
+### ==========================================================================
+
+
+help:
+ @echo ""
+ @echo "To compile stockfish, type: "
+ @echo ""
+ @echo "make target ARCH=arch [COMP=compiler] [COMPCXX=cxx]"
+ @echo ""
+ @echo "Supported targets:"
+ @echo ""
+ @echo "help > Display architecture details"
+ @echo "build > Standard build"
+ @echo "net > Download the default nnue net"
+ @echo "profile-build > Faster build (with profile-guided optimization)"
+ @echo "strip > Strip executable"
+ @echo "install > Install executable"
+ @echo "clean > Clean up"
+ @echo ""
+ @echo "Supported archs:"
+ @echo ""
+ @echo "x86-64-vnni512 > x86 64-bit with vnni support 512bit wide"
+ @echo "x86-64-vnni256 > x86 64-bit with vnni support 256bit wide"
+ @echo "x86-64-avx512 > x86 64-bit with avx512 support"
+ @echo "x86-64-bmi2 > x86 64-bit with bmi2 support"
+ @echo "x86-64-avx2 > x86 64-bit with avx2 support"
+ @echo "x86-64-sse41-popcnt > x86 64-bit with sse41 and popcnt support"
+ @echo "x86-64-modern > common modern CPU, currently x86-64-sse41-popcnt"
+ @echo "x86-64-ssse3 > x86 64-bit with ssse3 support"
+ @echo "x86-64-sse3-popcnt > x86 64-bit with sse3 and popcnt support"
+ @echo "x86-64 > x86 64-bit generic (with sse2 support)"
+ @echo "x86-32-sse41-popcnt > x86 32-bit with sse41 and popcnt support"
+ @echo "x86-32-sse2 > x86 32-bit with sse2 support"
+ @echo "x86-32 > x86 32-bit generic (with mmx and sse support)"
+ @echo "ppc-64 > PPC 64-bit"
+ @echo "ppc-32 > PPC 32-bit"
+ @echo "armv7 > ARMv7 32-bit"
+ @echo "armv7-neon > ARMv7 32-bit with popcnt and neon"
+ @echo "armv8 > ARMv8 64-bit with popcnt and neon"
+ @echo "e2k > Elbrus 2000"
+ @echo "apple-silicon > Apple silicon ARM64"
+ @echo "general-64 > unspecified 64-bit"
+ @echo "general-32 > unspecified 32-bit"
+ @echo ""
+ @echo "Supported compilers:"
+ @echo ""
+ @echo "gcc > Gnu compiler (default)"
+ @echo "mingw > Gnu compiler with MinGW under Windows"
+ @echo "clang > LLVM Clang compiler"
+ @echo "icc > Intel compiler"
+ @echo "ndk > Google NDK to cross-compile for Android"
+ @echo ""
+ @echo "Simple examples. If you don't know what to do, you likely want to run: "
+ @echo ""
+ @echo "make -j build ARCH=x86-64 (A portable, slow compile for 64-bit systems)"
+ @echo "make -j build ARCH=x86-32 (A portable, slow compile for 32-bit systems)"
+ @echo ""
+ @echo "Advanced examples, for experienced users looking for performance: "
+ @echo ""
+ @echo "make help ARCH=x86-64-bmi2"
+ @echo "make -j profile-build ARCH=x86-64-bmi2 COMP=gcc COMPCXX=g++-9.0"
+ @echo "make -j build ARCH=x86-64-ssse3 COMP=clang"
+ @echo ""
+ @echo "-------------------------------"
+ifeq ($(SUPPORTED_ARCH)$(help_skip_sanity), true)
+ @echo "The selected architecture $(ARCH) will enable the following configuration: "
+ @$(MAKE) ARCH=$(ARCH) COMP=$(COMP) config-sanity
+else
+ @echo "Specify a supported architecture with the ARCH option for more details"
+ @echo ""
+ @echo "-------------------------------"
+ @echo "Embed and enable NNUE by default: "
+ @echo ""
+ @echo "make build ARCH=x86-64 nnue=yes"
+ @echo ""
+ @echo "-------------------------------"
+ @echo "Version for large boards: "
+ @echo ""
+ @echo "make build ARCH=x86-64 COMP=gcc largeboards=yes"
+ @echo ""
+ @echo "Include all variants (adds Game of the Amazons): "
+ @echo ""
+ @echo "make build ARCH=x86-64 largeboards=yes all=yes"
+ @echo ""
+endif
+
+
+.PHONY: help build profile-build strip install clean net objclean profileclean \
+ config-sanity icc-profile-use icc-profile-make gcc-profile-use gcc-profile-make \
+ clang-profile-use clang-profile-make
+
+build: $(load_net) config-sanity
+ $(MAKE) ARCH=$(ARCH) COMP=$(COMP) all
+
+profile-build: $(load_net) config-sanity objclean profileclean
+ @echo ""
+ @echo "Step 1/4. Building instrumented executable ..."
+ $(MAKE) ARCH=$(ARCH) COMP=$(COMP) $(profile_make)
+ @echo ""
+ @echo "Step 2/4. Running benchmark for pgo-build ..."
+ $(PGOBENCH) > /dev/null
+ @echo ""
+ @echo "Step 3/4. Building optimized executable ..."
+ $(MAKE) ARCH=$(ARCH) COMP=$(COMP) objclean
+ $(MAKE) ARCH=$(ARCH) COMP=$(COMP) $(profile_use)
+ @echo ""
+ @echo "Step 4/4. Deleting profile data ..."
+ $(MAKE) ARCH=$(ARCH) COMP=$(COMP) profileclean
+
+strip:
+ $(STRIP) $(EXE)
+
+install:
+ -mkdir -p -m 755 $(BINDIR)
+ -cp $(EXE) $(BINDIR)
+ -strip $(BINDIR)/$(EXE)
+
+# clean all
+clean: objclean profileclean
+ @rm -f .depend *~ core
+
+# evaluation network (nnue)
+net:
+ $(eval nnuenet := $(shell grep EvalFileDefaultName evaluate.h | grep define | sed 's/.*\(nn-[a-z0-9]\{12\}.nnue\).*/\1/'))
+ @echo "Default net: $(nnuenet)"
+ $(eval nnuedownloadurl1 := https://tests.stockfishchess.org/api/nn/$(nnuenet))
+ $(eval nnuedownloadurl2 := https://github.com/official-stockfish/networks/raw/master/$(nnuenet))
+ $(eval curl_or_wget := $(shell if hash curl 2>/dev/null; then echo "curl -skL"; elif hash wget 2>/dev/null; then echo "wget -qO-"; fi))
+ @if [ "x$(curl_or_wget)" = "x" ]; then \
+ echo "Automatic download failed: neither curl nor wget is installed. Install one of these tools or download the net manually"; exit 1; \
+ fi
+ $(eval shasum_command := $(shell if hash shasum 2>/dev/null; then echo "shasum -a 256 "; elif hash sha256sum 2>/dev/null; then echo "sha256sum "; fi))
+ @if [ "x$(shasum_command)" = "x" ]; then \
+ echo "shasum / sha256sum not found, skipping net validation"; \
+ fi
+ @for nnuedownloadurl in "$(nnuedownloadurl1)" "$(nnuedownloadurl2)"; do \
+ if test -f "$(nnuenet)"; then \
+ echo "$(nnuenet) available."; \
+ else \
+ if [ "x$(curl_or_wget)" != "x" ]; then \
+ echo "Downloading $${nnuedownloadurl}"; $(curl_or_wget) $${nnuedownloadurl} > $(nnuenet);\
+ fi; \
+ fi; \
+ if [ "x$(shasum_command)" != "x" ]; then \
+ if [ "$(nnuenet)" != "nn-"`$(shasum_command) $(nnuenet) | cut -c1-12`".nnue" ]; then \
+ echo "Removing failed download"; rm -f $(nnuenet); \
+ else \
+ echo "Network validated"; break; \
+ fi; \
+ fi; \
+ done
+ @if ! test -f "$(nnuenet)"; then \
+ echo "Failed to download $(nnuenet)."; \
+ fi
+
+# clean binaries and objects
+objclean:
+ @rm -f $(EXE) *.o ./syzygy/*.o ./nnue/*.o ./nnue/features/*.o
+
+# clean auxiliary profiling files
+profileclean:
+ @rm -rf profdir
+ @rm -f bench.txt *.gcda *.gcno ./syzygy/*.gcda ./nnue/*.gcda ./nnue/features/*.gcda *.s
+ @rm -f stockfish.profdata *.profraw
+ @rm -f stockfish.exe.lto_wrapper_args
+ @rm -f stockfish.exe.ltrans.out
+ @rm -f ./-lstdc++.res
+
+default:
+ help
+
+### ==========================================================================
+### Section 5. Private Targets
+### ==========================================================================
+
+all: $(EXE) .depend
+
+config-sanity: $(load_net)
+ @echo ""
+ @echo "Config:"
+ @echo "debug: '$(debug)'"
+ @echo "sanitize: '$(sanitize)'"
+ @echo "optimize: '$(optimize)'"
+ @echo "arch: '$(arch)'"
+ @echo "bits: '$(bits)'"
+ @echo "kernel: '$(KERNEL)'"
+ @echo "os: '$(OS)'"
+ @echo "prefetch: '$(prefetch)'"
+ @echo "popcnt: '$(popcnt)'"
+ @echo "pext: '$(pext)'"
+ @echo "sse: '$(sse)'"
+ @echo "mmx: '$(mmx)'"
+ @echo "sse2: '$(sse2)'"
+ @echo "ssse3: '$(ssse3)'"
+ @echo "sse41: '$(sse41)'"
+ @echo "avx2: '$(avx2)'"
+ @echo "avx512: '$(avx512)'"
+ @echo "vnni256: '$(vnni256)'"
+ @echo "vnni512: '$(vnni512)'"
+ @echo "neon: '$(neon)'"
+ @echo ""
+ @echo "Fairy-Stockfish specific:"
+ @echo "largeboards: '$(largeboards)'"
+ @echo "all: '$(all)'"
+ @echo "precomputedmagics: '$(precomputedmagics)'"
+ @echo "nnue: '$(nnue)'"
+ @echo ""
+ @echo "Flags:"
+ @echo "CXX: $(CXX)"
+ @echo "CXXFLAGS: $(CXXFLAGS)"
+ @echo "LDFLAGS: $(LDFLAGS)"
+ @echo ""
+ @echo "Testing config sanity. If this fails, try 'make help' ..."
+ @echo ""
+ @test "$(debug)" = "yes" || test "$(debug)" = "no"
+ @test "$(optimize)" = "yes" || test "$(optimize)" = "no"
+ @test "$(SUPPORTED_ARCH)" = "true"
+ @test "$(arch)" = "any" || test "$(arch)" = "x86_64" || test "$(arch)" = "i386" || \
+ test "$(arch)" = "ppc64" || test "$(arch)" = "ppc" || test "$(arch)" = "e2k" || \
+ test "$(arch)" = "armv7" || test "$(arch)" = "armv8" || test "$(arch)" = "arm64"
+ @test "$(bits)" = "32" || test "$(bits)" = "64"
+ @test "$(prefetch)" = "yes" || test "$(prefetch)" = "no"
+ @test "$(popcnt)" = "yes" || test "$(popcnt)" = "no"
+ @test "$(pext)" = "yes" || test "$(pext)" = "no"
+ @test "$(sse)" = "yes" || test "$(sse)" = "no"
+ @test "$(mmx)" = "yes" || test "$(mmx)" = "no"
+ @test "$(sse2)" = "yes" || test "$(sse2)" = "no"
+ @test "$(ssse3)" = "yes" || test "$(ssse3)" = "no"
+ @test "$(sse41)" = "yes" || test "$(sse41)" = "no"
+ @test "$(avx2)" = "yes" || test "$(avx2)" = "no"
+ @test "$(avx512)" = "yes" || test "$(avx512)" = "no"
+ @test "$(vnni256)" = "yes" || test "$(vnni256)" = "no"
+ @test "$(vnni512)" = "yes" || test "$(vnni512)" = "no"
+ @test "$(neon)" = "yes" || test "$(neon)" = "no"
+ @test "$(comp)" = "gcc" || test "$(comp)" = "icc" || test "$(comp)" = "mingw" || test "$(comp)" = "clang" \
+ || test "$(comp)" = "armv7a-linux-androideabi16-clang" || test "$(comp)" = "aarch64-linux-android21-clang"
+
+$(EXE): $(OBJS)
+ +$(CXX) -o $@ $(OBJS) $(LDFLAGS)
+
+clang-profile-make:
+ $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
+ EXTRACXXFLAGS='-fprofile-instr-generate ' \
+ EXTRALDFLAGS=' -fprofile-instr-generate' \
+ all
+
+clang-profile-use:
+ $(XCRUN) llvm-profdata merge -output=stockfish.profdata *.profraw
+ $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
+ EXTRACXXFLAGS='-fprofile-instr-use=stockfish.profdata' \
+ EXTRALDFLAGS='-fprofile-use ' \
+ all
+
+gcc-profile-make:
+ @mkdir -p profdir
+ $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
+ EXTRACXXFLAGS='-fprofile-generate=profdir' \
+ EXTRALDFLAGS='-lgcov' \
+ all
+
+gcc-profile-use:
+ $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
+ EXTRACXXFLAGS='-fprofile-use=profdir -fno-peel-loops -fno-tracer' \
+ EXTRALDFLAGS='-lgcov' \
+ all
+
+icc-profile-make:
+ @mkdir -p profdir
+ $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
+ EXTRACXXFLAGS='-prof-gen=srcpos -prof_dir ./profdir' \
+ all
+
+icc-profile-use:
+ $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
+ EXTRACXXFLAGS='-prof_use -prof_dir ./profdir' \
+ all
+
+.depend:
+ -@$(CXX) $(DEPENDFLAGS) -MM $(SRCS) > $@ 2> /dev/null
+
+-include .depend
diff --git a/Fairy-Stockfish-master/src/Makefile_js b/Fairy-Stockfish-master/src/Makefile_js
new file mode 100644
index 0000000000000000000000000000000000000000..a224a71d0d872b90711d62acc738498154b35210
--- /dev/null
+++ b/Fairy-Stockfish-master/src/Makefile_js
@@ -0,0 +1,95 @@
+# ffish.js, a JavaScript chess variant library derived from Fairy-Stockfish
+# Copyright (C) 2022 Fabian Fichter, Johannes Czech
+#
+# ffish.js is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# ffish.js is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+EXE = ../tests/js/ffish.js
+
+SRCS = ffishjs.cpp benchmark.cpp bitbase.cpp bitboard.cpp endgame.cpp evaluate.cpp \
+ material.cpp misc.cpp movegen.cpp movepick.cpp pawns.cpp position.cpp psqt.cpp \
+ search.cpp thread.cpp timeman.cpp tt.cpp uci.cpp ucioption.cpp tune.cpp syzygy/tbprobe.cpp \
+ nnue/evaluate_nnue.cpp nnue/features/half_ka_v2.cpp \
+ partner.cpp parser.cpp piece.cpp variant.cpp xboard.cpp \
+ nnue/features/half_ka_v2_variants.cpp
+
+CXX=emcc
+CXXFLAGS += --bind -DNNUE_EMBEDDING_OFF -DNO_THREADS -std=c++17 -Wall
+
+largeboards = yes
+all = yes
+optimize = yes
+debug = no
+
+### Debugging
+ifeq ($(debug),no)
+ CXXFLAGS += -DNDEBUG -s ASSERTIONS=0 -s SAFE_HEAP=0
+else
+ CXXFLAGS += -g -s ASSERTIONS=1 -s SAFE_HEAP=1
+endif
+
+### Optimization
+ifeq ($(optimize),yes)
+ CXXFLAGS += -O3
+endif
+
+# Compile version with support for large board variants
+# Use precomputed magics by default
+ifneq ($(largeboards),no)
+ CXXFLAGS += -DLARGEBOARDS -DPRECOMPUTED_MAGICS -s TOTAL_MEMORY=32MB -s ALLOW_MEMORY_GROWTH=1 -s WASM_MEM_MAX=1GB
+endif
+
+# Enable all variants, even heavyweight ones like duck and amazons
+ifneq ($(all),no)
+ CXXFLAGS += -DALLVARS
+endif
+
+### Compile as ES6/ES2015 module
+ifeq ($(es6),yes)
+ CXXFLAGS += -s ENVIRONMENT='web,worker' -s EXPORT_ES6=1 -s MODULARIZE=1 -s USE_ES6_IMPORT_META=0
+endif
+
+.PHONY: help objclean clean build deps test serve
+
+help:
+ @echo ""
+ @echo "To compile ffishjs, type: "
+ @echo ""
+ @echo "make -f Makefile_js build"
+ @echo ""
+ @echo "Supported targets:"
+ @echo ""
+ @echo "help > Display this help"
+ @echo "build > Standard build"
+ @echo "clean > Clean up"
+ @echo "deps > Install runtime dependencies using npm"
+ @echo "test > Run tests"
+ @echo "serve > Run example server"
+ @echo ""
+
+objclean:
+ @rm -f $(EXE)
+
+clean: objclean
+
+build:
+ $(CXX) $(CXXFLAGS) $(SRCS) -o $(EXE)
+
+deps:
+ cd ../tests/js && npm install
+
+test: deps
+ cd ../tests/js && npm test
+
+serve: deps
+ cd ../tests/js && node index.js
diff --git a/Fairy-Stockfish-master/src/apiutil.h b/Fairy-Stockfish-master/src/apiutil.h
new file mode 100644
index 0000000000000000000000000000000000000000..c898cf2ca529dc867d55d43a5a019bbbe96cdc41
--- /dev/null
+++ b/Fairy-Stockfish-master/src/apiutil.h
@@ -0,0 +1,1165 @@
+/*
+ Fairy-Stockfish, a UCI chess variant playing engine derived from Stockfish
+ Copyright (C) 2018-2022 Fabian Fichter
+
+ Fairy-Stockfish is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Fairy-Stockfish is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef APIUTIL_H_INCLUDED
+#define APIUTIL_H_INCLUDED
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "types.h"
+#include "position.h"
+#include "variant.h"
+
+namespace Stockfish {
+
+enum Notation {
+ NOTATION_DEFAULT,
+ // https://en.wikipedia.org/wiki/Algebraic_notation_(chess)
+ NOTATION_SAN,
+ NOTATION_LAN,
+ // https://en.wikipedia.org/wiki/Shogi_notation#Western_notation
+ NOTATION_SHOGI_HOSKING, // Examples: P76, S’34
+ NOTATION_SHOGI_HODGES, // Examples: P-7f, S*3d
+ NOTATION_SHOGI_HODGES_NUMBER, // Examples: P-76, S*34
+ // http://www.janggi.pl/janggi-notation/
+ NOTATION_JANGGI,
+ // https://en.wikipedia.org/wiki/Xiangqi#Notation
+ NOTATION_XIANGQI_WXF,
+ // https://web.archive.org/web/20180817205956/http://bgsthai.com/2018/05/07/lawofthaichessc/
+ NOTATION_THAI_SAN,
+ NOTATION_THAI_LAN,
+};
+
+inline Notation default_notation(const Variant* v) {
+ if (v->variantTemplate == "shogi")
+ return NOTATION_SHOGI_HODGES_NUMBER;
+ return NOTATION_SAN;
+}
+
+enum Termination {
+ ONGOING,
+ CHECKMATE,
+ STALEMATE,
+ INSUFFICIENT_MATERIAL,
+ N_MOVE_RULE,
+ N_FOLD_REPETITION,
+ VARIANT_END,
+};
+
+const std::array THAI_FILES = {"ก", "ข", "ค", "ง", "จ", "ฉ", "ช", "ญ", "ต", "ถ", "ธ", "น"};
+const std::array THAI_RANKS = {"๑", "๒", "๓", "๔", "๕", "๖", "๗", "๘", "๙", "๑๐", "๑๑", "๑๒"};
+
+namespace SAN {
+
+enum Disambiguation {
+ NO_DISAMBIGUATION,
+ FILE_DISAMBIGUATION,
+ RANK_DISAMBIGUATION,
+ SQUARE_DISAMBIGUATION,
+};
+
+inline bool is_shogi(Notation n) {
+ return n == NOTATION_SHOGI_HOSKING || n == NOTATION_SHOGI_HODGES || n == NOTATION_SHOGI_HODGES_NUMBER;
+}
+
+inline bool is_thai(Notation n) {
+ return n == NOTATION_THAI_SAN || n == NOTATION_THAI_LAN;
+}
+
+// is there more than one file with a pair of pieces?
+inline bool multi_tandem(Bitboard b) {
+ int tandems = 0;
+ for (File f = FILE_A; f <= FILE_MAX; ++f)
+ if (more_than_one(b & file_bb(f)))
+ tandems++;
+ return tandems >= 2;
+}
+
+inline std::string piece_to_thai_char(Piece pc, bool promoted) {
+ switch(type_of(pc)) {
+ case KING:
+ return "ข";
+ case KHON:
+ return "ค";
+ case FERS:
+ return promoted ? "ง" : "ม็";
+ case KNIGHT:
+ return "ม";
+ case ROOK:
+ return "ร";
+ case PAWN:
+ return "บ";
+ case AIWOK:
+ return "ว";
+ default:
+ return "X";
+ }
+}
+
+inline std::string piece(const Position& pos, Move m, Notation n) {
+ Color us = pos.side_to_move();
+ Square from = from_sq(m);
+ Piece pc = pos.moved_piece(m);
+ PieceType pt = type_of(pc);
+ // Quiet pawn moves
+ if ((n == NOTATION_SAN || n == NOTATION_LAN || n == NOTATION_THAI_SAN) && type_of(pc) == PAWN && type_of(m) != DROP)
+ return "";
+ // Tandem pawns
+ else if (n == NOTATION_XIANGQI_WXF && popcount(pos.pieces(us, pt) & file_bb(from)) >= 3 - multi_tandem(pos.pieces(us, pt)))
+ return std::to_string(popcount(forward_file_bb(us, from) & pos.pieces(us, pt)) + 1);
+ // Moves of promoted pieces
+ else if (is_shogi(n) && type_of(m) != DROP && pos.unpromoted_piece_on(from))
+ return "+" + std::string(1, toupper(pos.piece_to_char()[pos.unpromoted_piece_on(from)]));
+ // Promoted drops
+ else if (is_shogi(n) && type_of(m) == DROP && dropped_piece_type(m) != in_hand_piece_type(m))
+ return "+" + std::string(1, toupper(pos.piece_to_char()[in_hand_piece_type(m)]));
+ else if (is_thai(n))
+ return piece_to_thai_char(pc, pos.is_promoted(from));
+ else if (pos.piece_to_char_synonyms()[pc] != ' ')
+ return std::string(1, toupper(pos.piece_to_char_synonyms()[pc]));
+ else
+ return std::string(1, toupper(pos.piece_to_char()[pc]));
+}
+
+inline std::string file(const Position& pos, Square s, Notation n) {
+ switch (n)
+ {
+ case NOTATION_SHOGI_HOSKING:
+ case NOTATION_SHOGI_HODGES:
+ case NOTATION_SHOGI_HODGES_NUMBER:
+ return std::to_string(pos.max_file() - file_of(s) + 1);
+ case NOTATION_JANGGI:
+ return std::to_string(file_of(s) + 1);
+ case NOTATION_XIANGQI_WXF:
+ return std::to_string((pos.side_to_move() == WHITE ? pos.max_file() - file_of(s) : file_of(s)) + 1);
+ case NOTATION_THAI_SAN:
+ case NOTATION_THAI_LAN:
+ return THAI_FILES[file_of(s)];
+ default:
+ return std::string(1, char('a' + file_of(s)));
+ }
+}
+
+inline std::string rank(const Position& pos, Square s, Notation n) {
+ switch (n)
+ {
+ case NOTATION_SHOGI_HOSKING:
+ case NOTATION_SHOGI_HODGES_NUMBER:
+ return std::to_string(pos.max_rank() - rank_of(s) + 1);
+ case NOTATION_SHOGI_HODGES:
+ return std::string(1, char('a' + pos.max_rank() - rank_of(s)));
+ case NOTATION_JANGGI:
+ return std::to_string((pos.max_rank() - rank_of(s) + 1) % 10);
+ case NOTATION_XIANGQI_WXF:
+ {
+ if (pos.empty(s))
+ // Handle piece drops
+ return std::to_string(relative_rank(pos.side_to_move(), s, pos.max_rank()) + 1);
+ else if (pos.pieces(pos.side_to_move(), type_of(pos.piece_on(s))) & forward_file_bb(pos.side_to_move(), s))
+ return "-";
+ else
+ return "+";
+ }
+ case NOTATION_THAI_SAN:
+ case NOTATION_THAI_LAN:
+ return THAI_RANKS[rank_of(s)];
+ default:
+ return std::to_string(rank_of(s) + 1);
+ }
+}
+
+inline std::string square(const Position& pos, Square s, Notation n) {
+ switch (n)
+ {
+ case NOTATION_JANGGI:
+ return rank(pos, s, n) + file(pos, s, n);
+ default:
+ return file(pos, s, n) + rank(pos, s, n);
+ }
+}
+
+inline Disambiguation disambiguation_level(const Position& pos, Move m, Notation n) {
+ // Drops never need disambiguation
+ if (type_of(m) == DROP)
+ return NO_DISAMBIGUATION;
+
+ // NOTATION_LAN and Janggi always use disambiguation
+ if (n == NOTATION_LAN || n == NOTATION_THAI_LAN || n == NOTATION_JANGGI)
+ return SQUARE_DISAMBIGUATION;
+
+ Color us = pos.side_to_move();
+ Square from = from_sq(m);
+ Square to = to_sq(m);
+ Piece pc = pos.moved_piece(m);
+ PieceType pt = type_of(pc);
+
+ // Xiangqi uses either file disambiguation or +/- if two pieces on file
+ if (n == NOTATION_XIANGQI_WXF)
+ {
+ // Disambiguate by rank (+/-) if target square of other piece is valid
+ if (popcount(pos.pieces(us, pt) & file_bb(from)) == 2 && !multi_tandem(pos.pieces(us, pt)))
+ {
+ Square otherFrom = lsb((pos.pieces(us, pt) & file_bb(from)) ^ from);
+ Square otherTo = otherFrom + Direction(to) - Direction(from);
+ if (is_ok(otherTo) && (pos.board_bb(us, pt) & otherTo))
+ return RANK_DISAMBIGUATION;
+ }
+ return FILE_DISAMBIGUATION;
+ }
+
+ // Pawn captures always use disambiguation
+ if ((n == NOTATION_SAN || n == NOTATION_THAI_SAN) && pt == PAWN)
+ {
+ if (pos.capture(m))
+ return FILE_DISAMBIGUATION;
+ if (type_of(m) == PROMOTION && from != to && pos.sittuyin_promotion())
+ return SQUARE_DISAMBIGUATION;
+ }
+
+ // A disambiguation occurs if we have more than one piece of type 'pt'
+ // that can reach 'to' with a legal move.
+ Bitboard b = pos.pieces(us, pt) ^ from;
+ Bitboard others = 0;
+
+ while (b)
+ {
+ Square s = pop_lsb(b);
+ // Construct a potential move with identical special move flags
+ // and only a different "from" square.
+ Move testMove = Move(m ^ make_move(from, to) ^ make_move(s, to));
+ if ( pos.pseudo_legal(testMove)
+ && pos.legal(testMove)
+ && !(is_shogi(n) && pos.unpromoted_piece_on(s) != pos.unpromoted_piece_on(from)))
+ others |= s;
+ }
+
+ if (!others)
+ return NO_DISAMBIGUATION;
+ else if (is_shogi(n))
+ return SQUARE_DISAMBIGUATION;
+ else if (!(others & file_bb(from)))
+ return FILE_DISAMBIGUATION;
+ else if (!(others & rank_bb(from)))
+ return RANK_DISAMBIGUATION;
+ else
+ return SQUARE_DISAMBIGUATION;
+}
+
+inline std::string disambiguation(const Position& pos, Square s, Notation n, Disambiguation d) {
+ switch (d)
+ {
+ case FILE_DISAMBIGUATION:
+ return file(pos, s, n);
+ case RANK_DISAMBIGUATION:
+ return rank(pos, s, n);
+ case SQUARE_DISAMBIGUATION:
+ return square(pos, s, n);
+ default:
+ assert(d == NO_DISAMBIGUATION);
+ return "";
+ }
+}
+
+inline const std::string move_to_san(Position& pos, Move m, Notation n) {
+ std::string san = "";
+ Color us = pos.side_to_move();
+ Square from = from_sq(m);
+ Square to = to_sq(m);
+
+ if (type_of(m) == CASTLING)
+ {
+ san = to > from ? "O-O" : "O-O-O";
+
+ if (is_gating(m))
+ {
+ san += std::string("/") + (char)toupper(pos.piece_to_char()[make_piece(us, gating_type(m))]);
+ san += square(pos, gating_square(m), n);
+ }
+ }
+ else
+ {
+ // Piece
+ san += piece(pos, m, n);
+
+ if (n == NOTATION_THAI_LAN)
+ san += " ";
+
+ // Origin square, disambiguation
+ Disambiguation d = disambiguation_level(pos, m, n);
+ san += disambiguation(pos, from, n, d);
+
+ // Separator/Operator
+ if (type_of(m) == DROP)
+ san += n == NOTATION_SHOGI_HOSKING ? '\'' : is_shogi(n) ? '*' : '@';
+ else if (n == NOTATION_XIANGQI_WXF)
+ {
+ if (rank_of(from) == rank_of(to))
+ san += '=';
+ else if (relative_rank(us, to, pos.max_rank()) > relative_rank(us, from, pos.max_rank()))
+ san += '+';
+ else
+ san += '-';
+ }
+ else if (pos.capture(m))
+ san += 'x';
+ else if (n == NOTATION_LAN || n == NOTATION_THAI_LAN || (is_shogi(n) && (n != NOTATION_SHOGI_HOSKING || d == SQUARE_DISAMBIGUATION)) || n == NOTATION_JANGGI || (n == NOTATION_THAI_SAN && type_of(pos.moved_piece(m)) != PAWN))
+ san += '-';
+
+ // Destination square
+ if (n == NOTATION_XIANGQI_WXF && type_of(m) != DROP)
+ san += file_of(to) == file_of(from) ? std::to_string(std::abs(rank_of(to) - rank_of(from))) : file(pos, to, n);
+ else
+ san += square(pos, to, n);
+
+ // Suffix
+ if (type_of(m) == PROMOTION)
+ san += std::string("=") + (char)toupper(pos.piece_to_char()[make_piece(us, promotion_type(m))]);
+ else if (type_of(m) == PIECE_PROMOTION)
+ san += is_shogi(n) ? std::string("+") : std::string("=") + (char)toupper(pos.piece_to_char()[make_piece(us, pos.promoted_piece_type(type_of(pos.moved_piece(m))))]);
+ else if (type_of(m) == PIECE_DEMOTION)
+ san += is_shogi(n) ? std::string("-") : std::string("=") + std::string(1, toupper(pos.piece_to_char()[pos.unpromoted_piece_on(from)]));
+ else if (type_of(m) == NORMAL && is_shogi(n) && pos.pseudo_legal(make(from, to)))
+ san += std::string("=");
+ if (is_gating(m))
+ san += std::string("/") + (char)toupper(pos.piece_to_char()[make_piece(us, gating_type(m))]);
+ }
+
+ // Wall square
+ if (pos.walling())
+ san += "," + square(pos, gating_square(m), n);
+
+ // Check and checkmate
+ if (pos.gives_check(m) && !is_shogi(n) && n != NOTATION_XIANGQI_WXF)
+ {
+ StateInfo st;
+ pos.do_move(m, st);
+ san += MoveList(pos).size() ? "+" : "#";
+ pos.undo_move(m);
+ }
+
+ return san;
+}
+
+} // namespace SAN
+
+inline bool has_insufficient_material(Color c, const Position& pos) {
+
+ // Other win rules
+ if ( pos.captures_to_hand()
+ || pos.count_in_hand(c, ALL_PIECES)
+ || (pos.extinction_value() != VALUE_NONE && !pos.extinction_pseudo_royal())
+ || (pos.variant()->nFoldRule && pos.variant()->nFoldValue != VALUE_DRAW)
+ || (pos.flag_region(c) && pos.count(c, pos.flag_piece(c))))
+ return false;
+
+ // Precalculate if any promotion pawn types have pieces
+ bool hasPromotingPawn = false;
+ for (PieceSet pawnTypes = pos.promotion_pawn_types(c); pawnTypes; )
+ {
+ PieceType pawnType = pop_lsb(pawnTypes);
+ if (pos.count(c, pawnType) > 0)
+ {
+ hasPromotingPawn = true;
+ break;
+ }
+ }
+
+ // Determine checkmating potential of present pieces
+ constexpr PieceSet MAJOR_PIECES = piece_set(ROOK) | QUEEN | ARCHBISHOP | CHANCELLOR
+ | SILVER | GOLD | COMMONER | CENTAUR | AMAZON | BERS;
+ constexpr PieceSet COLORBOUND_PIECES = piece_set(BISHOP) | FERS | FERS_ALFIL | ALFIL | ELEPHANT;
+ Bitboard restricted = pos.pieces(KING);
+ Bitboard colorbound = 0;
+ for (PieceSet ps = pos.piece_types(); ps;)
+ {
+ PieceType pt = pop_lsb(ps);
+
+ // Constrained pieces
+ if (pt == KING || !(pos.board_bb(c, pt) & pos.board_bb(~c, KING)) || (pos.extinction_pseudo_royal() && pos.blast_on_capture() && (pos.extinction_piece_types() & pt)))
+ restricted |= pos.pieces(c, pt);
+
+ // If piece is a major piece or a custom piece we consider it sufficient for mate.
+ // To avoid false positives, we assume any custom piece has mating potential.
+ else if ((MAJOR_PIECES & pt) || is_custom(pt))
+ {
+ // Check if piece is already on the board
+ if (pos.count(c, pt) > 0)
+ return false;
+
+ // Check if any pawn can promote to this piece type
+ if (hasPromotingPawn && (pos.promotion_piece_types(c) & pt))
+ return false;
+ }
+
+ // Collect color-bound pieces
+ else if (COLORBOUND_PIECES & pt)
+ colorbound |= pos.pieces(pt);
+ }
+
+ Bitboard unbound = pos.pieces() ^ restricted ^ colorbound;
+
+ // Color-bound pieces
+ if ((colorbound & pos.pieces(c)) && (((DarkSquares & colorbound) && (~DarkSquares & colorbound)) || unbound || pos.stalemate_value() != VALUE_DRAW || pos.check_counting() || pos.makpong()))
+ return false;
+
+ // Unbound pieces require one helper piece of either color
+ if ((pos.pieces(c) & unbound) && (popcount(pos.pieces() ^ restricted) >= 2 || pos.stalemate_value() != VALUE_DRAW || pos.check_counting() || pos.makpong()))
+ return false;
+
+ // Non-draw stalemate with lone custom king
+ if ( pos.stalemate_value() != VALUE_DRAW && pos.king_type() != KING
+ && pos.pieces(c, KING) && (pos.board_bb(c, KING) & pos.board_bb(~c, KING)))
+ return false;
+
+ return true;
+}
+
+inline Bitboard checked(const Position& pos) {
+ return (pos.checkers() ? square_bb(pos.square(pos.side_to_move())) : Bitboard(0))
+ | (pos.extinction_pseudo_royal() ? pos.checked_pseudo_royals(pos.side_to_move()) : Bitboard(0));
+}
+
+namespace FEN {
+
+enum FenValidation : int {
+ FEN_INVALID_COUNTING_RULE = -14,
+ FEN_INVALID_CHECK_COUNT = -13,
+ FEN_INVALID_PROMOTED_PIECE = -12,
+ FEN_INVALID_NB_PARTS = -11,
+ FEN_INVALID_CHAR = -10,
+ FEN_TOUCHING_KINGS = -9,
+ FEN_INVALID_BOARD_GEOMETRY = -8,
+ FEN_INVALID_POCKET_INFO = -7,
+ FEN_INVALID_SIDE_TO_MOVE = -6,
+ FEN_INVALID_CASTLING_INFO = -5,
+ FEN_INVALID_EN_PASSANT_SQ = -4,
+ FEN_INVALID_NUMBER_OF_KINGS = -3,
+ FEN_INVALID_HALF_MOVE_COUNTER = -2,
+ FEN_INVALID_MOVE_COUNTER = -1,
+ FEN_EMPTY = 0,
+ FEN_OK = 1
+};
+enum Validation : int {
+ NOK,
+ OK
+};
+
+struct CharSquare {
+ int rowIdx;
+ int fileIdx;
+ CharSquare() : rowIdx(-1), fileIdx(-1) {}
+ CharSquare(int row, int file) : rowIdx(row), fileIdx(file) {}
+};
+
+inline bool operator==(const CharSquare& s1, const CharSquare& s2) {
+ return s1.rowIdx == s2.rowIdx && s1.fileIdx == s2.fileIdx;
+}
+
+inline bool operator!=(const CharSquare& s1, const CharSquare& s2) {
+ return !(s1 == s2);
+}
+
+inline int non_root_euclidian_distance(const CharSquare& s1, const CharSquare& s2) {
+ return pow(s1.rowIdx - s2.rowIdx, 2) + pow(s1.fileIdx - s2.fileIdx, 2);
+}
+
+class CharBoard {
+private:
+ int nbRanks;
+ int nbFiles;
+ std::vector board; // fill an array where the pieces are for later geometry checks
+public:
+ CharBoard(int ranks, int files) : nbRanks(ranks), nbFiles(files) {
+ assert(nbFiles > 0 && nbRanks > 0);
+ board = std::vector(nbRanks * nbFiles, ' ');
+ }
+ void set_piece(int rankIdx, int fileIdx, char c) {
+ board[rankIdx * nbFiles + fileIdx] = c;
+ }
+ char get_piece(int rowIdx, int fileIdx) const {
+ return board[rowIdx * nbFiles + fileIdx];
+ }
+ int get_nb_ranks() const {
+ return nbRanks;
+ }
+ int get_nb_files() const {
+ return nbFiles;
+ }
+ /// Returns the square of a given character
+ CharSquare get_square_for_piece(char piece) const {
+ CharSquare s;
+ for (int r = 0; r < nbRanks; ++r)
+ {
+ for (int c = 0; c < nbFiles; ++c)
+ {
+ if (get_piece(r, c) == piece)
+ {
+ s.rowIdx = r;
+ s.fileIdx = c;
+ return s;
+ }
+ }
+ }
+ return s;
+ }
+ /// Returns all square positions for a given piece
+ std::vector get_squares_for_pieces(Color color, PieceSet ps, const std::string& pieceChars) const {
+ std::vector squares;
+ size_t pcIdx;
+ for (int r = 0; r < nbRanks; ++r)
+ for (int c = 0; c < nbFiles; ++c)
+ if ((pcIdx = pieceChars.find(get_piece(r, c))) != std::string::npos && (ps & type_of(Piece(pcIdx))) && color_of(Piece(pcIdx)) == color)
+ squares.emplace_back(CharSquare(r, c));
+ return squares;
+ }
+ friend std::ostream& operator<<(std::ostream& os, const CharBoard& board);
+};
+
+inline std::ostream& operator<<(std::ostream& os, const CharBoard& board) {
+ for (int r = 0; r < board.nbRanks; ++r)
+ {
+ for (int c = 0; c < board.nbFiles; ++c)
+ os << "[" << board.get_piece(r, c) << "] ";
+ os << std::endl;
+ }
+ return os;
+}
+
+inline bool contains(const std::string& str, char c) {
+ return str.find(c) != std::string::npos;
+}
+
+inline bool in_any(const std::vector& vec, char c) {
+ for (std::string str : vec)
+ if (contains(str, c))
+ return true;
+ return false;
+}
+
+inline Validation check_for_valid_characters(const std::string& firstFenPart, const std::string& validSpecialCharactersFirstField, const Variant* v) {
+ for (char c : firstFenPart)
+ {
+ if (!isdigit(c) && !in_any({v->pieceToChar, v->pieceToCharSynonyms, validSpecialCharactersFirstField}, c))
+ {
+ std::cerr << "Invalid piece character: '" << c << "'." << std::endl;
+ return NOK;
+ }
+ }
+ return OK;
+}
+
+inline Validation check_promoted_pieces(const std::string& firstFenPart, const Variant* v) {
+ // Only check promoted pieces if the variant supports shogi-style promotions
+ if (!v || !v->shogiStylePromotions)
+ return OK;
+
+ for (size_t i = 0; i < firstFenPart.length() - 1; ++i) {
+ // Look for promoted pieces ('+' followed by piece character)
+ if (firstFenPart[i] == '+') {
+ char pieceChar = firstFenPart[i + 1];
+
+ // Skip if next character is not a piece character or is a special character
+ if (isdigit(pieceChar) || pieceChar == '/' || pieceChar == ' ' || pieceChar == '[')
+ continue;
+
+ // Find the piece type corresponding to this character
+ size_t idx = v->pieceToChar.find(pieceChar);
+ if (idx == std::string::npos) {
+ // Try synonyms
+ idx = v->pieceToCharSynonyms.find(pieceChar);
+ if (idx == std::string::npos)
+ continue; // Character validation will catch this
+ }
+
+ // Ensure idx is within valid range for piece types
+ if (idx >= PIECE_TYPE_NB)
+ continue;
+
+ // Get the piece type directly from the index
+ PieceType pt = PieceType(idx);
+
+ // Check if this piece type has a promoted form
+ if (pt != NO_PIECE_TYPE && pt < PIECE_TYPE_NB && v->promotedPieceType[pt] == NO_PIECE_TYPE) {
+ std::cerr << "Invalid promoted piece: '+' followed by '" << pieceChar
+ << "'. This piece cannot be promoted in variant." << std::endl;
+ return NOK;
+ }
+ }
+ }
+ return OK;
+}
+
+inline std::vector get_fen_parts(const std::string& fullFen, char delim) {
+ std::vector fenParts;
+ std::string curPart;
+ std::stringstream ss(fullFen);
+ while (std::getline(ss, curPart, delim))
+ fenParts.emplace_back(curPart);
+ return fenParts;
+}
+
+/// fills the character board according to a given FEN string
+inline Validation fill_char_board(CharBoard& board, const std::string& fenBoard, const std::string& validSpecialCharactersFirstField, const Variant* v) {
+ int rankIdx = 0;
+ int fileIdx = 0;
+
+ char prevChar = '?';
+ for (char c : fenBoard)
+ {
+ if (c == ' ' || c == '[')
+ break;
+ if (c == '*')
+ ++fileIdx;
+ else if (isdigit(c))
+ {
+ fileIdx += c - '0';
+ // if we have multiple digits attached we can add multiples of 9 to compute the resulting number (e.g. -> 21 = 2 + 2 * 9 + 1)
+ if (isdigit(prevChar))
+ fileIdx += 9 * (prevChar - '0');
+ }
+ else if (c == '/')
+ {
+ ++rankIdx;
+ if (fileIdx != board.get_nb_files())
+ {
+ std::cerr << "curRankWidth != nbFiles: " << fileIdx << " != " << board.get_nb_files() << std::endl;
+ return NOK;
+ }
+ if (rankIdx == board.get_nb_ranks())
+ break;
+ fileIdx = 0;
+ }
+ else if (!contains(validSpecialCharactersFirstField, c))
+ { // normal piece
+ if (fileIdx == board.get_nb_files())
+ {
+ std::cerr << "File index: " << fileIdx << " for piece '" << c << "' exceeds maximum of allowed number of files: " << board.get_nb_files() << "." << std::endl;
+ return NOK;
+ }
+ board.set_piece(v->maxRank-rankIdx, fileIdx, c); // we mirror the rank index because the black pieces are given first in the FEN
+ ++fileIdx;
+ }
+ prevChar = c;
+ }
+
+ if (v->pieceDrops)
+ { // pockets can either be defined by [] or /
+ if (rankIdx+1 != board.get_nb_ranks() && rankIdx != board.get_nb_ranks())
+ {
+ std::cerr << "Invalid number of ranks. Expected: " << board.get_nb_ranks() << " Actual: " << rankIdx+1 << std::endl;
+ return NOK;
+ }
+ }
+ else
+ {
+ if (rankIdx+1 != board.get_nb_ranks())
+ {
+ std::cerr << "Invalid number of ranks. Expected: " << board.get_nb_ranks() << " Actual: " << rankIdx+1 << std::endl;
+ return NOK;
+ }
+ }
+ return OK;
+}
+
+inline Validation check_touching_kings(const CharBoard& board, const std::array& kingPositions) {
+ if (non_root_euclidian_distance(kingPositions[WHITE], kingPositions[BLACK]) <= 2)
+ {
+ std::cerr << "King pieces are next to each other." << std::endl;
+ std::cerr << board << std::endl;
+ return NOK;
+ }
+ return OK;
+}
+
+inline Validation fill_castling_info_splitted(const std::string& castlingInfo, std::array& castlingInfoSplitted) {
+ for (char c : castlingInfo)
+ {
+ if (c != '-')
+ {
+ if (!isalpha(c))
+ {
+ std::cerr << "Invalid castling specification: '" << c << "'." << std::endl;
+ return NOK;
+ }
+ else if (isupper(c))
+ castlingInfoSplitted[WHITE] += tolower(c);
+ else
+ castlingInfoSplitted[BLACK] += c;
+ }
+ }
+ return OK;
+}
+
+inline std::string color_to_string(Color c) {
+ switch (c)
+ {
+ case WHITE:
+ return "WHITE";
+ case BLACK:
+ return "BLACK";
+ case COLOR_NB:
+ return "COLOR_NB";
+ default:
+ return "INVALID_COLOR";
+ }
+}
+
+inline std::string castling_rights_to_string(CastlingRights castlingRights) {
+ switch (castlingRights)
+ {
+ case KING_SIDE:
+ return "KING_SIDE";
+ case QUEEN_SIDE:
+ return "QUEENS_SIDE";
+ case WHITE_OO:
+ return "WHITE_OO";
+ case WHITE_OOO:
+ return "WHITE_OOO";
+ case BLACK_OO:
+ return "BLACK_OO";
+ case BLACK_OOO:
+ return "BLACK_OOO";
+ case WHITE_CASTLING:
+ return "WHITE_CASTLING";
+ case BLACK_CASTLING:
+ return "BLACK_CASTLING";
+ case ANY_CASTLING:
+ return "ANY_CASTLING";
+ case CASTLING_RIGHT_NB:
+ return "CASTLING_RIGHT_NB";
+ default:
+ return "INVALID_CASTLING_RIGHTS";
+ }
+}
+
+inline Validation check_castling_rank(const std::array& castlingInfoSplitted, const CharBoard& board,
+ const std::array& kingPositions, const Variant* v) {
+
+ for (Color c : {WHITE, BLACK})
+ {
+ const Rank castlingRank = relative_rank(c, v->castlingRank, v->maxRank);
+ for (char castlingFlag : castlingInfoSplitted[c])
+ {
+ if (tolower(castlingFlag) == 'k' || tolower(castlingFlag) == 'q')
+ {
+ if (kingPositions[c].rowIdx != castlingRank)
+ {
+ std::cerr << "The " << color_to_string(c) << " king must be on rank " << castlingRank << " if castling is enabled for " << color_to_string(c) << "." << std::endl;
+ return NOK;
+ }
+ bool kingside = tolower(castlingFlag) == 'k';
+ bool castlingRook = false;
+ size_t pcIdx;
+ for (int f = kingside ? board.get_nb_files() - 1 : 0; f != kingPositions[c].fileIdx; kingside ? f-- : f++)
+ if ( (pcIdx = v->pieceToChar.find(board.get_piece(castlingRank, f))) != std::string::npos
+ && (v->castlingRookPieces[c] & type_of(Piece(pcIdx)))
+ && color_of(Piece(pcIdx)) == c)
+ {
+ castlingRook = true;
+ break;
+ }
+ if (!castlingRook)
+ {
+ std::cerr << "No castling rook for flag " << castlingFlag << std::endl;
+ return NOK;
+ }
+ }
+ else if (board.get_piece(castlingRank, tolower(castlingFlag) - 'a') == ' ')
+ {
+ std::cerr << "No gating piece for flag " << castlingFlag << std::endl;
+ return NOK;
+ }
+ }
+ }
+ return OK;
+}
+
+inline Validation check_standard_castling(std::array& castlingInfoSplitted, const CharBoard& board,
+ const std::array& kingPositions, const std::array& kingPositionsStart,
+ const std::array, 2>& rookPositionsStart, const Variant* v) {
+
+ for (Color c : {WHITE, BLACK})
+ {
+ if (castlingInfoSplitted[c].size() == 0)
+ continue;
+ if (kingPositions[c] != kingPositionsStart[c])
+ {
+ std::cerr << "The " << color_to_string(c) << " KING has moved. Castling is no longer valid for " << color_to_string(c) << "." << std::endl;
+ return NOK;
+ }
+
+ for (CastlingRights castling: {KING_SIDE, QUEEN_SIDE})
+ {
+ CharSquare rookStartingSquare = castling == QUEEN_SIDE ? rookPositionsStart[c][0] : rookPositionsStart[c][1];
+ char targetChar = castling == QUEEN_SIDE ? 'q' : 'k';
+ size_t pcIdx;
+ if (castlingInfoSplitted[c].find(targetChar) != std::string::npos)
+ {
+ if ( (pcIdx = v->pieceToChar.find(board.get_piece(rookStartingSquare.rowIdx, rookStartingSquare.fileIdx))) == std::string::npos
+ || !(v->castlingRookPieces[c] & type_of(Piece(pcIdx)))
+ || color_of(Piece(pcIdx)) != c)
+ {
+ std::cerr << "The " << color_to_string(c) << " ROOK on the "<< castling_rights_to_string(castling) << " has moved. "
+ << castling_rights_to_string(castling) << " castling is no longer valid for " << color_to_string(c) << "." << std::endl;
+ return NOK;
+ }
+ }
+
+ }
+ }
+ return OK;
+}
+
+inline Validation check_pocket_info(const std::string& fenBoard, int nbRanks, const Variant* v, std::string& pocket) {
+
+ char stopChar;
+ int offset = 0;
+ if (std::count(fenBoard.begin(), fenBoard.end(), '/') == nbRanks)
+ {
+ // look for last '/'
+ stopChar = '/';
+ }
+ else if (std::count(fenBoard.begin(), fenBoard.end(), '[') == 1)
+ {
+ // pocket is defined as [ and ]
+ stopChar = '[';
+ offset = 1;
+ if (*(fenBoard.end()-1) != ']')
+ {
+ std::cerr << "Pocket specification does not end with ']'." << std::endl;
+ return NOK;
+ }
+ }
+ else
+ // allow to skip pocket
+ return OK;
+
+ // look for last '/'
+ for (auto it = fenBoard.rbegin()+offset; it != fenBoard.rend(); ++it)
+ {
+ const char c = *it;
+ if (c == stopChar)
+ return OK;
+ if (c != '-')
+ {
+ if (!in_any({v->pieceToChar, v->pieceToCharSynonyms}, c))
+ {
+ std::cerr << "Invalid pocket piece: '" << c << "'." << std::endl;
+ return NOK;
+ }
+ else
+ pocket += c;
+ }
+ }
+ std::cerr << "Pocket piece closing character '" << stopChar << "' was not found." << std::endl;
+ return NOK;
+}
+
+inline int piece_count(const std::string& fenBoard, Color c, PieceType pt, const Variant* v) {
+ return std::count(fenBoard.begin(), fenBoard.end(), v->pieceToChar[make_piece(c, pt)]);
+}
+
+inline Validation check_number_of_kings(const std::string& fenBoard, const std::string& startFenBoard, const Variant* v) {
+ int nbWhiteKings = piece_count(fenBoard, WHITE, KING, v);
+ int nbBlackKings = piece_count(fenBoard, BLACK, KING, v);
+ int nbWhiteKingsStart = piece_count(startFenBoard, WHITE, KING, v);
+ int nbBlackKingsStart = piece_count(startFenBoard, BLACK, KING, v);
+
+ if (nbWhiteKings > 1)
+ {
+ std::cerr << "Invalid number of white kings. Maximum: 1. Given: " << nbWhiteKings << std::endl;
+ return NOK;
+ }
+ if (nbBlackKings > 1)
+ {
+ std::cerr << "Invalid number of black kings. Maximum: 1. Given: " << nbBlackKings << std::endl;
+ return NOK;
+ }
+ if (nbWhiteKings != nbWhiteKingsStart)
+ {
+ std::cerr << "Invalid number of white kings. Expected: " << nbWhiteKingsStart << ". Given: " << nbWhiteKings << std::endl;
+ return NOK;
+ }
+ if (nbBlackKings != nbBlackKingsStart)
+ {
+ std::cerr << "Invalid number of black kings. Expected: " << nbBlackKingsStart << ". Given: " << nbBlackKings << std::endl;
+ return NOK;
+ }
+ return OK;
+}
+
+
+inline Validation check_en_passant_square(const std::string& enPassantInfo) {
+ if (enPassantInfo.size() != 1 || enPassantInfo[0] != '-')
+ {
+ if (enPassantInfo.size() != 2)
+ {
+ std::cerr << "Invalid en-passant square '" << enPassantInfo << "'. Expects 2 characters. Actual: " << enPassantInfo.size() << " character(s)." << std::endl;
+ return NOK;
+ }
+ if (!isalpha(enPassantInfo[0]))
+ {
+ std::cerr << "Invalid en-passant square '" << enPassantInfo << "'. Expects 1st character to be a letter." << std::endl;
+ return NOK;
+ }
+ if (!isdigit(enPassantInfo[1]))
+ {
+ std::cerr << "Invalid en-passant square '" << enPassantInfo << "'. Expects 2nd character to be a digit." << std::endl;
+ return NOK;
+ }
+ }
+ return OK;
+}
+
+
+inline Validation check_check_count(const std::string& checkCountInfo) {
+ if (checkCountInfo.size() != 3)
+ {
+ std::cerr << "Invalid check count '" << checkCountInfo << "'. Expects 3 characters. Actual: " << checkCountInfo.size() << " character(s)." << std::endl;
+ return NOK;
+ }
+ if (!isdigit(checkCountInfo[0]))
+ {
+ std::cerr << "Invalid check count '" << checkCountInfo << "'. Expects 1st character to be a digit." << std::endl;
+ return NOK;
+ }
+ if (!isdigit(checkCountInfo[2])) {
+ std::cerr << "Invalid check count '" << checkCountInfo << "'. Expects 3rd character to be a digit." << std::endl;
+ return NOK;
+ }
+ return OK;
+}
+
+inline Validation check_lichess_check_count(const std::string& checkCountInfo) {
+ if (checkCountInfo.size() != 4)
+ {
+ std::cerr << "Invalid check count '" << checkCountInfo << "'. Expects 4 characters. Actual: " << checkCountInfo.size() << " character(s)." << std::endl;
+ return NOK;
+ }
+ if (!isdigit(checkCountInfo[1]) || checkCountInfo[1] - '0' > 3)
+ {
+ std::cerr << "Invalid check count '" << checkCountInfo << "'. Expects 2nd character to be a digit up to 3." << std::endl;
+ return NOK;
+ }
+ if (!isdigit(checkCountInfo[3]) || checkCountInfo[3] - '0' > 3) {
+ std::cerr << "Invalid check count '" << checkCountInfo << "'. Expects 4th character to be a digit up to 3." << std::endl;
+ return NOK;
+ }
+ return OK;
+}
+
+inline Validation check_digit_field(const std::string& field) {
+ if (field.size() == 1 && field[0] == '-')
+ return OK;
+ for (char c : field)
+ if (!isdigit(c))
+ return NOK;
+ return OK;
+}
+
+inline std::string get_valid_special_chars(const Variant* v) {
+ std::string validSpecialCharactersFirstField = "/*";
+ // Whether or not '-', '+', '~', '[', ']' are valid depends on the variant being played.
+ if (v->shogiStylePromotions)
+ validSpecialCharactersFirstField += '+';
+ if (v->promotionPieceTypes[WHITE] || v->promotionPieceTypes[BLACK])
+ validSpecialCharactersFirstField += '~';
+ if (!v->freeDrops && (v->pieceDrops || v->seirawanGating))
+ validSpecialCharactersFirstField += "[-]";
+ return validSpecialCharactersFirstField;
+}
+
+inline FenValidation validate_fen(const std::string& fen, const Variant* v, bool chess960 = false) {
+
+ const std::string validSpecialCharactersFirstField = get_valid_special_chars(v);
+ // 0) Layout
+ // check for empty fen
+ if (fen.empty())
+ {
+ std::cerr << "Fen is empty." << std::endl;
+ return FEN_EMPTY;
+ }
+
+ std::vector fenParts = get_fen_parts(fen, ' ');
+ std::vector startFenParts = get_fen_parts(v->startFen, ' ');
+
+ // check for number of parts
+ const unsigned int maxNumberFenParts = 6 + v->checkCounting;
+ if (fenParts.size() < 1 || fenParts.size() > maxNumberFenParts)
+ {
+ std::cerr << "Invalid number of fen parts. Expected: >= 1 and <= " << maxNumberFenParts
+ << " Actual: " << fenParts.size() << std::endl;
+ return FEN_INVALID_NB_PARTS;
+ }
+
+ // 1) Part
+ // check for valid characters
+ if (check_for_valid_characters(fenParts[0], validSpecialCharactersFirstField, v) == NOK)
+ return FEN_INVALID_CHAR;
+
+ // check for valid promoted pieces
+ if (check_promoted_pieces(fenParts[0], v) == NOK)
+ return FEN_INVALID_PROMOTED_PIECE;
+
+ // check for number of ranks
+ const int nbRanks = v->maxRank + 1;
+ // check for number of files
+ const int nbFiles = v->maxFile + 1;
+ CharBoard board(nbRanks, nbFiles); // create a 2D character board for later geometry checks
+
+ if (fill_char_board(board, fenParts[0], validSpecialCharactersFirstField, v) == NOK)
+ return FEN_INVALID_BOARD_GEOMETRY;
+
+ // check for pocket
+ std::string pocket = "";
+ if (v->pieceDrops || v->seirawanGating)
+ {
+ if (check_pocket_info(fenParts[0], nbRanks, v, pocket) == NOK)
+ return FEN_INVALID_POCKET_INFO;
+ }
+
+ // check for number of kings
+ if (v->pieceTypes & KING)
+ {
+ // we have a royal king in this variant,
+ // ensure that each side has exactly as many kings as in the starting position
+ // (variants like giveaway use the COMMONER piece type instead)
+ if (check_number_of_kings(fenParts[0], startFenParts[0], v) == NOK)
+ return FEN_INVALID_NUMBER_OF_KINGS;
+
+ // check for touching kings if there are exactly two royal kings on the board (excluding pocket)
+ if ( v->kingType == KING
+ && piece_count(fenParts[0], WHITE, KING, v) - piece_count(pocket, WHITE, KING, v) == 1
+ && piece_count(fenParts[0], BLACK, KING, v) - piece_count(pocket, BLACK, KING, v) == 1)
+ {
+ std::array kingPositions;
+ kingPositions[WHITE] = board.get_square_for_piece(v->pieceToChar[make_piece(WHITE, KING)]);
+ kingPositions[BLACK] = board.get_square_for_piece(v->pieceToChar[make_piece(BLACK, KING)]);
+ if (check_touching_kings(board, kingPositions) == NOK)
+ return FEN_TOUCHING_KINGS;
+ }
+ }
+
+ // 2) Part
+ // check side to move char
+ if (fenParts.size() >= 2 && fenParts[1][0] != 'w' && fenParts[1][0] != 'b')
+ {
+ std::cerr << "Invalid side to move specification: '" << fenParts[1][0] << "'." << std::endl;
+ return FEN_INVALID_SIDE_TO_MOVE;
+ }
+
+ // Castling and en passant can be skipped
+ bool skipCastlingAndEp = fenParts.size() >= 4 && fenParts.size() <= 5 && isdigit(fenParts[2][0]);
+
+ // 3) Part
+ // check castling rights
+ if (fenParts.size() >= 3 && !skipCastlingAndEp && v->castling)
+ {
+ std::array castlingInfoSplitted;
+ if (fill_castling_info_splitted(fenParts[2], castlingInfoSplitted) == NOK)
+ return FEN_INVALID_CASTLING_INFO;
+
+ if (castlingInfoSplitted[WHITE].size() != 0 || castlingInfoSplitted[BLACK].size() != 0)
+ {
+ std::array kingPositions;
+ kingPositions[WHITE] = board.get_square_for_piece(toupper(v->pieceToChar[v->castlingKingPiece[WHITE]]));
+ kingPositions[BLACK] = board.get_square_for_piece(tolower(v->pieceToChar[v->castlingKingPiece[BLACK]]));
+
+ CharBoard startBoard(board.get_nb_ranks(), board.get_nb_files());
+ fill_char_board(startBoard, v->startFen, validSpecialCharactersFirstField, v);
+
+ // Check pieces present on castling rank against castling/gating rights
+ if (check_castling_rank(castlingInfoSplitted, board, kingPositions, v) == NOK)
+ return FEN_INVALID_CASTLING_INFO;
+
+ // only check exact squares if starting position of castling pieces is known
+ if (!v->chess960 && !v->castlingDroppedPiece && !chess960)
+ {
+ std::array kingPositionsStart;
+ kingPositionsStart[WHITE] = startBoard.get_square_for_piece(v->pieceToChar[make_piece(WHITE, v->castlingKingPiece[WHITE])]);
+ kingPositionsStart[BLACK] = startBoard.get_square_for_piece(v->pieceToChar[make_piece(BLACK, v->castlingKingPiece[BLACK])]);
+ std::array, 2> rookPositionsStart;
+ rookPositionsStart[WHITE] = startBoard.get_squares_for_pieces(WHITE, v->castlingRookPieces[WHITE], v->pieceToChar);
+ rookPositionsStart[BLACK] = startBoard.get_squares_for_pieces(BLACK, v->castlingRookPieces[BLACK], v->pieceToChar);
+
+ if (check_standard_castling(castlingInfoSplitted, board, kingPositions, kingPositionsStart, rookPositionsStart, v) == NOK)
+ return FEN_INVALID_CASTLING_INFO;
+ }
+ }
+ }
+
+ // 4) Part
+ // check en-passant square
+ if (fenParts.size() >= 4 && !skipCastlingAndEp)
+ {
+ if (v->doubleStep && (v->pieceTypes & PAWN))
+ {
+ if (check_en_passant_square(fenParts[3]) == NOK)
+ return FEN_INVALID_EN_PASSANT_SQ;
+ }
+ else if (v->countingRule && !check_digit_field(fenParts[3]))
+ return FEN_INVALID_COUNTING_RULE;
+ }
+
+ // 5) Part
+ // check check count
+ unsigned int optionalInbetweenFields = 2 * !skipCastlingAndEp;
+ unsigned int optionalTrailingFields = 0;
+ if (fenParts.size() >= 3 + optionalInbetweenFields && v->checkCounting && fenParts.size() % 2)
+ {
+ if (check_check_count(fenParts[2 + optionalInbetweenFields]) == NOK)
+ {
+ // allow valid lichess style check as alternative
+ if (fenParts.size() < 5 + optionalInbetweenFields || check_lichess_check_count(fenParts[fenParts.size() - 1]) == NOK)
+ return FEN_INVALID_CHECK_COUNT;
+ else
+ optionalTrailingFields++;
+ }
+ else
+ optionalInbetweenFields++;
+ }
+
+ // 6) Part
+ // check half move counter
+ if (fenParts.size() >= 3 + optionalInbetweenFields && !check_digit_field(fenParts[fenParts.size() - 2 - optionalTrailingFields]))
+ {
+ std::cerr << "Invalid half move counter: '" << fenParts[fenParts.size()-2] << "'." << std::endl;
+ return FEN_INVALID_HALF_MOVE_COUNTER;
+ }
+
+ // 7) Part
+ // check move counter
+ if (fenParts.size() >= 4 + optionalInbetweenFields && !check_digit_field(fenParts[fenParts.size() - 1 - optionalTrailingFields]))
+ {
+ std::cerr << "Invalid move counter: '" << fenParts[fenParts.size()-1] << "'." << std::endl;
+ return FEN_INVALID_MOVE_COUNTER;
+ }
+
+ return FEN_OK;
+}
+} // namespace FEN
+
+} // namespace Stockfish
+
+#endif // #ifndef APIUTIL_H_INCLUDED
diff --git a/Fairy-Stockfish-master/src/benchmark.cpp b/Fairy-Stockfish-master/src/benchmark.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..00b9959dd17b4ca917289637980d9f3d57a05aa1
--- /dev/null
+++ b/Fairy-Stockfish-master/src/benchmark.cpp
@@ -0,0 +1,195 @@
+/*
+ Stockfish, a UCI chess playing engine derived from Glaurung 2.1
+ Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
+
+ Stockfish is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Stockfish is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include
+#include
+#include
+#include
+
+#include "position.h"
+#include "uci.h"
+
+using namespace std;
+
+namespace {
+
+const vector Defaults = {
+ "setoption name UCI_Chess960 value false",
+ "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
+ "r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 10",
+ "8/2p5/3p4/KP5r/1R3p1k/8/4P1P1/8 w - - 0 11",
+ "4rrk1/pp1n3p/3q2pQ/2p1pb2/2PP4/2P3N1/P2B2PP/4RRK1 b - - 7 19",
+ "rq3rk1/ppp2ppp/1bnpb3/3N2B1/3NP3/7P/PPPQ1PP1/2KR3R w - - 7 14 moves d4e6",
+ "r1bq1r1k/1pp1n1pp/1p1p4/4p2Q/4Pp2/1BNP4/PPP2PPP/3R1RK1 w - - 2 14 moves g2g4",
+ "r3r1k1/2p2ppp/p1p1bn2/8/1q2P3/2NPQN2/PPP3PP/R4RK1 b - - 2 15",
+ "r1bbk1nr/pp3p1p/2n5/1N4p1/2Np1B2/8/PPP2PPP/2KR1B1R w kq - 0 13",
+ "r1bq1rk1/ppp1nppp/4n3/3p3Q/3P4/1BP1B3/PP1N2PP/R4RK1 w - - 1 16",
+ "4r1k1/r1q2ppp/ppp2n2/4P3/5Rb1/1N1BQ3/PPP3PP/R5K1 w - - 1 17",
+ "2rqkb1r/ppp2p2/2npb1p1/1N1Nn2p/2P1PP2/8/PP2B1PP/R1BQK2R b KQ - 0 11",
+ "r1bq1r1k/b1p1npp1/p2p3p/1p6/3PP3/1B2NN2/PP3PPP/R2Q1RK1 w - - 1 16",
+ "3r1rk1/p5pp/bpp1pp2/8/q1PP1P2/b3P3/P2NQRPP/1R2B1K1 b - - 6 22",
+ "r1q2rk1/2p1bppp/2Pp4/p6b/Q1PNp3/4B3/PP1R1PPP/2K4R w - - 2 18",
+ "4k2r/1pb2ppp/1p2p3/1R1p4/3P4/2r1PN2/P4PPP/1R4K1 b - - 3 22",
+ "3q2k1/pb3p1p/4pbp1/2r5/PpN2N2/1P2P2P/5PP1/Q2R2K1 b - - 4 26",
+ "6k1/6p1/6Pp/ppp5/3pn2P/1P3K2/1PP2P2/3N4 b - - 0 1",
+ "3b4/5kp1/1p1p1p1p/pP1PpP1P/P1P1P3/3KN3/8/8 w - - 0 1",
+ "2K5/p7/7P/5pR1/8/5k2/r7/8 w - - 0 1 moves g5g6 f3e3 g6g5 e3f3",
+ "8/6pk/1p6/8/PP3p1p/5P2/4KP1q/3Q4 w - - 0 1",
+ "7k/3p2pp/4q3/8/4Q3/5Kp1/P6b/8 w - - 0 1",
+ "8/2p5/8/2kPKp1p/2p4P/2P5/3P4/8 w - - 0 1",
+ "8/1p3pp1/7p/5P1P/2k3P1/8/2K2P2/8 w - - 0 1",
+ "8/pp2r1k1/2p1p3/3pP2p/1P1P1P1P/P5KR/8/8 w - - 0 1",
+ "8/3p4/p1bk3p/Pp6/1Kp1PpPp/2P2P1P/2P5/5B2 b - - 0 1",
+ "5k2/7R/4P2p/5K2/p1r2P1p/8/8/8 b - - 0 1",
+ "6k1/6p1/P6p/r1N5/5p2/7P/1b3PP1/4R1K1 w - - 0 1",
+ "1r3k2/4q3/2Pp3b/3Bp3/2Q2p2/1p1P2P1/1P2KP2/3N4 w - - 0 1",
+ "6k1/4pp1p/3p2p1/P1pPb3/R7/1r2P1PP/3B1P2/6K1 w - - 0 1",
+ "8/3p3B/5p2/5P2/p7/PP5b/k7/6K1 w - - 0 1",
+ "5rk1/q6p/2p3bR/1pPp1rP1/1P1Pp3/P3B1Q1/1K3P2/R7 w - - 93 90",
+ "4rrk1/1p1nq3/p7/2p1P1pp/3P2bp/3Q1Bn1/PPPB4/1K2R1NR w - - 40 21",
+ "r3k2r/3nnpbp/q2pp1p1/p7/Pp1PPPP1/4BNN1/1P5P/R2Q1RK1 w kq - 0 16",
+ "3Qb1k1/1r2ppb1/pN1n2q1/Pp1Pp1Pr/4P2p/4BP2/4B1R1/1R5K b - - 11 40",
+ "4k3/3q1r2/1N2r1b1/3ppN2/2nPP3/1B1R2n1/2R1Q3/3K4 w - - 5 1",
+
+ // 5-man positions
+ "8/8/8/8/5kp1/P7/8/1K1N4 w - - 0 1", // Kc2 - mate
+ "8/8/8/5N2/8/p7/8/2NK3k w - - 0 1", // Na2 - mate
+ "8/3k4/8/8/8/4B3/4KB2/2B5 w - - 0 1", // draw
+
+ // 6-man positions
+ "8/8/1P6/5pr1/8/4R3/7k/2K5 w - - 0 1", // Re5 - mate
+ "8/2p4P/8/kr6/6R1/8/8/1K6 w - - 0 1", // Ka2 - mate
+ "8/8/3P3k/8/1p6/8/1P6/1K3n2 b - - 0 1", // Nd2 - draw
+
+ // 7-man positions
+ "8/R7/2q5/8/6k1/8/1P5p/K6R w - - 0 124", // Draw
+
+ // Mate and stalemate positions
+ "6k1/3b3r/1p1p4/p1n2p2/1PPNpP1q/P3Q1p1/1R1RB1P1/5K2 b - - 0 1",
+ "r2r1n2/pp2bk2/2p1p2p/3q4/3PN1QP/2P3R1/P4PP1/5RK1 w - - 0 1",
+ "8/8/8/8/8/6k1/6p1/6K1 w - -",
+ "7k/7P/6K1/8/3B4/8/8/8 b - -",
+
+ // Chess 960
+ "setoption name UCI_Chess960 value true",
+ "bbqnnrkr/pppppppp/8/8/8/8/PPPPPPPP/BBQNNRKR w HFhf - 0 1 moves g2g3 d7d5 d2d4 c8h3 c1g5 e8d6 g5e7 f7f6",
+ "setoption name UCI_Chess960 value false"
+};
+
+} // namespace
+
+namespace Stockfish {
+
+/// setup_bench() builds a list of UCI commands to be run by bench. There
+/// are five parameters: TT size in MB, number of search threads that
+/// should be used, the limit value spent for each position, a file name
+/// where to look for positions in FEN format, the type of the limit:
+/// depth, perft, nodes and movetime (in millisecs), and evaluation type
+/// mixed (default), classical, NNUE.
+///
+/// bench -> search default positions up to depth 13
+/// bench 64 1 15 -> search default positions up to depth 15 (TT = 64MB)
+/// bench 64 4 5000 current movetime -> search current position with 4 threads for 5 sec
+/// bench 64 1 100000 default nodes -> search default positions for 100K nodes each
+/// bench 16 1 5 default perft -> run a perft 5 on default positions
+
+vector setup_bench(const Position& current, istream& is) {
+
+ vector fens, list;
+ string go, token, varname;
+
+ streampos args = is.tellg();
+ // Check whether the next token is a variant name
+ if ((is >> token) && variants.find(token) != variants.end())
+ {
+ args = is.tellg();
+ varname = token;
+ }
+ else
+ {
+ is.seekg(args);
+ varname = string(Options["UCI_Variant"]);
+ }
+ const Variant* variant = variants.find(varname)->second;
+
+ // Assign default values to missing arguments
+ string ttSize = (is >> token) ? token : "16";
+ string threads = (is >> token) ? token : "1";
+ string limit = (is >> token) ? token : "13";
+ string fenFile = (is >> token) ? token : "default";
+ string limitType = (is >> token) ? token : "depth";
+ string evalType = (is >> token) ? token : "mixed";
+
+ go = limitType == "eval" ? "eval" : "go " + limitType + " " + limit;
+
+ if (fenFile == "default")
+ {
+ if (varname != "chess")
+ fens.push_back(variant->startFen);
+ else
+ fens = Defaults;
+ }
+
+ else if (fenFile == "current")
+ fens.push_back(current.fen());
+
+ else
+ {
+ string fen;
+ ifstream file(fenFile);
+
+ if (!file.is_open())
+ {
+ cerr << "Unable to open file " << fenFile << endl;
+ exit(EXIT_FAILURE);
+ }
+
+ while (getline(file, fen))
+ if (!fen.empty())
+ fens.push_back(fen);
+
+ file.close();
+ }
+
+ list.emplace_back("setoption name Threads value " + threads);
+ list.emplace_back("setoption name Hash value " + ttSize);
+ list.emplace_back("setoption name UCI_Variant value " + varname);
+ list.emplace_back("ucinewgame");
+
+ size_t posCounter = 0;
+
+ for (const string& fen : fens)
+ if (fen.find("setoption") != string::npos)
+ list.emplace_back(fen);
+ else
+ {
+ if (evalType == "classical" || (evalType == "mixed" && posCounter % 2 == 0))
+ list.emplace_back("setoption name Use NNUE value false");
+ else if (evalType == "NNUE" || (evalType == "mixed" && posCounter % 2 != 0))
+ list.emplace_back("setoption name Use NNUE value true");
+ list.emplace_back("position fen " + fen);
+ list.emplace_back(go);
+ ++posCounter;
+ }
+
+ list.emplace_back("setoption name Use NNUE value true");
+
+ return list;
+}
+
+} // namespace Stockfish
diff --git a/Fairy-Stockfish-master/src/bitbase.cpp b/Fairy-Stockfish-master/src/bitbase.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..08a3ed9409ef83b0ff5d634f75191da06e229502
--- /dev/null
+++ b/Fairy-Stockfish-master/src/bitbase.cpp
@@ -0,0 +1,177 @@
+/*
+ Stockfish, a UCI chess playing engine derived from Glaurung 2.1
+ Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
+
+ Stockfish is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Stockfish is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include
+#include
+#include
+
+#include "bitboard.h"
+#include "types.h"
+
+namespace Stockfish {
+
+namespace {
+
+ // There are 24 possible pawn squares: files A to D and ranks from 2 to 7.
+ // Positions with the pawn on files E to H will be mirrored before probing.
+ constexpr unsigned MAX_INDEX = 2*24*64*64; // stm * psq * wksq * bksq = 196608
+
+ std::bitset KPKBitbase;
+
+ // A KPK bitbase index is an integer in [0, IndexMax] range
+ //
+ // Information is mapped in a way that minimizes the number of iterations:
+ //
+ // bit 0- 5: white king square (from SQ_A1 to SQ_H8)
+ // bit 6-11: black king square (from SQ_A1 to SQ_H8)
+ // bit 12: side to move (WHITE or BLACK)
+ // bit 13-14: white pawn file (from FILE_A to FILE_D)
+ // bit 15-17: white pawn RANK_7 - rank (from RANK_7 - RANK_7 to RANK_7 - RANK_2)
+ unsigned index(Color stm, Square bksq, Square wksq, Square psq) {
+ return int(wksq) | (bksq << 6) | (stm << 12) | (file_of(psq) << 13) | ((RANK_7 - rank_of(psq)) << 15);
+ }
+
+ enum Result {
+ INVALID = 0,
+ UNKNOWN = 1,
+ DRAW = 2,
+ WIN = 4
+ };
+
+ Result& operator|=(Result& r, Result v) { return r = Result(r | v); }
+
+ struct KPKPosition {
+ KPKPosition() = default;
+ explicit KPKPosition(unsigned idx);
+ operator Result() const { return result; }
+ Result classify(const std::vector& db);
+
+ Color stm;
+ Square ksq[COLOR_NB], psq;
+ Result result;
+ };
+
+} // namespace
+
+bool Bitbases::probe(Square wksq, Square wpsq, Square bksq, Color stm) {
+
+ assert(file_of(wpsq) <= FILE_D);
+
+ return KPKBitbase[index(stm, bksq, wksq, wpsq)];
+}
+
+
+void Bitbases::init() {
+
+#ifdef LARGEBOARDS
+ // Bitbases are not working for large-board version
+ return;
+#endif
+
+ std::vector db(MAX_INDEX);
+ unsigned idx, repeat = 1;
+
+ // Initialize db with known win / draw positions
+ for (idx = 0; idx < MAX_INDEX; ++idx)
+ db[idx] = KPKPosition(idx);
+
+ // Iterate through the positions until none of the unknown positions can be
+ // changed to either wins or draws (15 cycles needed).
+ while (repeat)
+ for (repeat = idx = 0; idx < MAX_INDEX; ++idx)
+ repeat |= (db[idx] == UNKNOWN && db[idx].classify(db) != UNKNOWN);
+
+ // Fill the bitbase with the decisive results
+ for (idx = 0; idx < MAX_INDEX; ++idx)
+ if (db[idx] == WIN)
+ KPKBitbase.set(idx);
+}
+
+namespace {
+
+ KPKPosition::KPKPosition(unsigned idx) {
+
+ ksq[WHITE] = Square((idx >> 0) & 0x3F);
+ ksq[BLACK] = Square((idx >> 6) & 0x3F);
+ stm = Color ((idx >> 12) & 0x01);
+ psq = make_square(File((idx >> 13) & 0x3), Rank(RANK_7 - ((idx >> 15) & 0x7)));
+
+ // Invalid if two pieces are on the same square or if a king can be captured
+ if ( distance(ksq[WHITE], ksq[BLACK]) <= 1
+ || ksq[WHITE] == psq
+ || ksq[BLACK] == psq
+ || (stm == WHITE && (pawn_attacks_bb(WHITE, psq) & ksq[BLACK])))
+ result = INVALID;
+
+ // Win if the pawn can be promoted without getting captured
+ else if ( stm == WHITE
+ && rank_of(psq) == RANK_7
+ && ksq[WHITE] != psq + NORTH
+ && ( distance(ksq[BLACK], psq + NORTH) > 1
+ || (distance(ksq[WHITE], psq + NORTH) == 1)))
+ result = WIN;
+
+ // Draw if it is stalemate or the black king can capture the pawn
+ else if ( stm == BLACK
+ && ( !(attacks_bb(ksq[BLACK]) & ~(attacks_bb(ksq[WHITE]) | pawn_attacks_bb(WHITE, psq)))
+ || (attacks_bb(ksq[BLACK]) & ~attacks_bb(ksq[WHITE]) & psq)))
+ result = DRAW;
+
+ // Position will be classified later
+ else
+ result = UNKNOWN;
+ }
+
+ Result KPKPosition::classify(const std::vector& db) {
+
+ // White to move: If one move leads to a position classified as WIN, the result
+ // of the current position is WIN. If all moves lead to positions classified
+ // as DRAW, the current position is classified as DRAW, otherwise the current
+ // position is classified as UNKNOWN.
+ //
+ // Black to move: If one move leads to a position classified as DRAW, the result
+ // of the current position is DRAW. If all moves lead to positions classified
+ // as WIN, the position is classified as WIN, otherwise the current position is
+ // classified as UNKNOWN.
+ const Result Good = (stm == WHITE ? WIN : DRAW);
+ const Result Bad = (stm == WHITE ? DRAW : WIN);
+
+ Result r = INVALID;
+ Bitboard b = attacks_bb(ksq[stm]);
+
+ while (b)
+ r |= stm == WHITE ? db[index(BLACK, ksq[BLACK], pop_lsb(b), psq)]
+ : db[index(WHITE, pop_lsb(b), ksq[WHITE], psq)];
+
+ if (stm == WHITE)
+ {
+ if (rank_of(psq) < RANK_7) // Single push
+ r |= db[index(BLACK, ksq[BLACK], ksq[WHITE], psq + NORTH)];
+
+ if ( rank_of(psq) == RANK_2 // Double push
+ && psq + NORTH != ksq[WHITE]
+ && psq + NORTH != ksq[BLACK])
+ r |= db[index(BLACK, ksq[BLACK], ksq[WHITE], psq + NORTH + NORTH)];
+ }
+
+ return result = r & Good ? Good : r & UNKNOWN ? UNKNOWN : Bad;
+ }
+
+} // namespace
+
+} // namespace Stockfish
diff --git a/Fairy-Stockfish-master/src/bitboard.cpp b/Fairy-Stockfish-master/src/bitboard.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4f00575970a039998f71d9f7278dc853f5705b66
--- /dev/null
+++ b/Fairy-Stockfish-master/src/bitboard.cpp
@@ -0,0 +1,501 @@
+/*
+ Stockfish, a UCI chess playing engine derived from Glaurung 2.1
+ Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
+
+ Stockfish is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Stockfish is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include
+#include
+
+#include "bitboard.h"
+#include "magic.h"
+#include "misc.h"
+#include "piece.h"
+
+namespace Stockfish {
+
+uint8_t PopCnt16[1 << 16];
+uint8_t SquareDistance[SQUARE_NB][SQUARE_NB];
+
+Bitboard SquareBB[SQUARE_NB];
+Bitboard LineBB[SQUARE_NB][SQUARE_NB];
+Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
+Bitboard PseudoAttacks[COLOR_NB][PIECE_TYPE_NB][SQUARE_NB];
+Bitboard PseudoMoves[2][COLOR_NB][PIECE_TYPE_NB][SQUARE_NB];
+Bitboard LeaperAttacks[COLOR_NB][PIECE_TYPE_NB][SQUARE_NB];
+Bitboard LeaperMoves[2][COLOR_NB][PIECE_TYPE_NB][SQUARE_NB];
+Bitboard BoardSizeBB[FILE_NB][RANK_NB];
+RiderType AttackRiderTypes[PIECE_TYPE_NB];
+RiderType MoveRiderTypes[2][PIECE_TYPE_NB];
+
+Magic RookMagicsH[SQUARE_NB];
+Magic RookMagicsV[SQUARE_NB];
+Magic BishopMagics[SQUARE_NB];
+Magic CannonMagicsH[SQUARE_NB];
+Magic CannonMagicsV[SQUARE_NB];
+Magic LameDabbabaMagics[SQUARE_NB];
+Magic HorseMagics[SQUARE_NB];
+Magic ElephantMagics[SQUARE_NB];
+Magic JanggiElephantMagics[SQUARE_NB];
+Magic CannonDiagMagics[SQUARE_NB];
+Magic NightriderMagics[SQUARE_NB];
+Magic GrasshopperMagicsH[SQUARE_NB];
+Magic GrasshopperMagicsV[SQUARE_NB];
+Magic GrasshopperMagicsD[SQUARE_NB];
+
+Magic* magics[] = {BishopMagics, RookMagicsH, RookMagicsV, CannonMagicsH, CannonMagicsV,
+ LameDabbabaMagics, HorseMagics, ElephantMagics, JanggiElephantMagics, CannonDiagMagics, NightriderMagics,
+ GrasshopperMagicsH, GrasshopperMagicsV, GrasshopperMagicsD};
+
+namespace {
+
+// Some magics need to be split in order to reduce memory consumption.
+// Otherwise on a 12x10 board they can be >100 MB.
+#ifdef LARGEBOARDS
+ Bitboard RookTableH[0x11800]; // To store horizontal rook attacks
+ Bitboard RookTableV[0x4800]; // To store vertical rook attacks
+ Bitboard BishopTable[0x33C00]; // To store bishop attacks
+ Bitboard CannonTableH[0x11800]; // To store horizontal cannon attacks
+ Bitboard CannonTableV[0x4800]; // To store vertical cannon attacks
+ Bitboard LameDabbabaTable[0x500]; // To store lame dabbaba attacks
+ Bitboard HorseTable[0x500]; // To store horse attacks
+ Bitboard ElephantTable[0x400]; // To store elephant attacks
+ Bitboard JanggiElephantTable[0x1C000]; // To store janggi elephant attacks
+ Bitboard CannonDiagTable[0x33C00]; // To store diagonal cannon attacks
+ Bitboard NightriderTable[0x70200]; // To store nightrider attacks
+ Bitboard GrasshopperTableH[0x11800]; // To store horizontal grasshopper attacks
+ Bitboard GrasshopperTableV[0x4800]; // To store vertical grasshopper attacks
+ Bitboard GrasshopperTableD[0x33C00]; // To store diagonal grasshopper attacks
+#else
+ Bitboard RookTableH[0xA00]; // To store horizontal rook attacks
+ Bitboard RookTableV[0xA00]; // To store vertical rook attacks
+ Bitboard BishopTable[0x1480]; // To store bishop attacks
+ Bitboard CannonTableH[0xA00]; // To store horizontal cannon attacks
+ Bitboard CannonTableV[0xA00]; // To store vertical cannon attacks
+ Bitboard LameDabbabaTable[0x240]; // To store lame dabbaba attacks
+ Bitboard HorseTable[0x240]; // To store horse attacks
+ Bitboard ElephantTable[0x1A0]; // To store elephant attacks
+ Bitboard JanggiElephantTable[0x5C00]; // To store janggi elephant attacks
+ Bitboard CannonDiagTable[0x1480]; // To store diagonal cannon attacks
+ Bitboard NightriderTable[0x1840]; // To store nightrider attacks
+ Bitboard GrasshopperTableH[0xA00]; // To store horizontal grasshopper attacks
+ Bitboard GrasshopperTableV[0xA00]; // To store vertical grasshopper attacks
+ Bitboard GrasshopperTableD[0x1480]; // To store diagonal grasshopper attacks
+#endif
+
+ // Rider directions
+ const std::map RookDirectionsV { {NORTH, 0}, {SOUTH, 0}};
+ const std::map RookDirectionsH { {EAST, 0}, {WEST, 0} };
+ const std::map BishopDirections { {NORTH_EAST, 0}, {SOUTH_EAST, 0}, {SOUTH_WEST, 0}, {NORTH_WEST, 0} };
+ const std::map LameDabbabaDirections { {2 * NORTH, 0}, {2 * EAST, 0}, {2 * SOUTH, 0}, {2 * WEST, 0} };
+ const std::map HorseDirections { {2 * SOUTH + WEST, 0}, {2 * SOUTH + EAST, 0}, {SOUTH + 2 * WEST, 0}, {SOUTH + 2 * EAST, 0},
+ {NORTH + 2 * WEST, 0}, {NORTH + 2 * EAST, 0}, {2 * NORTH + WEST, 0}, {2 * NORTH + EAST, 0} };
+ const std::map ElephantDirections { {2 * NORTH_EAST, 0}, {2 * SOUTH_EAST, 0}, {2 * SOUTH_WEST, 0}, {2 * NORTH_WEST, 0} };
+ const std::map JanggiElephantDirections { {NORTH + 2 * NORTH_EAST, 0}, {EAST + 2 * NORTH_EAST, 0},
+ {EAST + 2 * SOUTH_EAST, 0}, {SOUTH + 2 * SOUTH_EAST, 0},
+ {SOUTH + 2 * SOUTH_WEST, 0}, {WEST + 2 * SOUTH_WEST, 0},
+ {WEST + 2 * NORTH_WEST, 0}, {NORTH + 2 * NORTH_WEST, 0} };
+ const std::map GrasshopperDirectionsV { {NORTH, 1}, {SOUTH, 1}};
+ const std::map GrasshopperDirectionsH { {EAST, 1}, {WEST, 1} };
+ const std::map GrasshopperDirectionsD { {NORTH_EAST, 1}, {SOUTH_EAST, 1}, {SOUTH_WEST, 1}, {NORTH_WEST, 1} };
+
+ enum MovementType { RIDER, HOPPER, LAME_LEAPER, HOPPER_RANGE };
+
+ template
+#ifdef PRECOMPUTED_MAGICS
+ void init_magics(Bitboard table[], Magic magics[], std::map directions, const Bitboard magicsInit[]);
+#else
+ void init_magics(Bitboard table[], Magic magics[], std::map directions);
+#endif
+
+ template
+ Bitboard sliding_attack(std::map directions, Square sq, Bitboard occupied, Color c = WHITE) {
+ assert(MT != LAME_LEAPER);
+
+ Bitboard attack = 0;
+
+ for (auto const& [d, limit] : directions)
+ {
+ int count = 0;
+ bool hurdle = false;
+ for (Square s = sq + (c == WHITE ? d : -d);
+ is_ok(s) && distance(s, s - (c == WHITE ? d : -d)) <= 2;
+ s += (c == WHITE ? d : -d))
+ {
+ if (MT != HOPPER || hurdle)
+ {
+ attack |= s;
+ // For hoppers we consider limit == 1 as a grasshopper,
+ // but limit > 1 as a limited distance hopper
+ if (limit && !(MT == HOPPER_RANGE && limit == 1) && ++count >= limit)
+ break;
+ }
+
+ if (occupied & s)
+ {
+ if (MT == HOPPER && !hurdle)
+ hurdle = true;
+ else
+ break;
+ }
+ }
+ }
+
+ return attack;
+ }
+
+ Bitboard lame_leaper_path(Direction d, Square s) {
+ Direction dr = d > 0 ? NORTH : SOUTH;
+ Direction df = (std::abs(d % NORTH) < NORTH / 2 ? d % NORTH : -(d % NORTH)) < 0 ? WEST : EAST;
+ Square to = s + d;
+ Bitboard b = 0;
+ if (!is_ok(to) || distance(s, to) >= 4)
+ return b;
+ while (s != to)
+ {
+ int diff = std::abs(file_of(to) - file_of(s)) - std::abs(rank_of(to) - rank_of(s));
+ if (diff > 0)
+ s += df;
+ else if (diff < 0)
+ s += dr;
+ else
+ s += df + dr;
+
+ if (s != to)
+ b |= s;
+ }
+ return b;
+ }
+
+ Bitboard lame_leaper_path(std::map directions, Square s) {
+ Bitboard b = 0;
+ for (const auto& i : directions)
+ b |= lame_leaper_path(i.first, s);
+ return b;
+ }
+
+ Bitboard lame_leaper_attack(std::map directions, Square s, Bitboard occupied) {
+ Bitboard b = 0;
+ for (const auto& i : directions)
+ {
+ Square to = s + i.first;
+ if (is_ok(to) && distance(s, to) < 4 && !(lame_leaper_path(i.first, s) & occupied))
+ b |= to;
+ }
+ return b;
+ }
+
+}
+
+/// safe_destination() returns the bitboard of target square for the given step
+/// from the given square. If the step is off the board, returns empty bitboard.
+
+inline Bitboard safe_destination(Square s, int step) {
+ Square to = Square(s + step);
+ return is_ok(to) && distance(s, to) <= 3 ? square_bb(to) : Bitboard(0);
+}
+
+
+/// Bitboards::pretty() returns an ASCII representation of a bitboard suitable
+/// to be printed to standard output. Useful for debugging.
+
+std::string Bitboards::pretty(Bitboard b) {
+
+ std::string s = "+---+---+---+---+---+---+---+---+---+---+---+---+\n";
+
+ for (Rank r = RANK_MAX; r >= RANK_1; --r)
+ {
+ for (File f = FILE_A; f <= FILE_MAX; ++f)
+ s += b & make_square(f, r) ? "| X " : "| ";
+
+ s += "| " + std::to_string(1 + r) + "\n+---+---+---+---+---+---+---+---+---+---+---+---+\n";
+ }
+ s += " a b c d e f g h i j k l\n";
+
+ return s;
+}
+
+/// Bitboards::init_pieces() initializes piece move/attack bitboards and rider types
+
+void Bitboards::init_pieces() {
+
+ for (PieceType pt = PAWN; pt <= KING; ++pt)
+ {
+ const PieceInfo* pi = pieceMap.find(pt)->second;
+
+ // Detect rider types
+ for (auto modality : {MODALITY_QUIET, MODALITY_CAPTURE})
+ {
+ for (bool initial : {false, true})
+ {
+ // We do not support initial captures
+ if (modality == MODALITY_CAPTURE && initial)
+ continue;
+ auto& riderTypes = modality == MODALITY_CAPTURE ? AttackRiderTypes[pt] : MoveRiderTypes[initial][pt];
+ riderTypes = NO_RIDER;
+ for (auto const& [d, limit] : pi->steps[initial][modality])
+ {
+ if (limit && LameDabbabaDirections.find(d) != LameDabbabaDirections.end())
+ riderTypes |= RIDER_LAME_DABBABA;
+ if (limit && HorseDirections.find(d) != HorseDirections.end())
+ riderTypes |= RIDER_HORSE;
+ if (limit && ElephantDirections.find(d) != ElephantDirections.end())
+ riderTypes |= RIDER_ELEPHANT;
+ if (limit && JanggiElephantDirections.find(d) != JanggiElephantDirections.end())
+ riderTypes |= RIDER_JANGGI_ELEPHANT;
+ }
+ for (auto const& [d, limit] : pi->slider[initial][modality])
+ {
+ if (BishopDirections.find(d) != BishopDirections.end())
+ riderTypes |= RIDER_BISHOP;
+ if (RookDirectionsH.find(d) != RookDirectionsH.end())
+ riderTypes |= RIDER_ROOK_H;
+ if (RookDirectionsV.find(d) != RookDirectionsV.end())
+ riderTypes |= RIDER_ROOK_V;
+ if (HorseDirections.find(d) != HorseDirections.end())
+ riderTypes |= RIDER_NIGHTRIDER;
+ }
+ for (auto const& [d, limit] : pi->hopper[initial][modality])
+ {
+ if (RookDirectionsH.find(d) != RookDirectionsH.end())
+ riderTypes |= limit == 1 ? RIDER_GRASSHOPPER_H : RIDER_CANNON_H;
+ if (RookDirectionsV.find(d) != RookDirectionsV.end())
+ riderTypes |= limit == 1 ? RIDER_GRASSHOPPER_V : RIDER_CANNON_V;
+ if (BishopDirections.find(d) != BishopDirections.end())
+ riderTypes |= limit == 1 ? RIDER_GRASSHOPPER_D : RIDER_CANNON_DIAG;
+ }
+ }
+ }
+
+ // Initialize move/attack bitboards
+ for (Color c : { WHITE, BLACK })
+ {
+ for (Square s = SQ_A1; s <= SQ_MAX; ++s)
+ {
+ for (auto modality : {MODALITY_QUIET, MODALITY_CAPTURE})
+ {
+ for (bool initial : {false, true})
+ {
+ // We do not support initial captures
+ if (modality == MODALITY_CAPTURE && initial)
+ continue;
+ auto& pseudo = modality == MODALITY_CAPTURE ? PseudoAttacks[c][pt][s] : PseudoMoves[initial][c][pt][s];
+ auto& leaper = modality == MODALITY_CAPTURE ? LeaperAttacks[c][pt][s] : LeaperMoves[initial][c][pt][s];
+ pseudo = 0;
+ leaper = 0;
+ for (auto const& [d, limit] : pi->steps[initial][modality])
+ {
+ pseudo |= safe_destination(s, c == WHITE ? d : -d);
+ if (!limit)
+ leaper |= safe_destination(s, c == WHITE ? d : -d);
+ }
+ pseudo |= sliding_attack(pi->slider[initial][modality], s, 0, c);
+ pseudo |= sliding_attack(pi->hopper[initial][modality], s, 0, c);
+ }
+ }
+ }
+ }
+ }
+}
+
+
+/// Bitboards::init() initializes various bitboard tables. It is called at
+/// startup and relies on global objects to be already zero-initialized.
+
+void Bitboards::init() {
+
+ for (unsigned i = 0; i < (1 << 16); ++i)
+ PopCnt16[i] = uint8_t(std::bitset<16>(i).count());
+
+ for (Square s = SQ_A1; s <= SQ_MAX; ++s)
+ SquareBB[s] = make_bitboard(s);
+
+ for (File f = FILE_A; f <= FILE_MAX; ++f)
+ for (Rank r = RANK_1; r <= RANK_MAX; ++r)
+ BoardSizeBB[f][r] = forward_file_bb(BLACK, make_square(f, r)) | SquareBB[make_square(f, r)] | (f > FILE_A ? BoardSizeBB[f - 1][r] : Bitboard(0));
+
+ for (Square s1 = SQ_A1; s1 <= SQ_MAX; ++s1)
+ for (Square s2 = SQ_A1; s2 <= SQ_MAX; ++s2)
+ SquareDistance[s1][s2] = std::max(distance(s1, s2), distance(s1, s2));
+
+#ifdef PRECOMPUTED_MAGICS
+ init_magics(RookTableH, RookMagicsH, RookDirectionsH, RookMagicHInit);
+ init_magics(RookTableV, RookMagicsV, RookDirectionsV, RookMagicVInit);
+ init_magics(BishopTable, BishopMagics, BishopDirections, BishopMagicInit);
+ init_magics(CannonTableH, CannonMagicsH, RookDirectionsH, CannonMagicHInit);
+ init_magics(CannonTableV, CannonMagicsV, RookDirectionsV, CannonMagicVInit);
+ init_magics(LameDabbabaTable, LameDabbabaMagics, LameDabbabaDirections, LameDabbabaMagicInit);
+ init_magics(HorseTable, HorseMagics, HorseDirections, HorseMagicInit);
+ init_magics(ElephantTable, ElephantMagics, ElephantDirections, ElephantMagicInit);
+ init_magics(JanggiElephantTable, JanggiElephantMagics, JanggiElephantDirections, JanggiElephantMagicInit);
+ init_magics(CannonDiagTable, CannonDiagMagics, BishopDirections, CannonDiagMagicInit);
+ init_magics(NightriderTable, NightriderMagics, HorseDirections, NightriderMagicInit);
+ init_magics(GrasshopperTableH, GrasshopperMagicsH, GrasshopperDirectionsH, GrasshopperMagicHInit);
+ init_magics(GrasshopperTableV, GrasshopperMagicsV, GrasshopperDirectionsV, GrasshopperMagicVInit);
+ init_magics(GrasshopperTableD, GrasshopperMagicsD, GrasshopperDirectionsD, GrasshopperMagicDInit);
+#else
+ init_magics(RookTableH, RookMagicsH, RookDirectionsH);
+ init_magics(RookTableV, RookMagicsV, RookDirectionsV);
+ init_magics(BishopTable, BishopMagics, BishopDirections);
+ init_magics(CannonTableH, CannonMagicsH, RookDirectionsH);
+ init_magics(CannonTableV, CannonMagicsV, RookDirectionsV);
+ init_magics(LameDabbabaTable, LameDabbabaMagics, LameDabbabaDirections);
+ init_magics(HorseTable, HorseMagics, HorseDirections);
+ init_magics(ElephantTable, ElephantMagics, ElephantDirections);
+ init_magics(JanggiElephantTable, JanggiElephantMagics, JanggiElephantDirections);
+ init_magics(CannonDiagTable, CannonDiagMagics, BishopDirections);
+ init_magics(NightriderTable, NightriderMagics, HorseDirections);
+ init_magics(GrasshopperTableH, GrasshopperMagicsH, GrasshopperDirectionsH);
+ init_magics(GrasshopperTableV, GrasshopperMagicsV, GrasshopperDirectionsV);
+ init_magics(GrasshopperTableD, GrasshopperMagicsD, GrasshopperDirectionsD);
+#endif
+
+ init_pieces();
+
+ for (Square s1 = SQ_A1; s1 <= SQ_MAX; ++s1)
+ {
+ for (PieceType pt : { BISHOP, ROOK })
+ for (Square s2 = SQ_A1; s2 <= SQ_MAX; ++s2)
+ {
+ if (PseudoAttacks[WHITE][pt][s1] & s2)
+ {
+ LineBB[s1][s2] = (attacks_bb(WHITE, pt, s1, 0) & attacks_bb(WHITE, pt, s2, 0)) | s1 | s2;
+ BetweenBB[s1][s2] = (attacks_bb(WHITE, pt, s1, square_bb(s2)) & attacks_bb(WHITE, pt, s2, square_bb(s1)));
+ }
+ BetweenBB[s1][s2] |= s2;
+ }
+ }
+}
+
+namespace {
+
+ // init_magics() computes all rook and bishop attacks at startup. Magic
+ // bitboards are used to look up attacks of sliding pieces. As a reference see
+ // www.chessprogramming.org/Magic_Bitboards. In particular, here we use the so
+ // called "fancy" approach.
+
+ template
+#ifdef PRECOMPUTED_MAGICS
+ void init_magics(Bitboard table[], Magic magics[], std::map directions, const Bitboard magicsInit[]) {
+#else
+ void init_magics(Bitboard table[], Magic magics[], std::map directions) {
+#endif
+
+ // Optimal PRNG seeds to pick the correct magics in the shortest time
+#ifndef PRECOMPUTED_MAGICS
+#ifdef LARGEBOARDS
+ int seeds[][RANK_NB] = { { 734, 10316, 55013, 32803, 12281, 15100, 16645, 255, 346, 89123 },
+ { 734, 10316, 55013, 32803, 12281, 15100, 16645, 255, 346, 89123 } };
+#else
+ int seeds[][RANK_NB] = { { 8977, 44560, 54343, 38998, 5731, 95205, 104912, 17020 },
+ { 728, 10316, 55013, 32803, 12281, 15100, 16645, 255 } };
+#endif
+#endif
+
+ Bitboard* occupancy = new Bitboard[1 << (FILE_NB + RANK_NB - 4)];
+ Bitboard* reference = new Bitboard[1 << (FILE_NB + RANK_NB - 4)];
+ Bitboard edges, b;
+ int* epoch = new int[1 << (FILE_NB + RANK_NB - 4)]();
+ int cnt = 0, size = 0;
+
+ for (Square s = SQ_A1; s <= SQ_MAX; ++s)
+ {
+ // Board edges are not considered in the relevant occupancies
+ edges = ((Rank1BB | rank_bb(RANK_MAX)) & ~rank_bb(s)) | ((FileABB | file_bb(FILE_MAX)) & ~file_bb(s));
+
+ // Given a square 's', the mask is the bitboard of sliding attacks from
+ // 's' computed on an empty board. The index must be big enough to contain
+ // all the attacks for each possible subset of the mask and so is 2 power
+ // the number of 1s of the mask. Hence we deduce the size of the shift to
+ // apply to the 64 or 32 bits word to get the index.
+ Magic& m = magics[s];
+ // The mask for hoppers is unlimited distance, even if the hopper is limited distance (e.g., grasshopper)
+ m.mask = (MT == LAME_LEAPER ? lame_leaper_path(directions, s) : sliding_attack(directions, s, 0)) & ~edges;
+#ifdef LARGEBOARDS
+ m.shift = 128 - popcount(m.mask);
+#else
+ m.shift = (Is64Bit ? 64 : 32) - popcount(m.mask);
+#endif
+
+ // Set the offset for the attacks table of the square. We have individual
+ // table sizes for each square with "Fancy Magic Bitboards".
+ m.attacks = s == SQ_A1 ? table : magics[s - 1].attacks + size;
+
+ // Use Carry-Rippler trick to enumerate all subsets of masks[s] and
+ // store the corresponding sliding attack bitboard in reference[].
+ b = size = 0;
+ do {
+ occupancy[size] = b;
+ reference[size] = MT == LAME_LEAPER ? lame_leaper_attack(directions, s, b) : sliding_attack(directions, s, b);
+
+ if (HasPext)
+ m.attacks[pext(b, m.mask)] = reference[size];
+
+ size++;
+ b = (b - m.mask) & m.mask;
+ } while (b);
+
+ if (HasPext)
+ continue;
+
+#ifndef PRECOMPUTED_MAGICS
+ PRNG rng(seeds[Is64Bit][rank_of(s)]);
+#endif
+
+ // Find a magic for square 's' picking up an (almost) random number
+ // until we find the one that passes the verification test.
+ for (int i = 0; i < size; )
+ {
+ for (m.magic = 0; popcount((m.magic * m.mask) >> (SQUARE_NB - FILE_NB)) < FILE_NB - 2; )
+ {
+#ifdef LARGEBOARDS
+#ifdef PRECOMPUTED_MAGICS
+ m.magic = magicsInit[s];
+#else
+ m.magic = (rng.sparse_rand() << 64) ^ rng.sparse_rand();
+#endif
+#else
+ m.magic = rng.sparse_rand();
+#endif
+ }
+
+ // A good magic must map every possible occupancy to an index that
+ // looks up the correct sliding attack in the attacks[s] database.
+ // Note that we build up the database for square 's' as a side
+ // effect of verifying the magic. Keep track of the attempt count
+ // and save it in epoch[], little speed-up trick to avoid resetting
+ // m.attacks[] after every failed attempt.
+ for (++cnt, i = 0; i < size; ++i)
+ {
+ unsigned idx = m.index(occupancy[i]);
+
+ if (epoch[idx] < cnt)
+ {
+ epoch[idx] = cnt;
+ m.attacks[idx] = reference[i];
+ }
+ else if (m.attacks[idx] != reference[i])
+ break;
+ }
+ }
+ }
+
+ delete[] occupancy;
+ delete[] reference;
+ delete[] epoch;
+ }
+}
+
+} // namespace Stockfish
diff --git a/Fairy-Stockfish-master/src/bitboard.h b/Fairy-Stockfish-master/src/bitboard.h
new file mode 100644
index 0000000000000000000000000000000000000000..ce575b5d3f34a090eab35143717c729f5b731ed7
--- /dev/null
+++ b/Fairy-Stockfish-master/src/bitboard.h
@@ -0,0 +1,787 @@
+/*
+ Stockfish, a UCI chess playing engine derived from Glaurung 2.1
+ Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
+
+ Stockfish is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Stockfish is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef BITBOARD_H_INCLUDED
+#define BITBOARD_H_INCLUDED
+
+#include
+
+#include "types.h"
+
+namespace Stockfish {
+
+namespace Bitbases {
+
+void init();
+bool probe(Square wksq, Square wpsq, Square bksq, Color us);
+
+} // namespace Stockfish::Bitbases
+
+namespace Bitboards {
+
+void init_pieces();
+void init();
+std::string pretty(Bitboard b);
+
+} // namespace Stockfish::Bitboards
+
+#ifdef LARGEBOARDS
+constexpr Bitboard AllSquares = ((~Bitboard(0)) >> 8);
+#else
+constexpr Bitboard AllSquares = ~Bitboard(0);
+#endif
+#ifdef LARGEBOARDS
+constexpr Bitboard DarkSquares = (Bitboard(0xAAA555AAA555AAULL) << 64) ^ Bitboard(0xA555AAA555AAA555ULL);
+#else
+constexpr Bitboard DarkSquares = 0xAA55AA55AA55AA55ULL;
+#endif
+
+#ifdef LARGEBOARDS
+constexpr Bitboard FileABB = (Bitboard(0x00100100100100ULL) << 64) ^ Bitboard(0x1001001001001001ULL);
+#else
+constexpr Bitboard FileABB = 0x0101010101010101ULL;
+#endif
+constexpr Bitboard FileBBB = FileABB << 1;
+constexpr Bitboard FileCBB = FileABB << 2;
+constexpr Bitboard FileDBB = FileABB << 3;
+constexpr Bitboard FileEBB = FileABB << 4;
+constexpr Bitboard FileFBB = FileABB << 5;
+constexpr Bitboard FileGBB = FileABB << 6;
+constexpr Bitboard FileHBB = FileABB << 7;
+#ifdef LARGEBOARDS
+constexpr Bitboard FileIBB = FileABB << 8;
+constexpr Bitboard FileJBB = FileABB << 9;
+constexpr Bitboard FileKBB = FileABB << 10;
+constexpr Bitboard FileLBB = FileABB << 11;
+#endif
+
+
+#ifdef LARGEBOARDS
+constexpr Bitboard Rank1BB = 0xFFF;
+#else
+constexpr Bitboard Rank1BB = 0xFF;
+#endif
+constexpr Bitboard Rank2BB = Rank1BB << (FILE_NB * 1);
+constexpr Bitboard Rank3BB = Rank1BB << (FILE_NB * 2);
+constexpr Bitboard Rank4BB = Rank1BB << (FILE_NB * 3);
+constexpr Bitboard Rank5BB = Rank1BB << (FILE_NB * 4);
+constexpr Bitboard Rank6BB = Rank1BB << (FILE_NB * 5);
+constexpr Bitboard Rank7BB = Rank1BB << (FILE_NB * 6);
+constexpr Bitboard Rank8BB = Rank1BB << (FILE_NB * 7);
+#ifdef LARGEBOARDS
+constexpr Bitboard Rank9BB = Rank1BB << (FILE_NB * 8);
+constexpr Bitboard Rank10BB = Rank1BB << (FILE_NB * 9);
+#endif
+
+constexpr Bitboard QueenSide = FileABB | FileBBB | FileCBB | FileDBB;
+constexpr Bitboard CenterFiles = FileCBB | FileDBB | FileEBB | FileFBB;
+constexpr Bitboard KingSide = FileEBB | FileFBB | FileGBB | FileHBB;
+constexpr Bitboard Center = (FileDBB | FileEBB) & (Rank4BB | Rank5BB);
+
+constexpr Bitboard KingFlank[FILE_NB] = {
+ QueenSide ^ FileDBB, QueenSide, QueenSide,
+ CenterFiles, CenterFiles,
+ KingSide, KingSide, KingSide ^ FileEBB
+};
+
+extern uint8_t PopCnt16[1 << 16];
+extern uint8_t SquareDistance[SQUARE_NB][SQUARE_NB];
+
+extern Bitboard SquareBB[SQUARE_NB];
+extern Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
+extern Bitboard LineBB[SQUARE_NB][SQUARE_NB];
+extern Bitboard PseudoAttacks[COLOR_NB][PIECE_TYPE_NB][SQUARE_NB];
+extern Bitboard PseudoMoves[2][COLOR_NB][PIECE_TYPE_NB][SQUARE_NB];
+extern Bitboard LeaperAttacks[COLOR_NB][PIECE_TYPE_NB][SQUARE_NB];
+extern Bitboard LeaperMoves[2][COLOR_NB][PIECE_TYPE_NB][SQUARE_NB];
+extern Bitboard SquareBB[SQUARE_NB];
+extern Bitboard BoardSizeBB[FILE_NB][RANK_NB];
+extern RiderType AttackRiderTypes[PIECE_TYPE_NB];
+extern RiderType MoveRiderTypes[2][PIECE_TYPE_NB];
+
+#ifdef LARGEBOARDS
+int popcount(Bitboard b); // required for 128 bit pext
+#endif
+
+/// Magic holds all magic bitboards relevant data for a single square
+struct Magic {
+ Bitboard mask;
+ Bitboard magic;
+ Bitboard* attacks;
+ unsigned shift;
+
+ // Compute the attack's index using the 'magic bitboards' approach
+ unsigned index(Bitboard occupied) const {
+
+ if (HasPext)
+ return unsigned(pext(occupied, mask));
+
+#ifdef LARGEBOARDS
+ return unsigned(((occupied & mask) * magic) >> shift);
+#else
+ if (Is64Bit)
+ return unsigned(((occupied & mask) * magic) >> shift);
+#endif
+
+ unsigned lo = unsigned(occupied) & unsigned(mask);
+ unsigned hi = unsigned(occupied >> 32) & unsigned(mask >> 32);
+ return (lo * unsigned(magic) ^ hi * unsigned(magic >> 32)) >> shift;
+ }
+};
+
+extern Magic RookMagicsH[SQUARE_NB];
+extern Magic RookMagicsV[SQUARE_NB];
+extern Magic BishopMagics[SQUARE_NB];
+extern Magic CannonMagicsH[SQUARE_NB];
+extern Magic CannonMagicsV[SQUARE_NB];
+extern Magic LameDabbabaMagics[SQUARE_NB];
+extern Magic HorseMagics[SQUARE_NB];
+extern Magic ElephantMagics[SQUARE_NB];
+extern Magic JanggiElephantMagics[SQUARE_NB];
+extern Magic CannonDiagMagics[SQUARE_NB];
+extern Magic NightriderMagics[SQUARE_NB];
+extern Magic GrasshopperMagicsH[SQUARE_NB];
+extern Magic GrasshopperMagicsV[SQUARE_NB];
+extern Magic GrasshopperMagicsD[SQUARE_NB];
+
+extern Magic* magics[];
+
+constexpr Bitboard make_bitboard() { return 0; }
+
+template
+constexpr Bitboard make_bitboard(Square s, Squares... squares) {
+ return (Bitboard(1) << s) | make_bitboard(squares...);
+}
+
+inline Bitboard square_bb(Square s) {
+ assert(is_ok(s));
+ return SquareBB[s];
+}
+
+
+/// Overloads of bitwise operators between a Bitboard and a Square for testing
+/// whether a given bit is set in a bitboard, and for setting and clearing bits.
+
+inline Bitboard operator&( Bitboard b, Square s) { return b & square_bb(s); }
+inline Bitboard operator|( Bitboard b, Square s) { return b | square_bb(s); }
+inline Bitboard operator^( Bitboard b, Square s) { return b ^ square_bb(s); }
+inline Bitboard& operator|=(Bitboard& b, Square s) { return b |= square_bb(s); }
+inline Bitboard& operator^=(Bitboard& b, Square s) { return b ^= square_bb(s); }
+
+inline Bitboard operator-( Bitboard b, Square s) { return b & ~square_bb(s); }
+inline Bitboard& operator-=(Bitboard& b, Square s) { return b &= ~square_bb(s); }
+
+inline Bitboard operator&(Square s, Bitboard b) { return b & s; }
+inline Bitboard operator|(Square s, Bitboard b) { return b | s; }
+inline Bitboard operator^(Square s, Bitboard b) { return b ^ s; }
+
+inline Bitboard operator|(Square s1, Square s2) { return square_bb(s1) | s2; }
+
+constexpr bool more_than_one(Bitboard b) {
+ return b & (b - 1);
+}
+
+
+inline Bitboard undo_move_board(Bitboard b, Move m) {
+ return (from_sq(m) != SQ_NONE && (b & to_sq(m))) ? (b ^ to_sq(m)) | from_sq(m) : b;
+}
+
+/// board_size_bb() returns a bitboard representing all the squares
+/// on a board with given size.
+
+inline Bitboard board_size_bb(File f, Rank r) {
+ return BoardSizeBB[f][r];
+}
+
+constexpr bool opposite_colors(Square s1, Square s2) {
+ return (s1 + rank_of(s1) + s2 + rank_of(s2)) & 1;
+}
+
+
+/// rank_bb() and file_bb() return a bitboard representing all the squares on
+/// the given file or rank.
+
+constexpr Bitboard rank_bb(Rank r) {
+ return Rank1BB << (FILE_NB * r);
+}
+
+constexpr Bitboard rank_bb(Square s) {
+ return rank_bb(rank_of(s));
+}
+
+constexpr Bitboard file_bb(File f) {
+ return FileABB << f;
+}
+
+constexpr Bitboard file_bb(Square s) {
+ return file_bb(file_of(s));
+}
+
+
+/// shift() moves a bitboard one or two steps as specified by the direction D
+
+template
+constexpr Bitboard shift(Bitboard b) {
+ return D == NORTH ? b << NORTH : D == SOUTH ? b >> NORTH
+ : D == NORTH+NORTH? b <<(2 * NORTH) : D == SOUTH+SOUTH? b >> (2 * NORTH)
+ : D == EAST ? (b & ~file_bb(FILE_MAX)) << EAST : D == WEST ? (b & ~FileABB) >> EAST
+ : D == NORTH_EAST ? (b & ~file_bb(FILE_MAX)) << NORTH_EAST : D == NORTH_WEST ? (b & ~FileABB) << NORTH_WEST
+ : D == SOUTH_EAST ? (b & ~file_bb(FILE_MAX)) >> NORTH_WEST : D == SOUTH_WEST ? (b & ~FileABB) >> NORTH_EAST
+ : Bitboard(0);
+}
+
+
+/// shift() moves a bitboard one step along direction D (mainly for pawns)
+
+constexpr Bitboard shift(Direction D, Bitboard b) {
+ return D == NORTH ? b << NORTH : D == SOUTH ? b >> NORTH
+ : D == NORTH+NORTH? b <<(2 * NORTH) : D == SOUTH+SOUTH? b >> (2 * NORTH)
+ : D == EAST ? (b & ~file_bb(FILE_MAX)) << EAST : D == WEST ? (b & ~FileABB) >> EAST
+ : D == NORTH_EAST ? (b & ~file_bb(FILE_MAX)) << NORTH_EAST : D == NORTH_WEST ? (b & ~FileABB) << NORTH_WEST
+ : D == SOUTH_EAST ? (b & ~file_bb(FILE_MAX)) >> NORTH_WEST : D == SOUTH_WEST ? (b & ~FileABB) >> NORTH_EAST
+ : Bitboard(0);
+}
+
+
+/// pawn_attacks_bb() returns the squares attacked by pawns of the given color
+/// from the squares in the given bitboard.
+
+template
+constexpr Bitboard pawn_attacks_bb(Bitboard b) {
+ return C == WHITE ? shift(b) | shift(b)
+ : shift(b) | shift(b);
+}
+
+inline Bitboard pawn_attacks_bb(Color c, Square s) {
+
+ assert(is_ok(s));
+ return PseudoAttacks[c][PAWN][s];
+}
+
+
+/// pawn_double_attacks_bb() returns the squares doubly attacked by pawns of the
+/// given color from the squares in the given bitboard.
+
+template
+constexpr Bitboard pawn_double_attacks_bb(Bitboard b) {
+ return C == WHITE ? shift(b) & shift(b)
+ : shift(b) & shift(b);
+}
+
+
+/// adjacent_files_bb() returns a bitboard representing all the squares on the
+/// adjacent files of a given square.
+
+constexpr Bitboard adjacent_files_bb(Square s) {
+ return shift(file_bb(s)) | shift(file_bb(s));
+}
+
+
+/// line_bb() returns a bitboard representing an entire line (from board edge
+/// to board edge) that intersects the two given squares. If the given squares
+/// are not on a same file/rank/diagonal, the function returns 0. For instance,
+/// line_bb(SQ_C4, SQ_F7) will return a bitboard with the A2-G8 diagonal.
+
+inline Bitboard line_bb(Square s1, Square s2) {
+
+ assert(is_ok(s1) && is_ok(s2));
+
+ return LineBB[s1][s2];
+}
+
+
+/// between_bb(s1, s2) returns a bitboard representing the squares in the semi-open
+/// segment between the squares s1 and s2 (excluding s1 but including s2). If the
+/// given squares are not on a same file/rank/diagonal, it returns s2. For instance,
+/// between_bb(SQ_C4, SQ_F7) will return a bitboard with squares D5, E6 and F7, but
+/// between_bb(SQ_E6, SQ_F8) will return a bitboard with the square F8. This trick
+/// allows to generate non-king evasion moves faster: the defending piece must either
+/// interpose itself to cover the check or capture the checking piece.
+
+inline Bitboard between_bb(Square s1, Square s2) {
+
+ assert(is_ok(s1) && is_ok(s2));
+
+ return BetweenBB[s1][s2];
+}
+
+inline Bitboard between_bb(Square s1, Square s2, PieceType pt) {
+ if (pt == HORSE)
+ return PseudoAttacks[WHITE][WAZIR][s2] & PseudoAttacks[WHITE][FERS][s1];
+ else if (pt == JANGGI_ELEPHANT)
+ return (PseudoAttacks[WHITE][WAZIR][s2] & PseudoAttacks[WHITE][ALFIL][s1])
+ | (PseudoAttacks[WHITE][KNIGHT][s2] & PseudoAttacks[WHITE][FERS][s1]);
+ else
+ return between_bb(s1, s2);
+}
+
+
+/// forward_ranks_bb() returns a bitboard representing the squares on the ranks in
+/// front of the given one, from the point of view of the given color. For instance,
+/// forward_ranks_bb(BLACK, SQ_D3) will return the 16 squares on ranks 1 and 2.
+
+constexpr Bitboard forward_ranks_bb(Color c, Square s) {
+ return c == WHITE ? (AllSquares ^ Rank1BB) << FILE_NB * relative_rank(WHITE, s, RANK_MAX)
+ : (AllSquares ^ rank_bb(RANK_MAX)) >> FILE_NB * relative_rank(BLACK, s, RANK_MAX);
+}
+
+constexpr Bitboard forward_ranks_bb(Color c, Rank r) {
+ return c == WHITE ? (AllSquares ^ Rank1BB) << FILE_NB * (r - RANK_1)
+ : (AllSquares ^ rank_bb(RANK_MAX)) >> FILE_NB * (RANK_MAX - r);
+}
+
+
+/// zone_bb() returns a bitboard representing the squares on all the ranks
+/// in front of and on the given relative rank, from the point of view of the given color.
+/// For instance, zone_bb(BLACK, RANK_7) will return the 16 squares on ranks 1 and 2.
+
+inline Bitboard zone_bb(Color c, Rank r, Rank maxRank) {
+ return forward_ranks_bb(c, relative_rank(c, r, maxRank)) | rank_bb(relative_rank(c, r, maxRank));
+}
+
+
+/// forward_file_bb() returns a bitboard representing all the squares along the
+/// line in front of the given one, from the point of view of the given color.
+
+constexpr Bitboard forward_file_bb(Color c, Square s) {
+ return forward_ranks_bb(c, s) & file_bb(s);
+}
+
+
+/// pawn_attack_span() returns a bitboard representing all the squares that can
+/// be attacked by a pawn of the given color when it moves along its file, starting
+/// from the given square.
+
+constexpr Bitboard pawn_attack_span(Color c, Square s) {
+ return forward_ranks_bb(c, s) & adjacent_files_bb(s);
+}
+
+
+/// passed_pawn_span() returns a bitboard which can be used to test if a pawn of
+/// the given color and on the given square is a passed pawn.
+
+constexpr Bitboard passed_pawn_span(Color c, Square s) {
+ return pawn_attack_span(c, s) | forward_file_bb(c, s);
+}
+
+
+/// aligned() returns true if the squares s1, s2 and s3 are aligned either on a
+/// straight or on a diagonal line.
+
+inline bool aligned(Square s1, Square s2, Square s3) {
+ return line_bb(s1, s2) & s3;
+}
+
+
+/// distance() functions return the distance between x and y, defined as the
+/// number of steps for a king in x to reach y.
+
+template inline int distance(Square x, Square y);
+template<> inline int distance(Square x, Square y) { return std::abs(file_of(x) - file_of(y)); }
+template<> inline int distance(Square x, Square y) { return std::abs(rank_of(x) - rank_of(y)); }
+template<> inline int distance(Square x, Square y) { return SquareDistance[x][y]; }
+
+inline int edge_distance(File f, File maxFile = FILE_H) { return std::min(f, File(maxFile - f)); }
+inline int edge_distance(Rank r, Rank maxRank = RANK_8) { return std::min(r, Rank(maxRank - r)); }
+
+
+template
+inline Bitboard rider_attacks_bb(Square s, Bitboard occupied) {
+
+ static_assert(R != NO_RIDER && !(R & (R - 1))); // exactly one bit
+ const Magic& m = R == RIDER_ROOK_H ? RookMagicsH[s]
+ : R == RIDER_ROOK_V ? RookMagicsV[s]
+ : R == RIDER_CANNON_H ? CannonMagicsH[s]
+ : R == RIDER_CANNON_V ? CannonMagicsV[s]
+ : R == RIDER_LAME_DABBABA ? LameDabbabaMagics[s]
+ : R == RIDER_HORSE ? HorseMagics[s]
+ : R == RIDER_ELEPHANT ? ElephantMagics[s]
+ : R == RIDER_JANGGI_ELEPHANT ? JanggiElephantMagics[s]
+ : R == RIDER_CANNON_DIAG ? CannonDiagMagics[s]
+ : R == RIDER_NIGHTRIDER ? NightriderMagics[s]
+ : R == RIDER_GRASSHOPPER_H ? GrasshopperMagicsH[s]
+ : R == RIDER_GRASSHOPPER_V ? GrasshopperMagicsV[s]
+ : R == RIDER_GRASSHOPPER_D ? GrasshopperMagicsD[s]
+ : BishopMagics[s];
+ return m.attacks[m.index(occupied)];
+}
+
+inline Square lsb(Bitboard b);
+
+inline Bitboard rider_attacks_bb(RiderType R, Square s, Bitboard occupied) {
+
+ assert(R != NO_RIDER && !(R & (R - 1))); // exactly one bit
+ const Magic& m = magics[lsb(R)][s]; // re-use Bitboard lsb for riders
+ return m.attacks[m.index(occupied)];
+}
+
+
+/// attacks_bb(Square) returns the pseudo attacks of the give piece type
+/// assuming an empty board.
+
+template
+inline Bitboard attacks_bb(Square s) {
+
+ assert((Pt != PAWN) && (is_ok(s)));
+
+ return PseudoAttacks[WHITE][Pt][s];
+}
+
+
+/// attacks_bb(Square, Bitboard) returns the attacks by the given piece
+/// assuming the board is occupied according to the passed Bitboard.
+/// Sliding piece attacks do not continue passed an occupied square.
+
+template
+inline Bitboard attacks_bb(Square s, Bitboard occupied) {
+
+ assert((Pt != PAWN) && (is_ok(s)));
+
+ switch (Pt)
+ {
+ case BISHOP: return rider_attacks_bb(s, occupied);
+ case ROOK : return rider_attacks_bb(s, occupied) | rider_attacks_bb(s, occupied);
+ case QUEEN : return attacks_bb(s, occupied) | attacks_bb(s, occupied);
+ default : return PseudoAttacks[WHITE][Pt][s];
+ }
+}
+
+/// pop_rider() finds and clears a rider in a (hybrid) rider type
+
+inline RiderType pop_rider(RiderType* r) {
+ assert(*r);
+ const RiderType r2 = *r & ~(*r - 1);
+ *r &= *r - 1;
+ return r2;
+}
+
+inline Bitboard attacks_bb(Color c, PieceType pt, Square s, Bitboard occupied) {
+ Bitboard b = LeaperAttacks[c][pt][s];
+ RiderType r = AttackRiderTypes[pt];
+ while (r)
+ b |= rider_attacks_bb(pop_rider(&r), s, occupied);
+ return b & PseudoAttacks[c][pt][s];
+}
+
+
+template
+inline Bitboard moves_bb(Color c, PieceType pt, Square s, Bitboard occupied) {
+ Bitboard b = LeaperMoves[Initial][c][pt][s];
+ RiderType r = MoveRiderTypes[Initial][pt];
+ while (r)
+ b |= rider_attacks_bb(pop_rider(&r), s, occupied);
+ return b & PseudoMoves[Initial][c][pt][s];
+}
+
+
+/// popcount() counts the number of non-zero bits in a bitboard
+
+inline int popcount(Bitboard b) {
+
+#ifndef USE_POPCNT
+
+#ifdef LARGEBOARDS
+ union { Bitboard bb; uint16_t u[8]; } v = { b };
+ return PopCnt16[v.u[0]] + PopCnt16[v.u[1]] + PopCnt16[v.u[2]] + PopCnt16[v.u[3]]
+ + PopCnt16[v.u[4]] + PopCnt16[v.u[5]] + PopCnt16[v.u[6]] + PopCnt16[v.u[7]];
+#else
+ union { Bitboard bb; uint16_t u[4]; } v = { b };
+ return PopCnt16[v.u[0]] + PopCnt16[v.u[1]] + PopCnt16[v.u[2]] + PopCnt16[v.u[3]];
+#endif
+
+#elif defined(_MSC_VER) || defined(__INTEL_COMPILER)
+
+#ifdef LARGEBOARDS
+ return (int)_mm_popcnt_u64(uint64_t(b >> 64)) + (int)_mm_popcnt_u64(uint64_t(b));
+#else
+ return (int)_mm_popcnt_u64(b);
+#endif
+
+#else // Assumed gcc or compatible compiler
+
+#ifdef LARGEBOARDS
+ return __builtin_popcountll(b >> 64) + __builtin_popcountll(b);
+#else
+ return __builtin_popcountll(b);
+#endif
+
+#endif
+}
+
+
+/// lsb() and msb() return the least/most significant bit in a non-zero bitboard
+
+#if defined(__GNUC__) // GCC, Clang, ICC
+
+inline Square lsb(Bitboard b) {
+ assert(b);
+#ifdef LARGEBOARDS
+ if (!(b << 64))
+ return Square(__builtin_ctzll(b >> 64) + 64);
+#endif
+ return Square(__builtin_ctzll(b));
+}
+
+inline Square msb(Bitboard b) {
+ assert(b);
+#ifdef LARGEBOARDS
+ if (b >> 64)
+ return Square(int(SQUARE_BIT_MASK) ^ __builtin_clzll(b >> 64));
+ return Square(int(SQUARE_BIT_MASK) ^ (__builtin_clzll(b) + 64));
+#else
+ return Square(int(SQUARE_BIT_MASK) ^ __builtin_clzll(b));
+#endif
+}
+
+#elif defined(_MSC_VER) // MSVC
+
+#ifdef _WIN64 // MSVC, WIN64
+
+inline Square lsb(Bitboard b) {
+ assert(b);
+ unsigned long idx;
+#ifdef LARGEBOARDS
+ if (uint64_t(b))
+ {
+ _BitScanForward64(&idx, uint64_t(b));
+ return Square(idx);
+ }
+ else
+ {
+ _BitScanForward64(&idx, uint64_t(b >> 64));
+ return Square(idx + 64);
+ }
+#else
+ _BitScanForward64(&idx, b);
+ return (Square) idx;
+#endif
+}
+
+inline Square msb(Bitboard b) {
+ assert(b);
+ unsigned long idx;
+#ifdef LARGEBOARDS
+ if (b >> 64)
+ {
+ _BitScanReverse64(&idx, uint64_t(b >> 64));
+ return Square(idx + 64);
+ }
+ else
+ {
+ _BitScanReverse64(&idx, uint64_t(b));
+ return Square(idx);
+ }
+#else
+ _BitScanReverse64(&idx, b);
+ return (Square) idx;
+#endif
+}
+
+#else // MSVC, WIN32
+
+inline Square lsb(Bitboard b) {
+ assert(b);
+ unsigned long idx;
+
+#ifdef LARGEBOARDS
+ if (b << 96) {
+ _BitScanForward(&idx, uint32_t(b));
+ return Square(idx);
+ } else if (b << 64) {
+ _BitScanForward(&idx, uint32_t(b >> 32));
+ return Square(idx + 32);
+ } else if (b << 32) {
+ _BitScanForward(&idx, uint32_t(b >> 64));
+ return Square(idx + 64);
+ } else {
+ _BitScanForward(&idx, uint32_t(b >> 96));
+ return Square(idx + 96);
+ }
+#else
+ if (b & 0xffffffff) {
+ _BitScanForward(&idx, uint32_t(b));
+ return Square(idx);
+ } else {
+ _BitScanForward(&idx, uint32_t(b >> 32));
+ return Square(idx + 32);
+ }
+#endif
+}
+
+inline Square msb(Bitboard b) {
+ assert(b);
+ unsigned long idx;
+
+#ifdef LARGEBOARDS
+ if (b >> 96) {
+ _BitScanReverse(&idx, uint32_t(b >> 96));
+ return Square(idx + 96);
+ } else if (b >> 64) {
+ _BitScanReverse(&idx, uint32_t(b >> 64));
+ return Square(idx + 64);
+ } else
+#endif
+ if (b >> 32) {
+ _BitScanReverse(&idx, uint32_t(b >> 32));
+ return Square(idx + 32);
+ } else {
+ _BitScanReverse(&idx, uint32_t(b));
+ return Square(idx);
+ }
+}
+
+#endif
+
+#else // Compiler is neither GCC nor MSVC compatible
+
+#error "Compiler not supported."
+
+#endif
+
+/// least_significant_square_bb() returns the bitboard of the least significant
+/// square of a non-zero bitboard. It is equivalent to square_bb(lsb(bb)).
+
+inline Bitboard least_significant_square_bb(Bitboard b) {
+ assert(b);
+ return b & -b;
+}
+
+/// pop_lsb() finds and clears the least significant bit in a non-zero bitboard
+
+inline Square pop_lsb(Bitboard& b) {
+ assert(b);
+ const Square s = lsb(b);
+ b &= b - 1;
+ return s;
+}
+
+
+/// frontmost_sq() returns the most advanced square for the given color,
+/// requires a non-zero bitboard.
+inline Square frontmost_sq(Color c, Bitboard b) {
+ assert(b);
+ return c == WHITE ? msb(b) : lsb(b);
+}
+
+
+/// popcount() counts the number of non-zero bits in a piece set
+
+inline int popcount(PieceSet ps) {
+
+#ifndef USE_POPCNT
+
+ union { uint64_t bb; uint16_t u[4]; } v = { (uint64_t)ps };
+ return PopCnt16[v.u[0]] + PopCnt16[v.u[1]] + PopCnt16[v.u[2]] + PopCnt16[v.u[3]];
+
+#elif defined(_MSC_VER) || defined(__INTEL_COMPILER)
+
+ return (int)_mm_popcnt_u64(ps);
+
+#else // Assumed gcc or compatible compiler
+
+ return __builtin_popcountll(ps);
+
+#endif
+}
+
+/// lsb() and msb() return the least/most significant bit in a non-zero piece set
+
+#if defined(__GNUC__) // GCC, Clang, ICC
+
+inline PieceType lsb(PieceSet ps) {
+ assert(ps);
+ return PieceType(__builtin_ctzll(ps));
+}
+
+inline PieceType msb(PieceSet ps) {
+ assert(ps);
+ return PieceType((PIECE_TYPE_NB - 1) ^ __builtin_clzll(ps));
+}
+
+#elif defined(_MSC_VER) // MSVC
+
+#ifdef _WIN64 // MSVC, WIN64
+
+inline PieceType lsb(PieceSet ps) {
+ assert(ps);
+ unsigned long idx;
+ _BitScanForward64(&idx, ps);
+ return (PieceType) idx;
+}
+
+inline PieceType msb(PieceSet ps) {
+ assert(ps);
+ unsigned long idx;
+ _BitScanReverse64(&idx, ps);
+ return (PieceType) idx;
+}
+
+#else // MSVC, WIN32
+
+inline PieceType lsb(PieceSet ps) {
+ assert(ps);
+ unsigned long idx;
+
+ if (ps & 0xffffffff) {
+ _BitScanForward(&idx, uint32_t(ps));
+ return PieceType(idx);
+ } else {
+ _BitScanForward(&idx, uint32_t(ps >> 32));
+ return PieceType(idx + 32);
+ }
+}
+
+inline PieceType msb(PieceSet ps) {
+ assert(ps);
+ unsigned long idx;
+ if (ps >> 32) {
+ _BitScanReverse(&idx, uint32_t(ps >> 32));
+ return PieceType(idx + 32);
+ } else {
+ _BitScanReverse(&idx, uint32_t(ps));
+ return PieceType(idx);
+ }
+}
+
+#endif
+
+#else // Compiler is neither GCC nor MSVC compatible
+
+#error "Compiler not supported."
+
+#endif
+
+/// pop_lsb() and pop_msb() find and clear the least/most significant bit in a non-zero piece set
+
+inline PieceType pop_lsb(PieceSet& ps) {
+ assert(ps);
+ const PieceType pt = lsb(ps);
+ ps &= PieceSet(ps - 1);
+ return pt;
+}
+
+inline PieceType pop_msb(PieceSet& ps) {
+ assert(ps);
+ const PieceType pt = msb(ps);
+ ps &= ~piece_set(pt);
+ return pt;
+}
+
+} // namespace Stockfish
+
+#endif // #ifndef BITBOARD_H_INCLUDED
diff --git a/Fairy-Stockfish-master/src/endgame.cpp b/Fairy-Stockfish-master/src/endgame.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6a8247d903ad3d2d2899a205b69871dc605ed859
--- /dev/null
+++ b/Fairy-Stockfish-master/src/endgame.cpp
@@ -0,0 +1,1321 @@
+/*
+ Stockfish, a UCI chess playing engine derived from Glaurung 2.1
+ Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
+
+ Stockfish is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Stockfish is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include
+
+#include "bitboard.h"
+#include "endgame.h"
+#include "movegen.h"
+
+namespace Stockfish {
+
+namespace {
+
+ // Used to drive the king towards the edge of the board
+ // in KX vs K and KQ vs KR endgames.
+ // Values range from 27 (center squares) to 90 (in the corners)
+ inline int push_to_edge(Square s, const Position& pos) {
+ int rd = edge_distance(rank_of(s), pos.max_rank()), fd = edge_distance(file_of(s), pos.max_file());
+ return 90 - (7 * fd * fd / 2 + 7 * rd * rd / 2);
+ }
+
+ // Used to drive the king towards A1H8 corners in KBN vs K endgames.
+ // Values range from 0 on A8H1 diagonal to 7 in A1H8 corners.
+ inline int push_to_corner(Square s, const Position& pos) {
+ return abs((pos.max_file() + pos.max_rank()) / 2 - rank_of(s) - file_of(s));
+ }
+
+ // Used to drive the king towards the edge of the board in KSF vs K.
+ inline int push_to_opposing_edge(Square s, const Position& pos) {
+ int rd = rank_of(s), fd = edge_distance(file_of(s), pos.max_file());
+ return 20 - (7 * fd * fd / 2 - 7 * rd * rd / 4);
+ }
+
+ // Drive a piece close to or away from another piece
+ inline int push_close(Square s1, Square s2) { return 140 - 20 * distance(s1, s2); }
+ inline int push_away(Square s1, Square s2) { return 120 - push_close(s1, s2); }
+
+#ifndef NDEBUG
+ bool verify_material(const Position& pos, Color c, Value npm, int pawnsCnt) {
+ return pos.non_pawn_material(c) == npm && pos.count(c) == pawnsCnt;
+ }
+#endif
+
+ // Map the square as if strongSide is white and strongSide's only pawn
+ // is on the left half of the board.
+ Square normalize(const Position& pos, Color strongSide, Square sq) {
+
+ assert(pos.count(strongSide) == 1);
+
+ if (file_of(pos.square(strongSide)) > pos.max_file() / 2)
+ sq = flip_file(sq, pos.max_file());
+
+ return strongSide == WHITE ? sq : flip_rank(sq, pos.max_rank());
+ }
+
+} // namespace
+
+
+namespace Endgames {
+
+ std::pair