BlueMoonBot commited on
Commit
f860ade
·
verified ·
1 Parent(s): 0a2ac5c

Delete Fairy-Stockfish-master

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. Fairy-Stockfish-master/.gitattributes +0 -1
  2. Fairy-Stockfish-master/.github/FUNDING.yml +0 -2
  3. Fairy-Stockfish-master/.github/dependabot.yml +0 -13
  4. Fairy-Stockfish-master/.github/workflows/fairy.yml +0 -93
  5. Fairy-Stockfish-master/.github/workflows/ffishjs.yml +0 -90
  6. Fairy-Stockfish-master/.github/workflows/release.yml +0 -116
  7. Fairy-Stockfish-master/.github/workflows/stockfish.yml +0 -213
  8. Fairy-Stockfish-master/.github/workflows/wheels.yml +0 -57
  9. Fairy-Stockfish-master/.gitignore +0 -43
  10. Fairy-Stockfish-master/AGENTS.md +0 -158
  11. Fairy-Stockfish-master/AUTHORS +0 -231
  12. Fairy-Stockfish-master/Copying.txt +0 -674
  13. Fairy-Stockfish-master/MANIFEST.in +0 -2
  14. Fairy-Stockfish-master/README.md +0 -126
  15. Fairy-Stockfish-master/Top CPU Contributors.txt +0 -205
  16. Fairy-Stockfish-master/appveyor.yml +0 -91
  17. Fairy-Stockfish-master/pyffish.pyi +0 -39
  18. Fairy-Stockfish-master/setup.py +0 -56
  19. Fairy-Stockfish-master/src/Makefile +0 -982
  20. Fairy-Stockfish-master/src/Makefile_js +0 -95
  21. Fairy-Stockfish-master/src/apiutil.h +0 -1165
  22. Fairy-Stockfish-master/src/benchmark.cpp +0 -195
  23. Fairy-Stockfish-master/src/bitbase.cpp +0 -177
  24. Fairy-Stockfish-master/src/bitboard.cpp +0 -501
  25. Fairy-Stockfish-master/src/bitboard.h +0 -787
  26. Fairy-Stockfish-master/src/endgame.cpp +0 -1321
  27. Fairy-Stockfish-master/src/endgame.h +0 -148
  28. Fairy-Stockfish-master/src/evaluate.cpp +0 -1736
  29. Fairy-Stockfish-master/src/evaluate.h +0 -66
  30. Fairy-Stockfish-master/src/ffishjs.cpp +0 -767
  31. Fairy-Stockfish-master/src/incbin/UNLICENCE +0 -26
  32. Fairy-Stockfish-master/src/incbin/incbin.h +0 -368
  33. Fairy-Stockfish-master/src/magic.h +0 -1741
  34. Fairy-Stockfish-master/src/main.cpp +0 -63
  35. Fairy-Stockfish-master/src/material.cpp +0 -321
  36. Fairy-Stockfish-master/src/material.h +0 -75
  37. Fairy-Stockfish-master/src/misc.cpp +0 -656
  38. Fairy-Stockfish-master/src/misc.h +0 -200
  39. Fairy-Stockfish-master/src/movegen.cpp +0 -528
  40. Fairy-Stockfish-master/src/movegen.h +0 -107
  41. Fairy-Stockfish-master/src/movepick.cpp +0 -279
  42. Fairy-Stockfish-master/src/movepick.h +0 -169
  43. Fairy-Stockfish-master/src/nnue/evaluate_nnue.cpp +0 -443
  44. Fairy-Stockfish-master/src/nnue/evaluate_nnue.h +0 -59
  45. Fairy-Stockfish-master/src/nnue/features/half_ka_v2.cpp +0 -90
  46. Fairy-Stockfish-master/src/nnue/features/half_ka_v2.h +0 -152
  47. Fairy-Stockfish-master/src/nnue/features/half_ka_v2_variants.cpp +0 -112
  48. Fairy-Stockfish-master/src/nnue/features/half_ka_v2_variants.h +0 -94
  49. Fairy-Stockfish-master/src/nnue/layers/affine_transform.h +0 -435
  50. Fairy-Stockfish-master/src/nnue/layers/clipped_relu.h +0 -191
Fairy-Stockfish-master/.gitattributes DELETED
@@ -1 +0,0 @@
1
- README.md merge=ours
 
 
Fairy-Stockfish-master/.github/FUNDING.yml DELETED
@@ -1,2 +0,0 @@
1
- # These are supported funding model platforms
2
- github: ianfab
 
 
 
Fairy-Stockfish-master/.github/dependabot.yml DELETED
@@ -1,13 +0,0 @@
1
- # Keep GitHub Actions up to date with GitHub's Dependabot...
2
- # https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot
3
- # https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#package-ecosystem
4
- version: 2
5
- updates:
6
- - package-ecosystem: github-actions
7
- directory: /
8
- groups:
9
- github-actions:
10
- patterns:
11
- - "*" # Group all Actions updates into a single larger pull request
12
- schedule:
13
- interval: weekly
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/.github/workflows/fairy.yml DELETED
@@ -1,93 +0,0 @@
1
- name: fairy
2
- on:
3
- push:
4
- branches:
5
- - master
6
- pull_request:
7
- branches:
8
- - master
9
- jobs:
10
- fairy:
11
- name: ${{ matrix.config.name }}
12
- runs-on: ${{ matrix.config.os }}
13
- env:
14
- COMPILER: ${{ matrix.config.compiler }}
15
- COMP: ${{ matrix.config.comp }}
16
- CXXFLAGS: "-Werror"
17
- strategy:
18
- matrix:
19
- config:
20
- - {
21
- name: "Ubuntu 24.04 GCC",
22
- os: ubuntu-24.04,
23
- compiler: g++,
24
- comp: gcc,
25
- run_expensive_tests: true
26
- }
27
- - {
28
- name: "Ubuntu 24.04 Clang",
29
- os: ubuntu-24.04,
30
- compiler: clang++,
31
- comp: clang,
32
- run_expensive_tests: false
33
- }
34
-
35
- defaults:
36
- run:
37
- working-directory: src
38
- steps:
39
- - uses: actions/checkout@v6
40
- with:
41
- fetch-depth: 0
42
-
43
- - name: Download required packages
44
- run: |
45
- sudo apt update
46
- sudo apt install expect valgrind g++-multilib
47
-
48
- - name: Download the used network from the fishtest framework
49
- run: |
50
- make net
51
-
52
- - name: Test NNUE
53
- run: |
54
- make clean
55
- make -j2 ARCH=x86-64 nnue=yes debug=yes build
56
- ./stockfish bench
57
-
58
- - name: Test NNUE largeboards
59
- run: |
60
- make clean
61
- make -j2 ARCH=x86-64 largeboards=yes nnue=yes debug=yes build
62
- ./stockfish bench
63
-
64
- - name: Build all variants
65
- run: |
66
- make clean
67
- make -j2 ARCH=x86-64 largeboards=yes all=yes debug=yes build
68
-
69
- - name: Test protocols
70
- run: |
71
- ../tests/protocol.sh
72
-
73
- - name: Test variants.ini
74
- run: |
75
- ! ./stockfish check variants.ini 2>&1 >/dev/null | grep -v "Parsing variant"
76
-
77
- - name: Test variant perft
78
- run: |
79
- ../tests/perft.sh all
80
-
81
- - name: Test variant bench
82
- run: |
83
- ./stockfish bench xiangqi
84
- ./stockfish bench shogi
85
- ./stockfish bench capablanca
86
- ./stockfish bench sittuyin
87
-
88
- - name: Test 32bit largeboards
89
- run: |
90
- if [[ "$COMP" == "gcc" ]]; then export EXTRACXXFLAGS=-Wno-class-memaccess; fi
91
- make clean
92
- make -j2 ARCH=x86-32 largeboards=yes build
93
- ../tests/perft.sh largeboard
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/.github/workflows/ffishjs.yml DELETED
@@ -1,90 +0,0 @@
1
- name: ffishjs
2
-
3
- on:
4
- push:
5
- branches: [ master ]
6
- pull_request:
7
- branches: [ master ]
8
-
9
- env:
10
- EM_VERSION: 1.39.16
11
- EM_CACHE_FOLDER: 'emsdk-cache'
12
-
13
- jobs:
14
- test:
15
- runs-on: ubuntu-24.04
16
-
17
- strategy:
18
- matrix:
19
- node-version: [12.x]
20
-
21
- steps:
22
- - uses: actions/checkout@v6
23
- - name: Setup cache
24
- id: cache-system-libraries
25
- uses: actions/cache@v5
26
- with:
27
- path: ${{env.EM_CACHE_FOLDER}}
28
- key: emsdk-${{env.EM_VERSION}}-${{ runner.os }}
29
- - uses: mymindstorm/setup-emsdk@v16
30
- with:
31
- version: ${{env.EM_VERSION}}
32
- actions-cache-folder: ${{env.EM_CACHE_FOLDER}}
33
- - name: Use Node.js ${{ matrix.node-version }}
34
- uses: actions/setup-node@v6
35
- with:
36
- node-version: ${{ matrix.node-version }}
37
- - name: Build ffishjs
38
- working-directory: src
39
- run: make -f Makefile_js build debug=yes
40
- - name: Install dependencies
41
- working-directory: tests/js
42
- run: npm install
43
- - name: Run unit tests
44
- working-directory: tests/js
45
- run: npm test
46
-
47
- build:
48
- runs-on: ubuntu-24.04
49
- needs: [test] #Building process must start after successful testing process
50
-
51
- strategy:
52
- matrix:
53
- node-version: [12.x]
54
-
55
- steps:
56
- - uses: actions/checkout@v6
57
- - name: Setup cache
58
- id: cache-system-libraries
59
- uses: actions/cache@v5
60
- with:
61
- path: ${{env.EM_CACHE_FOLDER}}
62
- key: emsdk-${{env.EM_VERSION}}-${{ runner.os }}
63
- - uses: mymindstorm/setup-emsdk@v16
64
- with:
65
- version: ${{env.EM_VERSION}}
66
- actions-cache-folder: ${{env.EM_CACHE_FOLDER}}
67
- - name: Use Node.js ${{ matrix.node-version }}
68
- uses: actions/setup-node@v6
69
- with:
70
- node-version: ${{ matrix.node-version }}
71
- - name: Build ffish.js ES6/ES2015 module
72
- working-directory: src
73
- run: rm -f ../tests/js/ffish.js & rm -f ../tests/js/ffish.wasm & make -f Makefile_js build es6=yes
74
- - name: Upload ffish.js ES6/ES2015 module ZIP archive
75
- uses: actions/upload-artifact@v7
76
- with:
77
- name: ffishjs-es6
78
- path: tests/js/*
79
- if-no-files-found: error
80
- compression-level: 9
81
- - name: Build ffish.js standard module
82
- working-directory: src
83
- run: rm -f ../tests/js/ffish.js & rm -f ../tests/js/ffish.wasm & make -f Makefile_js build
84
- - name: Upload ffish.js standard module ZIP archive
85
- uses: actions/upload-artifact@v7
86
- with:
87
- name: ffishjs-standard
88
- path: tests/js/*
89
- if-no-files-found: error
90
- compression-level: 9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/.github/workflows/release.yml DELETED
@@ -1,116 +0,0 @@
1
- name: Release
2
-
3
- on:
4
- push:
5
- branches: [ master ]
6
- pull_request:
7
- branches: [ master ]
8
-
9
- jobs:
10
- windows:
11
- strategy:
12
- matrix:
13
- arch: ["x86-64-bmi2", "x86-64-modern", "x86-64"]
14
- runs-on: windows-2022
15
-
16
- steps:
17
- - uses: al-cheb/configure-pagefile-action@v1.5
18
- with:
19
- minimum-size: 16GB
20
- maximum-size: 16GB
21
- disk-root: "C:"
22
-
23
- - uses: actions/checkout@v6
24
-
25
- - name: make
26
- 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
27
-
28
- - name: make largeboards
29
- 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
30
-
31
- - name: make all
32
- if: ${{ matrix.arch == 'x86-64' }}
33
- 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
34
-
35
- - uses: actions/upload-artifact@v7
36
- with:
37
- name: fairy-stockfish-windows-${{ matrix.arch }}
38
- path: src/fairy-stockfish*.exe
39
- if-no-files-found: error
40
- compression-level: 9
41
-
42
- linux:
43
- strategy:
44
- matrix:
45
- arch: ["x86-64-bmi2", "x86-64-modern", "x86-64"]
46
- runs-on: ubuntu-24.04
47
-
48
- steps:
49
- - uses: actions/checkout@v6
50
-
51
- - name: make
52
- run: cd src && make clean && make -j build COMP=gcc ARCH=${{ matrix.arch }} EXE=fairy-stockfish_${{ matrix.arch }} && strip fairy-stockfish_${{ matrix.arch }}
53
-
54
- - name: make largeboards
55
- 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 }}
56
-
57
- - name: make all
58
- if: ${{ matrix.arch == 'x86-64' }}
59
- 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 }}
60
-
61
- - uses: actions/upload-artifact@v7
62
- with:
63
- name: fairy-stockfish-linux-${{ matrix.arch }}
64
- path: src/fairy-stockfish*
65
- if-no-files-found: error
66
- compression-level: 9
67
-
68
- macos:
69
- strategy:
70
- matrix:
71
- arch: ["x86-64"]
72
- runs-on: macos-15-intel
73
-
74
- steps:
75
- - uses: actions/checkout@v6
76
-
77
- - name: make
78
- run: cd src && make clean && make -j build COMP=clang ARCH=${{ matrix.arch }} EXE=fairy-stockfish_${{ matrix.arch }} && strip fairy-stockfish_${{ matrix.arch }}
79
-
80
- - name: make largeboards
81
- 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 }}
82
-
83
- - name: make all
84
- 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 }}
85
-
86
- - uses: actions/upload-artifact@v7
87
- with:
88
- name: fairy-stockfish-macos-${{ matrix.arch }}
89
- path: src/fairy-stockfish*
90
- if-no-files-found: error
91
- compression-level: 9
92
-
93
- macos-m1:
94
- strategy:
95
- matrix:
96
- arch: ["apple-silicon"]
97
- runs-on: macos-14
98
-
99
- steps:
100
- - uses: actions/checkout@v6
101
-
102
- - name: make
103
- run: cd src && make clean && make -j build COMP=clang ARCH=${{ matrix.arch }} EXE=fairy-stockfish_${{ matrix.arch }} && strip fairy-stockfish_${{ matrix.arch }}
104
-
105
- - name: make largeboards
106
- 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 }}
107
-
108
- - name: make all
109
- 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 }}
110
-
111
- - uses: actions/upload-artifact@v7
112
- with:
113
- name: fairy-stockfish-macos-m1-${{ matrix.arch }}
114
- path: src/fairy-stockfish*
115
- if-no-files-found: error
116
- compression-level: 9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/.github/workflows/stockfish.yml DELETED
@@ -1,213 +0,0 @@
1
- name: Stockfish
2
- on:
3
- push:
4
- branches:
5
- - master
6
- - tools
7
- - github_ci
8
- pull_request:
9
- branches:
10
- - master
11
- - tools
12
- jobs:
13
- Stockfish:
14
- name: ${{ matrix.config.name }}
15
- runs-on: ${{ matrix.config.os }}
16
- env:
17
- COMPILER: ${{ matrix.config.compiler }}
18
- COMP: ${{ matrix.config.comp }}
19
- CXXFLAGS: "-Werror"
20
- strategy:
21
- matrix:
22
- config:
23
- - {
24
- name: "Ubuntu 24.04 GCC",
25
- os: ubuntu-24.04,
26
- compiler: g++,
27
- comp: gcc,
28
- run_expensive_tests: true
29
- }
30
- - {
31
- name: "Ubuntu 24.04 Clang",
32
- os: ubuntu-24.04,
33
- compiler: clang++,
34
- comp: clang,
35
- run_expensive_tests: false
36
- }
37
-
38
- defaults:
39
- run:
40
- working-directory: src
41
- steps:
42
- - uses: actions/checkout@v6
43
- with:
44
- fetch-depth: 0
45
-
46
- - name: Download required packages
47
- run: |
48
- sudo apt update
49
- sudo apt install expect valgrind g++-multilib llvm
50
-
51
- - name: Download the used network from the fishtest framework
52
- run: |
53
- make net
54
-
55
- - name: Extract the bench number from the commit history
56
- run: |
57
- git log HEAD | grep "\b[Bb]ench[ :]\+[0-9]\{7\}" | head -n 1 | sed "s/[^0-9]*\([0-9]*\).*/\1/g" > git_sig
58
- [ -s git_sig ] && echo "benchref=$(cat git_sig)" >> $GITHUB_ENV && echo "Reference bench:" $(cat git_sig) || echo "No bench found"
59
-
60
- - name: Check compiler
61
- run: |
62
- $COMPILER -v
63
-
64
- - name: Test help target
65
- run: |
66
- make help
67
-
68
- # x86-32 tests
69
-
70
- - name: Test debug x86-32 build
71
- run: |
72
- export CXXFLAGS="-Werror -D_GLIBCXX_DEBUG"
73
- make clean
74
- make -j2 ARCH=x86-32 optimize=no debug=yes build
75
- ../tests/signature.sh $benchref
76
-
77
- - name: Test debug x86-32 profile build (Optimization on, All features)
78
- run: |
79
- export CXXFLAGS=""
80
- make clean
81
- make -j2 ARCH=x86-32 optimize=yes all=yes largeboards=yes debug=yes profile-build
82
-
83
- - name: Test x86-32 build
84
- run: |
85
- make clean
86
- make -j2 ARCH=x86-32 build
87
- ../tests/signature.sh $benchref
88
-
89
- - name: Test x86-32-sse41-popcnt build
90
- run: |
91
- make clean
92
- make -j2 ARCH=x86-32-sse41-popcnt build
93
- ../tests/signature.sh $benchref
94
-
95
- - name: Test x86-32-sse2 build
96
- run: |
97
- make clean
98
- make -j2 ARCH=x86-32-sse2 build
99
- ../tests/signature.sh $benchref
100
-
101
- - name: Test general-32 build
102
- run: |
103
- make clean
104
- make -j2 ARCH=general-32 build
105
- ../tests/signature.sh $benchref
106
-
107
- # x86-64 tests
108
-
109
- - name: Test debug x86-64-modern build
110
- run: |
111
- export CXXFLAGS="-Werror -D_GLIBCXX_DEBUG"
112
- make clean
113
- make -j2 ARCH=x86-64-modern optimize=no debug=yes build
114
- ../tests/signature.sh $benchref
115
-
116
- - name: Test debug x86-64-modern profile build (Optimization on, All features)
117
- run: |
118
- export CXXFLAGS=""
119
- make clean
120
- make -j2 ARCH=x86-64-modern optimize=yes all=yes largeboards=yes debug=yes profile-build
121
-
122
- - name: Test x86-64-modern build
123
- run: |
124
- make clean
125
- make -j2 ARCH=x86-64-modern build
126
- ../tests/signature.sh $benchref
127
-
128
- - name: Test x86-64-ssse3 build
129
- run: |
130
- make clean
131
- make -j2 ARCH=x86-64-ssse3 build
132
- ../tests/signature.sh $benchref
133
-
134
- - name: Test x86-64-sse3-popcnt build
135
- run: |
136
- make clean
137
- make -j2 ARCH=x86-64-sse3-popcnt build
138
- ../tests/signature.sh $benchref
139
-
140
- - name: Test x86-64 build
141
- run: |
142
- make clean
143
- make -j2 ARCH=x86-64 build
144
- ../tests/signature.sh $benchref
145
-
146
- - name: Test general-64 build
147
- run: |
148
- make clean
149
- make -j2 ARCH=general-64 build
150
- ../tests/signature.sh $benchref
151
-
152
- # x86-64 with newer extensions tests
153
-
154
- - name: Compile x86-64-avx2 build
155
- run: |
156
- make clean
157
- make -j2 ARCH=x86-64-avx2 build
158
-
159
- - name: Compile x86-64-bmi2 build
160
- run: |
161
- make clean
162
- make -j2 ARCH=x86-64-bmi2 build
163
-
164
- - name: Compile x86-64-avx512 build
165
- run: |
166
- make clean
167
- make -j2 ARCH=x86-64-avx512 build
168
-
169
- - name: Compile x86-64-vnni512 build
170
- run: |
171
- make clean
172
- make -j2 ARCH=x86-64-vnni512 build
173
-
174
- - name: Compile x86-64-vnni256 build
175
- run: |
176
- make clean
177
- make -j2 ARCH=x86-64-vnni256 build
178
-
179
- # Other tests
180
-
181
- - name: Check perft and search reproducibility
182
- run: |
183
- make clean
184
- make -j2 ARCH=x86-64-modern build
185
- ../tests/perft.sh
186
- ../tests/reprosearch.sh
187
-
188
- # Sanitizers
189
-
190
- - name: Run under valgrind
191
- if: ${{ matrix.config.run_expensive_tests }}
192
- run: |
193
- export CXXFLAGS="-O1 -fno-inline"
194
- make clean
195
- make -j2 ARCH=x86-64-modern debug=yes optimize=no build > /dev/null
196
- ../tests/instrumented.sh --valgrind
197
- ../tests/instrumented.sh --valgrind-thread
198
-
199
- - name: Run with UB sanitizer
200
- if: ${{ matrix.config.run_expensive_tests }}
201
- run: |
202
- export CXXFLAGS="-O1 -fno-inline"
203
- make clean
204
- make -j2 ARCH=x86-64-modern sanitize=undefined optimize=no debug=yes build > /dev/null
205
- ../tests/instrumented.sh --sanitizer-undefined
206
-
207
- - name: Run with thread sanitizer
208
- if: ${{ matrix.config.run_expensive_tests }}
209
- run: |
210
- export CXXFLAGS="-O1 -fno-inline"
211
- make clean
212
- make -j2 ARCH=x86-64-modern sanitize=thread optimize=no debug=yes build > /dev/null
213
- ../tests/instrumented.sh --sanitizer-thread
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/.github/workflows/wheels.yml DELETED
@@ -1,57 +0,0 @@
1
- name: Wheels
2
-
3
- on:
4
- push:
5
- branches:
6
- - master
7
- pull_request:
8
- branches:
9
- - master
10
-
11
- jobs:
12
- build_wheels:
13
- name: Build wheels on ${{ matrix.os }}
14
- runs-on: ${{ matrix.os }}
15
- strategy:
16
- matrix:
17
- os: [ubuntu-24.04, windows-2022, macos-14]
18
-
19
- steps:
20
- - uses: actions/checkout@v6
21
-
22
- # Used to host cibuildwheel
23
- - uses: actions/setup-python@v6
24
-
25
- - name: Install cibuildwheel
26
- run: python -m pip install cibuildwheel==3.4.0
27
-
28
- - name: Build wheels
29
- run: python -m cibuildwheel --output-dir wheelhouse
30
- # to supply options, put them in 'env', like:
31
- env:
32
- MACOSX_DEPLOYMENT_TARGET: "10.14"
33
- CIBW_ARCHS_MACOS: "x86_64 arm64"
34
- CIBW_SKIP: "pp* *-win32 *-manylinux_i686 *-musllinux_* cp36-* cp37-* cp38"
35
- CIBW_TEST_COMMAND: python {project}/test.py
36
-
37
- - uses: actions/upload-artifact@v7
38
- with:
39
- name: dist-wheel-${{ matrix.os }}
40
- path: ./wheelhouse/*.whl
41
-
42
- build_sdist:
43
- name: Build source distribution
44
- runs-on: ubuntu-24.04
45
- steps:
46
- - uses: actions/checkout@v6
47
- - uses: actions/setup-python@v6
48
- with:
49
- python-version: '3.9'
50
-
51
- - name: Build sdist
52
- run: python setup.py sdist
53
-
54
- - uses: actions/upload-artifact@v7
55
- with:
56
- name: dist-source
57
- path: dist/*.tar.gz
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/.gitignore DELETED
@@ -1,43 +0,0 @@
1
- # Ignore binaries in src/ that have no extension
2
- /src/*
3
- !/src/*.*
4
- !/src/*/
5
-
6
- # Files from build
7
- **/*.o
8
- **/*.s
9
- src/.depend
10
-
11
- # Built binary
12
- src/stockfish*
13
- src/-lstdc++.res
14
-
15
- # Neural network for the NNUE evaluation
16
- **/*.nnue
17
-
18
-
19
- # Build/test artifacts
20
- *.exe
21
- tests/syzygy
22
-
23
- # ffishjs
24
- tests/js/node_modules
25
- ffish.js
26
- *.wasm
27
-
28
- # pyffish
29
- venv
30
- *.so
31
- pyffish.egg-info
32
- __pycache__
33
- *.pyc
34
-
35
- # test artifacts
36
- tests/*.exp
37
- src/*.log
38
- src/*.epd
39
- src/*.txt
40
-
41
- # IDEs
42
- .vscode
43
- .idea
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/AGENTS.md DELETED
@@ -1,158 +0,0 @@
1
- # Fairy-Stockfish Development Guide
2
-
3
- ## Repository Overview
4
-
5
- **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.
6
-
7
- **Repository Statistics:**
8
- - **Languages:** C++17 (primary), Python, JavaScript, Shell scripts
9
- - **Architecture:** Multi-protocol chess engine (UCI, UCCI, USI, XBoard/CECP)
10
- - **Target Platforms:** Windows, Linux, macOS, Android, WebAssembly
11
- - **Supported Variants:** 90+ chess variants including regional, historical, and modern variants
12
-
13
- ## Build System & Requirements
14
-
15
- ### Prerequisites
16
- - **Compiler:** GCC, Clang, or MSVC with C++17 support
17
- - **Build Tool:** GNU Make (required for C++ engine)
18
- - **Python:** 3.7+ (for Python bindings)
19
- - **Node.js:** (for JavaScript bindings)
20
- - **Additional Tools:** expect utility (for testing)
21
-
22
- ### Core Build Process
23
-
24
- Note: Run engine and test commands from the `src/` directory unless specified otherwise.
25
-
26
- #### Basic Build Commands
27
- ```bash
28
- # Standard release build (recommended for most users)
29
- make -j2 ARCH=x86-64 build
30
-
31
- # Debug build (for development)
32
- make -j2 ARCH=x86-64 debug=yes build
33
-
34
- # All variants including ones with large boards (up to 12x10) and large branching factor (all)
35
- make -j2 ARCH=x86-64 largeboards=yes all=yes build
36
- ```
37
-
38
- ### Python Bindings (pyffish)
39
- ```bash
40
- # Build Python bindings (from repository root)
41
- python3 setup.py install
42
-
43
- # Alternative: Install from PyPI
44
- pip install pyffish
45
- ```
46
-
47
- ### JavaScript Bindings (ffish.js)
48
- Also see the `tests/js/README.md`.
49
- ```bash
50
- cd src/
51
-
52
- # Build JavaScript bindings (requires emscripten)
53
- make -f Makefile_js build
54
-
55
- # Alternative: Install from npm
56
- npm install ffish
57
- ```
58
-
59
- ## Testing & Validation
60
-
61
- All test commands below assume the current directory is `src/`.
62
-
63
- ### Core Engine Tests
64
- ```bash
65
- # Basic functionality test
66
- ./stockfish bench
67
-
68
- # Variant-specific benchmarks
69
- ./stockfish bench xiangqi
70
- ./stockfish bench shogi
71
- ./stockfish bench capablanca
72
-
73
- # Validate variants configuration
74
- ./stockfish check variants.ini
75
- ```
76
-
77
- ### Comprehensive Test Suite
78
- ```bash
79
- # Protocol compliance tests
80
- ../tests/protocol.sh
81
-
82
- # Move generation validation
83
- ../tests/perft.sh all
84
- ../tests/perft.sh chess # Chess only
85
- ../tests/perft.sh largeboard # Large board variants only
86
-
87
- # Regression testing
88
- ../tests/regression.sh
89
-
90
- # Reproducible search test
91
- ../tests/reprosearch.sh
92
-
93
- # Build signature verification
94
- ../tests/signature.sh
95
- ```
96
-
97
-
98
- ## Project Architecture
99
-
100
- ### Directory Structure
101
- ```
102
- src/ # Core C++ engine source
103
- tests/ # Test scripts and data
104
- .github/workflows/ # CI/CD configurations
105
- ```
106
-
107
- ### Configuration Files
108
- - **`src/variants.ini`**: Defines examples for configuration of chess variants
109
- - **`setup.py`**: Python package build configuration
110
- - **`tests/js/package.json`**: JavaScript bindings configuration
111
-
112
- ### Key Source Files in `src/`
113
- - **`variant.h`**: Variant rule properties
114
- - **`variant.cpp`**: Variant-specific game rules
115
- - **`variant.ini`**: Variant rule configuration examples and documentation of variant properties
116
- - **`position.h`**: Position representation
117
- - **`position.cpp`**: Board logic
118
- - **`movegen.cpp`**: Move generation logic
119
- - **`parser.cpp`**: Variant rule configuration parsing
120
- - **`piece.cpp`**: Piece type definitions and behavior
121
- - **`pyffish.cpp`**: Python bindings
122
- - **`ffishjs.cpp`**: JavaScript bindings
123
-
124
- ## Continuous Integration
125
-
126
- ### GitHub Actions Workflows
127
- - **`fairy.yml`**: Core engine testing (perft, protocols, variants)
128
- - **`stockfish.yml`**: Standard Stockfish compatibility tests
129
- - **`release.yml`**: Binary releases for multiple platforms
130
- - **`wheels.yml`**: Python package builds
131
- - **`ffishjs.yml`**: JavaScript binding builds
132
-
133
- ## Common Development Patterns
134
-
135
- ### Making Engine Changes
136
- 1. **Always test basic functionality:** `./stockfish bench` after changes
137
- 2. **Validate variant compatibility:** `./stockfish check variants.ini`
138
- 3. **Run relevant tests:** `../tests/perft.sh all` for move generation changes
139
-
140
- ### Adding New Configurable Variants
141
- 1. **Edit `src/variants.ini`**: Add variant configuration
142
- 2. **Test parsing:** `./stockfish check variants.ini`
143
-
144
- ### Relevant websites for researching chess variant rules
145
- - [Chess Variants on Wikipedia](https://en.wikipedia.org/wiki/List_of_chess_variants)
146
- - [Chess Variants Wiki](https://www.chessvariants.com/)
147
- - [Variant Chess on BoardGameGeek](https://boardgamegeek.com/boardgamefamily/4024/traditional-games-chess)
148
- - [PyChess Variants](https://www.pychess.org/variants)
149
- - [Ludii](https://ludii.games/library.php)
150
- - [Lichess.org Variants](https://lichess.org/variant)
151
- - [Greenchess](https://greenchess.net/variants.php)
152
- - [Chess Variants on Chess.com](https://www.chess.com/variants)
153
-
154
- ### Development Best Practices
155
- * Make sure to only stage and commit changes that were changed as part of the task, do not simply add all changes.
156
- * Keep changes minimal and focused on the task at hand.
157
- * After applying changes make sure that all places related to the task have been identified.
158
- * Stay consistent with the existing code style and conventions.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/AUTHORS DELETED
@@ -1,231 +0,0 @@
1
- # Fairy-Stockfish authors
2
-
3
- # Main author
4
- Fabian Fichter (ianfab)
5
-
6
- # Contributors in alphabetical order
7
- alwey
8
- Belzedar94
9
- cloudfish
10
- CouchTomato87
11
- dpldgr
12
- Fulmene
13
- gbtami
14
- gnunicode
15
- johndoknjas
16
- kz04px
17
- majormink
18
- mtaktikos
19
- QueensGambit
20
- RainRat
21
- rkb97
22
- romstad
23
- Snowmoondaphne
24
- SriMethan
25
- thearst3rd
26
- TheYoBots
27
- tttak
28
- yjf2002ghty
29
- yoav-rozin
30
- ydirson
31
-
32
-
33
-
34
- # List of authors for Stockfish, as of June 14, 2021
35
-
36
- # Founders of the Stockfish project and fishtest infrastructure
37
- Tord Romstad (romstad)
38
- Marco Costalba (mcostalba)
39
- Joona Kiiski (zamar)
40
- Gary Linscott (glinscott)
41
-
42
- # Authors and inventors of NNUE, training, NNUE port
43
- Yu Nasu (ynasu87)
44
- Motohiro Isozaki (yaneurao)
45
- Hisayori Noda (nodchip)
46
-
47
- # all other authors of the code in alphabetical order
48
- Aditya (absimaldata)
49
- Adrian Petrescu (apetresc)
50
- Ajith Chandy Jose (ajithcj)
51
- Alain Savard (Rocky640)
52
- Alayan Feh (Alayan-stk-2)
53
- Alexander Kure
54
- Alexander Pagel (Lolligerhans)
55
- Alfredo Menezes (lonfom169)
56
- Ali AlZhrani (Cooffe)
57
- Andrew Grant (AndyGrant)
58
- Andrey Neporada (nepal)
59
- Andy Duplain
60
- Antoine Champion (antoinechampion)
61
- Aram Tumanian (atumanian)
62
- Arjun Temurnikar
63
- Artem Solopiy (EntityFX)
64
- Auguste Pop
65
- Balint Pfliegel
66
- Ben Koshy (BKSpurgeon)
67
- Bill Henry (VoyagerOne)
68
- Bojun Guo (noobpwnftw, Nooby)
69
- braich
70
- Brian Sheppard (SapphireBrand, briansheppard-toast)
71
- Bruno de Melo Costa (BM123499)
72
- Bryan Cross (crossbr)
73
- candirufish
74
- Chess13234
75
- Chris Cain (ceebo)
76
- Dale Weiler (graphitemaster)
77
- Dan Schmidt (dfannius)
78
- Daniel Axtens (daxtens)
79
- Daniel Dugovic (ddugovic)
80
- Dariusz Orzechowski (dorzechowski)
81
- David Zar
82
- Daylen Yang (daylen)
83
- Deshawn Mohan-Smith (GoldenRare)
84
- Dieter Dobbelaere (ddobbelaere)
85
- DiscanX
86
- Dominik Schlösser (domschl)
87
- double-beep
88
- Douglas Matos Gomes (dsmsgms)
89
- Eduardo Cáceres (eduherminio)
90
- Eelco de Groot (KingDefender)
91
- Elvin Liu (solarlight2)
92
- erbsenzaehler
93
- Ernesto Gatti
94
- Linmiao Xu (linrock)
95
- Fabian Beuke (madnight)
96
- Fabian Fichter (ianfab)
97
- Fanael Linithien (Fanael)
98
- fanon
99
- Fauzi Akram Dabat (FauziAkram)
100
- Felix Wittmann
101
- gamander
102
- Gary Heckman (gheckman)
103
- George Sobala (gsobala)
104
- gguliash
105
- Gian-Carlo Pascutto (gcp)
106
- Gontran Lemaire (gonlem)
107
- Goodkov Vasiliy Aleksandrovich (goodkov)
108
- Gregor Cramer
109
- GuardianRM
110
- Günther Demetz (pb00067, pb00068)
111
- Guy Vreuls (gvreuls)
112
- Henri Wiechers
113
- Hiraoka Takuya (HiraokaTakuya)
114
- homoSapiensSapiens
115
- Hongzhi Cheng
116
- Ivan Ivec (IIvec)
117
- Jacques B. (Timshel)
118
- Jan Ondruš (hxim)
119
- Jared Kish (Kurtbusch)
120
- Jarrod Torriero (DU-jdto)
121
- Jean Gauthier (OuaisBla)
122
- Jean-Francois Romang (jromang)
123
- Jekaa
124
- Jerry Donald Watson (jerrydonaldwatson)
125
- jjoshua2
126
- Jonathan Calovski (Mysseno)
127
- Jonathan Buladas Dumale (SFisGOD)
128
- Joost VandeVondele (vondele)
129
- Jörg Oster (joergoster)
130
- Joseph Ellis (jhellis3)
131
- Joseph R. Prostko
132
- Julian Willemer (NightlyKing)
133
- jundery
134
- Justin Blanchard (UncombedCoconut)
135
- Kelly Wilson
136
- Ken Takusagawa
137
- kinderchocolate
138
- Kiran Panditrao (Krgp)
139
- Kojirion
140
- Krystian Kuzniarek (kuzkry)
141
- Leonardo Ljubičić (ICCF World Champion)
142
- Leonid Pechenik (lp--)
143
- Linus Arver (listx)
144
- loco-loco
145
- Lub van den Berg (ElbertoOne)
146
- Luca Brivio (lucabrivio)
147
- Lucas Braesch (lucasart)
148
- Lyudmil Antonov (lantonov)
149
- Maciej Żenczykowski (zenczykowski)
150
- Malcolm Campbell (xoto10)
151
- Mark Tenzer (31m059)
152
- marotear
153
- Matt Ginsberg (mattginsberg)
154
- Matthew Lai (matthewlai)
155
- Matthew Sullivan (Matt14916)
156
- Maxim Molchanov (Maxim)
157
- Michael An (man)
158
- Michael Byrne (MichaelB7)
159
- Michael Chaly (Vizvezdenec)
160
- Michael Stembera (mstembera)
161
- Michael Whiteley (protonspring)
162
- Michel Van den Bergh (vdbergh)
163
- Miguel Lahoz (miguel-l)
164
- Mikael Bäckman (mbootsector)
165
- Mira
166
- Miroslav Fontán (Hexik)
167
- Moez Jellouli (MJZ1977)
168
- Mohammed Li (tthsqe12)
169
- Nathan Rugg (nmrugg)
170
- Nick Pelling (nickpelling)
171
- Nicklas Persson (NicklasPersson)
172
- Niklas Fiekas (niklasf)
173
- Nikolay Kostov (NikolayIT)
174
- Nguyen Pham (nguyenpham)
175
- Norman Schmidt (FireFather)
176
- notruck
177
- Ondrej Mosnáček (WOnder93)
178
- Oskar Werkelin Ahlin
179
- Pablo Vazquez
180
- Panthee
181
- Pascal Romaret
182
- Pasquale Pigazzini (ppigazzini)
183
- Patrick Jansen (mibere)
184
- pellanda
185
- Peter Zsifkovits (CoffeeOne)
186
- Praveen Kumar Tummala (praveentml)
187
- Rahul Dsilva (silversolver1)
188
- Ralph Stößer (Ralph Stoesser)
189
- Raminder Singh
190
- renouve
191
- Reuven Peleg
192
- Richard Lloyd
193
- Rodrigo Exterckötter Tjäder
194
- Ron Britvich (Britvich)
195
- Ronald de Man (syzygy1, syzygy)
196
- rqs
197
- Ryan Schmitt
198
- Ryan Takker
199
- Sami Kiminki (skiminki)
200
- Sebastian Buchwald (UniQP)
201
- Sergei Antonov (saproj)
202
- Sergei Ivanov (svivanov72)
203
- Sergio Vieri (sergiovieri)
204
- sf-x
205
- Shane Booth (shane31)
206
- Shawn Varghese (xXH4CKST3RXx)
207
- Siad Daboul (Topologist)
208
- Stefan Geschwentner (locutus2)
209
- Stefano Cardanobile (Stefano80)
210
- Steinar Gunderson (sesse)
211
- Stéphane Nicolet (snicolet)
212
- Prokop Randáček (ProkopRandacek)
213
- Thanar2
214
- thaspel
215
- theo77186
216
- Tom Truscott
217
- Tom Vijlbrief (tomtor)
218
- Tomasz Sobczyk (Sopel97)
219
- Torsten Franz (torfranz, tfranzer)
220
- Tracey Emery (basepr1me)
221
- tttak
222
- Unai Corzo (unaiic)
223
- Uri Blass (uriblass)
224
- Vince Negri (cuddlestmonkey)
225
- zz4032
226
-
227
-
228
- # Additionally, we acknowledge the authors and maintainers of fishtest,
229
- # an amazing and essential framework for the development of Stockfish!
230
- #
231
- # https://github.com/glinscott/fishtest/blob/master/AUTHORS
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/Copying.txt DELETED
@@ -1,674 +0,0 @@
1
- GNU GENERAL PUBLIC LICENSE
2
- Version 3, 29 June 2007
3
-
4
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5
- Everyone is permitted to copy and distribute verbatim copies
6
- of this license document, but changing it is not allowed.
7
-
8
- Preamble
9
-
10
- The GNU General Public License is a free, copyleft license for
11
- software and other kinds of works.
12
-
13
- The licenses for most software and other practical works are designed
14
- to take away your freedom to share and change the works. By contrast,
15
- the GNU General Public License is intended to guarantee your freedom to
16
- share and change all versions of a program--to make sure it remains free
17
- software for all its users. We, the Free Software Foundation, use the
18
- GNU General Public License for most of our software; it applies also to
19
- any other work released this way by its authors. You can apply it to
20
- your programs, too.
21
-
22
- When we speak of free software, we are referring to freedom, not
23
- price. Our General Public Licenses are designed to make sure that you
24
- have the freedom to distribute copies of free software (and charge for
25
- them if you wish), that you receive source code or can get it if you
26
- want it, that you can change the software or use pieces of it in new
27
- free programs, and that you know you can do these things.
28
-
29
- To protect your rights, we need to prevent others from denying you
30
- these rights or asking you to surrender the rights. Therefore, you have
31
- certain responsibilities if you distribute copies of the software, or if
32
- you modify it: responsibilities to respect the freedom of others.
33
-
34
- For example, if you distribute copies of such a program, whether
35
- gratis or for a fee, you must pass on to the recipients the same
36
- freedoms that you received. You must make sure that they, too, receive
37
- or can get the source code. And you must show them these terms so they
38
- know their rights.
39
-
40
- Developers that use the GNU GPL protect your rights with two steps:
41
- (1) assert copyright on the software, and (2) offer you this License
42
- giving you legal permission to copy, distribute and/or modify it.
43
-
44
- For the developers' and authors' protection, the GPL clearly explains
45
- that there is no warranty for this free software. For both users' and
46
- authors' sake, the GPL requires that modified versions be marked as
47
- changed, so that their problems will not be attributed erroneously to
48
- authors of previous versions.
49
-
50
- Some devices are designed to deny users access to install or run
51
- modified versions of the software inside them, although the manufacturer
52
- can do so. This is fundamentally incompatible with the aim of
53
- protecting users' freedom to change the software. The systematic
54
- pattern of such abuse occurs in the area of products for individuals to
55
- use, which is precisely where it is most unacceptable. Therefore, we
56
- have designed this version of the GPL to prohibit the practice for those
57
- products. If such problems arise substantially in other domains, we
58
- stand ready to extend this provision to those domains in future versions
59
- of the GPL, as needed to protect the freedom of users.
60
-
61
- Finally, every program is threatened constantly by software patents.
62
- States should not allow patents to restrict development and use of
63
- software on general-purpose computers, but in those that do, we wish to
64
- avoid the special danger that patents applied to a free program could
65
- make it effectively proprietary. To prevent this, the GPL assures that
66
- patents cannot be used to render the program non-free.
67
-
68
- The precise terms and conditions for copying, distribution and
69
- modification follow.
70
-
71
- TERMS AND CONDITIONS
72
-
73
- 0. Definitions.
74
-
75
- "This License" refers to version 3 of the GNU General Public License.
76
-
77
- "Copyright" also means copyright-like laws that apply to other kinds of
78
- works, such as semiconductor masks.
79
-
80
- "The Program" refers to any copyrightable work licensed under this
81
- License. Each licensee is addressed as "you". "Licensees" and
82
- "recipients" may be individuals or organizations.
83
-
84
- To "modify" a work means to copy from or adapt all or part of the work
85
- in a fashion requiring copyright permission, other than the making of an
86
- exact copy. The resulting work is called a "modified version" of the
87
- earlier work or a work "based on" the earlier work.
88
-
89
- A "covered work" means either the unmodified Program or a work based
90
- on the Program.
91
-
92
- To "propagate" a work means to do anything with it that, without
93
- permission, would make you directly or secondarily liable for
94
- infringement under applicable copyright law, except executing it on a
95
- computer or modifying a private copy. Propagation includes copying,
96
- distribution (with or without modification), making available to the
97
- public, and in some countries other activities as well.
98
-
99
- To "convey" a work means any kind of propagation that enables other
100
- parties to make or receive copies. Mere interaction with a user through
101
- a computer network, with no transfer of a copy, is not conveying.
102
-
103
- An interactive user interface displays "Appropriate Legal Notices"
104
- to the extent that it includes a convenient and prominently visible
105
- feature that (1) displays an appropriate copyright notice, and (2)
106
- tells the user that there is no warranty for the work (except to the
107
- extent that warranties are provided), that licensees may convey the
108
- work under this License, and how to view a copy of this License. If
109
- the interface presents a list of user commands or options, such as a
110
- menu, a prominent item in the list meets this criterion.
111
-
112
- 1. Source Code.
113
-
114
- The "source code" for a work means the preferred form of the work
115
- for making modifications to it. "Object code" means any non-source
116
- form of a work.
117
-
118
- A "Standard Interface" means an interface that either is an official
119
- standard defined by a recognized standards body, or, in the case of
120
- interfaces specified for a particular programming language, one that
121
- is widely used among developers working in that language.
122
-
123
- The "System Libraries" of an executable work include anything, other
124
- than the work as a whole, that (a) is included in the normal form of
125
- packaging a Major Component, but which is not part of that Major
126
- Component, and (b) serves only to enable use of the work with that
127
- Major Component, or to implement a Standard Interface for which an
128
- implementation is available to the public in source code form. A
129
- "Major Component", in this context, means a major essential component
130
- (kernel, window system, and so on) of the specific operating system
131
- (if any) on which the executable work runs, or a compiler used to
132
- produce the work, or an object code interpreter used to run it.
133
-
134
- The "Corresponding Source" for a work in object code form means all
135
- the source code needed to generate, install, and (for an executable
136
- work) run the object code and to modify the work, including scripts to
137
- control those activities. However, it does not include the work's
138
- System Libraries, or general-purpose tools or generally available free
139
- programs which are used unmodified in performing those activities but
140
- which are not part of the work. For example, Corresponding Source
141
- includes interface definition files associated with source files for
142
- the work, and the source code for shared libraries and dynamically
143
- linked subprograms that the work is specifically designed to require,
144
- such as by intimate data communication or control flow between those
145
- subprograms and other parts of the work.
146
-
147
- The Corresponding Source need not include anything that users
148
- can regenerate automatically from other parts of the Corresponding
149
- Source.
150
-
151
- The Corresponding Source for a work in source code form is that
152
- same work.
153
-
154
- 2. Basic Permissions.
155
-
156
- All rights granted under this License are granted for the term of
157
- copyright on the Program, and are irrevocable provided the stated
158
- conditions are met. This License explicitly affirms your unlimited
159
- permission to run the unmodified Program. The output from running a
160
- covered work is covered by this License only if the output, given its
161
- content, constitutes a covered work. This License acknowledges your
162
- rights of fair use or other equivalent, as provided by copyright law.
163
-
164
- You may make, run and propagate covered works that you do not
165
- convey, without conditions so long as your license otherwise remains
166
- in force. You may convey covered works to others for the sole purpose
167
- of having them make modifications exclusively for you, or provide you
168
- with facilities for running those works, provided that you comply with
169
- the terms of this License in conveying all material for which you do
170
- not control copyright. Those thus making or running the covered works
171
- for you must do so exclusively on your behalf, under your direction
172
- and control, on terms that prohibit them from making any copies of
173
- your copyrighted material outside their relationship with you.
174
-
175
- Conveying under any other circumstances is permitted solely under
176
- the conditions stated below. Sublicensing is not allowed; section 10
177
- makes it unnecessary.
178
-
179
- 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180
-
181
- No covered work shall be deemed part of an effective technological
182
- measure under any applicable law fulfilling obligations under article
183
- 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184
- similar laws prohibiting or restricting circumvention of such
185
- measures.
186
-
187
- When you convey a covered work, you waive any legal power to forbid
188
- circumvention of technological measures to the extent such circumvention
189
- is effected by exercising rights under this License with respect to
190
- the covered work, and you disclaim any intention to limit operation or
191
- modification of the work as a means of enforcing, against the work's
192
- users, your or third parties' legal rights to forbid circumvention of
193
- technological measures.
194
-
195
- 4. Conveying Verbatim Copies.
196
-
197
- You may convey verbatim copies of the Program's source code as you
198
- receive it, in any medium, provided that you conspicuously and
199
- appropriately publish on each copy an appropriate copyright notice;
200
- keep intact all notices stating that this License and any
201
- non-permissive terms added in accord with section 7 apply to the code;
202
- keep intact all notices of the absence of any warranty; and give all
203
- recipients a copy of this License along with the Program.
204
-
205
- You may charge any price or no price for each copy that you convey,
206
- and you may offer support or warranty protection for a fee.
207
-
208
- 5. Conveying Modified Source Versions.
209
-
210
- You may convey a work based on the Program, or the modifications to
211
- produce it from the Program, in the form of source code under the
212
- terms of section 4, provided that you also meet all of these conditions:
213
-
214
- a) The work must carry prominent notices stating that you modified
215
- it, and giving a relevant date.
216
-
217
- b) The work must carry prominent notices stating that it is
218
- released under this License and any conditions added under section
219
- 7. This requirement modifies the requirement in section 4 to
220
- "keep intact all notices".
221
-
222
- c) You must license the entire work, as a whole, under this
223
- License to anyone who comes into possession of a copy. This
224
- License will therefore apply, along with any applicable section 7
225
- additional terms, to the whole of the work, and all its parts,
226
- regardless of how they are packaged. This License gives no
227
- permission to license the work in any other way, but it does not
228
- invalidate such permission if you have separately received it.
229
-
230
- d) If the work has interactive user interfaces, each must display
231
- Appropriate Legal Notices; however, if the Program has interactive
232
- interfaces that do not display Appropriate Legal Notices, your
233
- work need not make them do so.
234
-
235
- A compilation of a covered work with other separate and independent
236
- works, which are not by their nature extensions of the covered work,
237
- and which are not combined with it such as to form a larger program,
238
- in or on a volume of a storage or distribution medium, is called an
239
- "aggregate" if the compilation and its resulting copyright are not
240
- used to limit the access or legal rights of the compilation's users
241
- beyond what the individual works permit. Inclusion of a covered work
242
- in an aggregate does not cause this License to apply to the other
243
- parts of the aggregate.
244
-
245
- 6. Conveying Non-Source Forms.
246
-
247
- You may convey a covered work in object code form under the terms
248
- of sections 4 and 5, provided that you also convey the
249
- machine-readable Corresponding Source under the terms of this License,
250
- in one of these ways:
251
-
252
- a) Convey the object code in, or embodied in, a physical product
253
- (including a physical distribution medium), accompanied by the
254
- Corresponding Source fixed on a durable physical medium
255
- customarily used for software interchange.
256
-
257
- b) Convey the object code in, or embodied in, a physical product
258
- (including a physical distribution medium), accompanied by a
259
- written offer, valid for at least three years and valid for as
260
- long as you offer spare parts or customer support for that product
261
- model, to give anyone who possesses the object code either (1) a
262
- copy of the Corresponding Source for all the software in the
263
- product that is covered by this License, on a durable physical
264
- medium customarily used for software interchange, for a price no
265
- more than your reasonable cost of physically performing this
266
- conveying of source, or (2) access to copy the
267
- Corresponding Source from a network server at no charge.
268
-
269
- c) Convey individual copies of the object code with a copy of the
270
- written offer to provide the Corresponding Source. This
271
- alternative is allowed only occasionally and noncommercially, and
272
- only if you received the object code with such an offer, in accord
273
- with subsection 6b.
274
-
275
- d) Convey the object code by offering access from a designated
276
- place (gratis or for a charge), and offer equivalent access to the
277
- Corresponding Source in the same way through the same place at no
278
- further charge. You need not require recipients to copy the
279
- Corresponding Source along with the object code. If the place to
280
- copy the object code is a network server, the Corresponding Source
281
- may be on a different server (operated by you or a third party)
282
- that supports equivalent copying facilities, provided you maintain
283
- clear directions next to the object code saying where to find the
284
- Corresponding Source. Regardless of what server hosts the
285
- Corresponding Source, you remain obligated to ensure that it is
286
- available for as long as needed to satisfy these requirements.
287
-
288
- e) Convey the object code using peer-to-peer transmission, provided
289
- you inform other peers where the object code and Corresponding
290
- Source of the work are being offered to the general public at no
291
- charge under subsection 6d.
292
-
293
- A separable portion of the object code, whose source code is excluded
294
- from the Corresponding Source as a System Library, need not be
295
- included in conveying the object code work.
296
-
297
- A "User Product" is either (1) a "consumer product", which means any
298
- tangible personal property which is normally used for personal, family,
299
- or household purposes, or (2) anything designed or sold for incorporation
300
- into a dwelling. In determining whether a product is a consumer product,
301
- doubtful cases shall be resolved in favor of coverage. For a particular
302
- product received by a particular user, "normally used" refers to a
303
- typical or common use of that class of product, regardless of the status
304
- of the particular user or of the way in which the particular user
305
- actually uses, or expects or is expected to use, the product. A product
306
- is a consumer product regardless of whether the product has substantial
307
- commercial, industrial or non-consumer uses, unless such uses represent
308
- the only significant mode of use of the product.
309
-
310
- "Installation Information" for a User Product means any methods,
311
- procedures, authorization keys, or other information required to install
312
- and execute modified versions of a covered work in that User Product from
313
- a modified version of its Corresponding Source. The information must
314
- suffice to ensure that the continued functioning of the modified object
315
- code is in no case prevented or interfered with solely because
316
- modification has been made.
317
-
318
- If you convey an object code work under this section in, or with, or
319
- specifically for use in, a User Product, and the conveying occurs as
320
- part of a transaction in which the right of possession and use of the
321
- User Product is transferred to the recipient in perpetuity or for a
322
- fixed term (regardless of how the transaction is characterized), the
323
- Corresponding Source conveyed under this section must be accompanied
324
- by the Installation Information. But this requirement does not apply
325
- if neither you nor any third party retains the ability to install
326
- modified object code on the User Product (for example, the work has
327
- been installed in ROM).
328
-
329
- The requirement to provide Installation Information does not include a
330
- requirement to continue to provide support service, warranty, or updates
331
- for a work that has been modified or installed by the recipient, or for
332
- the User Product in which it has been modified or installed. Access to a
333
- network may be denied when the modification itself materially and
334
- adversely affects the operation of the network or violates the rules and
335
- protocols for communication across the network.
336
-
337
- Corresponding Source conveyed, and Installation Information provided,
338
- in accord with this section must be in a format that is publicly
339
- documented (and with an implementation available to the public in
340
- source code form), and must require no special password or key for
341
- unpacking, reading or copying.
342
-
343
- 7. Additional Terms.
344
-
345
- "Additional permissions" are terms that supplement the terms of this
346
- License by making exceptions from one or more of its conditions.
347
- Additional permissions that are applicable to the entire Program shall
348
- be treated as though they were included in this License, to the extent
349
- that they are valid under applicable law. If additional permissions
350
- apply only to part of the Program, that part may be used separately
351
- under those permissions, but the entire Program remains governed by
352
- this License without regard to the additional permissions.
353
-
354
- When you convey a copy of a covered work, you may at your option
355
- remove any additional permissions from that copy, or from any part of
356
- it. (Additional permissions may be written to require their own
357
- removal in certain cases when you modify the work.) You may place
358
- additional permissions on material, added by you to a covered work,
359
- for which you have or can give appropriate copyright permission.
360
-
361
- Notwithstanding any other provision of this License, for material you
362
- add to a covered work, you may (if authorized by the copyright holders of
363
- that material) supplement the terms of this License with terms:
364
-
365
- a) Disclaiming warranty or limiting liability differently from the
366
- terms of sections 15 and 16 of this License; or
367
-
368
- b) Requiring preservation of specified reasonable legal notices or
369
- author attributions in that material or in the Appropriate Legal
370
- Notices displayed by works containing it; or
371
-
372
- c) Prohibiting misrepresentation of the origin of that material, or
373
- requiring that modified versions of such material be marked in
374
- reasonable ways as different from the original version; or
375
-
376
- d) Limiting the use for publicity purposes of names of licensors or
377
- authors of the material; or
378
-
379
- e) Declining to grant rights under trademark law for use of some
380
- trade names, trademarks, or service marks; or
381
-
382
- f) Requiring indemnification of licensors and authors of that
383
- material by anyone who conveys the material (or modified versions of
384
- it) with contractual assumptions of liability to the recipient, for
385
- any liability that these contractual assumptions directly impose on
386
- those licensors and authors.
387
-
388
- All other non-permissive additional terms are considered "further
389
- restrictions" within the meaning of section 10. If the Program as you
390
- received it, or any part of it, contains a notice stating that it is
391
- governed by this License along with a term that is a further
392
- restriction, you may remove that term. If a license document contains
393
- a further restriction but permits relicensing or conveying under this
394
- License, you may add to a covered work material governed by the terms
395
- of that license document, provided that the further restriction does
396
- not survive such relicensing or conveying.
397
-
398
- If you add terms to a covered work in accord with this section, you
399
- must place, in the relevant source files, a statement of the
400
- additional terms that apply to those files, or a notice indicating
401
- where to find the applicable terms.
402
-
403
- Additional terms, permissive or non-permissive, may be stated in the
404
- form of a separately written license, or stated as exceptions;
405
- the above requirements apply either way.
406
-
407
- 8. Termination.
408
-
409
- You may not propagate or modify a covered work except as expressly
410
- provided under this License. Any attempt otherwise to propagate or
411
- modify it is void, and will automatically terminate your rights under
412
- this License (including any patent licenses granted under the third
413
- paragraph of section 11).
414
-
415
- However, if you cease all violation of this License, then your
416
- license from a particular copyright holder is reinstated (a)
417
- provisionally, unless and until the copyright holder explicitly and
418
- finally terminates your license, and (b) permanently, if the copyright
419
- holder fails to notify you of the violation by some reasonable means
420
- prior to 60 days after the cessation.
421
-
422
- Moreover, your license from a particular copyright holder is
423
- reinstated permanently if the copyright holder notifies you of the
424
- violation by some reasonable means, this is the first time you have
425
- received notice of violation of this License (for any work) from that
426
- copyright holder, and you cure the violation prior to 30 days after
427
- your receipt of the notice.
428
-
429
- Termination of your rights under this section does not terminate the
430
- licenses of parties who have received copies or rights from you under
431
- this License. If your rights have been terminated and not permanently
432
- reinstated, you do not qualify to receive new licenses for the same
433
- material under section 10.
434
-
435
- 9. Acceptance Not Required for Having Copies.
436
-
437
- You are not required to accept this License in order to receive or
438
- run a copy of the Program. Ancillary propagation of a covered work
439
- occurring solely as a consequence of using peer-to-peer transmission
440
- to receive a copy likewise does not require acceptance. However,
441
- nothing other than this License grants you permission to propagate or
442
- modify any covered work. These actions infringe copyright if you do
443
- not accept this License. Therefore, by modifying or propagating a
444
- covered work, you indicate your acceptance of this License to do so.
445
-
446
- 10. Automatic Licensing of Downstream Recipients.
447
-
448
- Each time you convey a covered work, the recipient automatically
449
- receives a license from the original licensors, to run, modify and
450
- propagate that work, subject to this License. You are not responsible
451
- for enforcing compliance by third parties with this License.
452
-
453
- An "entity transaction" is a transaction transferring control of an
454
- organization, or substantially all assets of one, or subdividing an
455
- organization, or merging organizations. If propagation of a covered
456
- work results from an entity transaction, each party to that
457
- transaction who receives a copy of the work also receives whatever
458
- licenses to the work the party's predecessor in interest had or could
459
- give under the previous paragraph, plus a right to possession of the
460
- Corresponding Source of the work from the predecessor in interest, if
461
- the predecessor has it or can get it with reasonable efforts.
462
-
463
- You may not impose any further restrictions on the exercise of the
464
- rights granted or affirmed under this License. For example, you may
465
- not impose a license fee, royalty, or other charge for exercise of
466
- rights granted under this License, and you may not initiate litigation
467
- (including a cross-claim or counterclaim in a lawsuit) alleging that
468
- any patent claim is infringed by making, using, selling, offering for
469
- sale, or importing the Program or any portion of it.
470
-
471
- 11. Patents.
472
-
473
- A "contributor" is a copyright holder who authorizes use under this
474
- License of the Program or a work on which the Program is based. The
475
- work thus licensed is called the contributor's "contributor version".
476
-
477
- A contributor's "essential patent claims" are all patent claims
478
- owned or controlled by the contributor, whether already acquired or
479
- hereafter acquired, that would be infringed by some manner, permitted
480
- by this License, of making, using, or selling its contributor version,
481
- but do not include claims that would be infringed only as a
482
- consequence of further modification of the contributor version. For
483
- purposes of this definition, "control" includes the right to grant
484
- patent sublicenses in a manner consistent with the requirements of
485
- this License.
486
-
487
- Each contributor grants you a non-exclusive, worldwide, royalty-free
488
- patent license under the contributor's essential patent claims, to
489
- make, use, sell, offer for sale, import and otherwise run, modify and
490
- propagate the contents of its contributor version.
491
-
492
- In the following three paragraphs, a "patent license" is any express
493
- agreement or commitment, however denominated, not to enforce a patent
494
- (such as an express permission to practice a patent or covenant not to
495
- sue for patent infringement). To "grant" such a patent license to a
496
- party means to make such an agreement or commitment not to enforce a
497
- patent against the party.
498
-
499
- If you convey a covered work, knowingly relying on a patent license,
500
- and the Corresponding Source of the work is not available for anyone
501
- to copy, free of charge and under the terms of this License, through a
502
- publicly available network server or other readily accessible means,
503
- then you must either (1) cause the Corresponding Source to be so
504
- available, or (2) arrange to deprive yourself of the benefit of the
505
- patent license for this particular work, or (3) arrange, in a manner
506
- consistent with the requirements of this License, to extend the patent
507
- license to downstream recipients. "Knowingly relying" means you have
508
- actual knowledge that, but for the patent license, your conveying the
509
- covered work in a country, or your recipient's use of the covered work
510
- in a country, would infringe one or more identifiable patents in that
511
- country that you have reason to believe are valid.
512
-
513
- If, pursuant to or in connection with a single transaction or
514
- arrangement, you convey, or propagate by procuring conveyance of, a
515
- covered work, and grant a patent license to some of the parties
516
- receiving the covered work authorizing them to use, propagate, modify
517
- or convey a specific copy of the covered work, then the patent license
518
- you grant is automatically extended to all recipients of the covered
519
- work and works based on it.
520
-
521
- A patent license is "discriminatory" if it does not include within
522
- the scope of its coverage, prohibits the exercise of, or is
523
- conditioned on the non-exercise of one or more of the rights that are
524
- specifically granted under this License. You may not convey a covered
525
- work if you are a party to an arrangement with a third party that is
526
- in the business of distributing software, under which you make payment
527
- to the third party based on the extent of your activity of conveying
528
- the work, and under which the third party grants, to any of the
529
- parties who would receive the covered work from you, a discriminatory
530
- patent license (a) in connection with copies of the covered work
531
- conveyed by you (or copies made from those copies), or (b) primarily
532
- for and in connection with specific products or compilations that
533
- contain the covered work, unless you entered into that arrangement,
534
- or that patent license was granted, prior to 28 March 2007.
535
-
536
- Nothing in this License shall be construed as excluding or limiting
537
- any implied license or other defenses to infringement that may
538
- otherwise be available to you under applicable patent law.
539
-
540
- 12. No Surrender of Others' Freedom.
541
-
542
- If conditions are imposed on you (whether by court order, agreement or
543
- otherwise) that contradict the conditions of this License, they do not
544
- excuse you from the conditions of this License. If you cannot convey a
545
- covered work so as to satisfy simultaneously your obligations under this
546
- License and any other pertinent obligations, then as a consequence you may
547
- not convey it at all. For example, if you agree to terms that obligate you
548
- to collect a royalty for further conveying from those to whom you convey
549
- the Program, the only way you could satisfy both those terms and this
550
- License would be to refrain entirely from conveying the Program.
551
-
552
- 13. Use with the GNU Affero General Public License.
553
-
554
- Notwithstanding any other provision of this License, you have
555
- permission to link or combine any covered work with a work licensed
556
- under version 3 of the GNU Affero General Public License into a single
557
- combined work, and to convey the resulting work. The terms of this
558
- License will continue to apply to the part which is the covered work,
559
- but the special requirements of the GNU Affero General Public License,
560
- section 13, concerning interaction through a network will apply to the
561
- combination as such.
562
-
563
- 14. Revised Versions of this License.
564
-
565
- The Free Software Foundation may publish revised and/or new versions of
566
- the GNU General Public License from time to time. Such new versions will
567
- be similar in spirit to the present version, but may differ in detail to
568
- address new problems or concerns.
569
-
570
- Each version is given a distinguishing version number. If the
571
- Program specifies that a certain numbered version of the GNU General
572
- Public License "or any later version" applies to it, you have the
573
- option of following the terms and conditions either of that numbered
574
- version or of any later version published by the Free Software
575
- Foundation. If the Program does not specify a version number of the
576
- GNU General Public License, you may choose any version ever published
577
- by the Free Software Foundation.
578
-
579
- If the Program specifies that a proxy can decide which future
580
- versions of the GNU General Public License can be used, that proxy's
581
- public statement of acceptance of a version permanently authorizes you
582
- to choose that version for the Program.
583
-
584
- Later license versions may give you additional or different
585
- permissions. However, no additional obligations are imposed on any
586
- author or copyright holder as a result of your choosing to follow a
587
- later version.
588
-
589
- 15. Disclaimer of Warranty.
590
-
591
- THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592
- APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593
- HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594
- OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595
- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596
- PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597
- IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598
- ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599
-
600
- 16. Limitation of Liability.
601
-
602
- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603
- WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604
- THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605
- GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606
- USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607
- DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608
- PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609
- EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610
- SUCH DAMAGES.
611
-
612
- 17. Interpretation of Sections 15 and 16.
613
-
614
- If the disclaimer of warranty and limitation of liability provided
615
- above cannot be given local legal effect according to their terms,
616
- reviewing courts shall apply local law that most closely approximates
617
- an absolute waiver of all civil liability in connection with the
618
- Program, unless a warranty or assumption of liability accompanies a
619
- copy of the Program in return for a fee.
620
-
621
- END OF TERMS AND CONDITIONS
622
-
623
- How to Apply These Terms to Your New Programs
624
-
625
- If you develop a new program, and you want it to be of the greatest
626
- possible use to the public, the best way to achieve this is to make it
627
- free software which everyone can redistribute and change under these terms.
628
-
629
- To do so, attach the following notices to the program. It is safest
630
- to attach them to the start of each source file to most effectively
631
- state the exclusion of warranty; and each file should have at least
632
- the "copyright" line and a pointer to where the full notice is found.
633
-
634
- <one line to give the program's name and a brief idea of what it does.>
635
- Copyright (C) <year> <name of author>
636
-
637
- This program is free software: you can redistribute it and/or modify
638
- it under the terms of the GNU General Public License as published by
639
- the Free Software Foundation, either version 3 of the License, or
640
- (at your option) any later version.
641
-
642
- This program is distributed in the hope that it will be useful,
643
- but WITHOUT ANY WARRANTY; without even the implied warranty of
644
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645
- GNU General Public License for more details.
646
-
647
- You should have received a copy of the GNU General Public License
648
- along with this program. If not, see <http://www.gnu.org/licenses/>.
649
-
650
- Also add information on how to contact you by electronic and paper mail.
651
-
652
- If the program does terminal interaction, make it output a short
653
- notice like this when it starts in an interactive mode:
654
-
655
- <program> Copyright (C) <year> <name of author>
656
- This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657
- This is free software, and you are welcome to redistribute it
658
- under certain conditions; type `show c' for details.
659
-
660
- The hypothetical commands `show w' and `show c' should show the appropriate
661
- parts of the General Public License. Of course, your program's commands
662
- might be different; for a GUI interface, you would use an "about box".
663
-
664
- You should also get your employer (if you work as a programmer) or school,
665
- if any, to sign a "copyright disclaimer" for the program, if necessary.
666
- For more information on this, and how to apply and follow the GNU GPL, see
667
- <http://www.gnu.org/licenses/>.
668
-
669
- The GNU General Public License does not permit incorporating your program
670
- into proprietary programs. If your program is a subroutine library, you
671
- may consider it more useful to permit linking proprietary applications with
672
- the library. If this is what you want to do, use the GNU Lesser General
673
- Public License instead of this License. But first, please read
674
- <http://www.gnu.org/philosophy/why-not-lgpl.html>.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/MANIFEST.in DELETED
@@ -1,2 +0,0 @@
1
- include AUTHORS Copying.txt Readme.md test.py
2
- recursive-include src *.h *.cpp
 
 
 
Fairy-Stockfish-master/README.md DELETED
@@ -1,126 +0,0 @@
1
- # Fairy-Stockfish
2
-
3
- ## Overview
4
-
5
- [![Build Status](https://github.com/fairy-stockfish/Fairy-Stockfish/actions/workflows/release.yml/badge.svg?branch=master)](https://github.com/fairy-stockfish/Fairy-Stockfish/actions?query=workflow%3ARelease)
6
- [![Build Status](https://github.com/fairy-stockfish/Fairy-Stockfish/actions/workflows/fairy.yml/badge.svg?branch=master)](https://github.com/fairy-stockfish/Fairy-Stockfish/actions?query=workflow%3Afairy)
7
- [![Build Status](https://ci.appveyor.com/api/projects/status/github/fairy-stockfish/Fairy-Stockfish?branch=master&svg=true)](https://ci.appveyor.com/project/ianfab/Fairy-Stockfish/branch/master)
8
- [![PyPI version](https://badge.fury.io/py/pyffish.svg)](https://badge.fury.io/py/pyffish)
9
- [![NPM version](https://img.shields.io/npm/v/ffish.svg?sanitize=true)](https://www.npmjs.com/package/ffish)
10
-
11
- 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.
12
-
13
- 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.
14
-
15
- ## Installation
16
- 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.
17
-
18
- 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.
19
-
20
- 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).
21
- 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.
22
-
23
- ## Contributing
24
-
25
- 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.
26
-
27
- ## Supported games
28
-
29
- 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).
30
-
31
- ### Regional and historical games
32
- - [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)
33
- - [Shogi](https://en.wikipedia.org/wiki/Shogi), [Shogi variants](https://github.com/fairy-stockfish/Fairy-Stockfish#shogi-variants)
34
- - [Janggi](https://en.wikipedia.org/wiki/Janggi)
35
- - [Makruk](https://en.wikipedia.org/wiki/Makruk), [ASEAN](http://hgm.nubati.net/rules/ASEAN.html), Makpong, Ai-Wok
36
- - [Ouk Chatrang](https://en.wikipedia.org/wiki/Makruk#Cambodian_chess), [Kar Ouk](https://en.wikipedia.org/wiki/Makruk#Cambodian_chess)
37
- - [Sittuyin](https://en.wikipedia.org/wiki/Sittuyin)
38
- - [Shatar](https://en.wikipedia.org/wiki/Shatar), [Jeson Mor](https://en.wikipedia.org/wiki/Jeson_Mor)
39
- - [Shatranj](https://en.wikipedia.org/wiki/Shatranj), [Courier](https://en.wikipedia.org/wiki/Courier_chess)
40
- - [Raazuvaa](https://www.reddit.com/r/chess/comments/sj7y3n/raazuvaa_the_chess_of_the_maldives)
41
-
42
- ### Chess variants
43
- - [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)
44
- - [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)
45
- - [Chess960](https://en.wikipedia.org/wiki/Chess960), [Placement/Pre-Chess](https://www.chessvariants.com/link/placement-chess)
46
- - [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
47
- - [Bughouse](https://en.wikipedia.org/wiki/Bughouse_chess), [Koedem](http://schachclub-oetigheim.de/wp-content/uploads/2016/04/Koedem-rules.pdf)
48
- - [Seirawan](https://en.wikipedia.org/wiki/Seirawan_chess), Seirawan-Crazyhouse, [Dragon Chess](https://www.edami.com/dragonchess/)
49
- - [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)
50
- - [Hoppel-Poppel](http://www.chessvariants.com/diffmove.dir/hoppel-poppel.html), New Zealand
51
- - [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)
52
- - [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)
53
- - [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)
54
- - [Three-check](https://en.wikipedia.org/wiki/Three-check_chess), Five-check
55
- - [Los Alamos](https://en.wikipedia.org/wiki/Los_Alamos_chess), [Gardner's Minichess](https://en.wikipedia.org/wiki/Minichess#5%C3%975_chess)
56
- - [Atomic](https://en.wikipedia.org/wiki/Atomic_chess)
57
- - [Horde](https://en.wikipedia.org/wiki/Dunsany%27s_Chess#Horde_Chess), [Maharajah and the Sepoys](https://en.wikipedia.org/wiki/Maharajah_and_the_Sepoys)
58
- - [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)
59
- - [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)
60
- - [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)
61
- - [Spartan Chess](https://www.chessvariants.com/rules/spartan-chess)
62
- - [Wolf Chess](https://en.wikipedia.org/wiki/Wolf_chess)
63
- - [Troitzky Chess](https://www.chessvariants.com/play/troitzky-chess)
64
-
65
- ### Shogi variants
66
- - [Minishogi](https://en.wikipedia.org/wiki/Minishogi), [EuroShogi](https://en.wikipedia.org/wiki/EuroShogi), [Judkins shogi](https://en.wikipedia.org/wiki/Judkins_shogi)
67
- - [Kyoto shogi](https://en.wikipedia.org/wiki/Kyoto_shogi), [Microshogi](https://en.wikipedia.org/wiki/Micro_shogi)
68
- - [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)
69
- - [Tori shogi](https://en.wikipedia.org/wiki/Tori_shogi)
70
- - [Yari shogi](https://en.wikipedia.org/wiki/Yari_shogi)
71
- - [Okisaki shogi](https://en.wikipedia.org/wiki/Okisaki_shogi)
72
- - [Sho shogi](https://en.wikipedia.org/wiki/Sho_shogi)
73
-
74
- ### Related games
75
- - [Amazons](https://en.wikipedia.org/wiki/Game_of_the_Amazons)
76
- - [Ataxx](https://en.wikipedia.org/wiki/Ataxx)
77
- - [Breakthrough](https://en.wikipedia.org/wiki/Breakthrough_(board_game))
78
- - [Clobber](https://en.wikipedia.org/wiki/Clobber)
79
- - [Cfour](https://en.wikipedia.org/wiki/Connect_Four), [Tic-tac-toe](https://en.wikipedia.org/wiki/Tic-tac-toe)
80
- - [Five Field Kono](https://en.wikipedia.org/wiki/Five_Field_Kono)
81
- - [Flipersi](https://en.wikipedia.org/wiki/Reversi), [Flipello](https://en.wikipedia.org/wiki/Reversi#Othello)
82
- - [Fox and Hounds](https://boardgamegeek.com/boardgame/148180/fox-and-hounds)
83
- - [Isolation](https://boardgamegeek.com/boardgame/1875/isolation)
84
- - [Joust](https://www.chessvariants.com/programs.dir/joust.html)
85
- - [Snailtrail](https://boardgamegeek.com/boardgame/37135/snailtrail)
86
-
87
-
88
- ## Help
89
-
90
- 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).
91
-
92
- ## Bindings
93
-
94
- 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.
95
-
96
- ### Python
97
-
98
- 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).
99
-
100
- ### Javascript
101
-
102
- 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).
103
-
104
- ## Ports
105
-
106
- ### WebAssembly
107
-
108
- 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/.
109
-
110
- ## Terms of use
111
-
112
- Fairy-Stockfish is free, and distributed under the **GNU General Public License version 3**
113
- (GPL v3). Essentially, this means you are free to do almost exactly
114
- what you want with the program, including distributing it among your
115
- friends, making it available for download from your website, selling
116
- it (either by itself or as part of some bigger software package), or
117
- using it as the starting point for a software project of your own.
118
-
119
- The only real limitation is that whenever you distribute Fairy-Stockfish in
120
- some way, you MUST always include the full source code, or a pointer
121
- to where the source code can be found, to generate the exact binary
122
- you are distributing. If you make any changes to the source code,
123
- these changes must also be made available under the GPL.
124
-
125
- For full details, read the copy of the GPL v3 found in the file named
126
- [*Copying.txt*](https://github.com/fairy-stockfish/Fairy-Stockfish/blob/master/Copying.txt).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/Top CPU Contributors.txt DELETED
@@ -1,205 +0,0 @@
1
- Contributors to Fishtest with >10,000 CPU hours, as of Jun 29, 2021.
2
- Thank you!
3
-
4
- Username CPU Hours Games played
5
- -----------------------------------------------------
6
- noobpwnftw 27649494 1834734733
7
- mlang 1426107 89454622
8
- dew 1380910 82831648
9
- mibere 703840 46867607
10
- grandphish2 692707 41737913
11
- tvijlbrief 669642 42371594
12
- JojoM 597778 35297180
13
- TueRens 519226 31823562
14
- cw 458421 30307421
15
- fastgm 439667 25950040
16
- gvreuls 436599 28177460
17
- crunchy 427035 27344275
18
- CSU_Dynasty 374765 25106278
19
- Fisherman 326901 21822979
20
- ctoks 325477 21767943
21
- velislav 295343 18844324
22
- linrock 292789 10624427
23
- bcross 278584 19488961
24
- okrout 262818 13803272
25
- pemo 245982 11376085
26
- glinscott 217799 13780820
27
- leszek 212346 12959025
28
- nordlandia 211692 13484886
29
- bking_US 198894 11876016
30
- drabel 196463 13450602
31
- robal 195473 12375650
32
- mgrabiak 187226 12016564
33
- Dantist 183202 10990484
34
- Thanar 179852 12365359
35
- vdv 175274 9889046
36
- spams 157128 10319326
37
- marrco 150295 9402141
38
- sqrt2 147963 9724586
39
- mhoram 141278 8901241
40
- CoffeeOne 137100 5024116
41
- vdbergh 137041 8926915
42
- malala 136182 8002293
43
- xoto 133702 9156676
44
- davar 122092 7960001
45
- dsmith 122059 7570238
46
- Data 113305 8220352
47
- BrunoBanani 112960 7436849
48
- MaZePallas 102823 6633619
49
- sterni1971 100532 5880772
50
- ElbertoOne 99028 7023771
51
- brabos 92118 6186135
52
- oz 92100 6486640
53
- psk 89957 5984901
54
- amicic 89156 5392305
55
- sunu 88851 6028873
56
- Vizvezdenec 83761 5344740
57
- 0x3C33 82614 5271253
58
- BRAVONE 81239 5054681
59
- racerschmacer 80899 5759262
60
- cuistot 80300 4606144
61
- nssy 76497 5259388
62
- teddybaer 75125 5407666
63
- Pking_cda 73776 5293873
64
- jromang 72192 5057715
65
- solarlight 70517 5028306
66
- dv8silencer 70287 3883992
67
- Bobo1239 68515 4652287
68
- manap 66273 4121774
69
- skiminki 65088 4023328
70
- tinker 64333 4268790
71
- sschnee 60767 3500800
72
- qurashee 57344 3168264
73
- robnjr 57262 4053117
74
- Freja 56938 3733019
75
- ttruscott 56010 3680085
76
- rkl 55132 4164467
77
- renouve 53811 3501516
78
- finfish 51360 3370515
79
- eva42 51272 3599691
80
- rap 49985 3219146
81
- pb00067 49727 3298270
82
- ronaldjerum 47654 3240695
83
- bigpen0r 47653 3335327
84
- eastorwest 47585 3221629
85
- biffhero 46564 3111352
86
- VoyagerOne 45476 3452465
87
- yurikvelo 44834 3034550
88
- speedycpu 43842 3003273
89
- jbwiebe 43305 2805433
90
- Spprtr 42279 2680153
91
- DesolatedDodo 42007 2447516
92
- Antihistamine 41788 2761312
93
- mhunt 41735 2691355
94
- homyur 39893 2850481
95
- gri 39871 2515779
96
- Fifis 38776 2529121
97
- oryx 38724 2966648
98
- SC 37290 2731014
99
- csnodgrass 36207 2688994
100
- jmdana 36157 2210661
101
- strelock 34716 2074055
102
- rpngn 33951 2057395
103
- Garf 33922 2751802
104
- EthanOConnor 33370 2090311
105
- slakovv 32915 2021889
106
- manapbk 30987 1810399
107
- Prcuvu 30377 2170122
108
- anst 30301 2190091
109
- jkiiski 30136 1904470
110
- hyperbolic.tom 29840 2017394
111
- Pyafue 29650 1902349
112
- Wolfgang 29260 1658936
113
- zeryl 28156 1579911
114
- OuaisBla 27636 1578800
115
- DMBK 27051 1999456
116
- chriswk 26902 1868317
117
- achambord 26582 1767323
118
- Patrick_G 26276 1801617
119
- yorkman 26193 1992080
120
- SFTUser 25182 1675689
121
- nabildanial 24942 1519409
122
- Sharaf_DG 24765 1786697
123
- ncfish1 24411 1520927
124
- rodneyc 24227 1409514
125
- agg177 23890 1395014
126
- JanErik 23408 1703875
127
- Isidor 23388 1680691
128
- Norabor 23164 1591830
129
- cisco2015 22897 1762669
130
- Zirie 22542 1472937
131
- team-oh 22272 1636708
132
- MazeOfGalious 21978 1629593
133
- sg4032 21947 1643265
134
- ianh2105 21725 1632562
135
- xor12 21628 1680365
136
- dex 21612 1467203
137
- nesoneg 21494 1463031
138
- sphinx 21211 1384728
139
- jjoshua2 21001 1423089
140
- horst.prack 20878 1465656
141
- Ente 20865 1477066
142
- 0xB00B1ES 20590 1208666
143
- j3corre 20405 941444
144
- Adrian.Schmidt123 20316 1281436
145
- wei 19973 1745989
146
- MaxKlaxxMiner 19850 1009176
147
- rstoesser 19569 1293588
148
- gopeto 19491 1174952
149
- eudhan 19274 1283717
150
- jundery 18445 1115855
151
- megaman7de 18377 1067540
152
- iisiraider 18247 1101015
153
- ville 17883 1384026
154
- chris 17698 1487385
155
- purplefishies 17595 1092533
156
- dju 17353 978595
157
- DragonLord 17014 1162790
158
- IgorLeMasson 16064 1147232
159
- ako027ako 15671 1173203
160
- chuckstablers 15289 891576
161
- Nikolay.IT 15154 1068349
162
- Andrew Grant 15114 895539
163
- OssumOpossum 14857 1007129
164
- Karby 14808 867120
165
- enedene 14476 905279
166
- bpfliegel 14298 884523
167
- mpx86 14019 759568
168
- jpulman 13982 870599
169
- crocogoat 13803 1117422
170
- joster 13794 950160
171
- Nesa92 13786 1114691
172
- Hjax 13535 915487
173
- jsys14 13459 785000
174
- Dark_wizzie 13422 1007152
175
- mabichito 12903 749391
176
- thijsk 12886 722107
177
- AdrianSA 12860 804972
178
- Flopzee 12698 894821
179
- fatmurphy 12547 853210
180
- Rudolphous 12520 832340
181
- scuzzi 12511 845761
182
- SapphireBrand 12416 969604
183
- modolief 12386 896470
184
- Machariel 12335 810784
185
- pgontarz 12151 848794
186
- stocky 11954 699440
187
- mschmidt 11941 803401
188
- Maxim 11543 836024
189
- infinity 11470 727027
190
- torbjo 11395 729145
191
- Thomas A. Anderson 11372 732094
192
- savage84 11358 670860
193
- d64 11263 789184
194
- MooTheCow 11237 720174
195
- snicolet 11106 869170
196
- ali-al-zhrani 11086 767926
197
- AndreasKrug 10875 887457
198
- pirt 10806 836519
199
- basepi 10637 744851
200
- michaelrpg 10508 739039
201
- dzjp 10343 732529
202
- aga 10302 622975
203
- ols 10259 570669
204
- lbraesch 10252 647825
205
- FormazChar 10059 757283
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/appveyor.yml DELETED
@@ -1,91 +0,0 @@
1
- version: 1.0.{build}
2
- clone_depth: 50
3
-
4
- branches:
5
- only:
6
- - master
7
- - merge
8
- - appveyor
9
-
10
- # Operating system (build VM template)
11
- os: Visual Studio 2019
12
-
13
- # Build platform, i.e. x86, x64, AnyCPU. This setting is optional.
14
- platform:
15
- - x86
16
- - x64
17
-
18
- # build Configuration, i.e. Debug, Release, etc.
19
- configuration:
20
- - Debug
21
- - Release
22
-
23
- matrix:
24
- # The build fail immediately once one of the job fails
25
- fast_finish: true
26
-
27
- # Scripts that are called at very beginning, before repo cloning
28
- init:
29
- - cmake --version
30
- - msbuild /version
31
-
32
- before_build:
33
- - ps: |
34
- # Get sources
35
- $src = get-childitem -Path *.cpp -Recurse -Exclude pyffish.cpp,ffishjs.cpp | select -ExpandProperty FullName
36
- $src = $src -join ' '
37
- $src = $src.Replace("\", "/")
38
-
39
- # Build CMakeLists.txt
40
- $t = 'cmake_minimum_required(VERSION 3.17)',
41
- 'project(Stockfish)',
42
- 'set(CMAKE_CXX_STANDARD 17)',
43
- 'set(CMAKE_CXX_STANDARD_REQUIRED ON)',
44
- 'set (CMAKE_CXX_EXTENSIONS OFF)',
45
- 'set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/src)',
46
- 'set(source_files', $src, ')',
47
- 'add_compile_definitions(NNUE_EMBEDDING_OFF)',
48
- 'add_executable(stockfish ${source_files})'
49
-
50
- # Write CMakeLists.txt without BOM
51
- $MyPath = (Get-Item -Path "." -Verbose).FullName + '\CMakeLists.txt'
52
- $Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
53
- [System.IO.File]::WriteAllLines($MyPath, $t, $Utf8NoBomEncoding)
54
-
55
- # Obtain bench reference from git log
56
- $b = git log HEAD | sls "\b[Bb]ench[ :]+[0-9]{7}" | select -first 1
57
- $bench = $b -match '\D+(\d+)' | % { $matches[1] }
58
- Write-Host "Reference bench:" $bench
59
- $g = "Visual Studio 16 2019"
60
- If (${env:PLATFORM} -eq 'x64') { $a = "x64" }
61
- If (${env:PLATFORM} -eq 'x86') { $a = "Win32" }
62
- cmake -G "${g}" -A ${a} .
63
- Write-Host "Generated files for: " $g $a
64
-
65
- build_script:
66
- - cmake --build . --config %CONFIGURATION% -- /verbosity:minimal
67
- - ps: |
68
- # Download default NNUE net from fishtest
69
- $nnuenet = Get-Content -Path src\evaluate.h | Select-String -CaseSensitive -Pattern "EvalFileDefaultName" | Select-String -CaseSensitive -Pattern "nn-[a-z0-9]{12}.nnue"
70
- $dummy = $nnuenet -match "(?<nnuenet>nn-[a-z0-9]{12}.nnue)"
71
- $nnuenet = $Matches.nnuenet
72
- Write-Host "Default net:" $nnuenet
73
- $nnuedownloadurl = "https://github.com/official-stockfish/networks/raw/master/$nnuenet"
74
- $nnuefilepath = "src\${env:CONFIGURATION}\$nnuenet"
75
- if (Test-Path -Path $nnuefilepath) {
76
- Write-Host "Already available."
77
- } else {
78
- Write-Host "Downloading $nnuedownloadurl to $nnuefilepath"
79
- Invoke-WebRequest -Uri $nnuedownloadurl -OutFile $nnuefilepath
80
- }
81
-
82
- before_test:
83
- - cd src/%CONFIGURATION%
84
- - stockfish bench 2> out.txt >NUL
85
- - ps: |
86
- # Verify bench number
87
- $s = (gc "./out.txt" | out-string)
88
- $r = ($s -match 'Nodes searched \D+(\d+)' | % { $matches[1] })
89
- Write-Host "Engine bench:" $r
90
- Write-Host "Reference bench:" $bench
91
- If ($r -ne $bench) { exit 1 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/pyffish.pyi DELETED
@@ -1,39 +0,0 @@
1
- from typing import Any
2
-
3
- FEN_OK: int
4
- NOTATION_DEFAULT: int
5
- NOTATION_JANGGI: int
6
- NOTATION_LAN: int
7
- NOTATION_SAN: int
8
- NOTATION_SHOGI_HODGES: int
9
- NOTATION_SHOGI_HODGES_NUMBER: int
10
- NOTATION_SHOGI_HOSKING: int
11
- NOTATION_THAI_LAN: int
12
- NOTATION_THAI_SAN: int
13
- NOTATION_XIANGQI_WXF: int
14
- VALUE_DRAW: int
15
- VALUE_MATE: int
16
-
17
- class error(Exception): ...
18
-
19
- def version() -> tuple[int, int, int]: ...
20
- def info() -> str: ...
21
- def variants() -> list[str]: ...
22
- def set_option(name: str, value: Any) -> None: ...
23
- def load_variant_config(config: str) -> None: ...
24
- def start_fen(variant: str) -> str: ...
25
- def two_boards(variant: str) -> bool: ...
26
- def captures_to_hand(variant: str) -> bool: ...
27
- def get_san(variant: str, fen: str, move: str, chess960: bool = False, notation: int = NOTATION_DEFAULT) -> str: ...
28
- def get_san_moves(variant: str, fen: str, movelist: list[str], chess960: bool = False, notation: int = NOTATION_DEFAULT) -> list[str]: ...
29
- def legal_moves(variant: str, fen: str, movelist: list[str], chess960: bool = False) -> list[str]: ...
30
- 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: ...
31
- def gives_check(variant: str, fen: str, movelist: list[str], chess960: bool = False) -> bool: ...
32
- def is_capture(variant: str, fen: str, movelist: list[str], move: str, chess960: bool = False) -> bool: ...
33
- def piece_to_partner(variant: str, fen: str, movelist: list[str], chess960: bool = False) -> str: ...
34
- def game_result(variant: str, fen: str, movelist: list[str], chess960: bool = False) -> int: ...
35
- def is_immediate_game_end(variant: str, fen: str, movelist: list[str], chess960: bool = False) -> tuple[bool, int]: ...
36
- def is_optional_game_end(variant: str, fen: str, movelist: list[str], chess960: bool = False, count_started: int = 0) -> tuple[bool, int]: ...
37
- def has_insufficient_material(variant: str, fen: str, movelist: list[str], chess960: bool = False) -> tuple[bool, bool]: ...
38
- def validate_fen(fen: str, variant: str, chess960: bool = False) -> int: ...
39
- def get_fog_fen(fen: str, variant: str, chess960: bool = False) -> str: ...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/setup.py DELETED
@@ -1,56 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- from setuptools import setup, Extension
4
- from glob import glob
5
- import platform
6
- import io
7
- import os
8
-
9
-
10
- if platform.python_compiler().startswith("MSC"):
11
- args = ["/std:c++17"]
12
- else:
13
- args = ["-std=c++17", "-flto", "-Wno-date-time"]
14
-
15
- args.extend(["-DLARGEBOARDS", "-DALLVARS", "-DPRECOMPUTED_MAGICS", "-DNNUE_EMBEDDING_OFF"])
16
-
17
- if "64bit" in platform.architecture():
18
- args.append("-DIS_64BIT")
19
-
20
- CLASSIFIERS = [
21
- "Development Status :: 3 - Alpha",
22
- "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
23
- "Programming Language :: Python :: 3",
24
- "Operating System :: OS Independent",
25
- ]
26
-
27
- with io.open("README.md", "r", encoding="utf8") as fh:
28
- long_description = fh.read().strip()
29
-
30
- sources = glob("src/*.cpp") + glob("src/syzygy/*.cpp") + glob("src/nnue/*.cpp") + glob("src/nnue/features/*.cpp")
31
- headers = glob("src/*.h") + glob("src/syzygy/*.h") + glob("src/nnue/*.h") + glob("src/nnue/features/*.h")
32
- ffish_source_file = os.path.normcase("src/ffishjs.cpp")
33
- try:
34
- sources.remove(ffish_source_file)
35
- except ValueError:
36
- print(f"ffish_source_file {ffish_source_file} was not found in sources {sources}.")
37
-
38
- pyffish_module = Extension(
39
- "pyffish",
40
- sources=sources,
41
- depends=headers,
42
- extra_compile_args=args)
43
-
44
- setup(name="pyffish", version="0.0.89",
45
- description="Fairy-Stockfish Python wrapper",
46
- long_description=long_description,
47
- long_description_content_type="text/markdown",
48
- author="Bajusz Tamás",
49
- author_email="gbtami@gmail.com",
50
- license="GPL3",
51
- classifiers=CLASSIFIERS,
52
- url="https://github.com/gbtami/Fairy-Stockfish",
53
- python_requires=">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*",
54
- ext_modules=[pyffish_module],
55
- data_files=[("", ["pyffish.pyi"])]
56
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/src/Makefile DELETED
@@ -1,982 +0,0 @@
1
- # Stockfish, a UCI chess playing engine derived from Glaurung 2.1
2
- # Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
3
- #
4
- # Stockfish is free software: you can redistribute it and/or modify
5
- # it under the terms of the GNU General Public License as published by
6
- # the Free Software Foundation, either version 3 of the License, or
7
- # (at your option) any later version.
8
- #
9
- # Stockfish is distributed in the hope that it will be useful,
10
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- # GNU General Public License for more details.
13
- #
14
- # You should have received a copy of the GNU General Public License
15
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
-
17
-
18
- ### ==========================================================================
19
- ### Section 1. General Configuration
20
- ### ==========================================================================
21
-
22
- ### Executable name
23
- ifeq ($(COMP),mingw)
24
- EXE = stockfish.exe
25
- else
26
- EXE = stockfish
27
- endif
28
-
29
- ### Installation dir definitions
30
- PREFIX = /usr/local
31
- BINDIR = $(PREFIX)/bin
32
-
33
- ### Built-in benchmark for pgo-builds
34
- ifeq ($(SDE_PATH),)
35
- PGOBENCH = ./$(EXE) bench
36
- else
37
- PGOBENCH = $(SDE_PATH) -- ./$(EXE) bench
38
- endif
39
-
40
- ### Source and object files
41
- SRCS = benchmark.cpp bitbase.cpp bitboard.cpp endgame.cpp evaluate.cpp main.cpp \
42
- material.cpp misc.cpp movegen.cpp movepick.cpp pawns.cpp position.cpp psqt.cpp \
43
- search.cpp thread.cpp timeman.cpp tt.cpp uci.cpp ucioption.cpp tune.cpp syzygy/tbprobe.cpp \
44
- nnue/evaluate_nnue.cpp nnue/features/half_ka_v2.cpp \
45
- partner.cpp parser.cpp piece.cpp variant.cpp xboard.cpp \
46
- nnue/features/half_ka_v2_variants.cpp
47
-
48
- OBJS = $(notdir $(SRCS:.cpp=.o))
49
-
50
- VPATH = syzygy:nnue:nnue/features
51
-
52
- ### Establish the operating system name
53
- KERNEL = $(shell uname -s)
54
- ifeq ($(KERNEL),Linux)
55
- OS = $(shell uname -o)
56
- endif
57
-
58
- ### ==========================================================================
59
- ### Section 2. High-level Configuration
60
- ### ==========================================================================
61
- #
62
- # flag --- Comp switch --- Description
63
- # ----------------------------------------------------------------------------
64
- #
65
- # debug = yes/no --- -DNDEBUG --- Enable/Disable debug mode
66
- # sanitize = none/<sanitizer> ... (-fsanitize )
67
- # --- ( undefined ) --- enable undefined behavior checks
68
- # --- ( thread ) --- enable threading error checks
69
- # --- ( address ) --- enable memory access checks
70
- # --- ...etc... --- see compiler documentation for supported sanitizers
71
- # optimize = yes/no --- (-O3/-fast etc.) --- Enable/Disable optimizations
72
- # arch = (name) --- (-arch) --- Target architecture
73
- # bits = 64/32 --- -DIS_64BIT --- 64-/32-bit operating system
74
- # prefetch = yes/no --- -DUSE_PREFETCH --- Use prefetch asm-instruction
75
- # popcnt = yes/no --- -DUSE_POPCNT --- Use popcnt asm-instruction
76
- # pext = yes/no --- -DUSE_PEXT --- Use pext x86_64 asm-instruction
77
- # sse = yes/no --- -msse --- Use Intel Streaming SIMD Extensions
78
- # mmx = yes/no --- -mmmx --- Use Intel MMX instructions
79
- # sse2 = yes/no --- -msse2 --- Use Intel Streaming SIMD Extensions 2
80
- # ssse3 = yes/no --- -mssse3 --- Use Intel Supplemental Streaming SIMD Extensions 3
81
- # sse41 = yes/no --- -msse4.1 --- Use Intel Streaming SIMD Extensions 4.1
82
- # avx2 = yes/no --- -mavx2 --- Use Intel Advanced Vector Extensions 2
83
- # avx512 = yes/no --- -mavx512bw --- Use Intel Advanced Vector Extensions 512
84
- # vnni256 = yes/no --- -mavx512vnni --- Use Intel Vector Neural Network Instructions 256
85
- # vnni512 = yes/no --- -mavx512vnni --- Use Intel Vector Neural Network Instructions 512
86
- # neon = yes/no --- -DUSE_NEON --- Use ARM SIMD architecture
87
- #
88
- # Note that Makefile is space sensitive, so when adding new architectures
89
- # or modifying existing flags, you have to make sure there are no extra spaces
90
- # at the end of the line for flag values.
91
- #
92
- # Example of use for these flags:
93
- # make build ARCH=x86-64-avx512 debug=on sanitize="address undefined"
94
-
95
-
96
- ### 2.1. General and architecture defaults
97
- largeboards = no
98
- all = no
99
- precomputedmagics = yes
100
- nnue = no
101
- load_net = $(if $(filter $(nnue),yes),net)
102
-
103
- ifeq ($(ARCH),)
104
- ARCH = x86-64-modern
105
- help_skip_sanity = yes
106
- endif
107
- # explicitly check for the list of supported architectures (as listed with make help),
108
- # the user can override with `make ARCH=x86-32-vnni256 SUPPORTED_ARCH=true`
109
- ifeq ($(ARCH), $(filter $(ARCH), \
110
- x86-64-vnni512 x86-64-vnni256 x86-64-avx512 x86-64-bmi2 x86-64-avx2 \
111
- x86-64-sse41-popcnt x86-64-modern x86-64-ssse3 x86-64-sse3-popcnt \
112
- x86-64 x86-32-sse41-popcnt x86-32-sse2 x86-32 ppc-64 ppc-32 e2k \
113
- armv7 armv7-neon armv8 apple-silicon general-64 general-32))
114
- SUPPORTED_ARCH=true
115
- else
116
- SUPPORTED_ARCH=false
117
- endif
118
-
119
- optimize = yes
120
- debug = no
121
- sanitize = none
122
- bits = 64
123
- prefetch = no
124
- popcnt = no
125
- pext = no
126
- sse = no
127
- mmx = no
128
- sse2 = no
129
- ssse3 = no
130
- sse41 = no
131
- avx2 = no
132
- avx512 = no
133
- vnni256 = no
134
- vnni512 = no
135
- neon = no
136
- STRIP = strip
137
-
138
- ### 2.2 Architecture specific
139
-
140
- ifeq ($(findstring x86,$(ARCH)),x86)
141
-
142
- # x86-32/64
143
-
144
- ifeq ($(findstring x86-32,$(ARCH)),x86-32)
145
- arch = i386
146
- bits = 32
147
- sse = yes
148
- mmx = yes
149
- else
150
- arch = x86_64
151
- sse = yes
152
- sse2 = yes
153
- endif
154
-
155
- ifeq ($(findstring -sse,$(ARCH)),-sse)
156
- sse = yes
157
- endif
158
-
159
- ifeq ($(findstring -popcnt,$(ARCH)),-popcnt)
160
- popcnt = yes
161
- endif
162
-
163
- ifeq ($(findstring -mmx,$(ARCH)),-mmx)
164
- mmx = yes
165
- endif
166
-
167
- ifeq ($(findstring -sse2,$(ARCH)),-sse2)
168
- sse = yes
169
- sse2 = yes
170
- endif
171
-
172
- ifeq ($(findstring -ssse3,$(ARCH)),-ssse3)
173
- sse = yes
174
- sse2 = yes
175
- ssse3 = yes
176
- endif
177
-
178
- ifeq ($(findstring -sse41,$(ARCH)),-sse41)
179
- sse = yes
180
- sse2 = yes
181
- ssse3 = yes
182
- sse41 = yes
183
- endif
184
-
185
- ifeq ($(findstring -modern,$(ARCH)),-modern)
186
- popcnt = yes
187
- sse = yes
188
- sse2 = yes
189
- ssse3 = yes
190
- sse41 = yes
191
- endif
192
-
193
- ifeq ($(findstring -avx2,$(ARCH)),-avx2)
194
- popcnt = yes
195
- sse = yes
196
- sse2 = yes
197
- ssse3 = yes
198
- sse41 = yes
199
- avx2 = yes
200
- endif
201
-
202
- ifeq ($(findstring -bmi2,$(ARCH)),-bmi2)
203
- popcnt = yes
204
- sse = yes
205
- sse2 = yes
206
- ssse3 = yes
207
- sse41 = yes
208
- avx2 = yes
209
- pext = yes
210
- endif
211
-
212
- ifeq ($(findstring -avx512,$(ARCH)),-avx512)
213
- popcnt = yes
214
- sse = yes
215
- sse2 = yes
216
- ssse3 = yes
217
- sse41 = yes
218
- avx2 = yes
219
- pext = yes
220
- avx512 = yes
221
- endif
222
-
223
- ifeq ($(findstring -vnni256,$(ARCH)),-vnni256)
224
- popcnt = yes
225
- sse = yes
226
- sse2 = yes
227
- ssse3 = yes
228
- sse41 = yes
229
- avx2 = yes
230
- pext = yes
231
- vnni256 = yes
232
- endif
233
-
234
- ifeq ($(findstring -vnni512,$(ARCH)),-vnni512)
235
- popcnt = yes
236
- sse = yes
237
- sse2 = yes
238
- ssse3 = yes
239
- sse41 = yes
240
- avx2 = yes
241
- pext = yes
242
- avx512 = yes
243
- vnni512 = yes
244
- endif
245
-
246
- ifeq ($(sse),yes)
247
- prefetch = yes
248
- endif
249
-
250
- # 64-bit pext is not available on x86-32
251
- ifeq ($(bits),32)
252
- pext = no
253
- endif
254
-
255
- else
256
-
257
- # all other architectures
258
-
259
- ifeq ($(ARCH),general-32)
260
- arch = any
261
- bits = 32
262
- endif
263
-
264
- ifeq ($(ARCH),general-64)
265
- arch = any
266
- endif
267
-
268
- ifeq ($(ARCH),armv7)
269
- arch = armv7
270
- prefetch = yes
271
- bits = 32
272
- endif
273
-
274
- ifeq ($(ARCH),armv7-neon)
275
- arch = armv7
276
- prefetch = yes
277
- popcnt = yes
278
- neon = yes
279
- bits = 32
280
- endif
281
-
282
- ifeq ($(ARCH),armv8)
283
- arch = armv8
284
- prefetch = yes
285
- popcnt = yes
286
- neon = yes
287
- endif
288
-
289
- ifeq ($(ARCH),apple-silicon)
290
- arch = arm64
291
- prefetch = yes
292
- popcnt = yes
293
- neon = yes
294
- endif
295
-
296
- ifeq ($(ARCH),ppc-32)
297
- arch = ppc
298
- bits = 32
299
- endif
300
-
301
- ifeq ($(ARCH),ppc-64)
302
- arch = ppc64
303
- popcnt = yes
304
- prefetch = yes
305
- endif
306
-
307
- ifeq ($(findstring e2k,$(ARCH)),e2k)
308
- arch = e2k
309
- mmx = yes
310
- bits = 64
311
- sse = yes
312
- sse2 = yes
313
- ssse3 = yes
314
- sse41 = yes
315
- popcnt = yes
316
- endif
317
-
318
- endif
319
-
320
- # Disable precomputed magics when 64-bit PEXT is available
321
- ifeq ($(pext),yes)
322
- precomputedmagics = no
323
- endif
324
-
325
- ### ==========================================================================
326
- ### Section 3. Low-level Configuration
327
- ### ==========================================================================
328
-
329
- ### 3.1 Selecting compiler (default = gcc)
330
- CXXFLAGS += -Wall -Wcast-qual -fno-exceptions -std=c++17 $(EXTRACXXFLAGS)
331
- DEPENDFLAGS += -std=c++17
332
- LDFLAGS += $(EXTRALDFLAGS)
333
-
334
- # Ignore warning due to missing profile information from unused NNUE features
335
- CXXFLAGS += -Wno-profile-instr-out-of-date
336
-
337
- # Compile version with support for large board variants
338
- # Use precomputed magics by default if pext is not available
339
- ifneq ($(largeboards),no)
340
- CXXFLAGS += -DLARGEBOARDS
341
- ifeq ($(precomputedmagics),yes)
342
- CXXFLAGS += -DPRECOMPUTED_MAGICS
343
- endif
344
- endif
345
-
346
- # Embed and enable NNUE
347
- ifeq ($(nnue),no)
348
- CXXFLAGS += -DNNUE_EMBEDDING_OFF
349
- endif
350
-
351
- # Enable all variants, even heavyweight ones like duck and amazons
352
- ifneq ($(all),no)
353
- CXXFLAGS += -DALLVARS
354
- endif
355
-
356
- ifeq ($(COMP),)
357
- COMP=gcc
358
- endif
359
-
360
- ifeq ($(COMP),gcc)
361
- comp=gcc
362
- CXX=g++
363
- CXXFLAGS += -Wextra -Wshadow
364
- ifeq ($(largeboards),no)
365
- CXXFLAGS += -pedantic
366
- endif
367
-
368
- ifeq ($(arch),$(filter $(arch),armv7 armv8))
369
- ifeq ($(OS),Android)
370
- CXXFLAGS += -m$(bits)
371
- LDFLAGS += -m$(bits)
372
- endif
373
- else
374
- CXXFLAGS += -m$(bits)
375
- LDFLAGS += -m$(bits)
376
- endif
377
-
378
- ifeq ($(arch),$(filter $(arch),armv7))
379
- LDFLAGS += -latomic
380
- endif
381
-
382
- ifneq ($(KERNEL),Darwin)
383
- LDFLAGS += -Wl,--no-as-needed
384
- endif
385
- endif
386
-
387
- ifeq ($(COMP),mingw)
388
- comp=mingw
389
-
390
- ifeq ($(KERNEL),Linux)
391
- ifeq ($(bits),64)
392
- ifeq ($(shell which x86_64-w64-mingw32-c++-posix),)
393
- CXX=x86_64-w64-mingw32-c++
394
- else
395
- CXX=x86_64-w64-mingw32-c++-posix
396
- endif
397
- else
398
- ifeq ($(shell which i686-w64-mingw32-c++-posix),)
399
- CXX=i686-w64-mingw32-c++
400
- else
401
- CXX=i686-w64-mingw32-c++-posix
402
- endif
403
- endif
404
- else
405
- CXX=g++
406
- endif
407
-
408
- CXXFLAGS += -Wextra -Wshadow
409
- LDFLAGS += -static
410
- endif
411
-
412
- ifeq ($(COMP),icc)
413
- comp=icc
414
- CXX=icpc
415
- CXXFLAGS += -diag-disable 1476,10120 -Wcheck -Wabi -Wdeprecated -strict-ansi
416
- endif
417
-
418
- ifeq ($(COMP),clang)
419
- comp=clang
420
- CXX=clang++
421
- CXXFLAGS += -pedantic -Wextra -Wshadow
422
-
423
- ifneq ($(KERNEL),Darwin)
424
- ifneq ($(KERNEL),OpenBSD)
425
- ifneq ($(KERNEL),FreeBSD)
426
- LDFLAGS += -latomic
427
- endif
428
- endif
429
- endif
430
-
431
- ifeq ($(arch),$(filter $(arch),armv7 armv8))
432
- ifeq ($(OS),Android)
433
- CXXFLAGS += -m$(bits)
434
- LDFLAGS += -m$(bits)
435
- endif
436
- else
437
- CXXFLAGS += -m$(bits)
438
- LDFLAGS += -m$(bits)
439
- endif
440
- endif
441
-
442
- ifeq ($(KERNEL),Darwin)
443
- CXXFLAGS += -arch $(arch) -mmacosx-version-min=10.14
444
- LDFLAGS += -arch $(arch) -mmacosx-version-min=10.14
445
- XCRUN = xcrun
446
- endif
447
-
448
- # To cross-compile for Android, NDK version r21 or later is recommended.
449
- # In earlier NDK versions, you'll need to pass -fno-addrsig if using GNU binutils.
450
- # Currently we don't know how to make PGO builds with the NDK yet.
451
- ifeq ($(COMP),ndk)
452
- CXXFLAGS += -stdlib=libc++ -fPIE
453
- comp=clang
454
- ifeq ($(arch),armv7)
455
- CXX=armv7a-linux-androideabi16-clang++
456
- CXXFLAGS += -mthumb -march=armv7-a -mfloat-abi=softfp -mfpu=neon
457
- STRIP=arm-linux-androideabi-strip
458
- endif
459
- ifeq ($(arch),armv8)
460
- CXX=aarch64-linux-android21-clang++
461
- STRIP=aarch64-linux-android-strip
462
- endif
463
- LDFLAGS += -static-libstdc++ -pie -lm -latomic
464
- endif
465
-
466
- ifeq ($(comp),icc)
467
- profile_make = icc-profile-make
468
- profile_use = icc-profile-use
469
- else ifeq ($(comp),clang)
470
- profile_make = clang-profile-make
471
- profile_use = clang-profile-use
472
- else
473
- profile_make = gcc-profile-make
474
- profile_use = gcc-profile-use
475
- endif
476
-
477
- ### Travis CI script uses COMPILER to overwrite CXX
478
- ifdef COMPILER
479
- COMPCXX=$(COMPILER)
480
- endif
481
-
482
- ### Allow overwriting CXX from command line
483
- ifdef COMPCXX
484
- CXX=$(COMPCXX)
485
- endif
486
-
487
- ### Sometimes gcc is really clang
488
- ifeq ($(COMP),gcc)
489
- gccversion = $(shell $(CXX) --version)
490
- gccisclang = $(findstring clang,$(gccversion))
491
- ifneq ($(gccisclang),)
492
- profile_make = clang-profile-make
493
- profile_use = clang-profile-use
494
- endif
495
- endif
496
-
497
- ### On mingw use Windows threads, otherwise POSIX
498
- ifneq ($(comp),mingw)
499
- CXXFLAGS += -DUSE_PTHREADS
500
- # On Android Bionic's C library comes with its own pthread implementation bundled in
501
- ifneq ($(OS),Android)
502
- # Haiku has pthreads in its libroot, so only link it in on other platforms
503
- ifneq ($(KERNEL),Haiku)
504
- ifneq ($(COMP),ndk)
505
- LDFLAGS += -lpthread
506
- endif
507
- endif
508
- endif
509
- endif
510
-
511
- ### 3.2.1 Debugging
512
- ifeq ($(debug),no)
513
- CXXFLAGS += -DNDEBUG
514
- else
515
- CXXFLAGS += -g
516
- endif
517
-
518
- ### 3.2.2 Debugging with undefined behavior sanitizers
519
- ifneq ($(sanitize),none)
520
- CXXFLAGS += -g3 $(addprefix -fsanitize=,$(sanitize))
521
- LDFLAGS += $(addprefix -fsanitize=,$(sanitize))
522
- endif
523
-
524
- ### 3.3 Optimization
525
- ifeq ($(optimize),yes)
526
-
527
- CXXFLAGS += -O3 -fno-strict-aliasing
528
-
529
- ifeq ($(comp),gcc)
530
- ifeq ($(OS), Android)
531
- CXXFLAGS += -fno-gcse -mthumb -march=armv7-a -mfloat-abi=softfp
532
- endif
533
- endif
534
-
535
- ifeq ($(comp),$(filter $(comp),gcc clang icc))
536
- ifeq ($(KERNEL),Darwin)
537
- CXXFLAGS += -mdynamic-no-pic
538
- endif
539
- endif
540
-
541
- ifeq ($(comp),clang)
542
- clangmajorversion = $(shell $(CXX) -dumpversion 2>/dev/null | cut -f1 -d.)
543
- ifeq ($(shell expr $(clangmajorversion) \< 16),1)
544
- CXXFLAGS += -fexperimental-new-pass-manager
545
- endif
546
- endif
547
- endif
548
-
549
- ### 3.4 Bits
550
- ifeq ($(bits),64)
551
- CXXFLAGS += -DIS_64BIT
552
- endif
553
-
554
- ### 3.5 prefetch
555
- ifeq ($(prefetch),yes)
556
- ifeq ($(sse),yes)
557
- CXXFLAGS += -msse
558
- endif
559
- else
560
- CXXFLAGS += -DNO_PREFETCH
561
- endif
562
-
563
- ### 3.6 popcnt
564
- ifeq ($(popcnt),yes)
565
- ifeq ($(arch),$(filter $(arch),ppc64 armv7 armv8 arm64))
566
- CXXFLAGS += -DUSE_POPCNT
567
- else ifeq ($(comp),icc)
568
- CXXFLAGS += -msse3 -DUSE_POPCNT
569
- else
570
- CXXFLAGS += -msse3 -mpopcnt -DUSE_POPCNT
571
- endif
572
- endif
573
-
574
- ifeq ($(avx2),yes)
575
- CXXFLAGS += -DUSE_AVX2
576
- ifeq ($(comp),$(filter $(comp),gcc clang mingw))
577
- CXXFLAGS += -mavx2 -mbmi
578
- endif
579
- endif
580
-
581
- ifeq ($(avx512),yes)
582
- CXXFLAGS += -DUSE_AVX512
583
- ifeq ($(comp),$(filter $(comp),gcc clang mingw))
584
- CXXFLAGS += -mavx512f -mavx512bw
585
- endif
586
- endif
587
-
588
- ifeq ($(vnni256),yes)
589
- CXXFLAGS += -DUSE_VNNI
590
- ifeq ($(comp),$(filter $(comp),gcc clang mingw))
591
- CXXFLAGS += -mavx512f -mavx512bw -mavx512vnni -mavx512dq -mavx512vl -mprefer-vector-width=256
592
- endif
593
- endif
594
-
595
- ifeq ($(vnni512),yes)
596
- CXXFLAGS += -DUSE_VNNI
597
- ifeq ($(comp),$(filter $(comp),gcc clang mingw))
598
- CXXFLAGS += -mavx512vnni -mavx512dq -mavx512vl
599
- endif
600
- endif
601
-
602
- ifeq ($(sse41),yes)
603
- CXXFLAGS += -DUSE_SSE41
604
- ifeq ($(comp),$(filter $(comp),gcc clang mingw))
605
- CXXFLAGS += -msse4.1
606
- endif
607
- endif
608
-
609
- ifeq ($(ssse3),yes)
610
- CXXFLAGS += -DUSE_SSSE3
611
- ifeq ($(comp),$(filter $(comp),gcc clang mingw))
612
- CXXFLAGS += -mssse3
613
- endif
614
- endif
615
-
616
- ifeq ($(sse2),yes)
617
- CXXFLAGS += -DUSE_SSE2
618
- ifeq ($(comp),$(filter $(comp),gcc clang mingw))
619
- CXXFLAGS += -msse2
620
- endif
621
- endif
622
-
623
- ifeq ($(mmx),yes)
624
- CXXFLAGS += -DUSE_MMX
625
- ifeq ($(comp),$(filter $(comp),gcc clang mingw))
626
- CXXFLAGS += -mmmx
627
- endif
628
- endif
629
-
630
- ifeq ($(neon),yes)
631
- CXXFLAGS += -DUSE_NEON
632
- ifeq ($(KERNEL),Linux)
633
- ifneq ($(COMP),ndk)
634
- ifneq ($(arch),armv8)
635
- CXXFLAGS += -mfpu=neon
636
- endif
637
- endif
638
- endif
639
- endif
640
-
641
- ### 3.7 pext
642
- ifeq ($(pext),yes)
643
- CXXFLAGS += -DUSE_PEXT
644
- ifeq ($(comp),$(filter $(comp),gcc clang mingw))
645
- CXXFLAGS += -mbmi2
646
- endif
647
- endif
648
-
649
- ### 3.8 Link Time Optimization
650
- ### This is a mix of compile and link time options because the lto link phase
651
- ### needs access to the optimization flags.
652
- ifeq ($(optimize),yes)
653
- ifeq ($(debug), no)
654
- ifeq ($(comp),clang)
655
- CXXFLAGS += -flto
656
- ifneq ($(findstring MINGW,$(KERNEL)),)
657
- CXXFLAGS += -fuse-ld=lld
658
- else ifneq ($(findstring MSYS,$(KERNEL)),)
659
- CXXFLAGS += -fuse-ld=lld
660
- endif
661
- LDFLAGS += $(CXXFLAGS)
662
-
663
- # GCC and CLANG use different methods for parallelizing LTO and CLANG pretends to be
664
- # GCC on some systems.
665
- else ifeq ($(comp),gcc)
666
- ifeq ($(gccisclang),)
667
- CXXFLAGS += -flto
668
- LDFLAGS += $(CXXFLAGS) -flto=jobserver
669
- ifneq ($(findstring MINGW,$(KERNEL)),)
670
- LDFLAGS += -save-temps
671
- else ifneq ($(findstring MSYS,$(KERNEL)),)
672
- LDFLAGS += -save-temps
673
- endif
674
- else
675
- CXXFLAGS += -flto
676
- LDFLAGS += $(CXXFLAGS)
677
- endif
678
-
679
- # To use LTO and static linking on windows, the tool chain requires a recent gcc:
680
- # gcc version 10.1 in msys2 or TDM-GCC version 9.2 are known to work, older might not.
681
- # So, only enable it for a cross from Linux by default.
682
- else ifeq ($(comp),mingw)
683
- ifeq ($(KERNEL),Linux)
684
- ifneq ($(arch),i386)
685
- CXXFLAGS += -flto
686
- LDFLAGS += $(CXXFLAGS) -flto=jobserver
687
- endif
688
- endif
689
- endif
690
- endif
691
- endif
692
-
693
- ### 3.9 Android 5 can only run position independent executables. Note that this
694
- ### breaks Android 4.0 and earlier.
695
- ifeq ($(OS), Android)
696
- CXXFLAGS += -fPIE
697
- LDFLAGS += -fPIE -pie
698
- endif
699
-
700
- ### ==========================================================================
701
- ### Section 4. Public Targets
702
- ### ==========================================================================
703
-
704
-
705
- help:
706
- @echo ""
707
- @echo "To compile stockfish, type: "
708
- @echo ""
709
- @echo "make target ARCH=arch [COMP=compiler] [COMPCXX=cxx]"
710
- @echo ""
711
- @echo "Supported targets:"
712
- @echo ""
713
- @echo "help > Display architecture details"
714
- @echo "build > Standard build"
715
- @echo "net > Download the default nnue net"
716
- @echo "profile-build > Faster build (with profile-guided optimization)"
717
- @echo "strip > Strip executable"
718
- @echo "install > Install executable"
719
- @echo "clean > Clean up"
720
- @echo ""
721
- @echo "Supported archs:"
722
- @echo ""
723
- @echo "x86-64-vnni512 > x86 64-bit with vnni support 512bit wide"
724
- @echo "x86-64-vnni256 > x86 64-bit with vnni support 256bit wide"
725
- @echo "x86-64-avx512 > x86 64-bit with avx512 support"
726
- @echo "x86-64-bmi2 > x86 64-bit with bmi2 support"
727
- @echo "x86-64-avx2 > x86 64-bit with avx2 support"
728
- @echo "x86-64-sse41-popcnt > x86 64-bit with sse41 and popcnt support"
729
- @echo "x86-64-modern > common modern CPU, currently x86-64-sse41-popcnt"
730
- @echo "x86-64-ssse3 > x86 64-bit with ssse3 support"
731
- @echo "x86-64-sse3-popcnt > x86 64-bit with sse3 and popcnt support"
732
- @echo "x86-64 > x86 64-bit generic (with sse2 support)"
733
- @echo "x86-32-sse41-popcnt > x86 32-bit with sse41 and popcnt support"
734
- @echo "x86-32-sse2 > x86 32-bit with sse2 support"
735
- @echo "x86-32 > x86 32-bit generic (with mmx and sse support)"
736
- @echo "ppc-64 > PPC 64-bit"
737
- @echo "ppc-32 > PPC 32-bit"
738
- @echo "armv7 > ARMv7 32-bit"
739
- @echo "armv7-neon > ARMv7 32-bit with popcnt and neon"
740
- @echo "armv8 > ARMv8 64-bit with popcnt and neon"
741
- @echo "e2k > Elbrus 2000"
742
- @echo "apple-silicon > Apple silicon ARM64"
743
- @echo "general-64 > unspecified 64-bit"
744
- @echo "general-32 > unspecified 32-bit"
745
- @echo ""
746
- @echo "Supported compilers:"
747
- @echo ""
748
- @echo "gcc > Gnu compiler (default)"
749
- @echo "mingw > Gnu compiler with MinGW under Windows"
750
- @echo "clang > LLVM Clang compiler"
751
- @echo "icc > Intel compiler"
752
- @echo "ndk > Google NDK to cross-compile for Android"
753
- @echo ""
754
- @echo "Simple examples. If you don't know what to do, you likely want to run: "
755
- @echo ""
756
- @echo "make -j build ARCH=x86-64 (A portable, slow compile for 64-bit systems)"
757
- @echo "make -j build ARCH=x86-32 (A portable, slow compile for 32-bit systems)"
758
- @echo ""
759
- @echo "Advanced examples, for experienced users looking for performance: "
760
- @echo ""
761
- @echo "make help ARCH=x86-64-bmi2"
762
- @echo "make -j profile-build ARCH=x86-64-bmi2 COMP=gcc COMPCXX=g++-9.0"
763
- @echo "make -j build ARCH=x86-64-ssse3 COMP=clang"
764
- @echo ""
765
- @echo "-------------------------------"
766
- ifeq ($(SUPPORTED_ARCH)$(help_skip_sanity), true)
767
- @echo "The selected architecture $(ARCH) will enable the following configuration: "
768
- @$(MAKE) ARCH=$(ARCH) COMP=$(COMP) config-sanity
769
- else
770
- @echo "Specify a supported architecture with the ARCH option for more details"
771
- @echo ""
772
- @echo "-------------------------------"
773
- @echo "Embed and enable NNUE by default: "
774
- @echo ""
775
- @echo "make build ARCH=x86-64 nnue=yes"
776
- @echo ""
777
- @echo "-------------------------------"
778
- @echo "Version for large boards: "
779
- @echo ""
780
- @echo "make build ARCH=x86-64 COMP=gcc largeboards=yes"
781
- @echo ""
782
- @echo "Include all variants (adds Game of the Amazons): "
783
- @echo ""
784
- @echo "make build ARCH=x86-64 largeboards=yes all=yes"
785
- @echo ""
786
- endif
787
-
788
-
789
- .PHONY: help build profile-build strip install clean net objclean profileclean \
790
- config-sanity icc-profile-use icc-profile-make gcc-profile-use gcc-profile-make \
791
- clang-profile-use clang-profile-make
792
-
793
- build: $(load_net) config-sanity
794
- $(MAKE) ARCH=$(ARCH) COMP=$(COMP) all
795
-
796
- profile-build: $(load_net) config-sanity objclean profileclean
797
- @echo ""
798
- @echo "Step 1/4. Building instrumented executable ..."
799
- $(MAKE) ARCH=$(ARCH) COMP=$(COMP) $(profile_make)
800
- @echo ""
801
- @echo "Step 2/4. Running benchmark for pgo-build ..."
802
- $(PGOBENCH) > /dev/null
803
- @echo ""
804
- @echo "Step 3/4. Building optimized executable ..."
805
- $(MAKE) ARCH=$(ARCH) COMP=$(COMP) objclean
806
- $(MAKE) ARCH=$(ARCH) COMP=$(COMP) $(profile_use)
807
- @echo ""
808
- @echo "Step 4/4. Deleting profile data ..."
809
- $(MAKE) ARCH=$(ARCH) COMP=$(COMP) profileclean
810
-
811
- strip:
812
- $(STRIP) $(EXE)
813
-
814
- install:
815
- -mkdir -p -m 755 $(BINDIR)
816
- -cp $(EXE) $(BINDIR)
817
- -strip $(BINDIR)/$(EXE)
818
-
819
- # clean all
820
- clean: objclean profileclean
821
- @rm -f .depend *~ core
822
-
823
- # evaluation network (nnue)
824
- net:
825
- $(eval nnuenet := $(shell grep EvalFileDefaultName evaluate.h | grep define | sed 's/.*\(nn-[a-z0-9]\{12\}.nnue\).*/\1/'))
826
- @echo "Default net: $(nnuenet)"
827
- $(eval nnuedownloadurl1 := https://tests.stockfishchess.org/api/nn/$(nnuenet))
828
- $(eval nnuedownloadurl2 := https://github.com/official-stockfish/networks/raw/master/$(nnuenet))
829
- $(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))
830
- @if [ "x$(curl_or_wget)" = "x" ]; then \
831
- echo "Automatic download failed: neither curl nor wget is installed. Install one of these tools or download the net manually"; exit 1; \
832
- fi
833
- $(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))
834
- @if [ "x$(shasum_command)" = "x" ]; then \
835
- echo "shasum / sha256sum not found, skipping net validation"; \
836
- fi
837
- @for nnuedownloadurl in "$(nnuedownloadurl1)" "$(nnuedownloadurl2)"; do \
838
- if test -f "$(nnuenet)"; then \
839
- echo "$(nnuenet) available."; \
840
- else \
841
- if [ "x$(curl_or_wget)" != "x" ]; then \
842
- echo "Downloading $${nnuedownloadurl}"; $(curl_or_wget) $${nnuedownloadurl} > $(nnuenet);\
843
- fi; \
844
- fi; \
845
- if [ "x$(shasum_command)" != "x" ]; then \
846
- if [ "$(nnuenet)" != "nn-"`$(shasum_command) $(nnuenet) | cut -c1-12`".nnue" ]; then \
847
- echo "Removing failed download"; rm -f $(nnuenet); \
848
- else \
849
- echo "Network validated"; break; \
850
- fi; \
851
- fi; \
852
- done
853
- @if ! test -f "$(nnuenet)"; then \
854
- echo "Failed to download $(nnuenet)."; \
855
- fi
856
-
857
- # clean binaries and objects
858
- objclean:
859
- @rm -f $(EXE) *.o ./syzygy/*.o ./nnue/*.o ./nnue/features/*.o
860
-
861
- # clean auxiliary profiling files
862
- profileclean:
863
- @rm -rf profdir
864
- @rm -f bench.txt *.gcda *.gcno ./syzygy/*.gcda ./nnue/*.gcda ./nnue/features/*.gcda *.s
865
- @rm -f stockfish.profdata *.profraw
866
- @rm -f stockfish.exe.lto_wrapper_args
867
- @rm -f stockfish.exe.ltrans.out
868
- @rm -f ./-lstdc++.res
869
-
870
- default:
871
- help
872
-
873
- ### ==========================================================================
874
- ### Section 5. Private Targets
875
- ### ==========================================================================
876
-
877
- all: $(EXE) .depend
878
-
879
- config-sanity: $(load_net)
880
- @echo ""
881
- @echo "Config:"
882
- @echo "debug: '$(debug)'"
883
- @echo "sanitize: '$(sanitize)'"
884
- @echo "optimize: '$(optimize)'"
885
- @echo "arch: '$(arch)'"
886
- @echo "bits: '$(bits)'"
887
- @echo "kernel: '$(KERNEL)'"
888
- @echo "os: '$(OS)'"
889
- @echo "prefetch: '$(prefetch)'"
890
- @echo "popcnt: '$(popcnt)'"
891
- @echo "pext: '$(pext)'"
892
- @echo "sse: '$(sse)'"
893
- @echo "mmx: '$(mmx)'"
894
- @echo "sse2: '$(sse2)'"
895
- @echo "ssse3: '$(ssse3)'"
896
- @echo "sse41: '$(sse41)'"
897
- @echo "avx2: '$(avx2)'"
898
- @echo "avx512: '$(avx512)'"
899
- @echo "vnni256: '$(vnni256)'"
900
- @echo "vnni512: '$(vnni512)'"
901
- @echo "neon: '$(neon)'"
902
- @echo ""
903
- @echo "Fairy-Stockfish specific:"
904
- @echo "largeboards: '$(largeboards)'"
905
- @echo "all: '$(all)'"
906
- @echo "precomputedmagics: '$(precomputedmagics)'"
907
- @echo "nnue: '$(nnue)'"
908
- @echo ""
909
- @echo "Flags:"
910
- @echo "CXX: $(CXX)"
911
- @echo "CXXFLAGS: $(CXXFLAGS)"
912
- @echo "LDFLAGS: $(LDFLAGS)"
913
- @echo ""
914
- @echo "Testing config sanity. If this fails, try 'make help' ..."
915
- @echo ""
916
- @test "$(debug)" = "yes" || test "$(debug)" = "no"
917
- @test "$(optimize)" = "yes" || test "$(optimize)" = "no"
918
- @test "$(SUPPORTED_ARCH)" = "true"
919
- @test "$(arch)" = "any" || test "$(arch)" = "x86_64" || test "$(arch)" = "i386" || \
920
- test "$(arch)" = "ppc64" || test "$(arch)" = "ppc" || test "$(arch)" = "e2k" || \
921
- test "$(arch)" = "armv7" || test "$(arch)" = "armv8" || test "$(arch)" = "arm64"
922
- @test "$(bits)" = "32" || test "$(bits)" = "64"
923
- @test "$(prefetch)" = "yes" || test "$(prefetch)" = "no"
924
- @test "$(popcnt)" = "yes" || test "$(popcnt)" = "no"
925
- @test "$(pext)" = "yes" || test "$(pext)" = "no"
926
- @test "$(sse)" = "yes" || test "$(sse)" = "no"
927
- @test "$(mmx)" = "yes" || test "$(mmx)" = "no"
928
- @test "$(sse2)" = "yes" || test "$(sse2)" = "no"
929
- @test "$(ssse3)" = "yes" || test "$(ssse3)" = "no"
930
- @test "$(sse41)" = "yes" || test "$(sse41)" = "no"
931
- @test "$(avx2)" = "yes" || test "$(avx2)" = "no"
932
- @test "$(avx512)" = "yes" || test "$(avx512)" = "no"
933
- @test "$(vnni256)" = "yes" || test "$(vnni256)" = "no"
934
- @test "$(vnni512)" = "yes" || test "$(vnni512)" = "no"
935
- @test "$(neon)" = "yes" || test "$(neon)" = "no"
936
- @test "$(comp)" = "gcc" || test "$(comp)" = "icc" || test "$(comp)" = "mingw" || test "$(comp)" = "clang" \
937
- || test "$(comp)" = "armv7a-linux-androideabi16-clang" || test "$(comp)" = "aarch64-linux-android21-clang"
938
-
939
- $(EXE): $(OBJS)
940
- +$(CXX) -o $@ $(OBJS) $(LDFLAGS)
941
-
942
- clang-profile-make:
943
- $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
944
- EXTRACXXFLAGS='-fprofile-instr-generate ' \
945
- EXTRALDFLAGS=' -fprofile-instr-generate' \
946
- all
947
-
948
- clang-profile-use:
949
- $(XCRUN) llvm-profdata merge -output=stockfish.profdata *.profraw
950
- $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
951
- EXTRACXXFLAGS='-fprofile-instr-use=stockfish.profdata' \
952
- EXTRALDFLAGS='-fprofile-use ' \
953
- all
954
-
955
- gcc-profile-make:
956
- @mkdir -p profdir
957
- $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
958
- EXTRACXXFLAGS='-fprofile-generate=profdir' \
959
- EXTRALDFLAGS='-lgcov' \
960
- all
961
-
962
- gcc-profile-use:
963
- $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
964
- EXTRACXXFLAGS='-fprofile-use=profdir -fno-peel-loops -fno-tracer' \
965
- EXTRALDFLAGS='-lgcov' \
966
- all
967
-
968
- icc-profile-make:
969
- @mkdir -p profdir
970
- $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
971
- EXTRACXXFLAGS='-prof-gen=srcpos -prof_dir ./profdir' \
972
- all
973
-
974
- icc-profile-use:
975
- $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
976
- EXTRACXXFLAGS='-prof_use -prof_dir ./profdir' \
977
- all
978
-
979
- .depend:
980
- -@$(CXX) $(DEPENDFLAGS) -MM $(SRCS) > $@ 2> /dev/null
981
-
982
- -include .depend
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/src/Makefile_js DELETED
@@ -1,95 +0,0 @@
1
- # ffish.js, a JavaScript chess variant library derived from Fairy-Stockfish
2
- # Copyright (C) 2022 Fabian Fichter, Johannes Czech
3
- #
4
- # ffish.js is free software: you can redistribute it and/or modify
5
- # it under the terms of the GNU General Public License as published by
6
- # the Free Software Foundation, either version 3 of the License, or
7
- # (at your option) any later version.
8
- #
9
- # ffish.js is distributed in the hope that it will be useful,
10
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- # GNU General Public License for more details.
13
- #
14
- # You should have received a copy of the GNU General Public License
15
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
-
17
- EXE = ../tests/js/ffish.js
18
-
19
- SRCS = ffishjs.cpp benchmark.cpp bitbase.cpp bitboard.cpp endgame.cpp evaluate.cpp \
20
- material.cpp misc.cpp movegen.cpp movepick.cpp pawns.cpp position.cpp psqt.cpp \
21
- search.cpp thread.cpp timeman.cpp tt.cpp uci.cpp ucioption.cpp tune.cpp syzygy/tbprobe.cpp \
22
- nnue/evaluate_nnue.cpp nnue/features/half_ka_v2.cpp \
23
- partner.cpp parser.cpp piece.cpp variant.cpp xboard.cpp \
24
- nnue/features/half_ka_v2_variants.cpp
25
-
26
- CXX=emcc
27
- CXXFLAGS += --bind -DNNUE_EMBEDDING_OFF -DNO_THREADS -std=c++17 -Wall
28
-
29
- largeboards = yes
30
- all = yes
31
- optimize = yes
32
- debug = no
33
-
34
- ### Debugging
35
- ifeq ($(debug),no)
36
- CXXFLAGS += -DNDEBUG -s ASSERTIONS=0 -s SAFE_HEAP=0
37
- else
38
- CXXFLAGS += -g -s ASSERTIONS=1 -s SAFE_HEAP=1
39
- endif
40
-
41
- ### Optimization
42
- ifeq ($(optimize),yes)
43
- CXXFLAGS += -O3
44
- endif
45
-
46
- # Compile version with support for large board variants
47
- # Use precomputed magics by default
48
- ifneq ($(largeboards),no)
49
- CXXFLAGS += -DLARGEBOARDS -DPRECOMPUTED_MAGICS -s TOTAL_MEMORY=32MB -s ALLOW_MEMORY_GROWTH=1 -s WASM_MEM_MAX=1GB
50
- endif
51
-
52
- # Enable all variants, even heavyweight ones like duck and amazons
53
- ifneq ($(all),no)
54
- CXXFLAGS += -DALLVARS
55
- endif
56
-
57
- ### Compile as ES6/ES2015 module
58
- ifeq ($(es6),yes)
59
- CXXFLAGS += -s ENVIRONMENT='web,worker' -s EXPORT_ES6=1 -s MODULARIZE=1 -s USE_ES6_IMPORT_META=0
60
- endif
61
-
62
- .PHONY: help objclean clean build deps test serve
63
-
64
- help:
65
- @echo ""
66
- @echo "To compile ffishjs, type: "
67
- @echo ""
68
- @echo "make -f Makefile_js build"
69
- @echo ""
70
- @echo "Supported targets:"
71
- @echo ""
72
- @echo "help > Display this help"
73
- @echo "build > Standard build"
74
- @echo "clean > Clean up"
75
- @echo "deps > Install runtime dependencies using npm"
76
- @echo "test > Run tests"
77
- @echo "serve > Run example server"
78
- @echo ""
79
-
80
- objclean:
81
- @rm -f $(EXE)
82
-
83
- clean: objclean
84
-
85
- build:
86
- $(CXX) $(CXXFLAGS) $(SRCS) -o $(EXE)
87
-
88
- deps:
89
- cd ../tests/js && npm install
90
-
91
- test: deps
92
- cd ../tests/js && npm test
93
-
94
- serve: deps
95
- cd ../tests/js && node index.js
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/src/apiutil.h DELETED
@@ -1,1165 +0,0 @@
1
- /*
2
- Fairy-Stockfish, a UCI chess variant playing engine derived from Stockfish
3
- Copyright (C) 2018-2022 Fabian Fichter
4
-
5
- Fairy-Stockfish is free software: you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation, either version 3 of the License, or
8
- (at your option) any later version.
9
-
10
- Fairy-Stockfish is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- You should have received a copy of the GNU General Public License
16
- along with this program. If not, see <http://www.gnu.org/licenses/>.
17
- */
18
-
19
- #ifndef APIUTIL_H_INCLUDED
20
- #define APIUTIL_H_INCLUDED
21
-
22
- #include <array>
23
- #include <vector>
24
- #include <string>
25
- #include <sstream>
26
- #include <cctype>
27
- #include <iostream>
28
- #include <math.h>
29
-
30
- #include "types.h"
31
- #include "position.h"
32
- #include "variant.h"
33
-
34
- namespace Stockfish {
35
-
36
- enum Notation {
37
- NOTATION_DEFAULT,
38
- // https://en.wikipedia.org/wiki/Algebraic_notation_(chess)
39
- NOTATION_SAN,
40
- NOTATION_LAN,
41
- // https://en.wikipedia.org/wiki/Shogi_notation#Western_notation
42
- NOTATION_SHOGI_HOSKING, // Examples: P76, S’34
43
- NOTATION_SHOGI_HODGES, // Examples: P-7f, S*3d
44
- NOTATION_SHOGI_HODGES_NUMBER, // Examples: P-76, S*34
45
- // http://www.janggi.pl/janggi-notation/
46
- NOTATION_JANGGI,
47
- // https://en.wikipedia.org/wiki/Xiangqi#Notation
48
- NOTATION_XIANGQI_WXF,
49
- // https://web.archive.org/web/20180817205956/http://bgsthai.com/2018/05/07/lawofthaichessc/
50
- NOTATION_THAI_SAN,
51
- NOTATION_THAI_LAN,
52
- };
53
-
54
- inline Notation default_notation(const Variant* v) {
55
- if (v->variantTemplate == "shogi")
56
- return NOTATION_SHOGI_HODGES_NUMBER;
57
- return NOTATION_SAN;
58
- }
59
-
60
- enum Termination {
61
- ONGOING,
62
- CHECKMATE,
63
- STALEMATE,
64
- INSUFFICIENT_MATERIAL,
65
- N_MOVE_RULE,
66
- N_FOLD_REPETITION,
67
- VARIANT_END,
68
- };
69
-
70
- const std::array<std::string, 12> THAI_FILES = {"ก", "ข", "ค", "ง", "จ", "ฉ", "ช", "ญ", "ต", "ถ", "ธ", "น"};
71
- const std::array<std::string, 12> THAI_RANKS = {"๑", "๒", "๓", "๔", "๕", "๖", "๗", "๘", "๙", "๑๐", "๑๑", "๑๒"};
72
-
73
- namespace SAN {
74
-
75
- enum Disambiguation {
76
- NO_DISAMBIGUATION,
77
- FILE_DISAMBIGUATION,
78
- RANK_DISAMBIGUATION,
79
- SQUARE_DISAMBIGUATION,
80
- };
81
-
82
- inline bool is_shogi(Notation n) {
83
- return n == NOTATION_SHOGI_HOSKING || n == NOTATION_SHOGI_HODGES || n == NOTATION_SHOGI_HODGES_NUMBER;
84
- }
85
-
86
- inline bool is_thai(Notation n) {
87
- return n == NOTATION_THAI_SAN || n == NOTATION_THAI_LAN;
88
- }
89
-
90
- // is there more than one file with a pair of pieces?
91
- inline bool multi_tandem(Bitboard b) {
92
- int tandems = 0;
93
- for (File f = FILE_A; f <= FILE_MAX; ++f)
94
- if (more_than_one(b & file_bb(f)))
95
- tandems++;
96
- return tandems >= 2;
97
- }
98
-
99
- inline std::string piece_to_thai_char(Piece pc, bool promoted) {
100
- switch(type_of(pc)) {
101
- case KING:
102
- return "ข";
103
- case KHON:
104
- return "ค";
105
- case FERS:
106
- return promoted ? "ง" : "ม็";
107
- case KNIGHT:
108
- return "ม";
109
- case ROOK:
110
- return "ร";
111
- case PAWN:
112
- return "บ";
113
- case AIWOK:
114
- return "ว";
115
- default:
116
- return "X";
117
- }
118
- }
119
-
120
- inline std::string piece(const Position& pos, Move m, Notation n) {
121
- Color us = pos.side_to_move();
122
- Square from = from_sq(m);
123
- Piece pc = pos.moved_piece(m);
124
- PieceType pt = type_of(pc);
125
- // Quiet pawn moves
126
- if ((n == NOTATION_SAN || n == NOTATION_LAN || n == NOTATION_THAI_SAN) && type_of(pc) == PAWN && type_of(m) != DROP)
127
- return "";
128
- // Tandem pawns
129
- else if (n == NOTATION_XIANGQI_WXF && popcount(pos.pieces(us, pt) & file_bb(from)) >= 3 - multi_tandem(pos.pieces(us, pt)))
130
- return std::to_string(popcount(forward_file_bb(us, from) & pos.pieces(us, pt)) + 1);
131
- // Moves of promoted pieces
132
- else if (is_shogi(n) && type_of(m) != DROP && pos.unpromoted_piece_on(from))
133
- return "+" + std::string(1, toupper(pos.piece_to_char()[pos.unpromoted_piece_on(from)]));
134
- // Promoted drops
135
- else if (is_shogi(n) && type_of(m) == DROP && dropped_piece_type(m) != in_hand_piece_type(m))
136
- return "+" + std::string(1, toupper(pos.piece_to_char()[in_hand_piece_type(m)]));
137
- else if (is_thai(n))
138
- return piece_to_thai_char(pc, pos.is_promoted(from));
139
- else if (pos.piece_to_char_synonyms()[pc] != ' ')
140
- return std::string(1, toupper(pos.piece_to_char_synonyms()[pc]));
141
- else
142
- return std::string(1, toupper(pos.piece_to_char()[pc]));
143
- }
144
-
145
- inline std::string file(const Position& pos, Square s, Notation n) {
146
- switch (n)
147
- {
148
- case NOTATION_SHOGI_HOSKING:
149
- case NOTATION_SHOGI_HODGES:
150
- case NOTATION_SHOGI_HODGES_NUMBER:
151
- return std::to_string(pos.max_file() - file_of(s) + 1);
152
- case NOTATION_JANGGI:
153
- return std::to_string(file_of(s) + 1);
154
- case NOTATION_XIANGQI_WXF:
155
- return std::to_string((pos.side_to_move() == WHITE ? pos.max_file() - file_of(s) : file_of(s)) + 1);
156
- case NOTATION_THAI_SAN:
157
- case NOTATION_THAI_LAN:
158
- return THAI_FILES[file_of(s)];
159
- default:
160
- return std::string(1, char('a' + file_of(s)));
161
- }
162
- }
163
-
164
- inline std::string rank(const Position& pos, Square s, Notation n) {
165
- switch (n)
166
- {
167
- case NOTATION_SHOGI_HOSKING:
168
- case NOTATION_SHOGI_HODGES_NUMBER:
169
- return std::to_string(pos.max_rank() - rank_of(s) + 1);
170
- case NOTATION_SHOGI_HODGES:
171
- return std::string(1, char('a' + pos.max_rank() - rank_of(s)));
172
- case NOTATION_JANGGI:
173
- return std::to_string((pos.max_rank() - rank_of(s) + 1) % 10);
174
- case NOTATION_XIANGQI_WXF:
175
- {
176
- if (pos.empty(s))
177
- // Handle piece drops
178
- return std::to_string(relative_rank(pos.side_to_move(), s, pos.max_rank()) + 1);
179
- else if (pos.pieces(pos.side_to_move(), type_of(pos.piece_on(s))) & forward_file_bb(pos.side_to_move(), s))
180
- return "-";
181
- else
182
- return "+";
183
- }
184
- case NOTATION_THAI_SAN:
185
- case NOTATION_THAI_LAN:
186
- return THAI_RANKS[rank_of(s)];
187
- default:
188
- return std::to_string(rank_of(s) + 1);
189
- }
190
- }
191
-
192
- inline std::string square(const Position& pos, Square s, Notation n) {
193
- switch (n)
194
- {
195
- case NOTATION_JANGGI:
196
- return rank(pos, s, n) + file(pos, s, n);
197
- default:
198
- return file(pos, s, n) + rank(pos, s, n);
199
- }
200
- }
201
-
202
- inline Disambiguation disambiguation_level(const Position& pos, Move m, Notation n) {
203
- // Drops never need disambiguation
204
- if (type_of(m) == DROP)
205
- return NO_DISAMBIGUATION;
206
-
207
- // NOTATION_LAN and Janggi always use disambiguation
208
- if (n == NOTATION_LAN || n == NOTATION_THAI_LAN || n == NOTATION_JANGGI)
209
- return SQUARE_DISAMBIGUATION;
210
-
211
- Color us = pos.side_to_move();
212
- Square from = from_sq(m);
213
- Square to = to_sq(m);
214
- Piece pc = pos.moved_piece(m);
215
- PieceType pt = type_of(pc);
216
-
217
- // Xiangqi uses either file disambiguation or +/- if two pieces on file
218
- if (n == NOTATION_XIANGQI_WXF)
219
- {
220
- // Disambiguate by rank (+/-) if target square of other piece is valid
221
- if (popcount(pos.pieces(us, pt) & file_bb(from)) == 2 && !multi_tandem(pos.pieces(us, pt)))
222
- {
223
- Square otherFrom = lsb((pos.pieces(us, pt) & file_bb(from)) ^ from);
224
- Square otherTo = otherFrom + Direction(to) - Direction(from);
225
- if (is_ok(otherTo) && (pos.board_bb(us, pt) & otherTo))
226
- return RANK_DISAMBIGUATION;
227
- }
228
- return FILE_DISAMBIGUATION;
229
- }
230
-
231
- // Pawn captures always use disambiguation
232
- if ((n == NOTATION_SAN || n == NOTATION_THAI_SAN) && pt == PAWN)
233
- {
234
- if (pos.capture(m))
235
- return FILE_DISAMBIGUATION;
236
- if (type_of(m) == PROMOTION && from != to && pos.sittuyin_promotion())
237
- return SQUARE_DISAMBIGUATION;
238
- }
239
-
240
- // A disambiguation occurs if we have more than one piece of type 'pt'
241
- // that can reach 'to' with a legal move.
242
- Bitboard b = pos.pieces(us, pt) ^ from;
243
- Bitboard others = 0;
244
-
245
- while (b)
246
- {
247
- Square s = pop_lsb(b);
248
- // Construct a potential move with identical special move flags
249
- // and only a different "from" square.
250
- Move testMove = Move(m ^ make_move(from, to) ^ make_move(s, to));
251
- if ( pos.pseudo_legal(testMove)
252
- && pos.legal(testMove)
253
- && !(is_shogi(n) && pos.unpromoted_piece_on(s) != pos.unpromoted_piece_on(from)))
254
- others |= s;
255
- }
256
-
257
- if (!others)
258
- return NO_DISAMBIGUATION;
259
- else if (is_shogi(n))
260
- return SQUARE_DISAMBIGUATION;
261
- else if (!(others & file_bb(from)))
262
- return FILE_DISAMBIGUATION;
263
- else if (!(others & rank_bb(from)))
264
- return RANK_DISAMBIGUATION;
265
- else
266
- return SQUARE_DISAMBIGUATION;
267
- }
268
-
269
- inline std::string disambiguation(const Position& pos, Square s, Notation n, Disambiguation d) {
270
- switch (d)
271
- {
272
- case FILE_DISAMBIGUATION:
273
- return file(pos, s, n);
274
- case RANK_DISAMBIGUATION:
275
- return rank(pos, s, n);
276
- case SQUARE_DISAMBIGUATION:
277
- return square(pos, s, n);
278
- default:
279
- assert(d == NO_DISAMBIGUATION);
280
- return "";
281
- }
282
- }
283
-
284
- inline const std::string move_to_san(Position& pos, Move m, Notation n) {
285
- std::string san = "";
286
- Color us = pos.side_to_move();
287
- Square from = from_sq(m);
288
- Square to = to_sq(m);
289
-
290
- if (type_of(m) == CASTLING)
291
- {
292
- san = to > from ? "O-O" : "O-O-O";
293
-
294
- if (is_gating(m))
295
- {
296
- san += std::string("/") + (char)toupper(pos.piece_to_char()[make_piece(us, gating_type(m))]);
297
- san += square(pos, gating_square(m), n);
298
- }
299
- }
300
- else
301
- {
302
- // Piece
303
- san += piece(pos, m, n);
304
-
305
- if (n == NOTATION_THAI_LAN)
306
- san += " ";
307
-
308
- // Origin square, disambiguation
309
- Disambiguation d = disambiguation_level(pos, m, n);
310
- san += disambiguation(pos, from, n, d);
311
-
312
- // Separator/Operator
313
- if (type_of(m) == DROP)
314
- san += n == NOTATION_SHOGI_HOSKING ? '\'' : is_shogi(n) ? '*' : '@';
315
- else if (n == NOTATION_XIANGQI_WXF)
316
- {
317
- if (rank_of(from) == rank_of(to))
318
- san += '=';
319
- else if (relative_rank(us, to, pos.max_rank()) > relative_rank(us, from, pos.max_rank()))
320
- san += '+';
321
- else
322
- san += '-';
323
- }
324
- else if (pos.capture(m))
325
- san += 'x';
326
- 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))
327
- san += '-';
328
-
329
- // Destination square
330
- if (n == NOTATION_XIANGQI_WXF && type_of(m) != DROP)
331
- san += file_of(to) == file_of(from) ? std::to_string(std::abs(rank_of(to) - rank_of(from))) : file(pos, to, n);
332
- else
333
- san += square(pos, to, n);
334
-
335
- // Suffix
336
- if (type_of(m) == PROMOTION)
337
- san += std::string("=") + (char)toupper(pos.piece_to_char()[make_piece(us, promotion_type(m))]);
338
- else if (type_of(m) == PIECE_PROMOTION)
339
- 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))))]);
340
- else if (type_of(m) == PIECE_DEMOTION)
341
- san += is_shogi(n) ? std::string("-") : std::string("=") + std::string(1, toupper(pos.piece_to_char()[pos.unpromoted_piece_on(from)]));
342
- else if (type_of(m) == NORMAL && is_shogi(n) && pos.pseudo_legal(make<PIECE_PROMOTION>(from, to)))
343
- san += std::string("=");
344
- if (is_gating(m))
345
- san += std::string("/") + (char)toupper(pos.piece_to_char()[make_piece(us, gating_type(m))]);
346
- }
347
-
348
- // Wall square
349
- if (pos.walling())
350
- san += "," + square(pos, gating_square(m), n);
351
-
352
- // Check and checkmate
353
- if (pos.gives_check(m) && !is_shogi(n) && n != NOTATION_XIANGQI_WXF)
354
- {
355
- StateInfo st;
356
- pos.do_move(m, st);
357
- san += MoveList<LEGAL>(pos).size() ? "+" : "#";
358
- pos.undo_move(m);
359
- }
360
-
361
- return san;
362
- }
363
-
364
- } // namespace SAN
365
-
366
- inline bool has_insufficient_material(Color c, const Position& pos) {
367
-
368
- // Other win rules
369
- if ( pos.captures_to_hand()
370
- || pos.count_in_hand(c, ALL_PIECES)
371
- || (pos.extinction_value() != VALUE_NONE && !pos.extinction_pseudo_royal())
372
- || (pos.variant()->nFoldRule && pos.variant()->nFoldValue != VALUE_DRAW)
373
- || (pos.flag_region(c) && pos.count(c, pos.flag_piece(c))))
374
- return false;
375
-
376
- // Precalculate if any promotion pawn types have pieces
377
- bool hasPromotingPawn = false;
378
- for (PieceSet pawnTypes = pos.promotion_pawn_types(c); pawnTypes; )
379
- {
380
- PieceType pawnType = pop_lsb(pawnTypes);
381
- if (pos.count(c, pawnType) > 0)
382
- {
383
- hasPromotingPawn = true;
384
- break;
385
- }
386
- }
387
-
388
- // Determine checkmating potential of present pieces
389
- constexpr PieceSet MAJOR_PIECES = piece_set(ROOK) | QUEEN | ARCHBISHOP | CHANCELLOR
390
- | SILVER | GOLD | COMMONER | CENTAUR | AMAZON | BERS;
391
- constexpr PieceSet COLORBOUND_PIECES = piece_set(BISHOP) | FERS | FERS_ALFIL | ALFIL | ELEPHANT;
392
- Bitboard restricted = pos.pieces(KING);
393
- Bitboard colorbound = 0;
394
- for (PieceSet ps = pos.piece_types(); ps;)
395
- {
396
- PieceType pt = pop_lsb(ps);
397
-
398
- // Constrained pieces
399
- 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)))
400
- restricted |= pos.pieces(c, pt);
401
-
402
- // If piece is a major piece or a custom piece we consider it sufficient for mate.
403
- // To avoid false positives, we assume any custom piece has mating potential.
404
- else if ((MAJOR_PIECES & pt) || is_custom(pt))
405
- {
406
- // Check if piece is already on the board
407
- if (pos.count(c, pt) > 0)
408
- return false;
409
-
410
- // Check if any pawn can promote to this piece type
411
- if (hasPromotingPawn && (pos.promotion_piece_types(c) & pt))
412
- return false;
413
- }
414
-
415
- // Collect color-bound pieces
416
- else if (COLORBOUND_PIECES & pt)
417
- colorbound |= pos.pieces(pt);
418
- }
419
-
420
- Bitboard unbound = pos.pieces() ^ restricted ^ colorbound;
421
-
422
- // Color-bound pieces
423
- if ((colorbound & pos.pieces(c)) && (((DarkSquares & colorbound) && (~DarkSquares & colorbound)) || unbound || pos.stalemate_value() != VALUE_DRAW || pos.check_counting() || pos.makpong()))
424
- return false;
425
-
426
- // Unbound pieces require one helper piece of either color
427
- if ((pos.pieces(c) & unbound) && (popcount(pos.pieces() ^ restricted) >= 2 || pos.stalemate_value() != VALUE_DRAW || pos.check_counting() || pos.makpong()))
428
- return false;
429
-
430
- // Non-draw stalemate with lone custom king
431
- if ( pos.stalemate_value() != VALUE_DRAW && pos.king_type() != KING
432
- && pos.pieces(c, KING) && (pos.board_bb(c, KING) & pos.board_bb(~c, KING)))
433
- return false;
434
-
435
- return true;
436
- }
437
-
438
- inline Bitboard checked(const Position& pos) {
439
- return (pos.checkers() ? square_bb(pos.square<KING>(pos.side_to_move())) : Bitboard(0))
440
- | (pos.extinction_pseudo_royal() ? pos.checked_pseudo_royals(pos.side_to_move()) : Bitboard(0));
441
- }
442
-
443
- namespace FEN {
444
-
445
- enum FenValidation : int {
446
- FEN_INVALID_COUNTING_RULE = -14,
447
- FEN_INVALID_CHECK_COUNT = -13,
448
- FEN_INVALID_PROMOTED_PIECE = -12,
449
- FEN_INVALID_NB_PARTS = -11,
450
- FEN_INVALID_CHAR = -10,
451
- FEN_TOUCHING_KINGS = -9,
452
- FEN_INVALID_BOARD_GEOMETRY = -8,
453
- FEN_INVALID_POCKET_INFO = -7,
454
- FEN_INVALID_SIDE_TO_MOVE = -6,
455
- FEN_INVALID_CASTLING_INFO = -5,
456
- FEN_INVALID_EN_PASSANT_SQ = -4,
457
- FEN_INVALID_NUMBER_OF_KINGS = -3,
458
- FEN_INVALID_HALF_MOVE_COUNTER = -2,
459
- FEN_INVALID_MOVE_COUNTER = -1,
460
- FEN_EMPTY = 0,
461
- FEN_OK = 1
462
- };
463
- enum Validation : int {
464
- NOK,
465
- OK
466
- };
467
-
468
- struct CharSquare {
469
- int rowIdx;
470
- int fileIdx;
471
- CharSquare() : rowIdx(-1), fileIdx(-1) {}
472
- CharSquare(int row, int file) : rowIdx(row), fileIdx(file) {}
473
- };
474
-
475
- inline bool operator==(const CharSquare& s1, const CharSquare& s2) {
476
- return s1.rowIdx == s2.rowIdx && s1.fileIdx == s2.fileIdx;
477
- }
478
-
479
- inline bool operator!=(const CharSquare& s1, const CharSquare& s2) {
480
- return !(s1 == s2);
481
- }
482
-
483
- inline int non_root_euclidian_distance(const CharSquare& s1, const CharSquare& s2) {
484
- return pow(s1.rowIdx - s2.rowIdx, 2) + pow(s1.fileIdx - s2.fileIdx, 2);
485
- }
486
-
487
- class CharBoard {
488
- private:
489
- int nbRanks;
490
- int nbFiles;
491
- std::vector<char> board; // fill an array where the pieces are for later geometry checks
492
- public:
493
- CharBoard(int ranks, int files) : nbRanks(ranks), nbFiles(files) {
494
- assert(nbFiles > 0 && nbRanks > 0);
495
- board = std::vector<char>(nbRanks * nbFiles, ' ');
496
- }
497
- void set_piece(int rankIdx, int fileIdx, char c) {
498
- board[rankIdx * nbFiles + fileIdx] = c;
499
- }
500
- char get_piece(int rowIdx, int fileIdx) const {
501
- return board[rowIdx * nbFiles + fileIdx];
502
- }
503
- int get_nb_ranks() const {
504
- return nbRanks;
505
- }
506
- int get_nb_files() const {
507
- return nbFiles;
508
- }
509
- /// Returns the square of a given character
510
- CharSquare get_square_for_piece(char piece) const {
511
- CharSquare s;
512
- for (int r = 0; r < nbRanks; ++r)
513
- {
514
- for (int c = 0; c < nbFiles; ++c)
515
- {
516
- if (get_piece(r, c) == piece)
517
- {
518
- s.rowIdx = r;
519
- s.fileIdx = c;
520
- return s;
521
- }
522
- }
523
- }
524
- return s;
525
- }
526
- /// Returns all square positions for a given piece
527
- std::vector<CharSquare> get_squares_for_pieces(Color color, PieceSet ps, const std::string& pieceChars) const {
528
- std::vector<CharSquare> squares;
529
- size_t pcIdx;
530
- for (int r = 0; r < nbRanks; ++r)
531
- for (int c = 0; c < nbFiles; ++c)
532
- if ((pcIdx = pieceChars.find(get_piece(r, c))) != std::string::npos && (ps & type_of(Piece(pcIdx))) && color_of(Piece(pcIdx)) == color)
533
- squares.emplace_back(CharSquare(r, c));
534
- return squares;
535
- }
536
- friend std::ostream& operator<<(std::ostream& os, const CharBoard& board);
537
- };
538
-
539
- inline std::ostream& operator<<(std::ostream& os, const CharBoard& board) {
540
- for (int r = 0; r < board.nbRanks; ++r)
541
- {
542
- for (int c = 0; c < board.nbFiles; ++c)
543
- os << "[" << board.get_piece(r, c) << "] ";
544
- os << std::endl;
545
- }
546
- return os;
547
- }
548
-
549
- inline bool contains(const std::string& str, char c) {
550
- return str.find(c) != std::string::npos;
551
- }
552
-
553
- inline bool in_any(const std::vector<std::string>& vec, char c) {
554
- for (std::string str : vec)
555
- if (contains(str, c))
556
- return true;
557
- return false;
558
- }
559
-
560
- inline Validation check_for_valid_characters(const std::string& firstFenPart, const std::string& validSpecialCharactersFirstField, const Variant* v) {
561
- for (char c : firstFenPart)
562
- {
563
- if (!isdigit(c) && !in_any({v->pieceToChar, v->pieceToCharSynonyms, validSpecialCharactersFirstField}, c))
564
- {
565
- std::cerr << "Invalid piece character: '" << c << "'." << std::endl;
566
- return NOK;
567
- }
568
- }
569
- return OK;
570
- }
571
-
572
- inline Validation check_promoted_pieces(const std::string& firstFenPart, const Variant* v) {
573
- // Only check promoted pieces if the variant supports shogi-style promotions
574
- if (!v || !v->shogiStylePromotions)
575
- return OK;
576
-
577
- for (size_t i = 0; i < firstFenPart.length() - 1; ++i) {
578
- // Look for promoted pieces ('+' followed by piece character)
579
- if (firstFenPart[i] == '+') {
580
- char pieceChar = firstFenPart[i + 1];
581
-
582
- // Skip if next character is not a piece character or is a special character
583
- if (isdigit(pieceChar) || pieceChar == '/' || pieceChar == ' ' || pieceChar == '[')
584
- continue;
585
-
586
- // Find the piece type corresponding to this character
587
- size_t idx = v->pieceToChar.find(pieceChar);
588
- if (idx == std::string::npos) {
589
- // Try synonyms
590
- idx = v->pieceToCharSynonyms.find(pieceChar);
591
- if (idx == std::string::npos)
592
- continue; // Character validation will catch this
593
- }
594
-
595
- // Ensure idx is within valid range for piece types
596
- if (idx >= PIECE_TYPE_NB)
597
- continue;
598
-
599
- // Get the piece type directly from the index
600
- PieceType pt = PieceType(idx);
601
-
602
- // Check if this piece type has a promoted form
603
- if (pt != NO_PIECE_TYPE && pt < PIECE_TYPE_NB && v->promotedPieceType[pt] == NO_PIECE_TYPE) {
604
- std::cerr << "Invalid promoted piece: '+' followed by '" << pieceChar
605
- << "'. This piece cannot be promoted in variant." << std::endl;
606
- return NOK;
607
- }
608
- }
609
- }
610
- return OK;
611
- }
612
-
613
- inline std::vector<std::string> get_fen_parts(const std::string& fullFen, char delim) {
614
- std::vector<std::string> fenParts;
615
- std::string curPart;
616
- std::stringstream ss(fullFen);
617
- while (std::getline(ss, curPart, delim))
618
- fenParts.emplace_back(curPart);
619
- return fenParts;
620
- }
621
-
622
- /// fills the character board according to a given FEN string
623
- inline Validation fill_char_board(CharBoard& board, const std::string& fenBoard, const std::string& validSpecialCharactersFirstField, const Variant* v) {
624
- int rankIdx = 0;
625
- int fileIdx = 0;
626
-
627
- char prevChar = '?';
628
- for (char c : fenBoard)
629
- {
630
- if (c == ' ' || c == '[')
631
- break;
632
- if (c == '*')
633
- ++fileIdx;
634
- else if (isdigit(c))
635
- {
636
- fileIdx += c - '0';
637
- // if we have multiple digits attached we can add multiples of 9 to compute the resulting number (e.g. -> 21 = 2 + 2 * 9 + 1)
638
- if (isdigit(prevChar))
639
- fileIdx += 9 * (prevChar - '0');
640
- }
641
- else if (c == '/')
642
- {
643
- ++rankIdx;
644
- if (fileIdx != board.get_nb_files())
645
- {
646
- std::cerr << "curRankWidth != nbFiles: " << fileIdx << " != " << board.get_nb_files() << std::endl;
647
- return NOK;
648
- }
649
- if (rankIdx == board.get_nb_ranks())
650
- break;
651
- fileIdx = 0;
652
- }
653
- else if (!contains(validSpecialCharactersFirstField, c))
654
- { // normal piece
655
- if (fileIdx == board.get_nb_files())
656
- {
657
- std::cerr << "File index: " << fileIdx << " for piece '" << c << "' exceeds maximum of allowed number of files: " << board.get_nb_files() << "." << std::endl;
658
- return NOK;
659
- }
660
- board.set_piece(v->maxRank-rankIdx, fileIdx, c); // we mirror the rank index because the black pieces are given first in the FEN
661
- ++fileIdx;
662
- }
663
- prevChar = c;
664
- }
665
-
666
- if (v->pieceDrops)
667
- { // pockets can either be defined by [] or /
668
- if (rankIdx+1 != board.get_nb_ranks() && rankIdx != board.get_nb_ranks())
669
- {
670
- std::cerr << "Invalid number of ranks. Expected: " << board.get_nb_ranks() << " Actual: " << rankIdx+1 << std::endl;
671
- return NOK;
672
- }
673
- }
674
- else
675
- {
676
- if (rankIdx+1 != board.get_nb_ranks())
677
- {
678
- std::cerr << "Invalid number of ranks. Expected: " << board.get_nb_ranks() << " Actual: " << rankIdx+1 << std::endl;
679
- return NOK;
680
- }
681
- }
682
- return OK;
683
- }
684
-
685
- inline Validation check_touching_kings(const CharBoard& board, const std::array<CharSquare, 2>& kingPositions) {
686
- if (non_root_euclidian_distance(kingPositions[WHITE], kingPositions[BLACK]) <= 2)
687
- {
688
- std::cerr << "King pieces are next to each other." << std::endl;
689
- std::cerr << board << std::endl;
690
- return NOK;
691
- }
692
- return OK;
693
- }
694
-
695
- inline Validation fill_castling_info_splitted(const std::string& castlingInfo, std::array<std::string, 2>& castlingInfoSplitted) {
696
- for (char c : castlingInfo)
697
- {
698
- if (c != '-')
699
- {
700
- if (!isalpha(c))
701
- {
702
- std::cerr << "Invalid castling specification: '" << c << "'." << std::endl;
703
- return NOK;
704
- }
705
- else if (isupper(c))
706
- castlingInfoSplitted[WHITE] += tolower(c);
707
- else
708
- castlingInfoSplitted[BLACK] += c;
709
- }
710
- }
711
- return OK;
712
- }
713
-
714
- inline std::string color_to_string(Color c) {
715
- switch (c)
716
- {
717
- case WHITE:
718
- return "WHITE";
719
- case BLACK:
720
- return "BLACK";
721
- case COLOR_NB:
722
- return "COLOR_NB";
723
- default:
724
- return "INVALID_COLOR";
725
- }
726
- }
727
-
728
- inline std::string castling_rights_to_string(CastlingRights castlingRights) {
729
- switch (castlingRights)
730
- {
731
- case KING_SIDE:
732
- return "KING_SIDE";
733
- case QUEEN_SIDE:
734
- return "QUEENS_SIDE";
735
- case WHITE_OO:
736
- return "WHITE_OO";
737
- case WHITE_OOO:
738
- return "WHITE_OOO";
739
- case BLACK_OO:
740
- return "BLACK_OO";
741
- case BLACK_OOO:
742
- return "BLACK_OOO";
743
- case WHITE_CASTLING:
744
- return "WHITE_CASTLING";
745
- case BLACK_CASTLING:
746
- return "BLACK_CASTLING";
747
- case ANY_CASTLING:
748
- return "ANY_CASTLING";
749
- case CASTLING_RIGHT_NB:
750
- return "CASTLING_RIGHT_NB";
751
- default:
752
- return "INVALID_CASTLING_RIGHTS";
753
- }
754
- }
755
-
756
- inline Validation check_castling_rank(const std::array<std::string, 2>& castlingInfoSplitted, const CharBoard& board,
757
- const std::array<CharSquare, 2>& kingPositions, const Variant* v) {
758
-
759
- for (Color c : {WHITE, BLACK})
760
- {
761
- const Rank castlingRank = relative_rank(c, v->castlingRank, v->maxRank);
762
- for (char castlingFlag : castlingInfoSplitted[c])
763
- {
764
- if (tolower(castlingFlag) == 'k' || tolower(castlingFlag) == 'q')
765
- {
766
- if (kingPositions[c].rowIdx != castlingRank)
767
- {
768
- std::cerr << "The " << color_to_string(c) << " king must be on rank " << castlingRank << " if castling is enabled for " << color_to_string(c) << "." << std::endl;
769
- return NOK;
770
- }
771
- bool kingside = tolower(castlingFlag) == 'k';
772
- bool castlingRook = false;
773
- size_t pcIdx;
774
- for (int f = kingside ? board.get_nb_files() - 1 : 0; f != kingPositions[c].fileIdx; kingside ? f-- : f++)
775
- if ( (pcIdx = v->pieceToChar.find(board.get_piece(castlingRank, f))) != std::string::npos
776
- && (v->castlingRookPieces[c] & type_of(Piece(pcIdx)))
777
- && color_of(Piece(pcIdx)) == c)
778
- {
779
- castlingRook = true;
780
- break;
781
- }
782
- if (!castlingRook)
783
- {
784
- std::cerr << "No castling rook for flag " << castlingFlag << std::endl;
785
- return NOK;
786
- }
787
- }
788
- else if (board.get_piece(castlingRank, tolower(castlingFlag) - 'a') == ' ')
789
- {
790
- std::cerr << "No gating piece for flag " << castlingFlag << std::endl;
791
- return NOK;
792
- }
793
- }
794
- }
795
- return OK;
796
- }
797
-
798
- inline Validation check_standard_castling(std::array<std::string, 2>& castlingInfoSplitted, const CharBoard& board,
799
- const std::array<CharSquare, 2>& kingPositions, const std::array<CharSquare, 2>& kingPositionsStart,
800
- const std::array<std::vector<CharSquare>, 2>& rookPositionsStart, const Variant* v) {
801
-
802
- for (Color c : {WHITE, BLACK})
803
- {
804
- if (castlingInfoSplitted[c].size() == 0)
805
- continue;
806
- if (kingPositions[c] != kingPositionsStart[c])
807
- {
808
- std::cerr << "The " << color_to_string(c) << " KING has moved. Castling is no longer valid for " << color_to_string(c) << "." << std::endl;
809
- return NOK;
810
- }
811
-
812
- for (CastlingRights castling: {KING_SIDE, QUEEN_SIDE})
813
- {
814
- CharSquare rookStartingSquare = castling == QUEEN_SIDE ? rookPositionsStart[c][0] : rookPositionsStart[c][1];
815
- char targetChar = castling == QUEEN_SIDE ? 'q' : 'k';
816
- size_t pcIdx;
817
- if (castlingInfoSplitted[c].find(targetChar) != std::string::npos)
818
- {
819
- if ( (pcIdx = v->pieceToChar.find(board.get_piece(rookStartingSquare.rowIdx, rookStartingSquare.fileIdx))) == std::string::npos
820
- || !(v->castlingRookPieces[c] & type_of(Piece(pcIdx)))
821
- || color_of(Piece(pcIdx)) != c)
822
- {
823
- std::cerr << "The " << color_to_string(c) << " ROOK on the "<< castling_rights_to_string(castling) << " has moved. "
824
- << castling_rights_to_string(castling) << " castling is no longer valid for " << color_to_string(c) << "." << std::endl;
825
- return NOK;
826
- }
827
- }
828
-
829
- }
830
- }
831
- return OK;
832
- }
833
-
834
- inline Validation check_pocket_info(const std::string& fenBoard, int nbRanks, const Variant* v, std::string& pocket) {
835
-
836
- char stopChar;
837
- int offset = 0;
838
- if (std::count(fenBoard.begin(), fenBoard.end(), '/') == nbRanks)
839
- {
840
- // look for last '/'
841
- stopChar = '/';
842
- }
843
- else if (std::count(fenBoard.begin(), fenBoard.end(), '[') == 1)
844
- {
845
- // pocket is defined as [ and ]
846
- stopChar = '[';
847
- offset = 1;
848
- if (*(fenBoard.end()-1) != ']')
849
- {
850
- std::cerr << "Pocket specification does not end with ']'." << std::endl;
851
- return NOK;
852
- }
853
- }
854
- else
855
- // allow to skip pocket
856
- return OK;
857
-
858
- // look for last '/'
859
- for (auto it = fenBoard.rbegin()+offset; it != fenBoard.rend(); ++it)
860
- {
861
- const char c = *it;
862
- if (c == stopChar)
863
- return OK;
864
- if (c != '-')
865
- {
866
- if (!in_any({v->pieceToChar, v->pieceToCharSynonyms}, c))
867
- {
868
- std::cerr << "Invalid pocket piece: '" << c << "'." << std::endl;
869
- return NOK;
870
- }
871
- else
872
- pocket += c;
873
- }
874
- }
875
- std::cerr << "Pocket piece closing character '" << stopChar << "' was not found." << std::endl;
876
- return NOK;
877
- }
878
-
879
- inline int piece_count(const std::string& fenBoard, Color c, PieceType pt, const Variant* v) {
880
- return std::count(fenBoard.begin(), fenBoard.end(), v->pieceToChar[make_piece(c, pt)]);
881
- }
882
-
883
- inline Validation check_number_of_kings(const std::string& fenBoard, const std::string& startFenBoard, const Variant* v) {
884
- int nbWhiteKings = piece_count(fenBoard, WHITE, KING, v);
885
- int nbBlackKings = piece_count(fenBoard, BLACK, KING, v);
886
- int nbWhiteKingsStart = piece_count(startFenBoard, WHITE, KING, v);
887
- int nbBlackKingsStart = piece_count(startFenBoard, BLACK, KING, v);
888
-
889
- if (nbWhiteKings > 1)
890
- {
891
- std::cerr << "Invalid number of white kings. Maximum: 1. Given: " << nbWhiteKings << std::endl;
892
- return NOK;
893
- }
894
- if (nbBlackKings > 1)
895
- {
896
- std::cerr << "Invalid number of black kings. Maximum: 1. Given: " << nbBlackKings << std::endl;
897
- return NOK;
898
- }
899
- if (nbWhiteKings != nbWhiteKingsStart)
900
- {
901
- std::cerr << "Invalid number of white kings. Expected: " << nbWhiteKingsStart << ". Given: " << nbWhiteKings << std::endl;
902
- return NOK;
903
- }
904
- if (nbBlackKings != nbBlackKingsStart)
905
- {
906
- std::cerr << "Invalid number of black kings. Expected: " << nbBlackKingsStart << ". Given: " << nbBlackKings << std::endl;
907
- return NOK;
908
- }
909
- return OK;
910
- }
911
-
912
-
913
- inline Validation check_en_passant_square(const std::string& enPassantInfo) {
914
- if (enPassantInfo.size() != 1 || enPassantInfo[0] != '-')
915
- {
916
- if (enPassantInfo.size() != 2)
917
- {
918
- std::cerr << "Invalid en-passant square '" << enPassantInfo << "'. Expects 2 characters. Actual: " << enPassantInfo.size() << " character(s)." << std::endl;
919
- return NOK;
920
- }
921
- if (!isalpha(enPassantInfo[0]))
922
- {
923
- std::cerr << "Invalid en-passant square '" << enPassantInfo << "'. Expects 1st character to be a letter." << std::endl;
924
- return NOK;
925
- }
926
- if (!isdigit(enPassantInfo[1]))
927
- {
928
- std::cerr << "Invalid en-passant square '" << enPassantInfo << "'. Expects 2nd character to be a digit." << std::endl;
929
- return NOK;
930
- }
931
- }
932
- return OK;
933
- }
934
-
935
-
936
- inline Validation check_check_count(const std::string& checkCountInfo) {
937
- if (checkCountInfo.size() != 3)
938
- {
939
- std::cerr << "Invalid check count '" << checkCountInfo << "'. Expects 3 characters. Actual: " << checkCountInfo.size() << " character(s)." << std::endl;
940
- return NOK;
941
- }
942
- if (!isdigit(checkCountInfo[0]))
943
- {
944
- std::cerr << "Invalid check count '" << checkCountInfo << "'. Expects 1st character to be a digit." << std::endl;
945
- return NOK;
946
- }
947
- if (!isdigit(checkCountInfo[2])) {
948
- std::cerr << "Invalid check count '" << checkCountInfo << "'. Expects 3rd character to be a digit." << std::endl;
949
- return NOK;
950
- }
951
- return OK;
952
- }
953
-
954
- inline Validation check_lichess_check_count(const std::string& checkCountInfo) {
955
- if (checkCountInfo.size() != 4)
956
- {
957
- std::cerr << "Invalid check count '" << checkCountInfo << "'. Expects 4 characters. Actual: " << checkCountInfo.size() << " character(s)." << std::endl;
958
- return NOK;
959
- }
960
- if (!isdigit(checkCountInfo[1]) || checkCountInfo[1] - '0' > 3)
961
- {
962
- std::cerr << "Invalid check count '" << checkCountInfo << "'. Expects 2nd character to be a digit up to 3." << std::endl;
963
- return NOK;
964
- }
965
- if (!isdigit(checkCountInfo[3]) || checkCountInfo[3] - '0' > 3) {
966
- std::cerr << "Invalid check count '" << checkCountInfo << "'. Expects 4th character to be a digit up to 3." << std::endl;
967
- return NOK;
968
- }
969
- return OK;
970
- }
971
-
972
- inline Validation check_digit_field(const std::string& field) {
973
- if (field.size() == 1 && field[0] == '-')
974
- return OK;
975
- for (char c : field)
976
- if (!isdigit(c))
977
- return NOK;
978
- return OK;
979
- }
980
-
981
- inline std::string get_valid_special_chars(const Variant* v) {
982
- std::string validSpecialCharactersFirstField = "/*";
983
- // Whether or not '-', '+', '~', '[', ']' are valid depends on the variant being played.
984
- if (v->shogiStylePromotions)
985
- validSpecialCharactersFirstField += '+';
986
- if (v->promotionPieceTypes[WHITE] || v->promotionPieceTypes[BLACK])
987
- validSpecialCharactersFirstField += '~';
988
- if (!v->freeDrops && (v->pieceDrops || v->seirawanGating))
989
- validSpecialCharactersFirstField += "[-]";
990
- return validSpecialCharactersFirstField;
991
- }
992
-
993
- inline FenValidation validate_fen(const std::string& fen, const Variant* v, bool chess960 = false) {
994
-
995
- const std::string validSpecialCharactersFirstField = get_valid_special_chars(v);
996
- // 0) Layout
997
- // check for empty fen
998
- if (fen.empty())
999
- {
1000
- std::cerr << "Fen is empty." << std::endl;
1001
- return FEN_EMPTY;
1002
- }
1003
-
1004
- std::vector<std::string> fenParts = get_fen_parts(fen, ' ');
1005
- std::vector<std::string> startFenParts = get_fen_parts(v->startFen, ' ');
1006
-
1007
- // check for number of parts
1008
- const unsigned int maxNumberFenParts = 6 + v->checkCounting;
1009
- if (fenParts.size() < 1 || fenParts.size() > maxNumberFenParts)
1010
- {
1011
- std::cerr << "Invalid number of fen parts. Expected: >= 1 and <= " << maxNumberFenParts
1012
- << " Actual: " << fenParts.size() << std::endl;
1013
- return FEN_INVALID_NB_PARTS;
1014
- }
1015
-
1016
- // 1) Part
1017
- // check for valid characters
1018
- if (check_for_valid_characters(fenParts[0], validSpecialCharactersFirstField, v) == NOK)
1019
- return FEN_INVALID_CHAR;
1020
-
1021
- // check for valid promoted pieces
1022
- if (check_promoted_pieces(fenParts[0], v) == NOK)
1023
- return FEN_INVALID_PROMOTED_PIECE;
1024
-
1025
- // check for number of ranks
1026
- const int nbRanks = v->maxRank + 1;
1027
- // check for number of files
1028
- const int nbFiles = v->maxFile + 1;
1029
- CharBoard board(nbRanks, nbFiles); // create a 2D character board for later geometry checks
1030
-
1031
- if (fill_char_board(board, fenParts[0], validSpecialCharactersFirstField, v) == NOK)
1032
- return FEN_INVALID_BOARD_GEOMETRY;
1033
-
1034
- // check for pocket
1035
- std::string pocket = "";
1036
- if (v->pieceDrops || v->seirawanGating)
1037
- {
1038
- if (check_pocket_info(fenParts[0], nbRanks, v, pocket) == NOK)
1039
- return FEN_INVALID_POCKET_INFO;
1040
- }
1041
-
1042
- // check for number of kings
1043
- if (v->pieceTypes & KING)
1044
- {
1045
- // we have a royal king in this variant,
1046
- // ensure that each side has exactly as many kings as in the starting position
1047
- // (variants like giveaway use the COMMONER piece type instead)
1048
- if (check_number_of_kings(fenParts[0], startFenParts[0], v) == NOK)
1049
- return FEN_INVALID_NUMBER_OF_KINGS;
1050
-
1051
- // check for touching kings if there are exactly two royal kings on the board (excluding pocket)
1052
- if ( v->kingType == KING
1053
- && piece_count(fenParts[0], WHITE, KING, v) - piece_count(pocket, WHITE, KING, v) == 1
1054
- && piece_count(fenParts[0], BLACK, KING, v) - piece_count(pocket, BLACK, KING, v) == 1)
1055
- {
1056
- std::array<CharSquare, 2> kingPositions;
1057
- kingPositions[WHITE] = board.get_square_for_piece(v->pieceToChar[make_piece(WHITE, KING)]);
1058
- kingPositions[BLACK] = board.get_square_for_piece(v->pieceToChar[make_piece(BLACK, KING)]);
1059
- if (check_touching_kings(board, kingPositions) == NOK)
1060
- return FEN_TOUCHING_KINGS;
1061
- }
1062
- }
1063
-
1064
- // 2) Part
1065
- // check side to move char
1066
- if (fenParts.size() >= 2 && fenParts[1][0] != 'w' && fenParts[1][0] != 'b')
1067
- {
1068
- std::cerr << "Invalid side to move specification: '" << fenParts[1][0] << "'." << std::endl;
1069
- return FEN_INVALID_SIDE_TO_MOVE;
1070
- }
1071
-
1072
- // Castling and en passant can be skipped
1073
- bool skipCastlingAndEp = fenParts.size() >= 4 && fenParts.size() <= 5 && isdigit(fenParts[2][0]);
1074
-
1075
- // 3) Part
1076
- // check castling rights
1077
- if (fenParts.size() >= 3 && !skipCastlingAndEp && v->castling)
1078
- {
1079
- std::array<std::string, 2> castlingInfoSplitted;
1080
- if (fill_castling_info_splitted(fenParts[2], castlingInfoSplitted) == NOK)
1081
- return FEN_INVALID_CASTLING_INFO;
1082
-
1083
- if (castlingInfoSplitted[WHITE].size() != 0 || castlingInfoSplitted[BLACK].size() != 0)
1084
- {
1085
- std::array<CharSquare, 2> kingPositions;
1086
- kingPositions[WHITE] = board.get_square_for_piece(toupper(v->pieceToChar[v->castlingKingPiece[WHITE]]));
1087
- kingPositions[BLACK] = board.get_square_for_piece(tolower(v->pieceToChar[v->castlingKingPiece[BLACK]]));
1088
-
1089
- CharBoard startBoard(board.get_nb_ranks(), board.get_nb_files());
1090
- fill_char_board(startBoard, v->startFen, validSpecialCharactersFirstField, v);
1091
-
1092
- // Check pieces present on castling rank against castling/gating rights
1093
- if (check_castling_rank(castlingInfoSplitted, board, kingPositions, v) == NOK)
1094
- return FEN_INVALID_CASTLING_INFO;
1095
-
1096
- // only check exact squares if starting position of castling pieces is known
1097
- if (!v->chess960 && !v->castlingDroppedPiece && !chess960)
1098
- {
1099
- std::array<CharSquare, 2> kingPositionsStart;
1100
- kingPositionsStart[WHITE] = startBoard.get_square_for_piece(v->pieceToChar[make_piece(WHITE, v->castlingKingPiece[WHITE])]);
1101
- kingPositionsStart[BLACK] = startBoard.get_square_for_piece(v->pieceToChar[make_piece(BLACK, v->castlingKingPiece[BLACK])]);
1102
- std::array<std::vector<CharSquare>, 2> rookPositionsStart;
1103
- rookPositionsStart[WHITE] = startBoard.get_squares_for_pieces(WHITE, v->castlingRookPieces[WHITE], v->pieceToChar);
1104
- rookPositionsStart[BLACK] = startBoard.get_squares_for_pieces(BLACK, v->castlingRookPieces[BLACK], v->pieceToChar);
1105
-
1106
- if (check_standard_castling(castlingInfoSplitted, board, kingPositions, kingPositionsStart, rookPositionsStart, v) == NOK)
1107
- return FEN_INVALID_CASTLING_INFO;
1108
- }
1109
- }
1110
- }
1111
-
1112
- // 4) Part
1113
- // check en-passant square
1114
- if (fenParts.size() >= 4 && !skipCastlingAndEp)
1115
- {
1116
- if (v->doubleStep && (v->pieceTypes & PAWN))
1117
- {
1118
- if (check_en_passant_square(fenParts[3]) == NOK)
1119
- return FEN_INVALID_EN_PASSANT_SQ;
1120
- }
1121
- else if (v->countingRule && !check_digit_field(fenParts[3]))
1122
- return FEN_INVALID_COUNTING_RULE;
1123
- }
1124
-
1125
- // 5) Part
1126
- // check check count
1127
- unsigned int optionalInbetweenFields = 2 * !skipCastlingAndEp;
1128
- unsigned int optionalTrailingFields = 0;
1129
- if (fenParts.size() >= 3 + optionalInbetweenFields && v->checkCounting && fenParts.size() % 2)
1130
- {
1131
- if (check_check_count(fenParts[2 + optionalInbetweenFields]) == NOK)
1132
- {
1133
- // allow valid lichess style check as alternative
1134
- if (fenParts.size() < 5 + optionalInbetweenFields || check_lichess_check_count(fenParts[fenParts.size() - 1]) == NOK)
1135
- return FEN_INVALID_CHECK_COUNT;
1136
- else
1137
- optionalTrailingFields++;
1138
- }
1139
- else
1140
- optionalInbetweenFields++;
1141
- }
1142
-
1143
- // 6) Part
1144
- // check half move counter
1145
- if (fenParts.size() >= 3 + optionalInbetweenFields && !check_digit_field(fenParts[fenParts.size() - 2 - optionalTrailingFields]))
1146
- {
1147
- std::cerr << "Invalid half move counter: '" << fenParts[fenParts.size()-2] << "'." << std::endl;
1148
- return FEN_INVALID_HALF_MOVE_COUNTER;
1149
- }
1150
-
1151
- // 7) Part
1152
- // check move counter
1153
- if (fenParts.size() >= 4 + optionalInbetweenFields && !check_digit_field(fenParts[fenParts.size() - 1 - optionalTrailingFields]))
1154
- {
1155
- std::cerr << "Invalid move counter: '" << fenParts[fenParts.size()-1] << "'." << std::endl;
1156
- return FEN_INVALID_MOVE_COUNTER;
1157
- }
1158
-
1159
- return FEN_OK;
1160
- }
1161
- } // namespace FEN
1162
-
1163
- } // namespace Stockfish
1164
-
1165
- #endif // #ifndef APIUTIL_H_INCLUDED
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/src/benchmark.cpp DELETED
@@ -1,195 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
4
-
5
- Stockfish is free software: you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation, either version 3 of the License, or
8
- (at your option) any later version.
9
-
10
- Stockfish is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- You should have received a copy of the GNU General Public License
16
- along with this program. If not, see <http://www.gnu.org/licenses/>.
17
- */
18
-
19
- #include <fstream>
20
- #include <iostream>
21
- #include <istream>
22
- #include <vector>
23
-
24
- #include "position.h"
25
- #include "uci.h"
26
-
27
- using namespace std;
28
-
29
- namespace {
30
-
31
- const vector<string> Defaults = {
32
- "setoption name UCI_Chess960 value false",
33
- "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
34
- "r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 10",
35
- "8/2p5/3p4/KP5r/1R3p1k/8/4P1P1/8 w - - 0 11",
36
- "4rrk1/pp1n3p/3q2pQ/2p1pb2/2PP4/2P3N1/P2B2PP/4RRK1 b - - 7 19",
37
- "rq3rk1/ppp2ppp/1bnpb3/3N2B1/3NP3/7P/PPPQ1PP1/2KR3R w - - 7 14 moves d4e6",
38
- "r1bq1r1k/1pp1n1pp/1p1p4/4p2Q/4Pp2/1BNP4/PPP2PPP/3R1RK1 w - - 2 14 moves g2g4",
39
- "r3r1k1/2p2ppp/p1p1bn2/8/1q2P3/2NPQN2/PPP3PP/R4RK1 b - - 2 15",
40
- "r1bbk1nr/pp3p1p/2n5/1N4p1/2Np1B2/8/PPP2PPP/2KR1B1R w kq - 0 13",
41
- "r1bq1rk1/ppp1nppp/4n3/3p3Q/3P4/1BP1B3/PP1N2PP/R4RK1 w - - 1 16",
42
- "4r1k1/r1q2ppp/ppp2n2/4P3/5Rb1/1N1BQ3/PPP3PP/R5K1 w - - 1 17",
43
- "2rqkb1r/ppp2p2/2npb1p1/1N1Nn2p/2P1PP2/8/PP2B1PP/R1BQK2R b KQ - 0 11",
44
- "r1bq1r1k/b1p1npp1/p2p3p/1p6/3PP3/1B2NN2/PP3PPP/R2Q1RK1 w - - 1 16",
45
- "3r1rk1/p5pp/bpp1pp2/8/q1PP1P2/b3P3/P2NQRPP/1R2B1K1 b - - 6 22",
46
- "r1q2rk1/2p1bppp/2Pp4/p6b/Q1PNp3/4B3/PP1R1PPP/2K4R w - - 2 18",
47
- "4k2r/1pb2ppp/1p2p3/1R1p4/3P4/2r1PN2/P4PPP/1R4K1 b - - 3 22",
48
- "3q2k1/pb3p1p/4pbp1/2r5/PpN2N2/1P2P2P/5PP1/Q2R2K1 b - - 4 26",
49
- "6k1/6p1/6Pp/ppp5/3pn2P/1P3K2/1PP2P2/3N4 b - - 0 1",
50
- "3b4/5kp1/1p1p1p1p/pP1PpP1P/P1P1P3/3KN3/8/8 w - - 0 1",
51
- "2K5/p7/7P/5pR1/8/5k2/r7/8 w - - 0 1 moves g5g6 f3e3 g6g5 e3f3",
52
- "8/6pk/1p6/8/PP3p1p/5P2/4KP1q/3Q4 w - - 0 1",
53
- "7k/3p2pp/4q3/8/4Q3/5Kp1/P6b/8 w - - 0 1",
54
- "8/2p5/8/2kPKp1p/2p4P/2P5/3P4/8 w - - 0 1",
55
- "8/1p3pp1/7p/5P1P/2k3P1/8/2K2P2/8 w - - 0 1",
56
- "8/pp2r1k1/2p1p3/3pP2p/1P1P1P1P/P5KR/8/8 w - - 0 1",
57
- "8/3p4/p1bk3p/Pp6/1Kp1PpPp/2P2P1P/2P5/5B2 b - - 0 1",
58
- "5k2/7R/4P2p/5K2/p1r2P1p/8/8/8 b - - 0 1",
59
- "6k1/6p1/P6p/r1N5/5p2/7P/1b3PP1/4R1K1 w - - 0 1",
60
- "1r3k2/4q3/2Pp3b/3Bp3/2Q2p2/1p1P2P1/1P2KP2/3N4 w - - 0 1",
61
- "6k1/4pp1p/3p2p1/P1pPb3/R7/1r2P1PP/3B1P2/6K1 w - - 0 1",
62
- "8/3p3B/5p2/5P2/p7/PP5b/k7/6K1 w - - 0 1",
63
- "5rk1/q6p/2p3bR/1pPp1rP1/1P1Pp3/P3B1Q1/1K3P2/R7 w - - 93 90",
64
- "4rrk1/1p1nq3/p7/2p1P1pp/3P2bp/3Q1Bn1/PPPB4/1K2R1NR w - - 40 21",
65
- "r3k2r/3nnpbp/q2pp1p1/p7/Pp1PPPP1/4BNN1/1P5P/R2Q1RK1 w kq - 0 16",
66
- "3Qb1k1/1r2ppb1/pN1n2q1/Pp1Pp1Pr/4P2p/4BP2/4B1R1/1R5K b - - 11 40",
67
- "4k3/3q1r2/1N2r1b1/3ppN2/2nPP3/1B1R2n1/2R1Q3/3K4 w - - 5 1",
68
-
69
- // 5-man positions
70
- "8/8/8/8/5kp1/P7/8/1K1N4 w - - 0 1", // Kc2 - mate
71
- "8/8/8/5N2/8/p7/8/2NK3k w - - 0 1", // Na2 - mate
72
- "8/3k4/8/8/8/4B3/4KB2/2B5 w - - 0 1", // draw
73
-
74
- // 6-man positions
75
- "8/8/1P6/5pr1/8/4R3/7k/2K5 w - - 0 1", // Re5 - mate
76
- "8/2p4P/8/kr6/6R1/8/8/1K6 w - - 0 1", // Ka2 - mate
77
- "8/8/3P3k/8/1p6/8/1P6/1K3n2 b - - 0 1", // Nd2 - draw
78
-
79
- // 7-man positions
80
- "8/R7/2q5/8/6k1/8/1P5p/K6R w - - 0 124", // Draw
81
-
82
- // Mate and stalemate positions
83
- "6k1/3b3r/1p1p4/p1n2p2/1PPNpP1q/P3Q1p1/1R1RB1P1/5K2 b - - 0 1",
84
- "r2r1n2/pp2bk2/2p1p2p/3q4/3PN1QP/2P3R1/P4PP1/5RK1 w - - 0 1",
85
- "8/8/8/8/8/6k1/6p1/6K1 w - -",
86
- "7k/7P/6K1/8/3B4/8/8/8 b - -",
87
-
88
- // Chess 960
89
- "setoption name UCI_Chess960 value true",
90
- "bbqnnrkr/pppppppp/8/8/8/8/PPPPPPPP/BBQNNRKR w HFhf - 0 1 moves g2g3 d7d5 d2d4 c8h3 c1g5 e8d6 g5e7 f7f6",
91
- "setoption name UCI_Chess960 value false"
92
- };
93
-
94
- } // namespace
95
-
96
- namespace Stockfish {
97
-
98
- /// setup_bench() builds a list of UCI commands to be run by bench. There
99
- /// are five parameters: TT size in MB, number of search threads that
100
- /// should be used, the limit value spent for each position, a file name
101
- /// where to look for positions in FEN format, the type of the limit:
102
- /// depth, perft, nodes and movetime (in millisecs), and evaluation type
103
- /// mixed (default), classical, NNUE.
104
- ///
105
- /// bench -> search default positions up to depth 13
106
- /// bench 64 1 15 -> search default positions up to depth 15 (TT = 64MB)
107
- /// bench 64 4 5000 current movetime -> search current position with 4 threads for 5 sec
108
- /// bench 64 1 100000 default nodes -> search default positions for 100K nodes each
109
- /// bench 16 1 5 default perft -> run a perft 5 on default positions
110
-
111
- vector<string> setup_bench(const Position& current, istream& is) {
112
-
113
- vector<string> fens, list;
114
- string go, token, varname;
115
-
116
- streampos args = is.tellg();
117
- // Check whether the next token is a variant name
118
- if ((is >> token) && variants.find(token) != variants.end())
119
- {
120
- args = is.tellg();
121
- varname = token;
122
- }
123
- else
124
- {
125
- is.seekg(args);
126
- varname = string(Options["UCI_Variant"]);
127
- }
128
- const Variant* variant = variants.find(varname)->second;
129
-
130
- // Assign default values to missing arguments
131
- string ttSize = (is >> token) ? token : "16";
132
- string threads = (is >> token) ? token : "1";
133
- string limit = (is >> token) ? token : "13";
134
- string fenFile = (is >> token) ? token : "default";
135
- string limitType = (is >> token) ? token : "depth";
136
- string evalType = (is >> token) ? token : "mixed";
137
-
138
- go = limitType == "eval" ? "eval" : "go " + limitType + " " + limit;
139
-
140
- if (fenFile == "default")
141
- {
142
- if (varname != "chess")
143
- fens.push_back(variant->startFen);
144
- else
145
- fens = Defaults;
146
- }
147
-
148
- else if (fenFile == "current")
149
- fens.push_back(current.fen());
150
-
151
- else
152
- {
153
- string fen;
154
- ifstream file(fenFile);
155
-
156
- if (!file.is_open())
157
- {
158
- cerr << "Unable to open file " << fenFile << endl;
159
- exit(EXIT_FAILURE);
160
- }
161
-
162
- while (getline(file, fen))
163
- if (!fen.empty())
164
- fens.push_back(fen);
165
-
166
- file.close();
167
- }
168
-
169
- list.emplace_back("setoption name Threads value " + threads);
170
- list.emplace_back("setoption name Hash value " + ttSize);
171
- list.emplace_back("setoption name UCI_Variant value " + varname);
172
- list.emplace_back("ucinewgame");
173
-
174
- size_t posCounter = 0;
175
-
176
- for (const string& fen : fens)
177
- if (fen.find("setoption") != string::npos)
178
- list.emplace_back(fen);
179
- else
180
- {
181
- if (evalType == "classical" || (evalType == "mixed" && posCounter % 2 == 0))
182
- list.emplace_back("setoption name Use NNUE value false");
183
- else if (evalType == "NNUE" || (evalType == "mixed" && posCounter % 2 != 0))
184
- list.emplace_back("setoption name Use NNUE value true");
185
- list.emplace_back("position fen " + fen);
186
- list.emplace_back(go);
187
- ++posCounter;
188
- }
189
-
190
- list.emplace_back("setoption name Use NNUE value true");
191
-
192
- return list;
193
- }
194
-
195
- } // namespace Stockfish
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/src/bitbase.cpp DELETED
@@ -1,177 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
4
-
5
- Stockfish is free software: you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation, either version 3 of the License, or
8
- (at your option) any later version.
9
-
10
- Stockfish is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- You should have received a copy of the GNU General Public License
16
- along with this program. If not, see <http://www.gnu.org/licenses/>.
17
- */
18
-
19
- #include <cassert>
20
- #include <vector>
21
- #include <bitset>
22
-
23
- #include "bitboard.h"
24
- #include "types.h"
25
-
26
- namespace Stockfish {
27
-
28
- namespace {
29
-
30
- // There are 24 possible pawn squares: files A to D and ranks from 2 to 7.
31
- // Positions with the pawn on files E to H will be mirrored before probing.
32
- constexpr unsigned MAX_INDEX = 2*24*64*64; // stm * psq * wksq * bksq = 196608
33
-
34
- std::bitset<MAX_INDEX> KPKBitbase;
35
-
36
- // A KPK bitbase index is an integer in [0, IndexMax] range
37
- //
38
- // Information is mapped in a way that minimizes the number of iterations:
39
- //
40
- // bit 0- 5: white king square (from SQ_A1 to SQ_H8)
41
- // bit 6-11: black king square (from SQ_A1 to SQ_H8)
42
- // bit 12: side to move (WHITE or BLACK)
43
- // bit 13-14: white pawn file (from FILE_A to FILE_D)
44
- // bit 15-17: white pawn RANK_7 - rank (from RANK_7 - RANK_7 to RANK_7 - RANK_2)
45
- unsigned index(Color stm, Square bksq, Square wksq, Square psq) {
46
- return int(wksq) | (bksq << 6) | (stm << 12) | (file_of(psq) << 13) | ((RANK_7 - rank_of(psq)) << 15);
47
- }
48
-
49
- enum Result {
50
- INVALID = 0,
51
- UNKNOWN = 1,
52
- DRAW = 2,
53
- WIN = 4
54
- };
55
-
56
- Result& operator|=(Result& r, Result v) { return r = Result(r | v); }
57
-
58
- struct KPKPosition {
59
- KPKPosition() = default;
60
- explicit KPKPosition(unsigned idx);
61
- operator Result() const { return result; }
62
- Result classify(const std::vector<KPKPosition>& db);
63
-
64
- Color stm;
65
- Square ksq[COLOR_NB], psq;
66
- Result result;
67
- };
68
-
69
- } // namespace
70
-
71
- bool Bitbases::probe(Square wksq, Square wpsq, Square bksq, Color stm) {
72
-
73
- assert(file_of(wpsq) <= FILE_D);
74
-
75
- return KPKBitbase[index(stm, bksq, wksq, wpsq)];
76
- }
77
-
78
-
79
- void Bitbases::init() {
80
-
81
- #ifdef LARGEBOARDS
82
- // Bitbases are not working for large-board version
83
- return;
84
- #endif
85
-
86
- std::vector<KPKPosition> db(MAX_INDEX);
87
- unsigned idx, repeat = 1;
88
-
89
- // Initialize db with known win / draw positions
90
- for (idx = 0; idx < MAX_INDEX; ++idx)
91
- db[idx] = KPKPosition(idx);
92
-
93
- // Iterate through the positions until none of the unknown positions can be
94
- // changed to either wins or draws (15 cycles needed).
95
- while (repeat)
96
- for (repeat = idx = 0; idx < MAX_INDEX; ++idx)
97
- repeat |= (db[idx] == UNKNOWN && db[idx].classify(db) != UNKNOWN);
98
-
99
- // Fill the bitbase with the decisive results
100
- for (idx = 0; idx < MAX_INDEX; ++idx)
101
- if (db[idx] == WIN)
102
- KPKBitbase.set(idx);
103
- }
104
-
105
- namespace {
106
-
107
- KPKPosition::KPKPosition(unsigned idx) {
108
-
109
- ksq[WHITE] = Square((idx >> 0) & 0x3F);
110
- ksq[BLACK] = Square((idx >> 6) & 0x3F);
111
- stm = Color ((idx >> 12) & 0x01);
112
- psq = make_square(File((idx >> 13) & 0x3), Rank(RANK_7 - ((idx >> 15) & 0x7)));
113
-
114
- // Invalid if two pieces are on the same square or if a king can be captured
115
- if ( distance(ksq[WHITE], ksq[BLACK]) <= 1
116
- || ksq[WHITE] == psq
117
- || ksq[BLACK] == psq
118
- || (stm == WHITE && (pawn_attacks_bb(WHITE, psq) & ksq[BLACK])))
119
- result = INVALID;
120
-
121
- // Win if the pawn can be promoted without getting captured
122
- else if ( stm == WHITE
123
- && rank_of(psq) == RANK_7
124
- && ksq[WHITE] != psq + NORTH
125
- && ( distance(ksq[BLACK], psq + NORTH) > 1
126
- || (distance(ksq[WHITE], psq + NORTH) == 1)))
127
- result = WIN;
128
-
129
- // Draw if it is stalemate or the black king can capture the pawn
130
- else if ( stm == BLACK
131
- && ( !(attacks_bb<KING>(ksq[BLACK]) & ~(attacks_bb<KING>(ksq[WHITE]) | pawn_attacks_bb(WHITE, psq)))
132
- || (attacks_bb<KING>(ksq[BLACK]) & ~attacks_bb<KING>(ksq[WHITE]) & psq)))
133
- result = DRAW;
134
-
135
- // Position will be classified later
136
- else
137
- result = UNKNOWN;
138
- }
139
-
140
- Result KPKPosition::classify(const std::vector<KPKPosition>& db) {
141
-
142
- // White to move: If one move leads to a position classified as WIN, the result
143
- // of the current position is WIN. If all moves lead to positions classified
144
- // as DRAW, the current position is classified as DRAW, otherwise the current
145
- // position is classified as UNKNOWN.
146
- //
147
- // Black to move: If one move leads to a position classified as DRAW, the result
148
- // of the current position is DRAW. If all moves lead to positions classified
149
- // as WIN, the position is classified as WIN, otherwise the current position is
150
- // classified as UNKNOWN.
151
- const Result Good = (stm == WHITE ? WIN : DRAW);
152
- const Result Bad = (stm == WHITE ? DRAW : WIN);
153
-
154
- Result r = INVALID;
155
- Bitboard b = attacks_bb<KING>(ksq[stm]);
156
-
157
- while (b)
158
- r |= stm == WHITE ? db[index(BLACK, ksq[BLACK], pop_lsb(b), psq)]
159
- : db[index(WHITE, pop_lsb(b), ksq[WHITE], psq)];
160
-
161
- if (stm == WHITE)
162
- {
163
- if (rank_of(psq) < RANK_7) // Single push
164
- r |= db[index(BLACK, ksq[BLACK], ksq[WHITE], psq + NORTH)];
165
-
166
- if ( rank_of(psq) == RANK_2 // Double push
167
- && psq + NORTH != ksq[WHITE]
168
- && psq + NORTH != ksq[BLACK])
169
- r |= db[index(BLACK, ksq[BLACK], ksq[WHITE], psq + NORTH + NORTH)];
170
- }
171
-
172
- return result = r & Good ? Good : r & UNKNOWN ? UNKNOWN : Bad;
173
- }
174
-
175
- } // namespace
176
-
177
- } // namespace Stockfish
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/src/bitboard.cpp DELETED
@@ -1,501 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
4
-
5
- Stockfish is free software: you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation, either version 3 of the License, or
8
- (at your option) any later version.
9
-
10
- Stockfish is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- You should have received a copy of the GNU General Public License
16
- along with this program. If not, see <http://www.gnu.org/licenses/>.
17
- */
18
-
19
- #include <algorithm>
20
- #include <bitset>
21
-
22
- #include "bitboard.h"
23
- #include "magic.h"
24
- #include "misc.h"
25
- #include "piece.h"
26
-
27
- namespace Stockfish {
28
-
29
- uint8_t PopCnt16[1 << 16];
30
- uint8_t SquareDistance[SQUARE_NB][SQUARE_NB];
31
-
32
- Bitboard SquareBB[SQUARE_NB];
33
- Bitboard LineBB[SQUARE_NB][SQUARE_NB];
34
- Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
35
- Bitboard PseudoAttacks[COLOR_NB][PIECE_TYPE_NB][SQUARE_NB];
36
- Bitboard PseudoMoves[2][COLOR_NB][PIECE_TYPE_NB][SQUARE_NB];
37
- Bitboard LeaperAttacks[COLOR_NB][PIECE_TYPE_NB][SQUARE_NB];
38
- Bitboard LeaperMoves[2][COLOR_NB][PIECE_TYPE_NB][SQUARE_NB];
39
- Bitboard BoardSizeBB[FILE_NB][RANK_NB];
40
- RiderType AttackRiderTypes[PIECE_TYPE_NB];
41
- RiderType MoveRiderTypes[2][PIECE_TYPE_NB];
42
-
43
- Magic RookMagicsH[SQUARE_NB];
44
- Magic RookMagicsV[SQUARE_NB];
45
- Magic BishopMagics[SQUARE_NB];
46
- Magic CannonMagicsH[SQUARE_NB];
47
- Magic CannonMagicsV[SQUARE_NB];
48
- Magic LameDabbabaMagics[SQUARE_NB];
49
- Magic HorseMagics[SQUARE_NB];
50
- Magic ElephantMagics[SQUARE_NB];
51
- Magic JanggiElephantMagics[SQUARE_NB];
52
- Magic CannonDiagMagics[SQUARE_NB];
53
- Magic NightriderMagics[SQUARE_NB];
54
- Magic GrasshopperMagicsH[SQUARE_NB];
55
- Magic GrasshopperMagicsV[SQUARE_NB];
56
- Magic GrasshopperMagicsD[SQUARE_NB];
57
-
58
- Magic* magics[] = {BishopMagics, RookMagicsH, RookMagicsV, CannonMagicsH, CannonMagicsV,
59
- LameDabbabaMagics, HorseMagics, ElephantMagics, JanggiElephantMagics, CannonDiagMagics, NightriderMagics,
60
- GrasshopperMagicsH, GrasshopperMagicsV, GrasshopperMagicsD};
61
-
62
- namespace {
63
-
64
- // Some magics need to be split in order to reduce memory consumption.
65
- // Otherwise on a 12x10 board they can be >100 MB.
66
- #ifdef LARGEBOARDS
67
- Bitboard RookTableH[0x11800]; // To store horizontal rook attacks
68
- Bitboard RookTableV[0x4800]; // To store vertical rook attacks
69
- Bitboard BishopTable[0x33C00]; // To store bishop attacks
70
- Bitboard CannonTableH[0x11800]; // To store horizontal cannon attacks
71
- Bitboard CannonTableV[0x4800]; // To store vertical cannon attacks
72
- Bitboard LameDabbabaTable[0x500]; // To store lame dabbaba attacks
73
- Bitboard HorseTable[0x500]; // To store horse attacks
74
- Bitboard ElephantTable[0x400]; // To store elephant attacks
75
- Bitboard JanggiElephantTable[0x1C000]; // To store janggi elephant attacks
76
- Bitboard CannonDiagTable[0x33C00]; // To store diagonal cannon attacks
77
- Bitboard NightriderTable[0x70200]; // To store nightrider attacks
78
- Bitboard GrasshopperTableH[0x11800]; // To store horizontal grasshopper attacks
79
- Bitboard GrasshopperTableV[0x4800]; // To store vertical grasshopper attacks
80
- Bitboard GrasshopperTableD[0x33C00]; // To store diagonal grasshopper attacks
81
- #else
82
- Bitboard RookTableH[0xA00]; // To store horizontal rook attacks
83
- Bitboard RookTableV[0xA00]; // To store vertical rook attacks
84
- Bitboard BishopTable[0x1480]; // To store bishop attacks
85
- Bitboard CannonTableH[0xA00]; // To store horizontal cannon attacks
86
- Bitboard CannonTableV[0xA00]; // To store vertical cannon attacks
87
- Bitboard LameDabbabaTable[0x240]; // To store lame dabbaba attacks
88
- Bitboard HorseTable[0x240]; // To store horse attacks
89
- Bitboard ElephantTable[0x1A0]; // To store elephant attacks
90
- Bitboard JanggiElephantTable[0x5C00]; // To store janggi elephant attacks
91
- Bitboard CannonDiagTable[0x1480]; // To store diagonal cannon attacks
92
- Bitboard NightriderTable[0x1840]; // To store nightrider attacks
93
- Bitboard GrasshopperTableH[0xA00]; // To store horizontal grasshopper attacks
94
- Bitboard GrasshopperTableV[0xA00]; // To store vertical grasshopper attacks
95
- Bitboard GrasshopperTableD[0x1480]; // To store diagonal grasshopper attacks
96
- #endif
97
-
98
- // Rider directions
99
- const std::map<Direction, int> RookDirectionsV { {NORTH, 0}, {SOUTH, 0}};
100
- const std::map<Direction, int> RookDirectionsH { {EAST, 0}, {WEST, 0} };
101
- const std::map<Direction, int> BishopDirections { {NORTH_EAST, 0}, {SOUTH_EAST, 0}, {SOUTH_WEST, 0}, {NORTH_WEST, 0} };
102
- const std::map<Direction, int> LameDabbabaDirections { {2 * NORTH, 0}, {2 * EAST, 0}, {2 * SOUTH, 0}, {2 * WEST, 0} };
103
- const std::map<Direction, int> HorseDirections { {2 * SOUTH + WEST, 0}, {2 * SOUTH + EAST, 0}, {SOUTH + 2 * WEST, 0}, {SOUTH + 2 * EAST, 0},
104
- {NORTH + 2 * WEST, 0}, {NORTH + 2 * EAST, 0}, {2 * NORTH + WEST, 0}, {2 * NORTH + EAST, 0} };
105
- const std::map<Direction, int> ElephantDirections { {2 * NORTH_EAST, 0}, {2 * SOUTH_EAST, 0}, {2 * SOUTH_WEST, 0}, {2 * NORTH_WEST, 0} };
106
- const std::map<Direction, int> JanggiElephantDirections { {NORTH + 2 * NORTH_EAST, 0}, {EAST + 2 * NORTH_EAST, 0},
107
- {EAST + 2 * SOUTH_EAST, 0}, {SOUTH + 2 * SOUTH_EAST, 0},
108
- {SOUTH + 2 * SOUTH_WEST, 0}, {WEST + 2 * SOUTH_WEST, 0},
109
- {WEST + 2 * NORTH_WEST, 0}, {NORTH + 2 * NORTH_WEST, 0} };
110
- const std::map<Direction, int> GrasshopperDirectionsV { {NORTH, 1}, {SOUTH, 1}};
111
- const std::map<Direction, int> GrasshopperDirectionsH { {EAST, 1}, {WEST, 1} };
112
- const std::map<Direction, int> GrasshopperDirectionsD { {NORTH_EAST, 1}, {SOUTH_EAST, 1}, {SOUTH_WEST, 1}, {NORTH_WEST, 1} };
113
-
114
- enum MovementType { RIDER, HOPPER, LAME_LEAPER, HOPPER_RANGE };
115
-
116
- template <MovementType MT>
117
- #ifdef PRECOMPUTED_MAGICS
118
- void init_magics(Bitboard table[], Magic magics[], std::map<Direction, int> directions, const Bitboard magicsInit[]);
119
- #else
120
- void init_magics(Bitboard table[], Magic magics[], std::map<Direction, int> directions);
121
- #endif
122
-
123
- template <MovementType MT>
124
- Bitboard sliding_attack(std::map<Direction, int> directions, Square sq, Bitboard occupied, Color c = WHITE) {
125
- assert(MT != LAME_LEAPER);
126
-
127
- Bitboard attack = 0;
128
-
129
- for (auto const& [d, limit] : directions)
130
- {
131
- int count = 0;
132
- bool hurdle = false;
133
- for (Square s = sq + (c == WHITE ? d : -d);
134
- is_ok(s) && distance(s, s - (c == WHITE ? d : -d)) <= 2;
135
- s += (c == WHITE ? d : -d))
136
- {
137
- if (MT != HOPPER || hurdle)
138
- {
139
- attack |= s;
140
- // For hoppers we consider limit == 1 as a grasshopper,
141
- // but limit > 1 as a limited distance hopper
142
- if (limit && !(MT == HOPPER_RANGE && limit == 1) && ++count >= limit)
143
- break;
144
- }
145
-
146
- if (occupied & s)
147
- {
148
- if (MT == HOPPER && !hurdle)
149
- hurdle = true;
150
- else
151
- break;
152
- }
153
- }
154
- }
155
-
156
- return attack;
157
- }
158
-
159
- Bitboard lame_leaper_path(Direction d, Square s) {
160
- Direction dr = d > 0 ? NORTH : SOUTH;
161
- Direction df = (std::abs(d % NORTH) < NORTH / 2 ? d % NORTH : -(d % NORTH)) < 0 ? WEST : EAST;
162
- Square to = s + d;
163
- Bitboard b = 0;
164
- if (!is_ok(to) || distance(s, to) >= 4)
165
- return b;
166
- while (s != to)
167
- {
168
- int diff = std::abs(file_of(to) - file_of(s)) - std::abs(rank_of(to) - rank_of(s));
169
- if (diff > 0)
170
- s += df;
171
- else if (diff < 0)
172
- s += dr;
173
- else
174
- s += df + dr;
175
-
176
- if (s != to)
177
- b |= s;
178
- }
179
- return b;
180
- }
181
-
182
- Bitboard lame_leaper_path(std::map<Direction, int> directions, Square s) {
183
- Bitboard b = 0;
184
- for (const auto& i : directions)
185
- b |= lame_leaper_path(i.first, s);
186
- return b;
187
- }
188
-
189
- Bitboard lame_leaper_attack(std::map<Direction, int> directions, Square s, Bitboard occupied) {
190
- Bitboard b = 0;
191
- for (const auto& i : directions)
192
- {
193
- Square to = s + i.first;
194
- if (is_ok(to) && distance(s, to) < 4 && !(lame_leaper_path(i.first, s) & occupied))
195
- b |= to;
196
- }
197
- return b;
198
- }
199
-
200
- }
201
-
202
- /// safe_destination() returns the bitboard of target square for the given step
203
- /// from the given square. If the step is off the board, returns empty bitboard.
204
-
205
- inline Bitboard safe_destination(Square s, int step) {
206
- Square to = Square(s + step);
207
- return is_ok(to) && distance(s, to) <= 3 ? square_bb(to) : Bitboard(0);
208
- }
209
-
210
-
211
- /// Bitboards::pretty() returns an ASCII representation of a bitboard suitable
212
- /// to be printed to standard output. Useful for debugging.
213
-
214
- std::string Bitboards::pretty(Bitboard b) {
215
-
216
- std::string s = "+---+---+---+---+---+---+---+---+---+---+---+---+\n";
217
-
218
- for (Rank r = RANK_MAX; r >= RANK_1; --r)
219
- {
220
- for (File f = FILE_A; f <= FILE_MAX; ++f)
221
- s += b & make_square(f, r) ? "| X " : "| ";
222
-
223
- s += "| " + std::to_string(1 + r) + "\n+---+---+---+---+---+---+---+---+---+---+---+---+\n";
224
- }
225
- s += " a b c d e f g h i j k l\n";
226
-
227
- return s;
228
- }
229
-
230
- /// Bitboards::init_pieces() initializes piece move/attack bitboards and rider types
231
-
232
- void Bitboards::init_pieces() {
233
-
234
- for (PieceType pt = PAWN; pt <= KING; ++pt)
235
- {
236
- const PieceInfo* pi = pieceMap.find(pt)->second;
237
-
238
- // Detect rider types
239
- for (auto modality : {MODALITY_QUIET, MODALITY_CAPTURE})
240
- {
241
- for (bool initial : {false, true})
242
- {
243
- // We do not support initial captures
244
- if (modality == MODALITY_CAPTURE && initial)
245
- continue;
246
- auto& riderTypes = modality == MODALITY_CAPTURE ? AttackRiderTypes[pt] : MoveRiderTypes[initial][pt];
247
- riderTypes = NO_RIDER;
248
- for (auto const& [d, limit] : pi->steps[initial][modality])
249
- {
250
- if (limit && LameDabbabaDirections.find(d) != LameDabbabaDirections.end())
251
- riderTypes |= RIDER_LAME_DABBABA;
252
- if (limit && HorseDirections.find(d) != HorseDirections.end())
253
- riderTypes |= RIDER_HORSE;
254
- if (limit && ElephantDirections.find(d) != ElephantDirections.end())
255
- riderTypes |= RIDER_ELEPHANT;
256
- if (limit && JanggiElephantDirections.find(d) != JanggiElephantDirections.end())
257
- riderTypes |= RIDER_JANGGI_ELEPHANT;
258
- }
259
- for (auto const& [d, limit] : pi->slider[initial][modality])
260
- {
261
- if (BishopDirections.find(d) != BishopDirections.end())
262
- riderTypes |= RIDER_BISHOP;
263
- if (RookDirectionsH.find(d) != RookDirectionsH.end())
264
- riderTypes |= RIDER_ROOK_H;
265
- if (RookDirectionsV.find(d) != RookDirectionsV.end())
266
- riderTypes |= RIDER_ROOK_V;
267
- if (HorseDirections.find(d) != HorseDirections.end())
268
- riderTypes |= RIDER_NIGHTRIDER;
269
- }
270
- for (auto const& [d, limit] : pi->hopper[initial][modality])
271
- {
272
- if (RookDirectionsH.find(d) != RookDirectionsH.end())
273
- riderTypes |= limit == 1 ? RIDER_GRASSHOPPER_H : RIDER_CANNON_H;
274
- if (RookDirectionsV.find(d) != RookDirectionsV.end())
275
- riderTypes |= limit == 1 ? RIDER_GRASSHOPPER_V : RIDER_CANNON_V;
276
- if (BishopDirections.find(d) != BishopDirections.end())
277
- riderTypes |= limit == 1 ? RIDER_GRASSHOPPER_D : RIDER_CANNON_DIAG;
278
- }
279
- }
280
- }
281
-
282
- // Initialize move/attack bitboards
283
- for (Color c : { WHITE, BLACK })
284
- {
285
- for (Square s = SQ_A1; s <= SQ_MAX; ++s)
286
- {
287
- for (auto modality : {MODALITY_QUIET, MODALITY_CAPTURE})
288
- {
289
- for (bool initial : {false, true})
290
- {
291
- // We do not support initial captures
292
- if (modality == MODALITY_CAPTURE && initial)
293
- continue;
294
- auto& pseudo = modality == MODALITY_CAPTURE ? PseudoAttacks[c][pt][s] : PseudoMoves[initial][c][pt][s];
295
- auto& leaper = modality == MODALITY_CAPTURE ? LeaperAttacks[c][pt][s] : LeaperMoves[initial][c][pt][s];
296
- pseudo = 0;
297
- leaper = 0;
298
- for (auto const& [d, limit] : pi->steps[initial][modality])
299
- {
300
- pseudo |= safe_destination(s, c == WHITE ? d : -d);
301
- if (!limit)
302
- leaper |= safe_destination(s, c == WHITE ? d : -d);
303
- }
304
- pseudo |= sliding_attack<RIDER>(pi->slider[initial][modality], s, 0, c);
305
- pseudo |= sliding_attack<HOPPER_RANGE>(pi->hopper[initial][modality], s, 0, c);
306
- }
307
- }
308
- }
309
- }
310
- }
311
- }
312
-
313
-
314
- /// Bitboards::init() initializes various bitboard tables. It is called at
315
- /// startup and relies on global objects to be already zero-initialized.
316
-
317
- void Bitboards::init() {
318
-
319
- for (unsigned i = 0; i < (1 << 16); ++i)
320
- PopCnt16[i] = uint8_t(std::bitset<16>(i).count());
321
-
322
- for (Square s = SQ_A1; s <= SQ_MAX; ++s)
323
- SquareBB[s] = make_bitboard(s);
324
-
325
- for (File f = FILE_A; f <= FILE_MAX; ++f)
326
- for (Rank r = RANK_1; r <= RANK_MAX; ++r)
327
- 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));
328
-
329
- for (Square s1 = SQ_A1; s1 <= SQ_MAX; ++s1)
330
- for (Square s2 = SQ_A1; s2 <= SQ_MAX; ++s2)
331
- SquareDistance[s1][s2] = std::max(distance<File>(s1, s2), distance<Rank>(s1, s2));
332
-
333
- #ifdef PRECOMPUTED_MAGICS
334
- init_magics<RIDER>(RookTableH, RookMagicsH, RookDirectionsH, RookMagicHInit);
335
- init_magics<RIDER>(RookTableV, RookMagicsV, RookDirectionsV, RookMagicVInit);
336
- init_magics<RIDER>(BishopTable, BishopMagics, BishopDirections, BishopMagicInit);
337
- init_magics<HOPPER>(CannonTableH, CannonMagicsH, RookDirectionsH, CannonMagicHInit);
338
- init_magics<HOPPER>(CannonTableV, CannonMagicsV, RookDirectionsV, CannonMagicVInit);
339
- init_magics<LAME_LEAPER>(LameDabbabaTable, LameDabbabaMagics, LameDabbabaDirections, LameDabbabaMagicInit);
340
- init_magics<LAME_LEAPER>(HorseTable, HorseMagics, HorseDirections, HorseMagicInit);
341
- init_magics<LAME_LEAPER>(ElephantTable, ElephantMagics, ElephantDirections, ElephantMagicInit);
342
- init_magics<LAME_LEAPER>(JanggiElephantTable, JanggiElephantMagics, JanggiElephantDirections, JanggiElephantMagicInit);
343
- init_magics<HOPPER>(CannonDiagTable, CannonDiagMagics, BishopDirections, CannonDiagMagicInit);
344
- init_magics<RIDER>(NightriderTable, NightriderMagics, HorseDirections, NightriderMagicInit);
345
- init_magics<HOPPER>(GrasshopperTableH, GrasshopperMagicsH, GrasshopperDirectionsH, GrasshopperMagicHInit);
346
- init_magics<HOPPER>(GrasshopperTableV, GrasshopperMagicsV, GrasshopperDirectionsV, GrasshopperMagicVInit);
347
- init_magics<HOPPER>(GrasshopperTableD, GrasshopperMagicsD, GrasshopperDirectionsD, GrasshopperMagicDInit);
348
- #else
349
- init_magics<RIDER>(RookTableH, RookMagicsH, RookDirectionsH);
350
- init_magics<RIDER>(RookTableV, RookMagicsV, RookDirectionsV);
351
- init_magics<RIDER>(BishopTable, BishopMagics, BishopDirections);
352
- init_magics<HOPPER>(CannonTableH, CannonMagicsH, RookDirectionsH);
353
- init_magics<HOPPER>(CannonTableV, CannonMagicsV, RookDirectionsV);
354
- init_magics<LAME_LEAPER>(LameDabbabaTable, LameDabbabaMagics, LameDabbabaDirections);
355
- init_magics<LAME_LEAPER>(HorseTable, HorseMagics, HorseDirections);
356
- init_magics<LAME_LEAPER>(ElephantTable, ElephantMagics, ElephantDirections);
357
- init_magics<LAME_LEAPER>(JanggiElephantTable, JanggiElephantMagics, JanggiElephantDirections);
358
- init_magics<HOPPER>(CannonDiagTable, CannonDiagMagics, BishopDirections);
359
- init_magics<RIDER>(NightriderTable, NightriderMagics, HorseDirections);
360
- init_magics<HOPPER>(GrasshopperTableH, GrasshopperMagicsH, GrasshopperDirectionsH);
361
- init_magics<HOPPER>(GrasshopperTableV, GrasshopperMagicsV, GrasshopperDirectionsV);
362
- init_magics<HOPPER>(GrasshopperTableD, GrasshopperMagicsD, GrasshopperDirectionsD);
363
- #endif
364
-
365
- init_pieces();
366
-
367
- for (Square s1 = SQ_A1; s1 <= SQ_MAX; ++s1)
368
- {
369
- for (PieceType pt : { BISHOP, ROOK })
370
- for (Square s2 = SQ_A1; s2 <= SQ_MAX; ++s2)
371
- {
372
- if (PseudoAttacks[WHITE][pt][s1] & s2)
373
- {
374
- LineBB[s1][s2] = (attacks_bb(WHITE, pt, s1, 0) & attacks_bb(WHITE, pt, s2, 0)) | s1 | s2;
375
- BetweenBB[s1][s2] = (attacks_bb(WHITE, pt, s1, square_bb(s2)) & attacks_bb(WHITE, pt, s2, square_bb(s1)));
376
- }
377
- BetweenBB[s1][s2] |= s2;
378
- }
379
- }
380
- }
381
-
382
- namespace {
383
-
384
- // init_magics() computes all rook and bishop attacks at startup. Magic
385
- // bitboards are used to look up attacks of sliding pieces. As a reference see
386
- // www.chessprogramming.org/Magic_Bitboards. In particular, here we use the so
387
- // called "fancy" approach.
388
-
389
- template <MovementType MT>
390
- #ifdef PRECOMPUTED_MAGICS
391
- void init_magics(Bitboard table[], Magic magics[], std::map<Direction, int> directions, const Bitboard magicsInit[]) {
392
- #else
393
- void init_magics(Bitboard table[], Magic magics[], std::map<Direction, int> directions) {
394
- #endif
395
-
396
- // Optimal PRNG seeds to pick the correct magics in the shortest time
397
- #ifndef PRECOMPUTED_MAGICS
398
- #ifdef LARGEBOARDS
399
- int seeds[][RANK_NB] = { { 734, 10316, 55013, 32803, 12281, 15100, 16645, 255, 346, 89123 },
400
- { 734, 10316, 55013, 32803, 12281, 15100, 16645, 255, 346, 89123 } };
401
- #else
402
- int seeds[][RANK_NB] = { { 8977, 44560, 54343, 38998, 5731, 95205, 104912, 17020 },
403
- { 728, 10316, 55013, 32803, 12281, 15100, 16645, 255 } };
404
- #endif
405
- #endif
406
-
407
- Bitboard* occupancy = new Bitboard[1 << (FILE_NB + RANK_NB - 4)];
408
- Bitboard* reference = new Bitboard[1 << (FILE_NB + RANK_NB - 4)];
409
- Bitboard edges, b;
410
- int* epoch = new int[1 << (FILE_NB + RANK_NB - 4)]();
411
- int cnt = 0, size = 0;
412
-
413
- for (Square s = SQ_A1; s <= SQ_MAX; ++s)
414
- {
415
- // Board edges are not considered in the relevant occupancies
416
- edges = ((Rank1BB | rank_bb(RANK_MAX)) & ~rank_bb(s)) | ((FileABB | file_bb(FILE_MAX)) & ~file_bb(s));
417
-
418
- // Given a square 's', the mask is the bitboard of sliding attacks from
419
- // 's' computed on an empty board. The index must be big enough to contain
420
- // all the attacks for each possible subset of the mask and so is 2 power
421
- // the number of 1s of the mask. Hence we deduce the size of the shift to
422
- // apply to the 64 or 32 bits word to get the index.
423
- Magic& m = magics[s];
424
- // The mask for hoppers is unlimited distance, even if the hopper is limited distance (e.g., grasshopper)
425
- m.mask = (MT == LAME_LEAPER ? lame_leaper_path(directions, s) : sliding_attack<MT == HOPPER ? HOPPER_RANGE : MT>(directions, s, 0)) & ~edges;
426
- #ifdef LARGEBOARDS
427
- m.shift = 128 - popcount(m.mask);
428
- #else
429
- m.shift = (Is64Bit ? 64 : 32) - popcount(m.mask);
430
- #endif
431
-
432
- // Set the offset for the attacks table of the square. We have individual
433
- // table sizes for each square with "Fancy Magic Bitboards".
434
- m.attacks = s == SQ_A1 ? table : magics[s - 1].attacks + size;
435
-
436
- // Use Carry-Rippler trick to enumerate all subsets of masks[s] and
437
- // store the corresponding sliding attack bitboard in reference[].
438
- b = size = 0;
439
- do {
440
- occupancy[size] = b;
441
- reference[size] = MT == LAME_LEAPER ? lame_leaper_attack(directions, s, b) : sliding_attack<MT>(directions, s, b);
442
-
443
- if (HasPext)
444
- m.attacks[pext(b, m.mask)] = reference[size];
445
-
446
- size++;
447
- b = (b - m.mask) & m.mask;
448
- } while (b);
449
-
450
- if (HasPext)
451
- continue;
452
-
453
- #ifndef PRECOMPUTED_MAGICS
454
- PRNG rng(seeds[Is64Bit][rank_of(s)]);
455
- #endif
456
-
457
- // Find a magic for square 's' picking up an (almost) random number
458
- // until we find the one that passes the verification test.
459
- for (int i = 0; i < size; )
460
- {
461
- for (m.magic = 0; popcount((m.magic * m.mask) >> (SQUARE_NB - FILE_NB)) < FILE_NB - 2; )
462
- {
463
- #ifdef LARGEBOARDS
464
- #ifdef PRECOMPUTED_MAGICS
465
- m.magic = magicsInit[s];
466
- #else
467
- m.magic = (rng.sparse_rand<Bitboard>() << 64) ^ rng.sparse_rand<Bitboard>();
468
- #endif
469
- #else
470
- m.magic = rng.sparse_rand<Bitboard>();
471
- #endif
472
- }
473
-
474
- // A good magic must map every possible occupancy to an index that
475
- // looks up the correct sliding attack in the attacks[s] database.
476
- // Note that we build up the database for square 's' as a side
477
- // effect of verifying the magic. Keep track of the attempt count
478
- // and save it in epoch[], little speed-up trick to avoid resetting
479
- // m.attacks[] after every failed attempt.
480
- for (++cnt, i = 0; i < size; ++i)
481
- {
482
- unsigned idx = m.index(occupancy[i]);
483
-
484
- if (epoch[idx] < cnt)
485
- {
486
- epoch[idx] = cnt;
487
- m.attacks[idx] = reference[i];
488
- }
489
- else if (m.attacks[idx] != reference[i])
490
- break;
491
- }
492
- }
493
- }
494
-
495
- delete[] occupancy;
496
- delete[] reference;
497
- delete[] epoch;
498
- }
499
- }
500
-
501
- } // namespace Stockfish
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/src/bitboard.h DELETED
@@ -1,787 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
4
-
5
- Stockfish is free software: you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation, either version 3 of the License, or
8
- (at your option) any later version.
9
-
10
- Stockfish is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- You should have received a copy of the GNU General Public License
16
- along with this program. If not, see <http://www.gnu.org/licenses/>.
17
- */
18
-
19
- #ifndef BITBOARD_H_INCLUDED
20
- #define BITBOARD_H_INCLUDED
21
-
22
- #include <string>
23
-
24
- #include "types.h"
25
-
26
- namespace Stockfish {
27
-
28
- namespace Bitbases {
29
-
30
- void init();
31
- bool probe(Square wksq, Square wpsq, Square bksq, Color us);
32
-
33
- } // namespace Stockfish::Bitbases
34
-
35
- namespace Bitboards {
36
-
37
- void init_pieces();
38
- void init();
39
- std::string pretty(Bitboard b);
40
-
41
- } // namespace Stockfish::Bitboards
42
-
43
- #ifdef LARGEBOARDS
44
- constexpr Bitboard AllSquares = ((~Bitboard(0)) >> 8);
45
- #else
46
- constexpr Bitboard AllSquares = ~Bitboard(0);
47
- #endif
48
- #ifdef LARGEBOARDS
49
- constexpr Bitboard DarkSquares = (Bitboard(0xAAA555AAA555AAULL) << 64) ^ Bitboard(0xA555AAA555AAA555ULL);
50
- #else
51
- constexpr Bitboard DarkSquares = 0xAA55AA55AA55AA55ULL;
52
- #endif
53
-
54
- #ifdef LARGEBOARDS
55
- constexpr Bitboard FileABB = (Bitboard(0x00100100100100ULL) << 64) ^ Bitboard(0x1001001001001001ULL);
56
- #else
57
- constexpr Bitboard FileABB = 0x0101010101010101ULL;
58
- #endif
59
- constexpr Bitboard FileBBB = FileABB << 1;
60
- constexpr Bitboard FileCBB = FileABB << 2;
61
- constexpr Bitboard FileDBB = FileABB << 3;
62
- constexpr Bitboard FileEBB = FileABB << 4;
63
- constexpr Bitboard FileFBB = FileABB << 5;
64
- constexpr Bitboard FileGBB = FileABB << 6;
65
- constexpr Bitboard FileHBB = FileABB << 7;
66
- #ifdef LARGEBOARDS
67
- constexpr Bitboard FileIBB = FileABB << 8;
68
- constexpr Bitboard FileJBB = FileABB << 9;
69
- constexpr Bitboard FileKBB = FileABB << 10;
70
- constexpr Bitboard FileLBB = FileABB << 11;
71
- #endif
72
-
73
-
74
- #ifdef LARGEBOARDS
75
- constexpr Bitboard Rank1BB = 0xFFF;
76
- #else
77
- constexpr Bitboard Rank1BB = 0xFF;
78
- #endif
79
- constexpr Bitboard Rank2BB = Rank1BB << (FILE_NB * 1);
80
- constexpr Bitboard Rank3BB = Rank1BB << (FILE_NB * 2);
81
- constexpr Bitboard Rank4BB = Rank1BB << (FILE_NB * 3);
82
- constexpr Bitboard Rank5BB = Rank1BB << (FILE_NB * 4);
83
- constexpr Bitboard Rank6BB = Rank1BB << (FILE_NB * 5);
84
- constexpr Bitboard Rank7BB = Rank1BB << (FILE_NB * 6);
85
- constexpr Bitboard Rank8BB = Rank1BB << (FILE_NB * 7);
86
- #ifdef LARGEBOARDS
87
- constexpr Bitboard Rank9BB = Rank1BB << (FILE_NB * 8);
88
- constexpr Bitboard Rank10BB = Rank1BB << (FILE_NB * 9);
89
- #endif
90
-
91
- constexpr Bitboard QueenSide = FileABB | FileBBB | FileCBB | FileDBB;
92
- constexpr Bitboard CenterFiles = FileCBB | FileDBB | FileEBB | FileFBB;
93
- constexpr Bitboard KingSide = FileEBB | FileFBB | FileGBB | FileHBB;
94
- constexpr Bitboard Center = (FileDBB | FileEBB) & (Rank4BB | Rank5BB);
95
-
96
- constexpr Bitboard KingFlank[FILE_NB] = {
97
- QueenSide ^ FileDBB, QueenSide, QueenSide,
98
- CenterFiles, CenterFiles,
99
- KingSide, KingSide, KingSide ^ FileEBB
100
- };
101
-
102
- extern uint8_t PopCnt16[1 << 16];
103
- extern uint8_t SquareDistance[SQUARE_NB][SQUARE_NB];
104
-
105
- extern Bitboard SquareBB[SQUARE_NB];
106
- extern Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
107
- extern Bitboard LineBB[SQUARE_NB][SQUARE_NB];
108
- extern Bitboard PseudoAttacks[COLOR_NB][PIECE_TYPE_NB][SQUARE_NB];
109
- extern Bitboard PseudoMoves[2][COLOR_NB][PIECE_TYPE_NB][SQUARE_NB];
110
- extern Bitboard LeaperAttacks[COLOR_NB][PIECE_TYPE_NB][SQUARE_NB];
111
- extern Bitboard LeaperMoves[2][COLOR_NB][PIECE_TYPE_NB][SQUARE_NB];
112
- extern Bitboard SquareBB[SQUARE_NB];
113
- extern Bitboard BoardSizeBB[FILE_NB][RANK_NB];
114
- extern RiderType AttackRiderTypes[PIECE_TYPE_NB];
115
- extern RiderType MoveRiderTypes[2][PIECE_TYPE_NB];
116
-
117
- #ifdef LARGEBOARDS
118
- int popcount(Bitboard b); // required for 128 bit pext
119
- #endif
120
-
121
- /// Magic holds all magic bitboards relevant data for a single square
122
- struct Magic {
123
- Bitboard mask;
124
- Bitboard magic;
125
- Bitboard* attacks;
126
- unsigned shift;
127
-
128
- // Compute the attack's index using the 'magic bitboards' approach
129
- unsigned index(Bitboard occupied) const {
130
-
131
- if (HasPext)
132
- return unsigned(pext(occupied, mask));
133
-
134
- #ifdef LARGEBOARDS
135
- return unsigned(((occupied & mask) * magic) >> shift);
136
- #else
137
- if (Is64Bit)
138
- return unsigned(((occupied & mask) * magic) >> shift);
139
- #endif
140
-
141
- unsigned lo = unsigned(occupied) & unsigned(mask);
142
- unsigned hi = unsigned(occupied >> 32) & unsigned(mask >> 32);
143
- return (lo * unsigned(magic) ^ hi * unsigned(magic >> 32)) >> shift;
144
- }
145
- };
146
-
147
- extern Magic RookMagicsH[SQUARE_NB];
148
- extern Magic RookMagicsV[SQUARE_NB];
149
- extern Magic BishopMagics[SQUARE_NB];
150
- extern Magic CannonMagicsH[SQUARE_NB];
151
- extern Magic CannonMagicsV[SQUARE_NB];
152
- extern Magic LameDabbabaMagics[SQUARE_NB];
153
- extern Magic HorseMagics[SQUARE_NB];
154
- extern Magic ElephantMagics[SQUARE_NB];
155
- extern Magic JanggiElephantMagics[SQUARE_NB];
156
- extern Magic CannonDiagMagics[SQUARE_NB];
157
- extern Magic NightriderMagics[SQUARE_NB];
158
- extern Magic GrasshopperMagicsH[SQUARE_NB];
159
- extern Magic GrasshopperMagicsV[SQUARE_NB];
160
- extern Magic GrasshopperMagicsD[SQUARE_NB];
161
-
162
- extern Magic* magics[];
163
-
164
- constexpr Bitboard make_bitboard() { return 0; }
165
-
166
- template<typename ...Squares>
167
- constexpr Bitboard make_bitboard(Square s, Squares... squares) {
168
- return (Bitboard(1) << s) | make_bitboard(squares...);
169
- }
170
-
171
- inline Bitboard square_bb(Square s) {
172
- assert(is_ok(s));
173
- return SquareBB[s];
174
- }
175
-
176
-
177
- /// Overloads of bitwise operators between a Bitboard and a Square for testing
178
- /// whether a given bit is set in a bitboard, and for setting and clearing bits.
179
-
180
- inline Bitboard operator&( Bitboard b, Square s) { return b & square_bb(s); }
181
- inline Bitboard operator|( Bitboard b, Square s) { return b | square_bb(s); }
182
- inline Bitboard operator^( Bitboard b, Square s) { return b ^ square_bb(s); }
183
- inline Bitboard& operator|=(Bitboard& b, Square s) { return b |= square_bb(s); }
184
- inline Bitboard& operator^=(Bitboard& b, Square s) { return b ^= square_bb(s); }
185
-
186
- inline Bitboard operator-( Bitboard b, Square s) { return b & ~square_bb(s); }
187
- inline Bitboard& operator-=(Bitboard& b, Square s) { return b &= ~square_bb(s); }
188
-
189
- inline Bitboard operator&(Square s, Bitboard b) { return b & s; }
190
- inline Bitboard operator|(Square s, Bitboard b) { return b | s; }
191
- inline Bitboard operator^(Square s, Bitboard b) { return b ^ s; }
192
-
193
- inline Bitboard operator|(Square s1, Square s2) { return square_bb(s1) | s2; }
194
-
195
- constexpr bool more_than_one(Bitboard b) {
196
- return b & (b - 1);
197
- }
198
-
199
-
200
- inline Bitboard undo_move_board(Bitboard b, Move m) {
201
- return (from_sq(m) != SQ_NONE && (b & to_sq(m))) ? (b ^ to_sq(m)) | from_sq(m) : b;
202
- }
203
-
204
- /// board_size_bb() returns a bitboard representing all the squares
205
- /// on a board with given size.
206
-
207
- inline Bitboard board_size_bb(File f, Rank r) {
208
- return BoardSizeBB[f][r];
209
- }
210
-
211
- constexpr bool opposite_colors(Square s1, Square s2) {
212
- return (s1 + rank_of(s1) + s2 + rank_of(s2)) & 1;
213
- }
214
-
215
-
216
- /// rank_bb() and file_bb() return a bitboard representing all the squares on
217
- /// the given file or rank.
218
-
219
- constexpr Bitboard rank_bb(Rank r) {
220
- return Rank1BB << (FILE_NB * r);
221
- }
222
-
223
- constexpr Bitboard rank_bb(Square s) {
224
- return rank_bb(rank_of(s));
225
- }
226
-
227
- constexpr Bitboard file_bb(File f) {
228
- return FileABB << f;
229
- }
230
-
231
- constexpr Bitboard file_bb(Square s) {
232
- return file_bb(file_of(s));
233
- }
234
-
235
-
236
- /// shift() moves a bitboard one or two steps as specified by the direction D
237
-
238
- template<Direction D>
239
- constexpr Bitboard shift(Bitboard b) {
240
- return D == NORTH ? b << NORTH : D == SOUTH ? b >> NORTH
241
- : D == NORTH+NORTH? b <<(2 * NORTH) : D == SOUTH+SOUTH? b >> (2 * NORTH)
242
- : D == EAST ? (b & ~file_bb(FILE_MAX)) << EAST : D == WEST ? (b & ~FileABB) >> EAST
243
- : D == NORTH_EAST ? (b & ~file_bb(FILE_MAX)) << NORTH_EAST : D == NORTH_WEST ? (b & ~FileABB) << NORTH_WEST
244
- : D == SOUTH_EAST ? (b & ~file_bb(FILE_MAX)) >> NORTH_WEST : D == SOUTH_WEST ? (b & ~FileABB) >> NORTH_EAST
245
- : Bitboard(0);
246
- }
247
-
248
-
249
- /// shift() moves a bitboard one step along direction D (mainly for pawns)
250
-
251
- constexpr Bitboard shift(Direction D, Bitboard b) {
252
- return D == NORTH ? b << NORTH : D == SOUTH ? b >> NORTH
253
- : D == NORTH+NORTH? b <<(2 * NORTH) : D == SOUTH+SOUTH? b >> (2 * NORTH)
254
- : D == EAST ? (b & ~file_bb(FILE_MAX)) << EAST : D == WEST ? (b & ~FileABB) >> EAST
255
- : D == NORTH_EAST ? (b & ~file_bb(FILE_MAX)) << NORTH_EAST : D == NORTH_WEST ? (b & ~FileABB) << NORTH_WEST
256
- : D == SOUTH_EAST ? (b & ~file_bb(FILE_MAX)) >> NORTH_WEST : D == SOUTH_WEST ? (b & ~FileABB) >> NORTH_EAST
257
- : Bitboard(0);
258
- }
259
-
260
-
261
- /// pawn_attacks_bb() returns the squares attacked by pawns of the given color
262
- /// from the squares in the given bitboard.
263
-
264
- template<Color C>
265
- constexpr Bitboard pawn_attacks_bb(Bitboard b) {
266
- return C == WHITE ? shift<NORTH_WEST>(b) | shift<NORTH_EAST>(b)
267
- : shift<SOUTH_WEST>(b) | shift<SOUTH_EAST>(b);
268
- }
269
-
270
- inline Bitboard pawn_attacks_bb(Color c, Square s) {
271
-
272
- assert(is_ok(s));
273
- return PseudoAttacks[c][PAWN][s];
274
- }
275
-
276
-
277
- /// pawn_double_attacks_bb() returns the squares doubly attacked by pawns of the
278
- /// given color from the squares in the given bitboard.
279
-
280
- template<Color C>
281
- constexpr Bitboard pawn_double_attacks_bb(Bitboard b) {
282
- return C == WHITE ? shift<NORTH_WEST>(b) & shift<NORTH_EAST>(b)
283
- : shift<SOUTH_WEST>(b) & shift<SOUTH_EAST>(b);
284
- }
285
-
286
-
287
- /// adjacent_files_bb() returns a bitboard representing all the squares on the
288
- /// adjacent files of a given square.
289
-
290
- constexpr Bitboard adjacent_files_bb(Square s) {
291
- return shift<EAST>(file_bb(s)) | shift<WEST>(file_bb(s));
292
- }
293
-
294
-
295
- /// line_bb() returns a bitboard representing an entire line (from board edge
296
- /// to board edge) that intersects the two given squares. If the given squares
297
- /// are not on a same file/rank/diagonal, the function returns 0. For instance,
298
- /// line_bb(SQ_C4, SQ_F7) will return a bitboard with the A2-G8 diagonal.
299
-
300
- inline Bitboard line_bb(Square s1, Square s2) {
301
-
302
- assert(is_ok(s1) && is_ok(s2));
303
-
304
- return LineBB[s1][s2];
305
- }
306
-
307
-
308
- /// between_bb(s1, s2) returns a bitboard representing the squares in the semi-open
309
- /// segment between the squares s1 and s2 (excluding s1 but including s2). If the
310
- /// given squares are not on a same file/rank/diagonal, it returns s2. For instance,
311
- /// between_bb(SQ_C4, SQ_F7) will return a bitboard with squares D5, E6 and F7, but
312
- /// between_bb(SQ_E6, SQ_F8) will return a bitboard with the square F8. This trick
313
- /// allows to generate non-king evasion moves faster: the defending piece must either
314
- /// interpose itself to cover the check or capture the checking piece.
315
-
316
- inline Bitboard between_bb(Square s1, Square s2) {
317
-
318
- assert(is_ok(s1) && is_ok(s2));
319
-
320
- return BetweenBB[s1][s2];
321
- }
322
-
323
- inline Bitboard between_bb(Square s1, Square s2, PieceType pt) {
324
- if (pt == HORSE)
325
- return PseudoAttacks[WHITE][WAZIR][s2] & PseudoAttacks[WHITE][FERS][s1];
326
- else if (pt == JANGGI_ELEPHANT)
327
- return (PseudoAttacks[WHITE][WAZIR][s2] & PseudoAttacks[WHITE][ALFIL][s1])
328
- | (PseudoAttacks[WHITE][KNIGHT][s2] & PseudoAttacks[WHITE][FERS][s1]);
329
- else
330
- return between_bb(s1, s2);
331
- }
332
-
333
-
334
- /// forward_ranks_bb() returns a bitboard representing the squares on the ranks in
335
- /// front of the given one, from the point of view of the given color. For instance,
336
- /// forward_ranks_bb(BLACK, SQ_D3) will return the 16 squares on ranks 1 and 2.
337
-
338
- constexpr Bitboard forward_ranks_bb(Color c, Square s) {
339
- return c == WHITE ? (AllSquares ^ Rank1BB) << FILE_NB * relative_rank(WHITE, s, RANK_MAX)
340
- : (AllSquares ^ rank_bb(RANK_MAX)) >> FILE_NB * relative_rank(BLACK, s, RANK_MAX);
341
- }
342
-
343
- constexpr Bitboard forward_ranks_bb(Color c, Rank r) {
344
- return c == WHITE ? (AllSquares ^ Rank1BB) << FILE_NB * (r - RANK_1)
345
- : (AllSquares ^ rank_bb(RANK_MAX)) >> FILE_NB * (RANK_MAX - r);
346
- }
347
-
348
-
349
- /// zone_bb() returns a bitboard representing the squares on all the ranks
350
- /// in front of and on the given relative rank, from the point of view of the given color.
351
- /// For instance, zone_bb(BLACK, RANK_7) will return the 16 squares on ranks 1 and 2.
352
-
353
- inline Bitboard zone_bb(Color c, Rank r, Rank maxRank) {
354
- return forward_ranks_bb(c, relative_rank(c, r, maxRank)) | rank_bb(relative_rank(c, r, maxRank));
355
- }
356
-
357
-
358
- /// forward_file_bb() returns a bitboard representing all the squares along the
359
- /// line in front of the given one, from the point of view of the given color.
360
-
361
- constexpr Bitboard forward_file_bb(Color c, Square s) {
362
- return forward_ranks_bb(c, s) & file_bb(s);
363
- }
364
-
365
-
366
- /// pawn_attack_span() returns a bitboard representing all the squares that can
367
- /// be attacked by a pawn of the given color when it moves along its file, starting
368
- /// from the given square.
369
-
370
- constexpr Bitboard pawn_attack_span(Color c, Square s) {
371
- return forward_ranks_bb(c, s) & adjacent_files_bb(s);
372
- }
373
-
374
-
375
- /// passed_pawn_span() returns a bitboard which can be used to test if a pawn of
376
- /// the given color and on the given square is a passed pawn.
377
-
378
- constexpr Bitboard passed_pawn_span(Color c, Square s) {
379
- return pawn_attack_span(c, s) | forward_file_bb(c, s);
380
- }
381
-
382
-
383
- /// aligned() returns true if the squares s1, s2 and s3 are aligned either on a
384
- /// straight or on a diagonal line.
385
-
386
- inline bool aligned(Square s1, Square s2, Square s3) {
387
- return line_bb(s1, s2) & s3;
388
- }
389
-
390
-
391
- /// distance() functions return the distance between x and y, defined as the
392
- /// number of steps for a king in x to reach y.
393
-
394
- template<typename T1 = Square> inline int distance(Square x, Square y);
395
- template<> inline int distance<File>(Square x, Square y) { return std::abs(file_of(x) - file_of(y)); }
396
- template<> inline int distance<Rank>(Square x, Square y) { return std::abs(rank_of(x) - rank_of(y)); }
397
- template<> inline int distance<Square>(Square x, Square y) { return SquareDistance[x][y]; }
398
-
399
- inline int edge_distance(File f, File maxFile = FILE_H) { return std::min(f, File(maxFile - f)); }
400
- inline int edge_distance(Rank r, Rank maxRank = RANK_8) { return std::min(r, Rank(maxRank - r)); }
401
-
402
-
403
- template<RiderType R>
404
- inline Bitboard rider_attacks_bb(Square s, Bitboard occupied) {
405
-
406
- static_assert(R != NO_RIDER && !(R & (R - 1))); // exactly one bit
407
- const Magic& m = R == RIDER_ROOK_H ? RookMagicsH[s]
408
- : R == RIDER_ROOK_V ? RookMagicsV[s]
409
- : R == RIDER_CANNON_H ? CannonMagicsH[s]
410
- : R == RIDER_CANNON_V ? CannonMagicsV[s]
411
- : R == RIDER_LAME_DABBABA ? LameDabbabaMagics[s]
412
- : R == RIDER_HORSE ? HorseMagics[s]
413
- : R == RIDER_ELEPHANT ? ElephantMagics[s]
414
- : R == RIDER_JANGGI_ELEPHANT ? JanggiElephantMagics[s]
415
- : R == RIDER_CANNON_DIAG ? CannonDiagMagics[s]
416
- : R == RIDER_NIGHTRIDER ? NightriderMagics[s]
417
- : R == RIDER_GRASSHOPPER_H ? GrasshopperMagicsH[s]
418
- : R == RIDER_GRASSHOPPER_V ? GrasshopperMagicsV[s]
419
- : R == RIDER_GRASSHOPPER_D ? GrasshopperMagicsD[s]
420
- : BishopMagics[s];
421
- return m.attacks[m.index(occupied)];
422
- }
423
-
424
- inline Square lsb(Bitboard b);
425
-
426
- inline Bitboard rider_attacks_bb(RiderType R, Square s, Bitboard occupied) {
427
-
428
- assert(R != NO_RIDER && !(R & (R - 1))); // exactly one bit
429
- const Magic& m = magics[lsb(R)][s]; // re-use Bitboard lsb for riders
430
- return m.attacks[m.index(occupied)];
431
- }
432
-
433
-
434
- /// attacks_bb(Square) returns the pseudo attacks of the give piece type
435
- /// assuming an empty board.
436
-
437
- template<PieceType Pt>
438
- inline Bitboard attacks_bb(Square s) {
439
-
440
- assert((Pt != PAWN) && (is_ok(s)));
441
-
442
- return PseudoAttacks[WHITE][Pt][s];
443
- }
444
-
445
-
446
- /// attacks_bb(Square, Bitboard) returns the attacks by the given piece
447
- /// assuming the board is occupied according to the passed Bitboard.
448
- /// Sliding piece attacks do not continue passed an occupied square.
449
-
450
- template<PieceType Pt>
451
- inline Bitboard attacks_bb(Square s, Bitboard occupied) {
452
-
453
- assert((Pt != PAWN) && (is_ok(s)));
454
-
455
- switch (Pt)
456
- {
457
- case BISHOP: return rider_attacks_bb<RIDER_BISHOP>(s, occupied);
458
- case ROOK : return rider_attacks_bb<RIDER_ROOK_H>(s, occupied) | rider_attacks_bb<RIDER_ROOK_V>(s, occupied);
459
- case QUEEN : return attacks_bb<BISHOP>(s, occupied) | attacks_bb<ROOK>(s, occupied);
460
- default : return PseudoAttacks[WHITE][Pt][s];
461
- }
462
- }
463
-
464
- /// pop_rider() finds and clears a rider in a (hybrid) rider type
465
-
466
- inline RiderType pop_rider(RiderType* r) {
467
- assert(*r);
468
- const RiderType r2 = *r & ~(*r - 1);
469
- *r &= *r - 1;
470
- return r2;
471
- }
472
-
473
- inline Bitboard attacks_bb(Color c, PieceType pt, Square s, Bitboard occupied) {
474
- Bitboard b = LeaperAttacks[c][pt][s];
475
- RiderType r = AttackRiderTypes[pt];
476
- while (r)
477
- b |= rider_attacks_bb(pop_rider(&r), s, occupied);
478
- return b & PseudoAttacks[c][pt][s];
479
- }
480
-
481
-
482
- template <bool Initial=false>
483
- inline Bitboard moves_bb(Color c, PieceType pt, Square s, Bitboard occupied) {
484
- Bitboard b = LeaperMoves[Initial][c][pt][s];
485
- RiderType r = MoveRiderTypes[Initial][pt];
486
- while (r)
487
- b |= rider_attacks_bb(pop_rider(&r), s, occupied);
488
- return b & PseudoMoves[Initial][c][pt][s];
489
- }
490
-
491
-
492
- /// popcount() counts the number of non-zero bits in a bitboard
493
-
494
- inline int popcount(Bitboard b) {
495
-
496
- #ifndef USE_POPCNT
497
-
498
- #ifdef LARGEBOARDS
499
- union { Bitboard bb; uint16_t u[8]; } v = { b };
500
- return PopCnt16[v.u[0]] + PopCnt16[v.u[1]] + PopCnt16[v.u[2]] + PopCnt16[v.u[3]]
501
- + PopCnt16[v.u[4]] + PopCnt16[v.u[5]] + PopCnt16[v.u[6]] + PopCnt16[v.u[7]];
502
- #else
503
- union { Bitboard bb; uint16_t u[4]; } v = { b };
504
- return PopCnt16[v.u[0]] + PopCnt16[v.u[1]] + PopCnt16[v.u[2]] + PopCnt16[v.u[3]];
505
- #endif
506
-
507
- #elif defined(_MSC_VER) || defined(__INTEL_COMPILER)
508
-
509
- #ifdef LARGEBOARDS
510
- return (int)_mm_popcnt_u64(uint64_t(b >> 64)) + (int)_mm_popcnt_u64(uint64_t(b));
511
- #else
512
- return (int)_mm_popcnt_u64(b);
513
- #endif
514
-
515
- #else // Assumed gcc or compatible compiler
516
-
517
- #ifdef LARGEBOARDS
518
- return __builtin_popcountll(b >> 64) + __builtin_popcountll(b);
519
- #else
520
- return __builtin_popcountll(b);
521
- #endif
522
-
523
- #endif
524
- }
525
-
526
-
527
- /// lsb() and msb() return the least/most significant bit in a non-zero bitboard
528
-
529
- #if defined(__GNUC__) // GCC, Clang, ICC
530
-
531
- inline Square lsb(Bitboard b) {
532
- assert(b);
533
- #ifdef LARGEBOARDS
534
- if (!(b << 64))
535
- return Square(__builtin_ctzll(b >> 64) + 64);
536
- #endif
537
- return Square(__builtin_ctzll(b));
538
- }
539
-
540
- inline Square msb(Bitboard b) {
541
- assert(b);
542
- #ifdef LARGEBOARDS
543
- if (b >> 64)
544
- return Square(int(SQUARE_BIT_MASK) ^ __builtin_clzll(b >> 64));
545
- return Square(int(SQUARE_BIT_MASK) ^ (__builtin_clzll(b) + 64));
546
- #else
547
- return Square(int(SQUARE_BIT_MASK) ^ __builtin_clzll(b));
548
- #endif
549
- }
550
-
551
- #elif defined(_MSC_VER) // MSVC
552
-
553
- #ifdef _WIN64 // MSVC, WIN64
554
-
555
- inline Square lsb(Bitboard b) {
556
- assert(b);
557
- unsigned long idx;
558
- #ifdef LARGEBOARDS
559
- if (uint64_t(b))
560
- {
561
- _BitScanForward64(&idx, uint64_t(b));
562
- return Square(idx);
563
- }
564
- else
565
- {
566
- _BitScanForward64(&idx, uint64_t(b >> 64));
567
- return Square(idx + 64);
568
- }
569
- #else
570
- _BitScanForward64(&idx, b);
571
- return (Square) idx;
572
- #endif
573
- }
574
-
575
- inline Square msb(Bitboard b) {
576
- assert(b);
577
- unsigned long idx;
578
- #ifdef LARGEBOARDS
579
- if (b >> 64)
580
- {
581
- _BitScanReverse64(&idx, uint64_t(b >> 64));
582
- return Square(idx + 64);
583
- }
584
- else
585
- {
586
- _BitScanReverse64(&idx, uint64_t(b));
587
- return Square(idx);
588
- }
589
- #else
590
- _BitScanReverse64(&idx, b);
591
- return (Square) idx;
592
- #endif
593
- }
594
-
595
- #else // MSVC, WIN32
596
-
597
- inline Square lsb(Bitboard b) {
598
- assert(b);
599
- unsigned long idx;
600
-
601
- #ifdef LARGEBOARDS
602
- if (b << 96) {
603
- _BitScanForward(&idx, uint32_t(b));
604
- return Square(idx);
605
- } else if (b << 64) {
606
- _BitScanForward(&idx, uint32_t(b >> 32));
607
- return Square(idx + 32);
608
- } else if (b << 32) {
609
- _BitScanForward(&idx, uint32_t(b >> 64));
610
- return Square(idx + 64);
611
- } else {
612
- _BitScanForward(&idx, uint32_t(b >> 96));
613
- return Square(idx + 96);
614
- }
615
- #else
616
- if (b & 0xffffffff) {
617
- _BitScanForward(&idx, uint32_t(b));
618
- return Square(idx);
619
- } else {
620
- _BitScanForward(&idx, uint32_t(b >> 32));
621
- return Square(idx + 32);
622
- }
623
- #endif
624
- }
625
-
626
- inline Square msb(Bitboard b) {
627
- assert(b);
628
- unsigned long idx;
629
-
630
- #ifdef LARGEBOARDS
631
- if (b >> 96) {
632
- _BitScanReverse(&idx, uint32_t(b >> 96));
633
- return Square(idx + 96);
634
- } else if (b >> 64) {
635
- _BitScanReverse(&idx, uint32_t(b >> 64));
636
- return Square(idx + 64);
637
- } else
638
- #endif
639
- if (b >> 32) {
640
- _BitScanReverse(&idx, uint32_t(b >> 32));
641
- return Square(idx + 32);
642
- } else {
643
- _BitScanReverse(&idx, uint32_t(b));
644
- return Square(idx);
645
- }
646
- }
647
-
648
- #endif
649
-
650
- #else // Compiler is neither GCC nor MSVC compatible
651
-
652
- #error "Compiler not supported."
653
-
654
- #endif
655
-
656
- /// least_significant_square_bb() returns the bitboard of the least significant
657
- /// square of a non-zero bitboard. It is equivalent to square_bb(lsb(bb)).
658
-
659
- inline Bitboard least_significant_square_bb(Bitboard b) {
660
- assert(b);
661
- return b & -b;
662
- }
663
-
664
- /// pop_lsb() finds and clears the least significant bit in a non-zero bitboard
665
-
666
- inline Square pop_lsb(Bitboard& b) {
667
- assert(b);
668
- const Square s = lsb(b);
669
- b &= b - 1;
670
- return s;
671
- }
672
-
673
-
674
- /// frontmost_sq() returns the most advanced square for the given color,
675
- /// requires a non-zero bitboard.
676
- inline Square frontmost_sq(Color c, Bitboard b) {
677
- assert(b);
678
- return c == WHITE ? msb(b) : lsb(b);
679
- }
680
-
681
-
682
- /// popcount() counts the number of non-zero bits in a piece set
683
-
684
- inline int popcount(PieceSet ps) {
685
-
686
- #ifndef USE_POPCNT
687
-
688
- union { uint64_t bb; uint16_t u[4]; } v = { (uint64_t)ps };
689
- return PopCnt16[v.u[0]] + PopCnt16[v.u[1]] + PopCnt16[v.u[2]] + PopCnt16[v.u[3]];
690
-
691
- #elif defined(_MSC_VER) || defined(__INTEL_COMPILER)
692
-
693
- return (int)_mm_popcnt_u64(ps);
694
-
695
- #else // Assumed gcc or compatible compiler
696
-
697
- return __builtin_popcountll(ps);
698
-
699
- #endif
700
- }
701
-
702
- /// lsb() and msb() return the least/most significant bit in a non-zero piece set
703
-
704
- #if defined(__GNUC__) // GCC, Clang, ICC
705
-
706
- inline PieceType lsb(PieceSet ps) {
707
- assert(ps);
708
- return PieceType(__builtin_ctzll(ps));
709
- }
710
-
711
- inline PieceType msb(PieceSet ps) {
712
- assert(ps);
713
- return PieceType((PIECE_TYPE_NB - 1) ^ __builtin_clzll(ps));
714
- }
715
-
716
- #elif defined(_MSC_VER) // MSVC
717
-
718
- #ifdef _WIN64 // MSVC, WIN64
719
-
720
- inline PieceType lsb(PieceSet ps) {
721
- assert(ps);
722
- unsigned long idx;
723
- _BitScanForward64(&idx, ps);
724
- return (PieceType) idx;
725
- }
726
-
727
- inline PieceType msb(PieceSet ps) {
728
- assert(ps);
729
- unsigned long idx;
730
- _BitScanReverse64(&idx, ps);
731
- return (PieceType) idx;
732
- }
733
-
734
- #else // MSVC, WIN32
735
-
736
- inline PieceType lsb(PieceSet ps) {
737
- assert(ps);
738
- unsigned long idx;
739
-
740
- if (ps & 0xffffffff) {
741
- _BitScanForward(&idx, uint32_t(ps));
742
- return PieceType(idx);
743
- } else {
744
- _BitScanForward(&idx, uint32_t(ps >> 32));
745
- return PieceType(idx + 32);
746
- }
747
- }
748
-
749
- inline PieceType msb(PieceSet ps) {
750
- assert(ps);
751
- unsigned long idx;
752
- if (ps >> 32) {
753
- _BitScanReverse(&idx, uint32_t(ps >> 32));
754
- return PieceType(idx + 32);
755
- } else {
756
- _BitScanReverse(&idx, uint32_t(ps));
757
- return PieceType(idx);
758
- }
759
- }
760
-
761
- #endif
762
-
763
- #else // Compiler is neither GCC nor MSVC compatible
764
-
765
- #error "Compiler not supported."
766
-
767
- #endif
768
-
769
- /// pop_lsb() and pop_msb() find and clear the least/most significant bit in a non-zero piece set
770
-
771
- inline PieceType pop_lsb(PieceSet& ps) {
772
- assert(ps);
773
- const PieceType pt = lsb(ps);
774
- ps &= PieceSet(ps - 1);
775
- return pt;
776
- }
777
-
778
- inline PieceType pop_msb(PieceSet& ps) {
779
- assert(ps);
780
- const PieceType pt = msb(ps);
781
- ps &= ~piece_set(pt);
782
- return pt;
783
- }
784
-
785
- } // namespace Stockfish
786
-
787
- #endif // #ifndef BITBOARD_H_INCLUDED
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/src/endgame.cpp DELETED
@@ -1,1321 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
4
-
5
- Stockfish is free software: you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation, either version 3 of the License, or
8
- (at your option) any later version.
9
-
10
- Stockfish is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- You should have received a copy of the GNU General Public License
16
- along with this program. If not, see <http://www.gnu.org/licenses/>.
17
- */
18
-
19
- #include <cassert>
20
-
21
- #include "bitboard.h"
22
- #include "endgame.h"
23
- #include "movegen.h"
24
-
25
- namespace Stockfish {
26
-
27
- namespace {
28
-
29
- // Used to drive the king towards the edge of the board
30
- // in KX vs K and KQ vs KR endgames.
31
- // Values range from 27 (center squares) to 90 (in the corners)
32
- inline int push_to_edge(Square s, const Position& pos) {
33
- int rd = edge_distance(rank_of(s), pos.max_rank()), fd = edge_distance(file_of(s), pos.max_file());
34
- return 90 - (7 * fd * fd / 2 + 7 * rd * rd / 2);
35
- }
36
-
37
- // Used to drive the king towards A1H8 corners in KBN vs K endgames.
38
- // Values range from 0 on A8H1 diagonal to 7 in A1H8 corners.
39
- inline int push_to_corner(Square s, const Position& pos) {
40
- return abs((pos.max_file() + pos.max_rank()) / 2 - rank_of(s) - file_of(s));
41
- }
42
-
43
- // Used to drive the king towards the edge of the board in KSF vs K.
44
- inline int push_to_opposing_edge(Square s, const Position& pos) {
45
- int rd = rank_of(s), fd = edge_distance(file_of(s), pos.max_file());
46
- return 20 - (7 * fd * fd / 2 - 7 * rd * rd / 4);
47
- }
48
-
49
- // Drive a piece close to or away from another piece
50
- inline int push_close(Square s1, Square s2) { return 140 - 20 * distance(s1, s2); }
51
- inline int push_away(Square s1, Square s2) { return 120 - push_close(s1, s2); }
52
-
53
- #ifndef NDEBUG
54
- bool verify_material(const Position& pos, Color c, Value npm, int pawnsCnt) {
55
- return pos.non_pawn_material(c) == npm && pos.count<PAWN>(c) == pawnsCnt;
56
- }
57
- #endif
58
-
59
- // Map the square as if strongSide is white and strongSide's only pawn
60
- // is on the left half of the board.
61
- Square normalize(const Position& pos, Color strongSide, Square sq) {
62
-
63
- assert(pos.count<PAWN>(strongSide) == 1);
64
-
65
- if (file_of(pos.square<PAWN>(strongSide)) > pos.max_file() / 2)
66
- sq = flip_file(sq, pos.max_file());
67
-
68
- return strongSide == WHITE ? sq : flip_rank(sq, pos.max_rank());
69
- }
70
-
71
- } // namespace
72
-
73
-
74
- namespace Endgames {
75
-
76
- std::pair<Map<Value>, Map<ScaleFactor>> maps;
77
-
78
- void init() {
79
-
80
- add<KPK>("KPK");
81
- add<KNNK>("KNNK");
82
- add<KBNK>("KBNK");
83
- add<KRKP>("KRKP");
84
- add<KRKB>("KRKB");
85
- add<KRKN>("KRKN");
86
- add<KQKP>("KQKP");
87
- add<KQKR>("KQKR");
88
- add<KNNKP>("KNNKP");
89
-
90
- // Fairy piece endgames
91
- add<KNSK>("KNSK");
92
- add<KNFK>("KNFK");
93
- add<KNSFKR>("KNSFKR");
94
- add<KSFK>("KSFK");
95
- add<KSFKF>("KSFKF");
96
- add<KRKS>("KRKS");
97
- add<KCKR>("KCKR");
98
- add<KAKR>("KAKR");
99
-
100
- // Anti
101
- add<RK, EG_EVAL_ANTI>("RvM");
102
- add<KN, EG_EVAL_ANTI>("MvN");
103
- add<NN, EG_EVAL_ANTI>("NvN");
104
-
105
- // Atomic
106
- add<KPK, EG_EVAL_ATOMIC>("MPvM");
107
- add<KNK, EG_EVAL_ATOMIC>("MNvM");
108
- add<KBK, EG_EVAL_ATOMIC>("MBvM");
109
- add<KRK, EG_EVAL_ATOMIC>("MRvM");
110
- add<KQK, EG_EVAL_ATOMIC>("MQvM");
111
- add<KNNK, EG_EVAL_ATOMIC>("MNNvM");
112
-
113
- // Duck
114
- add<KBK, EG_EVAL_DUCK>("MBvM");
115
- add<KNK, EG_EVAL_DUCK>("MNvM");
116
- add<KPK, EG_EVAL_DUCK>("MPvM");
117
-
118
- // Racing kings
119
- add<KQK, EG_EVAL_RK>("KQK");
120
- add<KRK, EG_EVAL_RK>("KRK");
121
- add<KK, EG_EVAL_RK>("KK");
122
-
123
- add<KRPKB>("KRPKB");
124
- add<KBPKB>("KBPKB");
125
- add<KBPKN>("KBPKN");
126
- add<KBPPKB>("KBPPKB");
127
- add<KRPPKRP>("KRPPKRP");
128
- }
129
- }
130
-
131
-
132
- /// Mate with KX vs K. This function is used to evaluate positions with
133
- /// king and plenty of material vs a lone king. It simply gives the
134
- /// attacking side a bonus for driving the defending king towards the edge
135
- /// of the board, and for keeping the distance between the two kings small.
136
- template<>
137
- Value Endgame<KXK>::operator()(const Position& pos) const {
138
-
139
- assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
140
- assert(!pos.checkers()); // Eval is never called when in check
141
-
142
- // Stalemate detection with lone king
143
- if (pos.side_to_move() == weakSide && !MoveList<LEGAL>(pos).size())
144
- return VALUE_DRAW;
145
-
146
- Square strongKing = pos.square<KING>(strongSide);
147
- Square weakKing = pos.square<KING>(weakSide);
148
-
149
- Value result = pos.non_pawn_material(strongSide)
150
- + pos.count<PAWN>(strongSide) * PawnValueEg
151
- + push_to_edge(weakKing, pos)
152
- + push_close(strongKing, weakKing);
153
-
154
- if ( pos.count<QUEEN>(strongSide)
155
- || pos.count<ROOK>(strongSide)
156
- ||(pos.count<BISHOP>(strongSide) && pos.count<KNIGHT>(strongSide))
157
- || ( (pos.pieces(strongSide, BISHOP) & ~DarkSquares)
158
- && (pos.pieces(strongSide, BISHOP) & DarkSquares))
159
- || pos.count<SILVER>(strongSide) >= 2
160
- ||(pos.count<SILVER>(strongSide) && pos.count<KNIGHT>(strongSide))
161
- ||(pos.count<SILVER>(strongSide) && pos.count<FERS>(strongSide))
162
- ||(pos.count<KNIGHT>(strongSide) && pos.count<FERS>(strongSide) >= 2)
163
- ||(pos.count<FERS>(strongSide) >= 3
164
- && ( DarkSquares & pos.pieces(strongSide, FERS))
165
- && (~DarkSquares & pos.pieces(strongSide, FERS))))
166
- result = std::min(result + VALUE_KNOWN_WIN, VALUE_TB_WIN_IN_MAX_PLY - 1);
167
-
168
- return strongSide == pos.side_to_move() ? result : -result;
169
- }
170
-
171
-
172
- /// Mate with KBN vs K. This is similar to KX vs K, but we have to drive the
173
- /// defending king towards a corner square that our bishop attacks.
174
- template<>
175
- Value Endgame<KBNK>::operator()(const Position& pos) const {
176
-
177
- assert(verify_material(pos, strongSide, KnightValueMg + BishopValueMg, 0));
178
- assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
179
-
180
- Square strongKing = pos.square<KING>(strongSide);
181
- Square strongBishop = pos.square<BISHOP>(strongSide);
182
- Square weakKing = pos.square<KING>(weakSide);
183
-
184
- // If our bishop does not attack A1/H8, we flip the enemy king square
185
- // to drive to opposite corners (A8/H1).
186
-
187
- Value result = (VALUE_KNOWN_WIN + 3520)
188
- + push_close(strongKing, weakKing)
189
- + 420 * push_to_corner(opposite_colors(strongBishop, SQ_A1) ? flip_file(weakKing, pos.max_file()) : weakKing, pos);
190
-
191
- assert(abs(result) < VALUE_TB_WIN_IN_MAX_PLY);
192
- return strongSide == pos.side_to_move() ? result : -result;
193
- }
194
-
195
-
196
- /// KP vs K. This endgame is evaluated with the help of a bitbase
197
- template<>
198
- Value Endgame<KPK>::operator()(const Position& pos) const {
199
-
200
- assert(verify_material(pos, strongSide, VALUE_ZERO, 1));
201
- assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
202
-
203
- // Assume strongSide is white and the pawn is on files A-D
204
- Square strongKing = normalize(pos, strongSide, pos.square<KING>(strongSide));
205
- Square strongPawn = normalize(pos, strongSide, pos.square<PAWN>(strongSide));
206
- Square weakKing = normalize(pos, strongSide, pos.square<KING>(weakSide));
207
-
208
- Color us = strongSide == pos.side_to_move() ? WHITE : BLACK;
209
-
210
- // Non-standard promotion, evaluation unclear
211
- if ( pos.promotion_zone(us) != rank_bb(relative_rank(us, RANK_8, pos.max_rank()))
212
- || RANK_MAX != RANK_8
213
- || !(pos.promotion_piece_types(us) & QUEEN))
214
- {
215
- Value result = PawnValueEg + Value(rank_of(strongPawn));
216
- return strongSide == pos.side_to_move() ? result : -result;
217
- }
218
-
219
- if (!Bitbases::probe(strongKing, strongPawn, weakKing, us))
220
- return VALUE_DRAW;
221
-
222
- Value result = VALUE_KNOWN_WIN + PawnValueEg + Value(rank_of(strongPawn));
223
-
224
- return strongSide == pos.side_to_move() ? result : -result;
225
- }
226
-
227
-
228
- /// KR vs KP. This is a somewhat tricky endgame to evaluate precisely without
229
- /// a bitbase. The function below returns drawish scores when the pawn is
230
- /// far advanced with support of the king, while the attacking king is far
231
- /// away.
232
- template<>
233
- Value Endgame<KRKP>::operator()(const Position& pos) const {
234
-
235
- assert(verify_material(pos, strongSide, RookValueMg, 0));
236
- assert(verify_material(pos, weakSide, VALUE_ZERO, 1));
237
-
238
- Square strongKing = pos.square<KING>(strongSide);
239
- Square weakKing = pos.square<KING>(weakSide);
240
- Square strongRook = pos.square<ROOK>(strongSide);
241
- Square weakPawn = pos.square<PAWN>(weakSide);
242
- Square queeningSquare = make_square(file_of(weakPawn), relative_rank(weakSide, RANK_8));
243
- Value result;
244
-
245
- // If the stronger side's king is in front of the pawn, it's a win
246
- if (forward_file_bb(strongSide, strongKing) & weakPawn)
247
- result = RookValueEg - distance(strongKing, weakPawn);
248
-
249
- // If the weaker side's king is too far from the pawn and the rook,
250
- // it's a win.
251
- else if ( distance(weakKing, weakPawn) >= 3 + (pos.side_to_move() == weakSide)
252
- && distance(weakKing, strongRook) >= 3)
253
- result = RookValueEg - distance(strongKing, weakPawn);
254
-
255
- // If the pawn is far advanced and supported by the defending king,
256
- // the position is drawish
257
- else if ( relative_rank(strongSide, weakKing) <= RANK_3
258
- && distance(weakKing, weakPawn) == 1
259
- && relative_rank(strongSide, strongKing) >= RANK_4
260
- && distance(strongKing, weakPawn) > 2 + (pos.side_to_move() == strongSide))
261
- result = Value(80) - 8 * distance(strongKing, weakPawn);
262
-
263
- else
264
- result = Value(200) - 8 * ( distance(strongKing, weakPawn + pawn_push(weakSide))
265
- - distance(weakKing, weakPawn + pawn_push(weakSide))
266
- - distance(weakPawn, queeningSquare));
267
-
268
- return strongSide == pos.side_to_move() ? result : -result;
269
- }
270
-
271
-
272
- /// KR vs KB. This is very simple, and always returns drawish scores. The
273
- /// score is slightly bigger when the defending king is close to the edge.
274
- template<>
275
- Value Endgame<KRKB>::operator()(const Position& pos) const {
276
-
277
- assert(verify_material(pos, strongSide, RookValueMg, 0));
278
- assert(verify_material(pos, weakSide, BishopValueMg, 0));
279
-
280
- Value result = Value(push_to_edge(pos.square<KING>(weakSide), pos));
281
- return strongSide == pos.side_to_move() ? result : -result;
282
- }
283
-
284
-
285
- /// KR vs KN. The attacking side has slightly better winning chances than
286
- /// in KR vs KB, particularly if the king and the knight are far apart.
287
- template<>
288
- Value Endgame<KRKN>::operator()(const Position& pos) const {
289
-
290
- assert(verify_material(pos, strongSide, RookValueMg, 0));
291
- assert(verify_material(pos, weakSide, KnightValueMg, 0));
292
-
293
- Square weakKing = pos.square<KING>(weakSide);
294
- Square weakKnight = pos.square<KNIGHT>(weakSide);
295
- Value result = Value(push_to_edge(weakKing, pos) + push_away(weakKing, weakKnight));
296
- return strongSide == pos.side_to_move() ? result : -result;
297
- }
298
-
299
-
300
- /// KQ vs KP. In general, this is a win for the stronger side, but there are a
301
- /// few important exceptions. A pawn on 7th rank and on the A,C,F or H files
302
- /// with a king positioned next to it can be a draw, so in that case, we only
303
- /// use the distance between the kings.
304
- template<>
305
- Value Endgame<KQKP>::operator()(const Position& pos) const {
306
-
307
- assert(verify_material(pos, strongSide, QueenValueMg, 0));
308
- assert(verify_material(pos, weakSide, VALUE_ZERO, 1));
309
-
310
- Square strongKing = pos.square<KING>(strongSide);
311
- Square weakKing = pos.square<KING>(weakSide);
312
- Square weakPawn = pos.square<PAWN>(weakSide);
313
-
314
- Value result = Value(push_close(strongKing, weakKing));
315
-
316
- if ( relative_rank(weakSide, weakPawn) != RANK_7
317
- || distance(weakKing, weakPawn) != 1
318
- || ((FileBBB | FileDBB | FileEBB | FileGBB) & weakPawn))
319
- result += QueenValueEg - PawnValueEg;
320
-
321
- return strongSide == pos.side_to_move() ? result : -result;
322
- }
323
-
324
-
325
- /// KQ vs KR. This is almost identical to KX vs K: we give the attacking
326
- /// king a bonus for having the kings close together, and for forcing the
327
- /// defending king towards the edge. If we also take care to avoid null move for
328
- /// the defending side in the search, this is usually sufficient to win KQ vs KR.
329
- template<>
330
- Value Endgame<KQKR>::operator()(const Position& pos) const {
331
-
332
- assert(verify_material(pos, strongSide, QueenValueMg, 0));
333
- assert(verify_material(pos, weakSide, RookValueMg, 0));
334
-
335
- Square strongKing = pos.square<KING>(strongSide);
336
- Square weakKing = pos.square<KING>(weakSide);
337
-
338
- Value result = QueenValueEg
339
- - RookValueEg
340
- + push_to_edge(weakKing, pos)
341
- + push_close(strongKing, weakKing);
342
-
343
- return strongSide == pos.side_to_move() ? result : -result;
344
- }
345
-
346
-
347
- /// KC vs KR. Drawish, but good winning chances if king and rook are close.
348
- template<>
349
- Value Endgame<KCKR>::operator()(const Position& pos) const {
350
-
351
- assert(verify_material(pos, strongSide, ChancellorValueMg, 0));
352
- assert(verify_material(pos, weakSide, RookValueMg, 0));
353
-
354
- Square strongKing = pos.square<KING>(strongSide);
355
- Square weakKing = pos.square<KING>(weakSide);
356
- Square weakRook = pos.square<ROOK>(weakSide);
357
-
358
- Value result = Value(push_to_edge(weakKing, pos))
359
- + push_close(strongKing, weakKing)
360
- + push_close(weakRook, weakKing);
361
-
362
- return strongSide == pos.side_to_move() ? result : -result;
363
- }
364
-
365
-
366
- /// KA vs KR. Very drawish.
367
- template<>
368
- Value Endgame<KAKR>::operator()(const Position& pos) const {
369
-
370
- assert(verify_material(pos, strongSide, ArchbishopValueMg, 0));
371
- assert(verify_material(pos, weakSide, RookValueMg, 0));
372
-
373
- Square strongKing = pos.square<KING>(strongSide);
374
- Square weakKing = pos.square<KING>(weakSide);
375
-
376
- Value result = Value(push_to_edge(weakKing, pos))
377
- + push_close(strongKing, weakKing);
378
-
379
- return strongSide == pos.side_to_move() ? result : -result;
380
- }
381
-
382
-
383
- /// KNN vs KP. Very drawish, but there are some mate opportunities if we can
384
- /// press the weakSide King to a corner before the pawn advances too much.
385
- template<>
386
- Value Endgame<KNNKP>::operator()(const Position& pos) const {
387
-
388
- assert(verify_material(pos, strongSide, 2 * KnightValueMg, 0));
389
- assert(verify_material(pos, weakSide, VALUE_ZERO, 1));
390
-
391
- Square weakKing = pos.square<KING>(weakSide);
392
- Square weakPawn = pos.square<PAWN>(weakSide);
393
-
394
- Value result = PawnValueEg
395
- + 2 * push_to_edge(weakKing, pos)
396
- - 10 * relative_rank(weakSide, weakPawn);
397
-
398
- return strongSide == pos.side_to_move() ? result : -result;
399
- }
400
-
401
-
402
- /// Some cases of trivial draws
403
- template<> Value Endgame<KNNK>::operator()(const Position&) const { return VALUE_DRAW; }
404
-
405
-
406
- /// KFsPs vs K.
407
- template<>
408
- Value Endgame<KFsPsK>::operator()(const Position& pos) const {
409
-
410
- assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
411
-
412
- Square winnerKSq = pos.square<KING>(strongSide);
413
- Square loserKSq = pos.square<KING>(weakSide);
414
-
415
- Value result = pos.non_pawn_material(strongSide)
416
- + pos.count<PAWN>(strongSide) * PawnValueEg
417
- + push_to_edge(loserKSq, pos)
418
- + push_close(winnerKSq, loserKSq);
419
-
420
- if ( pos.count<FERS>(strongSide) >= 3
421
- && ( DarkSquares & pos.pieces(strongSide, FERS))
422
- && (~DarkSquares & pos.pieces(strongSide, FERS)))
423
- result = std::min(result + VALUE_KNOWN_WIN, VALUE_TB_WIN_IN_MAX_PLY - 1);
424
- else if (pos.count<FERS>(strongSide) + pos.count<PAWN>(strongSide) < 3)
425
- return VALUE_DRAW;
426
- else
427
- {
428
- bool dark = DarkSquares & pos.pieces(strongSide, FERS);
429
- bool light = ~DarkSquares & pos.pieces(strongSide, FERS);
430
-
431
- // Determine the color of ferzes from promoting pawns
432
- Bitboard b = pos.pieces(strongSide, PAWN);
433
- while (b && (!dark || !light))
434
- {
435
- Square s = pos.promotion_square(strongSide, pop_lsb(b));
436
- if (s != SQ_NONE)
437
- {
438
- if (DarkSquares & s)
439
- dark = true;
440
- else
441
- light = true;
442
- }
443
- }
444
- if (!dark || !light)
445
- return VALUE_DRAW; // we can not checkmate with same colored ferzes
446
- }
447
-
448
- return strongSide == pos.side_to_move() ? result : -result;
449
- }
450
-
451
-
452
- /// Mate with KNS vs K.
453
- template<>
454
- Value Endgame<KNSK>::operator()(const Position& pos) const {
455
-
456
- assert(verify_material(pos, strongSide, KnightValueMg + SilverValueMg, 0));
457
- assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
458
-
459
- Square winnerKSq = pos.square<KING>(strongSide);
460
- Square loserKSq = pos.square<KING>(weakSide);
461
-
462
- Value result = VALUE_KNOWN_WIN
463
- + push_close(winnerKSq, loserKSq)
464
- + push_to_opposing_edge(relative_square(strongSide, loserKSq, pos.max_rank()), pos);
465
-
466
- return strongSide == pos.side_to_move() ? result : -result;
467
- }
468
-
469
-
470
- /// KNF vs K. Can only be won if the weaker side's king
471
- /// is close to a corner of the same color as the fers.
472
- template<>
473
- Value Endgame<KNFK>::operator()(const Position& pos) const {
474
-
475
- assert(verify_material(pos, strongSide, KnightValueMg + FersValueMg, 0));
476
- assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
477
-
478
- Square winnerKSq = pos.square<KING>(strongSide);
479
- Square loserKSq = pos.square<KING>(weakSide);
480
- Square fersSq = pos.square<FERS>(strongSide);
481
-
482
- // tries to drive toward corners A1 or H8. If we have a
483
- // fers that cannot reach the above squares, we flip the kings in order
484
- // to drive the enemy toward corners A8 or H1.
485
- if (opposite_colors(fersSq, SQ_A1))
486
- {
487
- winnerKSq = relative_square(BLACK, winnerKSq, pos.max_rank());
488
- loserKSq = relative_square(BLACK, loserKSq, pos.max_rank());
489
- }
490
-
491
- Value result = Value(push_close(winnerKSq, loserKSq))
492
- + 50 * push_to_corner(loserKSq, pos);
493
-
494
- return strongSide == pos.side_to_move() ? result : -result;
495
- }
496
-
497
-
498
- /// KNSFKR vs K.
499
- template<>
500
- Value Endgame<KNSFKR>::operator()(const Position& pos) const {
501
-
502
- assert(verify_material(pos, strongSide, KnightValueMg + SilverValueMg + FersValueMg, 0));
503
- assert(verify_material(pos, weakSide, RookValueMg, 0));
504
-
505
- Square winnerKSq = pos.square<KING>(strongSide);
506
- Square loserKSq = pos.square<KING>(weakSide);
507
-
508
- Value result = KnightValueEg + SilverValueEg + FersValueEg - RookValueEg
509
- + push_close(winnerKSq, loserKSq)
510
- + push_to_opposing_edge(relative_square(strongSide, loserKSq, pos.max_rank()), pos);
511
-
512
- return strongSide == pos.side_to_move() ? result : -result;
513
- }
514
-
515
-
516
- /// Mate with KSF vs K.
517
- template<>
518
- Value Endgame<KSFK>::operator()(const Position& pos) const {
519
-
520
- assert(verify_material(pos, strongSide, SilverValueMg + FersValueMg, 0));
521
- assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
522
-
523
- Square winnerKSq = pos.square<KING>(strongSide);
524
- Square loserKSq = pos.square<KING>(weakSide);
525
-
526
- Value result = VALUE_KNOWN_WIN
527
- + push_close(winnerKSq, loserKSq)
528
- + push_to_opposing_edge(relative_square(strongSide, loserKSq, pos.max_rank()), pos);
529
-
530
- return strongSide == pos.side_to_move() ? result : -result;
531
- }
532
-
533
-
534
- /// Mate with KSF vs KF.
535
- template<>
536
- Value Endgame<KSFKF>::operator()(const Position& pos) const {
537
-
538
- assert(verify_material(pos, strongSide, SilverValueMg + FersValueMg, 0));
539
- assert(verify_material(pos, weakSide, FersValueMg, 0));
540
-
541
- Square winnerKSq = pos.square<KING>(strongSide);
542
- Square loserKSq = pos.square<KING>(weakSide);
543
- Square fersSq = pos.square<FERS>(weakSide);
544
-
545
- Value result = SilverValueEg
546
- + push_close(winnerKSq, loserKSq)
547
- + push_away(fersSq, loserKSq)
548
- + push_to_opposing_edge(relative_square(strongSide, loserKSq, pos.max_rank()), pos);
549
-
550
- return strongSide == pos.side_to_move() ? result : -result;
551
- }
552
-
553
-
554
- /// KR vs KS
555
- template<>
556
- Value Endgame<KRKS>::operator()(const Position& pos) const {
557
-
558
- assert(verify_material(pos, strongSide, RookValueMg, 0));
559
- assert(verify_material(pos, weakSide, SilverValueMg, 0));
560
-
561
- Square winnerKSq = pos.square<KING>(strongSide);
562
- Square loserKSq = pos.square<KING>(weakSide);
563
-
564
- Value result = RookValueEg
565
- - SilverValueEg
566
- + push_to_edge(loserKSq, pos)
567
- + push_close(winnerKSq, loserKSq);
568
-
569
- return strongSide == pos.side_to_move() ? result : -result;
570
- }
571
-
572
-
573
- /// KB and one or more pawns vs K. It checks for draws with rook pawns and
574
- /// a bishop of the wrong color. If such a draw is detected, SCALE_FACTOR_DRAW
575
- /// is returned. If not, the return value is SCALE_FACTOR_NONE, i.e. no scaling
576
- /// will be used.
577
- template<>
578
- ScaleFactor Endgame<KBPsK>::operator()(const Position& pos) const {
579
-
580
- assert(pos.non_pawn_material(strongSide) == BishopValueMg);
581
- assert(pos.count<PAWN>(strongSide) >= 1);
582
-
583
- // No assertions about the material of weakSide, because we want draws to
584
- // be detected even when the weaker side has some pawns.
585
-
586
- Bitboard strongPawns = pos.pieces(strongSide, PAWN);
587
- Bitboard allPawns = pos.pieces(PAWN);
588
-
589
- Square strongBishop = pos.square<BISHOP>(strongSide);
590
- Square weakKing = pos.square<KING>(weakSide);
591
- Square strongKing = pos.square<KING>(strongSide);
592
-
593
- // All strongSide pawns are on a single rook file?
594
- if (!(strongPawns & ~FileABB) || !(strongPawns & ~FileHBB))
595
- {
596
- Square queeningSquare = relative_square(strongSide, make_square(file_of(lsb(strongPawns)), RANK_8));
597
-
598
- if ( opposite_colors(queeningSquare, strongBishop)
599
- && distance(queeningSquare, weakKing) <= 1)
600
- return SCALE_FACTOR_DRAW;
601
- }
602
-
603
- // If all the pawns are on the same B or G file, then it's potentially a draw
604
- if ((!(allPawns & ~FileBBB) || !(allPawns & ~FileGBB))
605
- && pos.non_pawn_material(weakSide) == 0
606
- && pos.count<PAWN>(weakSide) >= 1)
607
- {
608
- // Get the least advanced weakSide pawn
609
- Square weakPawn = frontmost_sq(strongSide, pos.pieces(weakSide, PAWN));
610
-
611
- // There's potential for a draw if our pawn is blocked on the 7th rank,
612
- // the bishop cannot attack it or they only have one pawn left.
613
- if ( relative_rank(strongSide, weakPawn) == RANK_7
614
- && (strongPawns & (weakPawn + pawn_push(weakSide)))
615
- && (opposite_colors(strongBishop, weakPawn) || !more_than_one(strongPawns)))
616
- {
617
- int strongKingDist = distance(weakPawn, strongKing);
618
- int weakKingDist = distance(weakPawn, weakKing);
619
-
620
- // It's a draw if the weak king is on its back two ranks, within 2
621
- // squares of the blocking pawn and the strong king is not
622
- // closer. (I think this rule only fails in practically
623
- // unreachable positions such as 5k1K/6p1/6P1/8/8/3B4/8/8 w
624
- // and positions where qsearch will immediately correct the
625
- // problem such as 8/4k1p1/6P1/1K6/3B4/8/8/8 w).
626
- if ( relative_rank(strongSide, weakKing) >= RANK_7
627
- && weakKingDist <= 2
628
- && weakKingDist <= strongKingDist)
629
- return SCALE_FACTOR_DRAW;
630
- }
631
- }
632
-
633
- return SCALE_FACTOR_NONE;
634
- }
635
-
636
-
637
- /// KQ vs KR and one or more pawns. It tests for fortress draws with a rook on
638
- /// the third rank defended by a pawn.
639
- template<>
640
- ScaleFactor Endgame<KQKRPs>::operator()(const Position& pos) const {
641
-
642
- assert(verify_material(pos, strongSide, QueenValueMg, 0));
643
- assert(pos.count<ROOK>(weakSide) == 1);
644
- assert(pos.count<PAWN>(weakSide) >= 1);
645
-
646
- Square strongKing = pos.square<KING>(strongSide);
647
- Square weakKing = pos.square<KING>(weakSide);
648
- Square weakRook = pos.square<ROOK>(weakSide);
649
-
650
- if ( relative_rank(weakSide, weakKing) <= RANK_2
651
- && relative_rank(weakSide, strongKing) >= RANK_4
652
- && relative_rank(weakSide, weakRook) == RANK_3
653
- && ( pos.pieces(weakSide, PAWN)
654
- & attacks_bb<KING>(weakKing)
655
- & pawn_attacks_bb(strongSide, weakRook)))
656
- return SCALE_FACTOR_DRAW;
657
-
658
- return SCALE_FACTOR_NONE;
659
- }
660
-
661
-
662
- /// KRP vs KR. This function knows a handful of the most important classes of
663
- /// drawn positions, but is far from perfect. It would probably be a good idea
664
- /// to add more knowledge in the future.
665
- ///
666
- /// It would also be nice to rewrite the actual code for this function,
667
- /// which is mostly copied from Glaurung 1.x, and isn't very pretty.
668
- template<>
669
- ScaleFactor Endgame<KRPKR>::operator()(const Position& pos) const {
670
-
671
- assert(verify_material(pos, strongSide, RookValueMg, 1));
672
- assert(verify_material(pos, weakSide, RookValueMg, 0));
673
-
674
- // Assume strongSide is white and the pawn is on files A-D
675
- Square strongKing = normalize(pos, strongSide, pos.square<KING>(strongSide));
676
- Square strongRook = normalize(pos, strongSide, pos.square<ROOK>(strongSide));
677
- Square strongPawn = normalize(pos, strongSide, pos.square<PAWN>(strongSide));
678
- Square weakKing = normalize(pos, strongSide, pos.square<KING>(weakSide));
679
- Square weakRook = normalize(pos, strongSide, pos.square<ROOK>(weakSide));
680
-
681
- File pawnFile = file_of(strongPawn);
682
- Rank pawnRank = rank_of(strongPawn);
683
- Square queeningSquare = make_square(pawnFile, RANK_8);
684
- int tempo = (pos.side_to_move() == strongSide);
685
-
686
- // If the pawn is not too far advanced and the defending king defends the
687
- // queening square, use the third-rank defence.
688
- if ( pawnRank <= RANK_5
689
- && distance(weakKing, queeningSquare) <= 1
690
- && strongKing <= SQ_H5
691
- && (rank_of(weakRook) == RANK_6 || (pawnRank <= RANK_3 && rank_of(strongRook) != RANK_6)))
692
- return SCALE_FACTOR_DRAW;
693
-
694
- // The defending side saves a draw by checking from behind in case the pawn
695
- // has advanced to the 6th rank with the king behind.
696
- if ( pawnRank == RANK_6
697
- && distance(weakKing, queeningSquare) <= 1
698
- && rank_of(strongKing) + tempo <= RANK_6
699
- && (rank_of(weakRook) == RANK_1 || (!tempo && distance<File>(weakRook, strongPawn) >= 3)))
700
- return SCALE_FACTOR_DRAW;
701
-
702
- if ( pawnRank >= RANK_6
703
- && weakKing == queeningSquare
704
- && rank_of(weakRook) == RANK_1
705
- && (!tempo || distance(strongKing, strongPawn) >= 2))
706
- return SCALE_FACTOR_DRAW;
707
-
708
- // White pawn on a7 and rook on a8 is a draw if black's king is on g7 or h7
709
- // and the black rook is behind the pawn.
710
- if ( strongPawn == SQ_A7
711
- && strongRook == SQ_A8
712
- && (weakKing == SQ_H7 || weakKing == SQ_G7)
713
- && file_of(weakRook) == FILE_A
714
- && (rank_of(weakRook) <= RANK_3 || file_of(strongKing) >= FILE_D || rank_of(strongKing) <= RANK_5))
715
- return SCALE_FACTOR_DRAW;
716
-
717
- // If the defending king blocks the pawn and the attacking king is too far
718
- // away, it's a draw.
719
- if ( pawnRank <= RANK_5
720
- && weakKing == strongPawn + NORTH
721
- && distance(strongKing, strongPawn) - tempo >= 2
722
- && distance(strongKing, weakRook) - tempo >= 2)
723
- return SCALE_FACTOR_DRAW;
724
-
725
- // Pawn on the 7th rank supported by the rook from behind usually wins if the
726
- // attacking king is closer to the queening square than the defending king,
727
- // and the defending king cannot gain tempi by threatening the attacking rook.
728
- if ( pawnRank == RANK_7
729
- && pawnFile != FILE_A
730
- && file_of(strongRook) == pawnFile
731
- && strongRook != queeningSquare
732
- && (distance(strongKing, queeningSquare) < distance(weakKing, queeningSquare) - 2 + tempo)
733
- && (distance(strongKing, queeningSquare) < distance(weakKing, strongRook) + tempo))
734
- return ScaleFactor(SCALE_FACTOR_MAX - 2 * distance(strongKing, queeningSquare));
735
-
736
- // Similar to the above, but with the pawn further back
737
- if ( pawnFile != FILE_A
738
- && file_of(strongRook) == pawnFile
739
- && strongRook < strongPawn
740
- && (distance(strongKing, queeningSquare) < distance(weakKing, queeningSquare) - 2 + tempo)
741
- && (distance(strongKing, strongPawn + NORTH) < distance(weakKing, strongPawn + NORTH) - 2 + tempo)
742
- && ( distance(weakKing, strongRook) + tempo >= 3
743
- || ( distance(strongKing, queeningSquare) < distance(weakKing, strongRook) + tempo
744
- && (distance(strongKing, strongPawn + NORTH) < distance(weakKing, strongPawn) + tempo))))
745
- return ScaleFactor( SCALE_FACTOR_MAX
746
- - 8 * distance(strongPawn, queeningSquare)
747
- - 2 * distance(strongKing, queeningSquare));
748
-
749
- // If the pawn is not far advanced and the defending king is somewhere in
750
- // the pawn's path, it's probably a draw.
751
- if (pawnRank <= RANK_4 && weakKing > strongPawn)
752
- {
753
- if (file_of(weakKing) == file_of(strongPawn))
754
- return ScaleFactor(10);
755
- if ( distance<File>(weakKing, strongPawn) == 1
756
- && distance(strongKing, weakKing) > 2)
757
- return ScaleFactor(24 - 2 * distance(strongKing, weakKing));
758
- }
759
- return SCALE_FACTOR_NONE;
760
- }
761
-
762
- template<>
763
- ScaleFactor Endgame<KRPKB>::operator()(const Position& pos) const {
764
-
765
- assert(verify_material(pos, strongSide, RookValueMg, 1));
766
- assert(verify_material(pos, weakSide, BishopValueMg, 0));
767
-
768
- // Test for a rook pawn
769
- if (pos.pieces(PAWN) & (FileABB | FileHBB))
770
- {
771
- Square weakKing = pos.square<KING>(weakSide);
772
- Square weakBishop = pos.square<BISHOP>(weakSide);
773
- Square strongKing = pos.square<KING>(strongSide);
774
- Square strongPawn = pos.square<PAWN>(strongSide);
775
- Rank pawnRank = relative_rank(strongSide, strongPawn);
776
- Direction push = pawn_push(strongSide);
777
-
778
- // If the pawn is on the 5th rank and the pawn (currently) is on
779
- // the same color square as the bishop then there is a chance of
780
- // a fortress. Depending on the king position give a moderate
781
- // reduction or a stronger one if the defending king is near the
782
- // corner but not trapped there.
783
- if (pawnRank == RANK_5 && !opposite_colors(weakBishop, strongPawn))
784
- {
785
- int d = distance(strongPawn + 3 * push, weakKing);
786
-
787
- if (d <= 2 && !(d == 0 && weakKing == strongKing + 2 * push))
788
- return ScaleFactor(24);
789
- else
790
- return ScaleFactor(48);
791
- }
792
-
793
- // When the pawn has moved to the 6th rank we can be fairly sure
794
- // it's drawn if the bishop attacks the square in front of the
795
- // pawn from a reasonable distance and the defending king is near
796
- // the corner
797
- if ( pawnRank == RANK_6
798
- && distance(strongPawn + 2 * push, weakKing) <= 1
799
- && (attacks_bb<BISHOP>(weakBishop) & (strongPawn + push))
800
- && distance<File>(weakBishop, strongPawn) >= 2)
801
- return ScaleFactor(8);
802
- }
803
-
804
- return SCALE_FACTOR_NONE;
805
- }
806
-
807
- /// KRPP vs KRP. There is just a single rule: if the stronger side has no passed
808
- /// pawns and the defending king is actively placed, the position is drawish.
809
- template<>
810
- ScaleFactor Endgame<KRPPKRP>::operator()(const Position& pos) const {
811
-
812
- assert(verify_material(pos, strongSide, RookValueMg, 2));
813
- assert(verify_material(pos, weakSide, RookValueMg, 1));
814
-
815
- Square strongPawn1 = lsb(pos.pieces(strongSide, PAWN));
816
- Square strongPawn2 = msb(pos.pieces(strongSide, PAWN));
817
- Square weakKing = pos.square<KING>(weakSide);
818
-
819
- // Does the stronger side have a passed pawn?
820
- if (pos.pawn_passed(strongSide, strongPawn1) || pos.pawn_passed(strongSide, strongPawn2))
821
- return SCALE_FACTOR_NONE;
822
-
823
- Rank pawnRank = std::max(relative_rank(strongSide, strongPawn1), relative_rank(strongSide, strongPawn2));
824
-
825
- if ( distance<File>(weakKing, strongPawn1) <= 1
826
- && distance<File>(weakKing, strongPawn2) <= 1
827
- && relative_rank(strongSide, weakKing) > pawnRank)
828
- {
829
- assert(pawnRank > RANK_1 && pawnRank < RANK_7);
830
- return ScaleFactor(7 * pawnRank);
831
- }
832
- return SCALE_FACTOR_NONE;
833
- }
834
-
835
-
836
- /// K and two or more pawns vs K. There is just a single rule here: if all pawns
837
- /// are on the same rook file and are blocked by the defending king, it's a draw.
838
- template<>
839
- ScaleFactor Endgame<KPsK>::operator()(const Position& pos) const {
840
-
841
- assert(pos.non_pawn_material(strongSide) == VALUE_ZERO);
842
- assert(pos.count<PAWN>(strongSide) >= 2);
843
- assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
844
-
845
- Square weakKing = pos.square<KING>(weakSide);
846
- Bitboard strongPawns = pos.pieces(strongSide, PAWN);
847
-
848
- // If all pawns are ahead of the king on a single rook file, it's a draw.
849
- if ( !(strongPawns & ~(FileABB | FileHBB))
850
- && !(strongPawns & ~passed_pawn_span(weakSide, weakKing)))
851
- return SCALE_FACTOR_DRAW;
852
-
853
- return SCALE_FACTOR_NONE;
854
- }
855
-
856
-
857
- /// KBP vs KB. There are two rules: if the defending king is somewhere along the
858
- /// path of the pawn, and the square of the king is not of the same color as the
859
- /// stronger side's bishop, it's a draw. If the two bishops have opposite color,
860
- /// it's almost always a draw.
861
- template<>
862
- ScaleFactor Endgame<KBPKB>::operator()(const Position& pos) const {
863
-
864
- assert(verify_material(pos, strongSide, BishopValueMg, 1));
865
- assert(verify_material(pos, weakSide, BishopValueMg, 0));
866
-
867
- Square strongPawn = pos.square<PAWN>(strongSide);
868
- Square strongBishop = pos.square<BISHOP>(strongSide);
869
- Square weakBishop = pos.square<BISHOP>(weakSide);
870
- Square weakKing = pos.square<KING>(weakSide);
871
-
872
- // Case 1: Defending king blocks the pawn, and cannot be driven away
873
- if ( (forward_file_bb(strongSide, strongPawn) & weakKing)
874
- && ( opposite_colors(weakKing, strongBishop)
875
- || relative_rank(strongSide, weakKing) <= RANK_6))
876
- return SCALE_FACTOR_DRAW;
877
-
878
- // Case 2: Opposite colored bishops
879
- if (opposite_colors(strongBishop, weakBishop))
880
- return SCALE_FACTOR_DRAW;
881
-
882
- return SCALE_FACTOR_NONE;
883
- }
884
-
885
-
886
- /// KBPP vs KB. It detects a few basic draws with opposite-colored bishops
887
- template<>
888
- ScaleFactor Endgame<KBPPKB>::operator()(const Position& pos) const {
889
-
890
- assert(verify_material(pos, strongSide, BishopValueMg, 2));
891
- assert(verify_material(pos, weakSide, BishopValueMg, 0));
892
-
893
- Square strongBishop = pos.square<BISHOP>(strongSide);
894
- Square weakBishop = pos.square<BISHOP>(weakSide);
895
-
896
- if (!opposite_colors(strongBishop, weakBishop))
897
- return SCALE_FACTOR_NONE;
898
-
899
- Square weakKing = pos.square<KING>(weakSide);
900
- Square strongPawn1 = lsb(pos.pieces(strongSide, PAWN));
901
- Square strongPawn2 = msb(pos.pieces(strongSide, PAWN));
902
- Square blockSq1, blockSq2;
903
-
904
- if (relative_rank(strongSide, strongPawn1) > relative_rank(strongSide, strongPawn2))
905
- {
906
- blockSq1 = strongPawn1 + pawn_push(strongSide);
907
- blockSq2 = make_square(file_of(strongPawn2), rank_of(strongPawn1));
908
- }
909
- else
910
- {
911
- blockSq1 = strongPawn2 + pawn_push(strongSide);
912
- blockSq2 = make_square(file_of(strongPawn1), rank_of(strongPawn2));
913
- }
914
-
915
- switch (distance<File>(strongPawn1, strongPawn2))
916
- {
917
- case 0:
918
- // Both pawns are on the same file. It's an easy draw if the defender firmly
919
- // controls some square in the frontmost pawn's path.
920
- if ( file_of(weakKing) == file_of(blockSq1)
921
- && relative_rank(strongSide, weakKing) >= relative_rank(strongSide, blockSq1)
922
- && opposite_colors(weakKing, strongBishop))
923
- return SCALE_FACTOR_DRAW;
924
- else
925
- return SCALE_FACTOR_NONE;
926
-
927
- case 1:
928
- // Pawns on adjacent files. It's a draw if the defender firmly controls the
929
- // square in front of the frontmost pawn's path, and the square diagonally
930
- // behind this square on the file of the other pawn.
931
- if ( weakKing == blockSq1
932
- && opposite_colors(weakKing, strongBishop)
933
- && ( weakBishop == blockSq2
934
- || (attacks_bb<BISHOP>(blockSq2, pos.pieces()) & pos.pieces(weakSide, BISHOP))
935
- || distance<Rank>(strongPawn1, strongPawn2) >= 2))
936
- return SCALE_FACTOR_DRAW;
937
-
938
- else if ( weakKing == blockSq2
939
- && opposite_colors(weakKing, strongBishop)
940
- && ( weakBishop == blockSq1
941
- || (attacks_bb<BISHOP>(blockSq1, pos.pieces()) & pos.pieces(weakSide, BISHOP))))
942
- return SCALE_FACTOR_DRAW;
943
- else
944
- return SCALE_FACTOR_NONE;
945
-
946
- default:
947
- // The pawns are not on the same file or adjacent files. No scaling.
948
- return SCALE_FACTOR_NONE;
949
- }
950
- }
951
-
952
-
953
- /// KBP vs KN. There is a single rule: if the defending king is somewhere along
954
- /// the path of the pawn, and the square of the king is not of the same color as
955
- /// the stronger side's bishop, it's a draw.
956
- template<>
957
- ScaleFactor Endgame<KBPKN>::operator()(const Position& pos) const {
958
-
959
- assert(verify_material(pos, strongSide, BishopValueMg, 1));
960
- assert(verify_material(pos, weakSide, KnightValueMg, 0));
961
-
962
- Square strongPawn = pos.square<PAWN>(strongSide);
963
- Square strongBishop = pos.square<BISHOP>(strongSide);
964
- Square weakKing = pos.square<KING>(weakSide);
965
-
966
- if ( file_of(weakKing) == file_of(strongPawn)
967
- && relative_rank(strongSide, strongPawn) < relative_rank(strongSide, weakKing)
968
- && ( opposite_colors(weakKing, strongBishop)
969
- || relative_rank(strongSide, weakKing) <= RANK_6))
970
- return SCALE_FACTOR_DRAW;
971
-
972
- return SCALE_FACTOR_NONE;
973
- }
974
-
975
-
976
- /// KP vs KP. This is done by removing the weakest side's pawn and probing the
977
- /// KP vs K bitbase: if the weakest side has a draw without the pawn, it probably
978
- /// has at least a draw with the pawn as well. The exception is when the stronger
979
- /// side's pawn is far advanced and not on a rook file; in this case it is often
980
- /// possible to win (e.g. 8/4k3/3p4/3P4/6K1/8/8/8 w - - 0 1).
981
- template<>
982
- ScaleFactor Endgame<KPKP>::operator()(const Position& pos) const {
983
-
984
- assert(verify_material(pos, strongSide, VALUE_ZERO, 1));
985
- assert(verify_material(pos, weakSide, VALUE_ZERO, 1));
986
-
987
- // Assume strongSide is white and the pawn is on files A-D
988
- Square strongKing = normalize(pos, strongSide, pos.square<KING>(strongSide));
989
- Square weakKing = normalize(pos, strongSide, pos.square<KING>(weakSide));
990
- Square strongPawn = normalize(pos, strongSide, pos.square<PAWN>(strongSide));
991
-
992
- Color us = strongSide == pos.side_to_move() ? WHITE : BLACK;
993
-
994
- // If the pawn has advanced to the fifth rank or further, and is not a
995
- // rook pawn, it's too dangerous to assume that it's at least a draw.
996
- if (rank_of(strongPawn) >= RANK_5 && file_of(strongPawn) != FILE_A)
997
- return SCALE_FACTOR_NONE;
998
-
999
- // Probe the KPK bitbase with the weakest side's pawn removed. If it's a draw,
1000
- // it's probably at least a draw even with the pawn.
1001
- if ( pos.promotion_zone(us) != rank_bb(relative_rank(us, RANK_8, pos.max_rank()))
1002
- || RANK_MAX != RANK_8
1003
- || !(pos.promotion_piece_types(us) & QUEEN))
1004
- return SCALE_FACTOR_NONE;
1005
-
1006
- return Bitbases::probe(strongKing, strongPawn, weakKing, us) ? SCALE_FACTOR_NONE : SCALE_FACTOR_DRAW;
1007
- }
1008
-
1009
-
1010
- /// Endgame evals for special variants
1011
- /// R vs K. The rook side always wins if there is no immediate forced capture.
1012
- template<>
1013
- Value Endgame<RK, EG_EVAL_ANTI>::operator()(const Position& pos) const {
1014
-
1015
- assert(pos.endgame_eval() == EG_EVAL_ANTI);
1016
-
1017
- Square RSq = pos.square<ROOK>(strongSide);
1018
- Square KSq = pos.square<COMMONER>(weakSide);
1019
-
1020
- Value result = Value(push_to_edge(KSq, pos)) + push_close(RSq, KSq);
1021
-
1022
- int dist_min = std::min(distance<Rank>(RSq, KSq), distance<File>(RSq, KSq));
1023
- int dist_max = std::max(distance<Rank>(RSq, KSq), distance<File>(RSq, KSq));
1024
-
1025
- if (dist_min == 0)
1026
- result += strongSide == pos.side_to_move() || dist_max > 1 ? -VALUE_KNOWN_WIN : VALUE_KNOWN_WIN;
1027
- else if (dist_min == 1)
1028
- result += weakSide == pos.side_to_move() && dist_max > 1 ? -VALUE_KNOWN_WIN : VALUE_KNOWN_WIN;
1029
- else
1030
- result += VALUE_KNOWN_WIN;
1031
-
1032
- return strongSide == pos.side_to_move() ? result : -result;
1033
- }
1034
-
1035
-
1036
- /// K vs N. The king usually wins, but there are a few exceptions.
1037
- template<>
1038
- Value Endgame<KN, EG_EVAL_ANTI>::operator()(const Position& pos) const {
1039
-
1040
- assert(pos.endgame_eval() == EG_EVAL_ANTI);
1041
-
1042
- Square KSq = pos.square<COMMONER>(strongSide);
1043
- Square NSq = pos.square<KNIGHT>(weakSide);
1044
- Bitboard kingAttacks = attacks_bb<KING>(KSq) & pos.board_bb();
1045
- Bitboard knightAttacks = attacks_bb<KNIGHT>(NSq) & pos.board_bb();
1046
- bool strongSideToMove = pos.side_to_move() == strongSide;
1047
-
1048
- // Loss in 1 play
1049
- if (strongSideToMove ? kingAttacks & NSq : knightAttacks & KSq)
1050
- return VALUE_TB_LOSS_IN_MAX_PLY + 1;
1051
- // Win in 2 ply
1052
- if (kingAttacks & knightAttacks)
1053
- return VALUE_TB_WIN_IN_MAX_PLY - 2;
1054
- // Loss in 3 ply
1055
- if (strongSideToMove ? knightAttacks & KSq : kingAttacks & NSq)
1056
- return VALUE_TB_LOSS_IN_MAX_PLY + 3;
1057
-
1058
- Value result = Value(push_to_edge(NSq, pos)) - push_to_edge(KSq, pos);
1059
- // The king usually wins, but scenarios with king on the edge are more complicated
1060
- if (!(KSq & (FileABB | FileHBB | Rank1BB | Rank8BB)))
1061
- result += VALUE_KNOWN_WIN;
1062
-
1063
- return strongSideToMove ? result : -result;
1064
- }
1065
-
1066
- /// N vs N. The side to move always wins/loses if the knights are on
1067
- /// same/opposite colored squares.
1068
- template<>
1069
- Value Endgame<NN, EG_EVAL_ANTI>::operator()(const Position& pos) const {
1070
-
1071
- assert(pos.endgame_eval() == EG_EVAL_ANTI);
1072
-
1073
- Square N1Sq = pos.square<KNIGHT>(pos.side_to_move());
1074
- Square N2Sq = pos.square<KNIGHT>(~pos.side_to_move());
1075
-
1076
- Value result = VALUE_KNOWN_WIN + push_close(N1Sq, N2Sq);
1077
-
1078
- return !opposite_colors(N1Sq, N2Sq) ? result : -result;
1079
- }
1080
-
1081
-
1082
- template<>
1083
- Value Endgame<KXK, EG_EVAL_ATOMIC>::operator()(const Position& pos) const {
1084
-
1085
- assert(pos.endgame_eval() == EG_EVAL_ATOMIC);
1086
-
1087
- // Stalemate/checkmate detection with lone king
1088
- if (pos.side_to_move() == weakSide && !MoveList<LEGAL>(pos).size())
1089
- return std::min(pos.stalemate_value(), VALUE_MATE_IN_MAX_PLY - 1);
1090
-
1091
- Square winnerKSq = pos.square<COMMONER>(strongSide);
1092
- Square loserKSq = pos.square<COMMONER>(weakSide);
1093
-
1094
- Value result = pos.non_pawn_material(strongSide)
1095
- + pos.count<PAWN>(strongSide) * PawnValueEg
1096
- + push_to_edge(loserKSq, pos)
1097
- + push_away(winnerKSq, loserKSq);
1098
-
1099
- // We need at least a major and a minor, or three minors to force checkmate
1100
- if ( ((pos.count<QUEEN>(strongSide) || pos.count<ROOK>(strongSide)) && pos.count<ALL_PIECES>(strongSide) >= 3)
1101
- || (pos.count<BISHOP>(strongSide) + pos.count<KNIGHT>(strongSide) >= 3
1102
- && (pos.count<KNIGHT>(strongSide) >= 2 || ((pos.pieces(strongSide, BISHOP) & DarkSquares)
1103
- && (pos.pieces(strongSide, BISHOP) & ~DarkSquares)))))
1104
- result = std::min(result + VALUE_KNOWN_WIN, VALUE_MATE_IN_MAX_PLY - 1);
1105
-
1106
- return strongSide == pos.side_to_move() ? result : -result;
1107
- }
1108
-
1109
- template<>
1110
- Value Endgame<KPK, EG_EVAL_ATOMIC>::operator()(const Position& pos) const {
1111
-
1112
- assert(pos.endgame_eval() == EG_EVAL_ATOMIC);
1113
-
1114
- Square winnerKSq = pos.square<COMMONER>(strongSide);
1115
- Square loserKSq = pos.square<COMMONER>(weakSide);
1116
-
1117
- int dist = distance(winnerKSq, loserKSq);
1118
- // Draw in case of adjacent kings
1119
- if (dist <= (strongSide == pos.side_to_move() ? 1 : 2))
1120
- return VALUE_DRAW;
1121
-
1122
- Value result = PawnValueEg
1123
- + 20 * relative_rank(strongSide, pos.square<PAWN>(strongSide), pos.max_rank()) - 20
1124
- + push_away(winnerKSq, loserKSq);
1125
-
1126
- return strongSide == pos.side_to_move() ? result : -result;
1127
- }
1128
-
1129
- template<> Value Endgame<KNK, EG_EVAL_ATOMIC>::operator()(const Position&) const { return VALUE_DRAW; }
1130
-
1131
- template<> Value Endgame<KBK, EG_EVAL_ATOMIC>::operator()(const Position&) const { return VALUE_DRAW; }
1132
-
1133
- template<> Value Endgame<KRK, EG_EVAL_ATOMIC>::operator()(const Position&) const { return VALUE_DRAW; }
1134
-
1135
- template<>
1136
- Value Endgame<KQK, EG_EVAL_ATOMIC>::operator()(const Position& pos) const {
1137
-
1138
- assert(pos.endgame_eval() == EG_EVAL_ATOMIC);
1139
-
1140
- // Stalemate/checkmate detection with lone king
1141
- if (pos.side_to_move() == weakSide && !MoveList<LEGAL>(pos).size())
1142
- return std::min(pos.stalemate_value(), VALUE_MATE_IN_MAX_PLY - 1);
1143
-
1144
- Square winnerKSq = pos.square<COMMONER>(strongSide);
1145
- Square loserKSq = pos.square<COMMONER>(weakSide);
1146
-
1147
- int dist = distance(winnerKSq, loserKSq);
1148
- // Draw in case of adjacent kings
1149
- if (dist == 1)
1150
- return VALUE_DRAW;
1151
- // If the weaker side is to move and there is a way to connect kings, it is a draw
1152
- if ( pos.side_to_move() == weakSide
1153
- && (attacks_bb<KING>(winnerKSq) & attacks_bb<KING>(loserKSq) & ~pos.pieces()))
1154
- return VALUE_DRAW;
1155
-
1156
- Value result = Value(push_to_edge(loserKSq, pos))
1157
- + push_away(winnerKSq, loserKSq);
1158
-
1159
- if (dist >= (strongSide == pos.side_to_move() ? 3 : 4))
1160
- result += VALUE_KNOWN_WIN;
1161
-
1162
- return strongSide == pos.side_to_move() ? result : -result;
1163
- }
1164
-
1165
- template<> Value Endgame<KNNK, EG_EVAL_ATOMIC>::operator()(const Position&) const { return VALUE_DRAW; }
1166
-
1167
-
1168
- /// Self-mate with KX vs KX.
1169
- template<>
1170
- Value Endgame<KXKX, EG_EVAL_MISERE>::operator()(const Position& pos) const {
1171
-
1172
- assert(!pos.checkers()); // Eval is never called when in check
1173
-
1174
- // Stalemate detection with lone king
1175
- if (pos.side_to_move() == weakSide && !MoveList<LEGAL>(pos).size())
1176
- return VALUE_DRAW;
1177
-
1178
- Square strongKing = pos.square<KING>(strongSide);
1179
- Square weakKing = pos.square<KING>(weakSide);
1180
-
1181
- Value result = pos.non_pawn_material(strongSide) * int(VALUE_KNOWN_WIN) / int(VALUE_KNOWN_WIN + pos.non_pawn_material(strongSide))
1182
- - pos.non_pawn_material(weakSide)
1183
- + pos.count<PAWN>(weakSide) * PawnValueEg
1184
- + push_to_opposing_edge(relative_square(weakSide, strongKing, pos.max_rank()), pos) * 2
1185
- + push_close(strongKing, weakKing) * 2;
1186
-
1187
- for (Bitboard b = pos.pieces(PAWN); b;)
1188
- {
1189
- Square s = pop_lsb(b);
1190
- result += (push_close(strongKing, s) + push_close(weakKing, s)) / 2;
1191
- }
1192
-
1193
- if (!pos.count<PAWN>(weakSide))
1194
- result = VALUE_DRAW;
1195
- else if (pos.count<PAWN>(weakSide) == 1)
1196
- result = result / 2;
1197
-
1198
- return strongSide == pos.side_to_move() ? result : -result;
1199
- }
1200
-
1201
-
1202
- /// Mate with KX vs K. This function is used to evaluate positions with
1203
- /// king and plenty of material vs a lone king. It simply gives the
1204
- /// attacking side a bonus for driving the defending king towards the edge
1205
- /// of the board, and for keeping the distance between the two kings small.
1206
- template<>
1207
- Value Endgame<KXK, EG_EVAL_DUCK>::operator()(const Position& pos) const {
1208
-
1209
- Square strongKing = pos.square<COMMONER>(strongSide);
1210
- Square weakKing = pos.square<COMMONER>(weakSide);
1211
-
1212
- Value result = pos.non_pawn_material(strongSide)
1213
- + pos.count<PAWN>(strongSide) * PawnValueEg
1214
- + push_to_edge(weakKing, pos)
1215
- + push_close(strongKing, weakKing);
1216
-
1217
- result = std::min(result + VALUE_KNOWN_WIN, VALUE_TB_WIN_IN_MAX_PLY - 1);
1218
-
1219
- return strongSide == pos.side_to_move() ? result : -result;
1220
- }
1221
-
1222
-
1223
- /// Drawish, but king should stay away from the edge
1224
- template<>
1225
- Value Endgame<KNK, EG_EVAL_DUCK>::operator()(const Position& pos) const {
1226
-
1227
- Square strongKing = pos.square<COMMONER>(strongSide);
1228
- Square weakKing = pos.square<COMMONER>(weakSide);
1229
-
1230
- Value result = Value(push_to_edge(weakKing, pos))
1231
- + push_close(strongKing, weakKing);
1232
-
1233
- return strongSide == pos.side_to_move() ? result : -result;
1234
- }
1235
-
1236
-
1237
- /// Drawish, but king should stay away from the edge
1238
- template<>
1239
- Value Endgame<KBK, EG_EVAL_DUCK>::operator()(const Position& pos) const {
1240
-
1241
- Square strongKing = pos.square<COMMONER>(strongSide);
1242
- Square weakKing = pos.square<COMMONER>(weakSide);
1243
-
1244
- Value result = Value(push_to_edge(weakKing, pos))
1245
- + push_close(strongKing, weakKing);
1246
-
1247
- return strongSide == pos.side_to_move() ? result : -result;
1248
- }
1249
-
1250
-
1251
- /// Winning as long as pawn is safe
1252
- template<>
1253
- Value Endgame<KPK, EG_EVAL_DUCK>::operator()(const Position& pos) const {
1254
-
1255
- Square strongKing = pos.square<COMMONER>(strongSide);
1256
- Square weakKing = pos.square<COMMONER>(weakSide);
1257
- Square strongPawn = pos.square<PAWN>(strongSide);
1258
-
1259
- Value result = PawnValueEg + 50 * relative_rank(strongSide, strongPawn, pos.max_rank())
1260
- + push_to_edge(weakKing, pos)
1261
- + push_close(strongKing, weakKing)
1262
- + push_close(strongKing, strongPawn) / 2
1263
- + push_away(weakKing, strongPawn) / 2;
1264
-
1265
- return strongSide == pos.side_to_move() ? result : -result;
1266
- }
1267
-
1268
- /// Winning as long as last rank can be blocked
1269
- template<>
1270
- Value Endgame<KQK, EG_EVAL_RK>::operator()(const Position& pos) const {
1271
-
1272
- Square strongKing = pos.square<KING>(strongSide);
1273
- Square weakKing = pos.square<KING>(weakSide);
1274
- Square strongQueen = pos.square<QUEEN>(strongSide);
1275
-
1276
- Value result;
1277
-
1278
- if ( rank_of(weakKing) < rank_of(strongQueen)
1279
- || rank_of(weakKing) + (weakSide == pos.side_to_move()) < RANK_7
1280
- || (Rank8BB & attacks_bb<QUEEN>(strongQueen, pos.pieces()) & ~(attacks_bb<QUEEN>(weakKing) | attacks_bb<SHOGI_KNIGHT>(weakKing))))
1281
- result = VALUE_KNOWN_WIN + 100 * rank_of(strongKing);
1282
- else
1283
- result = -VALUE_KNOWN_WIN;
1284
-
1285
- return strongSide == pos.side_to_move() ? result : -result;
1286
- }
1287
-
1288
- /// Winning as long as last rank can be blocked
1289
- template<>
1290
- Value Endgame<KRK, EG_EVAL_RK>::operator()(const Position& pos) const {
1291
-
1292
- Square strongKing = pos.square<KING>(strongSide);
1293
- Square weakKing = pos.square<KING>(weakSide);
1294
- Square strongRook = pos.square<ROOK>(strongSide);
1295
-
1296
- Value result;
1297
-
1298
- if ( rank_of(weakKing) < rank_of(strongRook)
1299
- || rank_of(weakKing) + (weakSide == pos.side_to_move()) < RANK_7
1300
- || (Rank8BB & attacks_bb<ROOK>(strongRook, pos.pieces()) & ~(attacks_bb<QUEEN>(weakKing) | attacks_bb<SHOGI_KNIGHT>(weakKing))))
1301
- result = VALUE_KNOWN_WIN + 100 * rank_of(strongKing);
1302
- else
1303
- result = -VALUE_KNOWN_WIN;
1304
-
1305
- return strongSide == pos.side_to_move() ? result : -result;
1306
- }
1307
-
1308
- /// KvK. Pure race
1309
- template<>
1310
- Value Endgame<KK, EG_EVAL_RK>::operator()(const Position& pos) const {
1311
-
1312
- Square whiteKing = pos.square<KING>(WHITE);
1313
- Square blackKing = pos.square<KING>(BLACK);
1314
-
1315
- Value result = (VALUE_KNOWN_WIN + 100 * std::max(rank_of(whiteKing), rank_of(blackKing)))
1316
- * std::clamp(rank_of(whiteKing) - rank_of(blackKing) - (pos.side_to_move() == BLACK), -1, 1);
1317
-
1318
- return pos.side_to_move() == WHITE ? result : -result;
1319
- }
1320
-
1321
- } // namespace Stockfish
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/src/endgame.h DELETED
@@ -1,148 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
4
-
5
- Stockfish is free software: you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation, either version 3 of the License, or
8
- (at your option) any later version.
9
-
10
- Stockfish is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- You should have received a copy of the GNU General Public License
16
- along with this program. If not, see <http://www.gnu.org/licenses/>.
17
- */
18
-
19
- #ifndef ENDGAME_H_INCLUDED
20
- #define ENDGAME_H_INCLUDED
21
-
22
- #include <memory>
23
- #include <string>
24
- #include <type_traits>
25
- #include <unordered_map>
26
- #include <utility>
27
-
28
- #include "position.h"
29
- #include "types.h"
30
-
31
- namespace Stockfish {
32
-
33
- /// EndgameCode lists all supported endgame functions by corresponding codes
34
-
35
- enum EndgameCode {
36
-
37
- EVALUATION_FUNCTIONS,
38
- KNNK, // KNN vs K
39
- KNNKP, // KNN vs KP
40
- KXK, // Generic "mate lone king" eval
41
- KBNK, // KBN vs K
42
- KPK, // KP vs K
43
- KRKP, // KR vs KP
44
- KRKB, // KR vs KB
45
- KRKN, // KR vs KN
46
- KQKP, // KQ vs KP
47
- KQKR, // KQ vs KR
48
-
49
- // Fairy piece endgames
50
- KFsPsK, // KFsPsK vs K
51
- KNSK, // KNS vs K
52
- KNFK, // KNF vs K
53
- KNSFKR, // KNSFKR vs K
54
- KSFK, // KSF vs K
55
- KSFKF, // KSF vs KF
56
- KRKS, // KR vs KS
57
- KCKR, // KC vs KR
58
- KAKR, // KA vs KR
59
-
60
- // Special
61
- KXKX,
62
- RK,
63
- KN,
64
- NN,
65
- KQK,
66
- KRK,
67
- KBK,
68
- KNK,
69
- KK,
70
-
71
- SCALING_FUNCTIONS,
72
- KBPsK, // KB and pawns vs K
73
- KQKRPs, // KQ vs KR and pawns
74
- KRPKR, // KRP vs KR
75
- KRPKB, // KRP vs KB
76
- KRPPKRP, // KRPP vs KRP
77
- KPsK, // K and pawns vs K
78
- KBPKB, // KBP vs KB
79
- KBPPKB, // KBPP vs KB
80
- KBPKN, // KBP vs KN
81
- KPKP // KP vs KP
82
- };
83
-
84
-
85
- /// Endgame functions can be of two types depending on whether they return a
86
- /// Value or a ScaleFactor.
87
-
88
- template<EndgameCode E, EndgameEval V = EG_EVAL_CHESS> using
89
- eg_type = typename std::conditional<(E < SCALING_FUNCTIONS), Value, ScaleFactor>::type;
90
-
91
-
92
- /// Base and derived functors for endgame evaluation and scaling functions
93
-
94
- template<typename T>
95
- struct EndgameBase {
96
-
97
- explicit EndgameBase(Color c) : strongSide(c), weakSide(~c) {}
98
- virtual ~EndgameBase() = default;
99
- virtual T operator()(const Position&) const = 0;
100
-
101
- const Color strongSide, weakSide;
102
- };
103
-
104
-
105
- template<EndgameCode E, EndgameEval V = EG_EVAL_CHESS, typename T = eg_type<E, V>>
106
- struct Endgame : public EndgameBase<T> {
107
-
108
- explicit Endgame(Color c) : EndgameBase<T>(c) {}
109
- T operator()(const Position&) const override;
110
- };
111
-
112
-
113
- /// The Endgames namespace handles the pointers to endgame evaluation and scaling
114
- /// base objects in two std::map. We use polymorphism to invoke the actual
115
- /// endgame function by calling its virtual operator().
116
-
117
- namespace Endgames {
118
-
119
- template<typename T> using Ptr = std::unique_ptr<EndgameBase<T>>;
120
- template<typename T> using Map = std::unordered_map<Key, Ptr<T>>;
121
-
122
- extern std::pair<Map<Value>, Map<ScaleFactor>> maps;
123
-
124
- void init();
125
-
126
- template<typename T>
127
- Map<T>& map() {
128
- return std::get<std::is_same<T, ScaleFactor>::value>(maps);
129
- }
130
-
131
- template<EndgameCode E, EndgameEval V = EG_EVAL_CHESS, typename T = eg_type<E, V>>
132
- void add(const std::string& code) {
133
-
134
- StateInfo st;
135
- map<T>()[Position().set(code, WHITE, &st).material_key(V)] = Ptr<T>(new Endgame<E, V>(WHITE));
136
- map<T>()[Position().set(code, BLACK, &st).material_key(V)] = Ptr<T>(new Endgame<E, V>(BLACK));
137
- }
138
-
139
- template<typename T>
140
- const EndgameBase<T>* probe(Key key) {
141
- auto it = map<T>().find(key);
142
- return it != map<T>().end() ? it->second.get() : nullptr;
143
- }
144
- }
145
-
146
- } // namespace Stockfish
147
-
148
- #endif // #ifndef ENDGAME_H_INCLUDED
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/src/evaluate.cpp DELETED
@@ -1,1736 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
4
-
5
- Stockfish is free software: you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation, either version 3 of the License, or
8
- (at your option) any later version.
9
-
10
- Stockfish is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- You should have received a copy of the GNU General Public License
16
- along with this program. If not, see <http://www.gnu.org/licenses/>.
17
- */
18
-
19
- #include <algorithm>
20
- #include <cassert>
21
- #include <cstdlib>
22
- #include <cstring> // For std::memset
23
- #include <fstream>
24
- #include <iomanip>
25
- #include <sstream>
26
- #include <iostream>
27
- #include <streambuf>
28
- #include <vector>
29
-
30
- #include "bitboard.h"
31
- #include "evaluate.h"
32
- #include "material.h"
33
- #include "misc.h"
34
- #include "pawns.h"
35
- #include "thread.h"
36
- #include "timeman.h"
37
- #include "uci.h"
38
- #include "incbin/incbin.h"
39
-
40
-
41
- // Macro to embed the default efficiently updatable neural network (NNUE) file
42
- // data in the engine binary (using incbin.h, by Dale Weiler).
43
- // This macro invocation will declare the following three variables
44
- // const unsigned char gEmbeddedNNUEData[]; // a pointer to the embedded data
45
- // const unsigned char *const gEmbeddedNNUEEnd; // a marker to the end
46
- // const unsigned int gEmbeddedNNUESize; // the size of the embedded file
47
- // Note that this does not work in Microsoft Visual Studio.
48
- #if !defined(_MSC_VER) && !defined(NNUE_EMBEDDING_OFF)
49
- INCBIN(EmbeddedNNUE, EvalFileDefaultName);
50
- #else
51
- const unsigned char gEmbeddedNNUEData[1] = {0x0};
52
- [[maybe_unused]]
53
- const unsigned char *const gEmbeddedNNUEEnd = &gEmbeddedNNUEData[1];
54
- const unsigned int gEmbeddedNNUESize = 1;
55
- #endif
56
-
57
-
58
- using namespace std;
59
-
60
- namespace Stockfish {
61
-
62
- const Variant* currentNnueVariant;
63
-
64
- namespace Eval {
65
-
66
- bool useNNUE;
67
- string eval_file_loaded = "None";
68
-
69
- /// NNUE::init() tries to load a NNUE network at startup time, or when the engine
70
- /// receives a UCI command "setoption name EvalFile value nn-[a-z0-9]{12}.nnue"
71
- /// The name of the NNUE network is always retrieved from the EvalFile option.
72
- /// We search the given network in three locations: internally (the default
73
- /// network may be embedded in the binary), in the active working directory and
74
- /// in the engine directory. Distro packagers may define the DEFAULT_NNUE_DIRECTORY
75
- /// variable to have the engine search in a special directory in their distro.
76
-
77
- void NNUE::init() {
78
-
79
- useNNUE = Options["Use NNUE"];
80
- if (!useNNUE)
81
- return;
82
-
83
- string eval_file = string(Options["EvalFile"]);
84
-
85
- // Restrict NNUE usage to corresponding variant
86
- // Support multiple variant networks separated by semicolon(Windows)/colon(Unix)
87
- stringstream ss(eval_file);
88
- string variant = string(Options["UCI_Variant"]);
89
- useNNUE = false;
90
- while (getline(ss, eval_file, UCI::SepChar))
91
- {
92
- string basename = eval_file.substr(eval_file.find_last_of("\\/") + 1);
93
- string nnueAlias = variants.find(variant)->second->nnueAlias;
94
- if (basename.rfind(variant, 0) != string::npos || (!nnueAlias.empty() && basename.rfind(nnueAlias, 0) != string::npos))
95
- {
96
- useNNUE = true;
97
- break;
98
- }
99
- }
100
- if (!useNNUE)
101
- return;
102
-
103
- currentNnueVariant = variants.find(variant)->second;
104
-
105
- #if defined(DEFAULT_NNUE_DIRECTORY)
106
- #define stringify2(x) #x
107
- #define stringify(x) stringify2(x)
108
- vector<string> dirs = { "<internal>" , "" , CommandLine::binaryDirectory , stringify(DEFAULT_NNUE_DIRECTORY) };
109
- #else
110
- vector<string> dirs = { "<internal>" , "" , CommandLine::binaryDirectory };
111
- #endif
112
-
113
- for (string directory : dirs)
114
- if (eval_file_loaded != eval_file)
115
- {
116
- if (directory != "<internal>")
117
- {
118
- ifstream stream(directory + eval_file, ios::binary);
119
- if (load_eval(eval_file, stream))
120
- eval_file_loaded = eval_file;
121
- }
122
-
123
- if (directory == "<internal>" && eval_file == EvalFileDefaultName)
124
- {
125
- // C++ way to prepare a buffer for a memory stream
126
- class MemoryBuffer : public basic_streambuf<char> {
127
- public: MemoryBuffer(char* p, size_t n) { setg(p, p, p + n); setp(p, p + n); }
128
- };
129
-
130
- MemoryBuffer buffer(const_cast<char*>(reinterpret_cast<const char*>(gEmbeddedNNUEData)),
131
- size_t(gEmbeddedNNUESize));
132
-
133
- istream stream(&buffer);
134
- if (load_eval(eval_file, stream))
135
- eval_file_loaded = eval_file;
136
- }
137
- }
138
- }
139
-
140
- /// NNUE::verify() verifies that the last net used was loaded successfully
141
- void NNUE::verify() {
142
-
143
- string eval_file = string(Options["EvalFile"]);
144
-
145
- if (useNNUE && eval_file.find(eval_file_loaded) == string::npos)
146
- {
147
- UCI::OptionsMap defaults;
148
- UCI::init(defaults);
149
-
150
- string msg1 = "If the UCI option \"Use NNUE\" is set to true, network evaluation parameters compatible with the engine must be available.";
151
- string msg2 = "The option is set to true, but the network file " + eval_file + " was not loaded successfully.";
152
- string msg3 = "The UCI option EvalFile might need to specify the full path, including the directory name, to the network file.";
153
- string msg4 = "The default net can be downloaded from: https://tests.stockfishchess.org/api/nn/" + string(defaults["EvalFile"]);
154
- string msg5 = "The engine will be terminated now.";
155
-
156
- sync_cout << "info string ERROR: " << msg1 << sync_endl;
157
- sync_cout << "info string ERROR: " << msg2 << sync_endl;
158
- sync_cout << "info string ERROR: " << msg3 << sync_endl;
159
- sync_cout << "info string ERROR: " << msg4 << sync_endl;
160
- sync_cout << "info string ERROR: " << msg5 << sync_endl;
161
-
162
- exit(EXIT_FAILURE);
163
- }
164
-
165
- if (CurrentProtocol != XBOARD)
166
- {
167
- if (useNNUE)
168
- sync_cout << "info string NNUE evaluation using " << eval_file_loaded << " enabled" << sync_endl;
169
- else
170
- sync_cout << "info string classical evaluation enabled" << sync_endl;
171
- }
172
- }
173
- }
174
-
175
- namespace Trace {
176
-
177
- enum Tracing { NO_TRACE, TRACE };
178
-
179
- enum Term { // The first PIECE_TYPE_NB entries are reserved for PieceType
180
- MATERIAL = PIECE_TYPE_NB, IMBALANCE, MOBILITY, THREAT, PASSED, SPACE, VARIANT, WINNABLE, TOTAL, TERM_NB
181
- };
182
-
183
- Score scores[TERM_NB][COLOR_NB];
184
-
185
- double to_cp(Value v) { return double(v) / PawnValueEg; }
186
-
187
- void add(int idx, Color c, Score s) {
188
- scores[idx][c] = s;
189
- }
190
-
191
- void add(int idx, Score w, Score b = SCORE_ZERO) {
192
- scores[idx][WHITE] = w;
193
- scores[idx][BLACK] = b;
194
- }
195
-
196
- std::ostream& operator<<(std::ostream& os, Score s) {
197
- os << std::setw(5) << to_cp(mg_value(s)) << " "
198
- << std::setw(5) << to_cp(eg_value(s));
199
- return os;
200
- }
201
-
202
- std::ostream& operator<<(std::ostream& os, Term t) {
203
-
204
- if (t == MATERIAL || t == IMBALANCE || t == WINNABLE || t == TOTAL)
205
- os << " ---- ----" << " | " << " ---- ----";
206
- else
207
- os << scores[t][WHITE] << " | " << scores[t][BLACK];
208
-
209
- os << " | " << scores[t][WHITE] - scores[t][BLACK] << " |\n";
210
- return os;
211
- }
212
- }
213
-
214
- using namespace Trace;
215
-
216
- namespace {
217
-
218
- // Threshold for lazy and space evaluation
219
- constexpr Value LazyThreshold1 = Value(1565);
220
- constexpr Value LazyThreshold2 = Value(1102);
221
- constexpr Value SpaceThreshold = Value(11551);
222
-
223
- // KingAttackWeights[PieceType] contains king attack weights by piece type
224
- constexpr int KingAttackWeights[PIECE_TYPE_NB] = { 0, 0, 81, 52, 44, 10, 40 };
225
-
226
- // SafeCheck[PieceType][single/multiple] contains safe check bonus by piece type,
227
- // higher if multiple safe checks are possible for that piece type.
228
- constexpr int SafeCheck[][2] = {
229
- {}, {600, 600}, {803, 1292}, {639, 974}, {1087, 1878}, {759, 1132}, {600, 900}
230
- };
231
-
232
- #define S(mg, eg) make_score(mg, eg)
233
-
234
- // MobilityBonus[PieceType-2][attacked] contains bonuses for middle and end game,
235
- // indexed by piece type and number of attacked squares in the mobility area.
236
- constexpr Score MobilityBonus[][4 * RANK_NB] = {
237
- { S(-62,-79), S(-53,-57), S(-12,-31), S( -3,-17), S( 3, 7), S( 12, 13), // Knight
238
- S( 21, 16), S( 28, 21), S( 37, 26) },
239
- { S(-47,-59), S(-20,-25), S( 14, -8), S( 29, 12), S( 39, 21), S( 53, 40), // Bishop
240
- S( 53, 56), S( 60, 58), S( 62, 65), S( 69, 72), S( 78, 78), S( 83, 87),
241
- S( 91, 88), S( 96, 98) },
242
- { S(-60,-82), S(-24,-15), S( 0, 17) ,S( 3, 43), S( 4, 72), S( 14,100), // Rook
243
- S( 20,102), S( 30,122), S( 41,133), S(41 ,139), S( 41,153), S( 45,160),
244
- S( 57,165), S( 58,170), S( 67,175) },
245
- { S(-29,-49), S(-16,-29), S( -8, -8), S( -8, 17), S( 18, 39), S( 25, 54), // Queen
246
- S( 23, 59), S( 37, 73), S( 41, 76), S( 54, 95), S( 65, 95) ,S( 68,101),
247
- S( 69,124), S( 70,128), S( 70,132), S( 70,133) ,S( 71,136), S( 72,140),
248
- S( 74,147), S( 76,149), S( 90,153), S(104,169), S(105,171), S(106,171),
249
- S(112,178), S(114,185), S(114,187), S(119,221) }
250
- };
251
- constexpr Score MaxMobility = S(150, 200);
252
- constexpr Score DropMobility = S(10, 10);
253
-
254
- // BishopPawns[distance from edge] contains a file-dependent penalty for pawns on
255
- // squares of the same color as our bishop.
256
- constexpr Score BishopPawns[int(FILE_NB) / 2] = {
257
- S(3, 8), S(3, 9), S(2, 8), S(3, 8)
258
- };
259
-
260
- // KingProtector[knight/bishop] contains penalty for each distance unit to own king
261
- constexpr Score KingProtector[] = { S(8, 9), S(6, 9) };
262
-
263
- // Outpost[knight/bishop] contains bonuses for each knight or bishop occupying a
264
- // pawn protected square on rank 4 to 6 which is also safe from a pawn attack.
265
- constexpr Score Outpost[] = { S(57, 38), S(31, 24) };
266
-
267
- // PassedRank[Rank] contains a bonus according to the rank of a passed pawn
268
- constexpr Score PassedRank[RANK_NB] = {
269
- S(0, 0), S(7, 27), S(16, 32), S(17, 40), S(64, 71), S(170, 174), S(278, 262)
270
- };
271
-
272
- constexpr Score RookOnClosedFile = S(10, 5);
273
- constexpr Score RookOnOpenFile[] = { S(19, 6), S(47, 26) };
274
-
275
- // ThreatByMinor/ByRook[attacked PieceType] contains bonuses according to
276
- // which piece type attacks which one. Attacks on lesser pieces which are
277
- // pawn-defended are not considered.
278
- constexpr Score ThreatByMinor[PIECE_TYPE_NB] = {
279
- S(0, 0), S(5, 32), S(55, 41), S(77, 56), S(89, 119), S(79, 162)
280
- };
281
-
282
- constexpr Score ThreatByRook[PIECE_TYPE_NB] = {
283
- S(0, 0), S(3, 44), S(37, 68), S(42, 60), S(0, 39), S(58, 43)
284
- };
285
-
286
- constexpr Value CorneredBishop = Value(50);
287
-
288
- // Assorted bonuses and penalties
289
- constexpr Score UncontestedOutpost = S( 1, 10);
290
- constexpr Score BishopOnKingRing = S( 24, 0);
291
- constexpr Score BishopXRayPawns = S( 4, 5);
292
- constexpr Score FlankAttacks = S( 8, 0);
293
- constexpr Score Hanging = S( 69, 36);
294
- constexpr Score KnightOnQueen = S( 16, 11);
295
- constexpr Score LongDiagonalBishop = S( 45, 0);
296
- constexpr Score MinorBehindPawn = S( 18, 3);
297
- constexpr Score PassedFile = S( 11, 8);
298
- constexpr Score PawnlessFlank = S( 17, 95);
299
- constexpr Score ReachableOutpost = S( 31, 22);
300
- constexpr Score RestrictedPiece = S( 7, 7);
301
- constexpr Score RookOnKingRing = S( 16, 0);
302
- constexpr Score SliderOnQueen = S( 60, 18);
303
- constexpr Score ThreatByKing = S( 24, 89);
304
- constexpr Score ThreatByPawnPush = S( 48, 39);
305
- constexpr Score ThreatBySafePawn = S(173, 94);
306
- constexpr Score TrappedRook = S( 55, 13);
307
- constexpr Score WeakQueenProtection = S( 14, 0);
308
- constexpr Score WeakQueen = S( 56, 15);
309
-
310
-
311
- // Variant and fairy piece bonuses
312
- constexpr Score KingProximity = S(2, 6);
313
- constexpr Score EndgameKingProximity = S(0, 10);
314
- constexpr Score ConnectedSoldier = S(20, 20);
315
-
316
- constexpr int VirtualCheck = 600;
317
-
318
- #undef S
319
-
320
- // Evaluation class computes and stores attacks tables and other working data
321
- template<Tracing T>
322
- class Evaluation {
323
-
324
- public:
325
- Evaluation() = delete;
326
- explicit Evaluation(const Position& p) : pos(p) {}
327
- Evaluation& operator=(const Evaluation&) = delete;
328
- Value value();
329
-
330
- private:
331
- template<Color Us> void initialize();
332
- template<Color Us> Score pieces(PieceType Pt);
333
- template<Color Us> Score hand(PieceType pt);
334
- template<Color Us> Score king() const;
335
- template<Color Us> Score threats() const;
336
- template<Color Us> Score passed() const;
337
- template<Color Us> Score space() const;
338
- template<Color Us> Score variant() const;
339
- Value winnable(Score score) const;
340
-
341
- const Position& pos;
342
- Material::Entry* me;
343
- Pawns::Entry* pe;
344
- Bitboard mobilityArea[COLOR_NB];
345
- Score mobility[COLOR_NB] = { SCORE_ZERO, SCORE_ZERO };
346
-
347
- // attackedBy[color][piece type] is a bitboard representing all squares
348
- // attacked by a given color and piece type. Special "piece types" which
349
- // is also calculated is ALL_PIECES.
350
- Bitboard attackedBy[COLOR_NB][PIECE_TYPE_NB];
351
-
352
- // attackedBy2[color] are the squares attacked by at least 2 units of a given
353
- // color, including x-rays. But diagonal x-rays through pawns are not computed.
354
- Bitboard attackedBy2[COLOR_NB];
355
-
356
- // kingRing[color] are the squares adjacent to the king plus some other
357
- // very near squares, depending on king position.
358
- Bitboard kingRing[COLOR_NB];
359
-
360
- // kingAttackersCount[color] is the number of pieces of the given color
361
- // which attack a square in the kingRing of the enemy king.
362
- int kingAttackersCount[COLOR_NB];
363
- int kingAttackersCountInHand[COLOR_NB];
364
-
365
- // kingAttackersWeight[color] is the sum of the "weights" of the pieces of
366
- // the given color which attack a square in the kingRing of the enemy king.
367
- // The weights of the individual piece types are given by the elements in
368
- // the KingAttackWeights array.
369
- int kingAttackersWeight[COLOR_NB];
370
- int kingAttackersWeightInHand[COLOR_NB];
371
-
372
- // kingAttacksCount[color] is the number of attacks by the given color to
373
- // squares directly adjacent to the enemy king. Pieces which attack more
374
- // than one square are counted multiple times. For instance, if there is
375
- // a white knight on g5 and black's king is on g8, this white knight adds 2
376
- // to kingAttacksCount[WHITE].
377
- int kingAttacksCount[COLOR_NB];
378
- };
379
-
380
-
381
- // Evaluation::initialize() computes king and pawn attacks, and the king ring
382
- // bitboard for a given color. This is done at the beginning of the evaluation.
383
-
384
- template<Tracing T> template<Color Us>
385
- void Evaluation<T>::initialize() {
386
-
387
- constexpr Color Them = ~Us;
388
- constexpr Direction Up = pawn_push(Us);
389
- constexpr Direction Down = -Up;
390
- Bitboard LowRanks = rank_bb(relative_rank(Us, RANK_2, pos.max_rank())) | rank_bb(relative_rank(Us, RANK_3, pos.max_rank()));
391
-
392
- const Square ksq = pos.count<KING>(Us) ? pos.square<KING>(Us) : SQ_NONE;
393
-
394
- Bitboard dblAttackByPawn = pawn_double_attacks_bb<Us>(pos.pieces(Us, PAWN));
395
-
396
- // Find our pawns that are blocked or on the first two ranks
397
- Bitboard b = pos.pieces(Us, PAWN) & (shift<Down>(pos.pieces()) | LowRanks);
398
-
399
- // Squares occupied by those pawns, by our king or queen, by blockers to attacks on our king
400
- // or controlled by enemy pawns are excluded from the mobility area.
401
- if (pos.must_capture())
402
- mobilityArea[Us] = AllSquares;
403
- else
404
- mobilityArea[Us] = ~(b | pos.pieces(Us, KING, QUEEN) | pos.blockers_for_king(Us) | pe->pawn_attacks(Them)
405
- | (pos.pieces(Us, SHOGI_PAWN) & shift<Down>(pos.pieces(Us)))
406
- | shift<Down>(pos.pieces(Them, SHOGI_PAWN, SOLDIER))
407
- | shift<EAST>(pos.promoted_soldiers(Them))
408
- | shift<WEST>(pos.promoted_soldiers(Them)));
409
-
410
- // Initialize attackedBy[] for king and pawns
411
- attackedBy[Us][KING] = pos.count<KING>(Us) ? pos.attacks_from(Us, KING, ksq) : Bitboard(0);
412
- attackedBy[Us][PAWN] = pe->pawn_attacks(Us);
413
- attackedBy[Us][SHOGI_PAWN] = shift<Up>(pos.pieces(Us, SHOGI_PAWN));
414
- attackedBy[Us][ALL_PIECES] = attackedBy[Us][KING] | attackedBy[Us][PAWN] | attackedBy[Us][SHOGI_PAWN];
415
- attackedBy2[Us] = (attackedBy[Us][KING] & attackedBy[Us][PAWN])
416
- | (attackedBy[Us][KING] & attackedBy[Us][SHOGI_PAWN])
417
- | (attackedBy[Us][PAWN] & attackedBy[Us][SHOGI_PAWN])
418
- | dblAttackByPawn;
419
-
420
- // Init our king safety tables
421
- if (!pos.count<KING>(Us))
422
- kingRing[Us] = Bitboard(0);
423
- else
424
- {
425
- Square s = make_square(std::clamp(file_of(ksq), FILE_B, File(pos.max_file() - 1)),
426
- std::clamp(rank_of(ksq), RANK_2, Rank(pos.max_rank() - 1)));
427
- kingRing[Us] = attacks_bb<KING>(s) | s;
428
- }
429
-
430
- kingAttackersCount[Them] = popcount(kingRing[Us] & (pe->pawn_attacks(Them) | shift<Down>(pos.pieces(Them, SHOGI_PAWN))));
431
- kingAttacksCount[Them] = kingAttackersWeight[Them] = 0;
432
- kingAttackersCountInHand[Them] = kingAttackersWeightInHand[Them] = 0;
433
-
434
- // Remove from kingRing[] the squares defended by two pawns
435
- kingRing[Us] &= ~dblAttackByPawn;
436
-
437
- kingRing[Us] &= pos.board_bb();
438
- }
439
-
440
-
441
- // Evaluation::pieces() scores pieces of a given color and type
442
-
443
- template<Tracing T> template<Color Us>
444
- Score Evaluation<T>::pieces(PieceType Pt) {
445
-
446
- constexpr Color Them = ~Us;
447
- constexpr Direction Down = -pawn_push(Us);
448
- constexpr Bitboard OutpostRanks = (Us == WHITE ? Rank4BB | Rank5BB | Rank6BB
449
- : Rank5BB | Rank4BB | Rank3BB);
450
- Bitboard b1 = pos.pieces(Us, Pt);
451
- Bitboard b, bb;
452
- Score score = SCORE_ZERO;
453
-
454
- attackedBy[Us][Pt] = 0;
455
-
456
- while (b1)
457
- {
458
- Square s = pop_lsb(b1);
459
-
460
- // Find attacked squares, including x-ray attacks for bishops and rooks
461
- b = Pt == BISHOP ? attacks_bb<BISHOP>(s, pos.pieces() ^ pos.pieces(QUEEN))
462
- : Pt == ROOK && !pos.diagonal_lines() ? attacks_bb< ROOK>(s, pos.pieces() ^ pos.pieces(QUEEN) ^ pos.pieces(Us, ROOK))
463
- : pos.attacks_from(Us, Pt, s);
464
-
465
- // Restrict mobility to actual squares of board
466
- b &= pos.board_bb(Us, Pt);
467
-
468
- if (pos.blockers_for_king(Us) & s)
469
- b &= line_bb(pos.square<KING>(Us), s);
470
-
471
- attackedBy2[Us] |= attackedBy[Us][ALL_PIECES] & b;
472
- attackedBy[Us][Pt] |= b;
473
- attackedBy[Us][ALL_PIECES] |= b;
474
-
475
- if (b & kingRing[Them])
476
- {
477
- kingAttackersCount[Us]++;
478
- kingAttackersWeight[Us] += KingAttackWeights[std::min(Pt, FAIRY_PIECES)];
479
- kingAttacksCount[Us] += popcount(b & attackedBy[Them][KING]);
480
- }
481
-
482
- else if (Pt == ROOK && (file_bb(s) & kingRing[Them]))
483
- score += RookOnKingRing;
484
-
485
- else if (Pt == BISHOP && (attacks_bb<BISHOP>(s, pos.pieces(PAWN)) & kingRing[Them]))
486
- score += BishopOnKingRing;
487
-
488
- if (Pt > QUEEN)
489
- b = (b & pos.pieces()) | (pos.moves_from(Us, Pt, s) & ~pos.pieces() & pos.board_bb());
490
-
491
- int mob = popcount(b & mobilityArea[Us]);
492
- if (Pt <= QUEEN)
493
- mobility[Us] += MobilityBonus[Pt - 2][mob];
494
- else
495
- mobility[Us] += MaxMobility * (mob - 2) / (8 + mob);
496
-
497
- // Piece promotion bonus
498
- if (pos.promoted_piece_type(Pt) != NO_PIECE_TYPE)
499
- {
500
- Bitboard zone = pos.promotion_zone(Us);
501
- if (zone & (b | s))
502
- score += make_score(PieceValue[MG][pos.promoted_piece_type(Pt)] - PieceValue[MG][Pt],
503
- PieceValue[EG][pos.promoted_piece_type(Pt)] - PieceValue[EG][Pt]) / (zone & s && b ? 6 : 12);
504
- }
505
- else if (pos.piece_demotion() && pos.unpromoted_piece_on(s))
506
- score -= make_score(PieceValue[MG][Pt] - PieceValue[MG][pos.unpromoted_piece_on(s)],
507
- PieceValue[EG][Pt] - PieceValue[EG][pos.unpromoted_piece_on(s)]) / 4;
508
- else if (pos.captures_to_hand() && pos.unpromoted_piece_on(s))
509
- score += make_score(PieceValue[MG][Pt] - PieceValue[MG][pos.unpromoted_piece_on(s)],
510
- PieceValue[EG][Pt] - PieceValue[EG][pos.unpromoted_piece_on(s)]) / 8;
511
-
512
- // Penalty if the piece is far from the kings in drop variants
513
- if ((pos.captures_to_hand() || pos.two_boards()) && pos.count<KING>(Them) && pos.count<KING>(Us))
514
- {
515
- if (!(b & (kingRing[Us] | kingRing[Them])))
516
- score -= KingProximity * distance(s, pos.square<KING>(Us)) * distance(s, pos.square<KING>(Them));
517
- }
518
-
519
- else if (pos.count<KING>(Us) && (Pt == FERS || Pt == SILVER))
520
- score -= EndgameKingProximity * (distance(s, pos.square<KING>(Us)) - 2);
521
-
522
- if (Pt == SOLDIER && (pos.pieces(Us, SOLDIER) & rank_bb(s) & adjacent_files_bb(s)))
523
- score += ConnectedSoldier;
524
-
525
- if (Pt == BISHOP || Pt == KNIGHT)
526
- {
527
- // Bonus if the piece is on an outpost square or can reach one
528
- // Bonus for knights (UncontestedOutpost) if few relevant targets
529
- bb = OutpostRanks & (attackedBy[Us][PAWN] | shift<Down>(pos.pieces(PAWN)))
530
- & ~pe->pawn_attacks_span(Them);
531
- Bitboard targets = pos.pieces(Them) & ~pos.pieces(PAWN);
532
-
533
- if ( Pt == KNIGHT
534
- && bb & s & ~CenterFiles // on a side outpost
535
- && !(b & targets) // no relevant attacks
536
- && (!more_than_one(targets & (s & QueenSide ? QueenSide : KingSide))))
537
- score += UncontestedOutpost * popcount(pos.pieces(PAWN) & (s & QueenSide ? QueenSide : KingSide));
538
- else if (bb & s)
539
- score += Outpost[Pt == BISHOP];
540
- else if (Pt == KNIGHT && bb & b & ~pos.pieces(Us))
541
- score += ReachableOutpost;
542
-
543
- // Bonus for a knight or bishop shielded by pawn
544
- if (shift<Down>(pos.pieces(PAWN)) & s)
545
- score += MinorBehindPawn;
546
-
547
- // Penalty if the piece is far from the king
548
- if (pos.count<KING>(Us))
549
- score -= KingProtector[Pt == BISHOP] * distance(pos.square<KING>(Us), s);
550
-
551
- if (Pt == BISHOP)
552
- {
553
- // Penalty according to the number of our pawns on the same color square as the
554
- // bishop, bigger when the center files are blocked with pawns and smaller
555
- // when the bishop is outside the pawn chain.
556
- Bitboard blocked = pos.pieces(Us, PAWN) & shift<Down>(pos.pieces());
557
-
558
- score -= BishopPawns[edge_distance(file_of(s), pos.max_file())] * pos.pawns_on_same_color_squares(Us, s)
559
- * (!(attackedBy[Us][PAWN] & s) + popcount(blocked & CenterFiles));
560
-
561
- // Penalty for all enemy pawns x-rayed
562
- score -= BishopXRayPawns * popcount(attacks_bb<BISHOP>(s) & pos.pieces(Them, PAWN));
563
-
564
- // Bonus for bishop on a long diagonal which can "see" both center squares
565
- if (more_than_one(attacks_bb<BISHOP>(s, pos.pieces(PAWN)) & Center))
566
- score += LongDiagonalBishop;
567
-
568
- // An important Chess960 pattern: a cornered bishop blocked by a friendly
569
- // pawn diagonally in front of it is a very serious problem, especially
570
- // when that pawn is also blocked.
571
- if ( pos.is_chess960()
572
- && (s == relative_square(Us, SQ_A1) || s == relative_square(Us, SQ_H1)))
573
- {
574
- Direction d = pawn_push(Us) + (file_of(s) == FILE_A ? EAST : WEST);
575
- if (pos.piece_on(s + d) == make_piece(Us, PAWN))
576
- score -= !pos.empty(s + d + pawn_push(Us)) ? 4 * make_score(CorneredBishop, CorneredBishop)
577
- : 3 * make_score(CorneredBishop, CorneredBishop);
578
- }
579
- }
580
- }
581
-
582
- if (Pt == ROOK)
583
- {
584
- // Bonuses for rook on a (semi-)open or closed file
585
- if (pos.is_on_semiopen_file(Us, s))
586
- {
587
- score += RookOnOpenFile[pos.is_on_semiopen_file(Them, s)];
588
- }
589
- else
590
- {
591
- // If our pawn on this file is blocked, increase penalty
592
- if ( pos.pieces(Us, PAWN)
593
- & shift<Down>(pos.pieces())
594
- & file_bb(s))
595
- {
596
- score -= RookOnClosedFile;
597
- }
598
-
599
- // Penalty when trapped by the king, even more if the king cannot castle
600
- if (mob <= 3 && pos.count<KING>(Us))
601
- {
602
- File kf = file_of(pos.square<KING>(Us));
603
- if ((kf < FILE_E) == (file_of(s) < kf))
604
- score -= TrappedRook * (1 + !pos.castling_rights(Us));
605
- }
606
- }
607
- }
608
-
609
- if (Pt == QUEEN)
610
- {
611
- // Penalty if any relative pin or discovered attack against the queen
612
- Bitboard queenPinners;
613
- if (pos.slider_blockers(pos.pieces(Them, ROOK, BISHOP), s, queenPinners, Them))
614
- score -= WeakQueen;
615
- }
616
- }
617
- if constexpr (T)
618
- Trace::add(Pt, Us, score);
619
-
620
- return score;
621
- }
622
-
623
- // Evaluation::hand() scores pieces of a given color and type in hand
624
- template<Tracing T> template<Color Us>
625
- Score Evaluation<T>::hand(PieceType pt) {
626
-
627
- constexpr Color Them = ~Us;
628
-
629
- Score score = SCORE_ZERO;
630
-
631
- if (pos.count_in_hand(Us, pt) > 0 && pt != KING)
632
- {
633
- Bitboard b = pos.drop_region(Us, pt) & ~pos.pieces() & (~attackedBy2[Them] | attackedBy[Us][ALL_PIECES]);
634
- if ((b & kingRing[Them]) && pt != SHOGI_PAWN)
635
- {
636
- kingAttackersCountInHand[Us] += pos.count_in_hand(Us, pt);
637
- kingAttackersWeightInHand[Us] += KingAttackWeights[std::min(pt, FAIRY_PIECES)] * pos.count_in_hand(Us, pt);
638
- kingAttacksCount[Us] += popcount(b & attackedBy[Them][KING]);
639
- }
640
- Bitboard theirHalf = pos.board_bb() & ~forward_ranks_bb(Them, relative_rank(Them, Rank((pos.max_rank() - 1) / 2), pos.max_rank()));
641
- mobility[Us] += DropMobility * popcount(b & theirHalf & ~attackedBy[Them][ALL_PIECES]);
642
-
643
- // Bonus for Kyoto shogi style drops of promoted pieces
644
- if (pos.promoted_piece_type(pt) != NO_PIECE_TYPE && pos.drop_promoted())
645
- score += make_score(std::max(PieceValue[MG][pos.promoted_piece_type(pt)] - PieceValue[MG][pt], VALUE_ZERO),
646
- std::max(PieceValue[EG][pos.promoted_piece_type(pt)] - PieceValue[EG][pt], VALUE_ZERO)) / 4 * pos.count_in_hand(Us, pt);
647
-
648
- // Mobility bonus for reversi variants
649
- if (pos.enclosing_drop())
650
- mobility[Us] += make_score(500, 500) * popcount(b);
651
-
652
- // Reduce score if there is a deficit of gates
653
- if (pos.seirawan_gating() && !pos.piece_drops() && pos.count_in_hand(Us, ALL_PIECES) > popcount(pos.gates(Us)))
654
- score -= make_score(200, 900) / pos.count_in_hand(Us, ALL_PIECES) * (pos.count_in_hand(Us, ALL_PIECES) - popcount(pos.gates(Us)));
655
-
656
- // Redundant pieces that can not be doubled per file (e.g., shogi pawns)
657
- if (pt == pos.drop_no_doubled())
658
- score -= make_score(50, 20) * std::max(pos.count_with_hand(Us, pt) - pos.max_file() - 1, 0);
659
- }
660
-
661
- return score;
662
- }
663
-
664
- // Evaluation::king() assigns bonuses and penalties to a king of a given color
665
-
666
- template<Tracing T> template<Color Us>
667
- Score Evaluation<T>::king() const {
668
-
669
- constexpr Color Them = ~Us;
670
- Rank r = relative_rank(Us, std::min(Rank((pos.max_rank() - 1) / 2 + 1), pos.max_rank()), pos.max_rank());
671
- Bitboard Camp = pos.board_bb() & ~forward_ranks_bb(Us, r);
672
-
673
- if (!pos.count<KING>(Us) || !pos.checking_permitted() || pos.checkmate_value() != -VALUE_MATE)
674
- return SCORE_ZERO;
675
-
676
- Bitboard weak, b1, b2, b3, safe, unsafeChecks = 0;
677
- Bitboard queenChecks, knightChecks, pawnChecks, otherChecks;
678
- int kingDanger = 0;
679
- const Square ksq = pos.square<KING>(Us);
680
-
681
- // Init the score with king shelter and enemy pawns storm
682
- Score score = pe->king_safety<Us>(pos);
683
-
684
- // Attacked squares defended at most once by our queen or king
685
- weak = attackedBy[Them][ALL_PIECES]
686
- & ~attackedBy2[Us]
687
- & (~attackedBy[Us][ALL_PIECES] | attackedBy[Us][KING] | attackedBy[Us][QUEEN]);
688
-
689
- // Analyse the safe enemy's checks which are possible on next move
690
- safe = ~pos.pieces(Them);
691
- if (!pos.check_counting() || pos.checks_remaining(Them) > 1)
692
- safe &= ~attackedBy[Us][ALL_PIECES] | (weak & attackedBy2[Them]);
693
-
694
- b1 = attacks_bb<ROOK >(ksq, pos.pieces() ^ pos.pieces(Us, QUEEN));
695
- b2 = attacks_bb<BISHOP>(ksq, pos.pieces() ^ pos.pieces(Us, QUEEN));
696
-
697
- std::function <Bitboard (Color, PieceType)> get_attacks = [this](Color c, PieceType pt) {
698
- return attackedBy[c][pt] | (pos.piece_drops() && pos.count_in_hand(c, pt) > 0 ? pos.drop_region(c, pt) & ~pos.pieces() : Bitboard(0));
699
- };
700
- for (PieceSet ps = pos.piece_types(); ps;)
701
- {
702
- PieceType pt = pop_lsb(ps);
703
- switch (pt)
704
- {
705
- case QUEEN:
706
- // Enemy queen safe checks: we count them only if they are from squares from
707
- // which we can't give a rook check, because rook checks are more valuable.
708
- queenChecks = (b1 | b2)
709
- & get_attacks(Them, QUEEN)
710
- & pos.board_bb()
711
- & safe
712
- & ~attackedBy[Us][QUEEN]
713
- & ~(b1 & attackedBy[Them][ROOK]);
714
-
715
- if (queenChecks)
716
- kingDanger += SafeCheck[QUEEN][more_than_one(queenChecks)];
717
- break;
718
- case ROOK:
719
- case BISHOP:
720
- case KNIGHT:
721
- knightChecks = attacks_bb(Us, pt, ksq, pos.pieces() ^ pos.pieces(Us, QUEEN)) & get_attacks(Them, pt) & pos.board_bb();
722
- if (knightChecks & safe)
723
- kingDanger += SafeCheck[pt][more_than_one(knightChecks & safe)];
724
- else
725
- unsafeChecks |= knightChecks;
726
- break;
727
- case PAWN:
728
- if (pos.piece_drops() && pos.count_in_hand(Them, pt) > 0)
729
- {
730
- pawnChecks = attacks_bb(Us, pt, ksq, pos.pieces()) & ~pos.pieces() & pos.board_bb();
731
- if (pawnChecks & safe)
732
- kingDanger += SafeCheck[PAWN][more_than_one(pawnChecks & safe)];
733
- else
734
- unsafeChecks |= pawnChecks;
735
- }
736
- break;
737
- case SHOGI_PAWN:
738
- if (pos.promoted_piece_type(pt))
739
- {
740
- otherChecks = attacks_bb(Us, pos.promoted_piece_type(pt), ksq, pos.pieces()) & attackedBy[Them][pt]
741
- & pos.promotion_zone(Them) & pos.board_bb();
742
- if (otherChecks & safe)
743
- kingDanger += SafeCheck[FAIRY_PIECES][more_than_one(otherChecks & safe)];
744
- else
745
- unsafeChecks |= otherChecks;
746
- }
747
- break;
748
- case KING:
749
- break;
750
- default:
751
- otherChecks = attacks_bb(Us, pt, ksq, pos.pieces()) & get_attacks(Them, pt) & pos.board_bb();
752
- if (otherChecks & safe)
753
- kingDanger += SafeCheck[FAIRY_PIECES][more_than_one(otherChecks & safe)];
754
- else
755
- unsafeChecks |= otherChecks;
756
- }
757
- }
758
-
759
- // Virtual piece drops
760
- if (pos.two_boards() && pos.piece_drops())
761
- {
762
- for (PieceSet ps = pos.piece_types(); ps;)
763
- {
764
- PieceType pt = pop_lsb(ps);
765
- if (pos.count_in_hand(Them, pt) <= 0 && (attacks_bb(Us, pt, ksq, pos.pieces()) & safe & pos.drop_region(Them, pt) & ~pos.pieces()))
766
- {
767
- kingDanger += VirtualCheck * 500 / (500 + PieceValue[MG][pt]);
768
- // Presumably a mate threat
769
- if (!(attackedBy[Us][KING] & ~(attackedBy[Them][ALL_PIECES] | pos.pieces(Us))))
770
- kingDanger += 2000;
771
- }
772
- }
773
- }
774
-
775
- if (pos.check_counting())
776
- kingDanger += kingDanger * 7 / (3 + pos.checks_remaining(Them));
777
-
778
- Square s = file_of(ksq) == FILE_A ? ksq + EAST : file_of(ksq) == pos.max_file() ? ksq + WEST : ksq;
779
- Bitboard kingFlank = pos.max_file() == FILE_H ? KingFlank[file_of(ksq)] : file_bb(s) | adjacent_files_bb(s);
780
-
781
- // Find the squares that opponent attacks in our king flank, the squares
782
- // which they attack twice in that flank, and the squares that we defend.
783
- b1 = attackedBy[Them][ALL_PIECES] & kingFlank & Camp;
784
- b2 = b1 & attackedBy2[Them];
785
- b3 = attackedBy[Us][ALL_PIECES] & kingFlank & Camp;
786
-
787
- int kingFlankAttack = popcount(b1) + popcount(b2);
788
- int kingFlankDefense = popcount(b3);
789
-
790
- kingDanger += kingAttackersCount[Them] * kingAttackersWeight[Them]
791
- + kingAttackersCountInHand[Them] * kingAttackersWeight[Them]
792
- + kingAttackersCount[Them] * kingAttackersWeightInHand[Them]
793
- + 183 * popcount(kingRing[Us] & (weak | ~pos.board_bb(Us, KING))) * (1 + pos.captures_to_hand() + pos.check_counting())
794
- + 148 * popcount(unsafeChecks) * (1 + pos.check_counting())
795
- + 98 * popcount(pos.blockers_for_king(Us))
796
- + 69 * kingAttacksCount[Them] * (2 + 8 * pos.check_counting() + pos.captures_to_hand()) / 2
797
- + 3 * kingFlankAttack * kingFlankAttack / 8
798
- + mg_value(mobility[Them] - mobility[Us]) * int(!pos.captures_to_hand())
799
- - 873 * !(pos.major_pieces(Them) || pos.captures_to_hand())
800
- * 2 / (2 + 2 * pos.check_counting() + 2 * pos.two_boards() + 2 * pos.makpong()
801
- + (pos.king_type() != KING) * (pos.diagonal_lines() ? 1 : 2))
802
- - 100 * bool(attackedBy[Us][KNIGHT] & attackedBy[Us][KING])
803
- - 6 * mg_value(score) / 8
804
- - 4 * kingFlankDefense
805
- + 37;
806
-
807
- // Transform the kingDanger units into a Score, and subtract it from the evaluation
808
- if (kingDanger > 100)
809
- score -= make_score(std::min(kingDanger, 3500) * kingDanger / 4096, kingDanger / 16);
810
-
811
- // Penalty when our king is on a pawnless flank
812
- if (!(pos.pieces(PAWN) & kingFlank))
813
- score -= PawnlessFlank;
814
-
815
- // Penalty if king flank is under attack, potentially moving toward the king
816
- score -= FlankAttacks * kingFlankAttack * (1 + 5 * pos.captures_to_hand() + pos.check_counting());
817
-
818
- if (pos.check_counting())
819
- score += make_score(0, mg_value(score) * 2 / (2 + pos.checks_remaining(Them)));
820
-
821
- if (pos.king_type() == WAZIR)
822
- score += make_score(0, mg_value(score) / 2);
823
-
824
- // For drop games, king danger is independent of game phase, but dependent on material density
825
- if (pos.captures_to_hand() || pos.two_boards())
826
- score = make_score(mg_value(score) * me->material_density() / 11000,
827
- mg_value(score) * me->material_density() / 11000);
828
-
829
- if constexpr (T)
830
- Trace::add(KING, Us, score);
831
-
832
- return score;
833
- }
834
-
835
-
836
- // Evaluation::threats() assigns bonuses according to the types of the
837
- // attacking and the attacked pieces.
838
-
839
- template<Tracing T> template<Color Us>
840
- Score Evaluation<T>::threats() const {
841
-
842
- constexpr Color Them = ~Us;
843
- constexpr Direction Up = pawn_push(Us);
844
- constexpr Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB);
845
-
846
- Bitboard b, weak, defended, nonPawnEnemies, stronglyProtected, safe;
847
- Score score = SCORE_ZERO;
848
-
849
- // Bonuses for variants with mandatory captures
850
- if (pos.must_capture())
851
- {
852
- // Penalties for possible captures
853
- Bitboard captures = attackedBy[Us][ALL_PIECES] & pos.pieces(Them);
854
- if (captures)
855
- score -= make_score(2000, 2000) / (1 + popcount(captures & attackedBy[Them][ALL_PIECES] & ~attackedBy2[Us]));
856
-
857
- // Bonus if we threaten to force captures
858
- Bitboard moves = 0, piecebb = pos.pieces(Us);
859
- while (piecebb)
860
- {
861
- Square s = pop_lsb(piecebb);
862
- if (type_of(pos.piece_on(s)) != KING)
863
- moves |= pos.moves_from(Us, type_of(pos.piece_on(s)), s);
864
- }
865
- score += make_score(200, 200) * popcount(attackedBy[Them][ALL_PIECES] & moves & ~pos.pieces());
866
- score += make_score(200, 220) * popcount(attackedBy[Them][ALL_PIECES] & moves & ~pos.pieces() & ~attackedBy2[Us]);
867
- }
868
-
869
- // Extinction threats
870
- if (pos.extinction_value() == -VALUE_MATE)
871
- {
872
- Bitboard bExt = attackedBy[Us][ALL_PIECES] & pos.pieces(Them);
873
- for (PieceSet ps = pos.extinction_piece_types(); ps;)
874
- {
875
- PieceType pt = pop_lsb(ps);
876
- if (pt == ALL_PIECES)
877
- continue;
878
- int denom = std::max(pos.count_with_hand(Them, pt) - pos.extinction_piece_count(), 1);
879
- // Explosion threats
880
- if (pos.blast_on_capture())
881
- {
882
- int evasions = popcount(((attackedBy[Them][pt] & ~pos.pieces(Them)) | pos.pieces(Them, pt)) & ~attackedBy[Us][ALL_PIECES]) * denom;
883
- int attacks = popcount((attackedBy[Them][pt] | pos.pieces(Them, pt)) & attackedBy[Us][ALL_PIECES]);
884
- int explosions = 0;
885
-
886
- Bitboard bExtBlast = bExt & (attackedBy2[Us] | ~attackedBy[Us][pt]);
887
- while (bExtBlast)
888
- {
889
- Square s = pop_lsb(bExtBlast);
890
- if (((attacks_bb<KING>(s) | s) & pos.pieces(Them, pt)) && !(attacks_bb<KING>(s) & pos.pieces(Us, pt)))
891
- explosions++;
892
- }
893
- int danger = 20 * attacks / (evasions + 1) + 40 * explosions;
894
- score += make_score(danger * (100 + danger), 0);
895
- }
896
- else
897
- // Direct extinction threats
898
- score += make_score(1000, 1000) / (denom * denom) * popcount(bExt & pos.pieces(Them, pt));
899
- }
900
- }
901
-
902
- // Non-pawn enemies
903
- nonPawnEnemies = pos.pieces(Them) & ~pos.pieces(PAWN, SHOGI_PAWN) & ~pos.pieces(SOLDIER);
904
-
905
- // Squares strongly protected by the enemy, either because they defend the
906
- // square with a pawn, or because they defend the square twice and we don't.
907
- stronglyProtected = (attackedBy[Them][PAWN] | attackedBy[Them][SHOGI_PAWN] | attackedBy[Them][SOLDIER])
908
- | (attackedBy2[Them] & ~attackedBy2[Us]);
909
-
910
- // Non-pawn enemies, strongly protected
911
- defended = nonPawnEnemies & stronglyProtected;
912
-
913
- // Enemies not strongly protected and under our attack
914
- weak = pos.pieces(Them) & ~stronglyProtected & attackedBy[Us][ALL_PIECES];
915
-
916
- // Bonus according to the kind of attacking pieces
917
- if (defended | weak)
918
- {
919
- b = (defended | weak) & (attackedBy[Us][KNIGHT] | attackedBy[Us][BISHOP]);
920
- while (b)
921
- score += ThreatByMinor[type_of(pos.piece_on(pop_lsb(b)))];
922
-
923
- b = weak & attackedBy[Us][ROOK];
924
- while (b)
925
- score += ThreatByRook[type_of(pos.piece_on(pop_lsb(b)))];
926
-
927
- if (weak & attackedBy[Us][KING])
928
- score += ThreatByKing;
929
-
930
- b = ~attackedBy[Them][ALL_PIECES]
931
- | (nonPawnEnemies & attackedBy2[Us]);
932
- score += Hanging * popcount(weak & b);
933
-
934
- // Additional bonus if weak piece is only protected by a queen
935
- score += WeakQueenProtection * popcount(weak & attackedBy[Them][QUEEN]);
936
- }
937
-
938
- // Bonus for restricting their piece moves
939
- b = attackedBy[Them][ALL_PIECES]
940
- & ~stronglyProtected
941
- & attackedBy[Us][ALL_PIECES];
942
- score += RestrictedPiece * popcount(b);
943
-
944
- // Protected or unattacked squares
945
- safe = ~attackedBy[Them][ALL_PIECES] | attackedBy[Us][ALL_PIECES];
946
-
947
- // Bonus for attacking enemy pieces with our relatively safe pawns
948
- b = pos.pieces(Us, PAWN) & safe;
949
- b = pawn_attacks_bb<Us>(b) & nonPawnEnemies;
950
- score += ThreatBySafePawn * popcount(b);
951
-
952
- // Find squares where our pawns can push on the next move
953
- b = shift<Up>(pos.pieces(Us, PAWN)) & ~pos.pieces();
954
- b |= shift<Up>(b & TRank3BB) & ~pos.pieces();
955
-
956
- // Keep only the squares which are relatively safe
957
- b &= ~attackedBy[Them][PAWN] & safe;
958
-
959
- // Bonus for safe pawn threats on the next move
960
- b = (pawn_attacks_bb<Us>(b) | shift<Up>(shift<Up>(pos.pieces(Us, SHOGI_PAWN, SOLDIER)))) & nonPawnEnemies;
961
- score += ThreatByPawnPush * popcount(b);
962
-
963
- // Bonus for threats on the next moves against enemy queen
964
- if (pos.count<QUEEN>(Them) == 1)
965
- {
966
- bool queenImbalance = pos.count<QUEEN>() == 1;
967
-
968
- Square s = pos.square<QUEEN>(Them);
969
- safe = mobilityArea[Us]
970
- & ~pos.pieces(Us, PAWN)
971
- & ~stronglyProtected;
972
-
973
- b = attackedBy[Us][KNIGHT] & attacks_bb<KNIGHT>(s);
974
-
975
- score += KnightOnQueen * popcount(b & safe) * (1 + queenImbalance);
976
-
977
- b = (attackedBy[Us][BISHOP] & attacks_bb<BISHOP>(s, pos.pieces()))
978
- | (attackedBy[Us][ROOK ] & attacks_bb<ROOK >(s, pos.pieces()));
979
-
980
- score += SliderOnQueen * popcount(b & safe & attackedBy2[Us]) * (1 + queenImbalance);
981
- }
982
-
983
- if constexpr (T)
984
- Trace::add(THREAT, Us, score);
985
-
986
- return score;
987
- }
988
-
989
- // Evaluation::passed() evaluates the passed pawns and candidate passed
990
- // pawns of the given color.
991
-
992
- template<Tracing T> template<Color Us>
993
- Score Evaluation<T>::passed() const {
994
-
995
- constexpr Color Them = ~Us;
996
- constexpr Direction Up = pawn_push(Us);
997
- constexpr Direction Down = -Up;
998
-
999
- auto king_proximity = [&](Color c, Square s) {
1000
- return pos.extinction_value() == VALUE_MATE ? 0 : pos.count<KING>(c) ? std::min(distance(pos.square<KING>(c), s), 5) : 5;
1001
- };
1002
-
1003
- Bitboard b, bb, squaresToQueen, unsafeSquares, blockedPassers, helpers;
1004
- Score score = SCORE_ZERO;
1005
-
1006
- b = pe->passed_pawns(Us);
1007
-
1008
- blockedPassers = b & shift<Down>(pos.pieces(Them, PAWN));
1009
- if (blockedPassers)
1010
- {
1011
- helpers = shift<Up>(pos.pieces(Us, PAWN))
1012
- & ~pos.pieces(Them)
1013
- & (~attackedBy2[Them] | attackedBy[Us][ALL_PIECES]);
1014
-
1015
- // Remove blocked candidate passers that don't have help to pass
1016
- b &= ~blockedPassers
1017
- | shift<WEST>(helpers)
1018
- | shift<EAST>(helpers);
1019
- }
1020
-
1021
- while (b)
1022
- {
1023
- Square s = pop_lsb(b);
1024
-
1025
- assert(!(pos.pieces(Them, PAWN) & forward_file_bb(Us, s + Up)));
1026
-
1027
- int r = std::max(RANK_8 - std::max(relative_rank(Us, pos.promotion_square(Us, s), pos.max_rank()) - relative_rank(Us, s, pos.max_rank()), 0), 0);
1028
-
1029
- Score bonus = PassedRank[r];
1030
-
1031
- if (r > RANK_3)
1032
- {
1033
- int w = 5 * r - 13;
1034
- Square blockSq = s + Up;
1035
-
1036
- // Adjust bonus based on the king's proximity
1037
- bonus += make_score(0, ( king_proximity(Them, blockSq) * 19 / 4
1038
- - king_proximity(Us, blockSq) * 2) * w);
1039
-
1040
- // If blockSq is not the queening square then consider also a second push
1041
- if (r != RANK_7)
1042
- bonus -= make_score(0, king_proximity(Us, blockSq + Up) * w);
1043
-
1044
- // If the pawn is free to advance, then increase the bonus
1045
- if (pos.empty(blockSq))
1046
- {
1047
- squaresToQueen = forward_file_bb(Us, s);
1048
- unsafeSquares = passed_pawn_span(Us, s);
1049
-
1050
- bb = forward_file_bb(Them, s) & pos.pieces(ROOK, QUEEN);
1051
-
1052
- if (!(pos.pieces(Them) & bb))
1053
- unsafeSquares &= attackedBy[Them][ALL_PIECES] | pos.pieces(Them);
1054
-
1055
- // If there are no enemy pieces or attacks on passed pawn span, assign a big bonus.
1056
- // Or if there is some, but they are all attacked by our pawns, assign a bit smaller bonus.
1057
- // Otherwise assign a smaller bonus if the path to queen is not attacked
1058
- // and even smaller bonus if it is attacked but block square is not.
1059
- int k = !unsafeSquares ? 36 :
1060
- !(unsafeSquares & ~attackedBy[Us][PAWN]) ? 30 :
1061
- !(unsafeSquares & squaresToQueen) ? 17 :
1062
- !(unsafeSquares & blockSq) ? 7 :
1063
- 0 ;
1064
-
1065
- // Assign a larger bonus if the block square is defended
1066
- if ((pos.pieces(Us) & bb) || (attackedBy[Us][ALL_PIECES] & blockSq))
1067
- k += 5;
1068
-
1069
- bonus += make_score(k * w, k * w);
1070
- }
1071
- } // r > RANK_3
1072
-
1073
- score += bonus - PassedFile * edge_distance(file_of(s), pos.max_file());
1074
- }
1075
-
1076
- // Passed custom pawns
1077
- for (PieceSet ps = (pos.promotion_pawn_types(Us) & ~piece_set(PAWN)); ps;)
1078
- {
1079
- PieceType pt = pop_lsb(ps);
1080
- Bitboard b2 = pos.pieces(Us, pt);
1081
- while (b2)
1082
- {
1083
- Square s = pop_lsb(b2);
1084
- if (pos.promotion_square(Us, s) == SQ_NONE || (pos.pieces(Them, pt) & forward_file_bb(Us, s)))
1085
- continue;
1086
- int r = std::max(RANK_8 - std::max(relative_rank(Us, pos.promotion_square(Us, s), pos.max_rank()) - relative_rank(Us, s, pos.max_rank()), 0), 0);
1087
- score += PassedRank[r];
1088
- }
1089
- }
1090
-
1091
- // Scale by maximum promotion piece value
1092
- Value maxMg = VALUE_ZERO, maxEg = VALUE_ZERO;
1093
- for (PieceSet ps = pos.promotion_piece_types(Us); ps;)
1094
- {
1095
- PieceType pt = pop_lsb(ps);
1096
- maxMg = std::max(maxMg, PieceValue[MG][pt]);
1097
- maxEg = std::max(maxEg, PieceValue[EG][pt]);
1098
- }
1099
- score = make_score(mg_value(score) * int(maxMg - PawnValueMg) / (QueenValueMg - PawnValueMg),
1100
- eg_value(score) * int(maxEg - PawnValueEg) / (QueenValueEg - PawnValueEg));
1101
-
1102
- // Score passed shogi pawns
1103
- PieceType pt = pos.promoted_piece_type(SHOGI_PAWN);
1104
- if (pt != NO_PIECE_TYPE)
1105
- {
1106
- b = pos.pieces(Us, SHOGI_PAWN);
1107
- while (b)
1108
- {
1109
- Square s = pop_lsb(b);
1110
- if ((pos.pieces(Them, SHOGI_PAWN) & forward_file_bb(Us, s)) || pos.promotion_square(Us, s) == SQ_NONE)
1111
- continue;
1112
-
1113
- Square blockSq = s + Up;
1114
- int d = 2 * std::max(relative_rank(Us, pos.promotion_square(Us, s), pos.max_rank()) - relative_rank(Us, s, pos.max_rank()), 1);
1115
- d += !!(attackedBy[Them][ALL_PIECES] & ~attackedBy2[Us] & blockSq);
1116
- score += make_score(PieceValue[MG][pt], PieceValue[EG][pt]) / (d * d);
1117
- }
1118
- }
1119
-
1120
- if constexpr (T)
1121
- Trace::add(PASSED, Us, score);
1122
-
1123
- return score;
1124
- }
1125
-
1126
-
1127
- // Evaluation::space() computes a space evaluation for a given side, aiming to improve game
1128
- // play in the opening. It is based on the number of safe squares on the four central files
1129
- // on ranks 2 to 4. Completely safe squares behind a friendly pawn are counted twice.
1130
- // Finally, the space bonus is multiplied by a weight which decreases according to occupancy.
1131
-
1132
- template<Tracing T> template<Color Us>
1133
- Score Evaluation<T>::space() const {
1134
-
1135
- bool pawnsOnly = !(pos.pieces(Us) ^ pos.pieces(Us, PAWN));
1136
-
1137
- // Early exit if, for example, both queens or 6 minor pieces have been exchanged
1138
- if (pos.non_pawn_material() < SpaceThreshold && !pawnsOnly && pos.double_step_region(Us))
1139
- return SCORE_ZERO;
1140
-
1141
- constexpr Color Them = ~Us;
1142
- constexpr Direction Down = -pawn_push(Us);
1143
- constexpr Bitboard SpaceMask =
1144
- Us == WHITE ? CenterFiles & (Rank2BB | Rank3BB | Rank4BB)
1145
- : CenterFiles & (Rank7BB | Rank6BB | Rank5BB);
1146
-
1147
- // Find the available squares for our pieces inside the area defined by SpaceMask
1148
- Bitboard safe = SpaceMask
1149
- & ~pos.pieces(Us, PAWN)
1150
- & ~attackedBy[Them][PAWN];
1151
-
1152
- // Find all squares which are at most three squares behind some friendly pawn
1153
- Bitboard behind = pos.pieces(Us, PAWN);
1154
- behind |= shift<Down>(behind);
1155
- behind |= shift<Down+Down>(behind);
1156
-
1157
- if (pawnsOnly)
1158
- {
1159
- safe = pos.board_bb() & ((attackedBy2[Us] & ~attackedBy2[Them]) | (attackedBy[Us][PAWN] & ~pos.pieces(Us, PAWN)));
1160
- behind = 0;
1161
- }
1162
-
1163
- // Compute space score based on the number of safe squares and number of our pieces
1164
- // increased with number of total blocked pawns in position.
1165
- int bonus = popcount(safe) + popcount(behind & safe & ~attackedBy[Them][ALL_PIECES]);
1166
- int weight = pos.count<ALL_PIECES>(Us) - 3 + std::min(pe->blocked_count(), 9);
1167
- Score score = make_score(bonus * weight * weight / 16, 0);
1168
-
1169
- if (pos.flag_region(Us))
1170
- score += make_score(200, 200) * popcount(behind & safe & pos.flag_region(Us));
1171
-
1172
- if constexpr (T)
1173
- Trace::add(SPACE, Us, score);
1174
-
1175
- return score;
1176
- }
1177
-
1178
-
1179
- // Evaluation::variant() computes variant-specific evaluation bonuses for a given side.
1180
-
1181
- template<Tracing T> template<Color Us>
1182
- Score Evaluation<T>::variant() const {
1183
-
1184
- constexpr Color Them = ~Us;
1185
- constexpr Direction Down = pawn_push(Them);
1186
-
1187
- Score score = SCORE_ZERO;
1188
-
1189
- // Capture the flag
1190
- if (pos.flag_region(Us))
1191
- {
1192
- Bitboard ctfPieces = pos.pieces(Us, pos.flag_piece(Us));
1193
- Bitboard ctfTargets = pos.flag_region(Us) & pos.board_bb();
1194
- Bitboard onHold = 0;
1195
- Bitboard onHold2 = 0;
1196
- Bitboard processed = 0;
1197
- Bitboard blocked = pos.pieces(Us, PAWN) | attackedBy[Them][ALL_PIECES];
1198
- Bitboard doubleBlocked = attackedBy2[Them]
1199
- | (pos.pieces(Us, PAWN) & (shift<Down>(pos.pieces()) | attackedBy[Them][ALL_PIECES]))
1200
- | (pos.pieces(Them) & pe->pawn_attacks(Them))
1201
- | (pawn_attacks_bb<Them>(pos.pieces(Them, PAWN) & pe->pawn_attacks(Them)));
1202
- Bitboard inaccessible = pos.pieces(Us, PAWN) & shift<Down>(pos.pieces(Them, PAWN));
1203
- // Traverse all paths of the CTF pieces to the CTF targets.
1204
- // Put squares that are attacked or occupied on hold for one iteration.
1205
- // This reflects that likely a move will be needed to block or capture the attack.
1206
- // If all piece types are eligible, use the king path as a proxy for distance.
1207
- PieceType ptCtf = pos.flag_piece(Us) == ALL_PIECES ? KING : pos.flag_piece(Us);
1208
- for (int dist = 0; (ctfPieces || onHold || onHold2) && (ctfTargets & ~processed); dist++)
1209
- {
1210
- int wins = popcount(ctfTargets & ctfPieces);
1211
- if (wins)
1212
- score += make_score(4000, 4000) * wins / (wins + dist * dist);
1213
- Bitboard current = ctfPieces & ~ctfTargets;
1214
- processed |= ctfPieces;
1215
- ctfPieces = onHold & ~processed;
1216
- onHold = onHold2 & ~processed;
1217
- onHold2 = 0;
1218
- while (current)
1219
- {
1220
- Square s = pop_lsb(current);
1221
- Bitboard attacks = ( (PseudoAttacks[Us][ptCtf][s] & pos.pieces())
1222
- | (PseudoMoves[0][Us][ptCtf][s] & ~pos.pieces())) & ~processed & pos.board_bb();
1223
- ctfPieces |= attacks & ~blocked;
1224
- onHold |= attacks & ~doubleBlocked;
1225
- onHold2 |= attacks & ~inaccessible;
1226
- }
1227
- }
1228
- }
1229
-
1230
- // nCheck
1231
- if (pos.check_counting())
1232
- {
1233
- int remainingChecks = pos.checks_remaining(Us);
1234
- assert(remainingChecks > 0);
1235
- score += make_score(3600, 1000) / (remainingChecks * remainingChecks);
1236
- }
1237
-
1238
- // Extinction
1239
- if (pos.extinction_value() != VALUE_NONE)
1240
- {
1241
- for (PieceSet ps = pos.extinction_piece_types(); ps;)
1242
- {
1243
- PieceType pt = pop_lsb(ps);
1244
- if (pt != ALL_PIECES)
1245
- {
1246
- // Single piece type extinction bonus
1247
- int denom = std::max(pos.count(Us, pt) - pos.extinction_piece_count(), 1);
1248
- if (pos.count(Them, pt) >= pos.extinction_opponent_piece_count() || pos.two_boards())
1249
- score += make_score(1000000 / (500 + PieceValue[MG][pt]),
1250
- 1000000 / (500 + PieceValue[EG][pt])) / (denom * denom)
1251
- * (pos.extinction_value() / VALUE_MATE);
1252
- }
1253
- else if (pos.extinction_value() == VALUE_MATE)
1254
- {
1255
- // Losing chess variant bonus
1256
- score += make_score(pos.non_pawn_material(Us), pos.non_pawn_material(Us)) / std::max(pos.count<ALL_PIECES>(Us), 1);
1257
- }
1258
- else if (pos.count<PAWN>(Us) == pos.count<ALL_PIECES>(Us))
1259
- {
1260
- // Pawns easy to stop/capture
1261
- int l = 0, m = 0, r = popcount(pos.pieces(Us, PAWN) & file_bb(FILE_A));
1262
- for (File f = FILE_A; f <= pos.max_file(); ++f)
1263
- {
1264
- l = m; m = r; r = popcount(pos.pieces(Us, PAWN) & shift<EAST>(file_bb(f)));
1265
- score -= make_score(80 - 10 * (edge_distance(f, pos.max_file()) % 2),
1266
- 80 - 15 * (edge_distance(f, pos.max_file()) % 2)) * m / (1 + l * r);
1267
- }
1268
- }
1269
- else if (pos.count<PAWN>(Them) == pos.count<ALL_PIECES>(Them))
1270
- {
1271
- // Add a bonus according to how close we are to breaking through the pawn wall
1272
- int dist = 8;
1273
- Bitboard breakthroughs = attackedBy[Us][ALL_PIECES] & rank_bb(relative_rank(Us, pos.max_rank(), pos.max_rank()));
1274
- if (breakthroughs)
1275
- dist = attackedBy[Us][QUEEN] & breakthroughs ? 0 : 1;
1276
- else for (File f = FILE_A; f <= pos.max_file(); ++f)
1277
- dist = std::min(dist, popcount(pos.pieces(PAWN) & file_bb(f)));
1278
- score += make_score(70, 70) * pos.count<PAWN>(Them) / (1 + dist * dist) / (pos.pieces(Us, QUEEN) ? 2 : 4);
1279
- }
1280
- }
1281
- }
1282
-
1283
- // Connect-n
1284
- if (pos.connect_n() > 0)
1285
- {
1286
- //Calculate eligible pieces for connection once.
1287
- //Still consider all opponent pieces as blocking.
1288
- Bitboard connectPiecesUs = 0;
1289
- for (PieceSet ps = pos.connect_piece_types(); ps;){
1290
- PieceType pt = pop_lsb(ps);
1291
- connectPiecesUs |= pos.pieces(pt);
1292
- };
1293
- connectPiecesUs &= pos.pieces(Us);
1294
-
1295
- for (const Direction& d : pos.getConnectDirections())
1296
-
1297
- {
1298
- // Find sufficiently large gaps
1299
- Bitboard b = pos.board_bb() & ~pos.pieces(Them);
1300
- for (int i = 1; i < pos.connect_n(); i++)
1301
- b &= shift(d, b);
1302
- // Count number of pieces per gap
1303
- while (b)
1304
- {
1305
- Square s = pop_lsb(b);
1306
- int c = 0;
1307
- for (int j = 0; j < pos.connect_n(); j++)
1308
- if (connectPiecesUs & (s - j * d))
1309
- c++;
1310
- score += make_score(200, 200) * c / (pos.connect_n() - c) / (pos.connect_n() - c);
1311
- }
1312
- }
1313
- }
1314
-
1315
- // Potential piece flips (Reversi)
1316
- if (pos.flip_enclosed_pieces())
1317
- {
1318
- // Stable pieces
1319
- if (pos.flip_enclosed_pieces() == REVERSI)
1320
- {
1321
- Bitboard edges = (FileABB | file_bb(pos.max_file()) | Rank1BB | rank_bb(pos.max_rank())) & pos.board_bb();
1322
- Bitboard edgePieces = pos.pieces(Us) & edges;
1323
- while (edgePieces)
1324
- {
1325
- Bitboard connectedEdge = attacks_bb(Us, ROOK, pop_lsb(edgePieces), ~(pos.pieces(Us) & edges)) & edges;
1326
- if (!more_than_one(connectedEdge & ~pos.pieces(Us)))
1327
- score += make_score(300, 300);
1328
- else if (!(connectedEdge & ~pos.pieces()))
1329
- score += make_score(200, 200);
1330
- }
1331
- }
1332
-
1333
- // Unstable
1334
- Bitboard unstable = 0;
1335
- Bitboard drops = pos.drop_region(Them, IMMOBILE_PIECE);
1336
- while (drops)
1337
- {
1338
- Square s = pop_lsb(drops);
1339
- if (pos.flip_enclosed_pieces() == REVERSI)
1340
- {
1341
- Bitboard b = attacks_bb(Them, QUEEN, s, ~pos.pieces(Us)) & ~PseudoAttacks[Them][KING][s] & pos.pieces(Them);
1342
- while(b)
1343
- unstable |= between_bb(s, pop_lsb(b));
1344
- }
1345
- else
1346
- unstable |= PseudoAttacks[Them][KING][s] & pos.pieces(Us);
1347
- }
1348
- score -= make_score(200, 200) * popcount(unstable);
1349
- }
1350
-
1351
- if (T)
1352
- Trace::add(VARIANT, Us, score);
1353
-
1354
- return score;
1355
- }
1356
-
1357
-
1358
- // Evaluation::winnable() adjusts the midgame and endgame score components, based on
1359
- // the known attacking/defending status of the players. The final value is derived
1360
- // by interpolation from the midgame and endgame values.
1361
-
1362
- template<Tracing T>
1363
- Value Evaluation<T>::winnable(Score score) const {
1364
-
1365
- // No initiative bonus for variants that do not require sufficient mating material, e.g., extinction variants.
1366
- // This protects them from misidentification as drawish.
1367
- int complexity = 0;
1368
- bool pawnsOnBothFlanks = true;
1369
- if ( pos.extinction_value() == VALUE_NONE
1370
- && !pos.captures_to_hand()
1371
- && !pos.connect_n()
1372
- && !pos.material_counting()
1373
- && !(pos.flag_region(WHITE) || pos.flag_region(BLACK)))
1374
- {
1375
- int outflanking = !pos.count<KING>(WHITE) || !pos.count<KING>(BLACK) ? 0
1376
- : distance<File>(pos.square<KING>(WHITE), pos.square<KING>(BLACK))
1377
- + int(rank_of(pos.square<KING>(WHITE)) - rank_of(pos.square<KING>(BLACK)));
1378
-
1379
- pawnsOnBothFlanks = (pos.pieces(PAWN) & QueenSide)
1380
- && (pos.pieces(PAWN) & KingSide);
1381
-
1382
- bool almostUnwinnable = outflanking < 0
1383
- && pos.stalemate_value() == VALUE_DRAW
1384
- && !pawnsOnBothFlanks;
1385
-
1386
- bool infiltration = (pos.count<KING>(WHITE) && rank_of(pos.square<KING>(WHITE)) > RANK_4)
1387
- || (pos.count<KING>(BLACK) && rank_of(pos.square<KING>(BLACK)) < RANK_5);
1388
-
1389
- // Compute the initiative bonus for the attacking side
1390
- complexity = 9 * pe->passed_count()
1391
- + 12 * pos.count(WHITE, pos.main_promotion_pawn_type(WHITE)) * bool(pos.main_promotion_pawn_type(WHITE))
1392
- + 12 * pos.count(BLACK, pos.main_promotion_pawn_type(BLACK)) * bool(pos.main_promotion_pawn_type(BLACK))
1393
- + 15 * pos.count<SOLDIER>()
1394
- + 9 * outflanking
1395
- + 21 * pawnsOnBothFlanks
1396
- + 24 * infiltration
1397
- + 51 * !pos.non_pawn_material()
1398
- - 43 * almostUnwinnable
1399
- -110 ;
1400
- }
1401
-
1402
- Value mg = mg_value(score);
1403
- Value eg = eg_value(score);
1404
-
1405
- // Now apply the bonus: note that we find the attacking side by extracting the
1406
- // sign of the midgame or endgame values, and that we carefully cap the bonus
1407
- // so that the midgame and endgame scores do not change sign after the bonus.
1408
- int u = ((mg > 0) - (mg < 0)) * std::clamp(complexity + 50, -abs(mg), 0);
1409
- int v = ((eg > 0) - (eg < 0)) * std::max(complexity, -abs(eg));
1410
-
1411
- mg += u;
1412
- eg += v;
1413
-
1414
- // Compute the scale factor for the winning side
1415
- Color strongSide = eg > VALUE_DRAW ? WHITE : BLACK;
1416
- int sf = me->scale_factor(pos, strongSide);
1417
-
1418
- // If scale factor is not already specific, scale up/down via general heuristics
1419
- if (sf == SCALE_FACTOR_NORMAL && !pos.captures_to_hand() && !pos.material_counting())
1420
- {
1421
- if (pos.opposite_bishops())
1422
- {
1423
- // For pure opposite colored bishops endgames use scale factor
1424
- // based on the number of passed pawns of the strong side.
1425
- if ( pos.non_pawn_material(WHITE) == BishopValueMg
1426
- && pos.non_pawn_material(BLACK) == BishopValueMg)
1427
- sf = 18 + 4 * popcount(pe->passed_pawns(strongSide));
1428
- // For every other opposite colored bishops endgames use scale factor
1429
- // based on the number of all pieces of the strong side.
1430
- else
1431
- sf = 22 + 3 * pos.count<ALL_PIECES>(strongSide);
1432
- }
1433
- // For rook endgames with strong side not having overwhelming pawn number advantage
1434
- // and its pawns being on one flank and weak side protecting its pieces with a king
1435
- // use lower scale factor.
1436
- else if ( pos.non_pawn_material(WHITE) == RookValueMg
1437
- && pos.non_pawn_material(BLACK) == RookValueMg
1438
- && pos.count<PAWN>(strongSide) - pos.count<PAWN>(~strongSide) <= 1
1439
- && bool(KingSide & pos.pieces(strongSide, PAWN)) != bool(QueenSide & pos.pieces(strongSide, PAWN))
1440
- && pos.count<KING>(~strongSide)
1441
- && (attacks_bb<KING>(pos.square<KING>(~strongSide)) & pos.pieces(~strongSide, PAWN)))
1442
- sf = 36;
1443
- // For queen vs no queen endgames use scale factor
1444
- // based on number of minors of side that doesn't have queen.
1445
- else if (pos.count<QUEEN>() == 1)
1446
- sf = 37 + 3 * (pos.count<QUEEN>(WHITE) == 1 ? pos.count<BISHOP>(BLACK) + pos.count<KNIGHT>(BLACK)
1447
- : pos.count<BISHOP>(WHITE) + pos.count<KNIGHT>(WHITE));
1448
- // In every other case use scale factor based on
1449
- // the number of pawns of the strong side reduced if pawns are on a single flank.
1450
- else
1451
- sf = std::min(sf, 36 + 7 * (pos.count<PAWN>(strongSide) + pos.count<SOLDIER>(strongSide))) - 4 * !pawnsOnBothFlanks;
1452
-
1453
- // Reduce scale factor in case of pawns being on a single flank
1454
- sf -= 4 * !pawnsOnBothFlanks;
1455
- }
1456
-
1457
- // Interpolate between the middlegame and (scaled by 'sf') endgame score
1458
- v = mg * int(me->game_phase())
1459
- + eg * int(PHASE_MIDGAME - me->game_phase()) * ScaleFactor(sf) / SCALE_FACTOR_NORMAL;
1460
- v /= PHASE_MIDGAME;
1461
-
1462
- if constexpr (T)
1463
- {
1464
- Trace::add(WINNABLE, make_score(u, eg * ScaleFactor(sf) / SCALE_FACTOR_NORMAL - eg_value(score)));
1465
- Trace::add(TOTAL, make_score(mg, eg * ScaleFactor(sf) / SCALE_FACTOR_NORMAL));
1466
- }
1467
-
1468
- return Value(v);
1469
- }
1470
-
1471
-
1472
- // Evaluation::value() is the main function of the class. It computes the various
1473
- // parts of the evaluation and returns the value of the position from the point
1474
- // of view of the side to move.
1475
-
1476
- template<Tracing T>
1477
- Value Evaluation<T>::value() {
1478
-
1479
- assert(!pos.checkers());
1480
- assert(!pos.is_immediate_game_end());
1481
-
1482
- // Probe the material hash table
1483
- me = Material::probe(pos);
1484
-
1485
- // If we have a specialized evaluation function for the current material
1486
- // configuration, call it and return.
1487
- if (me->specialized_eval_exists())
1488
- return me->evaluate(pos);
1489
-
1490
- // Initialize score by reading the incrementally updated scores included in
1491
- // the position object (material + piece square tables) and the material
1492
- // imbalance. Score is computed internally from the white point of view.
1493
- Score score = pos.psq_score();
1494
- if (T)
1495
- Trace::add(MATERIAL, score);
1496
- score += me->imbalance() + pos.this_thread()->trend;
1497
-
1498
- // Probe the pawn hash table
1499
- pe = Pawns::probe(pos);
1500
- score += pe->pawn_score(WHITE) - pe->pawn_score(BLACK);
1501
-
1502
- // Early exit if score is high
1503
- auto lazy_skip = [&](Value lazyThreshold) {
1504
- return abs(mg_value(score) + eg_value(score)) / 2 > lazyThreshold + pos.non_pawn_material() / 64;
1505
- };
1506
-
1507
- if (lazy_skip(LazyThreshold1) && Options["UCI_Variant"] == "chess")
1508
- goto make_v;
1509
-
1510
- // Main evaluation begins here
1511
- std::memset(attackedBy, 0, sizeof(attackedBy));
1512
- initialize<WHITE>();
1513
- initialize<BLACK>();
1514
-
1515
- // Pieces evaluated first (also populates attackedBy, attackedBy2).
1516
- // For unused piece types, we still need to set attack bitboard to zero.
1517
- for (PieceSet ps = pos.piece_types(); ps;)
1518
- {
1519
- PieceType pt = pop_lsb(ps);
1520
- if (pt != SHOGI_PAWN && pt != PAWN && pt != KING)
1521
- score += pieces<WHITE>(pt) - pieces<BLACK>(pt);
1522
- }
1523
-
1524
- // Evaluate pieces in hand once attack tables are complete
1525
- if (pos.piece_drops() || pos.seirawan_gating())
1526
- for (PieceSet ps = pos.piece_types(); ps;)
1527
- {
1528
- PieceType pt = pop_lsb(ps);
1529
- score += hand<WHITE>(pt) - hand<BLACK>(pt);
1530
- }
1531
-
1532
- score += (mobility[WHITE] - mobility[BLACK]) * (1 + pos.captures_to_hand() + pos.must_capture() + pos.check_counting());
1533
-
1534
- // More complex interactions that require fully populated attack bitboards
1535
- score += king< WHITE>() - king< BLACK>()
1536
- + passed< WHITE>() - passed< BLACK>()
1537
- + variant<WHITE>() - variant<BLACK>();
1538
-
1539
- if (lazy_skip(LazyThreshold2) && Options["UCI_Variant"] == "chess")
1540
- goto make_v;
1541
-
1542
- score += threats<WHITE>() - threats<BLACK>()
1543
- + space< WHITE>() - space< BLACK>();
1544
-
1545
- make_v:
1546
- // Derive single value from mg and eg parts of score
1547
- Value v = winnable(score);
1548
-
1549
- // In case of tracing add all remaining individual evaluation terms
1550
- if constexpr (T)
1551
- {
1552
- Trace::add(IMBALANCE, me->imbalance());
1553
- Trace::add(PAWN, pe->pawn_score(WHITE), pe->pawn_score(BLACK));
1554
- Trace::add(MOBILITY, mobility[WHITE], mobility[BLACK]);
1555
- }
1556
-
1557
- // Evaluation grain
1558
- v = (v / 16) * 16;
1559
-
1560
- // Side to move point of view
1561
- v = (pos.side_to_move() == WHITE ? v : -v) + 80 * pos.captures_to_hand();
1562
-
1563
- return v;
1564
- }
1565
-
1566
-
1567
- /// Fisher Random Chess: correction for cornered bishops, to fix chess960 play with NNUE
1568
-
1569
- Value fix_FRC(const Position& pos) {
1570
-
1571
- constexpr Bitboard Corners = Bitboard(1ULL) << SQ_A1 | Bitboard(1ULL) << SQ_H1 | Bitboard(1ULL) << SQ_A8 | Bitboard(1ULL) << SQ_H8;
1572
-
1573
- if (!(pos.pieces(BISHOP) & Corners))
1574
- return VALUE_ZERO;
1575
-
1576
- int correction = 0;
1577
-
1578
- if ( pos.piece_on(SQ_A1) == W_BISHOP
1579
- && pos.piece_on(SQ_B2) == W_PAWN)
1580
- correction += !pos.empty(SQ_B3) ? -CorneredBishop * 4
1581
- : -CorneredBishop * 3;
1582
-
1583
- if ( pos.piece_on(SQ_H1) == W_BISHOP
1584
- && pos.piece_on(SQ_G2) == W_PAWN)
1585
- correction += !pos.empty(SQ_G3) ? -CorneredBishop * 4
1586
- : -CorneredBishop * 3;
1587
-
1588
- if ( pos.piece_on(SQ_A8) == B_BISHOP
1589
- && pos.piece_on(SQ_B7) == B_PAWN)
1590
- correction += !pos.empty(SQ_B6) ? CorneredBishop * 4
1591
- : CorneredBishop * 3;
1592
-
1593
- if ( pos.piece_on(SQ_H8) == B_BISHOP
1594
- && pos.piece_on(SQ_G7) == B_PAWN)
1595
- correction += !pos.empty(SQ_G6) ? CorneredBishop * 4
1596
- : CorneredBishop * 3;
1597
-
1598
- return pos.side_to_move() == WHITE ? Value(correction)
1599
- : -Value(correction);
1600
- }
1601
-
1602
- } // namespace Eval
1603
-
1604
-
1605
- /// evaluate() is the evaluator for the outer world. It returns a static
1606
- /// evaluation of the position from the point of view of the side to move.
1607
-
1608
- Value Eval::evaluate(const Position& pos) {
1609
-
1610
- Value v;
1611
-
1612
- if (!Eval::useNNUE || !pos.nnue_applicable())
1613
- v = Evaluation<NO_TRACE>(pos).value();
1614
- else
1615
- {
1616
- // Scale and shift NNUE for compatibility with search and classical evaluation
1617
- auto adjusted_NNUE = [&]()
1618
- {
1619
- int scale = 903
1620
- + 32 * pos.count<PAWN>()
1621
- + 32 * pos.non_pawn_material() / 1024;
1622
-
1623
- Value nnue = NNUE::evaluate(pos, true) * scale / 1024;
1624
-
1625
- if (pos.is_chess960())
1626
- nnue += fix_FRC(pos);
1627
-
1628
- if (pos.check_counting())
1629
- {
1630
- Color us = pos.side_to_move();
1631
- nnue += 6 * scale / (5 * pos.checks_remaining( us))
1632
- - 6 * scale / (5 * pos.checks_remaining(~us));
1633
- }
1634
-
1635
- return nnue;
1636
- };
1637
-
1638
- // If there is PSQ imbalance we use the classical eval, but we switch to
1639
- // NNUE eval faster when shuffling or if the material on the board is high.
1640
- int r50 = pos.rule50_count();
1641
- Value psq = Value(abs(eg_value(pos.psq_score())));
1642
- bool pure = !pos.check_counting();
1643
- bool classical = psq * 5 > (750 + pos.non_pawn_material() / 64) * (5 + r50) && !pure;
1644
-
1645
- v = classical ? Evaluation<NO_TRACE>(pos).value() // classical
1646
- : adjusted_NNUE(); // NNUE
1647
- }
1648
-
1649
- // Damp down the evaluation linearly when shuffling
1650
- if (pos.n_move_rule())
1651
- {
1652
- v = v * (2 * pos.n_move_rule() - pos.rule50_count()) / (2 * pos.n_move_rule());
1653
- if (pos.material_counting())
1654
- v += pos.material_counting_result() / (10 * std::max(2 * pos.n_move_rule() - pos.rule50_count(), 1));
1655
- }
1656
-
1657
- // Guarantee evaluation does not hit the virtual win/loss range
1658
- if (pos.two_boards() && std::abs(v) >= VALUE_VIRTUAL_MATE_IN_MAX_PLY)
1659
- v += v > VALUE_ZERO ? MAX_PLY + 1 : -MAX_PLY - 1;
1660
-
1661
- // Guarantee evaluation does not hit the tablebase range
1662
- v = std::clamp(v, VALUE_TB_LOSS_IN_MAX_PLY + 1, VALUE_TB_WIN_IN_MAX_PLY - 1);
1663
-
1664
- return v;
1665
- }
1666
-
1667
- /// trace() is like evaluate(), but instead of returning a value, it returns
1668
- /// a string (suitable for outputting to stdout) that contains the detailed
1669
- /// descriptions and values of each evaluation term. Useful for debugging.
1670
- /// Trace scores are from white's point of view
1671
-
1672
- std::string Eval::trace(Position& pos) {
1673
-
1674
- if (pos.checkers())
1675
- return "Final evaluation: none (in check)";
1676
-
1677
- std::stringstream ss;
1678
- ss << std::showpoint << std::noshowpos << std::fixed << std::setprecision(2);
1679
-
1680
- Value v;
1681
-
1682
- std::memset(scores, 0, sizeof(scores));
1683
-
1684
- pos.this_thread()->trend = SCORE_ZERO; // Reset any dynamic contempt
1685
-
1686
- v = Evaluation<TRACE>(pos).value();
1687
-
1688
- ss << std::showpoint << std::noshowpos << std::fixed << std::setprecision(2)
1689
- << " Contributing terms for the classical eval:\n"
1690
- << "+------------+-------------+-------------+-------------+\n"
1691
- << "| Term | White | Black | Total |\n"
1692
- << "| | MG EG | MG EG | MG EG |\n"
1693
- << "+------------+-------------+-------------+-------------+\n"
1694
- << "| Material | " << Term(MATERIAL)
1695
- << "| Imbalance | " << Term(IMBALANCE)
1696
- << "| Pawns | " << Term(PAWN)
1697
- << "| Knights | " << Term(KNIGHT)
1698
- << "| Bishops | " << Term(BISHOP)
1699
- << "| Rooks | " << Term(ROOK)
1700
- << "| Queens | " << Term(QUEEN)
1701
- << "| Mobility | " << Term(MOBILITY)
1702
- << "|King safety | " << Term(KING)
1703
- << "| Threats | " << Term(THREAT)
1704
- << "| Passed | " << Term(PASSED)
1705
- << "| Space | " << Term(SPACE)
1706
- << "| Variant | " << Term(VARIANT)
1707
- << "| Winnable | " << Term(WINNABLE)
1708
- << "+------------+-------------+-------------+-------------+\n"
1709
- << "| Total | " << Term(TOTAL)
1710
- << "+------------+-------------+-------------+-------------+\n";
1711
-
1712
- if (Eval::useNNUE && pos.nnue_applicable())
1713
- ss << '\n' << NNUE::trace(pos) << '\n';
1714
-
1715
- ss << std::showpoint << std::showpos << std::fixed << std::setprecision(2) << std::setw(15);
1716
-
1717
- v = pos.side_to_move() == WHITE ? v : -v;
1718
- ss << "\nClassical evaluation " << to_cp(v) << " (white side)\n";
1719
- if (Eval::useNNUE && pos.nnue_applicable())
1720
- {
1721
- v = NNUE::evaluate(pos, false);
1722
- v = pos.side_to_move() == WHITE ? v : -v;
1723
- ss << "NNUE evaluation " << to_cp(v) << " (white side)\n";
1724
- }
1725
-
1726
- v = evaluate(pos);
1727
- v = pos.side_to_move() == WHITE ? v : -v;
1728
- ss << "Final evaluation " << to_cp(v) << " (white side)";
1729
- if (Eval::useNNUE && pos.nnue_applicable())
1730
- ss << " [with scaled NNUE, hybrid, ...]";
1731
- ss << "\n";
1732
-
1733
- return ss.str();
1734
- }
1735
-
1736
- } // namespace Stockfish
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/src/evaluate.h DELETED
@@ -1,66 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
4
-
5
- Stockfish is free software: you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation, either version 3 of the License, or
8
- (at your option) any later version.
9
-
10
- Stockfish is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- You should have received a copy of the GNU General Public License
16
- along with this program. If not, see <http://www.gnu.org/licenses/>.
17
- */
18
-
19
- #ifndef EVALUATE_H_INCLUDED
20
- #define EVALUATE_H_INCLUDED
21
-
22
- #include <string>
23
- #include <optional>
24
-
25
- #include "types.h"
26
-
27
- #include "variant.h"
28
-
29
- namespace Stockfish {
30
-
31
- class Position;
32
-
33
- namespace Eval {
34
-
35
- std::string trace(Position& pos);
36
- Value evaluate(const Position& pos);
37
-
38
- extern bool useNNUE;
39
- extern std::string eval_file_loaded;
40
-
41
- // The default net name MUST follow the format nn-[SHA256 first 12 digits].nnue
42
- // for the build process (profile-build and fishtest) to work. Do not change the
43
- // name of the macro, as it is used in the Makefile.
44
- #define EvalFileDefaultName "nn-3475407dc199.nnue"
45
-
46
- namespace NNUE {
47
-
48
- std::string trace(Position& pos);
49
- Value evaluate(const Position& pos, bool adjusted = false);
50
-
51
- void init();
52
- void verify();
53
-
54
- bool load_eval(std::string name, std::istream& stream);
55
- bool save_eval(std::ostream& stream);
56
- bool save_eval(const std::optional<std::string>& filename);
57
-
58
- } // namespace NNUE
59
-
60
- } // namespace Eval
61
-
62
- extern const Variant* currentNnueVariant;
63
-
64
- } // namespace Stockfish
65
-
66
- #endif // #ifndef EVALUATE_H_INCLUDED
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/src/ffishjs.cpp DELETED
@@ -1,767 +0,0 @@
1
- /*
2
- ffish.js, a JavaScript chess variant library derived from Fairy-Stockfish
3
- Copyright (C) 2022 Fabian Fichter, Johannes Czech
4
-
5
- ffish.js is free software: you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation, either version 3 of the License, or
8
- (at your option) any later version.
9
-
10
- ffish.js is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- You should have received a copy of the GNU General Public License
16
- along with this program. If not, see <http://www.gnu.org/licenses/>.
17
- */
18
-
19
- #include <emscripten.h>
20
- #include <emscripten/bind.h>
21
- #include <vector>
22
- #include <string>
23
- #include <sstream>
24
- #include<iostream>
25
-
26
- #include "misc.h"
27
- #include "types.h"
28
- #include "bitboard.h"
29
- #include "evaluate.h"
30
- #include "position.h"
31
- #include "search.h"
32
- #include "syzygy/tbprobe.h"
33
- #include "thread.h"
34
- #include "tt.h"
35
- #include "uci.h"
36
- #include "piece.h"
37
- #include "variant.h"
38
- #include "movegen.h"
39
- #include "apiutil.h"
40
-
41
- using namespace emscripten;
42
-
43
- using namespace Stockfish;
44
-
45
- void initialize_stockfish() {
46
- pieceMap.init();
47
- variants.init();
48
- UCI::init(Options);
49
- Bitboards::init();
50
- Position::init();
51
- Bitbases::init();
52
- }
53
-
54
- #define DELIM " "
55
-
56
- inline void save_pop_back(std::string& s) {
57
- if (s.size() != 0) {
58
- s.pop_back();
59
- }
60
- }
61
-
62
- const Variant* get_variant(const std::string& uciVariant) {
63
- if (uciVariant.size() == 0 || uciVariant == "Standard" || uciVariant == "standard")
64
- return variants.find("chess")->second;
65
- return variants.find(uciVariant)->second;
66
- }
67
-
68
- template <bool isUCI>
69
- inline bool is_move_none(Move move, const std::string& strMove, const Position& pos) {
70
- if (move == MOVE_NONE) {
71
- std::cerr << "The given ";
72
- isUCI ? std::cerr << "uciMove" : std::cerr << "sanMove";
73
- std::cerr << " '" << strMove << "' for position '" << pos.fen() << "' is invalid." << std::endl;
74
- return true;
75
- }
76
- return false;
77
- }
78
-
79
- class Board {
80
- // note: we can't use references for strings here due to conversion to JavaScript
81
- private:
82
- const Variant* v;
83
- StateListPtr states;
84
- Position pos;
85
- Thread* thread;
86
- std::vector<Move> moveStack;
87
- bool is960;
88
-
89
- public:
90
- static bool sfInitialized;
91
-
92
- Board():
93
- Board("chess", "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1" , false) {
94
- }
95
-
96
- Board(std::string uciVariant):
97
- Board(uciVariant, "", false) {
98
- }
99
-
100
- Board(std::string uciVariant, std::string fen):
101
- Board(uciVariant, fen, false) {
102
- }
103
-
104
- Board(std::string uciVariant, std::string fen, bool is960) {
105
- init(uciVariant, fen, is960);
106
- }
107
-
108
- std::string legal_moves() {
109
- std::string moves;
110
- for (const ExtMove& move : MoveList<LEGAL>(this->pos)) {
111
- moves += UCI::move(this->pos, move);
112
- moves += DELIM;
113
- }
114
- save_pop_back(moves);
115
- return moves;
116
- }
117
-
118
- std::string legal_moves_san() {
119
- std::string movesSan;
120
- for (const ExtMove& move : MoveList<LEGAL>(this->pos)) {
121
- movesSan += SAN::move_to_san(this->pos, move, NOTATION_SAN);
122
- movesSan += DELIM;
123
- }
124
- save_pop_back(movesSan);
125
- return movesSan;
126
- }
127
-
128
- int number_legal_moves() const {
129
- return MoveList<LEGAL>(pos).size();
130
- }
131
-
132
- bool push(std::string uciMove) {
133
- const Move move = UCI::to_move(this->pos, uciMove);
134
- if (is_move_none<true>(move, uciMove, pos))
135
- return false;
136
- do_move(move);
137
- return true;
138
- }
139
-
140
- bool push_san(std::string sanMove) {
141
- return push_san(sanMove, NOTATION_SAN);
142
- }
143
-
144
- // TODO: This is a naive implementation which compares all legal SAN moves with the requested string.
145
- // If the SAN move wasn't found the position remains unchanged. Alternatively, implement a direct conversion.
146
- bool push_san(std::string sanMove, Notation notation) {
147
- Move foundMove = MOVE_NONE;
148
- for (const ExtMove& move : MoveList<LEGAL>(pos)) {
149
- if (sanMove == SAN::move_to_san(this->pos, move, notation)) {
150
- foundMove = move;
151
- break;
152
- }
153
- }
154
- if (is_move_none<false>(foundMove, sanMove, pos))
155
- return false;
156
- do_move(foundMove);
157
- return true;
158
- }
159
-
160
- void pop() {
161
- pos.undo_move(this->moveStack.back());
162
- moveStack.pop_back();
163
- states->pop_back();
164
- }
165
-
166
- void reset() {
167
- set_fen(v->startFen);
168
- }
169
-
170
- bool is_960() const {
171
- return is960;
172
- }
173
-
174
- std::string fen() const {
175
- return this->pos.fen();
176
- }
177
-
178
- std::string fen(bool showPromoted) const {
179
- return this->pos.fen(false, showPromoted);
180
- }
181
-
182
- std::string fen(bool showPromoted, int countStarted) const {
183
- return this->pos.fen(false, showPromoted, countStarted);
184
- }
185
-
186
- void set_fen(std::string fen) {
187
- resetStates();
188
- moveStack.clear();
189
- pos.set(v, fen, is960, &states->back(), thread);
190
- }
191
-
192
- // note: const identifier for pos not possible due to SAN::move_to_san()
193
- std::string san_move(std::string uciMove) {
194
- return san_move(uciMove, NOTATION_SAN);
195
- }
196
-
197
- std::string san_move(std::string uciMove, Notation notation) {
198
- const Move move = UCI::to_move(this->pos, uciMove);
199
- if (is_move_none<true>(move, uciMove, pos))
200
- return "";
201
- return SAN::move_to_san(this->pos, UCI::to_move(this->pos, uciMove), notation);
202
- }
203
-
204
- std::string variation_san(std::string uciMoves) {
205
- return variation_san(uciMoves, NOTATION_SAN, true);
206
- }
207
-
208
- std::string variation_san(std::string uciMoves, Notation notation) {
209
- return variation_san(uciMoves, notation, true);
210
- }
211
-
212
- std::string variation_san(std::string uciMoves, Notation notation, bool moveNumbers) {
213
- std::stringstream ss(uciMoves);
214
- StateListPtr tempStates;
215
- std::vector<Move> moves;
216
- std::string variationSan = "";
217
- std::string uciMove;
218
- bool first = true;
219
-
220
- while (std::getline(ss, uciMove, ' ')) {
221
- const Move move = UCI::to_move(this->pos, uciMove);
222
- if (is_move_none<true>(move, uciMove, pos))
223
- return "";
224
- moves.emplace_back(UCI::to_move(this->pos, uciMove));
225
- if (first) {
226
- first = false;
227
- if (moveNumbers) {
228
- variationSan = std::to_string(fullmove_number());
229
- if (pos.side_to_move() == WHITE)
230
- variationSan += ". ";
231
- else
232
- variationSan += "...";
233
- }
234
- variationSan += SAN::move_to_san(this->pos, moves.back(), Notation(notation));
235
- }
236
- else {
237
- if (moveNumbers && pos.side_to_move() == WHITE) {
238
- variationSan += DELIM;
239
- variationSan += std::to_string(fullmove_number());
240
- variationSan += ".";
241
- }
242
- variationSan += DELIM;
243
- variationSan += SAN::move_to_san(this->pos, moves.back(), Notation(notation));
244
- }
245
- states->emplace_back();
246
- pos.do_move(moves.back(), states->back());
247
- }
248
-
249
- // recover initial state
250
- for(auto rIt = std::rbegin(moves); rIt != std::rend(moves); ++rIt) {
251
- pos.undo_move(*rIt);
252
- }
253
-
254
- return variationSan;
255
- }
256
-
257
- // returns true for WHITE and false for BLACK
258
- bool turn() const {
259
- return !pos.side_to_move();
260
- }
261
-
262
- int fullmove_number() const {
263
- return pos.game_ply() / 2 + 1;
264
- }
265
-
266
- int halfmove_clock() const {
267
- return pos.rule50_count();
268
- }
269
-
270
- int game_ply() const {
271
- return pos.game_ply();
272
- }
273
-
274
- bool has_insufficient_material(bool turn) const {
275
- return Stockfish::has_insufficient_material(turn ? WHITE : BLACK, pos);
276
- }
277
-
278
- bool is_insufficient_material() const {
279
- return Stockfish::has_insufficient_material(WHITE, pos) && Stockfish::has_insufficient_material(BLACK, pos);
280
- }
281
-
282
- bool is_game_over() const {
283
- return is_game_over(false);
284
- }
285
-
286
- bool is_game_over(bool claim_draw) const {
287
- if (is_insufficient_material())
288
- return true;
289
- if (claim_draw && pos.is_optional_game_end())
290
- return true;
291
- return MoveList<LEGAL>(pos).size() == 0;
292
- }
293
-
294
- std::string result() const {
295
- return result(false);
296
- }
297
-
298
- std::string result(bool claim_draw) const {
299
- Value result;
300
- bool gameEnd = pos.is_immediate_game_end(result);
301
- if (!gameEnd) {
302
- if (is_insufficient_material()) {
303
- gameEnd = true;
304
- result = VALUE_DRAW;
305
- }
306
- }
307
- if (!gameEnd && MoveList<LEGAL>(pos).size() == 0) {
308
- gameEnd = true;
309
- result = pos.checkers() ? pos.checkmate_value() : pos.stalemate_value();
310
- }
311
- if (!gameEnd && claim_draw)
312
- gameEnd = pos.is_optional_game_end(result);
313
-
314
- if (!gameEnd)
315
- return "*";
316
- if (result == 0)
317
- return "1/2-1/2";
318
- if (pos.side_to_move() == BLACK)
319
- result = -result;
320
- if (result > 0)
321
- return "1-0";
322
- else
323
- return "0-1";
324
- }
325
-
326
- std::string checked_pieces() const {
327
- Bitboard checked = Stockfish::checked(pos);
328
- std::string squares;
329
- while (checked) {
330
- Square sr = pop_lsb(checked);
331
- squares += UCI::square(pos, sr);
332
- squares += DELIM;
333
- }
334
- save_pop_back(squares);
335
- return squares;
336
- }
337
-
338
- bool is_check() const {
339
- return Stockfish::checked(pos);
340
- }
341
-
342
- bool is_bikjang() const {
343
- return pos.bikjang();
344
- }
345
-
346
- bool is_capture(std::string uciMove) const {
347
- return pos.capture(UCI::to_move(pos, uciMove));
348
- }
349
-
350
- std::string move_stack() const {
351
- std::string moves;
352
- for(auto it = std::begin(moveStack); it != std::end(moveStack); ++it) {
353
- moves += UCI::move(pos, *it);
354
- moves += DELIM;
355
- }
356
- save_pop_back(moves);
357
- return moves;
358
- }
359
-
360
- void push_moves(std::string uciMoves) {
361
- std::stringstream ss(uciMoves);
362
- std::string uciMove;
363
- while (std::getline(ss, uciMove, ' ')) {
364
- push(uciMove);
365
- }
366
- }
367
-
368
- void push_san_moves(std::string sanMoves) {
369
- return push_san_moves(sanMoves, NOTATION_SAN);
370
- }
371
-
372
- void push_san_moves(std::string sanMoves, Notation notation) {
373
- std::stringstream ss(sanMoves);
374
- std::string sanMove;
375
- while (std::getline(ss, sanMove, ' '))
376
- push_san(sanMove, notation);
377
- }
378
-
379
- std::string pocket(bool color) {
380
- const Color c = Color(!color);
381
- std::string pocket;
382
- for (PieceType pt = KING; pt >= PAWN; --pt) {
383
- for (int i = 0; i < pos.count_in_hand(c, pt); ++i) {
384
- // only create BLACK pieces in order to convert to lower case
385
- pocket += std::string(1, pos.piece_to_char()[make_piece(BLACK, pt)]);
386
- }
387
- }
388
- return pocket;
389
- }
390
-
391
- std::string to_string() {
392
- std::string stringBoard;
393
- for (Rank r = pos.max_rank(); r >= RANK_1; --r) {
394
- for (File f = FILE_A; f <= pos.max_file(); ++f) {
395
- if (f != FILE_A)
396
- stringBoard += " ";
397
- const Piece p = pos.piece_on(make_square(f, r));
398
- switch(p) {
399
- case NO_PIECE:
400
- stringBoard += '.';
401
- break;
402
- default:
403
- stringBoard += pos.piece_to_char()[p];
404
- }
405
- }
406
- if (r != RANK_1)
407
- stringBoard += "\n";
408
- }
409
- return stringBoard;
410
- }
411
-
412
- std::string to_verbose_string() {
413
- std::stringstream ss;
414
- operator<<(ss, pos);
415
- return ss.str();
416
- }
417
-
418
- std::string variant() {
419
- // Iterate through the variants map
420
- for (auto it = variants.begin(); it != variants.end(); ++it)
421
- if (it->second == v)
422
- return it->first;
423
-
424
- std::cerr << "Current variant is not registered." << std::endl;
425
- return "unknown";
426
- }
427
-
428
- private:
429
- void resetStates() {
430
- this->states = StateListPtr(new std::deque<StateInfo>(1));
431
- }
432
-
433
- void do_move(Move move) {
434
- states->emplace_back();
435
- this->pos.do_move(move, states->back());
436
- this->moveStack.emplace_back(move);
437
- }
438
-
439
- void init(std::string uciVariant, std::string fen, bool is960) {
440
- if (!Board::sfInitialized) {
441
- initialize_stockfish();
442
- Board::sfInitialized = true;
443
- }
444
- v = get_variant(uciVariant);
445
- UCI::init_variant(v);
446
- this->resetStates();
447
- if (fen == "")
448
- fen = v->startFen;
449
- this->pos.set(this->v, fen, is960, &this->states->back(), this->thread);
450
- this->is960 = is960;
451
- }
452
- };
453
-
454
- bool Board::sfInitialized = false;
455
-
456
- namespace ffish {
457
- // returns the version of the Fairy-Stockfish binary
458
- std::string info() {
459
- return engine_info();
460
- }
461
-
462
- template <typename T>
463
- void set_option(std::string name, T value) {
464
- Options[name] = value;
465
- Board::sfInitialized = false;
466
- }
467
-
468
- std::string available_variants() {
469
- std::string availableVariants;
470
- for (std::string variant : variants.get_keys()) {
471
- availableVariants += variant;
472
- availableVariants += DELIM;
473
- }
474
- save_pop_back(availableVariants);
475
- return availableVariants;
476
- }
477
-
478
- void load_variant_config(std::string variantInitContent) {
479
- std::stringstream ss(variantInitContent);
480
- if (!Board::sfInitialized)
481
- initialize_stockfish();
482
- variants.parse_istream<false>(ss);
483
- Options["UCI_Variant"].set_combo(variants.get_keys());
484
- Board::sfInitialized = true;
485
- }
486
-
487
- bool captures_to_hand(std::string uciVariant) {
488
- const Variant* v = get_variant(uciVariant);
489
- return v->capturesToHand;
490
- }
491
-
492
- std::string starting_fen(std::string uciVariant) {
493
- const Variant* v = get_variant(uciVariant);
494
- return v->startFen;
495
- }
496
-
497
- int validate_fen(std::string fen, std::string uciVariant, bool chess960) {
498
- const Variant* v = get_variant(uciVariant);
499
- return FEN::validate_fen(fen, v, chess960);
500
- }
501
-
502
- int validate_fen(std::string fen, std::string uciVariant) {
503
- return validate_fen(fen, uciVariant, false);
504
- }
505
-
506
- int validate_fen(std::string fen) {
507
- return validate_fen(fen, "chess");
508
- }
509
- }
510
-
511
- class Game {
512
- private:
513
- std::unordered_map<std::string, std::string> header;
514
- std::unique_ptr<Board> board;
515
- std::string variant = "chess";
516
- std::string fen = ""; // start pos
517
- bool is960 = false;
518
- bool parsedGame = false;
519
- public:
520
- std::string header_keys() {
521
- std::string keys;
522
- for (auto it = header.begin(); it != header.end(); ++it) {
523
- keys += it->first;
524
- keys += DELIM;
525
- }
526
- save_pop_back(keys);
527
- return keys;
528
- }
529
-
530
- std::string headers(std::string item) {
531
- auto it = header.find(item);
532
- if (it == header.end())
533
- return "";
534
- return it->second;
535
- }
536
-
537
- std::string mainline_moves() {
538
- if (!parsedGame)
539
- return "";
540
- return board->move_stack();
541
- }
542
-
543
- friend Game read_game_pgn(std::string);
544
- };
545
-
546
-
547
- bool skip_comment(const std::string& pgn, size_t& curIdx, size_t& lineEnd) {
548
- curIdx = pgn.find('}', curIdx);
549
- if (curIdx == std::string::npos) {
550
- std::cerr << "Missing '}' for move comment while reading pgn." << std::endl;
551
- return false;
552
- }
553
- if (curIdx > lineEnd)
554
- lineEnd = pgn.find('\n', curIdx);
555
- return true;
556
- }
557
-
558
- Game read_game_pgn(std::string pgn) {
559
- Game game;
560
- size_t lineStart = 0;
561
- bool headersParsed = false;
562
-
563
- while(true) {
564
- size_t lineEnd = pgn.find('\n', lineStart);
565
-
566
- if (lineEnd == std::string::npos)
567
- lineEnd = pgn.size();
568
-
569
- if (!headersParsed && pgn[lineStart] == '[') {
570
- // parse header
571
- // look for item
572
- size_t headerKeyStart = lineStart+1;
573
- size_t headerKeyEnd = pgn.find(' ', lineStart);
574
- size_t headerItemStart = pgn.find('"', headerKeyEnd)+1;
575
- size_t headerItemEnd = pgn.find('"', headerItemStart);
576
-
577
- // put item into list
578
- game.header[pgn.substr(headerKeyStart, headerKeyEnd-headerKeyStart)] = pgn.substr(headerItemStart, headerItemEnd-headerItemStart);
579
- }
580
- else {
581
- if (!headersParsed) {
582
- headersParsed = true;
583
- auto it = game.header.find("Variant");
584
- if (it != game.header.end()) {
585
- game.is960 = it->second.find("960", it->second.size() - 3) != std::string::npos;
586
- if (game.is960) {
587
- game.variant = it->second.substr(0, it->second.size() - 3);
588
- } else {
589
- game.variant = it->second;
590
- }
591
- std::transform(game.variant.begin(), game.variant.end(), game.variant.begin(),
592
- [](unsigned char c){ return std::tolower(c); });
593
- }
594
-
595
- it = game.header.find("FEN");
596
- if (it != game.header.end())
597
- game.fen = it->second;
598
-
599
- game.board = std::make_unique<Board>(game.variant, game.fen, game.is960);
600
- game.parsedGame = true;
601
- }
602
-
603
- // game line
604
- size_t curIdx = lineStart;
605
- while (curIdx <= lineEnd) {
606
- if (pgn[curIdx] == '*')
607
- return game;
608
-
609
- if (pgn[curIdx] == '{') {
610
- if (!skip_comment(pgn, curIdx, lineEnd))
611
- return game;
612
- ++curIdx;
613
- }
614
-
615
- // Movetext RAV (Recursive Annotation Variation)
616
- size_t openedRAV = 0;
617
- if (pgn[curIdx] == '(') {
618
- openedRAV = 1;
619
- ++curIdx;
620
- }
621
- while (openedRAV != 0) {
622
- switch (pgn[curIdx]) {
623
- case '(':
624
- ++openedRAV;
625
- break;
626
- case ')':
627
- --openedRAV;
628
- break;
629
- case '{':
630
- if (!skip_comment(pgn, curIdx, lineEnd))
631
- return game;
632
- default: ; // pass
633
- }
634
- ++curIdx;
635
- if (curIdx > lineEnd)
636
- lineEnd = pgn.find('\n', curIdx);
637
- }
638
-
639
- if (pgn[curIdx] == '$') {
640
- // we are at a glyph
641
- curIdx = pgn.find(' ', curIdx);
642
- }
643
-
644
- if (pgn[curIdx] >= '0' && pgn[curIdx] <= '9') {
645
- // we are at a move number -> look for next point
646
- curIdx = pgn.find('.', curIdx);
647
- if (curIdx == std::string::npos)
648
- break;
649
- ++curIdx;
650
- // increment if we're at a space
651
- while (curIdx < pgn.size() && pgn[curIdx] == ' ')
652
- ++curIdx;
653
- // increment if we're at a point
654
- while (curIdx < pgn.size() && pgn[curIdx] == '.')
655
- ++curIdx;
656
- }
657
- // extract sanMove
658
- size_t sanMoveEnd = std::min(pgn.find(' ', curIdx), lineEnd);
659
- if (sanMoveEnd > curIdx) {
660
- std::string sanMove = pgn.substr(curIdx, sanMoveEnd-curIdx);
661
- // clean possible ? and ! from string
662
- size_t annotationChar1 = sanMove.find('?');
663
- size_t annotationChar2 = sanMove.find('!');
664
- if (annotationChar1 != std::string::npos || annotationChar2 != std::string::npos)
665
- sanMove = sanMove.substr(0, std::min(annotationChar1, annotationChar2));
666
- std::cout << sanMove << " ";
667
- game.board->push_san(sanMove);
668
- }
669
- curIdx = sanMoveEnd+1;
670
- }
671
- }
672
- lineStart = lineEnd+1;
673
-
674
- if (lineStart >= pgn.size())
675
- return game;
676
- }
677
- return game;
678
- }
679
-
680
-
681
- // binding code
682
- EMSCRIPTEN_BINDINGS(ffish_js) {
683
- class_<Board>("Board")
684
- .constructor<>()
685
- .constructor<std::string>()
686
- .constructor<std::string, std::string>()
687
- .constructor<std::string, std::string, bool>()
688
- .function("legalMoves", &Board::legal_moves)
689
- .function("legalMovesSan", &Board::legal_moves_san)
690
- .function("numberLegalMoves", &Board::number_legal_moves)
691
- .function("push", &Board::push)
692
- .function("pushSan", select_overload<bool(std::string)>(&Board::push_san))
693
- .function("pushSan", select_overload<bool(std::string, Notation)>(&Board::push_san))
694
- .function("pop", &Board::pop)
695
- .function("reset", &Board::reset)
696
- .function("is960", &Board::is_960)
697
- .function("fen", select_overload<std::string()const>(&Board::fen))
698
- .function("fen", select_overload<std::string(bool)const>(&Board::fen))
699
- .function("fen", select_overload<std::string(bool, int)const>(&Board::fen))
700
- .function("setFen", &Board::set_fen)
701
- .function("sanMove", select_overload<std::string(std::string)>(&Board::san_move))
702
- .function("sanMove", select_overload<std::string(std::string, Notation)>(&Board::san_move))
703
- .function("variationSan", select_overload<std::string(std::string)>(&Board::variation_san))
704
- .function("variationSan", select_overload<std::string(std::string, Notation)>(&Board::variation_san))
705
- .function("variationSan", select_overload<std::string(std::string, Notation, bool)>(&Board::variation_san))
706
- .function("turn", &Board::turn)
707
- .function("fullmoveNumber", &Board::fullmove_number)
708
- .function("halfmoveClock", &Board::halfmove_clock)
709
- .function("gamePly", &Board::game_ply)
710
- .function("hasInsufficientMaterial", &Board::has_insufficient_material)
711
- .function("isInsufficientMaterial", &Board::is_insufficient_material)
712
- .function("isGameOver", select_overload<bool() const>(&Board::is_game_over))
713
- .function("isGameOver", select_overload<bool(bool) const>(&Board::is_game_over))
714
- .function("result", select_overload<std::string() const>(&Board::result))
715
- .function("result", select_overload<std::string(bool) const>(&Board::result))
716
- .function("checkedPieces", &Board::checked_pieces)
717
- .function("isCheck", &Board::is_check)
718
- .function("isBikjang", &Board::is_bikjang)
719
- .function("isCapture", &Board::is_capture)
720
- .function("moveStack", &Board::move_stack)
721
- .function("pushMoves", &Board::push_moves)
722
- .function("pushSanMoves", select_overload<void(std::string)>(&Board::push_san_moves))
723
- .function("pushSanMoves", select_overload<void(std::string, Notation)>(&Board::push_san_moves))
724
- .function("pocket", &Board::pocket)
725
- .function("toString", &Board::to_string)
726
- .function("toVerboseString", &Board::to_verbose_string)
727
- .function("variant", &Board::variant);
728
- class_<Game>("Game")
729
- .function("headerKeys", &Game::header_keys)
730
- .function("headers", &Game::headers)
731
- .function("mainlineMoves", &Game::mainline_moves);
732
- // usage: e.g. ffish.Notation.DEFAULT
733
- enum_<Notation>("Notation")
734
- .value("DEFAULT", NOTATION_DEFAULT)
735
- .value("SAN", NOTATION_SAN)
736
- .value("LAN", NOTATION_LAN)
737
- .value("SHOGI_HOSKING", NOTATION_SHOGI_HOSKING)
738
- .value("SHOGI_HODGES", NOTATION_SHOGI_HODGES)
739
- .value("SHOGI_HODGES_NUMBER", NOTATION_SHOGI_HODGES_NUMBER)
740
- .value("JANGGI", NOTATION_JANGGI)
741
- .value("XIANGQI_WXF", NOTATION_XIANGQI_WXF)
742
- .value("THAI_SAN", NOTATION_THAI_SAN)
743
- .value("THAI_LAN", NOTATION_THAI_LAN);
744
- // usage: e.g. ffish.Termination.CHECKMATE
745
- enum_<Termination>("Termination")
746
- .value("ONGOING", ONGOING)
747
- .value("CHECKMATE", CHECKMATE)
748
- .value("STALEMATE", STALEMATE)
749
- .value("INSUFFICIENT_MATERIAL", INSUFFICIENT_MATERIAL)
750
- .value("N_MOVE_RULE", N_MOVE_RULE)
751
- .value("N_FOLD_REPETITION", N_FOLD_REPETITION)
752
- .value("VARIANT_END", VARIANT_END);
753
- function("info", &ffish::info);
754
- function("setOption", &ffish::set_option<std::string>);
755
- function("setOptionInt", &ffish::set_option<int>);
756
- function("setOptionBool", &ffish::set_option<bool>);
757
- function("readGamePGN", &read_game_pgn);
758
- function("variants", &ffish::available_variants);
759
- function("loadVariantConfig", &ffish::load_variant_config);
760
- function("capturesToHand", &ffish::captures_to_hand);
761
- function("startingFen", &ffish::starting_fen);
762
- function("validateFen", select_overload<int(std::string)>(&ffish::validate_fen));
763
- function("validateFen", select_overload<int(std::string, std::string)>(&ffish::validate_fen));
764
- function("validateFen", select_overload<int(std::string, std::string, bool)>(&ffish::validate_fen));
765
- // TODO: enable to string conversion method
766
- // .class_function("getStringFromInstance", &Board::get_string_from_instance);
767
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/src/incbin/UNLICENCE DELETED
@@ -1,26 +0,0 @@
1
- The file "incbin.h" is free and unencumbered software released into
2
- the public domain by Dale Weiler, see:
3
- <https://github.com/graphitemaster/incbin>
4
-
5
- Anyone is free to copy, modify, publish, use, compile, sell, or
6
- distribute this software, either in source code form or as a compiled
7
- binary, for any purpose, commercial or non-commercial, and by any
8
- means.
9
-
10
- In jurisdictions that recognize copyright laws, the author or authors
11
- of this software dedicate any and all copyright interest in the
12
- software to the public domain. We make this dedication for the benefit
13
- of the public at large and to the detriment of our heirs and
14
- successors. We intend this dedication to be an overt act of
15
- relinquishment in perpetuity of all present and future rights to this
16
- software under copyright law.
17
-
18
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21
- IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22
- OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23
- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24
- OTHER DEALINGS IN THE SOFTWARE.
25
-
26
- For more information, please refer to <http://unlicense.org/>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/src/incbin/incbin.h DELETED
@@ -1,368 +0,0 @@
1
- /**
2
- * @file incbin.h
3
- * @author Dale Weiler
4
- * @brief Utility for including binary files
5
- *
6
- * Facilities for including binary files into the current translation unit and
7
- * making use from them externally in other translation units.
8
- */
9
- #ifndef INCBIN_HDR
10
- #define INCBIN_HDR
11
- #include <limits.h>
12
- #if defined(__AVX512BW__) || \
13
- defined(__AVX512CD__) || \
14
- defined(__AVX512DQ__) || \
15
- defined(__AVX512ER__) || \
16
- defined(__AVX512PF__) || \
17
- defined(__AVX512VL__) || \
18
- defined(__AVX512F__)
19
- # define INCBIN_ALIGNMENT_INDEX 6
20
- #elif defined(__AVX__) || \
21
- defined(__AVX2__)
22
- # define INCBIN_ALIGNMENT_INDEX 5
23
- #elif defined(__SSE__) || \
24
- defined(__SSE2__) || \
25
- defined(__SSE3__) || \
26
- defined(__SSSE3__) || \
27
- defined(__SSE4_1__) || \
28
- defined(__SSE4_2__) || \
29
- defined(__neon__)
30
- # define INCBIN_ALIGNMENT_INDEX 4
31
- #elif ULONG_MAX != 0xffffffffu
32
- # define INCBIN_ALIGNMENT_INDEX 3
33
- # else
34
- # define INCBIN_ALIGNMENT_INDEX 2
35
- #endif
36
-
37
- /* Lookup table of (1 << n) where `n' is `INCBIN_ALIGNMENT_INDEX' */
38
- #define INCBIN_ALIGN_SHIFT_0 1
39
- #define INCBIN_ALIGN_SHIFT_1 2
40
- #define INCBIN_ALIGN_SHIFT_2 4
41
- #define INCBIN_ALIGN_SHIFT_3 8
42
- #define INCBIN_ALIGN_SHIFT_4 16
43
- #define INCBIN_ALIGN_SHIFT_5 32
44
- #define INCBIN_ALIGN_SHIFT_6 64
45
-
46
- /* Actual alignment value */
47
- #define INCBIN_ALIGNMENT \
48
- INCBIN_CONCATENATE( \
49
- INCBIN_CONCATENATE(INCBIN_ALIGN_SHIFT, _), \
50
- INCBIN_ALIGNMENT_INDEX)
51
-
52
- /* Stringize */
53
- #define INCBIN_STR(X) \
54
- #X
55
- #define INCBIN_STRINGIZE(X) \
56
- INCBIN_STR(X)
57
- /* Concatenate */
58
- #define INCBIN_CAT(X, Y) \
59
- X ## Y
60
- #define INCBIN_CONCATENATE(X, Y) \
61
- INCBIN_CAT(X, Y)
62
- /* Deferred macro expansion */
63
- #define INCBIN_EVAL(X) \
64
- X
65
- #define INCBIN_INVOKE(N, ...) \
66
- INCBIN_EVAL(N(__VA_ARGS__))
67
-
68
- /* Green Hills uses a different directive for including binary data */
69
- #if defined(__ghs__)
70
- # if (__ghs_asm == 2)
71
- # define INCBIN_MACRO ".file"
72
- /* Or consider the ".myrawdata" entry in the ld file */
73
- # else
74
- # define INCBIN_MACRO "\tINCBIN"
75
- # endif
76
- #else
77
- # define INCBIN_MACRO ".incbin"
78
- #endif
79
-
80
- #ifndef _MSC_VER
81
- # define INCBIN_ALIGN \
82
- __attribute__((aligned(INCBIN_ALIGNMENT)))
83
- #else
84
- # define INCBIN_ALIGN __declspec(align(INCBIN_ALIGNMENT))
85
- #endif
86
-
87
- #if defined(__arm__) || /* GNU C and RealView */ \
88
- defined(__arm) || /* Diab */ \
89
- defined(_ARM) /* ImageCraft */
90
- # define INCBIN_ARM
91
- #endif
92
-
93
- #ifdef __GNUC__
94
- /* Utilize .balign where supported */
95
- # define INCBIN_ALIGN_HOST ".balign " INCBIN_STRINGIZE(INCBIN_ALIGNMENT) "\n"
96
- # define INCBIN_ALIGN_BYTE ".balign 1\n"
97
- #elif defined(INCBIN_ARM)
98
- /*
99
- * On arm assemblers, the alignment value is calculated as (1 << n) where `n' is
100
- * the shift count. This is the value passed to `.align'
101
- */
102
- # define INCBIN_ALIGN_HOST ".align " INCBIN_STRINGIZE(INCBIN_ALIGNMENT_INDEX) "\n"
103
- # define INCBIN_ALIGN_BYTE ".align 0\n"
104
- #else
105
- /* We assume other inline assembler's treat `.align' as `.balign' */
106
- # define INCBIN_ALIGN_HOST ".align " INCBIN_STRINGIZE(INCBIN_ALIGNMENT) "\n"
107
- # define INCBIN_ALIGN_BYTE ".align 1\n"
108
- #endif
109
-
110
- /* INCBIN_CONST is used by incbin.c generated files */
111
- #if defined(__cplusplus)
112
- # define INCBIN_EXTERNAL extern "C"
113
- # define INCBIN_CONST extern const
114
- #else
115
- # define INCBIN_EXTERNAL extern
116
- # define INCBIN_CONST const
117
- #endif
118
-
119
- /**
120
- * @brief Optionally override the linker section into which data is emitted.
121
- *
122
- * @warning If you use this facility, you'll have to deal with platform-specific linker output
123
- * section naming on your own
124
- *
125
- * Overriding the default linker output section, e.g for esp8266/Arduino:
126
- * @code
127
- * #define INCBIN_OUTPUT_SECTION ".irom.text"
128
- * #include "incbin.h"
129
- * INCBIN(Foo, "foo.txt");
130
- * // Data is emitted into program memory that never gets copied to RAM
131
- * @endcode
132
- */
133
- #if !defined(INCBIN_OUTPUT_SECTION)
134
- # if defined(__APPLE__)
135
- # define INCBIN_OUTPUT_SECTION ".const_data"
136
- # else
137
- # define INCBIN_OUTPUT_SECTION ".rodata"
138
- # endif
139
- #endif
140
-
141
- #if defined(__APPLE__)
142
- /* The directives are different for Apple branded compilers */
143
- # define INCBIN_SECTION INCBIN_OUTPUT_SECTION "\n"
144
- # define INCBIN_GLOBAL(NAME) ".globl " INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME "\n"
145
- # define INCBIN_INT ".long "
146
- # define INCBIN_MANGLE "_"
147
- # define INCBIN_BYTE ".byte "
148
- # define INCBIN_TYPE(...)
149
- #else
150
- # define INCBIN_SECTION ".section " INCBIN_OUTPUT_SECTION "\n"
151
- # define INCBIN_GLOBAL(NAME) ".global " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME "\n"
152
- # if defined(__ghs__)
153
- # define INCBIN_INT ".word "
154
- # else
155
- # define INCBIN_INT ".int "
156
- # endif
157
- # if defined(__USER_LABEL_PREFIX__)
158
- # define INCBIN_MANGLE INCBIN_STRINGIZE(__USER_LABEL_PREFIX__)
159
- # else
160
- # define INCBIN_MANGLE ""
161
- # endif
162
- # if defined(INCBIN_ARM)
163
- /* On arm assemblers, `@' is used as a line comment token */
164
- # define INCBIN_TYPE(NAME) ".type " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME ", %object\n"
165
- # elif defined(__MINGW32__) || defined(__MINGW64__)
166
- /* Mingw doesn't support this directive either */
167
- # define INCBIN_TYPE(NAME)
168
- # else
169
- /* It's safe to use `@' on other architectures */
170
- # define INCBIN_TYPE(NAME) ".type " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME ", @object\n"
171
- # endif
172
- # define INCBIN_BYTE ".byte "
173
- #endif
174
-
175
- /* List of style types used for symbol names */
176
- #define INCBIN_STYLE_CAMEL 0
177
- #define INCBIN_STYLE_SNAKE 1
178
-
179
- /**
180
- * @brief Specify the prefix to use for symbol names.
181
- *
182
- * By default this is `g', producing symbols of the form:
183
- * @code
184
- * #include "incbin.h"
185
- * INCBIN(Foo, "foo.txt");
186
- *
187
- * // Now you have the following symbols:
188
- * // const unsigned char gFooData[];
189
- * // const unsigned char *const gFooEnd;
190
- * // const unsigned int gFooSize;
191
- * @endcode
192
- *
193
- * If however you specify a prefix before including: e.g:
194
- * @code
195
- * #define INCBIN_PREFIX incbin
196
- * #include "incbin.h"
197
- * INCBIN(Foo, "foo.txt");
198
- *
199
- * // Now you have the following symbols instead:
200
- * // const unsigned char incbinFooData[];
201
- * // const unsigned char *const incbinFooEnd;
202
- * // const unsigned int incbinFooSize;
203
- * @endcode
204
- */
205
- #if !defined(INCBIN_PREFIX)
206
- # define INCBIN_PREFIX g
207
- #endif
208
-
209
- /**
210
- * @brief Specify the style used for symbol names.
211
- *
212
- * Possible options are
213
- * - INCBIN_STYLE_CAMEL "CamelCase"
214
- * - INCBIN_STYLE_SNAKE "snake_case"
215
- *
216
- * Default option is *INCBIN_STYLE_CAMEL* producing symbols of the form:
217
- * @code
218
- * #include "incbin.h"
219
- * INCBIN(Foo, "foo.txt");
220
- *
221
- * // Now you have the following symbols:
222
- * // const unsigned char <prefix>FooData[];
223
- * // const unsigned char *const <prefix>FooEnd;
224
- * // const unsigned int <prefix>FooSize;
225
- * @endcode
226
- *
227
- * If however you specify a style before including: e.g:
228
- * @code
229
- * #define INCBIN_STYLE INCBIN_STYLE_SNAKE
230
- * #include "incbin.h"
231
- * INCBIN(foo, "foo.txt");
232
- *
233
- * // Now you have the following symbols:
234
- * // const unsigned char <prefix>foo_data[];
235
- * // const unsigned char *const <prefix>foo_end;
236
- * // const unsigned int <prefix>foo_size;
237
- * @endcode
238
- */
239
- #if !defined(INCBIN_STYLE)
240
- # define INCBIN_STYLE INCBIN_STYLE_CAMEL
241
- #endif
242
-
243
- /* Style lookup tables */
244
- #define INCBIN_STYLE_0_DATA Data
245
- #define INCBIN_STYLE_0_END End
246
- #define INCBIN_STYLE_0_SIZE Size
247
- #define INCBIN_STYLE_1_DATA _data
248
- #define INCBIN_STYLE_1_END _end
249
- #define INCBIN_STYLE_1_SIZE _size
250
-
251
- /* Style lookup: returning identifier */
252
- #define INCBIN_STYLE_IDENT(TYPE) \
253
- INCBIN_CONCATENATE( \
254
- INCBIN_STYLE_, \
255
- INCBIN_CONCATENATE( \
256
- INCBIN_EVAL(INCBIN_STYLE), \
257
- INCBIN_CONCATENATE(_, TYPE)))
258
-
259
- /* Style lookup: returning string literal */
260
- #define INCBIN_STYLE_STRING(TYPE) \
261
- INCBIN_STRINGIZE( \
262
- INCBIN_STYLE_IDENT(TYPE)) \
263
-
264
- /* Generate the global labels by indirectly invoking the macro with our style
265
- * type and concatenating the name against them. */
266
- #define INCBIN_GLOBAL_LABELS(NAME, TYPE) \
267
- INCBIN_INVOKE( \
268
- INCBIN_GLOBAL, \
269
- INCBIN_CONCATENATE( \
270
- NAME, \
271
- INCBIN_INVOKE( \
272
- INCBIN_STYLE_IDENT, \
273
- TYPE))) \
274
- INCBIN_INVOKE( \
275
- INCBIN_TYPE, \
276
- INCBIN_CONCATENATE( \
277
- NAME, \
278
- INCBIN_INVOKE( \
279
- INCBIN_STYLE_IDENT, \
280
- TYPE)))
281
-
282
- /**
283
- * @brief Externally reference binary data included in another translation unit.
284
- *
285
- * Produces three external symbols that reference the binary data included in
286
- * another translation unit.
287
- *
288
- * The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
289
- * "Data", as well as "End" and "Size" after. An example is provided below.
290
- *
291
- * @param NAME The name given for the binary data
292
- *
293
- * @code
294
- * INCBIN_EXTERN(Foo);
295
- *
296
- * // Now you have the following symbols:
297
- * // extern const unsigned char <prefix>FooData[];
298
- * // extern const unsigned char *const <prefix>FooEnd;
299
- * // extern const unsigned int <prefix>FooSize;
300
- * @endcode
301
- */
302
- #define INCBIN_EXTERN(NAME) \
303
- INCBIN_EXTERNAL const INCBIN_ALIGN unsigned char \
304
- INCBIN_CONCATENATE( \
305
- INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
306
- INCBIN_STYLE_IDENT(DATA))[]; \
307
- INCBIN_EXTERNAL const INCBIN_ALIGN unsigned char *const \
308
- INCBIN_CONCATENATE( \
309
- INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
310
- INCBIN_STYLE_IDENT(END)); \
311
- INCBIN_EXTERNAL const unsigned int \
312
- INCBIN_CONCATENATE( \
313
- INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
314
- INCBIN_STYLE_IDENT(SIZE))
315
-
316
- /**
317
- * @brief Include a binary file into the current translation unit.
318
- *
319
- * Includes a binary file into the current translation unit, producing three symbols
320
- * for objects that encode the data and size respectively.
321
- *
322
- * The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
323
- * "Data", as well as "End" and "Size" after. An example is provided below.
324
- *
325
- * @param NAME The name to associate with this binary data (as an identifier.)
326
- * @param FILENAME The file to include (as a string literal.)
327
- *
328
- * @code
329
- * INCBIN(Icon, "icon.png");
330
- *
331
- * // Now you have the following symbols:
332
- * // const unsigned char <prefix>IconData[];
333
- * // const unsigned char *const <prefix>IconEnd;
334
- * // const unsigned int <prefix>IconSize;
335
- * @endcode
336
- *
337
- * @warning This must be used in global scope
338
- * @warning The identifiers may be different if INCBIN_STYLE is not default
339
- *
340
- * To externally reference the data included by this in another translation unit
341
- * please @see INCBIN_EXTERN.
342
- */
343
- #ifdef _MSC_VER
344
- #define INCBIN(NAME, FILENAME) \
345
- INCBIN_EXTERN(NAME)
346
- #else
347
- #define INCBIN(NAME, FILENAME) \
348
- __asm__(INCBIN_SECTION \
349
- INCBIN_GLOBAL_LABELS(NAME, DATA) \
350
- INCBIN_ALIGN_HOST \
351
- INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(DATA) ":\n" \
352
- INCBIN_MACRO " \"" FILENAME "\"\n" \
353
- INCBIN_GLOBAL_LABELS(NAME, END) \
354
- INCBIN_ALIGN_BYTE \
355
- INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(END) ":\n" \
356
- INCBIN_BYTE "1\n" \
357
- INCBIN_GLOBAL_LABELS(NAME, SIZE) \
358
- INCBIN_ALIGN_HOST \
359
- INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(SIZE) ":\n" \
360
- INCBIN_INT INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(END) " - " \
361
- INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(DATA) "\n" \
362
- INCBIN_ALIGN_HOST \
363
- ".text\n" \
364
- ); \
365
- INCBIN_EXTERN(NAME)
366
-
367
- #endif
368
- #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/src/magic.h DELETED
@@ -1,1741 +0,0 @@
1
- /*
2
- Fairy-Stockfish, a UCI chess variant playing engine derived from Stockfish
3
- Copyright (C) 2018-2022 Fabian Fichter
4
-
5
- Fairy-Stockfish is free software: you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation, either version 3 of the License, or
8
- (at your option) any later version.
9
-
10
- Fairy-Stockfish is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- You should have received a copy of the GNU General Public License
16
- along with this program. If not, see <http://www.gnu.org/licenses/>.
17
- */
18
-
19
- #ifndef MAGIC_H_INCLUDED
20
- #define MAGIC_H_INCLUDED
21
-
22
- namespace Stockfish {
23
-
24
- #ifdef PRECOMPUTED_MAGICS
25
- #define B(a, b) (Bitboard(a) << 64) ^ Bitboard(b)
26
- // Use precomputed magics if pext is not available,
27
- // since the magics generation is very slow.
28
- constexpr Bitboard RookMagicHInit[SQUARE_NB] = {
29
- B(0x120000880110000, 0x1008000000020020),
30
- B(0x24200C080840A052, 0x2004004000010008),
31
- B(0xC030024000228800, 0x4000010400000020),
32
- B(0x1A0020802008802, 0x206010208000),
33
- B(0x12002000D001024, 0x80100800090138),
34
- B(0x4220010000241010, 0x3098000602001500),
35
- B(0x401010004801040, 0x8000280480100000),
36
- B(0x820082024921836, 0x220028000),
37
- B(0x100400502411400, 0x220402120240D14),
38
- B(0x880202020010404, 0xA80202510000),
39
- B(0x140002801000018, 0x1000346490040),
40
- B(0x120000880110000, 0x1008000000020020),
41
- B(0xD01004008030400, 0x104000408104420),
42
- B(0x8420060100020000, 0x800280400000120),
43
- B(0x4010020018010, 0x40A00001100000),
44
- B(0x40006A0004000200, 0x40000000110),
45
- B(0xD01004008030400, 0x104000408104420),
46
- B(0x8908A20028110011, 0x800080000001A114),
47
- B(0x200042000080F009, 0x20001000004000),
48
- B(0x2820008820100, 0x10002400058000B9),
49
- B(0x6083100420008050, 0x4040012600280080),
50
- B(0x216020000000446, 0x4080204000000211),
51
- B(0x340140003002089, 0x2402008000000911),
52
- B(0xD01004008030400, 0x104000408104420),
53
- B(0x1404040B20001000, 0x8000824010800011),
54
- B(0x8C0488120024214, 0x8414880202291),
55
- B(0x1010000060050000, 0x4000004050002602),
56
- B(0x4022983A0060000, 0x80000040010400),
57
- B(0x1404040B20001000, 0x8000824010800011),
58
- B(0x6020101802002840, 0x31000003000004),
59
- B(0x9000420008840, 0x4881300000000210),
60
- B(0xA200808865, 0x41C0048023000128),
61
- B(0x31801100400000, 0x8802DC001221240),
62
- B(0x884000080200920, 0x1004002410401001),
63
- B(0x2400040000884, 0x421006208040C0),
64
- B(0x1404040B20001000, 0x8000824010800011),
65
- B(0x24100400060009, 0x112008025042410),
66
- B(0x1800040009040200, 0x180000A1004E408A),
67
- B(0x24100400060009, 0x112008025042410),
68
- B(0x4060402008080, 0xC240080000110000),
69
- B(0x20080100920020, 0x2002248010242052),
70
- B(0x10001010802050, 0x880000001C98420),
71
- B(0x4000800100420022, 0x502022010A00D0),
72
- B(0x4C18104500200885, 0x400880800),
73
- B(0x8080810081020090, 0x8000000000000),
74
- B(0x8000062812080201, 0x8004C8300800),
75
- B(0xC010220920198, 0x85000A08000),
76
- B(0x24100400060009, 0x112008025042410),
77
- B(0x80102204040, 0x1000000900000000),
78
- B(0x2080000004202804, 0x120880003461),
79
- B(0x102004090A4030, 0x801020589240),
80
- B(0x20001100814000A0, 0x420202000820004),
81
- B(0x100800000A000120, 0x208000800010000),
82
- B(0x1008205000040802, 0x80002000400040),
83
- B(0x1480000098008401, 0xA0010000581010),
84
- B(0x30C0008200100820, 0x102800080904834),
85
- B(0x4810821884000500, 0x4400000200000212),
86
- B(0x1811D00128A0180, 0x2500848803000000),
87
- B(0x41618A0300040040, 0x21200200A421801),
88
- B(0x80102204040, 0x1000000900000000),
89
- B(0xA1808E0100108000, 0x2008000505000002),
90
- B(0x8C890020410000A0, 0xA010000048000400),
91
- B(0x40006002210044, 0x600008000408000),
92
- B(0x1200447220090042, 0x80001000160012),
93
- B(0x48410010AB000000, 0x9200600000000100),
94
- B(0x2040000000240003, 0x8020080288000600),
95
- B(0x9080000088848088, 0x4010210500000041),
96
- B(0xA1808E0100108000, 0x2008000505000002),
97
- B(0x480100400024, 0x1004800018200000),
98
- B(0x808403080080200, 0x802601000000500),
99
- B(0x8C890020410000A0, 0xA010000048000400),
100
- B(0xA1808E0100108000, 0x2008000505000002),
101
- B(0x100A40000004008, 0x2800200400200480),
102
- B(0x100A40000004008, 0x2800200400200480),
103
- B(0x400014006000000, 0x10006000810001F5),
104
- B(0xC410062001414, 0x820080041B01044),
105
- B(0x20000800310, 0x430040000201000),
106
- B(0xA40010008000008, 0x4002200028000040),
107
- B(0xC00102000008021C, 0x10C2000A010E024),
108
- B(0x80004200104008, 0x50A00800C400020),
109
- B(0x20200080012542, 0x910F0040000402C0),
110
- B(0xB040100504000300, 0x24802002000040),
111
- B(0x800001000014008, 0x400031004000),
112
- B(0x100A40000004008, 0x2800200400200480),
113
- B(0x84008002041081C0, 0x8080500200000000),
114
- B(0x440090001012001, 0x4020004010),
115
- B(0x100A0028088020, 0x80040E00010020),
116
- B(0x2180808000810, 0xB018040A00040000),
117
- B(0x40C80920304C4001, 0x42800B200800000),
118
- B(0x85000425001000, 0x4810048020001100),
119
- B(0x600C000801000004, 0x8015084010200020),
120
- B(0x20020050000240C0, 0x100202008600800),
121
- B(0x38000050001220, 0x9200010200145900),
122
- B(0x1042108040005, 0x1402A0802201001),
123
- B(0x824240000C20400, 0x1000000400080010),
124
- B(0x84008002041081C0, 0x8080500200000000),
125
- B(0x400804A1000008, 0x1024104A0200010),
126
- B(0x8000402308483, 0x20006020100100),
127
- B(0x80880120000080, 0x8000240100084),
128
- B(0x5840020004882001, 0x1004528000A00010),
129
- B(0x8001018800300002, 0x84010040804),
130
- B(0x180D10004000A008, 0xA001080008020004),
131
- B(0x400080B, 0x10A0000004010000),
132
- B(0x8080000200000, 0x2001000082004E0),
133
- B(0x40040001000C2000, 0x2024800001004008),
134
- B(0x400804A1000008, 0x1024104A0200010),
135
- B(0x8000402308483, 0x20006020100100),
136
- B(0x400804A1000008, 0x1024104A0200010),
137
- B(0x2000200000, 0x1201011000802),
138
- B(0x100100000000C4, 0x208004084048201),
139
- B(0x400084000044, 0x100810140300),
140
- B(0x29040C0C01010, 0x300204010820080),
141
- B(0x1A808000020200, 0x1000000005210040),
142
- B(0x20000400150000, 0x85008020),
143
- B(0x40C040008184014, 0x8002AA00024010),
144
- B(0x202000081B00804, 0x10001002008),
145
- B(0x40011000210060, 0x6080C40000021004),
146
- B(0x2000200000, 0x1201011000802),
147
- B(0x4100480203840, 0x300080100804),
148
- B(0x2000200000, 0x1201011000802),
149
- };
150
- constexpr Bitboard RookMagicVInit[SQUARE_NB] = {
151
- B(0x202000812104400, 0x24800B01C0000303),
152
- B(0x340020400010D, 0x88060150C00400),
153
- B(0x400802040609, 0x49010200501A0002),
154
- B(0x8002680301000208, 0x628006C0C020200),
155
- B(0x20400209001C0804, 0xA044000800143110),
156
- B(0xC400082060010202, 0x4000480401014000),
157
- B(0x22500200144040, 0x8204820084704C00),
158
- B(0x8C1204009030020, 0x328400805000000),
159
- B(0x84800800D0001640, 0x200080040060108),
160
- B(0x804810208020040, 0x140010108020000),
161
- B(0x1102010B008004, 0x300208006220020),
162
- B(0x140080404A0A2428, 0x6308010100080),
163
- B(0x20444002120408, 0xA080010508010001),
164
- B(0x82011044000D02, 0x4112028620110809),
165
- B(0x81010831000C02, 0x408802085000000),
166
- B(0x81010831000C02, 0x408802085000000),
167
- B(0x920008920600040, 0x8053801004000028),
168
- B(0x81140283208300, 0x10040C004200420),
169
- B(0x103080022201, 0xC01000081312620),
170
- B(0x2200221100008, 0x1000408104000A4),
171
- B(0x4402088080042008, 0x210401501040340),
172
- B(0x898400202170001, 0x80040404208000),
173
- B(0x20080004051012, 0x5100048200081800),
174
- B(0x2320020000401018, 0x108501021040210),
175
- B(0x21080410A422021, 0x83040180008800),
176
- B(0x44E8100000408224, 0x20010008040400),
177
- B(0x1800240002810405, 0x23004820000020),
178
- B(0x80A0100400110, 0x80104020100C4028),
179
- B(0x1002050001222C0, 0x5100818004024020),
180
- B(0x104000200040, 0xC010A09800102000),
181
- B(0x1020003A058120, 0x450900809000302),
182
- B(0x40040045008B1, 0x202800400383010),
183
- B(0x4640200220034, 0x8800485420304000),
184
- B(0x5001042100084288, 0x110820001240080A),
185
- B(0x2002C04004010120, 0xA15008020880001),
186
- B(0x2800004080C4190, 0x890808280020080),
187
- B(0x40C0401000104000, 0x2020880008002580),
188
- B(0x40020C002400802, 0x801104010000000),
189
- B(0x44842000040080, 0x2050011084000400),
190
- B(0x4110040800000401, 0x2023810029008000),
191
- B(0x20884000840, 0x8017102004008000),
192
- B(0x10411104000480, 0x1414042000201001),
193
- B(0x220040000008, 0x800306021000000),
194
- B(0x41400A0008080, 0x501000298ACAD10),
195
- B(0x800240012831810, 0x80120004468050E),
196
- B(0x800005020801008, 0x20102400240000),
197
- B(0x20C00040C114C010, 0x88080820200C00),
198
- B(0x1044010100820081, 0x20080841004000),
199
- B(0x8041048400022, 0x8020836040005002),
200
- B(0x2001004010205, 0x8001002884042009),
201
- B(0x128088400087, 0x20008002201002),
202
- B(0x8084108040402000, 0x80809000A080400),
203
- B(0x408081840880, 0x201002088000040),
204
- B(0xA40180010280, 0x241004006000010),
205
- B(0x4204100080048140, 0x2002C4F104202020),
206
- B(0x100140A10204, 0x980200800840060),
207
- B(0x1005140010202048, 0x1442280800202815),
208
- B(0x2000082025008600, 0x1108400040600003),
209
- B(0x1005050648000, 0x200020240008002),
210
- B(0x202010208044000, 0x8210404060008),
211
- B(0x8011040402000210, 0xC840180408016004),
212
- B(0x404098801028, 0x80020A0001000400),
213
- B(0x404098801028, 0x80020A0001000400),
214
- B(0x80101002180140, 0x40C2080820000C0),
215
- B(0x208202081260800, 0x14090E4C04000050),
216
- B(0x4221201084004C2, 0x110480A011060),
217
- B(0x8000008421090204, 0x1C01010800024),
218
- B(0x8000008421090204, 0x1C01010800024),
219
- B(0x200180C840088A0, 0x401100400820000),
220
- B(0x10084043A021070, 0x202041600080200),
221
- B(0x210E6202001040C, 0x10100800080B0),
222
- B(0x848008021204002, 0x801004308100BAD),
223
- B(0xC082C0390A000601, 0x4040080189008),
224
- B(0x431200240210402D, 0x58102820000),
225
- B(0x202020100A0019B0, 0x4010C0D018000000),
226
- B(0x800800908402203, 0x102948C84C184),
227
- B(0x26801100080845, 0x4009702022A00820),
228
- B(0x8880520010401040, 0x1060084832052000),
229
- B(0x100100022042081, 0x10000600008C121),
230
- B(0x46020384100040, 0x800200320882021),
231
- B(0xC0002010148, 0x4200800800040003),
232
- B(0x2002208020090040, 0x40820210021410),
233
- B(0x9000A41160002004, 0x2A09000100080043),
234
- B(0x800004010008001, 0x1108002020104600),
235
- B(0x800540C000A4E041, 0x18021180000401),
236
- B(0x808200900A900202, 0x8364202140012005),
237
- B(0x1DBA52000081010, 0x4008000023000010),
238
- B(0x4100110204401481, 0x800040091020001C),
239
- B(0x4100110204401481, 0x800040091020001C),
240
- B(0x4101100020400482, 0x2000402302100120),
241
- B(0x100408000A020212, 0xA000400111000020),
242
- B(0x2000010488080104, 0x3000404410208100),
243
- B(0x2684220180008DD0, 0x422040200004000A),
244
- B(0x2021200C0424, 0x1010100000080200),
245
- B(0x8908020020801006, 0x3010800020C2000),
246
- B(0x4000030008062044, 0x244010202688000),
247
- B(0x242101200408009, 0x8150040000200015),
248
- B(0x42004C02180204, 0x210208014241040),
249
- B(0x4E1A01C208410804, 0x8890041000012004),
250
- B(0x2080200401000080, 0x8001098429008004),
251
- B(0xA01400121804104, 0x280200C400000500),
252
- B(0xD0080408040420, 0x1006040100224000),
253
- B(0x28400205000800C9, 0x6021101401040075),
254
- B(0x4000900040020104, 0x88129801100D0C),
255
- B(0x8000004002180410, 0x400380200400204),
256
- B(0x4002A430043008, 0x400200340100020),
257
- B(0x401960004140A42, 0x100880710000464),
258
- B(0x58014090102, 0xB8D30004010080),
259
- B(0xA004C08000244000, 0x11280100E0000040),
260
- B(0x2102008089208804, 0x110001004080040),
261
- B(0x700010084E003004, 0x8080864112000D40),
262
- B(0x4080881000200C20, 0x30324040880E0600),
263
- B(0x2024A40401810820, 0x3000888002000000),
264
- B(0x8200100400014, 0x4400340800252844),
265
- B(0x24A00804288281, 0x410103002201140),
266
- B(0x4080005022A08, 0x1000402200100264),
267
- B(0x200080032244040, 0x200502189010001),
268
- B(0x28108110404001, 0x400600120008412),
269
- B(0xA00002102810020, 0xB1080240015408),
270
- B(0x810080200806, 0x410440804080046)
271
- };
272
- constexpr Bitboard BishopMagicInit[SQUARE_NB] = {
273
- B(0x2001040305000010, 0x830200040400082),
274
- B(0x1042400080E01200, 0x2004904010811400),
275
- B(0x400010120200, 0x880080D080018000),
276
- B(0x240190C00100040, 0x100A020140044404),
277
- B(0x1018010404010004, 0x1001010018081E0),
278
- B(0x41200A804C0904, 0x40000322000008),
279
- B(0x4001180A004, 0x8000001106000000),
280
- B(0x6006020020030600, 0x1840002100004841),
281
- B(0x4200200100, 0x4001041808002000),
282
- B(0x4100020050124600, 0x1001802902400CA0),
283
- B(0x448C0081440161, 0x200206010008000),
284
- B(0x400008008008408, 0x1000080210100080),
285
- B(0x200280C01008200, 0x210200813000080),
286
- B(0x1A000204400, 0x222200401023000),
287
- B(0x10081040640A00, 0x8410021881400000),
288
- B(0x1840400318080008, 0x800800840080000),
289
- B(0x4204050C040, 0x6500600200140000),
290
- B(0x1012100040204, 0x402404444400000),
291
- B(0x6000012680008240, 0x410140000004220),
292
- B(0x1000020810040008, 0x2D0011000060000),
293
- B(0x1020020400, 0x400108059001001),
294
- B(0x400020001100808, 0x480204800200000B),
295
- B(0x10000010030084, 0x2042000848900022),
296
- B(0x10000010030084, 0x2042000848900022),
297
- B(0x100D801402400, 0x1512404009000400),
298
- B(0x8000208005112400, 0xA02040401000000),
299
- B(0x1000420002800200, 0x4CA000183020000),
300
- B(0x800811480020, 0x408801010224001),
301
- B(0xC805200810900100, 0x9000084204004020),
302
- B(0x8200160204100004, 0x8040004004002022),
303
- B(0x104514013080080, 0x146410040001000),
304
- B(0x140844000080002, 0x1008102020040001),
305
- B(0x4040400041A2002, 0x8040000A8802510),
306
- B(0x801014041008002, 0x80068008025200),
307
- B(0xA00540A414040, 0x4101040010A0000),
308
- B(0x6484008010810002, 0x1100506884024000),
309
- B(0x2800401008006000, 0x1005420884029020),
310
- B(0x6822091010004421, 0x2000458080480),
311
- B(0x40101000200101, 0x10020100001C4E0),
312
- B(0x100400008C42, 0x4000100009008000),
313
- B(0x851220018800400, 0x1681800040080080),
314
- B(0x64200002010, 0x900020200040002),
315
- B(0x20800080000022, 0x80040810002010),
316
- B(0xA88408000802080, 0x20808001000000),
317
- B(0x200000400C005040, 0x100140020290108),
318
- B(0x224100000800408, 0x4204802004400020),
319
- B(0x80080620010210, 0x91080088804040),
320
- B(0x4008002100010, 0x80AC201001000001),
321
- B(0x10008200902C046, 0x8080D03004000010),
322
- B(0x3002100081000180, 0x2210002121528408),
323
- B(0x8C101800804420, 0x1019880200043008),
324
- B(0x200022000920D0, 0x8000800081300020),
325
- B(0x1D40800880000, 0x400040001400050),
326
- B(0x2020004100040, 0x200008040008008),
327
- B(0x4840800040100001, 0x100100040203040),
328
- B(0x40084001105, 0x8800080088000089),
329
- B(0x4000128008020008, 0x4004200200440020),
330
- B(0x210040008520000, 0x820219001080022),
331
- B(0x1494040018002116, 0x400101047020008),
332
- B(0x510008001910C224, 0x80200148118000),
333
- B(0xC0301002301000, 0x4211A08004801),
334
- B(0x50008E0C01001080, 0x100C004102845100),
335
- B(0x400600020060400, 0x88024100250050),
336
- B(0x8202920002002040, 0x810012000003),
337
- B(0x800004208800200, 0x18AA00201000048),
338
- B(0x402100800100002, 0x411000081000400),
339
- B(0x101000022004044, 0x9000100040000),
340
- B(0x41068001001, 0xC00400010001),
341
- B(0x310210001040, 0x1A1200020010000),
342
- B(0xA082409200004048, 0x490040800124101),
343
- B(0x18844820E0040212, 0x1000404420D10000),
344
- B(0x802908A40003348, 0x20200040104140),
345
- B(0x1800404028205003, 0xC020010401089020),
346
- B(0x802100044D01000, 0x8C41888000800040),
347
- B(0x1D0161011410081, 0x10008000100200),
348
- B(0x401000480040100, 0x286800404002212),
349
- B(0x821030000100009, 0x2000090200A00000),
350
- B(0x200020800200800, 0x2000480900841012),
351
- B(0x80A000048030080, 0x200000120200008),
352
- B(0x40B1400008020020, 0x148000200008004),
353
- B(0xA021700002002010, 0x3040E400040100),
354
- B(0x400242C200200640, 0x20440210200281),
355
- B(0x80AC140040206240, 0x120000102801401),
356
- B(0x2020340040832040, 0x10402100A44000),
357
- B(0x420100400040220, 0x80014C8004000106),
358
- B(0x504300822421120, 0x8004004008400100),
359
- B(0x2001100008040, 0x2020104302000000),
360
- B(0xA500802000A, 0x2008008000114100),
361
- B(0x8A0020000200, 0x9C00101001002408),
362
- B(0x104000001001008, 0x9001000204040060),
363
- B(0x1000820080108200, 0xA401000008100001),
364
- B(0x2008600009000480, 0x9008020001400000),
365
- B(0x4000800200040200, 0xA00030400308082),
366
- B(0x4004300202004709, 0x1000100180010020),
367
- B(0xC014800100440010, 0x402020280002C010),
368
- B(0x220208010884680, 0x1040280000042110),
369
- B(0x40B0018019202801, 0x1008408000100040),
370
- B(0x8269010206080044, 0x8001810000000040),
371
- B(0x4000020880081040, 0x208A44000028000),
372
- B(0x4004004E9004220A, 0x2104004001400024),
373
- B(0x8035006008C0904, 0x402002001080120),
374
- B(0x1800884002, 0x404400820000000),
375
- B(0x8088000004008910, 0x8024100401000000),
376
- B(0x142200086000100, 0x28021040020002E),
377
- B(0x1000409141004018, 0x100410820080040A),
378
- B(0x1800801800140, 0x810801060C0801),
379
- B(0x1000C00100402220, 0x808023420000000),
380
- B(0x8A0A202414305008, 0x100040200000021),
381
- B(0xC0208024050, 0x8003088008020401),
382
- B(0x8044004201440101, 0x400820080C024022),
383
- B(0x406018884120099, 0xB00088018002000),
384
- B(0x2000800010403010, 0xC5A002002010010),
385
- B(0x800020040840, 0x201800202800200),
386
- B(0x201280120020008D, 0x258809001000040),
387
- B(0x9100002020181, 0x80400082204000),
388
- B(0x104010080201001, 0x40080080181080),
389
- B(0x8440248092000430, 0xA200804900100000),
390
- B(0x2031010C01000C20, 0x200310A560082008),
391
- B(0x400202081811400, 0x40081802050000C),
392
- B(0x1011002100821300, 0x2400825040804100)
393
- };
394
- constexpr Bitboard CannonMagicHInit[SQUARE_NB] = {
395
- B(0x120000880110000, 0x1008000000020020),
396
- B(0x24200C080840A052, 0x2004004000010008),
397
- B(0xC030024000228800, 0x4000010400000020),
398
- B(0x1A0020802008802, 0x206010208000),
399
- B(0x12002000D001024, 0x80100800090138),
400
- B(0x4220010000241010, 0x3098000602001500),
401
- B(0x401010004801040, 0x8000280480100000),
402
- B(0x820082024921836, 0x220028000),
403
- B(0x100400502411400, 0x220402120240D14),
404
- B(0x880202020010404, 0xA80202510000),
405
- B(0x140002801000018, 0x1000346490040),
406
- B(0x120000880110000, 0x1008000000020020),
407
- B(0xD01004008030400, 0x104000408104420),
408
- B(0x8420060100020000, 0x800280400000120),
409
- B(0x4010020018010, 0x40A00001100000),
410
- B(0x40006A0004000200, 0x40000000110),
411
- B(0xD01004008030400, 0x104000408104420),
412
- B(0x8908A20028110011, 0x800080000001A114),
413
- B(0x200042000080F009, 0x20001000004000),
414
- B(0x2820008820100, 0x10002400058000B9),
415
- B(0x6083100420008050, 0x4040012600280080),
416
- B(0x216020000000446, 0x4080204000000211),
417
- B(0x340140003002089, 0x2402008000000911),
418
- B(0xD01004008030400, 0x104000408104420),
419
- B(0x1404040B20001000, 0x8000824010800011),
420
- B(0x8C0488120024214, 0x8414880202291),
421
- B(0x1010000060050000, 0x4000004050002602),
422
- B(0x4022983A0060000, 0x80000040010400),
423
- B(0x1404040B20001000, 0x8000824010800011),
424
- B(0x6020101802002840, 0x31000003000004),
425
- B(0x9000420008840, 0x4881300000000210),
426
- B(0xA200808865, 0x41C0048023000128),
427
- B(0x31801100400000, 0x8802DC001221240),
428
- B(0x884000080200920, 0x1004002410401001),
429
- B(0x2400040000884, 0x421006208040C0),
430
- B(0x1404040B20001000, 0x8000824010800011),
431
- B(0x24100400060009, 0x112008025042410),
432
- B(0x1800040009040200, 0x180000A1004E408A),
433
- B(0x24100400060009, 0x112008025042410),
434
- B(0x4060402008080, 0xC240080000110000),
435
- B(0x20080100920020, 0x2002248010242052),
436
- B(0x10001010802050, 0x880000001C98420),
437
- B(0x4000800100420022, 0x502022010A00D0),
438
- B(0x4C18104500200885, 0x400880800),
439
- B(0x8080810081020090, 0x8000000000000),
440
- B(0x8000062812080201, 0x8004C8300800),
441
- B(0x1800040009040200, 0x180000A1004E408A),
442
- B(0x24100400060009, 0x112008025042410),
443
- B(0x80102204040, 0x1000000900000000),
444
- B(0x2080000004202804, 0x120880003461),
445
- B(0x102004090A4030, 0x801020589240),
446
- B(0x20001100814000A0, 0x420202000820004),
447
- B(0x100800000A000120, 0x208000800010000),
448
- B(0x1008205000040802, 0x80002000400040),
449
- B(0x1480000098008401, 0xA0010000581010),
450
- B(0x30C0008200100820, 0x102800080904834),
451
- B(0x4810821884000500, 0x4400000200000212),
452
- B(0x1811D00128A0180, 0x2500848803000000),
453
- B(0x41618A0300040040, 0x21200200A421801),
454
- B(0x80102204040, 0x1000000900000000),
455
- B(0xA1808E0100108000, 0x2008000505000002),
456
- B(0x8C890020410000A0, 0xA010000048000400),
457
- B(0x40006002210044, 0x600008000408000),
458
- B(0x1200447220090042, 0x80001000160012),
459
- B(0x48410010AB000000, 0x9200600000000100),
460
- B(0x2040000000240003, 0x8020080288000600),
461
- B(0x9080000088848088, 0x4010210500000041),
462
- B(0xA1808E0100108000, 0x2008000505000002),
463
- B(0x480100400024, 0x1004800018200000),
464
- B(0x808403080080200, 0x802601000000500),
465
- B(0x8C890020410000A0, 0xA010000048000400),
466
- B(0xA1808E0100108000, 0x2008000505000002),
467
- B(0x100A40000004008, 0x2800200400200480),
468
- B(0x100A40000004008, 0x2800200400200480),
469
- B(0x400014006000000, 0x10006000810001F5),
470
- B(0xC410062001414, 0x820080041B01044),
471
- B(0x20000800310, 0x430040000201000),
472
- B(0xA40010008000008, 0x4002200028000040),
473
- B(0xC00102000008021C, 0x10C2000A010E024),
474
- B(0x80004200104008, 0x50A00800C400020),
475
- B(0x20200080012542, 0x910F0040000402C0),
476
- B(0xB040100504000300, 0x24802002000040),
477
- B(0x800001000014008, 0x400031004000),
478
- B(0x100A40000004008, 0x2800200400200480),
479
- B(0x84008002041081C0, 0x8080500200000000),
480
- B(0x440090001012001, 0x4020004010),
481
- B(0x100A0028088020, 0x80040E00010020),
482
- B(0x2180808000810, 0xB018040A00040000),
483
- B(0x40C80920304C4001, 0x42800B200800000),
484
- B(0x85000425001000, 0x4810048020001100),
485
- B(0x600C000801000004, 0x8015084010200020),
486
- B(0x20020050000240C0, 0x100202008600800),
487
- B(0x38000050001220, 0x9200010200145900),
488
- B(0x1042108040005, 0x1402A0802201001),
489
- B(0x824240000C20400, 0x1000000400080010),
490
- B(0x84008002041081C0, 0x8080500200000000),
491
- B(0x400804A1000008, 0x1024104A0200010),
492
- B(0x8000402308483, 0x20006020100100),
493
- B(0x80880120000080, 0x8000240100084),
494
- B(0x5840020004882001, 0x1004528000A00010),
495
- B(0x8001018800300002, 0x84010040804),
496
- B(0x180D10004000A008, 0xA001080008020004),
497
- B(0x400080B, 0x10A0000004010000),
498
- B(0x8080000200000, 0x2001000082004E0),
499
- B(0x40040001000C2000, 0x2024800001004008),
500
- B(0x400804A1000008, 0x1024104A0200010),
501
- B(0x8000402308483, 0x20006020100100),
502
- B(0x400804A1000008, 0x1024104A0200010),
503
- B(0x2000200000, 0x1201011000802),
504
- B(0x100100000000C4, 0x208004084048201),
505
- B(0x400084000044, 0x100810140300),
506
- B(0x29040C0C01010, 0x300204010820080),
507
- B(0x1A808000020200, 0x1000000005210040),
508
- B(0x20000400150000, 0x85008020),
509
- B(0x40C040008184014, 0x8002AA00024010),
510
- B(0x202000081B00804, 0x10001002008),
511
- B(0x40011000210060, 0x6080C40000021004),
512
- B(0x2000200000, 0x1201011000802),
513
- B(0x4100480203840, 0x300080100804),
514
- B(0x2000200000, 0x1201011000802),
515
- };
516
- constexpr Bitboard CannonMagicVInit[SQUARE_NB] = {
517
- B(0x202000812104400, 0x24800B01C0000303),
518
- B(0x340020400010D, 0x88060150C00400),
519
- B(0x400802040609, 0x49010200501A0002),
520
- B(0x8002680301000208, 0x628006C0C020200),
521
- B(0x20400209001C0804, 0xA044000800143110),
522
- B(0xC400082060010202, 0x4000480401014000),
523
- B(0x22500200144040, 0x8204820084704C00),
524
- B(0x8C1204009030020, 0x328400805000000),
525
- B(0x84800800D0001640, 0x200080040060108),
526
- B(0x804810208020040, 0x140010108020000),
527
- B(0x1102010B008004, 0x300208006220020),
528
- B(0x140080404A0A2428, 0x6308010100080),
529
- B(0x20444002120408, 0xA080010508010001),
530
- B(0x82011044000D02, 0x4112028620110809),
531
- B(0x81010831000C02, 0x408802085000000),
532
- B(0x81010831000C02, 0x408802085000000),
533
- B(0x920008920600040, 0x8053801004000028),
534
- B(0x81140283208300, 0x10040C004200420),
535
- B(0x103080022201, 0xC01000081312620),
536
- B(0x2200221100008, 0x1000408104000A4),
537
- B(0x4402088080042008, 0x210401501040340),
538
- B(0x898400202170001, 0x80040404208000),
539
- B(0x20080004051012, 0x5100048200081800),
540
- B(0x2320020000401018, 0x108501021040210),
541
- B(0x21080410A422021, 0x83040180008800),
542
- B(0x44E8100000408224, 0x20010008040400),
543
- B(0x1800240002810405, 0x23004820000020),
544
- B(0x80A0100400110, 0x80104020100C4028),
545
- B(0x1002050001222C0, 0x5100818004024020),
546
- B(0x104000200040, 0xC010A09800102000),
547
- B(0x1020003A058120, 0x450900809000302),
548
- B(0x40040045008B1, 0x202800400383010),
549
- B(0x4640200220034, 0x8800485420304000),
550
- B(0x5001042100084288, 0x110820001240080A),
551
- B(0x2002C04004010120, 0xA15008020880001),
552
- B(0x2800004080C4190, 0x890808280020080),
553
- B(0x40C0401000104000, 0x2020880008002580),
554
- B(0x40020C002400802, 0x801104010000000),
555
- B(0x44842000040080, 0x2050011084000400),
556
- B(0x4110040800000401, 0x2023810029008000),
557
- B(0x20884000840, 0x8017102004008000),
558
- B(0x10411104000480, 0x1414042000201001),
559
- B(0x220040000008, 0x800306021000000),
560
- B(0x41400A0008080, 0x501000298ACAD10),
561
- B(0x800240012831810, 0x80120004468050E),
562
- B(0x800005020801008, 0x20102400240000),
563
- B(0x20C00040C114C010, 0x88080820200C00),
564
- B(0x1044010100820081, 0x20080841004000),
565
- B(0x8041048400022, 0x8020836040005002),
566
- B(0x2001004010205, 0x8001002884042009),
567
- B(0x128088400087, 0x20008002201002),
568
- B(0x8084108040402000, 0x80809000A080400),
569
- B(0x408081840880, 0x201002088000040),
570
- B(0xA40180010280, 0x241004006000010),
571
- B(0x4204100080048140, 0x2002C4F104202020),
572
- B(0x100140A10204, 0x980200800840060),
573
- B(0x1005140010202048, 0x1442280800202815),
574
- B(0x2000082025008600, 0x1108400040600003),
575
- B(0x1005050648000, 0x200020240008002),
576
- B(0x202010208044000, 0x8210404060008),
577
- B(0x8011040402000210, 0xC840180408016004),
578
- B(0x404098801028, 0x80020A0001000400),
579
- B(0x404098801028, 0x80020A0001000400),
580
- B(0x80101002180140, 0x40C2080820000C0),
581
- B(0x208202081260800, 0x14090E4C04000050),
582
- B(0x4221201084004C2, 0x110480A011060),
583
- B(0x8000008421090204, 0x1C01010800024),
584
- B(0x8000008421090204, 0x1C01010800024),
585
- B(0x200180C840088A0, 0x401100400820000),
586
- B(0x10084043A021070, 0x202041600080200),
587
- B(0x210E6202001040C, 0x10100800080B0),
588
- B(0x848008021204002, 0x801004308100BAD),
589
- B(0xC082C0390A000601, 0x4040080189008),
590
- B(0x431200240210402D, 0x58102820000),
591
- B(0x202020100A0019B0, 0x4010C0D018000000),
592
- B(0x800800908402203, 0x102948C84C184),
593
- B(0x26801100080845, 0x4009702022A00820),
594
- B(0x8880520010401040, 0x1060084832052000),
595
- B(0x100100022042081, 0x10000600008C121),
596
- B(0x46020384100040, 0x800200320882021),
597
- B(0xC0002010148, 0x4200800800040003),
598
- B(0x2002208020090040, 0x40820210021410),
599
- B(0x9000A41160002004, 0x2A09000100080043),
600
- B(0x800004010008001, 0x1108002020104600),
601
- B(0x800540C000A4E041, 0x18021180000401),
602
- B(0x808200900A900202, 0x8364202140012005),
603
- B(0x1DBA52000081010, 0x4008000023000010),
604
- B(0x4100110204401481, 0x800040091020001C),
605
- B(0x4100110204401481, 0x800040091020001C),
606
- B(0x4101100020400482, 0x2000402302100120),
607
- B(0x100408000A020212, 0xA000400111000020),
608
- B(0x2000010488080104, 0x3000404410208100),
609
- B(0x2684220180008DD0, 0x422040200004000A),
610
- B(0x2021200C0424, 0x1010100000080200),
611
- B(0x8908020020801006, 0x3010800020C2000),
612
- B(0x4000030008062044, 0x244010202688000),
613
- B(0x242101200408009, 0x8150040000200015),
614
- B(0x42004C02180204, 0x210208014241040),
615
- B(0x4E1A01C208410804, 0x8890041000012004),
616
- B(0x2080200401000080, 0x8001098429008004),
617
- B(0xA01400121804104, 0x280200C400000500),
618
- B(0xD0080408040420, 0x1006040100224000),
619
- B(0x28400205000800C9, 0x6021101401040075),
620
- B(0x4000900040020104, 0x88129801100D0C),
621
- B(0x8000004002180410, 0x400380200400204),
622
- B(0x4002A430043008, 0x400200340100020),
623
- B(0x401960004140A42, 0x100880710000464),
624
- B(0x58014090102, 0xB8D30004010080),
625
- B(0xA004C08000244000, 0x11280100E0000040),
626
- B(0x2102008089208804, 0x110001004080040),
627
- B(0x700010084E003004, 0x8080864112000D40),
628
- B(0x4080881000200C20, 0x30324040880E0600),
629
- B(0x2024A40401810820, 0x3000888002000000),
630
- B(0x8200100400014, 0x4400340800252844),
631
- B(0x24A00804288281, 0x410103002201140),
632
- B(0x4080005022A08, 0x1000402200100264),
633
- B(0x200080032244040, 0x200502189010001),
634
- B(0x28108110404001, 0x400600120008412),
635
- B(0xA00002102810020, 0xB1080240015408),
636
- B(0x810080200806, 0x410440804080046),
637
- };
638
- constexpr Bitboard LameDabbabaMagicInit[SQUARE_NB] = {
639
- B(0x3C080482A592000C, 0x540104000020000),
640
- B(0x2802C40008000420, 0x4A00000001818009),
641
- B(0x1083040280804000, 0x120004C20100880),
642
- B(0x6840940880000892, 0x2014A01080800C2),
643
- B(0x8401489004000180, 0x2000800000400000),
644
- B(0x820161C800000110, 0x8000100000204020),
645
- B(0x610011A122000109, 0x1000004020008004),
646
- B(0x83282004023000, 0xE000020004848446),
647
- B(0x6840940880000892, 0x2014A01080800C2),
648
- B(0x4020120800800002, 0x88008000010020),
649
- B(0x30025B140A1000, 0x3141801401000040),
650
- B(0x41104D1810100050, 0x8141002010910),
651
- B(0x4200828A298400, 0x400340001040C000),
652
- B(0x8016A4900110040, 0x844812001068020),
653
- B(0x2250035820400A2, 0x8012010080900),
654
- B(0x820080083A009000, 0x880404091080110),
655
- B(0x80401500AF0020, 0x240000082201A04),
656
- B(0x668020020C081005, 0x4008001004100021),
657
- B(0x240100910000000, 0x82000A0030454000),
658
- B(0xA24091400008, 0x200014880004A921),
659
- B(0x840110042200410, 0x100080000A400000),
660
- B(0x40024024102000, 0x1000000002180404),
661
- B(0x92828423000530, 0x118800020110),
662
- B(0x1122404A1C90A8, 0x822040280020D00),
663
- B(0x41201A40900A000, 0x80C0480040605100),
664
- B(0x2504A85005488280, 0x3028112120022800),
665
- B(0x210180080626B048, 0x8000401000014000),
666
- B(0x1000410401040200, 0x41014000050C0106),
667
- B(0x1040650210802200, 0x80C0041000000),
668
- B(0x4020C10110900002, 0x2140C2001050009),
669
- B(0x191180092200022, 0x6010008400400800),
670
- B(0x8010821088080202, 0xCA240011008208),
671
- B(0x8C0488120024214, 0x8414880202291),
672
- B(0x8C0488120024214, 0x8414880202291),
673
- B(0x22080C8A0161401, 0x200C10004C002002),
674
- B(0x8430818023034080, 0x210090800000801),
675
- B(0x4845087008200, 0x40661480000),
676
- B(0x1202804428812050, 0x100022038020000),
677
- B(0x400016001201080, 0x24002200402060),
678
- B(0x680E041300800800, 0xE00130080004000),
679
- B(0x3409080200, 0x282840210000000),
680
- B(0x803310108400, 0x85200000080100A0),
681
- B(0xE180008A04162104, 0x9088240412404),
682
- B(0x20080100920020, 0x2002248010242052),
683
- B(0x8A000400C2410, 0x1000024086014300),
684
- B(0x1821040024663, 0x100000100010009),
685
- B(0x4000822310611, 0x120280406014008),
686
- B(0x1004008010818D08, 0x800000141892000),
687
- B(0x8010800004024042, 0x44B106008800896),
688
- B(0xA0063423444, 0x41002C15811008),
689
- B(0x2040012381001282, 0x4804080104A4000),
690
- B(0x10840101820880, 0xA800008000020020),
691
- B(0x10840101820880, 0xA800008000020020),
692
- B(0x60201D8300408190, 0x2010020920200000),
693
- B(0x4048100200090090, 0x2008090100000900),
694
- B(0x24200000280210, 0xD440050008004000),
695
- B(0x1280001000580020, 0x2200040089000A4),
696
- B(0x10208018C1020A20, 0x84C0432240610014),
697
- B(0x10208018C1020A20, 0x84C0432240610014),
698
- B(0x4108000010209089, 0x913000000024840),
699
- B(0x410C208008008E02, 0xE8000000000001),
700
- B(0x802208004005, 0x94206000022080),
701
- B(0xC00290018902002, 0x4204100000000000),
702
- B(0x2102801400093816, 0x9810004001000202),
703
- B(0x8008304000015800, 0x4A5C000000020000),
704
- B(0x1020108380800514, 0x1144210000000080),
705
- B(0xC0001000008090, 0x2812060000204000),
706
- B(0x1001100200003100, 0x246240060A004004),
707
- B(0xA00020A008002030, 0x2440C40000110B00),
708
- B(0x80502104000C008, 0x8222200042100010),
709
- B(0xC020200088014, 0x422094000000480),
710
- B(0x1029002000001030, 0x8105841120000210),
711
- B(0x49040D, 0x2310808A14042C0),
712
- B(0x200040200080A02C, 0xB890290400080000),
713
- B(0x2240180C0800002, 0x4151050280000100),
714
- B(0x2240180C0800002, 0x4151050280000100),
715
- B(0x8220224180420006, 0x4024501212011000),
716
- B(0x1806810A0881000, 0x802002048400080),
717
- B(0x400400A080842, 0x9305000401180000),
718
- B(0x10008001444110, 0x4420401040041833),
719
- B(0x2000002C02010E00, 0x400408D08009804),
720
- B(0x69D008200020100, 0x100842240049021),
721
- B(0x42C24450020000, 0xD38400880090884),
722
- B(0x485800800100001, 0x2484086522018840),
723
- B(0x900200020820042, 0x22302421400040C0),
724
- B(0x50B0413001818000, 0x452014040800C40),
725
- B(0x8004040021008, 0x20088A08000290),
726
- B(0x600C000801000004, 0x8015084010200020),
727
- B(0x208000C00, 0xE004804021100100),
728
- B(0x20001000040204, 0x948110C0B2081),
729
- B(0x268502400100021, 0x80A201840802080),
730
- B(0x408C000008, 0x8822102408014),
731
- B(0x1182080410100000, 0x608002046A0100),
732
- B(0x100820A083C00002, 0x3100100410A00),
733
- B(0x8401040000400124, 0x2000081288202200),
734
- B(0xB014040003000800, 0x11960D1101210),
735
- B(0x10040001900C000, 0x85603C1001280),
736
- B(0x2000844000000100, 0x2000024C60800800),
737
- B(0x120004234800900, 0x210010841040),
738
- B(0x8010300040000002, 0x4200008222104100),
739
- B(0x1000120402200100, 0x209080CC040108B4),
740
- B(0x110049A00000800, 0x80000420022180A8),
741
- B(0x80001C00080384, 0x1400101111081001),
742
- B(0x8011200008100428, 0x2020000880800922),
743
- B(0x10001000000204C8, 0x280C11104240),
744
- B(0x50100C82C000500, 0x28000280618DD1),
745
- B(0x8800498020000, 0x20500A0200320128),
746
- B(0x20010104000860, 0x8021720186008),
747
- B(0x4000000000100080, 0x35040084270C04),
748
- B(0x4500080000800, 0x280100002482C842),
749
- B(0x10400000000000, 0x20080051100130C2),
750
- B(0x10400000000000, 0x20080051100130C2),
751
- B(0x2000002110202014, 0x121004004004681),
752
- B(0x400202001006D40, 0x82240082202424),
753
- B(0x4500080000800, 0x280100002482C842),
754
- B(0xC6000000D00804, 0x1050020C0081090C),
755
- B(0x200080000000042, 0x10800661),
756
- B(0x2000001011200200, 0x2A420000802A0222),
757
- B(0x802020001202412, 0x2400404148426),
758
- B(0x8000440801040002, 0x444002800010052A),
759
- };
760
- constexpr Bitboard HorseMagicInit[SQUARE_NB] = {
761
- B(0x3C080482A592000C, 0x540104000020000),
762
- B(0x2802C40008000420, 0x4A00000001818009),
763
- B(0x1083040280804000, 0x120004C20100880),
764
- B(0x6840940880000892, 0x2014A01080800C2),
765
- B(0x8401489004000180, 0x2000800000400000),
766
- B(0x820161C800000110, 0x8000100000204020),
767
- B(0x610011A122000109, 0x1000004020008004),
768
- B(0x83282004023000, 0xE000020004848446),
769
- B(0x6840940880000892, 0x2014A01080800C2),
770
- B(0x4020120800800002, 0x88008000010020),
771
- B(0x30025B140A1000, 0x3141801401000040),
772
- B(0x41104D1810100050, 0x8141002010910),
773
- B(0x4200828A298400, 0x400340001040C000),
774
- B(0x8016A4900110040, 0x844812001068020),
775
- B(0x2250035820400A2, 0x8012010080900),
776
- B(0x820080083A009000, 0x880404091080110),
777
- B(0x80401500AF0020, 0x240000082201A04),
778
- B(0x668020020C081005, 0x4008001004100021),
779
- B(0x240100910000000, 0x82000A0030454000),
780
- B(0xA24091400008, 0x200014880004A921),
781
- B(0x840110042200410, 0x100080000A400000),
782
- B(0x40024024102000, 0x1000000002180404),
783
- B(0x92828423000530, 0x118800020110),
784
- B(0x1122404A1C90A8, 0x822040280020D00),
785
- B(0x41201A40900A000, 0x80C0480040605100),
786
- B(0x2504A85005488280, 0x3028112120022800),
787
- B(0x210180080626B048, 0x8000401000014000),
788
- B(0x1000410401040200, 0x41014000050C0106),
789
- B(0x1040650210802200, 0x80C0041000000),
790
- B(0x4020C10110900002, 0x2140C2001050009),
791
- B(0x191180092200022, 0x6010008400400800),
792
- B(0x8010821088080202, 0xCA240011008208),
793
- B(0x8C0488120024214, 0x8414880202291),
794
- B(0x8C0488120024214, 0x8414880202291),
795
- B(0x22080C8A0161401, 0x200C10004C002002),
796
- B(0x8430818023034080, 0x210090800000801),
797
- B(0x4845087008200, 0x40661480000),
798
- B(0x1202804428812050, 0x100022038020000),
799
- B(0x400016001201080, 0x24002200402060),
800
- B(0x680E041300800800, 0xE00130080004000),
801
- B(0x3409080200, 0x282840210000000),
802
- B(0x803310108400, 0x85200000080100A0),
803
- B(0xE180008A04162104, 0x9088240412404),
804
- B(0x20080100920020, 0x2002248010242052),
805
- B(0x8A000400C2410, 0x1000024086014300),
806
- B(0x1821040024663, 0x100000100010009),
807
- B(0x4000822310611, 0x120280406014008),
808
- B(0x1004008010818D08, 0x800000141892000),
809
- B(0x8010800004024042, 0x44B106008800896),
810
- B(0xA0063423444, 0x41002C15811008),
811
- B(0x2040012381001282, 0x4804080104A4000),
812
- B(0x10840101820880, 0xA800008000020020),
813
- B(0x10840101820880, 0xA800008000020020),
814
- B(0x60201D8300408190, 0x2010020920200000),
815
- B(0x4048100200090090, 0x2008090100000900),
816
- B(0x24200000280210, 0xD440050008004000),
817
- B(0x1280001000580020, 0x2200040089000A4),
818
- B(0x10208018C1020A20, 0x84C0432240610014),
819
- B(0x10208018C1020A20, 0x84C0432240610014),
820
- B(0x4108000010209089, 0x913000000024840),
821
- B(0x410C208008008E02, 0xE8000000000001),
822
- B(0x802208004005, 0x94206000022080),
823
- B(0xC00290018902002, 0x4204100000000000),
824
- B(0x2102801400093816, 0x9810004001000202),
825
- B(0x8008304000015800, 0x4A5C000000020000),
826
- B(0x1020108380800514, 0x1144210000000080),
827
- B(0xC0001000008090, 0x2812060000204000),
828
- B(0x1001100200003100, 0x246240060A004004),
829
- B(0xA00020A008002030, 0x2440C40000110B00),
830
- B(0x80502104000C008, 0x8222200042100010),
831
- B(0xC020200088014, 0x422094000000480),
832
- B(0x1029002000001030, 0x8105841120000210),
833
- B(0x49040D, 0x2310808A14042C0),
834
- B(0x200040200080A02C, 0xB890290400080000),
835
- B(0x2240180C0800002, 0x4151050280000100),
836
- B(0x2240180C0800002, 0x4151050280000100),
837
- B(0x8220224180420006, 0x4024501212011000),
838
- B(0x1806810A0881000, 0x802002048400080),
839
- B(0x400400A080842, 0x9305000401180000),
840
- B(0x10008001444110, 0x4420401040041833),
841
- B(0x2000002C02010E00, 0x400408D08009804),
842
- B(0x69D008200020100, 0x100842240049021),
843
- B(0x42C24450020000, 0xD38400880090884),
844
- B(0x485800800100001, 0x2484086522018840),
845
- B(0x900200020820042, 0x22302421400040C0),
846
- B(0x50B0413001818000, 0x452014040800C40),
847
- B(0x8004040021008, 0x20088A08000290),
848
- B(0x600C000801000004, 0x8015084010200020),
849
- B(0x208000C00, 0xE004804021100100),
850
- B(0x20001000040204, 0x948110C0B2081),
851
- B(0x268502400100021, 0x80A201840802080),
852
- B(0x408C000008, 0x8822102408014),
853
- B(0x1182080410100000, 0x608002046A0100),
854
- B(0x100820A083C00002, 0x3100100410A00),
855
- B(0x8401040000400124, 0x2000081288202200),
856
- B(0xB014040003000800, 0x11960D1101210),
857
- B(0x10040001900C000, 0x85603C1001280),
858
- B(0x2000844000000100, 0x2000024C60800800),
859
- B(0x120004234800900, 0x210010841040),
860
- B(0x8010300040000002, 0x4200008222104100),
861
- B(0x1000120402200100, 0x209080CC040108B4),
862
- B(0x110049A00000800, 0x80000420022180A8),
863
- B(0x80001C00080384, 0x1400101111081001),
864
- B(0x8011200008100428, 0x2020000880800922),
865
- B(0x10001000000204C8, 0x280C11104240),
866
- B(0x50100C82C000500, 0x28000280618DD1),
867
- B(0x8800498020000, 0x20500A0200320128),
868
- B(0x20010104000860, 0x8021720186008),
869
- B(0x4000000000100080, 0x35040084270C04),
870
- B(0x4500080000800, 0x280100002482C842),
871
- B(0x10400000000000, 0x20080051100130C2),
872
- B(0x10400000000000, 0x20080051100130C2),
873
- B(0x2000002110202014, 0x121004004004681),
874
- B(0x400202001006D40, 0x82240082202424),
875
- B(0x4500080000800, 0x280100002482C842),
876
- B(0xC6000000D00804, 0x1050020C0081090C),
877
- B(0x200080000000042, 0x10800661),
878
- B(0x2000001011200200, 0x2A420000802A0222),
879
- B(0x802020001202412, 0x2400404148426),
880
- B(0x8000440801040002, 0x444002800010052A),
881
- };
882
- constexpr Bitboard ElephantMagicInit[SQUARE_NB] = {
883
- B(0x64D2990200008, 0x4401880001C000),
884
- B(0x29BAA00010020, 0x200000400800600),
885
- B(0x3024240000000, 0x4100400010080),
886
- B(0xA490A00480020, 0x20084001041010A4),
887
- B(0x328C021008042, 0x100000000C10204),
888
- B(0x1964090001018, 0x7002040148001205),
889
- B(0x800302098404080, 0x4983020000000001),
890
- B(0x8812244630A02080, 0x8200006204003C08),
891
- B(0x41120231008000, 0x240441401020),
892
- B(0x840091030C00040, 0x1400008200023400),
893
- B(0x8001040E77030200, 0x100040090022000),
894
- B(0x602022139D835040, 0x101002010025900),
895
- B(0x405707C48400, 0x40010000008001),
896
- B(0x982003456A82050, 0x60800820040030),
897
- B(0x204184849200088, 0x101800004006),
898
- B(0x300222470949200, 0x2A0800200200800),
899
- B(0x400001211914000, 0x8200001407001),
900
- B(0x2000008614831020, 0x4000020001404000),
901
- B(0x84000024A2048048, 0x1200102000042),
902
- B(0x424010A58422008, 0x88440242212A0110),
903
- B(0x20020812C0C4408, 0x4121400000080010),
904
- B(0x680200062042420, 0x2001100000800000),
905
- B(0x200010060AEC855, 0x8083002040200000),
906
- B(0x4000008BAA85810, 0x82000805C0200A90),
907
- B(0x81450B200A025400, 0x4400101050000040),
908
- B(0x820A2241409010, 0x888420030000),
909
- B(0x909203000028, 0xC000004C00200041),
910
- B(0x8021400A84880240, 0x100180002010020),
911
- B(0x8001A20061410000, 0x14008499A000000),
912
- B(0x8201444800A00080, 0x402010040588120),
913
- B(0x100C06280020, 0x60010104840130),
914
- B(0x520040800080044, 0x8220000080001402),
915
- B(0x102021410040202, 0x2004400410006000),
916
- B(0x5401832090020400, 0x300010020001),
917
- B(0x180003105A84C108, 0x1012008800081000),
918
- B(0x480C10210026904, 0xA006000004200418),
919
- B(0x48050820210843A6, 0x108001004000C00),
920
- B(0x1030101182206324, 0x4401008921502002),
921
- B(0x40281060800800, 0x406000201260022),
922
- B(0xC29002440040C820, 0x400001002008020),
923
- B(0x40000400800241, 0xC220000000400280),
924
- B(0x40880126014208, 0x2A8004C008940000),
925
- B(0x121028100114080, 0x5010280481100082),
926
- B(0x4000088280442, 0x908420140008041),
927
- B(0x808C42400C0020, 0x3028100840801000),
928
- B(0x4000000410078488, 0x501000000620000),
929
- B(0x90080001421020A4, 0x4118400101060406),
930
- B(0x280420004855, 0xD200100400820000),
931
- B(0xA0063423444, 0x41002C15811008),
932
- B(0x200061201808102, 0x4286969000200002),
933
- B(0x10208018C1020A20, 0x84C0432240610014),
934
- B(0x4001A04880402000, 0x8100824080000001),
935
- B(0x60201D8300408190, 0x2010020920200000),
936
- B(0x20018C04908019, 0x2010884002002040),
937
- B(0x800000000C40810, 0x680100081150000D),
938
- B(0x2002002000040040, 0x8810049000010600),
939
- B(0x41618A0300040040, 0x21200200A421801),
940
- B(0x10208018C1020A20, 0x84C0432240610014),
941
- B(0x10208018C1020A20, 0x84C0432240610014),
942
- B(0x5A04001400412854, 0x8A44006000010002),
943
- B(0x13000C0810072432, 0x50049001021104),
944
- B(0x400048801142130, 0x4C1204100226010C),
945
- B(0x80001048, 0x408800104000080),
946
- B(0x8104868204040412, 0x22244202000081),
947
- B(0x8104868204040412, 0x22244202000081),
948
- B(0x4140001000240440, 0x80209004410004E),
949
- B(0x800800000100, 0xB111820100000002),
950
- B(0x404240004220, 0x2110402802050080),
951
- B(0x284010400004040, 0x100245002502020),
952
- B(0x14880A100114010, 0x400208080010024),
953
- B(0x4100004040440648, 0x10030D838041A80),
954
- B(0x32004000210, 0x4010225C88014000),
955
- B(0x2240180C0800002, 0x4151050280000100),
956
- B(0x2010A12002000042, 0x189051442010000),
957
- B(0x4060050080121883, 0x8250C10001000141),
958
- B(0x10000000044100, 0x8401084010261009),
959
- B(0xA00028040000, 0x2003224000002000),
960
- B(0x2060009001000020, 0x1000432022020228),
961
- B(0x404200000883080, 0x1080800848245000),
962
- B(0x240000402080, 0xCA0820814210502),
963
- B(0x200040200080A02C, 0xB890290400080000),
964
- B(0x800000000300482, 0x9203008100100013),
965
- B(0x8000210202042000, 0x22642104004C2400),
966
- B(0x1040400805000401, 0x2A0300102C80010),
967
- B(0x8010A01088020000, 0x122106105A06A030),
968
- B(0x8000C00001010494, 0x130A1A20404120),
969
- B(0x4B084010844290, 0x10A08008900840),
970
- B(0x1180001802460000, 0xB08000034C82004),
971
- B(0x4001880060028029, 0x204040002401000),
972
- B(0x8021A0001308002A, 0x97001822040040),
973
- B(0xC00000009A020AC1, 0x1000080900400),
974
- B(0x60010110001990, 0x4000880900400000),
975
- B(0x10290402401200, 0x230080402C08),
976
- B(0x4220000219012000, 0x140204804100008),
977
- B(0x1400200100002, 0x8E62200414128),
978
- B(0x402808502004403, 0x20049100C0284520),
979
- B(0xB30041004280280, 0x10020464DB200308),
980
- B(0x440010800808, 0xA0102E295812100),
981
- B(0x10008000B000, 0x2000058583220200),
982
- B(0x2000844000000100, 0x2000024C60800800),
983
- B(0x110000400100028, 0x24052304508004),
984
- B(0x8458000000840004, 0x118006463400001),
985
- B(0x804008000040050, 0x41044890228000),
986
- B(0x20000050000400, 0x80A101824A00086),
987
- B(0x600080404000020, 0x100007322480005),
988
- B(0xD082200020020008, 0x642000630120001),
989
- B(0x10000100040230, 0x8048114733320002),
990
- B(0x20200442002A880A, 0x8200002CB4B8052),
991
- B(0x290080000000, 0xA41297838F40D),
992
- B(0x800205000080, 0xF221232039874400),
993
- B(0x1444002004880C20, 0xC4100049144200),
994
- B(0x4500080000800, 0x280100002482C842),
995
- B(0x281240881008, 0x204084004C101900),
996
- B(0x1444002004880C20, 0xC4100049144200),
997
- B(0x4500080000800, 0x280100002482C842),
998
- B(0xC0010928430540, 0x92041902180),
999
- B(0x1051001208A, 0x4900064800C20640),
1000
- B(0x882020418C00000, 0x30004040092A821),
1001
- B(0x224404002004268C, 0x202500204C7D254),
1002
- B(0x290080000000, 0xA41297838F40D),
1003
- };
1004
- constexpr Bitboard JanggiElephantMagicInit[SQUARE_NB] = {
1005
- B(0xC502282200061400, 0x2D07081241D90200),
1006
- B(0xC502282200061400, 0x2D07081241D90200),
1007
- B(0x8084810022440C2, 0x81402202004),
1008
- B(0x80204010A800500, 0x5000021001740218),
1009
- B(0x8048100401208000, 0x2001000390000044),
1010
- B(0x202080020000000, 0x4010800010090424),
1011
- B(0x4081A0480073200, 0x100000A010406000),
1012
- B(0x4081A0480073200, 0x100000A010406000),
1013
- B(0x2040450004000C40, 0x8400000006302),
1014
- B(0x84010410018201, 0xA00A00000100000),
1015
- B(0x840091030C00040, 0x1400008200023400),
1016
- B(0x801058C0A0022, 0xC1920480010034),
1017
- B(0x80B4004800840800, 0x4080210A42040010),
1018
- B(0x400402221000445, 0x80321200408040),
1019
- B(0x4028142401012A00, 0x4005009000104448),
1020
- B(0x1440102040800220, 0x82800010A082000),
1021
- B(0x4100040300C00200, 0x800805100120000),
1022
- B(0x8200080061100, 0x2000101400000),
1023
- B(0x2000100410070001, 0x40818200B0900410),
1024
- B(0x400088020080000, 0x4A000402000CA0),
1025
- B(0x1402040410004000, 0x9840044504040),
1026
- B(0x20800088A00A0400, 0x1000020100180),
1027
- B(0x2001820520308201, 0x2008003404349000),
1028
- B(0x4004808022100, 0x8001000008081080),
1029
- B(0x102041041100425, 0x840400180B100104),
1030
- B(0x8806446000800214, 0x404402100010000),
1031
- B(0x8200141409C04101, 0x209030004A00D00),
1032
- B(0x8806004800880080, 0x1560004201000A01),
1033
- B(0x4200050600200090, 0x1CD0000000000421),
1034
- B(0x4820100022408100, 0x101404080320),
1035
- B(0x2A000A0A08080080, 0x1C02808000C2C0),
1036
- B(0x8808425040040014, 0x2021000100020),
1037
- B(0x5282104044A0020, 0x6B402104200008),
1038
- B(0x4001091040068120, 0x202000004003031),
1039
- B(0x4001091040068120, 0x202000004003031),
1040
- B(0x98040200A0214344, 0xA00300840010),
1041
- B(0x82508040A40808A, 0x40010000110042),
1042
- B(0x4400100101023, 0x450C8480040022),
1043
- B(0x210588880010800, 0x800A000108018102),
1044
- B(0x9400010144400, 0xC00010100018000),
1045
- B(0x20A0400100040004, 0x1242000101002040),
1046
- B(0x8022900040001001, 0x100000014000260),
1047
- B(0x51004124000A080, 0x40098400000002),
1048
- B(0x2158040001080022, 0x80009238401222),
1049
- B(0xA0103A0000802220, 0x20000200400010),
1050
- B(0x1101001208240, 0x100000800001064),
1051
- B(0x821020002090081, 0x5840D0010290280),
1052
- B(0x821020002090081, 0x5840D0010290280),
1053
- B(0x10400C1042000400, 0x4005000000440200),
1054
- B(0x844022008804820, 0x1000800100118000),
1055
- B(0x10802A9800800139, 0x4802840100842200),
1056
- B(0x4000A008200081, 0x4001100200402000),
1057
- B(0x200000008108400, 0x1000C00008080020),
1058
- B(0x120C11500100081, 0x440300308041100),
1059
- B(0x8080040080060100, 0xC00101B0040028),
1060
- B(0x901420A00110000, 0x8200010044700280),
1061
- B(0x140080080410000, 0x808040000C001001),
1062
- B(0x80210C0200A0008, 0x88088004600201),
1063
- B(0x8000004202020301, 0x2100142104002000),
1064
- B(0x1101011210004880, 0x8500840400000000),
1065
- B(0x40208802004800, 0x8080806009011240),
1066
- B(0x800000140408880, 0xC001018004060040),
1067
- B(0xC008080420500, 0x8024A10000000000),
1068
- B(0x2800000000400010, 0x44001C00400408),
1069
- B(0xA804008001200408, 0x202000020001000),
1070
- B(0xC08288805004080, 0x200042000800004),
1071
- B(0xA40A01000080012, 0x8800080042408),
1072
- B(0x2200100000100810, 0x800200010000100),
1073
- B(0x9881800004040001, 0x8058100100884004),
1074
- B(0x820000044020014, 0x4AA00010245012),
1075
- B(0x820000044020014, 0x4AA00010245012),
1076
- B(0x4000080240000808, 0x10100022054000),
1077
- B(0x5002000840101, 0x202020004000A00),
1078
- B(0x1188008200008402, 0x8088100020A2204),
1079
- B(0x304012004044080, 0x8028108818006010),
1080
- B(0x102210000008400, 0x1008000200380002),
1081
- B(0x51410E114200, 0x100C00084000000),
1082
- B(0x5001242320218, 0x800025000040040),
1083
- B(0x4008000200008190, 0x400020021000000),
1084
- B(0x10910022F0040, 0x450084400040001),
1085
- B(0x180010810000040, 0x4004100040040),
1086
- B(0x1088801424062010, 0x400084010030401),
1087
- B(0x3000120408000040, 0x10802001080A4051),
1088
- B(0x200008420, 0x40C0100020008804),
1089
- B(0x1048C000004000, 0x4220120804004000),
1090
- B(0x404A180000000E, 0x4C30412008110102),
1091
- B(0x400000404202005, 0x800808550EC40044),
1092
- B(0x282000200212010, 0x8001C0C102000210),
1093
- B(0x9012240000008100, 0x280CA04010040000),
1094
- B(0x2000C04001020C00, 0x2002010101042000),
1095
- B(0x1010000204408408, 0x8008004800E0C4A),
1096
- B(0x800286801000025, 0x8402401040050088),
1097
- B(0x40002000A0880000, 0x8400300108082086),
1098
- B(0x2080004404011, 0x20C080400100001),
1099
- B(0xB0010218100800, 0x8040200482C14103),
1100
- B(0x8011035000000C20, 0x4200044043200040),
1101
- B(0x804008000040050, 0x41044890228000),
1102
- B(0x80000400A0020020, 0x5308022021000000),
1103
- B(0x2118200000008004, 0x4141014004423D00),
1104
- B(0x90C0000200008040, 0x41041062000082),
1105
- B(0x1D000100941204, 0x12402001200420),
1106
- B(0x8C0040400400065, 0x22300B408100000),
1107
- B(0x8C0040400400065, 0x22300B408100000),
1108
- B(0x802802044600000, 0x1210100401030082),
1109
- B(0x9400488010000000, 0x8005404902040000),
1110
- B(0x2214020200001, 0x40102100820200),
1111
- B(0x2022000000800000, 0x6400440108480),
1112
- B(0x110000400100028, 0x24052304508004),
1113
- B(0x848820140010000, 0x201012500A000),
1114
- B(0x848820140010000, 0x201012500A000),
1115
- B(0x100100000000C4, 0x208004084048201),
1116
- B(0x100500000000290, 0x10102818208000),
1117
- B(0x2800414000C000, 0x20004005001301),
1118
- B(0x698180005101241, 0x10002014800210),
1119
- B(0x20000080000009, 0x440340C040),
1120
- B(0x1C0220200290020, 0x42100004004011C0),
1121
- B(0x200E620018320208, 0x440410402),
1122
- B(0xD04101010004024, 0x20000121104010A4),
1123
- B(0x220400000A80040, 0x806080020810010C),
1124
- B(0xA000200000000080, 0x1040801A0081208),
1125
- };
1126
- constexpr Bitboard CannonDiagMagicInit[SQUARE_NB] = {
1127
- B(0x811801000400, 0x312260280280202),
1128
- B(0x44A000402022680, 0x1020224880420005),
1129
- B(0x8000C80800200880, 0x2000810060080C0),
1130
- B(0x2010300240428040, 0x40240002C004E30),
1131
- B(0x1018010404010004, 0x1001010018081E0),
1132
- B(0x2042040010080090, 0x100000008410300),
1133
- B(0x400080020102000, 0x4500005300000000),
1134
- B(0x2D00C80420010200, 0x804003280020008),
1135
- B(0x8038820024420, 0x6010010080012040),
1136
- B(0x1202028004200088, 0x50018100004000C6),
1137
- B(0xA02010F0410081, 0x20013001000009A),
1138
- B(0x4013002041030588, 0x4802004110000004),
1139
- B(0x110020802000081, 0x202001800908002),
1140
- B(0x22010404103, 0x2020882080491200),
1141
- B(0x60000220400580, 0x85902800100100),
1142
- B(0x100080800050100, 0x200010220021088),
1143
- B(0x8088840404200080, 0x140011040104000),
1144
- B(0x4008508080082015, 0x8010100200580048),
1145
- B(0x4010400420201001, 0x260002080A80808),
1146
- B(0xC2002004A0008008, 0x8020082000110840),
1147
- B(0xA000A0820042400, 0x810408082100420),
1148
- B(0x80231808100004, 0x204002000800400),
1149
- B(0x8296144044004900, 0x4A1003008001840),
1150
- B(0x80A0020A0011008, 0x800104846080810),
1151
- B(0x803800801041000, 0x1030500102000404),
1152
- B(0x240C00900800850, 0x1804000108810000),
1153
- B(0x800400000088800, 0x800021801020000),
1154
- B(0x84800409300082, 0x1002D40680044000),
1155
- B(0xA110C0000200010, 0x401010001200260),
1156
- B(0x8200160204100004, 0x8040004004002022),
1157
- B(0x10001000000100C0, 0x84002811000200),
1158
- B(0x2000080020014001, 0x42002020000102),
1159
- B(0x109040044020018, 0x2020400202001000),
1160
- B(0x620000CD0108, 0x40040201008000),
1161
- B(0xA1402200A0020, 0x81400400300912),
1162
- B(0x20020CF100018020, 0x801A14086404000),
1163
- B(0x800801844001, 0x11621488425000),
1164
- B(0x10201004A8080, 0x100A000801000010),
1165
- B(0x2800411001000800, 0x80224084900020),
1166
- B(0x40400024028100, 0x501000400230060),
1167
- B(0x404808010080, 0x1201000400100004),
1168
- B(0x80802005200, 0x2000200008A0000),
1169
- B(0x20800080000022, 0x80040810002010),
1170
- B(0x40016004808240, 0x400114000801100),
1171
- B(0x8410004204240, 0x20011000604050),
1172
- B(0x8000C1009008268, 0x201004000209000),
1173
- B(0x10240C000920, 0xE000A5C14003002),
1174
- B(0x10184024280008, 0x90240802000000),
1175
- B(0x40889081081000, 0x8010050008800000),
1176
- B(0x100008C089000019, 0x802032014020010),
1177
- B(0x401C1804C00, 0x402501002002020),
1178
- B(0x200022000920D0, 0x8000800081300020),
1179
- B(0x801000400011, 0x400100044010226),
1180
- B(0x4A04010100100000, 0x500400080400000),
1181
- B(0xA000050200080000, 0x8500090001010000),
1182
- B(0x40400040001812, 0x4403000400100A0),
1183
- B(0x20C2250203020004, 0x210001C000080000),
1184
- B(0x21000408C6020001, 0x4200830012D1001),
1185
- B(0x840082016080A210, 0x2400080801081008),
1186
- B(0x40001020000, 0x4041240200083120),
1187
- B(0x2C04030010C0818, 0xA670002000818100),
1188
- B(0x4704A07085000510, 0x914001000040),
1189
- B(0x900210304100100, 0x1010004000281840),
1190
- B(0x8202920002002040, 0x810012000003),
1191
- B(0x4001400100050, 0x1144000408002000),
1192
- B(0x5900200020008100, 0x40200020002004),
1193
- B(0x301020002000480, 0x202000C0004),
1194
- B(0x20D000201104040, 0x34840100020010),
1195
- B(0x800004200080408, 0x40184200100240),
1196
- B(0x8430080100404020, 0x90042100244500),
1197
- B(0x3800100010220062, 0x50404030200218),
1198
- B(0x42E20008002020, 0x2000008200200300),
1199
- B(0xE488008280A004, 0x200001010CC80000),
1200
- B(0x6018010041109810, 0x800002000242041A),
1201
- B(0x40A8002438980, 0x8000810008208009),
1202
- B(0x401000480040100, 0x286800404002212),
1203
- B(0x821030000100009, 0x2000090200A00000),
1204
- B(0x20000100C0008028, 0x5000000100400082),
1205
- B(0x80A000048030080, 0x200000120200008),
1206
- B(0x6300280800204003, 0x48000105C0040100),
1207
- B(0x83008802420C0200, 0x2008020200080100),
1208
- B(0x1050C3102200042, 0x20103900010008),
1209
- B(0x8040902021408180, 0x12000021806200A4),
1210
- B(0x3008204008C10004, 0x680110100010401),
1211
- B(0x204321100421000, 0x400E204820494000),
1212
- B(0x8000044022404048, 0x4024010090024021),
1213
- B(0x140201424050, 0x280A000130008000),
1214
- B(0x900340808004002, 0x21026008000380),
1215
- B(0x82808000300444, 0x20002000A2001141),
1216
- B(0x140180100406002, 0x4004480001000004),
1217
- B(0x4808420800841900, 0x14008C0041000000),
1218
- B(0x2008600009000480, 0x9008020001400000),
1219
- B(0x2000100800100002, 0x2004100820210020),
1220
- B(0x2062010401A8100, 0x12200108420090),
1221
- B(0x1403188200032, 0x40048166105000),
1222
- B(0x410020020140041, 0x4400348102940040),
1223
- B(0x414040209208041, 0x4402400028B004),
1224
- B(0x8008010100421202, 0x401418002008800),
1225
- B(0x4000020010062200, 0xA02009148048000),
1226
- B(0x4443080082008B, 0x104014022801010),
1227
- B(0x42B440A0C000800, 0x9001009016111020),
1228
- B(0x400000214002, 0x8008080209020009),
1229
- B(0x480C414A001900, 0x3400100400210200),
1230
- B(0x1006008800604, 0x20240004030A050),
1231
- B(0x4C022401002A8300, 0x405008400000600),
1232
- B(0x3104000800A1042, 0x2004800204406200),
1233
- B(0xA09010280008200C, 0x4004000208C4168),
1234
- B(0x2800401120C20120, 0x4A00450200022030),
1235
- B(0x88001800304C0200, 0x204288102080000),
1236
- B(0x8044004201440101, 0x400820080C024022),
1237
- B(0xA000100C080, 0x4B40341004008081),
1238
- B(0x94802001300810, 0x140206008000800),
1239
- B(0x40002020202820, 0x280680404000040),
1240
- B(0xA820800004200, 0x80E1401012000491),
1241
- B(0x804000010020C000, 0x9403020200802000),
1242
- B(0x8C0001284201400, 0xC000100C01620800),
1243
- B(0x4010004002200414, 0x403080080200000),
1244
- B(0x140400A100800101, 0x10054C031080400),
1245
- B(0x20012C2400880082, 0x7000880020C03200),
1246
- B(0x204040300004, 0x840800041101002),
1247
- };
1248
- constexpr Bitboard NightriderMagicInit[SQUARE_NB] = {
1249
- B(0x8008100800020052, 0x8001440000000000),
1250
- B(0x24028400210090, 0x4200000000021),
1251
- B(0x22002020A0200800, 0x100820120000082),
1252
- B(0x424009020002200, 0x84810D4100002A),
1253
- B(0x404008020000600, 0x1000202000000081),
1254
- B(0x21020001000680, 0x2140200000000000),
1255
- B(0x2060021100000608, 0x8080020040000C8),
1256
- B(0x910C20408001200, 0x80A4030800000500),
1257
- B(0x2C40100010400009, 0x40400000200000C),
1258
- B(0x4090210034400004, 0x2104008000000),
1259
- B(0x1082008040840180, 0x140082080000000F),
1260
- B(0x8041001002101002, 0x8C002000000),
1261
- B(0x102205086800080, 0x84400030020D600),
1262
- B(0x2120080A32044E0, 0x400A02000016000),
1263
- B(0x6040003021040A0, 0x8000200206040040),
1264
- B(0x8001000008104082, 0x4002104202000114),
1265
- B(0x100400081080000, 0x201020020000020),
1266
- B(0x203000090010040, 0x140040010000000C),
1267
- B(0x9140000108100040, 0x4004004C08450010),
1268
- B(0x4402A12120020000, 0x450C002C000040C),
1269
- B(0x2028000200120800, 0x100100401001000),
1270
- B(0x800890081000, 0x10700A080180048),
1271
- B(0x41040C4008400, 0x8080001000080020),
1272
- B(0x2404000001060401, 0x10800116C0009110),
1273
- B(0x2001810020400110, 0xA0100800000480E2),
1274
- B(0x4081400120200218, 0x8800410800000000),
1275
- B(0x4C020020300E00, 0x810800000000808),
1276
- B(0xC8002200100108, 0x4860040380000100),
1277
- B(0x8000E0000804080, 0x4C800000000000),
1278
- B(0x211880010934041, 0x31000040000188),
1279
- B(0x4800801000003140, 0x80000000028),
1280
- B(0x61240410840004, 0x230100050000002),
1281
- B(0x61240410840004, 0x230100050000002),
1282
- B(0x4020008000C04C42, 0x3000021000000804),
1283
- B(0x829808040040840, 0x288010000002200),
1284
- B(0xA0420002040084, 0x1008604002000048),
1285
- B(0x10200004980, 0x2010410028000000),
1286
- B(0x4900200420100010, 0x1000A00401001898),
1287
- B(0x20000801600134, 0xC0002400000021C),
1288
- B(0x200040021010001, 0x8800000400000088),
1289
- B(0x88000824, 0x8800000040010000),
1290
- B(0x40000000200000D0, 0x8200004000AA84),
1291
- B(0x1002000000812002, 0x4000001C1008480),
1292
- B(0xC00010420003, 0x400002C00000004),
1293
- B(0x208400008008040, 0x111004280000C0),
1294
- B(0x60004000E800241, 0x202001000010040),
1295
- B(0x200004800061, 0x1109100480045800),
1296
- B(0x52880000200001, 0x608204100012DA0),
1297
- B(0x1000429008100800, 0x2008001000006018),
1298
- B(0x8490024200123001, 0x1041400080020),
1299
- B(0x810001020200014, 0x2C50500220000020),
1300
- B(0x20234B8000A0080, 0x4091200200000020),
1301
- B(0x400401010012600, 0xE00200000000020),
1302
- B(0x8040C00804004000, 0x8208014000000083),
1303
- B(0x102000410001044, 0x8200000000000),
1304
- B(0x102000410001044, 0x8200000000000),
1305
- B(0x242E00508040001, 0x80028000000000),
1306
- B(0x40810368002080, 0x4008080000224),
1307
- B(0x48200010208800, 0x1020800C000022),
1308
- B(0x220C4018008000, 0x282100130000211),
1309
- B(0x8008004400100, 0xC128208200020400),
1310
- B(0x44C004100020, 0x4008004000011000),
1311
- B(0x1008000000600008, 0x41C00180480183),
1312
- B(0x10080000, 0x404090018800020A),
1313
- B(0x4500000000004200, 0x45200200A0140),
1314
- B(0x2040000000240003, 0x8020080288000600),
1315
- B(0x2040000000240003, 0x8020080288000600),
1316
- B(0x2040000000240003, 0x8020080288000600),
1317
- B(0x48000000020A0080, 0x1000020200088),
1318
- B(0xA00000008404200, 0x4204010101001004),
1319
- B(0x10008030082, 0x2002800200100104),
1320
- B(0x44080002460010, 0x8007804100082D00),
1321
- B(0x98400040001802, 0x913002002020301),
1322
- B(0xA0400501040028, 0x8040481824002024),
1323
- B(0x4C0A0600100080A0, 0x8005000080008200),
1324
- B(0x802124000860008, 0x1009081800100080),
1325
- B(0x4000110040011000, 0x4080422200001081),
1326
- B(0x422008008000080, 0x4001020C00000202),
1327
- B(0x8000202008002101, 0xA008010000040),
1328
- B(0x804200020000020, 0xE0B0008010000001),
1329
- B(0x14040200002, 0x2000000006000004),
1330
- B(0x45000002010020, 0xA4040008400000),
1331
- B(0x800040020204184A, 0x10000402000006),
1332
- B(0x908000080400004, 0x5040100038400050),
1333
- B(0x3100002000040014, 0x804008008120000),
1334
- B(0x6002200000020008, 0xC011409081008881),
1335
- B(0xC02004060280001, 0x2003004010220254),
1336
- B(0x16410101, 0x100040108600000),
1337
- B(0x100000000200000, 0x201200010800200),
1338
- B(0xC400000004090002, 0x808808010224000A),
1339
- B(0xC400000004090002, 0x808808010224000A),
1340
- B(0x1000000000890001, 0x4050002001040),
1341
- B(0x618000000008484, 0x40000A0150000D4),
1342
- B(0x500000400009004, 0x1100200204100A1),
1343
- B(0x6006000008080480, 0x100254800C00904),
1344
- B(0x6006000008080480, 0x100254800C00904),
1345
- B(0x404808040044040, 0x4202020040000200),
1346
- B(0x2000080440810, 0x9044008844920000),
1347
- B(0x40204418040, 0x412000204080010),
1348
- B(0x88400820040248, 0x408040010C040800),
1349
- B(0x8110084000803, 0x102000000000),
1350
- B(0x4000040140001100, 0x80808102002),
1351
- B(0x100480044020008, 0x4601000100084488),
1352
- B(0x6200204420840, 0x41802043B0000),
1353
- B(0x540000010091010, 0x409004800A01208),
1354
- B(0x300040008000008, 0x2030080800010000),
1355
- B(0x408804010400090, 0x4008100800004000),
1356
- B(0x401600A0000080, 0x8400200201002200),
1357
- B(0x44000000100000, 0x1140040210000001),
1358
- B(0xC6000000D00804, 0x1050020C0081090C),
1359
- B(0x4098002, 0x900000C045008300),
1360
- B(0x245190008020, 0x2000C00100041000),
1361
- B(0x1000000A100046, 0x88000084800004),
1362
- B(0x1000000220240002, 0x400000401001088),
1363
- B(0x1000000220240002, 0x400000401001088),
1364
- B(0x820000118808000, 0x8000048161004A),
1365
- B(0x1100000000071A02, 0x500146102000048),
1366
- B(0x610000, 0x10010080040641),
1367
- B(0x2000010441A0044, 0x500800502020188),
1368
- B(0xA80000000180000, 0x234402012110080),
1369
- };
1370
- constexpr Bitboard GrasshopperMagicHInit[SQUARE_NB] = {
1371
- B(0x120000880110000, 0x1008000000020020),
1372
- B(0x24200C080840A052, 0x2004004000010008),
1373
- B(0xC030024000228800, 0x4000010400000020),
1374
- B(0x1A0020802008802, 0x206010208000),
1375
- B(0x12002000D001024, 0x80100800090138),
1376
- B(0x4220010000241010, 0x3098000602001500),
1377
- B(0x401010004801040, 0x8000280480100000),
1378
- B(0x820082024921836, 0x220028000),
1379
- B(0x100400502411400, 0x220402120240D14),
1380
- B(0x880202020010404, 0xA80202510000),
1381
- B(0x140002801000018, 0x1000346490040),
1382
- B(0x120000880110000, 0x1008000000020020),
1383
- B(0xD01004008030400, 0x104000408104420),
1384
- B(0x8420060100020000, 0x800280400000120),
1385
- B(0x4010020018010, 0x40A00001100000),
1386
- B(0x40006A0004000200, 0x40000000110),
1387
- B(0xD01004008030400, 0x104000408104420),
1388
- B(0x8908A20028110011, 0x800080000001A114),
1389
- B(0x200042000080F009, 0x20001000004000),
1390
- B(0x2820008820100, 0x10002400058000B9),
1391
- B(0x6083100420008050, 0x4040012600280080),
1392
- B(0x216020000000446, 0x4080204000000211),
1393
- B(0x340140003002089, 0x2402008000000911),
1394
- B(0xD01004008030400, 0x104000408104420),
1395
- B(0x1404040B20001000, 0x8000824010800011),
1396
- B(0x8C0488120024214, 0x8414880202291),
1397
- B(0x1010000060050000, 0x4000004050002602),
1398
- B(0x4022983A0060000, 0x80000040010400),
1399
- B(0x1404040B20001000, 0x8000824010800011),
1400
- B(0x6020101802002840, 0x31000003000004),
1401
- B(0x9000420008840, 0x4881300000000210),
1402
- B(0xA200808865, 0x41C0048023000128),
1403
- B(0x31801100400000, 0x8802DC001221240),
1404
- B(0x884000080200920, 0x1004002410401001),
1405
- B(0x2400040000884, 0x421006208040C0),
1406
- B(0x1404040B20001000, 0x8000824010800011),
1407
- B(0x24100400060009, 0x112008025042410),
1408
- B(0x1800040009040200, 0x180000A1004E408A),
1409
- B(0x24100400060009, 0x112008025042410),
1410
- B(0x4060402008080, 0xC240080000110000),
1411
- B(0x20080100920020, 0x2002248010242052),
1412
- B(0x10001010802050, 0x880000001C98420),
1413
- B(0x4000800100420022, 0x502022010A00D0),
1414
- B(0x4C18104500200885, 0x400880800),
1415
- B(0x8080810081020090, 0x8000000000000),
1416
- B(0x8000062812080201, 0x8004C8300800),
1417
- B(0xC010220920198, 0x85000A08000),
1418
- B(0x24100400060009, 0x112008025042410),
1419
- B(0x80102204040, 0x1000000900000000),
1420
- B(0x2080000004202804, 0x120880003461),
1421
- B(0x102004090A4030, 0x801020589240),
1422
- B(0x20001100814000A0, 0x420202000820004),
1423
- B(0x100800000A000120, 0x208000800010000),
1424
- B(0x1008205000040802, 0x80002000400040),
1425
- B(0x1480000098008401, 0xA0010000581010),
1426
- B(0x30C0008200100820, 0x102800080904834),
1427
- B(0x4810821884000500, 0x4400000200000212),
1428
- B(0x1811D00128A0180, 0x2500848803000000),
1429
- B(0x41618A0300040040, 0x21200200A421801),
1430
- B(0x80102204040, 0x1000000900000000),
1431
- B(0xA1808E0100108000, 0x2008000505000002),
1432
- B(0x8C890020410000A0, 0xA010000048000400),
1433
- B(0x40006002210044, 0x600008000408000),
1434
- B(0x1200447220090042, 0x80001000160012),
1435
- B(0x48410010AB000000, 0x9200600000000100),
1436
- B(0x2040000000240003, 0x8020080288000600),
1437
- B(0x9080000088848088, 0x4010210500000041),
1438
- B(0xA1808E0100108000, 0x2008000505000002),
1439
- B(0x480100400024, 0x1004800018200000),
1440
- B(0x808403080080200, 0x802601000000500),
1441
- B(0x8C890020410000A0, 0xA010000048000400),
1442
- B(0xA1808E0100108000, 0x2008000505000002),
1443
- B(0x100A40000004008, 0x2800200400200480),
1444
- B(0x100A40000004008, 0x2800200400200480),
1445
- B(0x400014006000000, 0x10006000810001F5),
1446
- B(0xC410062001414, 0x820080041B01044),
1447
- B(0x20000800310, 0x430040000201000),
1448
- B(0xA40010008000008, 0x4002200028000040),
1449
- B(0xC00102000008021C, 0x10C2000A010E024),
1450
- B(0x80004200104008, 0x50A00800C400020),
1451
- B(0x20200080012542, 0x910F0040000402C0),
1452
- B(0xB040100504000300, 0x24802002000040),
1453
- B(0x800001000014008, 0x400031004000),
1454
- B(0x100A40000004008, 0x2800200400200480),
1455
- B(0x84008002041081C0, 0x8080500200000000),
1456
- B(0x440090001012001, 0x4020004010),
1457
- B(0x100A0028088020, 0x80040E00010020),
1458
- B(0x2180808000810, 0xB018040A00040000),
1459
- B(0x40C80920304C4001, 0x42800B200800000),
1460
- B(0x85000425001000, 0x4810048020001100),
1461
- B(0x600C000801000004, 0x8015084010200020),
1462
- B(0x20020050000240C0, 0x100202008600800),
1463
- B(0x38000050001220, 0x9200010200145900),
1464
- B(0x1042108040005, 0x1402A0802201001),
1465
- B(0x824240000C20400, 0x1000000400080010),
1466
- B(0x84008002041081C0, 0x8080500200000000),
1467
- B(0x400804A1000008, 0x1024104A0200010),
1468
- B(0x8000402308483, 0x20006020100100),
1469
- B(0x80880120000080, 0x8000240100084),
1470
- B(0x5840020004882001, 0x1004528000A00010),
1471
- B(0x8001018800300002, 0x84010040804),
1472
- B(0x180D10004000A008, 0xA001080008020004),
1473
- B(0x400080B, 0x10A0000004010000),
1474
- B(0x8080000200000, 0x2001000082004E0),
1475
- B(0x40040001000C2000, 0x2024800001004008),
1476
- B(0x400804A1000008, 0x1024104A0200010),
1477
- B(0x8000402308483, 0x20006020100100),
1478
- B(0x400804A1000008, 0x1024104A0200010),
1479
- B(0x2000200000, 0x1201011000802),
1480
- B(0x100100000000C4, 0x208004084048201),
1481
- B(0x400084000044, 0x100810140300),
1482
- B(0x29040C0C01010, 0x300204010820080),
1483
- B(0x1A808000020200, 0x1000000005210040),
1484
- B(0x20000400150000, 0x85008020),
1485
- B(0x40C040008184014, 0x8002AA00024010),
1486
- B(0x202000081B00804, 0x10001002008),
1487
- B(0x40011000210060, 0x6080C40000021004),
1488
- B(0x2000200000, 0x1201011000802),
1489
- B(0x4100480203840, 0x300080100804),
1490
- B(0x2000200000, 0x1201011000802),
1491
- };
1492
- constexpr Bitboard GrasshopperMagicVInit[SQUARE_NB] = {
1493
- B(0x202000812104400, 0x24800B01C0000303),
1494
- B(0x340020400010D, 0x88060150C00400),
1495
- B(0x400802040609, 0x49010200501A0002),
1496
- B(0x8002680301000208, 0x628006C0C020200),
1497
- B(0x20400209001C0804, 0xA044000800143110),
1498
- B(0xC400082060010202, 0x4000480401014000),
1499
- B(0x22500200144040, 0x8204820084704C00),
1500
- B(0x8C1204009030020, 0x328400805000000),
1501
- B(0x84800800D0001640, 0x200080040060108),
1502
- B(0x804810208020040, 0x140010108020000),
1503
- B(0x1102010B008004, 0x300208006220020),
1504
- B(0x140080404A0A2428, 0x6308010100080),
1505
- B(0x20444002120408, 0xA080010508010001),
1506
- B(0x82011044000D02, 0x4112028620110809),
1507
- B(0x81010831000C02, 0x408802085000000),
1508
- B(0x81010831000C02, 0x408802085000000),
1509
- B(0x920008920600040, 0x8053801004000028),
1510
- B(0x81140283208300, 0x10040C004200420),
1511
- B(0x103080022201, 0xC01000081312620),
1512
- B(0x2200221100008, 0x1000408104000A4),
1513
- B(0x4402088080042008, 0x210401501040340),
1514
- B(0x898400202170001, 0x80040404208000),
1515
- B(0x20080004051012, 0x5100048200081800),
1516
- B(0x2320020000401018, 0x108501021040210),
1517
- B(0x21080410A422021, 0x83040180008800),
1518
- B(0x44E8100000408224, 0x20010008040400),
1519
- B(0x1800240002810405, 0x23004820000020),
1520
- B(0x80A0100400110, 0x80104020100C4028),
1521
- B(0x1002050001222C0, 0x5100818004024020),
1522
- B(0x104000200040, 0xC010A09800102000),
1523
- B(0x1020003A058120, 0x450900809000302),
1524
- B(0x40040045008B1, 0x202800400383010),
1525
- B(0x4640200220034, 0x8800485420304000),
1526
- B(0x5001042100084288, 0x110820001240080A),
1527
- B(0x2002C04004010120, 0xA15008020880001),
1528
- B(0x2800004080C4190, 0x890808280020080),
1529
- B(0x40C0401000104000, 0x2020880008002580),
1530
- B(0x40020C002400802, 0x801104010000000),
1531
- B(0x44842000040080, 0x2050011084000400),
1532
- B(0x4110040800000401, 0x2023810029008000),
1533
- B(0x20884000840, 0x8017102004008000),
1534
- B(0x10411104000480, 0x1414042000201001),
1535
- B(0x220040000008, 0x800306021000000),
1536
- B(0x41400A0008080, 0x501000298ACAD10),
1537
- B(0x800240012831810, 0x80120004468050E),
1538
- B(0x800005020801008, 0x20102400240000),
1539
- B(0x20C00040C114C010, 0x88080820200C00),
1540
- B(0x1044010100820081, 0x20080841004000),
1541
- B(0x8041048400022, 0x8020836040005002),
1542
- B(0x2001004010205, 0x8001002884042009),
1543
- B(0x128088400087, 0x20008002201002),
1544
- B(0x8084108040402000, 0x80809000A080400),
1545
- B(0x408081840880, 0x201002088000040),
1546
- B(0xA40180010280, 0x241004006000010),
1547
- B(0x4204100080048140, 0x2002C4F104202020),
1548
- B(0x100140A10204, 0x980200800840060),
1549
- B(0x1005140010202048, 0x1442280800202815),
1550
- B(0x2000082025008600, 0x1108400040600003),
1551
- B(0x1005050648000, 0x200020240008002),
1552
- B(0x202010208044000, 0x8210404060008),
1553
- B(0x8011040402000210, 0xC840180408016004),
1554
- B(0x404098801028, 0x80020A0001000400),
1555
- B(0x404098801028, 0x80020A0001000400),
1556
- B(0x80101002180140, 0x40C2080820000C0),
1557
- B(0x208202081260800, 0x14090E4C04000050),
1558
- B(0x4221201084004C2, 0x110480A011060),
1559
- B(0x8000008421090204, 0x1C01010800024),
1560
- B(0x8000008421090204, 0x1C01010800024),
1561
- B(0x200180C840088A0, 0x401100400820000),
1562
- B(0x10084043A021070, 0x202041600080200),
1563
- B(0x210E6202001040C, 0x10100800080B0),
1564
- B(0x848008021204002, 0x801004308100BAD),
1565
- B(0xC082C0390A000601, 0x4040080189008),
1566
- B(0x431200240210402D, 0x58102820000),
1567
- B(0x202020100A0019B0, 0x4010C0D018000000),
1568
- B(0x800800908402203, 0x102948C84C184),
1569
- B(0x26801100080845, 0x4009702022A00820),
1570
- B(0x8880520010401040, 0x1060084832052000),
1571
- B(0x100100022042081, 0x10000600008C121),
1572
- B(0x46020384100040, 0x800200320882021),
1573
- B(0xC0002010148, 0x4200800800040003),
1574
- B(0x2002208020090040, 0x40820210021410),
1575
- B(0x9000A41160002004, 0x2A09000100080043),
1576
- B(0x800004010008001, 0x1108002020104600),
1577
- B(0x800540C000A4E041, 0x18021180000401),
1578
- B(0x808200900A900202, 0x8364202140012005),
1579
- B(0x1DBA52000081010, 0x4008000023000010),
1580
- B(0x4100110204401481, 0x800040091020001C),
1581
- B(0x4100110204401481, 0x800040091020001C),
1582
- B(0x4101100020400482, 0x2000402302100120),
1583
- B(0x100408000A020212, 0xA000400111000020),
1584
- B(0x2000010488080104, 0x3000404410208100),
1585
- B(0x2684220180008DD0, 0x422040200004000A),
1586
- B(0x2021200C0424, 0x1010100000080200),
1587
- B(0x8908020020801006, 0x3010800020C2000),
1588
- B(0x4000030008062044, 0x244010202688000),
1589
- B(0x242101200408009, 0x8150040000200015),
1590
- B(0x42004C02180204, 0x210208014241040),
1591
- B(0x4E1A01C208410804, 0x8890041000012004),
1592
- B(0x2080200401000080, 0x8001098429008004),
1593
- B(0xA01400121804104, 0x280200C400000500),
1594
- B(0xD0080408040420, 0x1006040100224000),
1595
- B(0x28400205000800C9, 0x6021101401040075),
1596
- B(0x4000900040020104, 0x88129801100D0C),
1597
- B(0x8000004002180410, 0x400380200400204),
1598
- B(0x4002A430043008, 0x400200340100020),
1599
- B(0x401960004140A42, 0x100880710000464),
1600
- B(0x58014090102, 0xB8D30004010080),
1601
- B(0xA004C08000244000, 0x11280100E0000040),
1602
- B(0x2102008089208804, 0x110001004080040),
1603
- B(0x700010084E003004, 0x8080864112000D40),
1604
- B(0x4080881000200C20, 0x30324040880E0600),
1605
- B(0x2024A40401810820, 0x3000888002000000),
1606
- B(0x8200100400014, 0x4400340800252844),
1607
- B(0x24A00804288281, 0x410103002201140),
1608
- B(0x4080005022A08, 0x1000402200100264),
1609
- B(0x200080032244040, 0x200502189010001),
1610
- B(0x28108110404001, 0x400600120008412),
1611
- B(0xA00002102810020, 0xB1080240015408),
1612
- B(0x810080200806, 0x410440804080046),
1613
- };
1614
- constexpr Bitboard GrasshopperMagicDInit[SQUARE_NB] = {
1615
- B(0x811801000400, 0x312260280280202),
1616
- B(0x44A000402022680, 0x1020224880420005),
1617
- B(0x8000C80800200880, 0x2000810060080C0),
1618
- B(0x2010300240428040, 0x40240002C004E30),
1619
- B(0x1018010404010004, 0x1001010018081E0),
1620
- B(0x2042040010080090, 0x100000008410300),
1621
- B(0x400080020102000, 0x4500005300000000),
1622
- B(0x2D00C80420010200, 0x804003280020008),
1623
- B(0x8038820024420, 0x6010010080012040),
1624
- B(0x1202028004200088, 0x50018100004000C6),
1625
- B(0xA02010F0410081, 0x20013001000009A),
1626
- B(0x4013002041030588, 0x4802004110000004),
1627
- B(0x110020802000081, 0x202001800908002),
1628
- B(0x22010404103, 0x2020882080491200),
1629
- B(0x60000220400580, 0x85902800100100),
1630
- B(0x100080800050100, 0x200010220021088),
1631
- B(0x8088840404200080, 0x140011040104000),
1632
- B(0x4008508080082015, 0x8010100200580048),
1633
- B(0x4010400420201001, 0x260002080A80808),
1634
- B(0xC2002004A0008008, 0x8020082000110840),
1635
- B(0xA000A0820042400, 0x810408082100420),
1636
- B(0x80231808100004, 0x204002000800400),
1637
- B(0x8296144044004900, 0x4A1003008001840),
1638
- B(0x80A0020A0011008, 0x800104846080810),
1639
- B(0x803800801041000, 0x1030500102000404),
1640
- B(0x240C00900800850, 0x1804000108810000),
1641
- B(0x800400000088800, 0x800021801020000),
1642
- B(0x84800409300082, 0x1002D40680044000),
1643
- B(0xA110C0000200010, 0x401010001200260),
1644
- B(0x8200160204100004, 0x8040004004002022),
1645
- B(0x10001000000100C0, 0x84002811000200),
1646
- B(0x2000080020014001, 0x42002020000102),
1647
- B(0x109040044020018, 0x2020400202001000),
1648
- B(0x620000CD0108, 0x40040201008000),
1649
- B(0xA1402200A0020, 0x81400400300912),
1650
- B(0x20020CF100018020, 0x801A14086404000),
1651
- B(0x800801844001, 0x11621488425000),
1652
- B(0x10201004A8080, 0x100A000801000010),
1653
- B(0x2800411001000800, 0x80224084900020),
1654
- B(0x40400024028100, 0x501000400230060),
1655
- B(0x404808010080, 0x1201000400100004),
1656
- B(0x80802005200, 0x2000200008A0000),
1657
- B(0x20800080000022, 0x80040810002010),
1658
- B(0x40016004808240, 0x400114000801100),
1659
- B(0x8410004204240, 0x20011000604050),
1660
- B(0x8000C1009008268, 0x201004000209000),
1661
- B(0x10240C000920, 0xE000A5C14003002),
1662
- B(0x10184024280008, 0x90240802000000),
1663
- B(0x40889081081000, 0x8010050008800000),
1664
- B(0x100008C089000019, 0x802032014020010),
1665
- B(0x401C1804C00, 0x402501002002020),
1666
- B(0x200022000920D0, 0x8000800081300020),
1667
- B(0x801000400011, 0x400100044010226),
1668
- B(0x4A04010100100000, 0x500400080400000),
1669
- B(0xA000050200080000, 0x8500090001010000),
1670
- B(0x40400040001812, 0x4403000400100A0),
1671
- B(0x20C2250203020004, 0x210001C000080000),
1672
- B(0x21000408C6020001, 0x4200830012D1001),
1673
- B(0x840082016080A210, 0x2400080801081008),
1674
- B(0x40001020000, 0x4041240200083120),
1675
- B(0x2C04030010C0818, 0xA670002000818100),
1676
- B(0x4704A07085000510, 0x914001000040),
1677
- B(0x900210304100100, 0x1010004000281840),
1678
- B(0x8202920002002040, 0x810012000003),
1679
- B(0x4001400100050, 0x1144000408002000),
1680
- B(0x5900200020008100, 0x40200020002004),
1681
- B(0x301020002000480, 0x202000C0004),
1682
- B(0x20D000201104040, 0x34840100020010),
1683
- B(0x800004200080408, 0x40184200100240),
1684
- B(0x8430080100404020, 0x90042100244500),
1685
- B(0x3800100010220062, 0x50404030200218),
1686
- B(0x42E20008002020, 0x2000008200200300),
1687
- B(0xE488008280A004, 0x200001010CC80000),
1688
- B(0x6018010041109810, 0x800002000242041A),
1689
- B(0x40A8002438980, 0x8000810008208009),
1690
- B(0x401000480040100, 0x286800404002212),
1691
- B(0x821030000100009, 0x2000090200A00000),
1692
- B(0x20000100C0008028, 0x5000000100400082),
1693
- B(0x80A000048030080, 0x200000120200008),
1694
- B(0x6300280800204003, 0x48000105C0040100),
1695
- B(0x83008802420C0200, 0x2008020200080100),
1696
- B(0x1050C3102200042, 0x20103900010008),
1697
- B(0x8040902021408180, 0x12000021806200A4),
1698
- B(0x3008204008C10004, 0x680110100010401),
1699
- B(0x204321100421000, 0x400E204820494000),
1700
- B(0x8000044022404048, 0x4024010090024021),
1701
- B(0x140201424050, 0x280A000130008000),
1702
- B(0x900340808004002, 0x21026008000380),
1703
- B(0x82808000300444, 0x20002000A2001141),
1704
- B(0x140180100406002, 0x4004480001000004),
1705
- B(0x4808420800841900, 0x14008C0041000000),
1706
- B(0x2008600009000480, 0x9008020001400000),
1707
- B(0x2000100800100002, 0x2004100820210020),
1708
- B(0x2062010401A8100, 0x12200108420090),
1709
- B(0x1403188200032, 0x40048166105000),
1710
- B(0x410020020140041, 0x4400348102940040),
1711
- B(0x414040209208041, 0x4402400028B004),
1712
- B(0x8008010100421202, 0x401418002008800),
1713
- B(0x4000020010062200, 0xA02009148048000),
1714
- B(0x4443080082008B, 0x104014022801010),
1715
- B(0x42B440A0C000800, 0x9001009016111020),
1716
- B(0x400000214002, 0x8008080209020009),
1717
- B(0x480C414A001900, 0x3400100400210200),
1718
- B(0x1006008800604, 0x20240004030A050),
1719
- B(0x4C022401002A8300, 0x405008400000600),
1720
- B(0x3104000800A1042, 0x2004800204406200),
1721
- B(0xA09010280008200C, 0x4004000208C4168),
1722
- B(0x2800401120C20120, 0x4A00450200022030),
1723
- B(0x88001800304C0200, 0x204288102080000),
1724
- B(0x8044004201440101, 0x400820080C024022),
1725
- B(0xA000100C080, 0x4B40341004008081),
1726
- B(0x94802001300810, 0x140206008000800),
1727
- B(0x40002020202820, 0x280680404000040),
1728
- B(0xA820800004200, 0x80E1401012000491),
1729
- B(0x804000010020C000, 0x9403020200802000),
1730
- B(0x8C0001284201400, 0xC000100C01620800),
1731
- B(0x4010004002200414, 0x403080080200000),
1732
- B(0x140400A100800101, 0x10054C031080400),
1733
- B(0x20012C2400880082, 0x7000880020C03200),
1734
- B(0x204040300004, 0x840800041101002),
1735
- };
1736
- #undef B
1737
- #endif
1738
-
1739
- } // namespace Stockfish
1740
-
1741
- #endif // #ifndef MAGIC_H_INCLUDED
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/src/main.cpp DELETED
@@ -1,63 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
4
-
5
- Stockfish is free software: you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation, either version 3 of the License, or
8
- (at your option) any later version.
9
-
10
- Stockfish is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- You should have received a copy of the GNU General Public License
16
- along with this program. If not, see <http://www.gnu.org/licenses/>.
17
- */
18
-
19
- #include <iostream>
20
-
21
- #include "bitboard.h"
22
- #include "endgame.h"
23
- #include "position.h"
24
- #include "psqt.h"
25
- #include "search.h"
26
- #include "syzygy/tbprobe.h"
27
- #include "thread.h"
28
- #include "tt.h"
29
- #include "uci.h"
30
-
31
- #include "piece.h"
32
- #include "variant.h"
33
- #include "xboard.h"
34
-
35
-
36
- using namespace Stockfish;
37
-
38
- int main(int argc, char* argv[]) {
39
-
40
- std::cout << engine_info() << std::endl;
41
-
42
- pieceMap.init();
43
- variants.init();
44
- CommandLine::init(argc, argv);
45
- UCI::init(Options);
46
- Tune::init();
47
- PSQT::init(variants.find(Options["UCI_Variant"])->second);
48
- Bitboards::init();
49
- Position::init();
50
- Bitbases::init();
51
- Endgames::init();
52
- Threads.set(size_t(Options["Threads"]));
53
- Search::clear(); // After threads are up
54
- Eval::NNUE::init();
55
-
56
- UCI::loop(argc, argv);
57
-
58
- Threads.set(0);
59
- variants.clear_all();
60
- pieceMap.clear_all();
61
- delete XBoard::stateMachine;
62
- return 0;
63
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/src/material.cpp DELETED
@@ -1,321 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
4
-
5
- Stockfish is free software: you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation, either version 3 of the License, or
8
- (at your option) any later version.
9
-
10
- Stockfish is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- You should have received a copy of the GNU General Public License
16
- along with this program. If not, see <http://www.gnu.org/licenses/>.
17
- */
18
-
19
- #include <cassert>
20
- #include <cstring> // For std::memset
21
-
22
- #include "material.h"
23
- #include "thread.h"
24
-
25
- using namespace std;
26
-
27
- namespace Stockfish {
28
-
29
- namespace {
30
- #define S(mg, eg) make_score(mg, eg)
31
-
32
- // Polynomial material imbalance parameters
33
-
34
- // One Score parameter for each pair (our piece, another of our pieces)
35
- constexpr Score QuadraticOurs[][PIECE_TYPE_NB] = {
36
- // OUR PIECE 2
37
- // bishop pair pawn knight bishop rook queen
38
- {S(1419, 1455) }, // Bishop pair
39
- {S( 101, 28), S( 37, 39) }, // Pawn
40
- {S( 57, 64), S(249, 187), S(-49, -62) }, // Knight OUR PIECE 1
41
- {S( 0, 0), S(118, 137), S( 10, 27), S( 0, 0) }, // Bishop
42
- {S( -63, -68), S( -5, 3), S(100, 81), S(132, 118), S(-246, -244) }, // Rook
43
- {S(-210, -211), S( 37, 14), S(147, 141), S(161, 105), S(-158, -174), S(-9,-31) } // Queen
44
- };
45
-
46
- // One Score parameter for each pair (our piece, their piece)
47
- constexpr Score QuadraticTheirs[][PIECE_TYPE_NB] = {
48
- // THEIR PIECE
49
- // bishop pair pawn knight bishop rook queen
50
- { }, // Bishop pair
51
- {S( 33, 30) }, // Pawn
52
- {S( 46, 18), S(106, 84) }, // Knight OUR PIECE
53
- {S( 75, 35), S( 59, 44), S( 60, 15) }, // Bishop
54
- {S( 26, 35), S( 6, 22), S( 38, 39), S(-12, -2) }, // Rook
55
- {S( 97, 93), S(100, 163), S(-58, -91), S(112, 192), S(276, 225) } // Queen
56
- };
57
-
58
- #undef S
59
-
60
- // Endgame evaluation and scaling functions are accessed directly and not through
61
- // the function maps because they correspond to more than one material hash key.
62
- Endgame<KFsPsK> EvaluateKFsPsK[] = { Endgame<KFsPsK>(WHITE), Endgame<KFsPsK>(BLACK) };
63
- Endgame<KXK> EvaluateKXK[] = { Endgame<KXK>(WHITE), Endgame<KXK>(BLACK) };
64
- Endgame<KXK, EG_EVAL_ATOMIC> EvaluateKXKAtomic[] = { Endgame<KXK, EG_EVAL_ATOMIC>(WHITE), Endgame<KXK, EG_EVAL_ATOMIC>(BLACK) };
65
- Endgame<KXK, EG_EVAL_DUCK> EvaluateKXKDuck[] = { Endgame<KXK, EG_EVAL_DUCK>(WHITE), Endgame<KXK, EG_EVAL_DUCK>(BLACK) };
66
- Endgame<KXKX, EG_EVAL_MISERE> EvaluateKXKXMisere[] = { Endgame<KXKX, EG_EVAL_MISERE>(WHITE), Endgame<KXKX, EG_EVAL_MISERE>(BLACK) };
67
-
68
- Endgame<KBPsK> ScaleKBPsK[] = { Endgame<KBPsK>(WHITE), Endgame<KBPsK>(BLACK) };
69
- Endgame<KQKRPs> ScaleKQKRPs[] = { Endgame<KQKRPs>(WHITE), Endgame<KQKRPs>(BLACK) };
70
- Endgame<KPsK> ScaleKPsK[] = { Endgame<KPsK>(WHITE), Endgame<KPsK>(BLACK) };
71
- Endgame<KPKP> ScaleKPKP[] = { Endgame<KPKP>(WHITE), Endgame<KPKP>(BLACK) };
72
-
73
- // Helper used to detect a given material distribution
74
- bool is_KFsPsK(const Position& pos, Color us) {
75
- return (pos.promotion_piece_types(us) == piece_set(FERS))
76
- && !more_than_one(pos.pieces(~us))
77
- && (pos.count<FERS>(us) || pos.count<PAWN>(us))
78
- && !(pos.count<ALL_PIECES>(us) - pos.count<FERS>(us) - pos.count<PAWN>(us) - pos.count<KING>(us));
79
- }
80
-
81
- bool is_KXK(const Position& pos, Color us) {
82
- return !more_than_one(pos.pieces(~us))
83
- && pos.non_pawn_material(us) >= std::min(RookValueMg, 2 * SilverValueMg);
84
- }
85
-
86
- bool is_KXK_atomic(const Position& pos, Color us) {
87
- return !more_than_one(pos.pieces(~us))
88
- && pos.non_pawn_material(us) >= RookValueMg + KnightValueMg;
89
- }
90
-
91
- bool is_KXKX(const Position& pos, Color us) {
92
- return pos.non_pawn_material(us) - pos.non_pawn_material(~us) > QueenValueMg;
93
- }
94
-
95
- bool is_KBPsK(const Position& pos, Color us) {
96
- return pos.non_pawn_material(us) == BishopValueMg
97
- && pos.count<PAWN>(us) >= 1;
98
- }
99
-
100
- bool is_KQKRPs(const Position& pos, Color us) {
101
- return !pos.count<PAWN>(us)
102
- && pos.non_pawn_material(us) == QueenValueMg
103
- && pos.count<ROOK>(~us) == 1
104
- && pos.count<PAWN>(~us) >= 1;
105
- }
106
-
107
-
108
- /// imbalance() calculates the imbalance by comparing the piece count of each
109
- /// piece type for both colors.
110
-
111
- template<Color Us>
112
- Score imbalance(const Position& pos, const int pieceCount[][PIECE_TYPE_NB]) {
113
-
114
- constexpr Color Them = ~Us;
115
-
116
- Score bonus = SCORE_ZERO;
117
-
118
- // Second-degree polynomial material imbalance, by Tord Romstad
119
- for (int pt1 = NO_PIECE_TYPE; pt1 <= QUEEN; ++pt1)
120
- {
121
- if (!pieceCount[Us][pt1])
122
- continue;
123
-
124
- int v = QuadraticOurs[pt1][pt1] * pieceCount[Us][pt1];
125
-
126
- for (int pt2 = NO_PIECE_TYPE; pt2 < pt1; ++pt2)
127
- v += QuadraticOurs[pt1][pt2] * pieceCount[Us][pt2]
128
- + QuadraticTheirs[pt1][pt2] * pieceCount[Them][pt2];
129
-
130
- bonus += pieceCount[Us][pt1] * v;
131
- }
132
-
133
- if (pos.must_capture())
134
- bonus += (make_score(mg_value(QuadraticOurs[PAWN][PAWN]), 0) * pieceCount[Us][PAWN]
135
- + 3 * QuadraticOurs[KNIGHT][PAWN] * pieceCount[Us][KNIGHT]
136
- + QuadraticOurs[QUEEN][PAWN] * pieceCount[Us][QUEEN]) * pieceCount[Us][PAWN]
137
- + make_score( mg_value(QuadraticOurs[KNIGHT][KNIGHT]),
138
- -eg_value(QuadraticOurs[KNIGHT][KNIGHT])) * pieceCount[Us][KNIGHT] * pieceCount[Us][KNIGHT];
139
- else if (pos.blast_on_capture())
140
- bonus -= make_score(mg_value(QuadraticOurs[KNIGHT][PAWN]) * pieceCount[Us][KNIGHT] * pieceCount[Us][PAWN] / 2, 0);
141
- else if (pos.check_counting())
142
- bonus -= 2 * QuadraticOurs[PAWN][PAWN] * pieceCount[Us][PAWN] * pieceCount[Us][PAWN];
143
- else if (pos.captures_to_hand())
144
- bonus -= bonus / 10;
145
-
146
- return bonus;
147
- }
148
-
149
- } // namespace
150
-
151
- namespace Material {
152
-
153
-
154
- /// Material::probe() looks up the current position's material configuration in
155
- /// the material hash table. It returns a pointer to the Entry if the position
156
- /// is found. Otherwise a new Entry is computed and stored there, so we don't
157
- /// have to recompute all when the same material configuration occurs again.
158
-
159
- Entry* probe(const Position& pos) {
160
-
161
- Key key = pos.material_key(pos.endgame_eval());
162
- Entry* e = pos.this_thread()->materialTable[key];
163
-
164
- if (e->key == key)
165
- return e;
166
-
167
- std::memset(e, 0, sizeof(Entry));
168
- e->key = key;
169
- e->factor[WHITE] = e->factor[BLACK] = (uint8_t)SCALE_FACTOR_NORMAL;
170
-
171
- Value npm_w = pos.non_pawn_material(WHITE);
172
- Value npm_b = pos.non_pawn_material(BLACK);
173
- Value npm = std::clamp(npm_w + npm_b, EndgameLimit, MidgameLimit);
174
-
175
- // Map total non-pawn material into [PHASE_ENDGAME, PHASE_MIDGAME]
176
- if (pos.captures_to_hand() || pos.two_boards())
177
- {
178
- Value npm2 = VALUE_ZERO;
179
- for (PieceSet ps = pos.piece_types(); ps;)
180
- {
181
- PieceType pt = pop_lsb(ps);
182
- npm2 += pos.count_in_hand(pt) * PieceValue[MG][make_piece(WHITE, pt)];
183
- }
184
- e->gamePhase = Phase(PHASE_MIDGAME * npm / std::max(int(npm + npm2), 1));
185
- int countAll = pos.count_with_hand(WHITE, ALL_PIECES) + pos.count_with_hand(BLACK, ALL_PIECES);
186
- e->materialDensity = (npm + npm2 + pos.count<PAWN>() * PawnValueMg) * countAll / (pos.files() * pos.ranks());
187
- }
188
- else
189
- e->gamePhase = Phase(((npm - EndgameLimit) * PHASE_MIDGAME) / (MidgameLimit - EndgameLimit));
190
-
191
- // Let's look if we have a specialized evaluation function for this particular
192
- // material configuration. Firstly we look for a fixed configuration one, then
193
- // for a generic one if the previous search failed.
194
- if (pos.endgame_eval() && (e->evaluationFunction = Endgames::probe<Value>(key)) != nullptr)
195
- return e;
196
-
197
- switch (pos.endgame_eval())
198
- {
199
- case EG_EVAL_CHESS:
200
- for (Color c : { WHITE, BLACK })
201
- if (is_KFsPsK(pos, c))
202
- {
203
- e->evaluationFunction = &EvaluateKFsPsK[c];
204
- return e;
205
- }
206
-
207
- for (Color c : { WHITE, BLACK })
208
- if (is_KXK(pos, c))
209
- {
210
- e->evaluationFunction = &EvaluateKXK[c];
211
- return e;
212
- }
213
-
214
- // OK, we didn't find any special evaluation function for the current material
215
- // configuration. Is there a suitable specialized scaling function?
216
- {
217
- const auto* sf = Endgames::probe<ScaleFactor>(key);
218
-
219
- if (sf)
220
- {
221
- e->scalingFunction[sf->strongSide] = sf; // Only strong color assigned
222
- return e;
223
- }
224
- }
225
-
226
- // We didn't find any specialized scaling function, so fall back on generic
227
- // ones that refer to more than one material distribution. Note that in this
228
- // case we don't return after setting the function.
229
- for (Color c : { WHITE, BLACK })
230
- {
231
- if (is_KBPsK(pos, c))
232
- e->scalingFunction[c] = &ScaleKBPsK[c];
233
-
234
- else if (is_KQKRPs(pos, c))
235
- e->scalingFunction[c] = &ScaleKQKRPs[c];
236
- }
237
-
238
- if (npm_w + npm_b == VALUE_ZERO && pos.pieces(PAWN)) // Only pawns on the board
239
- {
240
- if (!pos.count<PAWN>(BLACK))
241
- {
242
- assert(pos.count<PAWN>(WHITE) >= 2);
243
-
244
- e->scalingFunction[WHITE] = &ScaleKPsK[WHITE];
245
- }
246
- else if (!pos.count<PAWN>(WHITE))
247
- {
248
- assert(pos.count<PAWN>(BLACK) >= 2);
249
-
250
- e->scalingFunction[BLACK] = &ScaleKPsK[BLACK];
251
- }
252
- else if (pos.count<PAWN>(WHITE) == 1 && pos.count<PAWN>(BLACK) == 1)
253
- {
254
- // This is a special case because we set scaling functions
255
- // for both colors instead of only one.
256
- e->scalingFunction[WHITE] = &ScaleKPKP[WHITE];
257
- e->scalingFunction[BLACK] = &ScaleKPKP[BLACK];
258
- }
259
- }
260
-
261
- // Zero or just one pawn makes it difficult to win, even with a small material
262
- // advantage. This catches some trivial draws like KK, KBK and KNK and gives a
263
- // drawish scale factor for cases such as KRKBP and KmmKm (except for KBBKN).
264
- if (!pos.count<PAWN>(WHITE) && npm_w - npm_b <= BishopValueMg)
265
- e->factor[WHITE] = uint8_t(npm_w < RookValueMg && pos.count<ALL_PIECES>(WHITE) <= 2 ? SCALE_FACTOR_DRAW :
266
- npm_b <= BishopValueMg && pos.count<ALL_PIECES>(WHITE) <= 3 ? 4 : 14);
267
-
268
- if (!pos.count<PAWN>(BLACK) && npm_b - npm_w <= BishopValueMg)
269
- e->factor[BLACK] = uint8_t(npm_b < RookValueMg && pos.count<ALL_PIECES>(BLACK) <= 2 ? SCALE_FACTOR_DRAW :
270
- npm_w <= BishopValueMg && pos.count<ALL_PIECES>(BLACK) <= 3 ? 4 : 14);
271
- break;
272
- case EG_EVAL_ANTI:
273
- break;
274
- case EG_EVAL_ATOMIC:
275
- for (Color c : { WHITE, BLACK })
276
- if (is_KXK_atomic(pos, c))
277
- {
278
- e->evaluationFunction = &EvaluateKXKAtomic[c];
279
- return e;
280
- }
281
- break;
282
- case EG_EVAL_DUCK:
283
- for (Color c : { WHITE, BLACK })
284
- if (is_KXK(pos, c))
285
- {
286
- e->evaluationFunction = &EvaluateKXKDuck[c];
287
- return e;
288
- }
289
- break;
290
- case EG_EVAL_MISERE:
291
- for (Color c : { WHITE, BLACK })
292
- if (is_KXKX(pos, c))
293
- {
294
- e->evaluationFunction = &EvaluateKXKXMisere[c];
295
- return e;
296
- }
297
- break;
298
- case EG_EVAL_RK:
299
- break;
300
- case NO_EG_EVAL:
301
- break;
302
- default:
303
- assert(false);
304
- }
305
-
306
- // Evaluate the material imbalance. We use PIECE_TYPE_NONE as a place holder
307
- // for the bishop pair "extended piece", which allows us to be more flexible
308
- // in defining bishop pair bonuses.
309
- const int pieceCount[COLOR_NB][PIECE_TYPE_NB] = {
310
- { pos.count<BISHOP>(WHITE) > 1, pos.count<PAWN>(WHITE), pos.count<KNIGHT>(WHITE),
311
- pos.count<BISHOP>(WHITE) , pos.count<ROOK>(WHITE), pos.count<QUEEN >(WHITE) },
312
- { pos.count<BISHOP>(BLACK) > 1, pos.count<PAWN>(BLACK), pos.count<KNIGHT>(BLACK),
313
- pos.count<BISHOP>(BLACK) , pos.count<ROOK>(BLACK), pos.count<QUEEN >(BLACK) } };
314
-
315
- e->score = (imbalance<WHITE>(pos, pieceCount) - imbalance<BLACK>(pos, pieceCount)) / 16;
316
- return e;
317
- }
318
-
319
- } // namespace Material
320
-
321
- } // namespace Stockfish
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/src/material.h DELETED
@@ -1,75 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
4
-
5
- Stockfish is free software: you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation, either version 3 of the License, or
8
- (at your option) any later version.
9
-
10
- Stockfish is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- You should have received a copy of the GNU General Public License
16
- along with this program. If not, see <http://www.gnu.org/licenses/>.
17
- */
18
-
19
- #ifndef MATERIAL_H_INCLUDED
20
- #define MATERIAL_H_INCLUDED
21
-
22
- #include "endgame.h"
23
- #include "misc.h"
24
- #include "position.h"
25
- #include "types.h"
26
-
27
- namespace Stockfish::Material {
28
-
29
- /// Material::Entry contains various information about a material configuration.
30
- /// It contains a material imbalance evaluation, a function pointer to a special
31
- /// endgame evaluation function (which in most cases is NULL, meaning that the
32
- /// standard evaluation function will be used), and scale factors.
33
- ///
34
- /// The scale factors are used to scale the evaluation score up or down. For
35
- /// instance, in KRB vs KR endgames, the score is scaled down by a factor of 4,
36
- /// which will result in scores of absolute value less than one pawn.
37
-
38
- struct Entry {
39
-
40
- Score imbalance() const { return score; }
41
- Phase game_phase() const { return (Phase)gamePhase; }
42
- bool specialized_eval_exists() const { return evaluationFunction != nullptr; }
43
- Value evaluate(const Position& pos) const { return (*evaluationFunction)(pos); }
44
-
45
- int material_density() const { return materialDensity; }
46
-
47
- // scale_factor() takes a position and a color as input and returns a scale factor
48
- // for the given color. We have to provide the position in addition to the color
49
- // because the scale factor may also be a function which should be applied to
50
- // the position. For instance, in KBP vs K endgames, the scaling function looks
51
- // for rook pawns and wrong-colored bishops.
52
- ScaleFactor scale_factor(const Position& pos, Color c) const {
53
- ScaleFactor sf = scalingFunction[c] ? (*scalingFunction[c])(pos)
54
- : SCALE_FACTOR_NONE;
55
- return sf != SCALE_FACTOR_NONE ? sf : ScaleFactor(factor[c]);
56
- }
57
-
58
- Key key;
59
- const EndgameBase<Value>* evaluationFunction;
60
- const EndgameBase<ScaleFactor>* scalingFunction[COLOR_NB]; // Could be one for each
61
- // side (e.g. KPKP, KBPsK)
62
- Score score;
63
- int16_t gamePhase;
64
- uint8_t factor[COLOR_NB];
65
-
66
- int materialDensity;
67
- };
68
-
69
- typedef HashTable<Entry, 8192> Table;
70
-
71
- Entry* probe(const Position& pos);
72
-
73
- } // namespace Stockfish::Material
74
-
75
- #endif // #ifndef MATERIAL_H_INCLUDED
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/src/misc.cpp DELETED
@@ -1,656 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
4
-
5
- Stockfish is free software: you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation, either version 3 of the License, or
8
- (at your option) any later version.
9
-
10
- Stockfish is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- You should have received a copy of the GNU General Public License
16
- along with this program. If not, see <http://www.gnu.org/licenses/>.
17
- */
18
-
19
- #ifdef _WIN32
20
- #if _WIN32_WINNT < 0x0601
21
- #undef _WIN32_WINNT
22
- #define _WIN32_WINNT 0x0601 // Force to include needed API prototypes
23
- #endif
24
-
25
- #ifndef NOMINMAX
26
- #define NOMINMAX
27
- #endif
28
-
29
- #include <windows.h>
30
- // The needed Windows API for processor groups could be missed from old Windows
31
- // versions, so instead of calling them directly (forcing the linker to resolve
32
- // the calls at compile time), try to load them at runtime. To do this we need
33
- // first to define the corresponding function pointers.
34
- extern "C" {
35
- typedef bool(*fun1_t)(LOGICAL_PROCESSOR_RELATIONSHIP,
36
- PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, PDWORD);
37
- typedef bool(*fun2_t)(USHORT, PGROUP_AFFINITY);
38
- typedef bool(*fun3_t)(HANDLE, CONST GROUP_AFFINITY*, PGROUP_AFFINITY);
39
- }
40
- #endif
41
-
42
- #include <fstream>
43
- #include <iomanip>
44
- #include <iostream>
45
- #include <sstream>
46
- #include <vector>
47
- #include <cstdlib>
48
-
49
- #if defined(__linux__) && !defined(__ANDROID__)
50
- #include <stdlib.h>
51
- #include <sys/mman.h>
52
- #endif
53
-
54
- #if defined(__APPLE__) || defined(__ANDROID__) || defined(__OpenBSD__) || (defined(__GLIBCXX__) && !defined(_GLIBCXX_HAVE_ALIGNED_ALLOC) && !defined(_WIN32)) || defined(__e2k__)
55
- #define POSIXALIGNEDALLOC
56
- #include <stdlib.h>
57
- #endif
58
-
59
- #include "misc.h"
60
- #include "thread.h"
61
-
62
- using namespace std;
63
-
64
- namespace Stockfish {
65
-
66
- namespace {
67
-
68
- /// Version number. If Version is left empty, then compile date in the format
69
- /// DD-MM-YY and show in engine_info.
70
- const string Version = "";
71
-
72
- /// Our fancy logging facility. The trick here is to replace cin.rdbuf() and
73
- /// cout.rdbuf() with two Tie objects that tie cin and cout to a file stream. We
74
- /// can toggle the logging of std::cout and std:cin at runtime whilst preserving
75
- /// usual I/O functionality, all without changing a single line of code!
76
- /// Idea from http://groups.google.com/group/comp.lang.c++/msg/1d941c0f26ea0d81
77
-
78
- struct Tie: public streambuf { // MSVC requires split streambuf for cin and cout
79
-
80
- Tie(streambuf* b, streambuf* l) : buf(b), logBuf(l) {}
81
-
82
- int sync() override { return logBuf->pubsync(), buf->pubsync(); }
83
- int overflow(int c) override { return log(buf->sputc((char)c), "<< "); }
84
- int underflow() override { return buf->sgetc(); }
85
- int uflow() override { return log(buf->sbumpc(), ">> "); }
86
-
87
- streambuf *buf, *logBuf;
88
-
89
- int log(int c, const char* prefix) {
90
-
91
- static int last = '\n'; // Single log file
92
-
93
- if (last == '\n')
94
- logBuf->sputn(prefix, 3);
95
-
96
- return last = logBuf->sputc((char)c);
97
- }
98
- };
99
-
100
- class Logger {
101
-
102
- Logger() : in(cin.rdbuf(), file.rdbuf()), out(cout.rdbuf(), file.rdbuf()) {}
103
- ~Logger() { start(""); }
104
-
105
- ofstream file;
106
- Tie in, out;
107
-
108
- public:
109
- static void start(const std::string& fname) {
110
-
111
- static Logger l;
112
-
113
- if (!fname.empty() && !l.file.is_open())
114
- {
115
- l.file.open(fname, ifstream::out);
116
-
117
- if (!l.file.is_open())
118
- {
119
- cerr << "Unable to open debug log file " << fname << endl;
120
- exit(EXIT_FAILURE);
121
- }
122
-
123
- cin.rdbuf(&l.in);
124
- cout.rdbuf(&l.out);
125
- }
126
- else if (fname.empty() && l.file.is_open())
127
- {
128
- cout.rdbuf(l.out.buf);
129
- cin.rdbuf(l.in.buf);
130
- l.file.close();
131
- }
132
- }
133
- };
134
-
135
- } // namespace
136
-
137
-
138
- /// engine_info() returns the full name of the current Stockfish version. This
139
- /// will be either "Stockfish <Tag> DD-MM-YY" (where DD-MM-YY is the date when
140
- /// the program was compiled) or "Stockfish <Version>", depending on whether
141
- /// Version is empty.
142
-
143
- string engine_info(bool to_uci, bool to_xboard) {
144
-
145
- const string months("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec");
146
- string month, day, year;
147
- stringstream ss, date(__DATE__); // From compiler, format is "Sep 21 2008"
148
-
149
- ss << "Fairy-Stockfish " << Version << setfill('0');
150
-
151
- if (Version.empty())
152
- {
153
- date >> month >> day >> year;
154
- ss << setw(2) << day << setw(2) << (1 + months.find(month) / 4) << year.substr(2);
155
- }
156
-
157
- #ifdef LARGEBOARDS
158
- ss << " LB";
159
- #endif
160
-
161
- if (!to_xboard)
162
- ss << (to_uci ? "\nid author ": " by ")
163
- << "Fabian Fichter";
164
-
165
- return ss.str();
166
- }
167
-
168
-
169
- /// compiler_info() returns a string trying to describe the compiler we use
170
-
171
- std::string compiler_info() {
172
-
173
- #define stringify2(x) #x
174
- #define stringify(x) stringify2(x)
175
- #define make_version_string(major, minor, patch) stringify(major) "." stringify(minor) "." stringify(patch)
176
-
177
- /// Predefined macros hell:
178
- ///
179
- /// __GNUC__ Compiler is gcc, Clang or Intel on Linux
180
- /// __INTEL_COMPILER Compiler is Intel
181
- /// _MSC_VER Compiler is MSVC or Intel on Windows
182
- /// _WIN32 Building on Windows (any)
183
- /// _WIN64 Building on Windows 64 bit
184
-
185
- std::string compiler = "\nCompiled by ";
186
-
187
- #ifdef __clang__
188
- compiler += "clang++ ";
189
- compiler += make_version_string(__clang_major__, __clang_minor__, __clang_patchlevel__);
190
- #elif __INTEL_COMPILER
191
- compiler += "Intel compiler ";
192
- compiler += "(version ";
193
- compiler += stringify(__INTEL_COMPILER) " update " stringify(__INTEL_COMPILER_UPDATE);
194
- compiler += ")";
195
- #elif _MSC_VER
196
- compiler += "MSVC ";
197
- compiler += "(version ";
198
- compiler += stringify(_MSC_FULL_VER) "." stringify(_MSC_BUILD);
199
- compiler += ")";
200
- #elif defined(__e2k__) && defined(__LCC__)
201
- #define dot_ver2(n) \
202
- compiler += (char)'.'; \
203
- compiler += (char)('0' + (n) / 10); \
204
- compiler += (char)('0' + (n) % 10);
205
-
206
- compiler += "MCST LCC ";
207
- compiler += "(version ";
208
- compiler += std::to_string(__LCC__ / 100);
209
- dot_ver2(__LCC__ % 100)
210
- dot_ver2(__LCC_MINOR__)
211
- compiler += ")";
212
- #elif __GNUC__
213
- compiler += "g++ (GNUC) ";
214
- compiler += make_version_string(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
215
- #else
216
- compiler += "Unknown compiler ";
217
- compiler += "(unknown version)";
218
- #endif
219
-
220
- #if defined(__APPLE__)
221
- compiler += " on Apple";
222
- #elif defined(__CYGWIN__)
223
- compiler += " on Cygwin";
224
- #elif defined(__MINGW64__)
225
- compiler += " on MinGW64";
226
- #elif defined(__MINGW32__)
227
- compiler += " on MinGW32";
228
- #elif defined(__ANDROID__)
229
- compiler += " on Android";
230
- #elif defined(__linux__)
231
- compiler += " on Linux";
232
- #elif defined(_WIN64)
233
- compiler += " on Microsoft Windows 64-bit";
234
- #elif defined(_WIN32)
235
- compiler += " on Microsoft Windows 32-bit";
236
- #else
237
- compiler += " on unknown system";
238
- #endif
239
-
240
- compiler += "\nCompilation settings include: ";
241
- compiler += (Is64Bit ? " 64bit" : " 32bit");
242
- #if defined(USE_VNNI)
243
- compiler += " VNNI";
244
- #endif
245
- #if defined(USE_AVX512)
246
- compiler += " AVX512";
247
- #endif
248
- compiler += (HasPext ? " BMI2" : "");
249
- #if defined(USE_AVX2)
250
- compiler += " AVX2";
251
- #endif
252
- #if defined(USE_SSE41)
253
- compiler += " SSE41";
254
- #endif
255
- #if defined(USE_SSSE3)
256
- compiler += " SSSE3";
257
- #endif
258
- #if defined(USE_SSE2)
259
- compiler += " SSE2";
260
- #endif
261
- compiler += (HasPopCnt ? " POPCNT" : "");
262
- #if defined(USE_MMX)
263
- compiler += " MMX";
264
- #endif
265
- #if defined(USE_NEON)
266
- compiler += " NEON";
267
- #endif
268
-
269
- #if !defined(NDEBUG)
270
- compiler += " DEBUG";
271
- #endif
272
-
273
- compiler += "\n__VERSION__ macro expands to: ";
274
- #ifdef __VERSION__
275
- compiler += __VERSION__;
276
- #else
277
- compiler += "(undefined macro)";
278
- #endif
279
- compiler += "\n";
280
-
281
- return compiler;
282
- }
283
-
284
-
285
- /// Debug functions used mainly to collect run-time statistics
286
- static std::atomic<int64_t> hits[2], means[2];
287
-
288
- void dbg_hit_on(bool b) { ++hits[0]; if (b) ++hits[1]; }
289
- void dbg_hit_on(bool c, bool b) { if (c) dbg_hit_on(b); }
290
- void dbg_mean_of(int v) { ++means[0]; means[1] += v; }
291
-
292
- void dbg_print() {
293
-
294
- if (hits[0])
295
- cerr << "Total " << hits[0] << " Hits " << hits[1]
296
- << " hit rate (%) " << 100 * hits[1] / hits[0] << endl;
297
-
298
- if (means[0])
299
- cerr << "Total " << means[0] << " Mean "
300
- << (double)means[1] / means[0] << endl;
301
- }
302
-
303
-
304
- /// Used to serialize access to std::cout to avoid multiple threads writing at
305
- /// the same time.
306
-
307
- std::ostream& operator<<(std::ostream& os, SyncCout sc) {
308
-
309
- static std::mutex m;
310
-
311
- if (sc == IO_LOCK)
312
- m.lock();
313
-
314
- if (sc == IO_UNLOCK)
315
- m.unlock();
316
-
317
- return os;
318
- }
319
-
320
-
321
- /// Trampoline helper to avoid moving Logger to misc.h
322
- void start_logger(const std::string& fname) { Logger::start(fname); }
323
-
324
-
325
- /// prefetch() preloads the given address in L1/L2 cache. This is a non-blocking
326
- /// function that doesn't stall the CPU waiting for data to be loaded from memory,
327
- /// which can be quite slow.
328
- #ifdef NO_PREFETCH
329
-
330
- void prefetch(void*) {}
331
-
332
- #else
333
-
334
- void prefetch(void* addr) {
335
-
336
- # if defined(__INTEL_COMPILER)
337
- // This hack prevents prefetches from being optimized away by
338
- // Intel compiler. Both MSVC and gcc seem not be affected by this.
339
- __asm__ ("");
340
- # endif
341
-
342
- # if defined(__INTEL_COMPILER) || defined(_MSC_VER)
343
- _mm_prefetch((char*)addr, _MM_HINT_T0);
344
- # else
345
- __builtin_prefetch(addr);
346
- # endif
347
- }
348
-
349
- #endif
350
-
351
-
352
- /// std_aligned_alloc() is our wrapper for systems where the c++17 implementation
353
- /// does not guarantee the availability of aligned_alloc(). Memory allocated with
354
- /// std_aligned_alloc() must be freed with std_aligned_free().
355
-
356
- void* std_aligned_alloc(size_t alignment, size_t size) {
357
-
358
- #if defined(POSIXALIGNEDALLOC)
359
- void *mem;
360
- return posix_memalign(&mem, alignment, size) ? nullptr : mem;
361
- #elif defined(_WIN32)
362
- return _mm_malloc(size, alignment);
363
- #else
364
- return aligned_alloc(alignment, size);
365
- #endif
366
- }
367
-
368
- void std_aligned_free(void* ptr) {
369
-
370
- #if defined(POSIXALIGNEDALLOC)
371
- free(ptr);
372
- #elif defined(_WIN32)
373
- _mm_free(ptr);
374
- #else
375
- free(ptr);
376
- #endif
377
- }
378
-
379
- /// aligned_large_pages_alloc() will return suitably aligned memory, if possible using large pages.
380
-
381
- #if defined(_WIN32)
382
-
383
- static void* aligned_large_pages_alloc_windows(size_t allocSize) {
384
-
385
- #if !defined(_WIN64)
386
- return nullptr;
387
- #else
388
-
389
- HANDLE hProcessToken { };
390
- LUID luid { };
391
- void* mem = nullptr;
392
-
393
- const size_t largePageSize = GetLargePageMinimum();
394
- if (!largePageSize)
395
- return nullptr;
396
-
397
- // We need SeLockMemoryPrivilege, so try to enable it for the process
398
- if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hProcessToken))
399
- return nullptr;
400
-
401
- if (LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME, &luid))
402
- {
403
- TOKEN_PRIVILEGES tp { };
404
- TOKEN_PRIVILEGES prevTp { };
405
- DWORD prevTpLen = 0;
406
-
407
- tp.PrivilegeCount = 1;
408
- tp.Privileges[0].Luid = luid;
409
- tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
410
-
411
- // Try to enable SeLockMemoryPrivilege. Note that even if AdjustTokenPrivileges() succeeds,
412
- // we still need to query GetLastError() to ensure that the privileges were actually obtained.
413
- if (AdjustTokenPrivileges(
414
- hProcessToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &prevTp, &prevTpLen) &&
415
- GetLastError() == ERROR_SUCCESS)
416
- {
417
- // Round up size to full pages and allocate
418
- allocSize = (allocSize + largePageSize - 1) & ~size_t(largePageSize - 1);
419
- mem = VirtualAlloc(
420
- NULL, allocSize, MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE);
421
-
422
- // Privilege no longer needed, restore previous state
423
- AdjustTokenPrivileges(hProcessToken, FALSE, &prevTp, 0, NULL, NULL);
424
- }
425
- }
426
-
427
- CloseHandle(hProcessToken);
428
-
429
- return mem;
430
-
431
- #endif
432
- }
433
-
434
- void* aligned_large_pages_alloc(size_t allocSize) {
435
-
436
- // Try to allocate large pages
437
- void* mem = aligned_large_pages_alloc_windows(allocSize);
438
-
439
- // Fall back to regular, page aligned, allocation if necessary
440
- if (!mem)
441
- mem = VirtualAlloc(NULL, allocSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
442
-
443
- return mem;
444
- }
445
-
446
- #else
447
-
448
- void* aligned_large_pages_alloc(size_t allocSize) {
449
-
450
- #if defined(__linux__)
451
- constexpr size_t alignment = 2 * 1024 * 1024; // assumed 2MB page size
452
- #else
453
- constexpr size_t alignment = 4096; // assumed small page size
454
- #endif
455
-
456
- // round up to multiples of alignment
457
- size_t size = ((allocSize + alignment - 1) / alignment) * alignment;
458
- void *mem = std_aligned_alloc(alignment, size);
459
- #if defined(MADV_HUGEPAGE)
460
- madvise(mem, size, MADV_HUGEPAGE);
461
- #endif
462
- return mem;
463
- }
464
-
465
- #endif
466
-
467
-
468
- /// aligned_large_pages_free() will free the previously allocated ttmem
469
-
470
- #if defined(_WIN32)
471
-
472
- void aligned_large_pages_free(void* mem) {
473
-
474
- if (mem && !VirtualFree(mem, 0, MEM_RELEASE))
475
- {
476
- DWORD err = GetLastError();
477
- std::cerr << "Failed to free large page memory. Error code: 0x"
478
- << std::hex << err
479
- << std::dec << std::endl;
480
- exit(EXIT_FAILURE);
481
- }
482
- }
483
-
484
- #else
485
-
486
- void aligned_large_pages_free(void *mem) {
487
- std_aligned_free(mem);
488
- }
489
-
490
- #endif
491
-
492
-
493
- namespace WinProcGroup {
494
-
495
- #ifndef _WIN32
496
-
497
- void bindThisThread(size_t) {}
498
-
499
- #else
500
-
501
- /// best_group() retrieves logical processor information using Windows specific
502
- /// API and returns the best group id for the thread with index idx. Original
503
- /// code from Texel by Peter Österlund.
504
-
505
- int best_group(size_t idx) {
506
-
507
- int threads = 0;
508
- int nodes = 0;
509
- int cores = 0;
510
- DWORD returnLength = 0;
511
- DWORD byteOffset = 0;
512
-
513
- // Early exit if the needed API is not available at runtime
514
- HMODULE k32 = GetModuleHandle("Kernel32.dll");
515
- auto fun1 = (fun1_t)(void(*)())GetProcAddress(k32, "GetLogicalProcessorInformationEx");
516
- if (!fun1)
517
- return -1;
518
-
519
- // First call to get returnLength. We expect it to fail due to null buffer
520
- if (fun1(RelationAll, nullptr, &returnLength))
521
- return -1;
522
-
523
- // Once we know returnLength, allocate the buffer
524
- SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *buffer, *ptr;
525
- ptr = buffer = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)malloc(returnLength);
526
-
527
- // Second call, now we expect to succeed
528
- if (!fun1(RelationAll, buffer, &returnLength))
529
- {
530
- free(buffer);
531
- return -1;
532
- }
533
-
534
- while (byteOffset < returnLength)
535
- {
536
- if (ptr->Relationship == RelationNumaNode)
537
- nodes++;
538
-
539
- else if (ptr->Relationship == RelationProcessorCore)
540
- {
541
- cores++;
542
- threads += (ptr->Processor.Flags == LTP_PC_SMT) ? 2 : 1;
543
- }
544
-
545
- assert(ptr->Size);
546
- byteOffset += ptr->Size;
547
- ptr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)(((char*)ptr) + ptr->Size);
548
- }
549
-
550
- free(buffer);
551
-
552
- std::vector<int> groups;
553
-
554
- // Run as many threads as possible on the same node until core limit is
555
- // reached, then move on filling the next node.
556
- for (int n = 0; n < nodes; n++)
557
- for (int i = 0; i < cores / nodes; i++)
558
- groups.push_back(n);
559
-
560
- // In case a core has more than one logical processor (we assume 2) and we
561
- // have still threads to allocate, then spread them evenly across available
562
- // nodes.
563
- for (int t = 0; t < threads - cores; t++)
564
- groups.push_back(t % nodes);
565
-
566
- // If we still have more threads than the total number of logical processors
567
- // then return -1 and let the OS to decide what to do.
568
- return idx < groups.size() ? groups[idx] : -1;
569
- }
570
-
571
-
572
- /// bindThisThread() set the group affinity of the current thread
573
-
574
- void bindThisThread(size_t idx) {
575
-
576
- // Use only local variables to be thread-safe
577
- int group = best_group(idx);
578
-
579
- if (group == -1)
580
- return;
581
-
582
- // Early exit if the needed API are not available at runtime
583
- HMODULE k32 = GetModuleHandle("Kernel32.dll");
584
- auto fun2 = (fun2_t)(void(*)())GetProcAddress(k32, "GetNumaNodeProcessorMaskEx");
585
- auto fun3 = (fun3_t)(void(*)())GetProcAddress(k32, "SetThreadGroupAffinity");
586
-
587
- if (!fun2 || !fun3)
588
- return;
589
-
590
- GROUP_AFFINITY affinity;
591
- if (fun2(group, &affinity))
592
- fun3(GetCurrentThread(), &affinity, nullptr);
593
- }
594
-
595
- #endif
596
-
597
- } // namespace WinProcGroup
598
-
599
- #ifdef _WIN32
600
- #include <direct.h>
601
- #define GETCWD _getcwd
602
- #else
603
- #include <unistd.h>
604
- #define GETCWD getcwd
605
- #endif
606
-
607
- namespace CommandLine {
608
-
609
- string argv0; // path+name of the executable binary, as given by argv[0]
610
- string binaryDirectory; // path of the executable directory
611
- string workingDirectory; // path of the working directory
612
-
613
- void init(int argc, char* argv[]) {
614
- (void)argc;
615
- string pathSeparator;
616
-
617
- // extract the path+name of the executable binary
618
- argv0 = argv[0];
619
-
620
- #ifdef _WIN32
621
- pathSeparator = "\\";
622
- #ifdef _MSC_VER
623
- // Under windows argv[0] may not have the extension. Also _get_pgmptr() had
624
- // issues in some windows 10 versions, so check returned values carefully.
625
- char* pgmptr = nullptr;
626
- if (!_get_pgmptr(&pgmptr) && pgmptr != nullptr && *pgmptr)
627
- argv0 = pgmptr;
628
- #endif
629
- #else
630
- pathSeparator = "/";
631
- #endif
632
-
633
- // extract the working directory
634
- workingDirectory = "";
635
- char buff[40000];
636
- char* cwd = GETCWD(buff, 40000);
637
- if (cwd)
638
- workingDirectory = cwd;
639
-
640
- // extract the binary directory path from argv0
641
- binaryDirectory = argv0;
642
- size_t pos = binaryDirectory.find_last_of("\\/");
643
- if (pos == std::string::npos)
644
- binaryDirectory = "." + pathSeparator;
645
- else
646
- binaryDirectory.resize(pos + 1);
647
-
648
- // pattern replacement: "./" at the start of path is replaced by the working directory
649
- if (binaryDirectory.find("." + pathSeparator) == 0)
650
- binaryDirectory.replace(0, 1, workingDirectory);
651
- }
652
-
653
-
654
- } // namespace CommandLine
655
-
656
- } // namespace Stockfish
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/src/misc.h DELETED
@@ -1,200 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
4
-
5
- Stockfish is free software: you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation, either version 3 of the License, or
8
- (at your option) any later version.
9
-
10
- Stockfish is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- You should have received a copy of the GNU General Public License
16
- along with this program. If not, see <http://www.gnu.org/licenses/>.
17
- */
18
-
19
- #ifndef MISC_H_INCLUDED
20
- #define MISC_H_INCLUDED
21
-
22
- #include <cassert>
23
- #include <chrono>
24
- #include <ostream>
25
- #include <string>
26
- #include <vector>
27
- #include <cstdint>
28
-
29
- #include "types.h"
30
-
31
- namespace Stockfish {
32
-
33
- std::string engine_info(bool to_uci = false, bool to_xboard = false);
34
- std::string compiler_info();
35
- void prefetch(void* addr);
36
- void start_logger(const std::string& fname);
37
- void* std_aligned_alloc(size_t alignment, size_t size);
38
- void std_aligned_free(void* ptr);
39
- void* aligned_large_pages_alloc(size_t size); // memory aligned by page size, min alignment: 4096 bytes
40
- void aligned_large_pages_free(void* mem); // nop if mem == nullptr
41
-
42
- void dbg_hit_on(bool b);
43
- void dbg_hit_on(bool c, bool b);
44
- void dbg_mean_of(int v);
45
- void dbg_print();
46
-
47
- typedef std::chrono::milliseconds::rep TimePoint; // A value in milliseconds
48
- static_assert(sizeof(TimePoint) == sizeof(int64_t), "TimePoint should be 64 bits");
49
- inline TimePoint now() {
50
- return std::chrono::duration_cast<std::chrono::milliseconds>
51
- (std::chrono::steady_clock::now().time_since_epoch()).count();
52
- }
53
-
54
- template<class Entry, int Size>
55
- struct HashTable {
56
- Entry* operator[](Key key) { return &table[(uint32_t)key & (Size - 1)]; }
57
-
58
- private:
59
- std::vector<Entry> table = std::vector<Entry>(Size); // Allocate on the heap
60
- };
61
-
62
-
63
- enum SyncCout { IO_LOCK, IO_UNLOCK };
64
- std::ostream& operator<<(std::ostream&, SyncCout);
65
-
66
- #define sync_cout std::cout << IO_LOCK
67
- #define sync_endl std::endl << IO_UNLOCK
68
-
69
-
70
- // align_ptr_up() : get the first aligned element of an array.
71
- // ptr must point to an array of size at least `sizeof(T) * N + alignment` bytes,
72
- // where N is the number of elements in the array.
73
- template <uintptr_t Alignment, typename T>
74
- T* align_ptr_up(T* ptr)
75
- {
76
- static_assert(alignof(T) < Alignment);
77
-
78
- const uintptr_t ptrint = reinterpret_cast<uintptr_t>(reinterpret_cast<char*>(ptr));
79
- return reinterpret_cast<T*>(reinterpret_cast<char*>((ptrint + (Alignment - 1)) / Alignment * Alignment));
80
- }
81
-
82
-
83
- // IsLittleEndian : true if and only if the binary is compiled on a little endian machine
84
- static inline const union { uint32_t i; char c[4]; } Le = { 0x01020304 };
85
- static inline const bool IsLittleEndian = (Le.c[0] == 4);
86
-
87
-
88
- template <typename T>
89
- class ValueListInserter {
90
- public:
91
- ValueListInserter(T* v, std::size_t& s) :
92
- values(v),
93
- size(&s)
94
- {
95
- }
96
-
97
- void push_back(const T& value) { values[(*size)++] = value; }
98
- private:
99
- T* values;
100
- std::size_t* size;
101
- };
102
-
103
- template <typename T, std::size_t MaxSize>
104
- class ValueList {
105
-
106
- public:
107
- std::size_t size() const { return size_; }
108
- void resize(std::size_t newSize) { size_ = newSize; }
109
- void push_back(const T& value) { values_[size_++] = value; }
110
- T& operator[](std::size_t index) { return values_[index]; }
111
- T* begin() { return values_; }
112
- T* end() { return values_ + size_; }
113
- const T& operator[](std::size_t index) const { return values_[index]; }
114
- const T* begin() const { return values_; }
115
- const T* end() const { return values_ + size_; }
116
- operator ValueListInserter<T>() { return ValueListInserter(values_, size_); }
117
-
118
- void swap(ValueList& other) {
119
- const std::size_t maxSize = std::max(size_, other.size_);
120
- for (std::size_t i = 0; i < maxSize; ++i) {
121
- std::swap(values_[i], other.values_[i]);
122
- }
123
- std::swap(size_, other.size_);
124
- }
125
-
126
- private:
127
- T values_[MaxSize];
128
- std::size_t size_ = 0;
129
- };
130
-
131
- /// xorshift64star Pseudo-Random Number Generator
132
- /// This class is based on original code written and dedicated
133
- /// to the public domain by Sebastiano Vigna (2014).
134
- /// It has the following characteristics:
135
- ///
136
- /// - Outputs 64-bit numbers
137
- /// - Passes Dieharder and SmallCrush test batteries
138
- /// - Does not require warm-up, no zeroland to escape
139
- /// - Internal state is a single 64-bit integer
140
- /// - Period is 2^64 - 1
141
- /// - Speed: 1.60 ns/call (Core i7 @3.40GHz)
142
- ///
143
- /// For further analysis see
144
- /// <http://vigna.di.unimi.it/ftp/papers/xorshift.pdf>
145
-
146
- class PRNG {
147
-
148
- uint64_t s;
149
-
150
- uint64_t rand64() {
151
-
152
- s ^= s >> 12, s ^= s << 25, s ^= s >> 27;
153
- return s * 2685821657736338717LL;
154
- }
155
-
156
- public:
157
- PRNG(uint64_t seed) : s(seed) { assert(seed); }
158
-
159
- template<typename T> T rand() { return T(rand64()); }
160
-
161
- /// Special generator used to fast init magic numbers.
162
- /// Output values only have 1/8th of their bits set on average.
163
- template<typename T> T sparse_rand()
164
- { return T(rand64() & rand64() & rand64()); }
165
- };
166
-
167
- inline uint64_t mul_hi64(uint64_t a, uint64_t b) {
168
- #if defined(__GNUC__) && defined(IS_64BIT)
169
- __extension__ typedef unsigned __int128 uint128;
170
- return ((uint128)a * (uint128)b) >> 64;
171
- #else
172
- uint64_t aL = (uint32_t)a, aH = a >> 32;
173
- uint64_t bL = (uint32_t)b, bH = b >> 32;
174
- uint64_t c1 = (aL * bL) >> 32;
175
- uint64_t c2 = aH * bL + c1;
176
- uint64_t c3 = aL * bH + (uint32_t)c2;
177
- return aH * bH + (c2 >> 32) + (c3 >> 32);
178
- #endif
179
- }
180
-
181
- /// Under Windows it is not possible for a process to run on more than one
182
- /// logical processor group. This usually means to be limited to use max 64
183
- /// cores. To overcome this, some special platform specific API should be
184
- /// called to set group affinity for each thread. Original code from Texel by
185
- /// Peter Österlund.
186
-
187
- namespace WinProcGroup {
188
- void bindThisThread(size_t idx);
189
- }
190
-
191
- namespace CommandLine {
192
- void init(int argc, char* argv[]);
193
-
194
- extern std::string binaryDirectory; // path of the executable directory
195
- extern std::string workingDirectory; // path of the working directory
196
- }
197
-
198
- } // namespace Stockfish
199
-
200
- #endif // #ifndef MISC_H_INCLUDED
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/src/movegen.cpp DELETED
@@ -1,528 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
4
-
5
- Stockfish is free software: you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation, either version 3 of the License, or
8
- (at your option) any later version.
9
-
10
- Stockfish is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- You should have received a copy of the GNU General Public License
16
- along with this program. If not, see <http://www.gnu.org/licenses/>.
17
- */
18
-
19
- #include <cassert>
20
-
21
- #include "movegen.h"
22
- #include "position.h"
23
-
24
- namespace Stockfish {
25
-
26
- namespace {
27
-
28
- template<MoveType T>
29
- ExtMove* make_move_and_gating(const Position& pos, ExtMove* moveList, Color us, Square from, Square to, PieceType pt = NO_PIECE_TYPE) {
30
-
31
- // Wall placing moves
32
- //if it's "wall or move", and they chose non-null move, skip even generating wall move
33
- if (pos.walling() && !(pos.wall_or_move() && (from!=to)))
34
- {
35
- Bitboard b = pos.board_bb() & ~((pos.pieces() ^ from) | to);
36
- if (T == CASTLING)
37
- {
38
- Square kto = make_square(to > from ? pos.castling_kingside_file() : pos.castling_queenside_file(), pos.castling_rank(us));
39
- Direction step = kto > from ? EAST : WEST;
40
- Square rto = kto - step;
41
- b ^= square_bb(to) ^ kto ^ rto;
42
- }
43
- if (T == EN_PASSANT)
44
- b ^= pos.capture_square(to);
45
-
46
- if (pos.walling_rule() == ARROW)
47
- b &= moves_bb(us, type_of(pos.piece_on(from)), to, pos.pieces() ^ from);
48
-
49
- //Any current or future wall variant must follow the walling region rule if set:
50
- b &= pos.walling_region(us);
51
-
52
- if (pos.walling_rule() == PAST)
53
- b &= square_bb(from);
54
- if (pos.walling_rule() == EDGE)
55
- {
56
- Bitboard wallsquares = pos.state()->wallSquares;
57
-
58
- b &= (FileABB | file_bb(pos.max_file()) | Rank1BB | rank_bb(pos.max_rank())) |
59
- ( shift<NORTH >(wallsquares) | shift<SOUTH >(wallsquares)
60
- | shift<EAST >(wallsquares) | shift<WEST >(wallsquares));
61
- }
62
- while (b)
63
- *moveList++ = make_gating<T>(from, to, pt, pop_lsb(b));
64
- return moveList;
65
- }
66
-
67
- *moveList++ = make<T>(from, to, pt);
68
-
69
- // Gating moves
70
- if (pos.seirawan_gating() && (pos.gates(us) & from))
71
- for (PieceSet ps = pos.piece_types(); ps;)
72
- {
73
- PieceType pt_gating = pop_lsb(ps);
74
- if (pos.can_drop(us, pt_gating) && (pos.drop_region(us, pt_gating) & from))
75
- *moveList++ = make_gating<T>(from, to, pt_gating, from);
76
- }
77
- if (pos.seirawan_gating() && T == CASTLING && (pos.gates(us) & to))
78
- for (PieceSet ps = pos.piece_types(); ps;)
79
- {
80
- PieceType pt_gating = pop_lsb(ps);
81
- if (pos.can_drop(us, pt_gating) && (pos.drop_region(us, pt_gating) & to))
82
- *moveList++ = make_gating<T>(from, to, pt_gating, to);
83
- }
84
-
85
- return moveList;
86
- }
87
-
88
- template<Color c, GenType Type, Direction D>
89
- ExtMove* make_promotions(const Position& pos, ExtMove* moveList, Square to) {
90
-
91
- if (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS)
92
- {
93
- for (PieceSet promotions = pos.promotion_piece_types(c); promotions;)
94
- {
95
- PieceType pt = pop_msb(promotions);
96
- if (!pos.promotion_limit(pt) || pos.promotion_limit(pt) > pos.count(c, pt))
97
- moveList = make_move_and_gating<PROMOTION>(pos, moveList, pos.side_to_move(), to - D, to, pt);
98
- }
99
- PieceType pt = pos.promoted_piece_type(PAWN);
100
- if (pt && !(pos.piece_promotion_on_capture() && pos.empty(to)))
101
- moveList = make_move_and_gating<PIECE_PROMOTION>(pos, moveList, pos.side_to_move(), to - D, to);
102
- }
103
-
104
- return moveList;
105
- }
106
-
107
- template<Color Us, GenType Type>
108
- ExtMove* generate_drops(const Position& pos, ExtMove* moveList, PieceType pt, Bitboard b) {
109
- assert(Type != CAPTURES);
110
- // Do not generate virtual drops for perft and at root
111
- if (pos.can_drop(Us, pt) || (Type != NON_EVASIONS && pos.two_boards() && pos.allow_virtual_drop(Us, pt)))
112
- {
113
- // Restrict to valid target
114
- b &= pos.drop_region(Us, pt);
115
-
116
- // Add to move list
117
- if (pos.drop_promoted() && pos.promoted_piece_type(pt))
118
- {
119
- Bitboard b2 = b;
120
- if (Type == QUIET_CHECKS)
121
- b2 &= pos.check_squares(pos.promoted_piece_type(pt));
122
- while (b2)
123
- *moveList++ = make_drop(pop_lsb(b2), pt, pos.promoted_piece_type(pt));
124
- }
125
- if (Type == QUIET_CHECKS || !pos.can_drop(Us, pt))
126
- b &= pos.check_squares(pt);
127
- while (b)
128
- *moveList++ = make_drop(pop_lsb(b), pt, pt);
129
- }
130
-
131
- return moveList;
132
- }
133
-
134
- template<Color Us, GenType Type>
135
- ExtMove* generate_pawn_moves(const Position& pos, ExtMove* moveList, Bitboard target) {
136
-
137
- if (!pos.pieces(Us, PAWN))
138
- return moveList;
139
-
140
- constexpr Color Them = ~Us;
141
- constexpr Direction Up = pawn_push(Us);
142
- constexpr Direction UpRight = (Us == WHITE ? NORTH_EAST : SOUTH_WEST);
143
- constexpr Direction UpLeft = (Us == WHITE ? NORTH_WEST : SOUTH_EAST);
144
-
145
- const Bitboard promotionZone = pos.promotion_zone(Us);
146
- const Bitboard standardPromotionZone = pos.sittuyin_promotion() ? Bitboard(0) : promotionZone;
147
- const Bitboard doubleStepRegion = pos.double_step_region(Us);
148
- const Bitboard tripleStepRegion = pos.triple_step_region(Us);
149
-
150
- const Bitboard pawns = pos.pieces(Us, PAWN);
151
- const Bitboard movable = pos.board_bb(Us, PAWN) & ~pos.pieces();
152
- const Bitboard capturable = pos.board_bb(Us, PAWN) & pos.pieces(Them);
153
-
154
- target = Type == EVASIONS ? target : AllSquares;
155
-
156
- // Define single and double push, left and right capture, as well as respective promotion moves
157
- Bitboard b1 = shift<Up>(pawns) & movable & target;
158
- Bitboard b2 = shift<Up>(shift<Up>(pawns & doubleStepRegion) & movable) & movable & target;
159
- Bitboard b3 = shift<Up>(shift<Up>(shift<Up>(pawns & tripleStepRegion) & movable) & movable) & movable & target;
160
- Bitboard brc = shift<UpRight>(pawns) & capturable & target;
161
- Bitboard blc = shift<UpLeft >(pawns) & capturable & target;
162
-
163
- Bitboard b1p = b1 & standardPromotionZone;
164
- Bitboard b2p = b2 & standardPromotionZone;
165
- Bitboard b3p = b3 & standardPromotionZone;
166
- Bitboard brcp = brc & standardPromotionZone;
167
- Bitboard blcp = blc & standardPromotionZone;
168
-
169
- // Restrict regions based on rules and move generation type
170
- if (pos.mandatory_pawn_promotion())
171
- {
172
- b1 &= ~standardPromotionZone;
173
- b2 &= ~standardPromotionZone;
174
- b3 &= ~standardPromotionZone;
175
- brc &= ~standardPromotionZone;
176
- blc &= ~standardPromotionZone;
177
- }
178
-
179
- if (Type == QUIET_CHECKS && pos.count<KING>(Them))
180
- {
181
- // To make a quiet check, you either make a direct check by pushing a pawn
182
- // or push a blocker pawn that is not on the same file as the enemy king.
183
- // Discovered check promotion has been already generated amongst the captures.
184
- Square ksq = pos.square<KING>(Them);
185
- Bitboard dcCandidatePawns = pos.blockers_for_king(Them) & ~file_bb(ksq);
186
- b1 &= pawn_attacks_bb(Them, ksq) | shift< Up>(dcCandidatePawns);
187
- b2 &= pawn_attacks_bb(Them, ksq) | shift<Up+Up>(dcCandidatePawns);
188
- }
189
-
190
- // Single and double pawn pushes, no promotions
191
- if (Type != CAPTURES)
192
- {
193
- while (b1)
194
- {
195
- Square to = pop_lsb(b1);
196
- moveList = make_move_and_gating<NORMAL>(pos, moveList, Us, to - Up, to);
197
- }
198
-
199
- while (b2)
200
- {
201
- Square to = pop_lsb(b2);
202
- moveList = make_move_and_gating<NORMAL>(pos, moveList, Us, to - Up - Up, to);
203
- }
204
-
205
- while (b3)
206
- {
207
- Square to = pop_lsb(b3);
208
- moveList = make_move_and_gating<NORMAL>(pos, moveList, Us, to - Up - Up - Up, to);
209
- }
210
- }
211
-
212
- // Promotions and underpromotions
213
- while (brcp)
214
- moveList = make_promotions<Us, Type, UpRight>(pos, moveList, pop_lsb(brcp));
215
-
216
- while (blcp)
217
- moveList = make_promotions<Us, Type, UpLeft >(pos, moveList, pop_lsb(blcp));
218
-
219
- while (b1p)
220
- moveList = make_promotions<Us, Type, Up >(pos, moveList, pop_lsb(b1p));
221
-
222
- while (b2p)
223
- moveList = make_promotions<Us, Type, Up+Up >(pos, moveList, pop_lsb(b2p));
224
-
225
- while (b3p)
226
- moveList = make_promotions<Us, Type, Up+Up+Up>(pos, moveList, pop_lsb(b3p));
227
-
228
- // Sittuyin promotions
229
- if (pos.sittuyin_promotion() && (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS))
230
- {
231
- // Pawns need to be in promotion zone if there is more than one pawn
232
- Bitboard promotionPawns = pos.count<PAWN>(Us) > 1 ? pawns & promotionZone : pawns;
233
- while (promotionPawns)
234
- {
235
- Square from = pop_lsb(promotionPawns);
236
- for (PieceSet ps = pos.promotion_piece_types(Us); ps;)
237
- {
238
- PieceType pt = pop_msb(ps);
239
- if (pos.promotion_limit(pt) && pos.promotion_limit(pt) <= pos.count(Us, pt))
240
- continue;
241
- Bitboard b = ((pos.attacks_from(Us, pt, from) & ~pos.pieces()) | from) & target;
242
- while (b)
243
- {
244
- Square to = pop_lsb(b);
245
- if (!(attacks_bb(Us, pt, to, pos.pieces() ^ from) & pos.pieces(Them)))
246
- *moveList++ = make<PROMOTION>(from, to, pt);
247
- }
248
- }
249
- }
250
- }
251
-
252
- // Standard and en passant captures
253
- if (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS)
254
- {
255
- while (brc)
256
- {
257
- Square to = pop_lsb(brc);
258
- moveList = make_move_and_gating<NORMAL>(pos, moveList, Us, to - UpRight, to);
259
- }
260
-
261
- while (blc)
262
- {
263
- Square to = pop_lsb(blc);
264
- moveList = make_move_and_gating<NORMAL>(pos, moveList, Us, to - UpLeft, to);
265
- }
266
-
267
- for (Bitboard epSquares = pos.ep_squares() & ~pos.pieces(); epSquares; )
268
- {
269
- Square epSquare = pop_lsb(epSquares);
270
-
271
- // An en passant capture cannot resolve a discovered check (unless there non-sliding riders)
272
- if (Type == EVASIONS && (target & (epSquare + Up)) && !pos.non_sliding_riders())
273
- return moveList;
274
-
275
- Bitboard b = pawns & pawn_attacks_bb(Them, epSquare);
276
-
277
- // En passant square is already disabled for non-fairy variants if there is no attacker
278
- assert(b || !pos.fast_attacks());
279
-
280
- while (b)
281
- moveList = make_move_and_gating<EN_PASSANT>(pos, moveList, Us, pop_lsb(b), epSquare);
282
- }
283
- }
284
-
285
- return moveList;
286
- }
287
-
288
-
289
- template<Color Us, GenType Type>
290
- ExtMove* generate_moves(const Position& pos, ExtMove* moveList, PieceType Pt, Bitboard target) {
291
-
292
- assert(Pt != KING && Pt != PAWN);
293
-
294
- Bitboard bb = pos.pieces(Us, Pt);
295
-
296
- while (bb)
297
- {
298
- Square from = pop_lsb(bb);
299
-
300
- Bitboard attacks = pos.attacks_from(Us, Pt, from);
301
- Bitboard quiets = pos.moves_from(Us, Pt, from);
302
- Bitboard b = ( (attacks & pos.pieces())
303
- | (quiets & ~pos.pieces()));
304
- Bitboard b1 = b & target;
305
- Bitboard promotion_zone = pos.promotion_zone(Us);
306
- PieceType promPt = pos.promoted_piece_type(Pt);
307
- Bitboard b2 = promPt && (!pos.promotion_limit(promPt) || pos.promotion_limit(promPt) > pos.count(Us, promPt)) ? b1 : Bitboard(0);
308
- Bitboard b3 = pos.piece_demotion() && pos.is_promoted(from) ? b1 : Bitboard(0);
309
- Bitboard pawnPromotions = (pos.promotion_pawn_types(Us) & Pt) ? (b & (Type == EVASIONS ? target : ~pos.pieces(Us)) & promotion_zone) : Bitboard(0);
310
- Bitboard epSquares = (pos.en_passant_types(Us) & Pt) ? (attacks & ~quiets & pos.ep_squares() & ~pos.pieces()) : Bitboard(0);
311
-
312
- // target squares considering pawn promotions
313
- if (pawnPromotions && pos.mandatory_pawn_promotion())
314
- b1 &= ~pawnPromotions;
315
-
316
- // Restrict target squares considering promotion zone
317
- if (b2 | b3)
318
- {
319
- if (pos.mandatory_piece_promotion())
320
- b1 &= (promotion_zone & from ? Bitboard(0) : ~promotion_zone) | (pos.piece_promotion_on_capture() ? ~pos.pieces() : Bitboard(0));
321
- // Exclude quiet promotions/demotions
322
- if (pos.piece_promotion_on_capture())
323
- {
324
- b2 &= pos.pieces();
325
- b3 &= pos.pieces();
326
- }
327
- // Consider promotions/demotions into promotion zone
328
- if (!(promotion_zone & from))
329
- {
330
- b2 &= promotion_zone;
331
- b3 &= promotion_zone;
332
- }
333
- }
334
-
335
- if (Type == QUIET_CHECKS)
336
- {
337
- b1 &= pos.check_squares(Pt);
338
- if (b2)
339
- b2 &= pos.check_squares(pos.promoted_piece_type(Pt));
340
- if (b3)
341
- b3 &= pos.check_squares(type_of(pos.unpromoted_piece_on(from)));
342
- }
343
-
344
- while (b1)
345
- moveList = make_move_and_gating<NORMAL>(pos, moveList, Us, from, pop_lsb(b1));
346
-
347
- // Shogi-style piece promotions
348
- while (b2)
349
- *moveList++ = make<PIECE_PROMOTION>(from, pop_lsb(b2));
350
-
351
- // Piece demotions
352
- while (b3)
353
- *moveList++ = make<PIECE_DEMOTION>(from, pop_lsb(b3));
354
-
355
- // Pawn-style promotions
356
- if ((Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS) && pawnPromotions)
357
- for (PieceSet ps = pos.promotion_piece_types(Us); ps;)
358
- {
359
- PieceType ptP = pop_msb(ps);
360
- if (!pos.promotion_limit(ptP) || pos.promotion_limit(ptP) > pos.count(Us, ptP))
361
- for (Bitboard promotions = pawnPromotions; promotions; )
362
- moveList = make_move_and_gating<PROMOTION>(pos, moveList, pos.side_to_move(), from, pop_lsb(promotions), ptP);
363
- }
364
-
365
- // En passant captures
366
- if (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS)
367
- while (epSquares)
368
- moveList = make_move_and_gating<EN_PASSANT>(pos, moveList, Us, from, pop_lsb(epSquares));
369
- }
370
-
371
- return moveList;
372
- }
373
-
374
-
375
- template<Color Us, GenType Type>
376
- ExtMove* generate_all(const Position& pos, ExtMove* moveList) {
377
-
378
- static_assert(Type != LEGAL, "Unsupported type in generate_all()");
379
-
380
- constexpr bool Checks = Type == QUIET_CHECKS; // Reduce template instantiations
381
- const Square ksq = pos.count<KING>(Us) ? pos.square<KING>(Us) : SQ_NONE;
382
- Bitboard target;
383
-
384
- // Skip generating non-king moves when in double check
385
- if (Type != EVASIONS || !more_than_one(pos.checkers() & ~pos.non_sliding_riders()))
386
- {
387
- target = Type == EVASIONS ? between_bb(ksq, lsb(pos.checkers()))
388
- : Type == NON_EVASIONS ? ~pos.pieces( Us)
389
- : Type == CAPTURES ? pos.pieces(~Us)
390
- : ~pos.pieces( ); // QUIETS || QUIET_CHECKS
391
-
392
- if (Type == EVASIONS)
393
- {
394
- if (pos.checkers() & pos.non_sliding_riders())
395
- target = ~pos.pieces(Us);
396
- // Leaper attacks can not be blocked
397
- Square checksq = lsb(pos.checkers());
398
- if (LeaperAttacks[~Us][type_of(pos.piece_on(checksq))][checksq] & pos.square<KING>(Us))
399
- target = pos.checkers();
400
- }
401
-
402
- // Remove inaccessible squares (outside board + wall squares)
403
- target &= pos.board_bb();
404
-
405
- moveList = generate_pawn_moves<Us, Type>(pos, moveList, target);
406
- for (PieceSet ps = pos.piece_types() & ~(piece_set(PAWN) | KING); ps;)
407
- moveList = generate_moves<Us, Type>(pos, moveList, pop_lsb(ps), target);
408
- // generate drops
409
- if (pos.piece_drops() && Type != CAPTURES && (pos.can_drop(Us, ALL_PIECES) || pos.two_boards()))
410
- for (PieceSet ps = pos.piece_types(); ps;)
411
- moveList = generate_drops<Us, Type>(pos, moveList, pop_lsb(ps), target & ~pos.pieces(~Us));
412
-
413
- // Castling with non-king piece
414
- if (!pos.count<KING>(Us) && Type != CAPTURES && pos.can_castle(Us & ANY_CASTLING))
415
- {
416
- Square from = pos.castling_king_square(Us);
417
- for(CastlingRights cr : { Us & KING_SIDE, Us & QUEEN_SIDE } )
418
- if (!pos.castling_impeded(cr) && pos.can_castle(cr))
419
- moveList = make_move_and_gating<CASTLING>(pos, moveList, Us, from, pos.castling_rook_square(cr));
420
- }
421
-
422
- // Special moves
423
- if (pos.cambodian_moves() && pos.gates(Us) && Type != CAPTURES)
424
- {
425
- if (Type != EVASIONS && (pos.pieces(Us, KING) & pos.gates(Us)))
426
- {
427
- Square from = pos.square<KING>(Us);
428
- Bitboard b = PseudoAttacks[WHITE][KNIGHT][from] & rank_bb(rank_of(from + (Us == WHITE ? NORTH : SOUTH)))
429
- & target & ~pos.pieces();
430
- while (b)
431
- moveList = make_move_and_gating<SPECIAL>(pos, moveList, Us, from, pop_lsb(b));
432
- }
433
-
434
- Bitboard b = pos.pieces(Us, FERS) & pos.gates(Us);
435
- while (b)
436
- {
437
- Square from = pop_lsb(b);
438
- Square to = from + 2 * (Us == WHITE ? NORTH : SOUTH);
439
- if (is_ok(to) && (target & to & ~pos.pieces()))
440
- moveList = make_move_and_gating<SPECIAL>(pos, moveList, Us, from, to);
441
- }
442
- }
443
-
444
- // Workaround for passing: Execute a non-move with any piece
445
- if (pos.pass(Us) && !pos.count<KING>(Us) && pos.pieces(Us))
446
- *moveList++ = make<SPECIAL>(lsb(pos.pieces(Us)), lsb(pos.pieces(Us)));
447
-
448
- //if "wall or move", generate walling action with null move
449
- if (pos.wall_or_move())
450
- {
451
- moveList = make_move_and_gating<SPECIAL>(pos, moveList, Us, lsb(pos.pieces(Us)), lsb(pos.pieces(Us)));
452
- }
453
- }
454
-
455
- // King moves
456
- if (pos.count<KING>(Us) && (!Checks || pos.blockers_for_king(~Us) & ksq))
457
- {
458
- Bitboard b = ( (pos.attacks_from(Us, KING, ksq) & pos.pieces())
459
- | (pos.moves_from(Us, KING, ksq) & ~pos.pieces())) & (Type == EVASIONS ? ~pos.pieces(Us) : target);
460
- while (b)
461
- moveList = make_move_and_gating<NORMAL>(pos, moveList, Us, ksq, pop_lsb(b));
462
-
463
- // Passing move by king
464
- if (pos.pass(Us))
465
- *moveList++ = make<SPECIAL>(ksq, ksq);
466
-
467
- if ((Type == QUIETS || Type == NON_EVASIONS) && pos.can_castle(Us & ANY_CASTLING))
468
- for (CastlingRights cr : { Us & KING_SIDE, Us & QUEEN_SIDE } )
469
- if (!pos.castling_impeded(cr) && pos.can_castle(cr))
470
- moveList = make_move_and_gating<CASTLING>(pos, moveList, Us,ksq, pos.castling_rook_square(cr));
471
- }
472
-
473
- return moveList;
474
- }
475
-
476
- } // namespace
477
-
478
-
479
- /// <CAPTURES> Generates all pseudo-legal captures plus queen promotions
480
- /// <QUIETS> Generates all pseudo-legal non-captures and underpromotions
481
- /// <EVASIONS> Generates all pseudo-legal check evasions when the side to move is in check
482
- /// <QUIET_CHECKS> Generates all pseudo-legal non-captures giving check, except castling and promotions
483
- /// <NON_EVASIONS> Generates all pseudo-legal captures and non-captures
484
- ///
485
- /// Returns a pointer to the end of the move list.
486
-
487
- template<GenType Type>
488
- ExtMove* generate(const Position& pos, ExtMove* moveList) {
489
-
490
- static_assert(Type != LEGAL, "Unsupported type in generate()");
491
- assert((Type == EVASIONS) == (bool)pos.checkers());
492
-
493
- Color us = pos.side_to_move();
494
-
495
- return us == WHITE ? generate_all<WHITE, Type>(pos, moveList)
496
- : generate_all<BLACK, Type>(pos, moveList);
497
- }
498
-
499
- // Explicit template instantiations
500
- template ExtMove* generate<CAPTURES>(const Position&, ExtMove*);
501
- template ExtMove* generate<QUIETS>(const Position&, ExtMove*);
502
- template ExtMove* generate<EVASIONS>(const Position&, ExtMove*);
503
- template ExtMove* generate<QUIET_CHECKS>(const Position&, ExtMove*);
504
- template ExtMove* generate<NON_EVASIONS>(const Position&, ExtMove*);
505
-
506
-
507
- /// generate<LEGAL> generates all the legal moves in the given position
508
-
509
- template<>
510
- ExtMove* generate<LEGAL>(const Position& pos, ExtMove* moveList) {
511
-
512
- if (pos.is_immediate_game_end())
513
- return moveList;
514
-
515
- ExtMove* cur = moveList;
516
-
517
- moveList = pos.checkers() ? generate<EVASIONS >(pos, moveList)
518
- : generate<NON_EVASIONS>(pos, moveList);
519
- while (cur != moveList)
520
- if (!pos.legal(*cur) || pos.virtual_drop(*cur))
521
- *cur = (--moveList)->move;
522
- else
523
- ++cur;
524
-
525
- return moveList;
526
- }
527
-
528
- } // namespace Stockfish
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/src/movegen.h DELETED
@@ -1,107 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
4
-
5
- Stockfish is free software: you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation, either version 3 of the License, or
8
- (at your option) any later version.
9
-
10
- Stockfish is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- You should have received a copy of the GNU General Public License
16
- along with this program. If not, see <http://www.gnu.org/licenses/>.
17
- */
18
-
19
- #ifndef MOVEGEN_H_INCLUDED
20
- #define MOVEGEN_H_INCLUDED
21
-
22
- #include <algorithm>
23
-
24
- #include "types.h"
25
-
26
- namespace Stockfish {
27
-
28
- class Position;
29
-
30
- enum GenType {
31
- CAPTURES,
32
- QUIETS,
33
- QUIET_CHECKS,
34
- EVASIONS,
35
- NON_EVASIONS,
36
- LEGAL
37
- };
38
-
39
- struct ExtMove {
40
- Move move;
41
- int value;
42
-
43
- operator Move() const { return move; }
44
- void operator=(Move m) { move = m; }
45
-
46
- // Inhibit unwanted implicit conversions to Move
47
- // with an ambiguity that yields to a compile error.
48
- operator float() const = delete;
49
- };
50
-
51
- inline bool operator<(const ExtMove& f, const ExtMove& s) {
52
- return f.value < s.value;
53
- }
54
-
55
- template<GenType>
56
- ExtMove* generate(const Position& pos, ExtMove* moveList);
57
-
58
- constexpr size_t moveListSize = sizeof(ExtMove) * MAX_MOVES;
59
-
60
- /// The MoveList struct is a simple wrapper around generate(). It sometimes comes
61
- /// in handy to use this class instead of the low level generate() function.
62
- template<GenType T>
63
- struct MoveList {
64
-
65
-
66
- #ifdef USE_HEAP_INSTEAD_OF_STACK_FOR_MOVE_LIST
67
- explicit MoveList(const Position& pos)
68
- {
69
- this->moveList = (ExtMove*)malloc(moveListSize);
70
- if (this->moveList == 0)
71
- {
72
- printf("Error: Failed to allocate memory in heap.");
73
- exit(1);
74
- }
75
- this->last = generate<T>(pos, this->moveList);
76
- }
77
-
78
- ~MoveList()
79
- {
80
- free(this->moveList);
81
- }
82
- #else
83
- explicit MoveList(const Position& pos) : last(generate<T>(pos, moveList))
84
- {
85
- ;
86
- }
87
- #endif
88
-
89
- const ExtMove* begin() const { return moveList; }
90
- const ExtMove* end() const { return last; }
91
- size_t size() const { return last - moveList; }
92
- bool contains(Move move) const {
93
- return std::find(begin(), end(), move) != end();
94
- }
95
-
96
- private:
97
- ExtMove* last;
98
- #ifdef USE_HEAP_INSTEAD_OF_STACK_FOR_MOVE_LIST
99
- ExtMove* moveList = 0;
100
- #else
101
- ExtMove moveList[MAX_MOVES];
102
- #endif
103
- };
104
-
105
- } // namespace Stockfish
106
-
107
- #endif // #ifndef MOVEGEN_H_INCLUDED
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/src/movepick.cpp DELETED
@@ -1,279 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
4
-
5
- Stockfish is free software: you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation, either version 3 of the License, or
8
- (at your option) any later version.
9
-
10
- Stockfish is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- You should have received a copy of the GNU General Public License
16
- along with this program. If not, see <http://www.gnu.org/licenses/>.
17
- */
18
-
19
- #include <cassert>
20
-
21
- #include "movepick.h"
22
-
23
- namespace Stockfish {
24
-
25
- // Since continuation history grows quadratically with the number of piece types,
26
- // we need to reserve a limited number of slots and map piece types to these slots
27
- // in order to reduce memory consumption to a reasonable level.
28
- int history_slot(Piece pc) {
29
- return pc == NO_PIECE ? 0 : (type_of(pc) == KING ? PIECE_SLOTS - 1 : type_of(pc) % (PIECE_SLOTS - 1)) + color_of(pc) * PIECE_SLOTS;
30
- }
31
-
32
- namespace {
33
-
34
- enum Stages {
35
- MAIN_TT, CAPTURE_INIT, GOOD_CAPTURE, REFUTATION, QUIET_INIT, QUIET, BAD_CAPTURE,
36
- EVASION_TT, EVASION_INIT, EVASION,
37
- PROBCUT_TT, PROBCUT_INIT, PROBCUT,
38
- QSEARCH_TT, QCAPTURE_INIT, QCAPTURE, QCHECK_INIT, QCHECK
39
- };
40
-
41
- // partial_insertion_sort() sorts moves in descending order up to and including
42
- // a given limit. The order of moves smaller than the limit is left unspecified.
43
- void partial_insertion_sort(ExtMove* begin, ExtMove* end, int limit) {
44
-
45
- for (ExtMove *sortedEnd = begin, *p = begin + 1; p < end; ++p)
46
- if (p->value >= limit)
47
- {
48
- ExtMove tmp = *p, *q;
49
- *p = *++sortedEnd;
50
- for (q = sortedEnd; q != begin && *(q - 1) < tmp; --q)
51
- *q = *(q - 1);
52
- *q = tmp;
53
- }
54
- }
55
-
56
- } // namespace
57
-
58
-
59
- /// Constructors of the MovePicker class. As arguments we pass information
60
- /// to help it to return the (presumably) good moves first, to decide which
61
- /// moves to return (in the quiescence search, for instance, we only want to
62
- /// search captures, promotions, and some checks) and how important good move
63
- /// ordering is at the current node.
64
-
65
- /// MovePicker constructor for the main search
66
- MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHistory* mh, const GateHistory* dh, const LowPlyHistory* lp,
67
- const CapturePieceToHistory* cph, const PieceToHistory** ch, Move cm, const Move* killers, int pl)
68
- : pos(p), mainHistory(mh), gateHistory(dh), lowPlyHistory(lp), captureHistory(cph), continuationHistory(ch),
69
- ttMove(ttm), refutations{{killers[0], 0}, {killers[1], 0}, {cm, 0}}, depth(d), ply(pl) {
70
-
71
- assert(d > 0);
72
-
73
- stage = (pos.checkers() ? EVASION_TT : MAIN_TT) +
74
- !(ttm && pos.pseudo_legal(ttm));
75
- }
76
-
77
- /// MovePicker constructor for quiescence search
78
- MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHistory* mh, const GateHistory* dh,
79
- const CapturePieceToHistory* cph, const PieceToHistory** ch, Square rs)
80
- : pos(p), mainHistory(mh), gateHistory(dh), captureHistory(cph), continuationHistory(ch), ttMove(ttm), recaptureSquare(rs), depth(d) {
81
-
82
- assert(d <= 0);
83
-
84
- stage = (pos.checkers() ? EVASION_TT : QSEARCH_TT) +
85
- !( ttm
86
- && (pos.checkers() || depth > DEPTH_QS_RECAPTURES || to_sq(ttm) == recaptureSquare)
87
- && pos.pseudo_legal(ttm));
88
- }
89
-
90
- /// MovePicker constructor for ProbCut: we generate captures with SEE greater
91
- /// than or equal to the given threshold.
92
- MovePicker::MovePicker(const Position& p, Move ttm, Value th, const GateHistory* dh, const CapturePieceToHistory* cph)
93
- : pos(p), gateHistory(dh), captureHistory(cph), ttMove(ttm), threshold(th) {
94
-
95
- assert(!pos.checkers());
96
-
97
- stage = PROBCUT_TT + !(ttm && pos.capture(ttm)
98
- && pos.pseudo_legal(ttm)
99
- && pos.see_ge(ttm, threshold));
100
- }
101
-
102
- /// MovePicker::score() assigns a numerical value to each move in a list, used
103
- /// for sorting. Captures are ordered by Most Valuable Victim (MVV), preferring
104
- /// captures with a good history. Quiets moves are ordered using the histories.
105
- template<GenType Type>
106
- void MovePicker::score() {
107
-
108
- static_assert(Type == CAPTURES || Type == QUIETS || Type == EVASIONS, "Wrong type");
109
-
110
- for (auto& m : *this)
111
- if constexpr (Type == CAPTURES)
112
- m.value = int(PieceValue[MG][pos.piece_on(to_sq(m))]) * 6
113
- + (*gateHistory)[pos.side_to_move()][gating_square(m)]
114
- + (*captureHistory)[pos.moved_piece(m)][to_sq(m)][type_of(pos.piece_on(to_sq(m)))];
115
-
116
- else if constexpr (Type == QUIETS)
117
- m.value = (*mainHistory)[pos.side_to_move()][from_to(m)]
118
- + (*gateHistory)[pos.side_to_move()][gating_square(m)]
119
- + 2 * (*continuationHistory[0])[history_slot(pos.moved_piece(m))][to_sq(m)]
120
- + (*continuationHistory[1])[history_slot(pos.moved_piece(m))][to_sq(m)]
121
- + (*continuationHistory[3])[history_slot(pos.moved_piece(m))][to_sq(m)]
122
- + (*continuationHistory[5])[history_slot(pos.moved_piece(m))][to_sq(m)]
123
- + (ply < MAX_LPH ? std::min(4, depth / 3) * (*lowPlyHistory)[ply][from_to(m)] : 0);
124
-
125
- else // Type == EVASIONS
126
- {
127
- if (pos.capture(m))
128
- m.value = PieceValue[MG][pos.piece_on(to_sq(m))]
129
- - Value(type_of(pos.moved_piece(m)));
130
- else
131
- m.value = (*mainHistory)[pos.side_to_move()][from_to(m)]
132
- + 2 * (*continuationHistory[0])[history_slot(pos.moved_piece(m))][to_sq(m)]
133
- - (1 << 28);
134
- }
135
- }
136
-
137
- /// MovePicker::select() returns the next move satisfying a predicate function.
138
- /// It never returns the TT move.
139
- template<MovePicker::PickType T, typename Pred>
140
- Move MovePicker::select(Pred filter) {
141
-
142
- while (cur < endMoves)
143
- {
144
- if (T == Best)
145
- std::swap(*cur, *std::max_element(cur, endMoves));
146
-
147
- if (*cur != ttMove && filter())
148
- return *cur++;
149
-
150
- cur++;
151
- }
152
- return MOVE_NONE;
153
- }
154
-
155
- /// MovePicker::next_move() is the most important method of the MovePicker class. It
156
- /// returns a new pseudo-legal move every time it is called until there are no more
157
- /// moves left, picking the move with the highest score from a list of generated moves.
158
- Move MovePicker::next_move(bool skipQuiets) {
159
-
160
- top:
161
- switch (stage) {
162
-
163
- case MAIN_TT:
164
- case EVASION_TT:
165
- case QSEARCH_TT:
166
- case PROBCUT_TT:
167
- ++stage;
168
- assert(pos.legal(ttMove) == MoveList<LEGAL>(pos).contains(ttMove) || pos.virtual_drop(ttMove));
169
- return ttMove;
170
-
171
- case CAPTURE_INIT:
172
- case PROBCUT_INIT:
173
- case QCAPTURE_INIT:
174
- cur = endBadCaptures = moves;
175
- endMoves = generate<CAPTURES>(pos, cur);
176
-
177
- score<CAPTURES>();
178
- ++stage;
179
- goto top;
180
-
181
- case GOOD_CAPTURE:
182
- if (select<Best>([&](){
183
- return pos.see_ge(*cur, Value(-69 * cur->value / 1024 - 500 * (pos.captures_to_hand() && pos.gives_check(*cur))))?
184
- // Move losing capture to endBadCaptures to be tried later
185
- true : (*endBadCaptures++ = *cur, false); }))
186
- return *(cur - 1);
187
-
188
- // Prepare the pointers to loop over the refutations array
189
- cur = std::begin(refutations);
190
- endMoves = std::end(refutations);
191
-
192
- // If the countermove is the same as a killer, skip it
193
- if ( refutations[0].move == refutations[2].move
194
- || refutations[1].move == refutations[2].move)
195
- --endMoves;
196
-
197
- ++stage;
198
- [[fallthrough]];
199
-
200
- case REFUTATION:
201
- if (select<Next>([&](){ return *cur != MOVE_NONE
202
- && !pos.capture(*cur)
203
- && pos.pseudo_legal(*cur); }))
204
- return *(cur - 1);
205
- ++stage;
206
- [[fallthrough]];
207
-
208
- case QUIET_INIT:
209
- if (!skipQuiets && !(pos.must_capture() && pos.has_capture()))
210
- {
211
- cur = endBadCaptures;
212
- endMoves = generate<QUIETS>(pos, cur);
213
-
214
- score<QUIETS>();
215
- partial_insertion_sort(cur, endMoves, -3000 * depth);
216
- }
217
-
218
- ++stage;
219
- [[fallthrough]];
220
-
221
- case QUIET:
222
- if ( !skipQuiets
223
- && select<Next>([&](){return *cur != refutations[0].move
224
- && *cur != refutations[1].move
225
- && *cur != refutations[2].move;}))
226
- return *(cur - 1);
227
-
228
- // Prepare the pointers to loop over the bad captures
229
- cur = moves;
230
- endMoves = endBadCaptures;
231
-
232
- ++stage;
233
- [[fallthrough]];
234
-
235
- case BAD_CAPTURE:
236
- return select<Next>([](){ return true; });
237
-
238
- case EVASION_INIT:
239
- cur = moves;
240
- endMoves = generate<EVASIONS>(pos, cur);
241
-
242
- score<EVASIONS>();
243
- ++stage;
244
- [[fallthrough]];
245
-
246
- case EVASION:
247
- return select<Best>([](){ return true; });
248
-
249
- case PROBCUT:
250
- return select<Best>([&](){ return pos.see_ge(*cur, threshold); });
251
-
252
- case QCAPTURE:
253
- if (select<Best>([&](){ return depth > DEPTH_QS_RECAPTURES
254
- || to_sq(*cur) == recaptureSquare; }))
255
- return *(cur - 1);
256
-
257
- // If we did not find any move and we do not try checks, we have finished
258
- if (depth != DEPTH_QS_CHECKS)
259
- return MOVE_NONE;
260
-
261
- ++stage;
262
- [[fallthrough]];
263
-
264
- case QCHECK_INIT:
265
- cur = moves;
266
- endMoves = generate<QUIET_CHECKS>(pos, cur);
267
-
268
- ++stage;
269
- [[fallthrough]];
270
-
271
- case QCHECK:
272
- return select<Next>([](){ return true; });
273
- }
274
-
275
- assert(false);
276
- return MOVE_NONE; // Silence warning
277
- }
278
-
279
- } // namespace Stockfish
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/src/movepick.h DELETED
@@ -1,169 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
4
-
5
- Stockfish is free software: you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation, either version 3 of the License, or
8
- (at your option) any later version.
9
-
10
- Stockfish is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- You should have received a copy of the GNU General Public License
16
- along with this program. If not, see <http://www.gnu.org/licenses/>.
17
- */
18
-
19
- #ifndef MOVEPICK_H_INCLUDED
20
- #define MOVEPICK_H_INCLUDED
21
-
22
- #include <array>
23
- #include <limits>
24
- #include <type_traits>
25
-
26
- #include "movegen.h"
27
- #include "position.h"
28
- #include "types.h"
29
-
30
- namespace Stockfish {
31
-
32
- /// StatsEntry stores the stat table value. It is usually a number but could
33
- /// be a move or even a nested history. We use a class instead of naked value
34
- /// to directly call history update operator<<() on the entry so to use stats
35
- /// tables at caller sites as simple multi-dim arrays.
36
- template<typename T, int D>
37
- class StatsEntry {
38
-
39
- T entry;
40
-
41
- public:
42
- void operator=(const T& v) { entry = v; }
43
- T* operator&() { return &entry; }
44
- T* operator->() { return &entry; }
45
- operator const T&() const { return entry; }
46
-
47
- void operator<<(int bonus) {
48
- assert(abs(bonus) <= D); // Ensure range is [-D, D]
49
- static_assert(D <= std::numeric_limits<T>::max(), "D overflows T");
50
-
51
- entry += bonus - entry * abs(bonus) / D;
52
-
53
- assert(abs(entry) <= D);
54
- }
55
- };
56
-
57
- /// Stats is a generic N-dimensional array used to store various statistics.
58
- /// The first template parameter T is the base type of the array, the second
59
- /// template parameter D limits the range of updates in [-D, D] when we update
60
- /// values with the << operator, while the last parameters (Size and Sizes)
61
- /// encode the dimensions of the array.
62
- template <typename T, int D, int Size, int... Sizes>
63
- struct Stats : public std::array<Stats<T, D, Sizes...>, Size>
64
- {
65
- typedef Stats<T, D, Size, Sizes...> stats;
66
-
67
- void fill(const T& v) {
68
-
69
- // For standard-layout 'this' points to first struct member
70
- assert(std::is_standard_layout<stats>::value);
71
-
72
- typedef StatsEntry<T, D> entry;
73
- entry* p = reinterpret_cast<entry*>(this);
74
- std::fill(p, p + sizeof(*this) / sizeof(entry), v);
75
- }
76
- };
77
-
78
- template <typename T, int D, int Size>
79
- struct Stats<T, D, Size> : public std::array<StatsEntry<T, D>, Size> {};
80
-
81
- /// In stats table, D=0 means that the template parameter is not used
82
- enum StatsParams { NOT_USED = 0, PIECE_SLOTS = 8 };
83
- enum StatsType { NoCaptures, Captures };
84
-
85
- /// ButterflyHistory records how often quiet moves have been successful or
86
- /// unsuccessful during the current search, and is used for reduction and move
87
- /// ordering decisions. It uses 2 tables (one for each color) indexed by
88
- /// the move's from and to squares, see www.chessprogramming.org/Butterfly_Boards
89
- typedef Stats<int16_t, 13365, COLOR_NB, int(SQUARE_NB + 1) * int(1 << SQUARE_BITS)> ButterflyHistory;
90
-
91
- typedef Stats<int16_t, 13365, COLOR_NB, SQUARE_NB> GateHistory;
92
-
93
- /// At higher depths LowPlyHistory records successful quiet moves near the root
94
- /// and quiet moves which are/were in the PV (ttPv). It is cleared with each new
95
- /// search and filled during iterative deepening.
96
- constexpr int MAX_LPH = 4;
97
- typedef Stats<int16_t, 10692, MAX_LPH, int(SQUARE_NB + 1) * int(1 << SQUARE_BITS)> LowPlyHistory;
98
-
99
- /// CounterMoveHistory stores counter moves indexed by [piece][to] of the previous
100
- /// move, see www.chessprogramming.org/Countermove_Heuristic
101
- typedef Stats<Move, NOT_USED, PIECE_NB, SQUARE_NB> CounterMoveHistory;
102
-
103
- /// CapturePieceToHistory is addressed by a move's [piece][to][captured piece type]
104
- typedef Stats<int16_t, 10692, PIECE_NB, SQUARE_NB, PIECE_TYPE_NB> CapturePieceToHistory;
105
-
106
- /// PieceToHistory is like ButterflyHistory but is addressed by a move's [piece][to]
107
- typedef Stats<int16_t, 29952, 2 * PIECE_SLOTS, SQUARE_NB> PieceToHistory;
108
-
109
- /// ContinuationHistory is the combined history of a given pair of moves, usually
110
- /// the current one given a previous one. The nested history table is based on
111
- /// PieceToHistory instead of ButterflyBoards.
112
- typedef Stats<PieceToHistory, NOT_USED, 2 * PIECE_SLOTS, SQUARE_NB> ContinuationHistory;
113
-
114
- int history_slot(Piece pc);
115
-
116
- /// MovePicker class is used to pick one pseudo-legal move at a time from the
117
- /// current position. The most important method is next_move(), which returns a
118
- /// new pseudo-legal move each time it is called, until there are no moves left,
119
- /// when MOVE_NONE is returned. In order to improve the efficiency of the
120
- /// alpha-beta algorithm, MovePicker attempts to return the moves which are most
121
- /// likely to get a cut-off first.
122
- class MovePicker {
123
-
124
- enum PickType { Next, Best };
125
-
126
- public:
127
- MovePicker(const MovePicker&) = delete;
128
- MovePicker& operator=(const MovePicker&) = delete;
129
- MovePicker(const Position&, Move, Value, const GateHistory*, const CapturePieceToHistory*);
130
- MovePicker(const Position&, Move, Depth, const ButterflyHistory*,
131
- const GateHistory*,
132
- const CapturePieceToHistory*,
133
- const PieceToHistory**,
134
- Square);
135
- MovePicker(const Position&, Move, Depth, const ButterflyHistory*,
136
- const GateHistory*,
137
- const LowPlyHistory*,
138
- const CapturePieceToHistory*,
139
- const PieceToHistory**,
140
- Move,
141
- const Move*,
142
- int);
143
- Move next_move(bool skipQuiets = false);
144
-
145
- private:
146
- template<PickType T, typename Pred> Move select(Pred);
147
- template<GenType> void score();
148
- ExtMove* begin() { return cur; }
149
- ExtMove* end() { return endMoves; }
150
-
151
- const Position& pos;
152
- const ButterflyHistory* mainHistory;
153
- const GateHistory* gateHistory;
154
- const LowPlyHistory* lowPlyHistory;
155
- const CapturePieceToHistory* captureHistory;
156
- const PieceToHistory** continuationHistory;
157
- Move ttMove;
158
- ExtMove refutations[3], *cur, *endMoves, *endBadCaptures;
159
- int stage;
160
- Square recaptureSquare;
161
- Value threshold;
162
- Depth depth;
163
- int ply;
164
- ExtMove moves[MAX_MOVES];
165
- };
166
-
167
- } // namespace Stockfish
168
-
169
- #endif // #ifndef MOVEPICK_H_INCLUDED
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/src/nnue/evaluate_nnue.cpp DELETED
@@ -1,443 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
4
-
5
- Stockfish is free software: you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation, either version 3 of the License, or
8
- (at your option) any later version.
9
-
10
- Stockfish is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- You should have received a copy of the GNU General Public License
16
- along with this program. If not, see <http://www.gnu.org/licenses/>.
17
- */
18
-
19
- // Code for calculating NNUE evaluation function
20
-
21
- #include <iostream>
22
- #include <set>
23
- #include <sstream>
24
- #include <iomanip>
25
- #include <fstream>
26
-
27
- #include "../evaluate.h"
28
- #include "../position.h"
29
- #include "../misc.h"
30
- #include "../uci.h"
31
- #include "../types.h"
32
-
33
- #include "evaluate_nnue.h"
34
-
35
- namespace Stockfish::Eval::NNUE {
36
-
37
- // Input feature converter
38
- LargePagePtr<FeatureTransformer> featureTransformer;
39
-
40
- // Evaluation function
41
- AlignedPtr<Network> network[LayerStacks];
42
-
43
- // Evaluation function file name
44
- std::string fileName;
45
- std::string netDescription;
46
-
47
- namespace Detail {
48
-
49
- // Initialize the evaluation function parameters
50
- template <typename T>
51
- void initialize(AlignedPtr<T>& pointer) {
52
-
53
- pointer.reset(reinterpret_cast<T*>(std_aligned_alloc(alignof(T), sizeof(T))));
54
- std::memset(pointer.get(), 0, sizeof(T));
55
- }
56
-
57
- template <typename T>
58
- void initialize(LargePagePtr<T>& pointer) {
59
-
60
- static_assert(alignof(T) <= 4096, "aligned_large_pages_alloc() may fail for such a big alignment requirement of T");
61
- pointer.reset(reinterpret_cast<T*>(aligned_large_pages_alloc(sizeof(T))));
62
- std::memset(pointer.get(), 0, sizeof(T));
63
- }
64
-
65
- // Read evaluation function parameters
66
- template <typename T>
67
- bool read_parameters(std::istream& stream, T& reference) {
68
-
69
- std::uint32_t header;
70
- header = read_little_endian<std::uint32_t>(stream);
71
- if (!stream || header != T::get_hash_value()) return false;
72
- return reference.read_parameters(stream);
73
- }
74
-
75
- // Write evaluation function parameters
76
- template <typename T>
77
- bool write_parameters(std::ostream& stream, const T& reference) {
78
-
79
- write_little_endian<std::uint32_t>(stream, T::get_hash_value());
80
- return reference.write_parameters(stream);
81
- }
82
-
83
- } // namespace Detail
84
-
85
- // Initialize the evaluation function parameters
86
- void initialize() {
87
-
88
- Detail::initialize(featureTransformer);
89
- for (std::size_t i = 0; i < LayerStacks; ++i)
90
- Detail::initialize(network[i]);
91
- }
92
-
93
- // Read network header
94
- bool read_header(std::istream& stream, std::uint32_t* hashValue, std::string* desc)
95
- {
96
- std::uint32_t version, size;
97
-
98
- version = read_little_endian<std::uint32_t>(stream);
99
- *hashValue = read_little_endian<std::uint32_t>(stream);
100
- size = read_little_endian<std::uint32_t>(stream);
101
- if (!stream || version != Version) return false;
102
- desc->resize(size);
103
- stream.read(&(*desc)[0], size);
104
- return !stream.fail();
105
- }
106
-
107
- // Write network header
108
- bool write_header(std::ostream& stream, std::uint32_t hashValue, const std::string& desc)
109
- {
110
- write_little_endian<std::uint32_t>(stream, Version);
111
- write_little_endian<std::uint32_t>(stream, hashValue);
112
- write_little_endian<std::uint32_t>(stream, desc.size());
113
- stream.write(&desc[0], desc.size());
114
- return !stream.fail();
115
- }
116
-
117
- // Read network parameters
118
- bool read_parameters(std::istream& stream) {
119
-
120
- std::uint32_t hashValue;
121
- if (!read_header(stream, &hashValue, &netDescription)) return false;
122
- if (hashValue != HashValue) return false;
123
- if (!Detail::read_parameters(stream, *featureTransformer)) return false;
124
- for (std::size_t i = 0; i < LayerStacks; ++i)
125
- if (!Detail::read_parameters(stream, *(network[i]))) return false;
126
- return stream && stream.peek() == std::ios::traits_type::eof();
127
- }
128
-
129
- // Write network parameters
130
- bool write_parameters(std::ostream& stream) {
131
-
132
- if (!write_header(stream, HashValue, netDescription)) return false;
133
- if (!Detail::write_parameters(stream, *featureTransformer)) return false;
134
- for (std::size_t i = 0; i < LayerStacks; ++i)
135
- if (!Detail::write_parameters(stream, *(network[i]))) return false;
136
- return (bool)stream;
137
- }
138
-
139
- // Evaluation function. Perform differential calculation.
140
- Value evaluate(const Position& pos, bool adjusted) {
141
-
142
- // We manually align the arrays on the stack because with gcc < 9.3
143
- // overaligning stack variables with alignas() doesn't work correctly.
144
-
145
- constexpr uint64_t alignment = CacheLineSize;
146
-
147
- #if defined(ALIGNAS_ON_STACK_VARIABLES_BROKEN)
148
- TransformedFeatureType transformedFeaturesUnaligned[
149
- FeatureTransformer::BufferSize + alignment / sizeof(TransformedFeatureType)];
150
- char bufferUnaligned[Network::BufferSize + alignment];
151
-
152
- auto* transformedFeatures = align_ptr_up<alignment>(&transformedFeaturesUnaligned[0]);
153
- auto* buffer = align_ptr_up<alignment>(&bufferUnaligned[0]);
154
- #else
155
- alignas(alignment)
156
- TransformedFeatureType transformedFeatures[FeatureTransformer::BufferSize];
157
- alignas(alignment) char buffer[Network::BufferSize];
158
- #endif
159
-
160
- ASSERT_ALIGNED(transformedFeatures, alignment);
161
- ASSERT_ALIGNED(buffer, alignment);
162
-
163
- const std::size_t bucket = std::min((pos.count<ALL_PIECES>() - 1) * 8 / currentNnueVariant->nnueMaxPieces, 7);
164
- const auto psqt = featureTransformer->transform(pos, transformedFeatures, bucket);
165
- const auto output = network[bucket]->propagate(transformedFeatures, buffer);
166
-
167
- int materialist = psqt;
168
- int positional = output[0];
169
-
170
- int delta_npm = abs(pos.non_pawn_material(WHITE) - pos.non_pawn_material(BLACK));
171
- int entertainment = (adjusted && delta_npm <= BishopValueMg - KnightValueMg ? 7 : 0);
172
-
173
- int A = 128 - entertainment;
174
- int B = 128 + entertainment;
175
-
176
- int sum = (A * materialist + B * positional) / 128;
177
-
178
- return static_cast<Value>( sum / OutputScale );
179
- }
180
-
181
- struct NnueEvalTrace {
182
- static_assert(LayerStacks == PSQTBuckets);
183
-
184
- Value psqt[LayerStacks];
185
- Value positional[LayerStacks];
186
- std::size_t correctBucket;
187
- };
188
-
189
- static NnueEvalTrace trace_evaluate(const Position& pos) {
190
-
191
- // We manually align the arrays on the stack because with gcc < 9.3
192
- // overaligning stack variables with alignas() doesn't work correctly.
193
-
194
- constexpr uint64_t alignment = CacheLineSize;
195
-
196
- #if defined(ALIGNAS_ON_STACK_VARIABLES_BROKEN)
197
- TransformedFeatureType transformedFeaturesUnaligned[
198
- FeatureTransformer::BufferSize + alignment / sizeof(TransformedFeatureType)];
199
- char bufferUnaligned[Network::BufferSize + alignment];
200
-
201
- auto* transformedFeatures = align_ptr_up<alignment>(&transformedFeaturesUnaligned[0]);
202
- auto* buffer = align_ptr_up<alignment>(&bufferUnaligned[0]);
203
- #else
204
- alignas(alignment)
205
- TransformedFeatureType transformedFeatures[FeatureTransformer::BufferSize];
206
- alignas(alignment) char buffer[Network::BufferSize];
207
- #endif
208
-
209
- ASSERT_ALIGNED(transformedFeatures, alignment);
210
- ASSERT_ALIGNED(buffer, alignment);
211
-
212
- NnueEvalTrace t{};
213
- t.correctBucket = std::min((pos.count<ALL_PIECES>() - 1) * 8 / currentNnueVariant->nnueMaxPieces, 7);
214
- for (std::size_t bucket = 0; bucket < LayerStacks; ++bucket) {
215
- const auto psqt = featureTransformer->transform(pos, transformedFeatures, bucket);
216
- const auto output = network[bucket]->propagate(transformedFeatures, buffer);
217
-
218
- int materialist = psqt;
219
- int positional = output[0];
220
-
221
- t.psqt[bucket] = static_cast<Value>( materialist / OutputScale );
222
- t.positional[bucket] = static_cast<Value>( positional / OutputScale );
223
- }
224
-
225
- return t;
226
- }
227
-
228
- // Requires the buffer to have capacity for at least 5 values
229
- static void format_cp_compact(Value v, char* buffer) {
230
-
231
- buffer[0] = (v < 0 ? '-' : v > 0 ? '+' : ' ');
232
-
233
- int cp = std::abs(100 * v / PawnValueEg);
234
-
235
- if (cp >= 10000)
236
- {
237
- buffer[1] = '0' + cp / 10000; cp %= 10000;
238
- buffer[2] = '0' + cp / 1000; cp %= 1000;
239
- buffer[3] = '0' + cp / 100; cp %= 100;
240
- buffer[4] = ' ';
241
- }
242
- else if (cp >= 1000)
243
- {
244
- buffer[1] = '0' + cp / 1000; cp %= 1000;
245
- buffer[2] = '0' + cp / 100; cp %= 100;
246
- buffer[3] = '.';
247
- buffer[4] = '0' + cp / 10;
248
- }
249
- else
250
- {
251
- buffer[1] = '0' + cp / 100; cp %= 100;
252
- buffer[2] = '.';
253
- buffer[3] = '0' + cp / 10; cp %= 10;
254
- buffer[4] = '0' + cp / 1;
255
- }
256
- }
257
-
258
- // Requires the buffer to have capacity for at least 7 values
259
- static void format_cp_aligned_dot(Value v, char* buffer) {
260
- buffer[0] = (v < 0 ? '-' : v > 0 ? '+' : ' ');
261
-
262
- int cp = std::abs(100 * v / PawnValueEg);
263
-
264
- if (cp >= 10000)
265
- {
266
- buffer[1] = '0' + cp / 10000; cp %= 10000;
267
- buffer[2] = '0' + cp / 1000; cp %= 1000;
268
- buffer[3] = '0' + cp / 100; cp %= 100;
269
- buffer[4] = '.';
270
- buffer[5] = '0' + cp / 10; cp %= 10;
271
- buffer[6] = '0' + cp;
272
- }
273
- else if (cp >= 1000)
274
- {
275
- buffer[1] = ' ';
276
- buffer[2] = '0' + cp / 1000; cp %= 1000;
277
- buffer[3] = '0' + cp / 100; cp %= 100;
278
- buffer[4] = '.';
279
- buffer[5] = '0' + cp / 10; cp %= 10;
280
- buffer[6] = '0' + cp;
281
- }
282
- else
283
- {
284
- buffer[1] = ' ';
285
- buffer[2] = ' ';
286
- buffer[3] = '0' + cp / 100; cp %= 100;
287
- buffer[4] = '.';
288
- buffer[5] = '0' + cp / 10; cp %= 10;
289
- buffer[6] = '0' + cp / 1;
290
- }
291
- }
292
-
293
-
294
- // trace() returns a string with the value of each piece on a board,
295
- // and a table for (PSQT, Layers) values bucket by bucket.
296
-
297
- std::string trace(Position& pos) {
298
-
299
- std::stringstream ss;
300
-
301
- char board[3*RANK_NB+1][8*FILE_NB+2];
302
- std::memset(board, ' ', sizeof(board));
303
- for (int row = 0; row < 3*pos.ranks()+1; ++row)
304
- board[row][8*FILE_NB+1] = '\0';
305
-
306
- // A lambda to output one box of the board
307
- auto writeSquare = [&board, &pos](File file, Rank rank, Piece pc, Value value) {
308
-
309
- const int x = ((int)file) * 8;
310
- const int y = (pos.max_rank() - (int)rank) * 3;
311
- for (int i = 1; i < 8; ++i)
312
- board[y][x+i] = board[y+3][x+i] = '-';
313
- for (int i = 1; i < 3; ++i)
314
- board[y+i][x] = board[y+i][x+8] = '|';
315
- board[y][x] = board[y][x+8] = board[y+3][x+8] = board[y+3][x] = '+';
316
- if (pc != NO_PIECE)
317
- board[y+1][x+4] = pos.piece_to_char()[pc];
318
- if (value != VALUE_NONE)
319
- format_cp_compact(value, &board[y+2][x+2]);
320
- };
321
-
322
- // We estimate the value of each piece by doing a differential evaluation from
323
- // the current base eval, simulating the removal of the piece from its square.
324
- Value base = evaluate(pos);
325
- base = pos.side_to_move() == WHITE ? base : -base;
326
-
327
- for (File f = FILE_A; f <= pos.max_file(); ++f)
328
- for (Rank r = RANK_1; r <= pos.max_rank(); ++r)
329
- {
330
- Square sq = make_square(f, r);
331
- Piece pc = pos.piece_on(sq);
332
- Piece unpromotedPc = pos.unpromoted_piece_on(sq);
333
- bool isPromoted = pos.is_promoted(sq);
334
- Value v = VALUE_NONE;
335
-
336
- if (pc != NO_PIECE && type_of(pc) != pos.nnue_king())
337
- {
338
- auto st = pos.state();
339
-
340
- pos.remove_piece(sq);
341
- st->accumulator.computed[WHITE] = false;
342
- st->accumulator.computed[BLACK] = false;
343
-
344
- Value eval = evaluate(pos);
345
- eval = pos.side_to_move() == WHITE ? eval : -eval;
346
- v = base - eval;
347
-
348
- pos.put_piece(pc, sq, isPromoted, unpromotedPc);
349
- st->accumulator.computed[WHITE] = false;
350
- st->accumulator.computed[BLACK] = false;
351
- }
352
-
353
- writeSquare(f, r, pc, v);
354
- }
355
-
356
- ss << " NNUE derived piece values:\n";
357
- for (int row = 0; row < 3*pos.ranks()+1; ++row)
358
- ss << board[row] << '\n';
359
- ss << '\n';
360
-
361
- auto t = trace_evaluate(pos);
362
-
363
- ss << " NNUE network contributions "
364
- << (pos.side_to_move() == WHITE ? "(White to move)" : "(Black to move)") << std::endl
365
- << "+------------+------------+------------+------------+\n"
366
- << "| Bucket | Material | Positional | Total |\n"
367
- << "| | (PSQT) | (Layers) | |\n"
368
- << "+------------+------------+------------+------------+\n";
369
-
370
- for (std::size_t bucket = 0; bucket < LayerStacks; ++bucket)
371
- {
372
- char buffer[3][8];
373
- std::memset(buffer, '\0', sizeof(buffer));
374
-
375
- format_cp_aligned_dot(t.psqt[bucket], buffer[0]);
376
- format_cp_aligned_dot(t.positional[bucket], buffer[1]);
377
- format_cp_aligned_dot(t.psqt[bucket] + t.positional[bucket], buffer[2]);
378
-
379
- ss << "| " << bucket << " "
380
- << " | " << buffer[0] << " "
381
- << " | " << buffer[1] << " "
382
- << " | " << buffer[2] << " "
383
- << " |";
384
- if (bucket == t.correctBucket)
385
- ss << " <-- this bucket is used";
386
- ss << '\n';
387
- }
388
-
389
- ss << "+------------+------------+------------+------------+\n";
390
-
391
- return ss.str();
392
- }
393
-
394
-
395
- // Load eval, from a file stream or a memory stream
396
- bool load_eval(std::string name, std::istream& stream) {
397
-
398
- initialize();
399
- fileName = name;
400
- return read_parameters(stream);
401
- }
402
-
403
- // Save eval, to a file stream or a memory stream
404
- bool save_eval(std::ostream& stream) {
405
-
406
- if (fileName.empty())
407
- return false;
408
-
409
- return write_parameters(stream);
410
- }
411
-
412
- /// Save eval, to a file given by its name
413
- bool save_eval(const std::optional<std::string>& filename) {
414
-
415
- std::string actualFilename;
416
- std::string msg;
417
-
418
- if (filename.has_value())
419
- actualFilename = filename.value();
420
- else
421
- {
422
- if (eval_file_loaded != EvalFileDefaultName)
423
- {
424
- msg = "Failed to export a net. A non-embedded net can only be saved if the filename is specified";
425
-
426
- sync_cout << msg << sync_endl;
427
- return false;
428
- }
429
- actualFilename = EvalFileDefaultName;
430
- }
431
-
432
- std::ofstream stream(actualFilename, std::ios_base::binary);
433
- bool saved = save_eval(stream);
434
-
435
- msg = saved ? "Network saved successfully to " + actualFilename
436
- : "Failed to export a net";
437
-
438
- sync_cout << msg << sync_endl;
439
- return saved;
440
- }
441
-
442
-
443
- } // namespace Stockfish::Eval::NNUE
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/src/nnue/evaluate_nnue.h DELETED
@@ -1,59 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
4
-
5
- Stockfish is free software: you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation, either version 3 of the License, or
8
- (at your option) any later version.
9
-
10
- Stockfish is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- You should have received a copy of the GNU General Public License
16
- along with this program. If not, see <http://www.gnu.org/licenses/>.
17
- */
18
-
19
- // header used in NNUE evaluation function
20
-
21
- #ifndef NNUE_EVALUATE_NNUE_H_INCLUDED
22
- #define NNUE_EVALUATE_NNUE_H_INCLUDED
23
-
24
- #include "nnue_feature_transformer.h"
25
-
26
- #include <memory>
27
-
28
- namespace Stockfish::Eval::NNUE {
29
-
30
- // Hash value of evaluation function structure
31
- constexpr std::uint32_t HashValue =
32
- FeatureTransformer::get_hash_value() ^ Network::get_hash_value();
33
-
34
- // Deleter for automating release of memory area
35
- template <typename T>
36
- struct AlignedDeleter {
37
- void operator()(T* ptr) const {
38
- ptr->~T();
39
- std_aligned_free(ptr);
40
- }
41
- };
42
-
43
- template <typename T>
44
- struct LargePageDeleter {
45
- void operator()(T* ptr) const {
46
- ptr->~T();
47
- aligned_large_pages_free(ptr);
48
- }
49
- };
50
-
51
- template <typename T>
52
- using AlignedPtr = std::unique_ptr<T, AlignedDeleter<T>>;
53
-
54
- template <typename T>
55
- using LargePagePtr = std::unique_ptr<T, LargePageDeleter<T>>;
56
-
57
- } // namespace Stockfish::Eval::NNUE
58
-
59
- #endif // #ifndef NNUE_EVALUATE_NNUE_H_INCLUDED
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/src/nnue/features/half_ka_v2.cpp DELETED
@@ -1,90 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
4
-
5
- Stockfish is free software: you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation, either version 3 of the License, or
8
- (at your option) any later version.
9
-
10
- Stockfish is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- You should have received a copy of the GNU General Public License
16
- along with this program. If not, see <http://www.gnu.org/licenses/>.
17
- */
18
-
19
- //Definition of input features HalfKAv2 of NNUE evaluation function
20
-
21
- #include "half_ka_v2.h"
22
-
23
- #include "../../position.h"
24
-
25
- namespace Stockfish::Eval::NNUE::Features {
26
-
27
- // Map square to numbering on 8x8 board
28
- constexpr Square to_chess_square(Square s) {
29
- return Square(s - rank_of(s) * (FILE_MAX - FILE_H));
30
- }
31
-
32
- // Orient a square according to perspective (rotates by 180 for black)
33
- inline Square HalfKAv2::orient(Color perspective, Square s) {
34
- return Square(int(to_chess_square(s)) ^ (bool(perspective) * 56));
35
- }
36
-
37
- // Index of a feature for a given king position and another piece on some square
38
- inline IndexType HalfKAv2::make_index(Color perspective, Square s, Piece pc, Square ksq) {
39
- return IndexType(orient(perspective, s) + PieceSquareIndex[perspective][pc] + PS_NB * ksq);
40
- }
41
-
42
- // Get a list of indices for active features
43
- void HalfKAv2::append_active_indices(
44
- const Position& pos,
45
- Color perspective,
46
- ValueListInserter<IndexType> active
47
- ) {
48
- Square ksq = orient(perspective, pos.square<KING>(perspective));
49
- Bitboard bb = pos.pieces();
50
- while (bb)
51
- {
52
- Square s = pop_lsb(bb);
53
- active.push_back(make_index(perspective, s, pos.piece_on(s), ksq));
54
- }
55
- }
56
-
57
-
58
- // append_changed_indices() : get a list of indices for recently changed features
59
-
60
- void HalfKAv2::append_changed_indices(
61
- Square ksq,
62
- StateInfo* st,
63
- Color perspective,
64
- ValueListInserter<IndexType> removed,
65
- ValueListInserter<IndexType> added
66
- ) {
67
- const auto& dp = st->dirtyPiece;
68
- Square oriented_ksq = orient(perspective, ksq);
69
- for (int i = 0; i < dp.dirty_num; ++i) {
70
- Piece pc = dp.piece[i];
71
- if (dp.from[i] != SQ_NONE)
72
- removed.push_back(make_index(perspective, dp.from[i], pc, oriented_ksq));
73
- if (dp.to[i] != SQ_NONE)
74
- added.push_back(make_index(perspective, dp.to[i], pc, oriented_ksq));
75
- }
76
- }
77
-
78
- int HalfKAv2::update_cost(StateInfo* st) {
79
- return st->dirtyPiece.dirty_num;
80
- }
81
-
82
- int HalfKAv2::refresh_cost(const Position& pos) {
83
- return pos.count<ALL_PIECES>();
84
- }
85
-
86
- bool HalfKAv2::requires_refresh(StateInfo* st, Color perspective) {
87
- return st->dirtyPiece.piece[0] == make_piece(perspective, KING);
88
- }
89
-
90
- } // namespace Stockfish::Eval::NNUE::Features
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/src/nnue/features/half_ka_v2.h DELETED
@@ -1,152 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
4
-
5
- Stockfish is free software: you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation, either version 3 of the License, or
8
- (at your option) any later version.
9
-
10
- Stockfish is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- You should have received a copy of the GNU General Public License
16
- along with this program. If not, see <http://www.gnu.org/licenses/>.
17
- */
18
-
19
- //Definition of input features HalfKAv2 of NNUE evaluation function
20
-
21
- #ifndef NNUE_FEATURES_HALF_KA_V2_H_INCLUDED
22
- #define NNUE_FEATURES_HALF_KA_V2_H_INCLUDED
23
-
24
- #include "../nnue_common.h"
25
-
26
- #include "../../evaluate.h"
27
- #include "../../misc.h"
28
-
29
- namespace Stockfish {
30
- struct StateInfo;
31
- }
32
-
33
- namespace Stockfish::Eval::NNUE::Features {
34
-
35
- // Feature HalfKAv2: Combination of the position of own king
36
- // and the position of pieces
37
- class HalfKAv2 {
38
-
39
- // unique number for each piece type on each square
40
- enum {
41
- PS_NONE = 0,
42
- PS_W_PAWN = 0,
43
- PS_B_PAWN = 1 * SQUARE_NB_CHESS,
44
- PS_W_KNIGHT = 2 * SQUARE_NB_CHESS,
45
- PS_B_KNIGHT = 3 * SQUARE_NB_CHESS,
46
- PS_W_BISHOP = 4 * SQUARE_NB_CHESS,
47
- PS_B_BISHOP = 5 * SQUARE_NB_CHESS,
48
- PS_W_ROOK = 6 * SQUARE_NB_CHESS,
49
- PS_B_ROOK = 7 * SQUARE_NB_CHESS,
50
- PS_W_QUEEN = 8 * SQUARE_NB_CHESS,
51
- PS_B_QUEEN = 9 * SQUARE_NB_CHESS,
52
- PS_KING = 10 * SQUARE_NB_CHESS,
53
- PS_NB = 11 * SQUARE_NB_CHESS
54
- };
55
-
56
- static constexpr uint32_t PieceSquareIndex[COLOR_NB][PIECE_NB] = {
57
- // convention: W - us, B - them
58
- // viewed from other side, W and B are reversed
59
- {
60
- PS_NONE, PS_W_PAWN, PS_W_KNIGHT, PS_W_BISHOP, PS_W_ROOK, PS_W_QUEEN, PS_NONE, PS_NONE,
61
- PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
62
- PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
63
- PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
64
- PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
65
- PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
66
- PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
67
- PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_KING,
68
-
69
- PS_NONE, PS_B_PAWN, PS_B_KNIGHT, PS_B_BISHOP, PS_B_ROOK, PS_B_QUEEN, PS_NONE, PS_NONE,
70
- PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
71
- PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
72
- PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
73
- PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
74
- PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
75
- PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
76
- PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_KING,
77
- },
78
-
79
- {
80
- PS_NONE, PS_B_PAWN, PS_B_KNIGHT, PS_B_BISHOP, PS_B_ROOK, PS_B_QUEEN, PS_NONE, PS_NONE,
81
- PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
82
- PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
83
- PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
84
- PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
85
- PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
86
- PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
87
- PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_KING,
88
-
89
- PS_NONE, PS_W_PAWN, PS_W_KNIGHT, PS_W_BISHOP, PS_W_ROOK, PS_W_QUEEN, PS_NONE, PS_NONE,
90
- PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
91
- PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
92
- PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
93
- PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
94
- PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
95
- PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE,
96
- PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_NONE, PS_KING,
97
- }
98
- };
99
- // Check that the fragile array definition is correct
100
- static_assert(PieceSquareIndex[WHITE][make_piece(WHITE, PAWN)] == PS_W_PAWN);
101
- static_assert(PieceSquareIndex[WHITE][make_piece(WHITE, KING)] == PS_KING);
102
- static_assert(PieceSquareIndex[WHITE][make_piece(BLACK, PAWN)] == PS_B_PAWN);
103
- static_assert(PieceSquareIndex[WHITE][make_piece(BLACK, KING)] == PS_KING);
104
-
105
-
106
- // Orient a square according to perspective (rotates by 180 for black)
107
- static Square orient(Color perspective, Square s);
108
-
109
- // Index of a feature for a given king position and another piece on some square
110
- static IndexType make_index(Color perspective, Square s, Piece pc, Square ksq);
111
-
112
- public:
113
- // Feature name
114
- static constexpr const char* Name = "HalfKAv2(Friend)";
115
-
116
- // Hash value embedded in the evaluation file
117
- static constexpr std::uint32_t HashValue = 0x5f234cb8u;
118
-
119
- // Number of feature dimensions
120
- static constexpr IndexType Dimensions =
121
- static_cast<IndexType>(SQUARE_NB_CHESS) * static_cast<IndexType>(PS_NB);
122
-
123
- // Maximum number of simultaneously active features.
124
- static constexpr IndexType MaxActiveDimensions = 32;
125
-
126
- // Get a list of indices for active features
127
- static void append_active_indices(
128
- const Position& pos,
129
- Color perspective,
130
- ValueListInserter<IndexType> active);
131
-
132
- // Get a list of indices for recently changed features
133
- static void append_changed_indices(
134
- Square ksq,
135
- StateInfo* st,
136
- Color perspective,
137
- ValueListInserter<IndexType> removed,
138
- ValueListInserter<IndexType> added);
139
-
140
- // Returns the cost of updating one perspective, the most costly one.
141
- // Assumes no refresh needed.
142
- static int update_cost(StateInfo* st);
143
- static int refresh_cost(const Position& pos);
144
-
145
- // Returns whether the change stored in this StateInfo means that
146
- // a full accumulator refresh is required.
147
- static bool requires_refresh(StateInfo* st, Color perspective);
148
- };
149
-
150
- } // namespace Stockfish::Eval::NNUE::Features
151
-
152
- #endif // #ifndef NNUE_FEATURES_HALF_KA_V2_H_INCLUDED
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/src/nnue/features/half_ka_v2_variants.cpp DELETED
@@ -1,112 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
4
-
5
- Stockfish is free software: you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation, either version 3 of the License, or
8
- (at your option) any later version.
9
-
10
- Stockfish is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- You should have received a copy of the GNU General Public License
16
- along with this program. If not, see <http://www.gnu.org/licenses/>.
17
- */
18
-
19
- //Definition of input features HalfKAv2 of NNUE evaluation function
20
-
21
- #include "half_ka_v2_variants.h"
22
-
23
- #include "../../position.h"
24
-
25
- namespace Stockfish::Eval::NNUE::Features {
26
-
27
- // Map square to numbering on variant board
28
- inline Square to_variant_square(Square s, const Position& pos) {
29
- return Square(s - rank_of(s) * (FILE_MAX - pos.max_file()));
30
- }
31
-
32
- // Orient a square according to perspective (rotates by 180 for black)
33
- // Missing kings map to index 0 (SQ_A1)
34
- inline Square HalfKAv2Variants::orient(Color perspective, Square s, const Position& pos) {
35
- return s != SQ_NONE ? to_variant_square( perspective == WHITE || (pos.flag_region(BLACK) & Rank8BB) ? s
36
- : flip_rank(s, pos.max_rank()), pos) : SQ_A1;
37
- }
38
-
39
- // Index of a feature for a given king position and another piece on some square
40
- inline IndexType HalfKAv2Variants::make_index(Color perspective, Square s, Piece pc, Square ksq, const Position& pos) {
41
- return IndexType(orient(perspective, s, pos) + pos.nnue_piece_square_index(perspective, pc) + pos.nnue_king_square_index(ksq));
42
- }
43
-
44
- // Index of a feature for a given king position and another piece on some square
45
- inline IndexType HalfKAv2Variants::make_index(Color perspective, int handCount, Piece pc, Square ksq, const Position& pos) {
46
- return IndexType(handCount + pos.nnue_piece_hand_index(perspective, pc) + pos.nnue_king_square_index(ksq));
47
- }
48
-
49
- // Get a list of indices for active features
50
- void HalfKAv2Variants::append_active_indices(
51
- const Position& pos,
52
- Color perspective,
53
- ValueListInserter<IndexType> active
54
- ) {
55
- Square oriented_ksq = orient(perspective, pos.nnue_king_square(perspective), pos);
56
- Bitboard bb = pos.pieces(WHITE) | pos.pieces(BLACK);
57
- while (bb)
58
- {
59
- Square s = pop_lsb(bb);
60
- active.push_back(make_index(perspective, s, pos.piece_on(s), oriented_ksq, pos));
61
- }
62
-
63
- // Indices for pieces in hand
64
- if (pos.nnue_use_pockets())
65
- for (Color c : {WHITE, BLACK})
66
- for (PieceSet ps = pos.piece_types(); ps;)
67
- {
68
- PieceType pt = pop_lsb(ps);
69
- for (int i = 0; i < pos.count_in_hand(c, pt); i++)
70
- active.push_back(make_index(perspective, i, make_piece(c, pt), oriented_ksq, pos));
71
- }
72
-
73
- }
74
-
75
- // append_changed_indices() : get a list of indices for recently changed features
76
-
77
- void HalfKAv2Variants::append_changed_indices(
78
- Square ksq,
79
- StateInfo* st,
80
- Color perspective,
81
- ValueListInserter<IndexType> removed,
82
- ValueListInserter<IndexType> added,
83
- const Position& pos
84
- ) {
85
- const auto& dp = st->dirtyPiece;
86
- Square oriented_ksq = orient(perspective, ksq, pos);
87
- for (int i = 0; i < dp.dirty_num; ++i) {
88
- Piece pc = dp.piece[i];
89
- if (dp.from[i] != SQ_NONE)
90
- removed.push_back(make_index(perspective, dp.from[i], pc, oriented_ksq, pos));
91
- else if (dp.handPiece[i] != NO_PIECE)
92
- removed.push_back(make_index(perspective, dp.handCount[i] - 1, dp.handPiece[i], oriented_ksq, pos));
93
- if (dp.to[i] != SQ_NONE)
94
- added.push_back(make_index(perspective, dp.to[i], pc, oriented_ksq, pos));
95
- else if (dp.handPiece[i] != NO_PIECE)
96
- added.push_back(make_index(perspective, dp.handCount[i] - 1, dp.handPiece[i], oriented_ksq, pos));
97
- }
98
- }
99
-
100
- int HalfKAv2Variants::update_cost(StateInfo* st) {
101
- return st->dirtyPiece.dirty_num;
102
- }
103
-
104
- int HalfKAv2Variants::refresh_cost(const Position& pos) {
105
- return pos.count<ALL_PIECES>();
106
- }
107
-
108
- bool HalfKAv2Variants::requires_refresh(StateInfo* st, Color perspective, const Position& pos) {
109
- return st->dirtyPiece.piece[0] == make_piece(perspective, pos.nnue_king()) || pos.flip_enclosed_pieces();
110
- }
111
-
112
- } // namespace Stockfish::Eval::NNUE::Features
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/src/nnue/features/half_ka_v2_variants.h DELETED
@@ -1,94 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
4
-
5
- Stockfish is free software: you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation, either version 3 of the License, or
8
- (at your option) any later version.
9
-
10
- Stockfish is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- You should have received a copy of the GNU General Public License
16
- along with this program. If not, see <http://www.gnu.org/licenses/>.
17
- */
18
-
19
- //Definition of input features HalfKAv2 of NNUE evaluation function
20
-
21
- #ifndef NNUE_FEATURES_HALF_KA_V2_VARIANTS_H_INCLUDED
22
- #define NNUE_FEATURES_HALF_KA_V2_VARIANTS_H_INCLUDED
23
-
24
- #include "../nnue_common.h"
25
-
26
- #include "../../evaluate.h"
27
- #include "../../misc.h"
28
-
29
- #include "half_ka_v2.h"
30
-
31
- namespace Stockfish {
32
- struct StateInfo;
33
- }
34
-
35
- namespace Stockfish::Eval::NNUE::Features {
36
-
37
- // Feature HalfKAv2: Combination of the position of own king
38
- // and the position of pieces
39
- class HalfKAv2Variants {
40
-
41
- // Orient a square according to perspective (rotates by 180 for black)
42
- static Square orient(Color perspective, Square s, const Position& pos);
43
-
44
- // Index of a feature for a given king position and another piece on some square
45
- static IndexType make_index(Color perspective, Square s, Piece pc, Square ksq, const Position& pos);
46
-
47
- // Index of a feature for a given king position and another piece in hand
48
- static IndexType make_index(Color perspective, int handCount, Piece pc, Square ksq, const Position& pos);
49
-
50
- public:
51
- // Feature name
52
- static constexpr const char* Name = "HalfKAv2(Friend)";
53
-
54
- // Hash value embedded in the evaluation file
55
- static constexpr std::uint32_t HashValue = 0x5f234cb8u;
56
-
57
- // Number of feature dimensions
58
- static constexpr IndexType Dimensions = static_cast<IndexType>(SQUARE_NB) * static_cast<IndexType>(SQUARE_NB) * 19;
59
-
60
- static IndexType get_dimensions() {
61
- return currentNnueVariant->nnueDimensions;
62
- }
63
-
64
- // Maximum number of simultaneously active features.
65
- static constexpr IndexType MaxActiveDimensions = 128;
66
-
67
- // Get a list of indices for active features
68
- static void append_active_indices(
69
- const Position& pos,
70
- Color perspective,
71
- ValueListInserter<IndexType> active);
72
-
73
- // Get a list of indices for recently changed features
74
- static void append_changed_indices(
75
- Square ksq,
76
- StateInfo* st,
77
- Color perspective,
78
- ValueListInserter<IndexType> removed,
79
- ValueListInserter<IndexType> added,
80
- const Position& pos);
81
-
82
- // Returns the cost of updating one perspective, the most costly one.
83
- // Assumes no refresh needed.
84
- static int update_cost(StateInfo* st);
85
- static int refresh_cost(const Position& pos);
86
-
87
- // Returns whether the change stored in this StateInfo means that
88
- // a full accumulator refresh is required.
89
- static bool requires_refresh(StateInfo* st, Color perspective, const Position& pos);
90
- };
91
-
92
- } // namespace Stockfish::Eval::NNUE::Features
93
-
94
- #endif // #ifndef NNUE_FEATURES_HALF_KA_V2_VARIANTS_H_INCLUDED
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/src/nnue/layers/affine_transform.h DELETED
@@ -1,435 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
4
-
5
- Stockfish is free software: you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation, either version 3 of the License, or
8
- (at your option) any later version.
9
-
10
- Stockfish is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- You should have received a copy of the GNU General Public License
16
- along with this program. If not, see <http://www.gnu.org/licenses/>.
17
- */
18
-
19
- // Definition of layer AffineTransform of NNUE evaluation function
20
-
21
- #ifndef NNUE_LAYERS_AFFINE_TRANSFORM_H_INCLUDED
22
- #define NNUE_LAYERS_AFFINE_TRANSFORM_H_INCLUDED
23
-
24
- #include <iostream>
25
- #include "../nnue_common.h"
26
-
27
- namespace Stockfish::Eval::NNUE::Layers {
28
-
29
- // Affine transformation layer
30
- template <typename PreviousLayer, IndexType OutDims>
31
- class AffineTransform {
32
- public:
33
- // Input/output type
34
- using InputType = typename PreviousLayer::OutputType;
35
- using OutputType = std::int32_t;
36
- static_assert(std::is_same<InputType, std::uint8_t>::value, "");
37
-
38
- // Number of input/output dimensions
39
- static constexpr IndexType InputDimensions =
40
- PreviousLayer::OutputDimensions;
41
- static constexpr IndexType OutputDimensions = OutDims;
42
- static constexpr IndexType PaddedInputDimensions =
43
- ceil_to_multiple<IndexType>(InputDimensions, MaxSimdWidth);
44
- #if defined (USE_AVX512)
45
- static constexpr const IndexType OutputSimdWidth = SimdWidth / 2;
46
- #elif defined (USE_SSSE3)
47
- static constexpr const IndexType OutputSimdWidth = SimdWidth / 4;
48
- #endif
49
-
50
- // Size of forward propagation buffer used in this layer
51
- static constexpr std::size_t SelfBufferSize =
52
- ceil_to_multiple(OutputDimensions * sizeof(OutputType), CacheLineSize);
53
-
54
- // Size of the forward propagation buffer used from the input layer to this layer
55
- static constexpr std::size_t BufferSize =
56
- PreviousLayer::BufferSize + SelfBufferSize;
57
-
58
- // Hash value embedded in the evaluation file
59
- static constexpr std::uint32_t get_hash_value() {
60
- std::uint32_t hashValue = 0xCC03DAE4u;
61
- hashValue += OutputDimensions;
62
- hashValue ^= PreviousLayer::get_hash_value() >> 1;
63
- hashValue ^= PreviousLayer::get_hash_value() << 31;
64
- return hashValue;
65
- }
66
-
67
- // Read network parameters
68
- bool read_parameters(std::istream& stream) {
69
- if (!previousLayer.read_parameters(stream)) return false;
70
- for (std::size_t i = 0; i < OutputDimensions; ++i)
71
- biases[i] = read_little_endian<BiasType>(stream);
72
- for (std::size_t i = 0; i < OutputDimensions * PaddedInputDimensions; ++i)
73
- #if !defined (USE_SSSE3)
74
- weights[i] = read_little_endian<WeightType>(stream);
75
- #else
76
- weights[
77
- (i / 4) % (PaddedInputDimensions / 4) * OutputDimensions * 4 +
78
- i / PaddedInputDimensions * 4 +
79
- i % 4
80
- ] = read_little_endian<WeightType>(stream);
81
- #endif
82
-
83
- return !stream.fail();
84
- }
85
-
86
- // Write network parameters
87
- bool write_parameters(std::ostream& stream) const {
88
- if (!previousLayer.write_parameters(stream)) return false;
89
- for (std::size_t i = 0; i < OutputDimensions; ++i)
90
- write_little_endian<BiasType>(stream, biases[i]);
91
- #if !defined (USE_SSSE3)
92
- for (std::size_t i = 0; i < OutputDimensions * PaddedInputDimensions; ++i)
93
- write_little_endian<WeightType>(stream, weights[i]);
94
- #else
95
- std::unique_ptr<WeightType[]> unscrambledWeights = std::make_unique<WeightType[]>(OutputDimensions * PaddedInputDimensions);
96
- for (std::size_t i = 0; i < OutputDimensions * PaddedInputDimensions; ++i) {
97
- unscrambledWeights[i] =
98
- weights[
99
- (i / 4) % (PaddedInputDimensions / 4) * OutputDimensions * 4 +
100
- i / PaddedInputDimensions * 4 +
101
- i % 4
102
- ];
103
- }
104
-
105
- for (std::size_t i = 0; i < OutputDimensions * PaddedInputDimensions; ++i)
106
- write_little_endian<WeightType>(stream, unscrambledWeights[i]);
107
- #endif
108
-
109
- return !stream.fail();
110
- }
111
-
112
- // Forward propagation
113
- const OutputType* propagate(
114
- const TransformedFeatureType* transformedFeatures, char* buffer) const {
115
- const auto input = previousLayer.propagate(
116
- transformedFeatures, buffer + SelfBufferSize);
117
-
118
- #if defined (USE_AVX512)
119
-
120
- [[maybe_unused]] const __m512i Ones512 = _mm512_set1_epi16(1);
121
-
122
- [[maybe_unused]] auto m512_hadd = [](__m512i sum, int bias) -> int {
123
- return _mm512_reduce_add_epi32(sum) + bias;
124
- };
125
-
126
- [[maybe_unused]] auto m512_add_dpbusd_epi32 = [=](__m512i& acc, __m512i a, __m512i b) {
127
- #if defined (USE_VNNI)
128
- acc = _mm512_dpbusd_epi32(acc, a, b);
129
- #else
130
- __m512i product0 = _mm512_maddubs_epi16(a, b);
131
- product0 = _mm512_madd_epi16(product0, Ones512);
132
- acc = _mm512_add_epi32(acc, product0);
133
- #endif
134
- };
135
-
136
- [[maybe_unused]] auto m512_add_dpbusd_epi32x4 = [=](__m512i& acc, __m512i a0, __m512i b0, __m512i a1, __m512i b1,
137
- __m512i a2, __m512i b2, __m512i a3, __m512i b3) {
138
- #if defined (USE_VNNI)
139
- acc = _mm512_dpbusd_epi32(acc, a0, b0);
140
- acc = _mm512_dpbusd_epi32(acc, a1, b1);
141
- acc = _mm512_dpbusd_epi32(acc, a2, b2);
142
- acc = _mm512_dpbusd_epi32(acc, a3, b3);
143
- #else
144
- __m512i product0 = _mm512_maddubs_epi16(a0, b0);
145
- __m512i product1 = _mm512_maddubs_epi16(a1, b1);
146
- __m512i product2 = _mm512_maddubs_epi16(a2, b2);
147
- __m512i product3 = _mm512_maddubs_epi16(a3, b3);
148
- product0 = _mm512_adds_epi16(product0, product1);
149
- product0 = _mm512_madd_epi16(product0, Ones512);
150
- product2 = _mm512_adds_epi16(product2, product3);
151
- product2 = _mm512_madd_epi16(product2, Ones512);
152
- acc = _mm512_add_epi32(acc, _mm512_add_epi32(product0, product2));
153
- #endif
154
- };
155
-
156
- #endif
157
- #if defined (USE_AVX2)
158
-
159
- [[maybe_unused]] const __m256i Ones256 = _mm256_set1_epi16(1);
160
-
161
- [[maybe_unused]] auto m256_hadd = [](__m256i sum, int bias) -> int {
162
- __m128i sum128 = _mm_add_epi32(_mm256_castsi256_si128(sum), _mm256_extracti128_si256(sum, 1));
163
- sum128 = _mm_add_epi32(sum128, _mm_shuffle_epi32(sum128, _MM_PERM_BADC));
164
- sum128 = _mm_add_epi32(sum128, _mm_shuffle_epi32(sum128, _MM_PERM_CDAB));
165
- return _mm_cvtsi128_si32(sum128) + bias;
166
- };
167
-
168
- [[maybe_unused]] auto m256_add_dpbusd_epi32 = [=](__m256i& acc, __m256i a, __m256i b) {
169
- #if defined (USE_VNNI)
170
- acc = _mm256_dpbusd_epi32(acc, a, b);
171
- #else
172
- __m256i product0 = _mm256_maddubs_epi16(a, b);
173
- product0 = _mm256_madd_epi16(product0, Ones256);
174
- acc = _mm256_add_epi32(acc, product0);
175
- #endif
176
- };
177
-
178
- [[maybe_unused]] auto m256_add_dpbusd_epi32x4 = [=](__m256i& acc, __m256i a0, __m256i b0, __m256i a1, __m256i b1,
179
- __m256i a2, __m256i b2, __m256i a3, __m256i b3) {
180
- #if defined (USE_VNNI)
181
- acc = _mm256_dpbusd_epi32(acc, a0, b0);
182
- acc = _mm256_dpbusd_epi32(acc, a1, b1);
183
- acc = _mm256_dpbusd_epi32(acc, a2, b2);
184
- acc = _mm256_dpbusd_epi32(acc, a3, b3);
185
- #else
186
- __m256i product0 = _mm256_maddubs_epi16(a0, b0);
187
- __m256i product1 = _mm256_maddubs_epi16(a1, b1);
188
- __m256i product2 = _mm256_maddubs_epi16(a2, b2);
189
- __m256i product3 = _mm256_maddubs_epi16(a3, b3);
190
- product0 = _mm256_adds_epi16(product0, product1);
191
- product0 = _mm256_madd_epi16(product0, Ones256);
192
- product2 = _mm256_adds_epi16(product2, product3);
193
- product2 = _mm256_madd_epi16(product2, Ones256);
194
- acc = _mm256_add_epi32(acc, _mm256_add_epi32(product0, product2));
195
- #endif
196
- };
197
-
198
- #endif
199
- #if defined (USE_SSSE3)
200
-
201
- [[maybe_unused]] const __m128i Ones128 = _mm_set1_epi16(1);
202
-
203
- [[maybe_unused]] auto m128_hadd = [](__m128i sum, int bias) -> int {
204
- sum = _mm_add_epi32(sum, _mm_shuffle_epi32(sum, 0x4E)); //_MM_PERM_BADC
205
- sum = _mm_add_epi32(sum, _mm_shuffle_epi32(sum, 0xB1)); //_MM_PERM_CDAB
206
- return _mm_cvtsi128_si32(sum) + bias;
207
- };
208
-
209
- [[maybe_unused]] auto m128_add_dpbusd_epi32 = [=](__m128i& acc, __m128i a, __m128i b) {
210
- __m128i product0 = _mm_maddubs_epi16(a, b);
211
- product0 = _mm_madd_epi16(product0, Ones128);
212
- acc = _mm_add_epi32(acc, product0);
213
- };
214
-
215
- [[maybe_unused]] auto m128_add_dpbusd_epi32x4 = [=](__m128i& acc, __m128i a0, __m128i b0, __m128i a1, __m128i b1,
216
- __m128i a2, __m128i b2, __m128i a3, __m128i b3) {
217
- __m128i product0 = _mm_maddubs_epi16(a0, b0);
218
- __m128i product1 = _mm_maddubs_epi16(a1, b1);
219
- __m128i product2 = _mm_maddubs_epi16(a2, b2);
220
- __m128i product3 = _mm_maddubs_epi16(a3, b3);
221
- product0 = _mm_adds_epi16(product0, product1);
222
- product0 = _mm_madd_epi16(product0, Ones128);
223
- product2 = _mm_adds_epi16(product2, product3);
224
- product2 = _mm_madd_epi16(product2, Ones128);
225
- acc = _mm_add_epi32(acc, _mm_add_epi32(product0, product2));
226
- };
227
-
228
- #endif
229
-
230
- #if defined (USE_AVX512)
231
- using vec_t = __m512i;
232
- #define vec_setzero _mm512_setzero_si512
233
- #define vec_set_32 _mm512_set1_epi32
234
- auto& vec_add_dpbusd_32 = m512_add_dpbusd_epi32;
235
- auto& vec_add_dpbusd_32x4 = m512_add_dpbusd_epi32x4;
236
- auto& vec_hadd = m512_hadd;
237
- #elif defined (USE_AVX2)
238
- using vec_t = __m256i;
239
- #define vec_setzero _mm256_setzero_si256
240
- #define vec_set_32 _mm256_set1_epi32
241
- auto& vec_add_dpbusd_32 = m256_add_dpbusd_epi32;
242
- auto& vec_add_dpbusd_32x4 = m256_add_dpbusd_epi32x4;
243
- auto& vec_hadd = m256_hadd;
244
- #elif defined (USE_SSSE3)
245
- using vec_t = __m128i;
246
- #define vec_setzero _mm_setzero_si128
247
- #define vec_set_32 _mm_set1_epi32
248
- auto& vec_add_dpbusd_32 = m128_add_dpbusd_epi32;
249
- auto& vec_add_dpbusd_32x4 = m128_add_dpbusd_epi32x4;
250
- auto& vec_hadd = m128_hadd;
251
- #endif
252
-
253
- #if defined (USE_SSSE3)
254
- // Different layout, we process 4 inputs at a time, always.
255
- static_assert(InputDimensions % 4 == 0);
256
-
257
- const auto output = reinterpret_cast<OutputType*>(buffer);
258
- const auto inputVector = reinterpret_cast<const vec_t*>(input);
259
-
260
- static_assert(OutputDimensions % OutputSimdWidth == 0 || OutputDimensions == 1);
261
-
262
- // OutputDimensions is either 1 or a multiple of SimdWidth
263
- // because then it is also an input dimension.
264
- if constexpr (OutputDimensions % OutputSimdWidth == 0)
265
- {
266
- constexpr IndexType NumChunks = InputDimensions / 4;
267
-
268
- const auto input32 = reinterpret_cast<const std::int32_t*>(input);
269
- vec_t* outptr = reinterpret_cast<vec_t*>(output);
270
- std::memcpy(output, biases, OutputDimensions * sizeof(OutputType));
271
-
272
- for (int i = 0; i < (int)NumChunks - 3; i += 4)
273
- {
274
- const vec_t in0 = vec_set_32(input32[i + 0]);
275
- const vec_t in1 = vec_set_32(input32[i + 1]);
276
- const vec_t in2 = vec_set_32(input32[i + 2]);
277
- const vec_t in3 = vec_set_32(input32[i + 3]);
278
- const auto col0 = reinterpret_cast<const vec_t*>(&weights[(i + 0) * OutputDimensions * 4]);
279
- const auto col1 = reinterpret_cast<const vec_t*>(&weights[(i + 1) * OutputDimensions * 4]);
280
- const auto col2 = reinterpret_cast<const vec_t*>(&weights[(i + 2) * OutputDimensions * 4]);
281
- const auto col3 = reinterpret_cast<const vec_t*>(&weights[(i + 3) * OutputDimensions * 4]);
282
- for (int j = 0; j * OutputSimdWidth < OutputDimensions; ++j)
283
- vec_add_dpbusd_32x4(outptr[j], in0, col0[j], in1, col1[j], in2, col2[j], in3, col3[j]);
284
- }
285
- }
286
- else if constexpr (OutputDimensions == 1)
287
- {
288
- #if defined (USE_AVX512)
289
- if constexpr (PaddedInputDimensions % (SimdWidth * 2) != 0)
290
- {
291
- constexpr IndexType NumChunks = PaddedInputDimensions / SimdWidth;
292
- const auto inputVector256 = reinterpret_cast<const __m256i*>(input);
293
-
294
- __m256i sum0 = _mm256_setzero_si256();
295
- const auto row0 = reinterpret_cast<const __m256i*>(&weights[0]);
296
-
297
- for (int j = 0; j < (int)NumChunks; ++j)
298
- {
299
- const __m256i in = inputVector256[j];
300
- m256_add_dpbusd_epi32(sum0, in, row0[j]);
301
- }
302
- output[0] = m256_hadd(sum0, biases[0]);
303
- }
304
- else
305
- #endif
306
- {
307
- #if defined (USE_AVX512)
308
- constexpr IndexType NumChunks = PaddedInputDimensions / (SimdWidth * 2);
309
- #else
310
- constexpr IndexType NumChunks = PaddedInputDimensions / SimdWidth;
311
- #endif
312
- vec_t sum0 = vec_setzero();
313
- const auto row0 = reinterpret_cast<const vec_t*>(&weights[0]);
314
-
315
- for (int j = 0; j < (int)NumChunks; ++j)
316
- {
317
- const vec_t in = inputVector[j];
318
- vec_add_dpbusd_32(sum0, in, row0[j]);
319
- }
320
- output[0] = vec_hadd(sum0, biases[0]);
321
- }
322
- }
323
-
324
- #else
325
-
326
- // Use old implementation for the other architectures.
327
-
328
- auto output = reinterpret_cast<OutputType*>(buffer);
329
-
330
- #if defined(USE_SSE2)
331
- // At least a multiple of 16, with SSE2.
332
- static_assert(InputDimensions % SimdWidth == 0);
333
- constexpr IndexType NumChunks = InputDimensions / SimdWidth;
334
- const __m128i Zeros = _mm_setzero_si128();
335
- const auto inputVector = reinterpret_cast<const __m128i*>(input);
336
-
337
- #elif defined(USE_MMX)
338
- static_assert(InputDimensions % SimdWidth == 0);
339
- constexpr IndexType NumChunks = InputDimensions / SimdWidth;
340
- const __m64 Zeros = _mm_setzero_si64();
341
- const auto inputVector = reinterpret_cast<const __m64*>(input);
342
-
343
- #elif defined(USE_NEON)
344
- static_assert(InputDimensions % SimdWidth == 0);
345
- constexpr IndexType NumChunks = InputDimensions / SimdWidth;
346
- const auto inputVector = reinterpret_cast<const int8x8_t*>(input);
347
- #endif
348
-
349
- for (IndexType i = 0; i < OutputDimensions; ++i) {
350
- const IndexType offset = i * PaddedInputDimensions;
351
-
352
- #if defined(USE_SSE2)
353
- __m128i sumLo = _mm_cvtsi32_si128(biases[i]);
354
- __m128i sumHi = Zeros;
355
- const auto row = reinterpret_cast<const __m128i*>(&weights[offset]);
356
- for (IndexType j = 0; j < NumChunks; ++j) {
357
- __m128i row_j = _mm_load_si128(&row[j]);
358
- __m128i input_j = _mm_load_si128(&inputVector[j]);
359
- __m128i extendedRowLo = _mm_srai_epi16(_mm_unpacklo_epi8(row_j, row_j), 8);
360
- __m128i extendedRowHi = _mm_srai_epi16(_mm_unpackhi_epi8(row_j, row_j), 8);
361
- __m128i extendedInputLo = _mm_unpacklo_epi8(input_j, Zeros);
362
- __m128i extendedInputHi = _mm_unpackhi_epi8(input_j, Zeros);
363
- __m128i productLo = _mm_madd_epi16(extendedRowLo, extendedInputLo);
364
- __m128i productHi = _mm_madd_epi16(extendedRowHi, extendedInputHi);
365
- sumLo = _mm_add_epi32(sumLo, productLo);
366
- sumHi = _mm_add_epi32(sumHi, productHi);
367
- }
368
- __m128i sum = _mm_add_epi32(sumLo, sumHi);
369
- __m128i sumHigh_64 = _mm_shuffle_epi32(sum, _MM_SHUFFLE(1, 0, 3, 2));
370
- sum = _mm_add_epi32(sum, sumHigh_64);
371
- __m128i sum_second_32 = _mm_shufflelo_epi16(sum, _MM_SHUFFLE(1, 0, 3, 2));
372
- sum = _mm_add_epi32(sum, sum_second_32);
373
- output[i] = _mm_cvtsi128_si32(sum);
374
-
375
- #elif defined(USE_MMX)
376
- __m64 sumLo = _mm_cvtsi32_si64(biases[i]);
377
- __m64 sumHi = Zeros;
378
- const auto row = reinterpret_cast<const __m64*>(&weights[offset]);
379
- for (IndexType j = 0; j < NumChunks; ++j) {
380
- __m64 row_j = row[j];
381
- __m64 input_j = inputVector[j];
382
- __m64 extendedRowLo = _mm_srai_pi16(_mm_unpacklo_pi8(row_j, row_j), 8);
383
- __m64 extendedRowHi = _mm_srai_pi16(_mm_unpackhi_pi8(row_j, row_j), 8);
384
- __m64 extendedInputLo = _mm_unpacklo_pi8(input_j, Zeros);
385
- __m64 extendedInputHi = _mm_unpackhi_pi8(input_j, Zeros);
386
- __m64 productLo = _mm_madd_pi16(extendedRowLo, extendedInputLo);
387
- __m64 productHi = _mm_madd_pi16(extendedRowHi, extendedInputHi);
388
- sumLo = _mm_add_pi32(sumLo, productLo);
389
- sumHi = _mm_add_pi32(sumHi, productHi);
390
- }
391
- __m64 sum = _mm_add_pi32(sumLo, sumHi);
392
- sum = _mm_add_pi32(sum, _mm_unpackhi_pi32(sum, sum));
393
- output[i] = _mm_cvtsi64_si32(sum);
394
-
395
- #elif defined(USE_NEON)
396
- int32x4_t sum = {biases[i]};
397
- const auto row = reinterpret_cast<const int8x8_t*>(&weights[offset]);
398
- for (IndexType j = 0; j < NumChunks; ++j) {
399
- int16x8_t product = vmull_s8(inputVector[j * 2], row[j * 2]);
400
- product = vmlal_s8(product, inputVector[j * 2 + 1], row[j * 2 + 1]);
401
- sum = vpadalq_s16(sum, product);
402
- }
403
- output[i] = sum[0] + sum[1] + sum[2] + sum[3];
404
-
405
- #else
406
- OutputType sum = biases[i];
407
- for (IndexType j = 0; j < InputDimensions; ++j) {
408
- sum += weights[offset + j] * input[j];
409
- }
410
- output[i] = sum;
411
- #endif
412
-
413
- }
414
- #if defined(USE_MMX)
415
- _mm_empty();
416
- #endif
417
-
418
- #endif
419
-
420
- return output;
421
- }
422
-
423
- private:
424
- using BiasType = OutputType;
425
- using WeightType = std::int8_t;
426
-
427
- PreviousLayer previousLayer;
428
-
429
- alignas(CacheLineSize) BiasType biases[OutputDimensions];
430
- alignas(CacheLineSize) WeightType weights[OutputDimensions * PaddedInputDimensions];
431
- };
432
-
433
- } // namespace Stockfish::Eval::NNUE::Layers
434
-
435
- #endif // #ifndef NNUE_LAYERS_AFFINE_TRANSFORM_H_INCLUDED
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Fairy-Stockfish-master/src/nnue/layers/clipped_relu.h DELETED
@@ -1,191 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file)
4
-
5
- Stockfish is free software: you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation, either version 3 of the License, or
8
- (at your option) any later version.
9
-
10
- Stockfish is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- You should have received a copy of the GNU General Public License
16
- along with this program. If not, see <http://www.gnu.org/licenses/>.
17
- */
18
-
19
- // Definition of layer ClippedReLU of NNUE evaluation function
20
-
21
- #ifndef NNUE_LAYERS_CLIPPED_RELU_H_INCLUDED
22
- #define NNUE_LAYERS_CLIPPED_RELU_H_INCLUDED
23
-
24
- #include "../nnue_common.h"
25
-
26
- namespace Stockfish::Eval::NNUE::Layers {
27
-
28
- // Clipped ReLU
29
- template <typename PreviousLayer>
30
- class ClippedReLU {
31
- public:
32
- // Input/output type
33
- using InputType = typename PreviousLayer::OutputType;
34
- using OutputType = std::uint8_t;
35
- static_assert(std::is_same<InputType, std::int32_t>::value, "");
36
-
37
- // Number of input/output dimensions
38
- static constexpr IndexType InputDimensions =
39
- PreviousLayer::OutputDimensions;
40
- static constexpr IndexType OutputDimensions = InputDimensions;
41
-
42
- // Size of forward propagation buffer used in this layer
43
- static constexpr std::size_t SelfBufferSize =
44
- ceil_to_multiple(OutputDimensions * sizeof(OutputType), CacheLineSize);
45
-
46
- // Size of the forward propagation buffer used from the input layer to this layer
47
- static constexpr std::size_t BufferSize =
48
- PreviousLayer::BufferSize + SelfBufferSize;
49
-
50
- // Hash value embedded in the evaluation file
51
- static constexpr std::uint32_t get_hash_value() {
52
- std::uint32_t hashValue = 0x538D24C7u;
53
- hashValue += PreviousLayer::get_hash_value();
54
- return hashValue;
55
- }
56
-
57
- // Read network parameters
58
- bool read_parameters(std::istream& stream) {
59
- return previousLayer.read_parameters(stream);
60
- }
61
-
62
- // Write network parameters
63
- bool write_parameters(std::ostream& stream) const {
64
- return previousLayer.write_parameters(stream);
65
- }
66
-
67
- // Forward propagation
68
- const OutputType* propagate(
69
- const TransformedFeatureType* transformedFeatures, char* buffer) const {
70
- const auto input = previousLayer.propagate(
71
- transformedFeatures, buffer + SelfBufferSize);
72
- const auto output = reinterpret_cast<OutputType*>(buffer);
73
-
74
- #if defined(USE_AVX2)
75
- if constexpr (InputDimensions % SimdWidth == 0) {
76
- constexpr IndexType NumChunks = InputDimensions / SimdWidth;
77
- const __m256i Zero = _mm256_setzero_si256();
78
- const __m256i Offsets = _mm256_set_epi32(7, 3, 6, 2, 5, 1, 4, 0);
79
- const auto in = reinterpret_cast<const __m256i*>(input);
80
- const auto out = reinterpret_cast<__m256i*>(output);
81
- for (IndexType i = 0; i < NumChunks; ++i) {
82
- const __m256i words0 = _mm256_srai_epi16(_mm256_packs_epi32(
83
- _mm256_load_si256(&in[i * 4 + 0]),
84
- _mm256_load_si256(&in[i * 4 + 1])), WeightScaleBits);
85
- const __m256i words1 = _mm256_srai_epi16(_mm256_packs_epi32(
86
- _mm256_load_si256(&in[i * 4 + 2]),
87
- _mm256_load_si256(&in[i * 4 + 3])), WeightScaleBits);
88
- _mm256_store_si256(&out[i], _mm256_permutevar8x32_epi32(_mm256_max_epi8(
89
- _mm256_packs_epi16(words0, words1), Zero), Offsets));
90
- }
91
- } else {
92
- constexpr IndexType NumChunks = InputDimensions / (SimdWidth / 2);
93
- const __m128i Zero = _mm_setzero_si128();
94
- const auto in = reinterpret_cast<const __m128i*>(input);
95
- const auto out = reinterpret_cast<__m128i*>(output);
96
- for (IndexType i = 0; i < NumChunks; ++i) {
97
- const __m128i words0 = _mm_srai_epi16(_mm_packs_epi32(
98
- _mm_load_si128(&in[i * 4 + 0]),
99
- _mm_load_si128(&in[i * 4 + 1])), WeightScaleBits);
100
- const __m128i words1 = _mm_srai_epi16(_mm_packs_epi32(
101
- _mm_load_si128(&in[i * 4 + 2]),
102
- _mm_load_si128(&in[i * 4 + 3])), WeightScaleBits);
103
- const __m128i packedbytes = _mm_packs_epi16(words0, words1);
104
- _mm_store_si128(&out[i], _mm_max_epi8(packedbytes, Zero));
105
- }
106
- }
107
- constexpr IndexType Start =
108
- InputDimensions % SimdWidth == 0
109
- ? InputDimensions / SimdWidth * SimdWidth
110
- : InputDimensions / (SimdWidth / 2) * (SimdWidth / 2);
111
-
112
- #elif defined(USE_SSE2)
113
- constexpr IndexType NumChunks = InputDimensions / SimdWidth;
114
-
115
- #ifdef USE_SSE41
116
- const __m128i Zero = _mm_setzero_si128();
117
- #else
118
- const __m128i k0x80s = _mm_set1_epi8(-128);
119
- #endif
120
-
121
- const auto in = reinterpret_cast<const __m128i*>(input);
122
- const auto out = reinterpret_cast<__m128i*>(output);
123
- for (IndexType i = 0; i < NumChunks; ++i) {
124
- const __m128i words0 = _mm_srai_epi16(_mm_packs_epi32(
125
- _mm_load_si128(&in[i * 4 + 0]),
126
- _mm_load_si128(&in[i * 4 + 1])), WeightScaleBits);
127
- const __m128i words1 = _mm_srai_epi16(_mm_packs_epi32(
128
- _mm_load_si128(&in[i * 4 + 2]),
129
- _mm_load_si128(&in[i * 4 + 3])), WeightScaleBits);
130
- const __m128i packedbytes = _mm_packs_epi16(words0, words1);
131
- _mm_store_si128(&out[i],
132
-
133
- #ifdef USE_SSE41
134
- _mm_max_epi8(packedbytes, Zero)
135
- #else
136
- _mm_subs_epi8(_mm_adds_epi8(packedbytes, k0x80s), k0x80s)
137
- #endif
138
-
139
- );
140
- }
141
- constexpr IndexType Start = NumChunks * SimdWidth;
142
-
143
- #elif defined(USE_MMX)
144
- constexpr IndexType NumChunks = InputDimensions / SimdWidth;
145
- const __m64 k0x80s = _mm_set1_pi8(-128);
146
- const auto in = reinterpret_cast<const __m64*>(input);
147
- const auto out = reinterpret_cast<__m64*>(output);
148
- for (IndexType i = 0; i < NumChunks; ++i) {
149
- const __m64 words0 = _mm_srai_pi16(
150
- _mm_packs_pi32(in[i * 4 + 0], in[i * 4 + 1]),
151
- WeightScaleBits);
152
- const __m64 words1 = _mm_srai_pi16(
153
- _mm_packs_pi32(in[i * 4 + 2], in[i * 4 + 3]),
154
- WeightScaleBits);
155
- const __m64 packedbytes = _mm_packs_pi16(words0, words1);
156
- out[i] = _mm_subs_pi8(_mm_adds_pi8(packedbytes, k0x80s), k0x80s);
157
- }
158
- _mm_empty();
159
- constexpr IndexType Start = NumChunks * SimdWidth;
160
-
161
- #elif defined(USE_NEON)
162
- constexpr IndexType NumChunks = InputDimensions / (SimdWidth / 2);
163
- const int8x8_t Zero = {0};
164
- const auto in = reinterpret_cast<const int32x4_t*>(input);
165
- const auto out = reinterpret_cast<int8x8_t*>(output);
166
- for (IndexType i = 0; i < NumChunks; ++i) {
167
- int16x8_t shifted;
168
- const auto pack = reinterpret_cast<int16x4_t*>(&shifted);
169
- pack[0] = vqshrn_n_s32(in[i * 2 + 0], WeightScaleBits);
170
- pack[1] = vqshrn_n_s32(in[i * 2 + 1], WeightScaleBits);
171
- out[i] = vmax_s8(vqmovn_s16(shifted), Zero);
172
- }
173
- constexpr IndexType Start = NumChunks * (SimdWidth / 2);
174
- #else
175
- constexpr IndexType Start = 0;
176
- #endif
177
-
178
- for (IndexType i = Start; i < InputDimensions; ++i) {
179
- output[i] = static_cast<OutputType>(
180
- std::max(0, std::min(127, input[i] >> WeightScaleBits)));
181
- }
182
- return output;
183
- }
184
-
185
- private:
186
- PreviousLayer previousLayer;
187
- };
188
-
189
- } // namespace Stockfish::Eval::NNUE::Layers
190
-
191
- #endif // NNUE_LAYERS_CLIPPED_RELU_H_INCLUDED