.
diff --git a/stockfish/README.md b/stockfish/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..621f1d13076fe3af45f52ce13002290f7a7973e0
--- /dev/null
+++ b/stockfish/README.md
@@ -0,0 +1,161 @@
+
+
+ [![Stockfish][stockfish128-logo]][website-link]
+
+
Stockfish
+
+ A free and strong UCI chess engine.
+
+ [Explore Stockfish docs »][wiki-link]
+
+
+ [Report bug][issue-link]
+ ·
+ [Open a discussion][discussions-link]
+ ·
+ [Discord][discord-link]
+ ·
+ [Blog][website-blog-link]
+
+ [![Build][build-badge]][build-link]
+ [![License][license-badge]][license-link]
+
+ [![Release][release-badge]][release-link]
+ [![Commits][commits-badge]][commits-link]
+
+ [![Website][website-badge]][website-link]
+ [![Fishtest][fishtest-badge]][fishtest-link]
+ [![Discord][discord-badge]][discord-link]
+
+
+
+## Overview
+
+[Stockfish][website-link] is a **free and strong UCI chess engine** derived from
+Glaurung 2.1 that analyzes chess positions and computes the optimal moves.
+
+Stockfish **does not include a graphical user interface** (GUI) that is required
+to display a chessboard and to make it easy to input moves. These GUIs are
+developed independently from Stockfish and are available online. **Read the
+documentation for your GUI** of choice for information about how to use
+Stockfish with it.
+
+See also the Stockfish [documentation][wiki-usage-link] for further usage help.
+
+## Files
+
+This distribution of Stockfish consists of the following files:
+
+ * [README.md][readme-link], the file you are currently reading.
+
+ * [Copying.txt][license-link], a text file containing the GNU General Public
+ License version 3.
+
+ * [AUTHORS][authors-link], a text file with the list of authors for the project.
+
+ * [src][src-link], a subdirectory containing the full source code, including a
+ Makefile that can be used to compile Stockfish on Unix-like systems.
+
+ * a file with the .nnue extension, storing the neural network for the NNUE
+ evaluation. Binary distributions will have this file embedded.
+
+## Contributing
+
+__See [Contributing Guide](CONTRIBUTING.md).__
+
+### Donating hardware
+
+Improving Stockfish requires a massive amount of testing. You can donate your
+hardware resources by installing the [Fishtest Worker][worker-link] and viewing
+the current tests on [Fishtest][fishtest-link].
+
+### Improving the code
+
+In the [chessprogramming wiki][programming-link], many techniques used in
+Stockfish are explained with a lot of background information.
+The [section on Stockfish][programmingsf-link] describes many features
+and techniques used by Stockfish. However, it is generic rather than
+focused on Stockfish's precise implementation.
+
+The engine testing is done on [Fishtest][fishtest-link].
+If you want to help improve Stockfish, please read this [guideline][guideline-link]
+first, where the basics of Stockfish development are explained.
+
+Discussions about Stockfish take place these days mainly in the Stockfish
+[Discord server][discord-link]. This is also the best place to ask questions
+about the codebase and how to improve it.
+
+## Compiling Stockfish
+
+Stockfish has support for 32 or 64-bit CPUs, certain hardware instructions,
+big-endian machines such as Power PC, and other platforms.
+
+On Unix-like systems, it should be easy to compile Stockfish directly from the
+source code with the included Makefile in the folder `src`. In general, it is
+recommended to run `make help` to see a list of make targets with corresponding
+descriptions. An example suitable for most Intel and AMD chips:
+
+```
+cd src
+make -j profile-build
+```
+
+Detailed compilation instructions for all platforms can be found in our
+[documentation][wiki-compile-link]. Our wiki also has information about
+the [UCI commands][wiki-uci-link] supported by Stockfish.
+
+## Terms of use
+
+Stockfish is free and distributed under the
+[**GNU General Public License version 3**][license-link] (GPL v3). Essentially,
+this means you are free to do almost exactly what you want with the program,
+including distributing it among your friends, making it available for download
+from your website, selling it (either by itself or as part of some bigger
+software package), or using it as the starting point for a software project of
+your own.
+
+The only real limitation is that whenever you distribute Stockfish in some way,
+you MUST always include the license and the full source code (or a pointer to
+where the source code can be found) to generate the exact binary you are
+distributing. If you make any changes to the source code, these changes must
+also be made available under GPL v3.
+
+## Acknowledgements
+
+Stockfish uses neural networks trained on [data provided by the Leela Chess Zero
+project][lc0-data-link], which is made available under the [Open Database License][odbl-link] (ODbL).
+
+
+[authors-link]: https://github.com/official-stockfish/Stockfish/blob/master/AUTHORS
+[build-link]: https://github.com/official-stockfish/Stockfish/actions/workflows/stockfish.yml
+[commits-link]: https://github.com/official-stockfish/Stockfish/commits/master
+[discord-link]: https://discord.gg/GWDRS3kU6R
+[issue-link]: https://github.com/official-stockfish/Stockfish/issues/new?assignees=&labels=&template=BUG-REPORT.yml
+[discussions-link]: https://github.com/official-stockfish/Stockfish/discussions/new
+[fishtest-link]: https://tests.stockfishchess.org/tests
+[guideline-link]: https://github.com/official-stockfish/fishtest/wiki/Creating-my-first-test
+[license-link]: https://github.com/official-stockfish/Stockfish/blob/master/Copying.txt
+[programming-link]: https://www.chessprogramming.org/Main_Page
+[programmingsf-link]: https://www.chessprogramming.org/Stockfish
+[readme-link]: https://github.com/official-stockfish/Stockfish/blob/master/README.md
+[release-link]: https://github.com/official-stockfish/Stockfish/releases/latest
+[src-link]: https://github.com/official-stockfish/Stockfish/tree/master/src
+[stockfish128-logo]: https://stockfishchess.org/images/logo/icon_128x128.png
+[uci-link]: https://backscattering.de/chess/uci/
+[website-link]: https://stockfishchess.org
+[website-blog-link]: https://stockfishchess.org/blog/
+[wiki-link]: https://github.com/official-stockfish/Stockfish/wiki
+[wiki-compile-link]: https://github.com/official-stockfish/Stockfish/wiki/Compiling-from-source
+[wiki-uci-link]: https://github.com/official-stockfish/Stockfish/wiki/UCI-&-Commands
+[wiki-usage-link]: https://github.com/official-stockfish/Stockfish/wiki/Download-and-usage
+[worker-link]: https://github.com/official-stockfish/fishtest/wiki/Running-the-worker
+[lc0-data-link]: https://storage.lczero.org/files/training_data
+[odbl-link]: https://opendatacommons.org/licenses/odbl/odbl-10.txt
+
+[build-badge]: https://img.shields.io/github/actions/workflow/status/official-stockfish/Stockfish/stockfish.yml?branch=master&style=for-the-badge&label=stockfish&logo=github
+[commits-badge]: https://img.shields.io/github/commits-since/official-stockfish/Stockfish/latest?style=for-the-badge
+[discord-badge]: https://img.shields.io/discord/435943710472011776?style=for-the-badge&label=discord&logo=Discord
+[fishtest-badge]: https://img.shields.io/website?style=for-the-badge&down_color=red&down_message=Offline&label=Fishtest&up_color=success&up_message=Online&url=https%3A%2F%2Ftests.stockfishchess.org%2Ftests%2Ffinished
+[license-badge]: https://img.shields.io/github/license/official-stockfish/Stockfish?style=for-the-badge&label=license&color=success
+[release-badge]: https://img.shields.io/github/v/release/official-stockfish/Stockfish?style=for-the-badge&label=official%20release
+[website-badge]: https://img.shields.io/website?style=for-the-badge&down_color=red&down_message=Offline&label=website&up_color=success&up_message=Online&url=https%3A%2F%2Fstockfishchess.org
diff --git a/stockfish/Top CPU Contributors.txt b/stockfish/Top CPU Contributors.txt
new file mode 100644
index 0000000000000000000000000000000000000000..4e598ecfc5b3480bdaddc813f30bb66edc325e34
--- /dev/null
+++ b/stockfish/Top CPU Contributors.txt
@@ -0,0 +1,322 @@
+Contributors to Fishtest with >10,000 CPU hours, as of 2025-03-22.
+Thank you!
+
+Username CPU Hours Games played
+------------------------------------------------------------------
+noobpwnftw 41712226 3294628533
+vdv 28993864 954145232
+technologov 24984442 1115931964
+linrock 11463033 741692823
+mlang 3026000 200065824
+okrout 2726068 248285678
+olafm 2420096 161297116
+pemo 1838361 62294199
+TueRens 1804847 80170868
+dew 1689162 100033738
+sebastronomy 1655637 67294942
+grandphish2 1474752 92156319
+JojoM 1130625 73666098
+rpngn 973590 59996557
+oz 921203 60370346
+tvijlbrief 796125 51897690
+gvreuls 792215 55184194
+mibere 703840 46867607
+leszek 599745 44681421
+cw 519602 34988289
+fastgm 503862 30260818
+CSU_Dynasty 474794 31654170
+maximmasiutin 441753 28129452
+robal 437950 28869118
+ctoks 435150 28542141
+crunchy 427414 27371625
+bcross 415724 29061187
+mgrabiak 380202 27586936
+velislav 342588 22140902
+ncfish1 329039 20624527
+Fisherman 327231 21829379
+Sylvain27 317021 11494912
+marrco 310446 19587107
+Dantist 296386 18031762
+Fifis 289595 14969251
+tolkki963 286043 23596996
+Calis007 272677 17281620
+cody 258835 13301710
+nordlandia 249322 16420192
+javran 212141 16507618
+glinscott 208125 13277240
+drabel 204167 13930674
+mhoram 202894 12601997
+bking_US 198894 11876016
+Wencey 198537 9606420
+Thanar 179852 12365359
+sschnee 170521 10891112
+armo9494 168141 11177514
+DesolatedDodo 160605 10392474
+spams 157128 10319326
+maposora 155839 13963260
+sqrt2 147963 9724586
+vdbergh 140514 9242985
+jcAEie 140086 10603658
+CoffeeOne 137100 5024116
+malala 136182 8002293
+Goatminola 134893 11640524
+xoto 133759 9159372
+markkulix 132104 11000548
+naclosagc 131472 4660806
+Dubslow 129685 8527664
+davar 129023 8376525
+DMBK 122960 8980062
+dsmith 122059 7570238
+Wolfgang 120919 8619168
+CypressChess 120902 8683904
+amicic 119661 7938029
+cuistot 116864 7828864
+sterni1971 113754 6054022
+Data 113305 8220352
+BrunoBanani 112960 7436849
+megaman7de 109139 7360928
+skiminki 107583 7218170
+zeryl 104523 6618969
+MaZePallas 102823 6633619
+sunu 100167 7040199
+thirdlife 99178 2246544
+ElbertoOne 99028 7023771
+TataneSan 97257 4239502
+romangol 95662 7784954
+bigpen0r 94825 6529241
+brabos 92118 6186135
+Maxim 90818 3283364
+psk 89957 5984901
+szupaw 89775 7800606
+jromang 87260 5988073
+racerschmacer 85805 6122790
+Vizvezdenec 83761 5344740
+0x3C33 82614 5271253
+Spprtr 82103 5663635
+BRAVONE 81239 5054681
+MarcusTullius 78930 5189659
+Mineta 78731 4947996
+Torom 77978 2651656
+nssy 76497 5259388
+woutboat 76379 6031688
+teddybaer 75125 5407666
+Pking_cda 73776 5293873
+Viren6 73664 1356502
+yurikvelo 73611 5046822
+Bobo1239 70579 4794999
+solarlight 70517 5028306
+dv8silencer 70287 3883992
+manap 66273 4121774
+tinker 64333 4268790
+qurashee 61208 3429862
+DanielMiao1 60181 1317252
+AGI 58316 4336328
+jojo2357 57435 4944212
+robnjr 57262 4053117
+Freja 56938 3733019
+MaxKlaxxMiner 56879 3423958
+ttruscott 56010 3680085
+rkl 55132 4164467
+jmdana 54988 4041917
+notchris 53936 4184018
+renouve 53811 3501516
+CounterFlow 52536 3203740
+finfish 51360 3370515
+eva42 51272 3599691
+eastorwest 51117 3454811
+rap 49985 3219146
+pb00067 49733 3298934
+GPUex 48686 3684998
+OuaisBla 48626 3445134
+ronaldjerum 47654 3240695
+biffhero 46564 3111352
+oryx 46141 3583236
+jibarbosa 45890 4541218
+DeepnessFulled 45734 3944282
+abdicj 45577 2631772
+VoyagerOne 45476 3452465
+mecevdimitar 44240 2584396
+speedycpu 43842 3003273
+jbwiebe 43305 2805433
+gopeto 43046 2821514
+YvesKn 42628 2177630
+Antihistamine 41788 2761312
+mhunt 41735 2691355
+somethingintheshadows 41502 3330418
+homyur 39893 2850481
+gri 39871 2515779
+vidar808 39774 1656372
+Garf 37741 2999686
+SC 37299 2731694
+Gaster319 37229 3289674
+csnodgrass 36207 2688994
+ZacHFX 35528 2486328
+icewulf 34782 2415146
+strelock 34716 2074055
+EthanOConnor 33370 2090311
+slakovv 32915 2021889
+shawnxu 32144 2814668
+Gelma 31771 1551204
+srowen 31181 1732120
+kdave 31157 2198362
+manapbk 30987 1810399
+votoanthuan 30691 2460856
+Prcuvu 30377 2170122
+anst 30301 2190091
+jkiiski 30136 1904470
+spcc 29925 1901692
+hyperbolic.tom 29840 2017394
+chuckstablers 29659 2093438
+Pyafue 29650 1902349
+WoodMan777 29300 2579864
+belzedar94 28846 1811530
+chriswk 26902 1868317
+xwziegtm 26897 2124586
+Jopo12321 26818 1816482
+achambord 26582 1767323
+Patrick_G 26276 1801617
+yorkman 26193 1992080
+Ulysses 25517 1711634
+SFTUser 25182 1675689
+nabildanial 25068 1531665
+Sharaf_DG 24765 1786697
+rodneyc 24376 1416402
+jsys14 24297 1721230
+AndreasKrug 24235 1934711
+agg177 23890 1395014
+Ente 23752 1678188
+JanErik 23408 1703875
+Isidor 23388 1680691
+Norabor 23371 1603244
+Nullvalue 23155 2022752
+fishtester 23115 1581502
+wizardassassin 23073 1789536
+Skiff84 22984 1053680
+cisco2015 22920 1763301
+ols 22914 1322047
+Hjax 22561 1566151
+Zirie 22542 1472937
+team-oh 22272 1636708
+mkstockfishtester 22253 2029566
+Roady 22220 1465606
+MazeOfGalious 21978 1629593
+sg4032 21950 1643373
+tsim67 21939 1343944
+ianh2105 21725 1632562
+Serpensin 21704 1809188
+xor12 21628 1680365
+dex 21612 1467203
+nesoneg 21494 1463031
+IslandLambda 21468 1239756
+user213718 21454 1404128
+sphinx 21211 1384728
+qoo_charly_cai 21136 1514927
+jjoshua2 21001 1423089
+Zake9298 20938 1565848
+horst.prack 20878 1465656
+0xB00B1ES 20590 1208666
+Dinde 20459 1292774
+t3hf1sht3ster 20456 670646
+j3corre 20405 941444
+0x539 20332 1039516
+Adrian.Schmidt123 20316 1281436
+malfoy 20313 1350694
+purpletree 20019 1461026
+wei 19973 1745989
+teenychess 19819 1762006
+rstoesser 19569 1293588
+eudhan 19274 1283717
+nalanzeyu 19211 396674
+vulcan 18871 1729392
+Karpovbot 18766 1053178
+jundery 18445 1115855
+Farseer 18281 1074642
+sebv15 18267 1262588
+whelanh 17887 347974
+ville 17883 1384026
+chris 17698 1487385
+purplefishies 17595 1092533
+dju 17414 981289
+iisiraider 17275 1049015
+Karby 17177 1030688
+DragonLord 17014 1162790
+pirt 16991 1274215
+redstone59 16842 1461780
+Alb11747 16787 1213990
+Naven94 16414 951718
+scuzzi 16155 995347
+IgorLeMasson 16064 1147232
+ako027ako 15671 1173203
+xuhdev 15516 1528278
+infinigon 15285 965966
+Nikolay.IT 15154 1068349
+Andrew Grant 15114 895539
+OssumOpossum 14857 1007129
+LunaticBFF57 14525 1190310
+enedene 14476 905279
+YELNAMRON 14475 1141330
+RickGroszkiewicz 14272 1385984
+joendter 14269 982014
+bpfliegel 14233 882523
+mpx86 14019 759568
+jpulman 13982 870599
+getraideBFF 13871 1172846
+crocogoat 13817 1119086
+Nesa92 13806 1116101
+joster 13710 946160
+mbeier 13650 1044928
+Pablohn26 13552 1088532
+wxt9861 13550 1312306
+Dark_wizzie 13422 1007152
+Rudolphous 13244 883140
+Jackfish 13177 894206
+MooTheCow 13091 892304
+Machariel 13010 863104
+mabichito 12903 749391
+thijsk 12886 722107
+AdrianSA 12860 804972
+Flopzee 12698 894821
+szczur90 12684 977536
+Kyrega 12661 456438
+mschmidt 12644 863193
+korposzczur 12606 838168
+fatmurphy 12547 853210
+Oakwen 12532 855759
+SapphireBrand 12416 969604
+deflectooor 12386 579392
+modolief 12386 896470
+ckaz 12273 754644
+Hongildong 12201 648712
+pgontarz 12151 848794
+dbernier 12103 860824
+FormazChar 12051 913497
+shreven 12044 884734
+rensonthemove 11999 971993
+stocky 11954 699440
+3cho 11842 1036786
+ImperiumAeternum 11482 979142
+infinity 11470 727027
+aga 11412 695127
+Def9Infinity 11408 700682
+torbjo 11395 729145
+Thomas A. Anderson 11372 732094
+savage84 11358 670860
+d64 11263 789184
+ali-al-zhrani 11245 779246
+vaskoul 11144 953906
+snicolet 11106 869170
+dapper 11032 771402
+Ethnikoi 10993 945906
+Snuuka 10938 435504
+Karmatron 10871 678306
+gerbil 10871 1005842
+OliverClarke 10696 942654
+basepi 10637 744851
+michaelrpg 10624 748179
+Cubox 10621 826448
+dragon123118 10421 936506
+OIVAS7572 10420 995586
+GBx3TV 10388 339952
+Garruk 10365 706465
+dzjp 10343 732529
+borinot 10026 902130
diff --git a/stockfish/scripts/get_native_properties.sh b/stockfish/scripts/get_native_properties.sh
new file mode 100644
index 0000000000000000000000000000000000000000..132bd6f484fa724a0f64a8e0c4256ce7157b1932
--- /dev/null
+++ b/stockfish/scripts/get_native_properties.sh
@@ -0,0 +1,153 @@
+#!/bin/sh
+
+#
+# Returns properties of the native system.
+# best architecture as supported by the CPU
+# filename of the best binary uploaded as an artifact during CI
+#
+
+# Check if all the given flags are present in the CPU flags list
+check_flags() {
+ for flag; do
+ printf '%s\n' "$flags" | grep -q -w "$flag" || return 1
+ done
+}
+
+# Set the CPU flags list
+# remove underscores and points from flags, e.g. gcc uses avx512vnni, while some cpuinfo can have avx512_vnni, some systems use sse4_1 others sse4.1
+get_flags() {
+ flags=$(awk '/^flags[ \t]*:|^Features[ \t]*:/{gsub(/^flags[ \t]*:[ \t]*|^Features[ \t]*:[ \t]*|[_.]/, ""); line=$0} END{print line}' /proc/cpuinfo)
+}
+
+# Check for gcc march "znver1" or "znver2" https://en.wikichip.org/wiki/amd/cpuid
+check_znver_1_2() {
+ vendor_id=$(awk '/^vendor_id/{print $3; exit}' /proc/cpuinfo)
+ cpu_family=$(awk '/^cpu family/{print $4; exit}' /proc/cpuinfo)
+ [ "$vendor_id" = "AuthenticAMD" ] && [ "$cpu_family" = "23" ] && znver_1_2=true
+}
+
+# Set the file CPU loongarch64 architecture
+set_arch_loongarch64() {
+ if check_flags 'lasx'; then
+ true_arch='loongarch64-lasx'
+ elif check_flags 'lsx'; then
+ true_arch='lonngarch64-lsx'
+ else
+ true_arch='loongarch64'
+ fi
+}
+
+# Set the file CPU x86_64 architecture
+set_arch_x86_64() {
+ if check_flags 'avx512vnni' 'avx512dq' 'avx512f' 'avx512bw' 'avx512vl'; then
+ true_arch='x86-64-vnni256'
+ elif check_flags 'avx512f' 'avx512bw'; then
+ true_arch='x86-64-avx512'
+ elif [ -z "${znver_1_2+1}" ] && check_flags 'bmi2'; then
+ true_arch='x86-64-bmi2'
+ elif check_flags 'avx2'; then
+ true_arch='x86-64-avx2'
+ elif check_flags 'sse41' && check_flags 'popcnt'; then
+ true_arch='x86-64-sse41-popcnt'
+ else
+ true_arch='x86-64'
+ fi
+}
+
+set_arch_ppc_64() {
+ if $(grep -q -w "altivec" /proc/cpuinfo); then
+ power=$(grep -oP -m 1 'cpu\t+: POWER\K\d+' /proc/cpuinfo)
+ if [ "0$power" -gt 7 ]; then
+ # VSX started with POWER8
+ true_arch='ppc-64-vsx'
+ else
+ true_arch='ppc-64-altivec'
+ fi
+ else
+ true_arch='ppc-64'
+ fi
+}
+
+# Check the system type
+uname_s=$(uname -s)
+uname_m=$(uname -m)
+case $uname_s in
+ 'Darwin') # Mac OSX system
+ case $uname_m in
+ 'arm64')
+ true_arch='apple-silicon'
+ file_arch='m1-apple-silicon'
+ ;;
+ 'x86_64')
+ flags=$(sysctl -n machdep.cpu.features machdep.cpu.leaf7_features | tr '\n' ' ' | tr '[:upper:]' '[:lower:]' | tr -d '_.')
+ set_arch_x86_64
+ if [ "$true_arch" = 'x86-64-vnni256' ] || [ "$true_arch" = 'x86-64-avx512' ]; then
+ file_arch='x86-64-bmi2'
+ fi
+ ;;
+ esac
+ file_os='macos'
+ file_ext='tar'
+ ;;
+ 'Linux') # Linux system
+ get_flags
+ case $uname_m in
+ 'x86_64')
+ file_os='ubuntu'
+ check_znver_1_2
+ set_arch_x86_64
+ ;;
+ 'i686')
+ file_os='ubuntu'
+ true_arch='x86-32'
+ ;;
+ 'ppc64'*)
+ file_os='ubuntu'
+ set_arch_ppc_64
+ ;;
+ 'aarch64')
+ file_os='android'
+ true_arch='armv8'
+ if check_flags 'asimddp'; then
+ true_arch="$true_arch-dotprod"
+ fi
+ ;;
+ 'armv7'*)
+ file_os='android'
+ true_arch='armv7'
+ if check_flags 'neon'; then
+ true_arch="$true_arch-neon"
+ fi
+ ;;
+ 'loongarch64'*)
+ file_os='linux'
+ set_arch_loongarch64
+ ;;
+ *) # Unsupported machine type, exit with error
+ printf 'Unsupported machine type: %s\n' "$uname_m"
+ exit 1
+ ;;
+ esac
+ file_ext='tar'
+ ;;
+ 'CYGWIN'*|'MINGW'*|'MSYS'*) # Windows system with POSIX compatibility layer
+ get_flags
+ check_znver_1_2
+ set_arch_x86_64
+ file_os='windows'
+ file_ext='zip'
+ ;;
+ *)
+ # Unknown system type, exit with error
+ printf 'Unsupported system type: %s\n' "$uname_s"
+ exit 1
+ ;;
+esac
+
+if [ -z "$file_arch" ]; then
+ file_arch=$true_arch
+fi
+
+file_name="stockfish-$file_os-$file_arch.$file_ext"
+
+printf '%s %s\n' "$true_arch" "$file_name"
diff --git a/stockfish/scripts/net.sh b/stockfish/scripts/net.sh
new file mode 100644
index 0000000000000000000000000000000000000000..1aa1fbfb188ea0851491444da1c76874386aa243
--- /dev/null
+++ b/stockfish/scripts/net.sh
@@ -0,0 +1,76 @@
+#!/bin/sh
+
+wget_or_curl=$( (command -v wget > /dev/null 2>&1 && echo "wget -qO-") || \
+ (command -v curl > /dev/null 2>&1 && echo "curl -skL"))
+
+
+sha256sum=$( (command -v shasum > /dev/null 2>&1 && echo "shasum -a 256") || \
+ (command -v sha256sum > /dev/null 2>&1 && echo "sha256sum"))
+
+if [ -z "$sha256sum" ]; then
+ >&2 echo "sha256sum not found, NNUE files will be assumed valid."
+fi
+
+get_nnue_filename() {
+ grep "$1" evaluate.h | grep "#define" | sed "s/.*\(nn-[a-z0-9]\{12\}.nnue\).*/\1/"
+}
+
+validate_network() {
+ # If no sha256sum command is available, assume the file is always valid.
+ if [ -n "$sha256sum" ] && [ -f "$1" ]; then
+ if [ "$1" != "nn-$($sha256sum "$1" | cut -c 1-12).nnue" ]; then
+ rm -f "$1"
+ return 1
+ fi
+ fi
+}
+
+fetch_network() {
+ _filename="$(get_nnue_filename "$1")"
+
+ if [ -z "$_filename" ]; then
+ >&2 echo "NNUE file name not found for: $1"
+ return 1
+ fi
+
+ if [ -f "$_filename" ]; then
+ if validate_network "$_filename"; then
+ echo "Existing $_filename validated, skipping download"
+ return
+ else
+ echo "Removing invalid NNUE file: $_filename"
+ fi
+ fi
+
+ if [ -z "$wget_or_curl" ]; then
+ >&2 printf "%s\n" "Neither wget or curl is installed." \
+ "Install one of these tools to download NNUE files automatically."
+ exit 1
+ fi
+
+ for url in \
+ "https://tests.stockfishchess.org/api/nn/$_filename" \
+ "https://github.com/official-stockfish/networks/raw/master/$_filename"; do
+ echo "Downloading from $url ..."
+ if $wget_or_curl "$url" > "$_filename"; then
+ if validate_network "$_filename"; then
+ echo "Successfully validated $_filename"
+ else
+ echo "Downloaded $_filename is invalid"
+ continue
+ fi
+ else
+ echo "Failed to download from $url"
+ fi
+ if [ -f "$_filename" ]; then
+ return
+ fi
+ done
+
+ # Download was not successful in the loop, return false.
+ >&2 echo "Failed to download $_filename"
+ return 1
+}
+
+fetch_network EvalFileDefaultNameBig && \
+fetch_network EvalFileDefaultNameSmall
diff --git a/stockfish/src/Makefile b/stockfish/src/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..76b94785ecb59a3e58a57325091e1d6cff66723d
--- /dev/null
+++ b/stockfish/src/Makefile
@@ -0,0 +1,1123 @@
+# Stockfish, a UCI chess playing engine derived from Glaurung 2.1
+# Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
+#
+# Stockfish is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Stockfish is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+
+### ==========================================================================
+### Section 1. General Configuration
+### ==========================================================================
+
+### Establish the operating system name
+KERNEL := $(shell uname -s)
+ifeq ($(KERNEL),Linux)
+ OS := $(shell uname -o)
+endif
+
+### Target Windows OS
+ifeq ($(OS),Windows_NT)
+ ifneq ($(COMP),ndk)
+ target_windows = yes
+ endif
+else ifeq ($(COMP),mingw)
+ target_windows = yes
+ ifeq ($(WINE_PATH),)
+ WINE_PATH := $(shell which wine)
+ endif
+endif
+
+### Executable name
+ifeq ($(target_windows),yes)
+ EXE = stockfish.exe
+else
+ EXE = stockfish
+endif
+
+### Installation dir definitions
+PREFIX = /usr/local
+BINDIR = $(PREFIX)/bin
+
+### Built-in benchmark for pgo-builds
+PGOBENCH = $(WINE_PATH) ./$(EXE) bench
+
+### Source and object files
+SRCS = benchmark.cpp bitboard.cpp evaluate.cpp main.cpp \
+ misc.cpp movegen.cpp movepick.cpp position.cpp \
+ search.cpp thread.cpp timeman.cpp tt.cpp uci.cpp ucioption.cpp tune.cpp syzygy/tbprobe.cpp \
+ nnue/nnue_accumulator.cpp nnue/nnue_misc.cpp nnue/features/half_ka_v2_hm.cpp nnue/network.cpp \
+ engine.cpp score.cpp memory.cpp
+
+HEADERS = benchmark.h bitboard.h evaluate.h misc.h movegen.h movepick.h history.h \
+ nnue/nnue_misc.h nnue/features/half_ka_v2_hm.h nnue/layers/affine_transform.h \
+ nnue/layers/affine_transform_sparse_input.h nnue/layers/clipped_relu.h nnue/layers/simd.h \
+ nnue/layers/sqr_clipped_relu.h nnue/nnue_accumulator.h nnue/nnue_architecture.h \
+ nnue/nnue_common.h nnue/nnue_feature_transformer.h position.h \
+ search.h syzygy/tbprobe.h thread.h thread_win32_osx.h timeman.h \
+ tt.h tune.h types.h uci.h ucioption.h perft.h nnue/network.h engine.h score.h numa.h memory.h
+
+OBJS = $(notdir $(SRCS:.cpp=.o))
+
+VPATH = syzygy:nnue:nnue/features
+
+### ==========================================================================
+### Section 2. High-level Configuration
+### ==========================================================================
+#
+# flag --- Comp switch --- Description
+# ----------------------------------------------------------------------------
+#
+# debug = yes/no --- -DNDEBUG --- Enable/Disable debug mode
+# sanitize = none/ ... (-fsanitize )
+# --- ( undefined ) --- enable undefined behavior checks
+# --- ( thread ) --- enable threading error checks
+# --- ( address ) --- enable memory access checks
+# --- ...etc... --- see compiler documentation for supported sanitizers
+# optimize = yes/no --- (-O3/-fast etc.) --- Enable/Disable optimizations
+# arch = (name) --- (-arch) --- Target architecture
+# bits = 64/32 --- -DIS_64BIT --- 64-/32-bit operating system
+# prefetch = yes/no --- -DUSE_PREFETCH --- Use prefetch asm-instruction
+# popcnt = yes/no --- -DUSE_POPCNT --- Use popcnt asm-instruction
+# pext = yes/no --- -DUSE_PEXT --- Use pext x86_64 asm-instruction
+# sse = yes/no --- -msse --- Use Intel Streaming SIMD Extensions
+# mmx = yes/no --- -mmmx --- Use Intel MMX instructions
+# sse2 = yes/no --- -msse2 --- Use Intel Streaming SIMD Extensions 2
+# ssse3 = yes/no --- -mssse3 --- Use Intel Supplemental Streaming SIMD Extensions 3
+# sse41 = yes/no --- -msse4.1 --- Use Intel Streaming SIMD Extensions 4.1
+# avx2 = yes/no --- -mavx2 --- Use Intel Advanced Vector Extensions 2
+# avxvnni = yes/no --- -mavxvnni --- Use Intel Vector Neural Network Instructions AVX
+# avx512 = yes/no --- -mavx512bw --- Use Intel Advanced Vector Extensions 512
+# vnni256 = yes/no --- -mavx256vnni --- Use Intel Vector Neural Network Instructions 512 with 256bit operands
+# vnni512 = yes/no --- -mavx512vnni --- Use Intel Vector Neural Network Instructions 512
+# altivec = yes/no --- -maltivec --- Use PowerPC Altivec SIMD extension
+# vsx = yes/no --- -mvsx --- Use POWER VSX SIMD extension
+# neon = yes/no --- -DUSE_NEON --- Use ARM SIMD architecture
+# dotprod = yes/no --- -DUSE_NEON_DOTPROD --- Use ARM advanced SIMD Int8 dot product instructions
+# lsx = yes/no --- -mlsx --- Use Loongson SIMD eXtension
+# lasx = yes/no --- -mlasx --- use Loongson Advanced SIMD eXtension
+#
+# Note that Makefile is space sensitive, so when adding new architectures
+# or modifying existing flags, you have to make sure there are no extra spaces
+# at the end of the line for flag values.
+#
+# Example of use for these flags:
+# make build ARCH=x86-64-avx512 debug=yes sanitize="address undefined"
+
+
+### 2.1. General and architecture defaults
+
+ifeq ($(ARCH),)
+ ARCH = native
+endif
+
+ifeq ($(ARCH), native)
+ override ARCH := $(shell $(SHELL) ../scripts/get_native_properties.sh | cut -d " " -f 1)
+endif
+
+# explicitly check for the list of supported architectures (as listed with make help),
+# the user can override with `make ARCH=x86-32-vnni256 SUPPORTED_ARCH=true`
+ifeq ($(ARCH), $(filter $(ARCH), \
+ x86-64-vnni512 x86-64-vnni256 x86-64-avx512 x86-64-avxvnni x86-64-bmi2 \
+ x86-64-avx2 x86-64-sse41-popcnt x86-64-modern x86-64-ssse3 x86-64-sse3-popcnt \
+ x86-64 x86-32-sse41-popcnt x86-32-sse2 x86-32 ppc-64 ppc-64-altivec ppc-64-vsx ppc-32 e2k \
+ armv7 armv7-neon armv8 armv8-dotprod apple-silicon general-64 general-32 riscv64 \
+ loongarch64 loongarch64-lsx loongarch64-lasx))
+ SUPPORTED_ARCH=true
+else
+ SUPPORTED_ARCH=false
+endif
+
+optimize = yes
+debug = no
+sanitize = none
+bits = 64
+prefetch = no
+popcnt = no
+pext = no
+sse = no
+mmx = no
+sse2 = no
+ssse3 = no
+sse41 = no
+avx2 = no
+avxvnni = no
+avx512 = no
+vnni256 = no
+vnni512 = no
+altivec = no
+vsx = no
+neon = no
+dotprod = no
+arm_version = 0
+lsx = no
+lasx = no
+STRIP = strip
+
+ifneq ($(shell which clang-format-18 2> /dev/null),)
+ CLANG-FORMAT = clang-format-18
+else
+ CLANG-FORMAT = clang-format
+endif
+
+### 2.2 Architecture specific
+
+ifeq ($(findstring x86,$(ARCH)),x86)
+
+# x86-32/64
+
+ifeq ($(findstring x86-32,$(ARCH)),x86-32)
+ arch = i386
+ bits = 32
+ sse = no
+ mmx = yes
+else
+ arch = x86_64
+ sse = yes
+ sse2 = yes
+endif
+
+ifeq ($(findstring -sse,$(ARCH)),-sse)
+ sse = yes
+endif
+
+ifeq ($(findstring -popcnt,$(ARCH)),-popcnt)
+ popcnt = yes
+endif
+
+ifeq ($(findstring -mmx,$(ARCH)),-mmx)
+ mmx = yes
+endif
+
+ifeq ($(findstring -sse2,$(ARCH)),-sse2)
+ sse = yes
+ sse2 = yes
+endif
+
+ifeq ($(findstring -ssse3,$(ARCH)),-ssse3)
+ sse = yes
+ sse2 = yes
+ ssse3 = yes
+endif
+
+ifeq ($(findstring -sse41,$(ARCH)),-sse41)
+ sse = yes
+ sse2 = yes
+ ssse3 = yes
+ sse41 = yes
+endif
+
+ifeq ($(findstring -modern,$(ARCH)),-modern)
+ $(warning *** ARCH=$(ARCH) is deprecated, defaulting to ARCH=x86-64-sse41-popcnt. Execute `make help` for a list of available architectures. ***)
+ $(shell sleep 5)
+ popcnt = yes
+ sse = yes
+ sse2 = yes
+ ssse3 = yes
+ sse41 = yes
+endif
+
+ifeq ($(findstring -avx2,$(ARCH)),-avx2)
+ popcnt = yes
+ sse = yes
+ sse2 = yes
+ ssse3 = yes
+ sse41 = yes
+ avx2 = yes
+endif
+
+ifeq ($(findstring -avxvnni,$(ARCH)),-avxvnni)
+ popcnt = yes
+ sse = yes
+ sse2 = yes
+ ssse3 = yes
+ sse41 = yes
+ avx2 = yes
+ avxvnni = yes
+ pext = yes
+endif
+
+ifeq ($(findstring -bmi2,$(ARCH)),-bmi2)
+ popcnt = yes
+ sse = yes
+ sse2 = yes
+ ssse3 = yes
+ sse41 = yes
+ avx2 = yes
+ pext = yes
+endif
+
+ifeq ($(findstring -avx512,$(ARCH)),-avx512)
+ popcnt = yes
+ sse = yes
+ sse2 = yes
+ ssse3 = yes
+ sse41 = yes
+ avx2 = yes
+ pext = yes
+ avx512 = yes
+endif
+
+ifeq ($(findstring -vnni256,$(ARCH)),-vnni256)
+ popcnt = yes
+ sse = yes
+ sse2 = yes
+ ssse3 = yes
+ sse41 = yes
+ avx2 = yes
+ pext = yes
+ vnni256 = yes
+endif
+
+ifeq ($(findstring -vnni512,$(ARCH)),-vnni512)
+ popcnt = yes
+ sse = yes
+ sse2 = yes
+ ssse3 = yes
+ sse41 = yes
+ avx2 = yes
+ pext = yes
+ avx512 = yes
+ vnni512 = yes
+endif
+
+ifeq ($(sse),yes)
+ prefetch = yes
+endif
+
+# 64-bit pext is not available on x86-32
+ifeq ($(bits),32)
+ pext = no
+endif
+
+else
+
+# all other architectures
+
+ifeq ($(ARCH),general-32)
+ arch = any
+ bits = 32
+endif
+
+ifeq ($(ARCH),general-64)
+ arch = any
+endif
+
+ifeq ($(ARCH),armv7)
+ arch = armv7
+ prefetch = yes
+ bits = 32
+ arm_version = 7
+endif
+
+ifeq ($(ARCH),armv7-neon)
+ arch = armv7
+ prefetch = yes
+ popcnt = yes
+ neon = yes
+ bits = 32
+ arm_version = 7
+endif
+
+ifeq ($(ARCH),armv8)
+ arch = armv8
+ prefetch = yes
+ popcnt = yes
+ neon = yes
+ arm_version = 8
+endif
+
+ifeq ($(ARCH),armv8-dotprod)
+ arch = armv8
+ prefetch = yes
+ popcnt = yes
+ neon = yes
+ dotprod = yes
+ arm_version = 8
+endif
+
+ifeq ($(ARCH),apple-silicon)
+ arch = arm64
+ prefetch = yes
+ popcnt = yes
+ neon = yes
+ dotprod = yes
+ arm_version = 8
+endif
+
+ifeq ($(ARCH),ppc-32)
+ arch = ppc
+ bits = 32
+endif
+
+ifeq ($(ARCH),ppc-64)
+ arch = ppc64
+ popcnt = yes
+ prefetch = yes
+endif
+
+ifeq ($(ARCH),ppc-64-altivec)
+ arch = ppc64
+ popcnt = yes
+ prefetch = yes
+ altivec = yes
+endif
+
+ifeq ($(ARCH),ppc-64-vsx)
+ arch = ppc64
+ popcnt = yes
+ prefetch = yes
+ vsx = yes
+endif
+
+ifeq ($(findstring e2k,$(ARCH)),e2k)
+ arch = e2k
+ mmx = yes
+ bits = 64
+ sse = yes
+ sse2 = yes
+ ssse3 = yes
+ sse41 = yes
+ popcnt = yes
+endif
+
+ifeq ($(ARCH),riscv64)
+ arch = riscv64
+endif
+
+ifeq ($(findstring loongarch64,$(ARCH)),loongarch64)
+ arch = loongarch64
+ prefetch = yes
+
+ifeq ($(findstring -lasx,$(ARCH)),-lasx)
+ lsx = yes
+ lasx = yes
+endif
+
+ifeq ($(findstring -lsx,$(ARCH)),-lsx)
+ lsx = yes
+endif
+
+endif
+endif
+
+
+### ==========================================================================
+### Section 3. Low-level Configuration
+### ==========================================================================
+
+### 3.1 Selecting compiler (default = gcc)
+ifeq ($(MAKELEVEL),0)
+ export ENV_CXXFLAGS := $(CXXFLAGS)
+ export ENV_DEPENDFLAGS := $(DEPENDFLAGS)
+ export ENV_LDFLAGS := $(LDFLAGS)
+endif
+
+CXXFLAGS = $(ENV_CXXFLAGS) -Wall -Wcast-qual -fno-exceptions -std=c++17 $(EXTRACXXFLAGS)
+DEPENDFLAGS = $(ENV_DEPENDFLAGS) -std=c++17
+LDFLAGS = $(ENV_LDFLAGS) $(EXTRALDFLAGS)
+
+ifeq ($(COMP),)
+ COMP=gcc
+endif
+
+ifeq ($(COMP),gcc)
+ comp=gcc
+ CXX=g++
+ CXXFLAGS += -pedantic -Wextra -Wshadow -Wmissing-declarations
+
+ ifeq ($(arch),$(filter $(arch),armv7 armv8 riscv64))
+ ifeq ($(OS),Android)
+ CXXFLAGS += -m$(bits)
+ LDFLAGS += -m$(bits)
+ endif
+ ifeq ($(ARCH),riscv64)
+ CXXFLAGS += -latomic
+ endif
+ else ifeq ($(arch),loongarch64)
+ CXXFLAGS += -latomic
+ else
+ CXXFLAGS += -m$(bits)
+ LDFLAGS += -m$(bits)
+ endif
+
+ ifeq ($(arch),$(filter $(arch),armv7))
+ LDFLAGS += -latomic
+ endif
+
+ ifneq ($(KERNEL),Darwin)
+ LDFLAGS += -Wl,--no-as-needed
+ endif
+endif
+
+ifeq ($(target_windows),yes)
+ LDFLAGS += -static
+endif
+
+ifeq ($(COMP),mingw)
+ comp=mingw
+
+ ifeq ($(bits),64)
+ ifeq ($(shell which x86_64-w64-mingw32-c++-posix 2> /dev/null),)
+ CXX=x86_64-w64-mingw32-c++
+ else
+ CXX=x86_64-w64-mingw32-c++-posix
+ endif
+ else
+ ifeq ($(shell which i686-w64-mingw32-c++-posix 2> /dev/null),)
+ CXX=i686-w64-mingw32-c++
+ else
+ CXX=i686-w64-mingw32-c++-posix
+ endif
+ endif
+ CXXFLAGS += -pedantic -Wextra -Wshadow -Wmissing-declarations
+endif
+
+ifeq ($(COMP),icx)
+ comp=icx
+ CXX=icpx
+ CXXFLAGS += --intel -pedantic -Wextra -Wshadow -Wmissing-prototypes \
+ -Wconditional-uninitialized -Wabi -Wdeprecated
+endif
+
+ifeq ($(COMP),clang)
+ comp=clang
+ CXX=clang++
+ ifeq ($(target_windows),yes)
+ CXX=x86_64-w64-mingw32-clang++
+ endif
+
+ CXXFLAGS += -pedantic -Wextra -Wshadow -Wmissing-prototypes \
+ -Wconditional-uninitialized
+
+ ifeq ($(filter $(KERNEL),Darwin OpenBSD FreeBSD),)
+ ifeq ($(target_windows),)
+ ifneq ($(RTLIB),compiler-rt)
+ LDFLAGS += -latomic
+ endif
+ endif
+ endif
+
+ ifeq ($(arch),$(filter $(arch),armv7 armv8 riscv64))
+ ifeq ($(OS),Android)
+ CXXFLAGS += -m$(bits)
+ LDFLAGS += -m$(bits)
+ endif
+ ifeq ($(ARCH),riscv64)
+ CXXFLAGS += -latomic
+ endif
+ else ifeq ($(arch),loongarch64)
+ CXXFLAGS += -latomic
+ else
+ CXXFLAGS += -m$(bits)
+ LDFLAGS += -m$(bits)
+ endif
+endif
+
+ifeq ($(KERNEL),Darwin)
+ CXXFLAGS += -mmacosx-version-min=10.15
+ LDFLAGS += -mmacosx-version-min=10.15
+ ifneq ($(arch),any)
+ CXXFLAGS += -arch $(arch)
+ LDFLAGS += -arch $(arch)
+ endif
+ XCRUN = xcrun
+endif
+
+# To cross-compile for Android, NDK version r21 or later is recommended.
+# In earlier NDK versions, you'll need to pass -fno-addrsig if using GNU binutils.
+# Currently we don't know how to make PGO builds with the NDK yet.
+ifeq ($(COMP),ndk)
+ CXXFLAGS += -stdlib=libc++ -fPIE
+ comp=clang
+ ifeq ($(arch),armv7)
+ CXX=armv7a-linux-androideabi16-clang++
+ CXXFLAGS += -mthumb -march=armv7-a -mfloat-abi=softfp -mfpu=neon
+ ifneq ($(shell which arm-linux-androideabi-strip 2>/dev/null),)
+ STRIP=arm-linux-androideabi-strip
+ else
+ STRIP=llvm-strip
+ endif
+ endif
+ ifeq ($(arch),armv8)
+ CXX=aarch64-linux-android21-clang++
+ ifneq ($(shell which aarch64-linux-android-strip 2>/dev/null),)
+ STRIP=aarch64-linux-android-strip
+ else
+ STRIP=llvm-strip
+ endif
+ endif
+ ifeq ($(arch),x86_64)
+ CXX=x86_64-linux-android21-clang++
+ ifneq ($(shell which x86_64-linux-android-strip 2>/dev/null),)
+ STRIP=x86_64-linux-android-strip
+ else
+ STRIP=llvm-strip
+ endif
+ endif
+ LDFLAGS += -static-libstdc++ -pie -lm -latomic
+endif
+
+ifeq ($(comp),icx)
+ profile_make = icx-profile-make
+ profile_use = icx-profile-use
+else ifeq ($(comp),clang)
+ profile_make = clang-profile-make
+ profile_use = clang-profile-use
+else
+ profile_make = gcc-profile-make
+ profile_use = gcc-profile-use
+ ifeq ($(KERNEL),Darwin)
+ EXTRAPROFILEFLAGS = -fvisibility=hidden
+ endif
+endif
+
+### Allow overwriting CXX from command line
+ifdef COMPCXX
+ CXX=$(COMPCXX)
+endif
+
+### Sometimes gcc is really clang
+ifeq ($(COMP),gcc)
+ gccversion := $(shell $(CXX) --version 2>/dev/null)
+ gccisclang := $(findstring clang,$(gccversion))
+ ifneq ($(gccisclang),)
+ profile_make = clang-profile-make
+ profile_use = clang-profile-use
+ endif
+endif
+
+### On mingw use Windows threads, otherwise POSIX
+ifneq ($(comp),mingw)
+ CXXFLAGS += -DUSE_PTHREADS
+ # On Android Bionic's C library comes with its own pthread implementation bundled in
+ ifneq ($(OS),Android)
+ # Haiku has pthreads in its libroot, so only link it in on other platforms
+ ifneq ($(KERNEL),Haiku)
+ ifneq ($(COMP),ndk)
+ LDFLAGS += -lpthread
+ endif
+ endif
+ endif
+endif
+
+### 3.2.1 Debugging
+ifeq ($(debug),no)
+ CXXFLAGS += -DNDEBUG
+else
+ CXXFLAGS += -g
+endif
+
+### 3.2.2 Debugging with undefined behavior sanitizers
+ifneq ($(sanitize),none)
+ CXXFLAGS += -g3 $(addprefix -fsanitize=,$(sanitize))
+ LDFLAGS += $(addprefix -fsanitize=,$(sanitize))
+endif
+
+### 3.3 Optimization
+ifeq ($(optimize),yes)
+
+ CXXFLAGS += -O3 -funroll-loops
+
+ ifeq ($(comp),gcc)
+ ifeq ($(OS), Android)
+ CXXFLAGS += -fno-gcse -mthumb -march=armv7-a -mfloat-abi=softfp
+ endif
+ endif
+
+ ifeq ($(KERNEL),Darwin)
+ ifeq ($(comp),$(filter $(comp),clang icx))
+ CXXFLAGS += -mdynamic-no-pic
+ endif
+
+ ifeq ($(comp),gcc)
+ ifneq ($(arch),arm64)
+ CXXFLAGS += -mdynamic-no-pic
+ endif
+ endif
+ endif
+
+ ifeq ($(comp),clang)
+ clangmajorversion := $(shell $(CXX) -dumpversion 2>/dev/null | cut -f1 -d.)
+ ifeq ($(shell expr $(clangmajorversion) \< 16),1)
+ CXXFLAGS += -fexperimental-new-pass-manager
+ endif
+ endif
+endif
+
+### 3.4 Bits
+ifeq ($(bits),64)
+ CXXFLAGS += -DIS_64BIT
+endif
+
+### 3.5 prefetch and popcount
+ifeq ($(prefetch),yes)
+ ifeq ($(sse),yes)
+ CXXFLAGS += -msse
+ endif
+else
+ CXXFLAGS += -DNO_PREFETCH
+endif
+
+ifeq ($(popcnt),yes)
+ ifeq ($(arch),$(filter $(arch),ppc64 ppc64-altivec ppc64-vsx armv7 armv8 arm64))
+ CXXFLAGS += -DUSE_POPCNT
+ else
+ CXXFLAGS += -msse3 -mpopcnt -DUSE_POPCNT
+ endif
+endif
+
+### 3.6 SIMD architectures
+ifeq ($(avx2),yes)
+ CXXFLAGS += -DUSE_AVX2
+ ifeq ($(comp),$(filter $(comp),gcc clang mingw icx))
+ CXXFLAGS += -mavx2 -mbmi
+ endif
+endif
+
+ifeq ($(avxvnni),yes)
+ CXXFLAGS += -DUSE_VNNI -DUSE_AVXVNNI
+ ifeq ($(comp),$(filter $(comp),gcc clang mingw icx))
+ CXXFLAGS += -mavxvnni
+ endif
+endif
+
+ifeq ($(avx512),yes)
+ CXXFLAGS += -DUSE_AVX512
+ ifeq ($(comp),$(filter $(comp),gcc clang mingw icx))
+ CXXFLAGS += -mavx512f -mavx512bw
+ endif
+endif
+
+ifeq ($(vnni256),yes)
+ CXXFLAGS += -DUSE_VNNI
+ ifeq ($(comp),$(filter $(comp),gcc clang mingw icx))
+ CXXFLAGS += -mavx512f -mavx512bw -mavx512vnni -mavx512dq -mavx512vl -mprefer-vector-width=256
+ endif
+endif
+
+ifeq ($(vnni512),yes)
+ CXXFLAGS += -DUSE_VNNI
+ ifeq ($(comp),$(filter $(comp),gcc clang mingw icx))
+ CXXFLAGS += -mavx512f -mavx512bw -mavx512vnni -mavx512dq -mavx512vl -mprefer-vector-width=512
+ endif
+endif
+
+ifeq ($(sse41),yes)
+ CXXFLAGS += -DUSE_SSE41
+ ifeq ($(comp),$(filter $(comp),gcc clang mingw icx))
+ CXXFLAGS += -msse4.1
+ endif
+endif
+
+ifeq ($(ssse3),yes)
+ CXXFLAGS += -DUSE_SSSE3
+ ifeq ($(comp),$(filter $(comp),gcc clang mingw icx))
+ CXXFLAGS += -mssse3
+ endif
+endif
+
+ifeq ($(sse2),yes)
+ CXXFLAGS += -DUSE_SSE2
+ ifeq ($(comp),$(filter $(comp),gcc clang mingw icx))
+ CXXFLAGS += -msse2
+ endif
+endif
+
+ifeq ($(mmx),yes)
+ ifeq ($(comp),$(filter $(comp),gcc clang mingw icx))
+ CXXFLAGS += -mmmx
+ endif
+endif
+
+ifeq ($(altivec),yes)
+ CXXFLAGS += -maltivec
+ ifeq ($(COMP),gcc)
+ CXXFLAGS += -mabi=altivec
+ endif
+endif
+
+ifeq ($(vsx),yes)
+ CXXFLAGS += -mvsx
+ ifeq ($(COMP),gcc)
+ CXXFLAGS += -DNO_WARN_X86_INTRINSICS -DUSE_SSE2
+ endif
+endif
+
+ifeq ($(neon),yes)
+ CXXFLAGS += -DUSE_NEON=$(arm_version)
+ ifeq ($(KERNEL),Linux)
+ ifneq ($(COMP),ndk)
+ ifneq ($(arch),armv8)
+ CXXFLAGS += -mfpu=neon
+ endif
+ endif
+ endif
+endif
+
+ifeq ($(dotprod),yes)
+ CXXFLAGS += -march=armv8.2-a+dotprod -DUSE_NEON_DOTPROD
+endif
+
+ifeq ($(lasx),yes)
+ ifeq ($(comp),$(filter $(comp),gcc clang mingw icx))
+ CXXFLAGS += -mlasx
+ endif
+endif
+
+ifeq ($(lsx),yes)
+ ifeq ($(comp),$(filter $(comp),gcc clang mingw icx))
+ CXXFLAGS += -mlsx
+ endif
+endif
+
+### 3.7 pext
+ifeq ($(pext),yes)
+ CXXFLAGS += -DUSE_PEXT
+ ifeq ($(comp),$(filter $(comp),gcc clang mingw icx))
+ CXXFLAGS += -mbmi2
+ endif
+endif
+
+### 3.8.1 Try to include git commit sha for versioning
+GIT_SHA := $(shell git rev-parse HEAD 2>/dev/null | cut -c 1-8)
+ifneq ($(GIT_SHA), )
+ CXXFLAGS += -DGIT_SHA=$(GIT_SHA)
+endif
+
+### 3.8.2 Try to include git commit date for versioning
+GIT_DATE := $(shell git show -s --date=format:'%Y%m%d' --format=%cd HEAD 2>/dev/null)
+ifneq ($(GIT_DATE), )
+ CXXFLAGS += -DGIT_DATE=$(GIT_DATE)
+endif
+
+### 3.8.3 Try to include architecture
+ifneq ($(ARCH), )
+ CXXFLAGS += -DARCH=$(ARCH)
+endif
+
+### 3.9 Link Time Optimization
+### This is a mix of compile and link time options because the lto link phase
+### needs access to the optimization flags.
+ifeq ($(optimize),yes)
+ifeq ($(debug), no)
+ ifeq ($(comp),$(filter $(comp),clang icx))
+ CXXFLAGS += -flto=full
+ ifeq ($(comp),icx)
+ CXXFLAGS += -fwhole-program-vtables
+ endif
+ ifeq ($(target_windows),yes)
+ CXXFLAGS += -fuse-ld=lld
+ endif
+ LDFLAGS += $(CXXFLAGS)
+
+# GCC and CLANG use different methods for parallelizing LTO and CLANG pretends to be
+# GCC on some systems.
+ else ifeq ($(comp),gcc)
+ ifeq ($(gccisclang),)
+ CXXFLAGS += -flto -flto-partition=one
+ LDFLAGS += $(CXXFLAGS) -flto=jobserver
+ else
+ CXXFLAGS += -flto=full
+ LDFLAGS += $(CXXFLAGS)
+ endif
+
+# To use LTO and static linking on Windows,
+# the tool chain requires gcc version 10.1 or later.
+ else ifeq ($(comp),mingw)
+ CXXFLAGS += -flto -flto-partition=one
+ LDFLAGS += $(CXXFLAGS) -save-temps
+ endif
+endif
+endif
+
+### 3.10 Android 5 can only run position independent executables. Note that this
+### breaks Android 4.0 and earlier.
+ifeq ($(OS), Android)
+ CXXFLAGS += -fPIE
+ LDFLAGS += -fPIE -pie
+endif
+
+### ==========================================================================
+### Section 4. Public Targets
+### ==========================================================================
+
+help:
+ @echo "" && \
+ echo "To compile stockfish, type: " && \
+ echo "" && \
+ echo "make -j target [ARCH=arch] [COMP=compiler] [COMPCXX=cxx]" && \
+ echo "" && \
+ echo "Supported targets:" && \
+ echo "" && \
+ echo "help > Display architecture details" && \
+ echo "profile-build > standard build with profile-guided optimization" && \
+ echo "build > skip profile-guided optimization" && \
+ echo "net > Download the default nnue nets" && \
+ echo "strip > Strip executable" && \
+ echo "install > Install executable" && \
+ echo "clean > Clean up" && \
+ echo "" && \
+ echo "Supported archs:" && \
+ echo "" && \
+ echo "native > select the best architecture for the host processor (default)" && \
+ echo "x86-64-vnni512 > x86 64-bit with vnni 512bit support" && \
+ echo "x86-64-vnni256 > x86 64-bit with vnni 512bit support, limit operands to 256bit wide" && \
+ echo "x86-64-avx512 > x86 64-bit with avx512 support" && \
+ echo "x86-64-avxvnni > x86 64-bit with vnni 256bit support" && \
+ echo "x86-64-bmi2 > x86 64-bit with bmi2 support" && \
+ echo "x86-64-avx2 > x86 64-bit with avx2 support" && \
+ echo "x86-64-sse41-popcnt > x86 64-bit with sse41 and popcnt support" && \
+ echo "x86-64-modern > deprecated, currently x86-64-sse41-popcnt" && \
+ echo "x86-64-ssse3 > x86 64-bit with ssse3 support" && \
+ echo "x86-64-sse3-popcnt > x86 64-bit with sse3 compile and popcnt support" && \
+ echo "x86-64 > x86 64-bit generic (with sse2 support)" && \
+ echo "x86-32-sse41-popcnt > x86 32-bit with sse41 and popcnt support" && \
+ echo "x86-32-sse2 > x86 32-bit with sse2 support" && \
+ echo "x86-32 > x86 32-bit generic (with mmx compile support)" && \
+ echo "ppc-64 > PPC 64-bit" && \
+ echo "ppc-64-altivec > PPC 64-bit with altivec support" && \
+ echo "ppc-64-vsx > PPC 64-bit with vsx support" && \
+ echo "ppc-32 > PPC 32-bit" && \
+ echo "armv7 > ARMv7 32-bit" && \
+ echo "armv7-neon > ARMv7 32-bit with popcnt and neon" && \
+ echo "armv8 > ARMv8 64-bit with popcnt and neon" && \
+ echo "armv8-dotprod > ARMv8 64-bit with popcnt, neon and dot product support" && \
+ echo "e2k > Elbrus 2000" && \
+ echo "apple-silicon > Apple silicon ARM64" && \
+ echo "general-64 > unspecified 64-bit" && \
+ echo "general-32 > unspecified 32-bit" && \
+ echo "riscv64 > RISC-V 64-bit" && \
+ echo "loongarch64 > LoongArch 64-bit" && \
+ echo "loongarch64-lsx > LoongArch 64-bit with SIMD eXtension" && \
+ echo "loongarch64-lasx > LoongArch 64-bit with Advanced SIMD eXtension" && \
+ echo "" && \
+ echo "Supported compilers:" && \
+ echo "" && \
+ echo "gcc > GNU compiler (default)" && \
+ echo "mingw > GNU compiler with MinGW under Windows" && \
+ echo "clang > LLVM Clang compiler" && \
+ echo "icx > Intel oneAPI DPC++/C++ Compiler" && \
+ echo "ndk > Google NDK to cross-compile for Android" && \
+ echo "" && \
+ echo "Simple examples. If you don't know what to do, you likely want to run one of: " && \
+ echo "" && \
+ echo "make -j profile-build ARCH=x86-64-avx2 # typically a fast compile for common systems " && \
+ echo "make -j profile-build ARCH=x86-64-sse41-popcnt # A more portable compile for 64-bit systems " && \
+ echo "make -j profile-build ARCH=x86-64 # A portable compile for 64-bit systems " && \
+ echo "" && \
+ echo "Advanced examples, for experienced users: " && \
+ echo "" && \
+ echo "make -j profile-build ARCH=x86-64-avxvnni" && \
+ echo "make -j profile-build ARCH=x86-64-avxvnni COMP=gcc COMPCXX=g++-12.0" && \
+ echo "make -j build ARCH=x86-64-ssse3 COMP=clang" && \
+ echo ""
+ifneq ($(SUPPORTED_ARCH), true)
+ @echo "Specify a supported architecture with the ARCH option for more details"
+ @echo ""
+endif
+
+
+.PHONY: help analyze build profile-build strip install clean net \
+ objclean profileclean config-sanity \
+ icx-profile-use icx-profile-make \
+ gcc-profile-use gcc-profile-make \
+ clang-profile-use clang-profile-make FORCE \
+ format analyze
+
+analyze: net config-sanity objclean
+ $(MAKE) -k ARCH=$(ARCH) COMP=$(COMP) $(OBJS)
+
+build: net config-sanity
+ $(MAKE) ARCH=$(ARCH) COMP=$(COMP) all
+
+profile-build: net config-sanity objclean profileclean
+ @echo ""
+ @echo "Step 1/4. Building instrumented executable ..."
+ $(MAKE) ARCH=$(ARCH) COMP=$(COMP) $(profile_make)
+ @echo ""
+ @echo "Step 2/4. Running benchmark for pgo-build ..."
+ $(PGOBENCH) > PGOBENCH.out 2>&1
+ tail -n 4 PGOBENCH.out
+ @echo ""
+ @echo "Step 3/4. Building optimized executable ..."
+ $(MAKE) ARCH=$(ARCH) COMP=$(COMP) objclean
+ $(MAKE) ARCH=$(ARCH) COMP=$(COMP) $(profile_use)
+ @echo ""
+ @echo "Step 4/4. Deleting profile data ..."
+ $(MAKE) ARCH=$(ARCH) COMP=$(COMP) profileclean
+
+strip:
+ $(STRIP) $(EXE)
+
+install:
+ -mkdir -p -m 755 $(BINDIR)
+ -cp $(EXE) $(BINDIR)
+ $(STRIP) $(BINDIR)/$(EXE)
+
+# clean all
+clean: objclean profileclean
+ @rm -f .depend *~ core
+
+# clean binaries and objects
+objclean:
+ @rm -f stockfish stockfish.exe *.o ./syzygy/*.o ./nnue/*.o ./nnue/features/*.o
+
+# clean auxiliary profiling files
+profileclean:
+ @rm -rf profdir
+ @rm -f bench.txt *.gcda *.gcno ./syzygy/*.gcda ./nnue/*.gcda ./nnue/features/*.gcda *.s PGOBENCH.out
+ @rm -f stockfish.profdata *.profraw
+ @rm -f stockfish.*args*
+ @rm -f stockfish.*lt*
+ @rm -f stockfish.res
+ @rm -f ./-lstdc++.res
+
+# evaluation network (nnue)
+net:
+ @$(SHELL) ../scripts/net.sh
+
+format:
+ $(CLANG-FORMAT) -i $(SRCS) $(HEADERS) -style=file
+
+# default target
+default:
+ help
+
+### ==========================================================================
+### Section 5. Private Targets
+### ==========================================================================
+
+all: $(EXE) .depend
+
+config-sanity: net
+ @echo ""
+ @echo "Config:" && \
+ echo "debug: '$(debug)'" && \
+ echo "sanitize: '$(sanitize)'" && \
+ echo "optimize: '$(optimize)'" && \
+ echo "arch: '$(arch)'" && \
+ echo "bits: '$(bits)'" && \
+ echo "kernel: '$(KERNEL)'" && \
+ echo "os: '$(OS)'" && \
+ echo "prefetch: '$(prefetch)'" && \
+ echo "popcnt: '$(popcnt)'" && \
+ echo "pext: '$(pext)'" && \
+ echo "sse: '$(sse)'" && \
+ echo "mmx: '$(mmx)'" && \
+ echo "sse2: '$(sse2)'" && \
+ echo "ssse3: '$(ssse3)'" && \
+ echo "sse41: '$(sse41)'" && \
+ echo "avx2: '$(avx2)'" && \
+ echo "avxvnni: '$(avxvnni)'" && \
+ echo "avx512: '$(avx512)'" && \
+ echo "vnni256: '$(vnni256)'" && \
+ echo "vnni512: '$(vnni512)'" && \
+ echo "altivec: '$(altivec)'" && \
+ echo "vsx: '$(vsx)'" && \
+ echo "neon: '$(neon)'" && \
+ echo "dotprod: '$(dotprod)'" && \
+ echo "arm_version: '$(arm_version)'" && \
+ echo "lsx: '$(lsx)'" && \
+ echo "lasx: '$(lasx)'" && \
+ echo "target_windows: '$(target_windows)'" && \
+ echo "" && \
+ echo "Flags:" && \
+ echo "CXX: $(CXX)" && \
+ echo "CXXFLAGS: $(CXXFLAGS)" && \
+ echo "LDFLAGS: $(LDFLAGS)" && \
+ echo "" && \
+ echo "Testing config sanity. If this fails, try 'make help' ..." && \
+ echo "" && \
+ (test "$(debug)" = "yes" || test "$(debug)" = "no") && \
+ (test "$(optimize)" = "yes" || test "$(optimize)" = "no") && \
+ (test "$(SUPPORTED_ARCH)" = "true") && \
+ (test "$(arch)" = "any" || test "$(arch)" = "x86_64" || test "$(arch)" = "i386" || \
+ test "$(arch)" = "ppc64" || test "$(arch)" = "ppc" || test "$(arch)" = "e2k" || \
+ test "$(arch)" = "armv7" || test "$(arch)" = "armv8" || test "$(arch)" = "arm64" || \
+ test "$(arch)" = "riscv64" || test "$(arch)" = "loongarch64") && \
+ (test "$(bits)" = "32" || test "$(bits)" = "64") && \
+ (test "$(prefetch)" = "yes" || test "$(prefetch)" = "no") && \
+ (test "$(popcnt)" = "yes" || test "$(popcnt)" = "no") && \
+ (test "$(pext)" = "yes" || test "$(pext)" = "no") && \
+ (test "$(sse)" = "yes" || test "$(sse)" = "no") && \
+ (test "$(mmx)" = "yes" || test "$(mmx)" = "no") && \
+ (test "$(sse2)" = "yes" || test "$(sse2)" = "no") && \
+ (test "$(ssse3)" = "yes" || test "$(ssse3)" = "no") && \
+ (test "$(sse41)" = "yes" || test "$(sse41)" = "no") && \
+ (test "$(avx2)" = "yes" || test "$(avx2)" = "no") && \
+ (test "$(avx512)" = "yes" || test "$(avx512)" = "no") && \
+ (test "$(vnni256)" = "yes" || test "$(vnni256)" = "no") && \
+ (test "$(vnni512)" = "yes" || test "$(vnni512)" = "no") && \
+ (test "$(altivec)" = "yes" || test "$(altivec)" = "no") && \
+ (test "$(vsx)" = "yes" || test "$(vsx)" = "no") && \
+ (test "$(neon)" = "yes" || test "$(neon)" = "no") && \
+ (test "$(lsx)" = "yes" || test "$(lsx)" = "no") && \
+ (test "$(lasx)" = "yes" || test "$(lasx)" = "no") && \
+ (test "$(comp)" = "gcc" || test "$(comp)" = "icx" || test "$(comp)" = "mingw" || \
+ test "$(comp)" = "clang" || test "$(comp)" = "armv7a-linux-androideabi16-clang" || \
+ test "$(comp)" = "aarch64-linux-android21-clang")
+
+$(EXE): $(OBJS)
+ +$(CXX) -o $@ $(OBJS) $(LDFLAGS)
+
+# Force recompilation to ensure version info is up-to-date
+misc.o: FORCE
+FORCE:
+
+clang-profile-make:
+ $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
+ EXTRACXXFLAGS='-fprofile-generate ' \
+ EXTRALDFLAGS=' -fprofile-generate' \
+ all
+
+clang-profile-use:
+ $(XCRUN) llvm-profdata merge -output=stockfish.profdata *.profraw
+ $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
+ EXTRACXXFLAGS='-fprofile-use=stockfish.profdata' \
+ EXTRALDFLAGS='-fprofile-use ' \
+ all
+
+gcc-profile-make:
+ @mkdir -p profdir
+ $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
+ EXTRACXXFLAGS='-fprofile-generate=profdir' \
+ EXTRACXXFLAGS+=$(EXTRAPROFILEFLAGS) \
+ EXTRALDFLAGS='-lgcov' \
+ all
+
+gcc-profile-use:
+ $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
+ EXTRACXXFLAGS='-fprofile-use=profdir -fno-peel-loops -fno-tracer' \
+ EXTRACXXFLAGS+=$(EXTRAPROFILEFLAGS) \
+ EXTRALDFLAGS='-lgcov' \
+ all
+
+icx-profile-make:
+ $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
+ EXTRACXXFLAGS='-fprofile-instr-generate ' \
+ EXTRALDFLAGS=' -fprofile-instr-generate' \
+ all
+
+icx-profile-use:
+ $(XCRUN) llvm-profdata merge -output=stockfish.profdata *.profraw
+ $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
+ EXTRACXXFLAGS='-fprofile-instr-use=stockfish.profdata' \
+ EXTRALDFLAGS='-fprofile-use ' \
+ all
+
+.depend: $(SRCS)
+ -@$(CXX) $(DEPENDFLAGS) -MM $(SRCS) > $@ 2> /dev/null
+
+ifeq (, $(filter $(MAKECMDGOALS), help strip install clean net objclean profileclean config-sanity))
+-include .depend
+endif
diff --git a/stockfish/src/benchmark.cpp b/stockfish/src/benchmark.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a9f70f10d1a715fd1ce4f365c826a03c2ce8575e
--- /dev/null
+++ b/stockfish/src/benchmark.cpp
@@ -0,0 +1,512 @@
+/*
+ Stockfish, a UCI chess playing engine derived from Glaurung 2.1
+ Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
+
+ Stockfish is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Stockfish is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "benchmark.h"
+#include "numa.h"
+
+#include
+#include
+#include
+#include
+
+namespace {
+
+// clang-format off
+const std::vector Defaults = {
+ "setoption name UCI_Chess960 value false",
+ "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
+ "r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 10",
+ "8/2p5/3p4/KP5r/1R3p1k/8/4P1P1/8 w - - 0 11",
+ "4rrk1/pp1n3p/3q2pQ/2p1pb2/2PP4/2P3N1/P2B2PP/4RRK1 b - - 7 19",
+ "rq3rk1/ppp2ppp/1bnpb3/3N2B1/3NP3/7P/PPPQ1PP1/2KR3R w - - 7 14 moves d4e6",
+ "r1bq1r1k/1pp1n1pp/1p1p4/4p2Q/4Pp2/1BNP4/PPP2PPP/3R1RK1 w - - 2 14 moves g2g4",
+ "r3r1k1/2p2ppp/p1p1bn2/8/1q2P3/2NPQN2/PPP3PP/R4RK1 b - - 2 15",
+ "r1bbk1nr/pp3p1p/2n5/1N4p1/2Np1B2/8/PPP2PPP/2KR1B1R w kq - 0 13",
+ "r1bq1rk1/ppp1nppp/4n3/3p3Q/3P4/1BP1B3/PP1N2PP/R4RK1 w - - 1 16",
+ "4r1k1/r1q2ppp/ppp2n2/4P3/5Rb1/1N1BQ3/PPP3PP/R5K1 w - - 1 17",
+ "2rqkb1r/ppp2p2/2npb1p1/1N1Nn2p/2P1PP2/8/PP2B1PP/R1BQK2R b KQ - 0 11",
+ "r1bq1r1k/b1p1npp1/p2p3p/1p6/3PP3/1B2NN2/PP3PPP/R2Q1RK1 w - - 1 16",
+ "3r1rk1/p5pp/bpp1pp2/8/q1PP1P2/b3P3/P2NQRPP/1R2B1K1 b - - 6 22",
+ "r1q2rk1/2p1bppp/2Pp4/p6b/Q1PNp3/4B3/PP1R1PPP/2K4R w - - 2 18",
+ "4k2r/1pb2ppp/1p2p3/1R1p4/3P4/2r1PN2/P4PPP/1R4K1 b - - 3 22",
+ "3q2k1/pb3p1p/4pbp1/2r5/PpN2N2/1P2P2P/5PP1/Q2R2K1 b - - 4 26",
+ "6k1/6p1/6Pp/ppp5/3pn2P/1P3K2/1PP2P2/3N4 b - - 0 1",
+ "3b4/5kp1/1p1p1p1p/pP1PpP1P/P1P1P3/3KN3/8/8 w - - 0 1",
+ "2K5/p7/7P/5pR1/8/5k2/r7/8 w - - 0 1 moves g5g6 f3e3 g6g5 e3f3",
+ "8/6pk/1p6/8/PP3p1p/5P2/4KP1q/3Q4 w - - 0 1",
+ "7k/3p2pp/4q3/8/4Q3/5Kp1/P6b/8 w - - 0 1",
+ "8/2p5/8/2kPKp1p/2p4P/2P5/3P4/8 w - - 0 1",
+ "8/1p3pp1/7p/5P1P/2k3P1/8/2K2P2/8 w - - 0 1",
+ "8/pp2r1k1/2p1p3/3pP2p/1P1P1P1P/P5KR/8/8 w - - 0 1",
+ "8/3p4/p1bk3p/Pp6/1Kp1PpPp/2P2P1P/2P5/5B2 b - - 0 1",
+ "5k2/7R/4P2p/5K2/p1r2P1p/8/8/8 b - - 0 1",
+ "6k1/6p1/P6p/r1N5/5p2/7P/1b3PP1/4R1K1 w - - 0 1",
+ "1r3k2/4q3/2Pp3b/3Bp3/2Q2p2/1p1P2P1/1P2KP2/3N4 w - - 0 1",
+ "6k1/4pp1p/3p2p1/P1pPb3/R7/1r2P1PP/3B1P2/6K1 w - - 0 1",
+ "8/3p3B/5p2/5P2/p7/PP5b/k7/6K1 w - - 0 1",
+ "5rk1/q6p/2p3bR/1pPp1rP1/1P1Pp3/P3B1Q1/1K3P2/R7 w - - 93 90",
+ "4rrk1/1p1nq3/p7/2p1P1pp/3P2bp/3Q1Bn1/PPPB4/1K2R1NR w - - 40 21",
+ "r3k2r/3nnpbp/q2pp1p1/p7/Pp1PPPP1/4BNN1/1P5P/R2Q1RK1 w kq - 0 16",
+ "3Qb1k1/1r2ppb1/pN1n2q1/Pp1Pp1Pr/4P2p/4BP2/4B1R1/1R5K b - - 11 40",
+ "4k3/3q1r2/1N2r1b1/3ppN2/2nPP3/1B1R2n1/2R1Q3/3K4 w - - 5 1",
+
+ // 5-man positions
+ "8/8/8/8/5kp1/P7/8/1K1N4 w - - 0 1", // Kc2 - mate
+ "8/8/8/5N2/8/p7/8/2NK3k w - - 0 1", // Na2 - mate
+ "8/3k4/8/8/8/4B3/4KB2/2B5 w - - 0 1", // draw
+
+ // 6-man positions
+ "8/8/1P6/5pr1/8/4R3/7k/2K5 w - - 0 1", // Re5 - mate
+ "8/2p4P/8/kr6/6R1/8/8/1K6 w - - 0 1", // Ka2 - mate
+ "8/8/3P3k/8/1p6/8/1P6/1K3n2 b - - 0 1", // Nd2 - draw
+
+ // 7-man positions
+ "8/R7/2q5/8/6k1/8/1P5p/K6R w - - 0 124", // Draw
+
+ // Mate and stalemate positions
+ "6k1/3b3r/1p1p4/p1n2p2/1PPNpP1q/P3Q1p1/1R1RB1P1/5K2 b - - 0 1",
+ "r2r1n2/pp2bk2/2p1p2p/3q4/3PN1QP/2P3R1/P4PP1/5RK1 w - - 0 1",
+ "8/8/8/8/8/6k1/6p1/6K1 w - -",
+ "7k/7P/6K1/8/3B4/8/8/8 b - -",
+
+ // Chess 960
+ "setoption name UCI_Chess960 value true",
+ "bbqnnrkr/pppppppp/8/8/8/8/PPPPPPPP/BBQNNRKR w HFhf - 0 1 moves g2g3 d7d5 d2d4 c8h3 c1g5 e8d6 g5e7 f7f6",
+ "nqbnrkrb/pppppppp/8/8/8/8/PPPPPPPP/NQBNRKRB w KQkq - 0 1",
+ "setoption name UCI_Chess960 value false"
+};
+// clang-format on
+
+// clang-format off
+// human-randomly picked 5 games with <60 moves from
+// https://tests.stockfishchess.org/tests/view/665c71f9fd45fb0f907c21e0
+// only moves for one side
+const std::vector> BenchmarkPositions = {
+ {
+ "rnbq1k1r/ppp1bppp/4pn2/8/2B5/2NP1N2/PPP2PPP/R1BQR1K1 b - - 2 8",
+ "rnbq1k1r/pp2bppp/4pn2/2p5/2B2B2/2NP1N2/PPP2PPP/R2QR1K1 b - - 1 9",
+ "r1bq1k1r/pp2bppp/2n1pn2/2p5/2B1NB2/3P1N2/PPP2PPP/R2QR1K1 b - - 3 10",
+ "r1bq1k1r/pp2bppp/2n1p3/2p5/2B1PB2/5N2/PPP2PPP/R2QR1K1 b - - 0 11",
+ "r1b2k1r/pp2bppp/2n1p3/2p5/2B1PB2/5N2/PPP2PPP/3RR1K1 b - - 0 12",
+ "r1b1k2r/pp2bppp/2n1p3/2p5/2B1PB2/2P2N2/PP3PPP/3RR1K1 b - - 0 13",
+ "r1b1k2r/1p2bppp/p1n1p3/2p5/4PB2/2P2N2/PP2BPPP/3RR1K1 b - - 1 14",
+ "r1b1k2r/4bppp/p1n1p3/1pp5/P3PB2/2P2N2/1P2BPPP/3RR1K1 b - - 0 15",
+ "r1b1k2r/4bppp/p1n1p3/1P6/2p1PB2/2P2N2/1P2BPPP/3RR1K1 b - - 0 16",
+ "r1b1k2r/4bppp/2n1p3/1p6/2p1PB2/1PP2N2/4BPPP/3RR1K1 b - - 0 17",
+ "r3k2r/3bbppp/2n1p3/1p6/2P1PB2/2P2N2/4BPPP/3RR1K1 b - - 0 18",
+ "r3k2r/3bbppp/2n1p3/8/1pP1P3/2P2N2/3BBPPP/3RR1K1 b - - 1 19",
+ "1r2k2r/3bbppp/2n1p3/8/1pPNP3/2P5/3BBPPP/3RR1K1 b - - 3 20",
+ "1r2k2r/3bbppp/2n1p3/8/2PNP3/2B5/4BPPP/3RR1K1 b - - 0 21",
+ "1r2k2r/3bb1pp/2n1pp2/1N6/2P1P3/2B5/4BPPP/3RR1K1 b - - 1 22",
+ "1r2k2r/3b2pp/2n1pp2/1N6/1BP1P3/8/4BPPP/3RR1K1 b - - 0 23",
+ "1r2k2r/3b2pp/4pp2/1N6/1nP1P3/8/3RBPPP/4R1K1 b - - 1 24",
+ "1r5r/3bk1pp/4pp2/1N6/1nP1PP2/8/3RB1PP/4R1K1 b - - 0 25",
+ "1r5r/3bk1pp/2n1pp2/1N6/2P1PP2/8/3RBKPP/4R3 b - - 2 26",
+ "1r5r/3bk1pp/2n2p2/1N2p3/2P1PP2/6P1/3RBK1P/4R3 b - - 0 27",
+ "1r1r4/3bk1pp/2n2p2/1N2p3/2P1PP2/6P1/3RBK1P/R7 b - - 2 28",
+ "1r1r4/N3k1pp/2n1bp2/4p3/2P1PP2/6P1/3RBK1P/R7 b - - 4 29",
+ "1r1r4/3bk1pp/2N2p2/4p3/2P1PP2/6P1/3RBK1P/R7 b - - 0 30",
+ "1r1R4/4k1pp/2b2p2/4p3/2P1PP2/6P1/4BK1P/R7 b - - 0 31",
+ "3r4/4k1pp/2b2p2/4P3/2P1P3/6P1/4BK1P/R7 b - - 0 32",
+ "3r4/R3k1pp/2b5/4p3/2P1P3/6P1/4BK1P/8 b - - 1 33",
+ "8/3rk1pp/2b5/R3p3/2P1P3/6P1/4BK1P/8 b - - 3 34",
+ "8/3r2pp/2bk4/R1P1p3/4P3/6P1/4BK1P/8 b - - 0 35",
+ "8/2kr2pp/2b5/R1P1p3/4P3/4K1P1/4B2P/8 b - - 2 36",
+ "1k6/3r2pp/2b5/RBP1p3/4P3/4K1P1/7P/8 b - - 4 37",
+ "8/1k1r2pp/2b5/R1P1p3/4P3/3BK1P1/7P/8 b - - 6 38",
+ "1k6/3r2pp/2b5/2P1p3/4P3/3BK1P1/7P/R7 b - - 8 39",
+ "1k6/r5pp/2b5/2P1p3/4P3/3BK1P1/7P/5R2 b - - 10 40",
+ "1k3R2/6pp/2b5/2P1p3/4P3/r2BK1P1/7P/8 b - - 12 41",
+ "5R2/2k3pp/2b5/2P1p3/4P3/r2B2P1/3K3P/8 b - - 14 42",
+ "5R2/2k3pp/2b5/2P1p3/4P3/3BK1P1/r6P/8 b - - 16 43",
+ "5R2/2k3pp/2b5/2P1p3/4P3/r2B2P1/4K2P/8 b - - 18 44",
+ "5R2/2k3pp/2b5/2P1p3/4P3/3B1KP1/r6P/8 b - - 20 45",
+ "8/2k2Rpp/2b5/2P1p3/4P3/r2B1KP1/7P/8 b - - 22 46",
+ "3k4/5Rpp/2b5/2P1p3/4P3/r2B2P1/4K2P/8 b - - 24 47",
+ "3k4/5Rpp/2b5/2P1p3/4P3/3B1KP1/r6P/8 b - - 26 48",
+ "3k4/5Rpp/2b5/2P1p3/4P3/r2B2P1/4K2P/8 b - - 28 49",
+ "3k4/5Rpp/2b5/2P1p3/4P3/3BK1P1/r6P/8 b - - 30 50",
+ "3k4/5Rpp/2b5/2P1p3/4P3/r2B2P1/3K3P/8 b - - 32 51",
+ "3k4/5Rpp/2b5/2P1p3/4P3/2KB2P1/r6P/8 b - - 34 52",
+ "3k4/5Rpp/2b5/2P1p3/4P3/r2B2P1/2K4P/8 b - - 36 53",
+ "3k4/5Rpp/2b5/2P1p3/4P3/1K1B2P1/r6P/8 b - - 38 54",
+ "3k4/6Rp/2b5/2P1p3/4P3/1K1B2P1/7r/8 b - - 0 55",
+ "3k4/8/2b3Rp/2P1p3/4P3/1K1B2P1/7r/8 b - - 1 56",
+ "8/2k3R1/2b4p/2P1p3/4P3/1K1B2P1/7r/8 b - - 3 57",
+ "3k4/8/2b3Rp/2P1p3/4P3/1K1B2P1/7r/8 b - - 5 58",
+ "8/2k5/2b3Rp/2P1p3/1K2P3/3B2P1/7r/8 b - - 7 59",
+ "8/2k5/2b3Rp/2P1p3/4P3/2KB2P1/3r4/8 b - - 9 60",
+ "8/2k5/2b3Rp/2P1p3/1K2P3/3B2P1/6r1/8 b - - 11 61",
+ "8/2k5/2b3Rp/2P1p3/4P3/2KB2P1/3r4/8 b - - 13 62",
+ "8/2k5/2b3Rp/2P1p3/2K1P3/3B2P1/6r1/8 b - - 15 63",
+ "4b3/2k3R1/7p/2P1p3/2K1P3/3B2P1/6r1/8 b - - 17 64",
+ },
+ {
+ "r1bqkbnr/npp1pppp/p7/3P4/4pB2/2N5/PPP2PPP/R2QKBNR w KQkq - 1 6",
+ "r1bqkb1r/npp1pppp/p4n2/3P4/4pB2/2N5/PPP1QPPP/R3KBNR w KQkq - 3 7",
+ "r2qkb1r/npp1pppp/p4n2/3P1b2/4pB2/2N5/PPP1QPPP/2KR1BNR w kq - 5 8",
+ "r2qkb1r/1pp1pppp/p4n2/1n1P1b2/4pB2/2N4P/PPP1QPP1/2KR1BNR w kq - 1 9",
+ "r2qkb1r/1pp1pppp/5n2/1p1P1b2/4pB2/7P/PPP1QPP1/2KR1BNR w kq - 0 10",
+ "r2qkb1r/1ppbpppp/5n2/1Q1P4/4pB2/7P/PPP2PP1/2KR1BNR w kq - 1 11",
+ "3qkb1r/1Qpbpppp/5n2/3P4/4pB2/7P/rPP2PP1/2KR1BNR w k - 0 12",
+ "q3kb1r/1Qpbpppp/5n2/3P4/4pB2/7P/rPP2PP1/1K1R1BNR w k - 2 13",
+ "r3kb1r/2pbpppp/5n2/3P4/4pB2/7P/1PP2PP1/1K1R1BNR w k - 0 14",
+ "r3kb1r/2Bb1ppp/4pn2/3P4/4p3/7P/1PP2PP1/1K1R1BNR w k - 0 15",
+ "r3kb1r/2Bb2pp/4pn2/8/4p3/7P/1PP2PP1/1K1R1BNR w k - 0 16",
+ "r3k2r/2Bb2pp/4pn2/2b5/4p3/7P/1PP1NPP1/1K1R1B1R w k - 2 17",
+ "r6r/2Bbk1pp/4pn2/2b5/3Np3/7P/1PP2PP1/1K1R1B1R w - - 4 18",
+ "r6r/b2bk1pp/4pn2/4B3/3Np3/7P/1PP2PP1/1K1R1B1R w - - 6 19",
+ "r1r5/b2bk1pp/4pn2/4B3/2BNp3/7P/1PP2PP1/1K1R3R w - - 8 20",
+ "r7/b2bk1pp/4pn2/2r1B3/2BNp3/1P5P/2P2PP1/1K1R3R w - - 1 21",
+ "rb6/3bk1pp/4pn2/2r1B3/2BNpP2/1P5P/2P3P1/1K1R3R w - - 1 22",
+ "1r6/3bk1pp/4pn2/2r5/2BNpP2/1P5P/2P3P1/1K1R3R w - - 0 23",
+ "1r6/3bk1p1/4pn1p/2r5/2BNpP2/1P5P/2P3P1/2KR3R w - - 0 24",
+ "8/3bk1p1/1r2pn1p/2r5/2BNpP1P/1P6/2P3P1/2KR3R w - - 1 25",
+ "8/3bk3/1r2pnpp/2r5/2BNpP1P/1P6/2P3P1/2K1R2R w - - 0 26",
+ "2b5/4k3/1r2pnpp/2r5/2BNpP1P/1P4P1/2P5/2K1R2R w - - 1 27",
+ "8/1b2k3/1r2pnpp/2r5/2BNpP1P/1P4P1/2P5/2K1R1R1 w - - 3 28",
+ "8/1b1nk3/1r2p1pp/2r5/2BNpPPP/1P6/2P5/2K1R1R1 w - - 1 29",
+ "8/1b2k3/1r2p1pp/2r1nP2/2BNp1PP/1P6/2P5/2K1R1R1 w - - 1 30",
+ "8/1b2k3/1r2p1p1/2r1nPp1/2BNp2P/1P6/2P5/2K1R1R1 w - - 0 31",
+ "8/1b2k3/1r2p1n1/2r3p1/2BNp2P/1P6/2P5/2K1R1R1 w - - 0 32",
+ "8/1b2k3/1r2p1n1/6r1/2BNp2P/1P6/2P5/2K1R3 w - - 0 33",
+ "8/1b2k3/1r2p3/4n1P1/2BNp3/1P6/2P5/2K1R3 w - - 1 34",
+ "8/1b2k3/1r2p3/4n1P1/2BN4/1P2p3/2P5/2K4R w - - 0 35",
+ "8/1b2k3/1r2p2R/6P1/2nN4/1P2p3/2P5/2K5 w - - 0 36",
+ "8/1b2k3/3rp2R/6P1/2PN4/4p3/2P5/2K5 w - - 1 37",
+ "8/4k3/3rp2R/6P1/2PN4/2P1p3/6b1/2K5 w - - 1 38",
+ "8/4k3/r3p2R/2P3P1/3N4/2P1p3/6b1/2K5 w - - 1 39",
+ "8/3k4/r3p2R/2P2NP1/8/2P1p3/6b1/2K5 w - - 3 40",
+ "8/3k4/4p2R/2P3P1/8/2P1N3/6b1/r1K5 w - - 1 41",
+ "8/3k4/4p2R/2P3P1/8/2P1N3/3K2b1/6r1 w - - 3 42",
+ "8/3k4/4p2R/2P3P1/8/2PKNb2/8/6r1 w - - 5 43",
+ "8/4k3/4p1R1/2P3P1/8/2PKNb2/8/6r1 w - - 7 44",
+ "8/4k3/4p1R1/2P3P1/3K4/2P1N3/8/6rb w - - 9 45",
+ "8/3k4/4p1R1/2P1K1P1/8/2P1N3/8/6rb w - - 11 46",
+ "8/3k4/4p1R1/2P3P1/5K2/2P1N3/8/4r2b w - - 13 47",
+ "8/3k4/2b1p2R/2P3P1/5K2/2P1N3/8/4r3 w - - 15 48",
+ "8/3k4/2b1p3/2P3P1/5K2/2P1N2R/8/6r1 w - - 17 49",
+ "2k5/7R/2b1p3/2P3P1/5K2/2P1N3/8/6r1 w - - 19 50",
+ "2k5/7R/4p3/2P3P1/b1P2K2/4N3/8/6r1 w - - 1 51",
+ "2k5/3bR3/4p3/2P3P1/2P2K2/4N3/8/6r1 w - - 3 52",
+ "3k4/3b2R1/4p3/2P3P1/2P2K2/4N3/8/6r1 w - - 5 53",
+ "3kb3/6R1/4p1P1/2P5/2P2K2/4N3/8/6r1 w - - 1 54",
+ "3kb3/6R1/4p1P1/2P5/2P2KN1/8/8/2r5 w - - 3 55",
+ "3kb3/6R1/4p1P1/2P1N3/2P2K2/8/8/5r2 w - - 5 56",
+ "3kb3/6R1/4p1P1/2P1N3/2P5/4K3/8/4r3 w - - 7 57",
+ },
+ {
+ "rnbq1rk1/ppp1npb1/4p1p1/3P3p/3PP3/2N2N2/PP2BPPP/R1BQ1RK1 b - - 0 8",
+ "rnbq1rk1/ppp1npb1/6p1/3pP2p/3P4/2N2N2/PP2BPPP/R1BQ1RK1 b - - 0 9",
+ "rn1q1rk1/ppp1npb1/6p1/3pP2p/3P2b1/2N2N2/PP2BPPP/R1BQR1K1 b - - 2 10",
+ "r2q1rk1/ppp1npb1/2n3p1/3pP2p/3P2bN/2N5/PP2BPPP/R1BQR1K1 b - - 4 11",
+ "r4rk1/pppqnpb1/2n3p1/3pP2p/3P2bN/2N4P/PP2BPP1/R1BQR1K1 b - - 0 12",
+ "r4rk1/pppqnpb1/2n3p1/3pP2p/3P3N/7P/PP2NPP1/R1BQR1K1 b - - 0 13",
+ "r4rk1/pppq1pb1/2n3p1/3pPN1p/3P4/7P/PP2NPP1/R1BQR1K1 b - - 0 14",
+ "r4rk1/ppp2pb1/2n3p1/3pPq1p/3P1N2/7P/PP3PP1/R1BQR1K1 b - - 1 15",
+ "r4rk1/pppq1pb1/2n3p1/3pP2p/P2P1N2/7P/1P3PP1/R1BQR1K1 b - - 0 16",
+ "r2n1rk1/pppq1pb1/6p1/3pP2p/P2P1N2/R6P/1P3PP1/2BQR1K1 b - - 2 17",
+ "r4rk1/pppq1pb1/4N1p1/3pP2p/P2P4/R6P/1P3PP1/2BQR1K1 b - - 0 18",
+ "r4rk1/ppp2pb1/4q1p1/3pP1Bp/P2P4/R6P/1P3PP1/3QR1K1 b - - 1 19",
+ "r3r1k1/ppp2pb1/4q1p1/3pP1Bp/P2P1P2/R6P/1P4P1/3QR1K1 b - - 0 20",
+ "r3r1k1/ppp3b1/4qpp1/3pP2p/P2P1P1B/R6P/1P4P1/3QR1K1 b - - 1 21",
+ "r3r1k1/ppp3b1/4q1p1/3pP2p/P4P1B/R6P/1P4P1/3QR1K1 b - - 0 22",
+ "r4rk1/ppp3b1/4q1p1/3pP1Bp/P4P2/R6P/1P4P1/3QR1K1 b - - 2 23",
+ "r4rk1/pp4b1/4q1p1/2ppP1Bp/P4P2/3R3P/1P4P1/3QR1K1 b - - 1 24",
+ "r4rk1/pp4b1/4q1p1/2p1P1Bp/P2p1PP1/3R3P/1P6/3QR1K1 b - - 0 25",
+ "r4rk1/pp4b1/4q1p1/2p1P1B1/P2p1PP1/3R4/1P6/3QR1K1 b - - 0 26",
+ "r5k1/pp3rb1/4q1p1/2p1P1B1/P2p1PP1/6R1/1P6/3QR1K1 b - - 2 27",
+ "5rk1/pp3rb1/4q1p1/2p1P1B1/P2pRPP1/6R1/1P6/3Q2K1 b - - 4 28",
+ "5rk1/1p3rb1/p3q1p1/P1p1P1B1/3pRPP1/6R1/1P6/3Q2K1 b - - 0 29",
+ "4r1k1/1p3rb1/p3q1p1/P1p1P1B1/3pRPP1/1P4R1/8/3Q2K1 b - - 0 30",
+ "4r1k1/5rb1/pP2q1p1/2p1P1B1/3pRPP1/1P4R1/8/3Q2K1 b - - 0 31",
+ "4r1k1/5rb1/pq4p1/2p1P1B1/3pRPP1/1P4R1/4Q3/6K1 b - - 1 32",
+ "4r1k1/1r4b1/pq4p1/2p1P1B1/3pRPP1/1P4R1/2Q5/6K1 b - - 3 33",
+ "4r1k1/1r4b1/1q4p1/p1p1P1B1/3p1PP1/1P4R1/2Q5/4R1K1 b - - 1 34",
+ "4r1k1/3r2b1/1q4p1/p1p1P1B1/2Qp1PP1/1P4R1/8/4R1K1 b - - 3 35",
+ "4r1k1/3r2b1/4q1p1/p1p1P1B1/2Qp1PP1/1P4R1/5K2/4R3 b - - 5 36",
+ "4r1k1/3r2b1/6p1/p1p1P1B1/2Pp1PP1/6R1/5K2/4R3 b - - 0 37",
+ "4r1k1/3r2b1/6p1/p1p1P1B1/2P2PP1/3p2R1/5K2/3R4 b - - 1 38",
+ "5rk1/3r2b1/6p1/p1p1P1B1/2P2PP1/3p2R1/8/3RK3 b - - 3 39",
+ "5rk1/6b1/6p1/p1p1P1B1/2Pr1PP1/3R4/8/3RK3 b - - 0 40",
+ "5rk1/3R2b1/6p1/p1p1P1B1/2r2PP1/8/8/3RK3 b - - 1 41",
+ "5rk1/3R2b1/6p1/p1p1P1B1/4rPP1/8/3K4/3R4 b - - 3 42",
+ "1r4k1/3R2b1/6p1/p1p1P1B1/4rPP1/2K5/8/3R4 b - - 5 43",
+ "1r4k1/3R2b1/6p1/p1p1P1B1/2K2PP1/4r3/8/3R4 b - - 7 44",
+ "1r3bk1/8/3R2p1/p1p1P1B1/2K2PP1/4r3/8/3R4 b - - 9 45",
+ "1r3bk1/8/6R1/2p1P1B1/p1K2PP1/4r3/8/3R4 b - - 0 46",
+ "1r3b2/5k2/R7/2p1P1B1/p1K2PP1/4r3/8/3R4 b - - 2 47",
+ "5b2/1r3k2/R7/2p1P1B1/p1K2PP1/4r3/8/7R b - - 4 48",
+ "5b2/5k2/R7/2pKP1B1/pr3PP1/4r3/8/7R b - - 6 49",
+ "5b2/5k2/R1K5/2p1P1B1/p2r1PP1/4r3/8/7R b - - 8 50",
+ "8/R4kb1/2K5/2p1P1B1/p2r1PP1/4r3/8/7R b - - 10 51",
+ "8/R5b1/2K3k1/2p1PPB1/p2r2P1/4r3/8/7R b - - 0 52",
+ "8/6R1/2K5/2p1PPk1/p2r2P1/4r3/8/7R b - - 0 53",
+ "8/6R1/2K5/2p1PP2/p2r1kP1/4r3/8/5R2 b - - 2 54",
+ "8/6R1/2K2P2/2p1P3/p2r2P1/4r1k1/8/5R2 b - - 0 55",
+ "8/5PR1/2K5/2p1P3/p2r2P1/4r3/6k1/5R2 b - - 0 56",
+ },
+ {
+ "rn1qkb1r/p1pbpppp/5n2/8/2pP4/2N5/1PQ1PPPP/R1B1KBNR w KQkq - 0 7",
+ "r2qkb1r/p1pbpppp/2n2n2/8/2pP4/2N2N2/1PQ1PPPP/R1B1KB1R w KQkq - 2 8",
+ "r2qkb1r/p1pbpppp/5n2/8/1npPP3/2N2N2/1PQ2PPP/R1B1KB1R w KQkq - 1 9",
+ "r2qkb1r/p1pb1ppp/4pn2/8/1npPP3/2N2N2/1P3PPP/R1BQKB1R w KQkq - 0 10",
+ "r2qk2r/p1pbbppp/4pn2/8/1nBPP3/2N2N2/1P3PPP/R1BQK2R w KQkq - 1 11",
+ "r2q1rk1/p1pbbppp/4pn2/8/1nBPP3/2N2N2/1P3PPP/R1BQ1RK1 w - - 3 12",
+ "r2q1rk1/2pbbppp/p3pn2/8/1nBPPB2/2N2N2/1P3PPP/R2Q1RK1 w - - 0 13",
+ "r2q1rk1/2p1bppp/p3pn2/1b6/1nBPPB2/2N2N2/1P3PPP/R2QR1K1 w - - 2 14",
+ "r2q1rk1/4bppp/p1p1pn2/1b6/1nBPPB2/1PN2N2/5PPP/R2QR1K1 w - - 0 15",
+ "r4rk1/3qbppp/p1p1pn2/1b6/1nBPPB2/1PN2N2/3Q1PPP/R3R1K1 w - - 2 16",
+ "r4rk1/1q2bppp/p1p1pn2/1b6/1nBPPB2/1PN2N1P/3Q1PP1/R3R1K1 w - - 1 17",
+ "r3r1k1/1q2bppp/p1p1pn2/1b6/1nBPPB2/1PN2N1P/4QPP1/R3R1K1 w - - 3 18",
+ "r3r1k1/1q1nbppp/p1p1p3/1b6/1nBPPB2/1PN2N1P/4QPP1/3RR1K1 w - - 5 19",
+ "r3rbk1/1q1n1ppp/p1p1p3/1b6/1nBPPB2/1PN2N1P/3RQPP1/4R1K1 w - - 7 20",
+ "r3rbk1/1q3ppp/pnp1p3/1b6/1nBPPB2/1PN2N1P/3RQPP1/4R2K w - - 9 21",
+ "2r1rbk1/1q3ppp/pnp1p3/1b6/1nBPPB2/1PN2N1P/3RQPP1/1R5K w - - 11 22",
+ "2r1rbk1/1q4pp/pnp1pp2/1b6/1nBPPB2/1PN2N1P/4QPP1/1R1R3K w - - 0 23",
+ "2r1rbk1/5qpp/pnp1pp2/1b6/1nBPP3/1PN1BN1P/4QPP1/1R1R3K w - - 2 24",
+ "2r1rbk1/5qp1/pnp1pp1p/1b6/1nBPP3/1PN1BN1P/4QPP1/1R1R2K1 w - - 0 25",
+ "2r1rbk1/5qp1/pnp1pp1p/1b6/2BPP3/1P2BN1P/n3QPP1/1R1R2K1 w - - 0 26",
+ "r3rbk1/5qp1/pnp1pp1p/1b6/2BPP3/1P2BN1P/Q4PP1/1R1R2K1 w - - 1 27",
+ "rr3bk1/5qp1/pnp1pp1p/1b6/2BPP3/1P2BN1P/Q4PP1/R2R2K1 w - - 3 28",
+ "rr2qbk1/6p1/pnp1pp1p/1b6/2BPP3/1P2BN1P/4QPP1/R2R2K1 w - - 5 29",
+ "rr2qbk1/6p1/1np1pp1p/pb6/2BPP3/1P1QBN1P/5PP1/R2R2K1 w - - 0 30",
+ "rr2qbk1/6p1/1n2pp1p/pp6/3PP3/1P1QBN1P/5PP1/R2R2K1 w - - 0 31",
+ "rr2qbk1/6p1/1n2pp1p/1p1P4/p3P3/1P1QBN1P/5PP1/R2R2K1 w - - 0 32",
+ "rr2qbk1/3n2p1/3Ppp1p/1p6/p3P3/1P1QBN1P/5PP1/R2R2K1 w - - 1 33",
+ "rr3bk1/3n2p1/3Ppp1p/1p5q/pP2P3/3QBN1P/5PP1/R2R2K1 w - - 1 34",
+ "rr3bk1/3n2p1/3Ppp1p/1p5q/1P2P3/p2QBN1P/5PP1/2RR2K1 w - - 0 35",
+ "1r3bk1/3n2p1/r2Ppp1p/1p5q/1P2P3/pQ2BN1P/5PP1/2RR2K1 w - - 2 36",
+ "1r2qbk1/2Rn2p1/r2Ppp1p/1p6/1P2P3/pQ2BN1P/5PP1/3R2K1 w - - 4 37",
+ "1r2qbk1/2Rn2p1/r2Ppp1p/1pB5/1P2P3/1Q3N1P/p4PP1/3R2K1 w - - 0 38",
+ "1r2q1k1/2Rn2p1/r2bpp1p/1pB5/1P2P3/1Q3N1P/p4PP1/R5K1 w - - 0 39",
+ "1r2q1k1/2Rn2p1/3rpp1p/1p6/1P2P3/1Q3N1P/p4PP1/R5K1 w - - 0 40",
+ "2r1q1k1/2Rn2p1/3rpp1p/1p6/1P2P3/5N1P/Q4PP1/R5K1 w - - 1 41",
+ "1r2q1k1/1R1n2p1/3rpp1p/1p6/1P2P3/5N1P/Q4PP1/R5K1 w - - 3 42",
+ "2r1q1k1/2Rn2p1/3rpp1p/1p6/1P2P3/5N1P/Q4PP1/R5K1 w - - 5 43",
+ "1r2q1k1/1R1n2p1/3rpp1p/1p6/1P2P3/5N1P/Q4PP1/R5K1 w - - 7 44",
+ "1rq3k1/R2n2p1/3rpp1p/1p6/1P2P3/5N1P/Q4PP1/R5K1 w - - 9 45",
+ "2q3k1/Rr1n2p1/3rpp1p/1p6/1P2P3/5N1P/4QPP1/R5K1 w - - 11 46",
+ "Rrq3k1/3n2p1/3rpp1p/1p6/1P2P3/5N1P/4QPP1/R5K1 w - - 13 47",
+ },
+ {
+ "rn1qkb1r/1pp2ppp/p4p2/3p1b2/5P2/1P2PN2/P1PP2PP/RN1QKB1R b KQkq - 1 6",
+ "r2qkb1r/1pp2ppp/p1n2p2/3p1b2/3P1P2/1P2PN2/P1P3PP/RN1QKB1R b KQkq - 0 7",
+ "r2qkb1r/1pp2ppp/p4p2/3p1b2/1n1P1P2/1P1BPN2/P1P3PP/RN1QK2R b KQkq - 2 8",
+ "r2qkb1r/1pp2ppp/p4p2/3p1b2/3P1P2/1P1PPN2/P5PP/RN1QK2R b KQkq - 0 9",
+ "r2qk2r/1pp2ppp/p2b1p2/3p1b2/3P1P2/1PNPPN2/P5PP/R2QK2R b KQkq - 2 10",
+ "r2qk2r/1p3ppp/p1pb1p2/3p1b2/3P1P2/1PNPPN2/P5PP/R2Q1RK1 b kq - 1 11",
+ "r2q1rk1/1p3ppp/p1pb1p2/3p1b2/3P1P2/1PNPPN2/P2Q2PP/R4RK1 b - - 3 12",
+ "r2qr1k1/1p3ppp/p1pb1p2/3p1b2/3P1P2/1P1PPN2/P2QN1PP/R4RK1 b - - 5 13",
+ "r3r1k1/1p3ppp/pqpb1p2/3p1b2/3P1P2/1P1PPNN1/P2Q2PP/R4RK1 b - - 7 14",
+ "r3r1k1/1p3ppp/pqp2p2/3p1b2/1b1P1P2/1P1PPNN1/P1Q3PP/R4RK1 b - - 9 15",
+ "r3r1k1/1p1b1ppp/pqp2p2/3p4/1b1P1P2/1P1PPNN1/P4QPP/R4RK1 b - - 11 16",
+ "2r1r1k1/1p1b1ppp/pqp2p2/3p4/1b1PPP2/1P1P1NN1/P4QPP/R4RK1 b - - 0 17",
+ "2r1r1k1/1p1b1ppp/pq3p2/2pp4/1b1PPP2/PP1P1NN1/5QPP/R4RK1 b - - 0 18",
+ "2r1r1k1/1p1b1ppp/pq3p2/2Pp4/4PP2/PPbP1NN1/5QPP/R4RK1 b - - 0 19",
+ "2r1r1k1/1p1b1ppp/p4p2/2Pp4/4PP2/PqbP1NN1/5QPP/RR4K1 b - - 1 20",
+ "2r1r1k1/1p1b1ppp/p4p2/2Pp4/q3PP2/P1bP1NN1/R4QPP/1R4K1 b - - 3 21",
+ "2r1r1k1/1p3ppp/p4p2/1bPP4/q4P2/P1bP1NN1/R4QPP/1R4K1 b - - 0 22",
+ "2r1r1k1/1p3ppp/p4p2/2PP4/q4P2/P1bb1NN1/R4QPP/2R3K1 b - - 1 23",
+ "2r1r1k1/1p3ppp/p2P1p2/2P5/2q2P2/P1bb1NN1/R4QPP/2R3K1 b - - 0 24",
+ "2rr2k1/1p3ppp/p2P1p2/2P5/2q2P2/P1bb1NN1/R4QPP/2R4K b - - 2 25",
+ "2rr2k1/1p3ppp/p2P1p2/2Q5/5P2/P1bb1NN1/R5PP/2R4K b - - 0 26",
+ "3r2k1/1p3ppp/p2P1p2/2r5/5P2/P1bb1N2/R3N1PP/2R4K b - - 1 27",
+ "3r2k1/1p3ppp/p2P1p2/2r5/5P2/P1b2N2/4R1PP/2R4K b - - 0 28",
+ "3r2k1/1p3ppp/p2P1p2/2r5/1b3P2/P4N2/4R1PP/3R3K b - - 2 29",
+ "3r2k1/1p2Rppp/p2P1p2/b1r5/5P2/P4N2/6PP/3R3K b - - 4 30",
+ "3r2k1/1R3ppp/p1rP1p2/b7/5P2/P4N2/6PP/3R3K b - - 0 31",
+ "3r2k1/1R3ppp/p2R1p2/b7/5P2/P4N2/6PP/7K b - - 0 32",
+ "6k1/1R3ppp/p2r1p2/b7/5P2/P4NP1/7P/7K b - - 0 33",
+ "6k1/1R3p1p/p2r1pp1/b7/5P1P/P4NP1/8/7K b - - 0 34",
+ "6k1/3R1p1p/pr3pp1/b7/5P1P/P4NP1/8/7K b - - 2 35",
+ "6k1/5p2/pr3pp1/b2R3p/5P1P/P4NP1/8/7K b - - 1 36",
+ "6k1/5p2/pr3pp1/7p/5P1P/P1bR1NP1/8/7K b - - 3 37",
+ "6k1/5p2/p1r2pp1/7p/5P1P/P1bR1NP1/6K1/8 b - - 5 38",
+ "6k1/5p2/p1r2pp1/b2R3p/5P1P/P4NP1/6K1/8 b - - 7 39",
+ "6k1/5p2/p4pp1/b2R3p/5P1P/P4NPK/2r5/8 b - - 9 40",
+ "6k1/2b2p2/p4pp1/7p/5P1P/P2R1NPK/2r5/8 b - - 11 41",
+ "6k1/2b2p2/5pp1/p6p/3N1P1P/P2R2PK/2r5/8 b - - 1 42",
+ "6k1/2b2p2/5pp1/p6p/3N1P1P/P1R3PK/r7/8 b - - 3 43",
+ "6k1/5p2/1b3pp1/p6p/5P1P/P1R3PK/r1N5/8 b - - 5 44",
+ "8/5pk1/1bR2pp1/p6p/5P1P/P5PK/r1N5/8 b - - 7 45",
+ "3b4/5pk1/2R2pp1/p4P1p/7P/P5PK/r1N5/8 b - - 0 46",
+ "8/4bpk1/2R2pp1/p4P1p/6PP/P6K/r1N5/8 b - - 0 47",
+ "8/5pk1/2R2pP1/p6p/6PP/b6K/r1N5/8 b - - 0 48",
+ "8/6k1/2R2pp1/p6P/7P/b6K/r1N5/8 b - - 0 49",
+ "8/6k1/2R2p2/p6p/7P/b5K1/r1N5/8 b - - 1 50",
+ "8/8/2R2pk1/p6p/7P/b4K2/r1N5/8 b - - 3 51",
+ "8/8/2R2pk1/p6p/7P/4NK2/rb6/8 b - - 5 52",
+ "2R5/8/5pk1/7p/p6P/4NK2/rb6/8 b - - 1 53",
+ "6R1/8/5pk1/7p/p6P/4NK2/1b6/r7 b - - 3 54",
+ "R7/5k2/5p2/7p/p6P/4NK2/1b6/r7 b - - 5 55",
+ "R7/5k2/5p2/7p/7P/p3N3/1b2K3/r7 b - - 1 56",
+ "8/R4k2/5p2/7p/7P/p3N3/1b2K3/7r b - - 3 57",
+ "8/8/5pk1/7p/R6P/p3N3/1b2K3/7r b - - 5 58",
+ "8/8/5pk1/7p/R6P/p7/4K3/2bN3r b - - 7 59",
+ "8/8/5pk1/7p/R6P/p7/4KN1r/2b5 b - - 9 60",
+ "8/8/5pk1/7p/R6P/p3K3/1b3N1r/8 b - - 11 61",
+ "8/8/R4pk1/7p/7P/p1b1K3/5N1r/8 b - - 13 62",
+ "8/8/5pk1/7p/7P/2b1K3/R4N1r/8 b - - 0 63",
+ "8/8/5pk1/7p/3K3P/8/R4N1r/4b3 b - - 2 64",
+ }
+};
+// clang-format on
+
+} // namespace
+
+namespace Stockfish::Benchmark {
+
+// Builds a list of UCI commands to be run by bench. There
+// are five parameters: TT size in MB, number of search threads that
+// should be used, the limit value spent for each position, a file name
+// where to look for positions in FEN format, and the type of the limit:
+// depth, perft, nodes and movetime (in milliseconds). Examples:
+//
+// bench : search default positions up to depth 13
+// bench 64 1 15 : search default positions up to depth 15 (TT = 64MB)
+// bench 64 1 100000 default nodes : search default positions for 100K nodes each
+// bench 64 4 5000 current movetime : search current position with 4 threads for 5 sec
+// bench 16 1 5 blah perft : run a perft 5 on positions in file "blah"
+std::vector setup_bench(const std::string& currentFen, std::istream& is) {
+
+ std::vector fens, list;
+ std::string go, token;
+
+ // Assign default values to missing arguments
+ std::string ttSize = (is >> token) ? token : "16";
+ std::string threads = (is >> token) ? token : "1";
+ std::string limit = (is >> token) ? token : "13";
+ std::string fenFile = (is >> token) ? token : "default";
+ std::string limitType = (is >> token) ? token : "depth";
+
+ go = limitType == "eval" ? "eval" : "go " + limitType + " " + limit;
+
+ if (fenFile == "default")
+ fens = Defaults;
+
+ else if (fenFile == "current")
+ fens.push_back(currentFen);
+
+ else
+ {
+ std::string fen;
+ std::ifstream file(fenFile);
+
+ if (!file.is_open())
+ {
+ std::cerr << "Unable to open file " << fenFile << std::endl;
+ exit(EXIT_FAILURE);
+ }
+
+ while (getline(file, fen))
+ if (!fen.empty())
+ fens.push_back(fen);
+
+ file.close();
+ }
+
+ list.emplace_back("setoption name Threads value " + threads);
+ list.emplace_back("setoption name Hash value " + ttSize);
+ list.emplace_back("ucinewgame");
+
+ for (const std::string& fen : fens)
+ if (fen.find("setoption") != std::string::npos)
+ list.emplace_back(fen);
+ else
+ {
+ list.emplace_back("position fen " + fen);
+ list.emplace_back(go);
+ }
+
+ return list;
+}
+
+BenchmarkSetup setup_benchmark(std::istream& is) {
+ // TT_SIZE_PER_THREAD is chosen such that roughly half of the hash is used all positions
+ // for the current sequence have been searched.
+ static constexpr int TT_SIZE_PER_THREAD = 128;
+
+ static constexpr int DEFAULT_DURATION_S = 150;
+
+ BenchmarkSetup setup{};
+
+ // Assign default values to missing arguments
+ int desiredTimeS;
+
+ if (!(is >> setup.threads))
+ setup.threads = get_hardware_concurrency();
+ else
+ setup.originalInvocation += std::to_string(setup.threads);
+
+ if (!(is >> setup.ttSize))
+ setup.ttSize = TT_SIZE_PER_THREAD * setup.threads;
+ else
+ setup.originalInvocation += " " + std::to_string(setup.ttSize);
+
+ if (!(is >> desiredTimeS))
+ desiredTimeS = DEFAULT_DURATION_S;
+ else
+ setup.originalInvocation += " " + std::to_string(desiredTimeS);
+
+ setup.filledInvocation += std::to_string(setup.threads) + " " + std::to_string(setup.ttSize)
+ + " " + std::to_string(desiredTimeS);
+
+ auto getCorrectedTime = [&](int ply) {
+ // time per move is fit roughly based on LTC games
+ // seconds = 50/{ply+15}
+ // ms = 50000/{ply+15}
+ // with this fit 10th move gets 2000ms
+ // adjust for desired 10th move time
+ return 50000.0 / (static_cast(ply) + 15.0);
+ };
+
+ float totalTime = 0;
+ for (const auto& game : BenchmarkPositions)
+ {
+ setup.commands.emplace_back("ucinewgame");
+ int ply = 1;
+ for (int i = 0; i < static_cast(game.size()); ++i)
+ {
+ const float correctedTime = getCorrectedTime(ply);
+ totalTime += correctedTime;
+ ply += 1;
+ }
+ }
+
+ float timeScaleFactor = static_cast(desiredTimeS * 1000) / totalTime;
+
+ for (const auto& game : BenchmarkPositions)
+ {
+ setup.commands.emplace_back("ucinewgame");
+ int ply = 1;
+ for (const std::string& fen : game)
+ {
+ setup.commands.emplace_back("position fen " + fen);
+
+ const int correctedTime = static_cast(getCorrectedTime(ply) * timeScaleFactor);
+ setup.commands.emplace_back("go movetime " + std::to_string(correctedTime));
+
+ ply += 1;
+ }
+ }
+
+ return setup;
+}
+
+} // namespace Stockfish
\ No newline at end of file
diff --git a/stockfish/src/benchmark.h b/stockfish/src/benchmark.h
new file mode 100644
index 0000000000000000000000000000000000000000..d6bdc275df949adcc3c5d18272c54eb553b46acd
--- /dev/null
+++ b/stockfish/src/benchmark.h
@@ -0,0 +1,42 @@
+/*
+ Stockfish, a UCI chess playing engine derived from Glaurung 2.1
+ Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
+
+ Stockfish is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Stockfish is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef BENCHMARK_H_INCLUDED
+#define BENCHMARK_H_INCLUDED
+
+#include
+#include
+#include
+
+namespace Stockfish::Benchmark {
+
+std::vector setup_bench(const std::string&, std::istream&);
+
+struct BenchmarkSetup {
+ int ttSize;
+ int threads;
+ std::vector commands;
+ std::string originalInvocation;
+ std::string filledInvocation;
+};
+
+BenchmarkSetup setup_benchmark(std::istream&);
+
+} // namespace Stockfish
+
+#endif // #ifndef BENCHMARK_H_INCLUDED
diff --git a/stockfish/src/bitboard.cpp b/stockfish/src/bitboard.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8798c5701d566f3e85c60ce270fd13a947862b36
--- /dev/null
+++ b/stockfish/src/bitboard.cpp
@@ -0,0 +1,228 @@
+/*
+ Stockfish, a UCI chess playing engine derived from Glaurung 2.1
+ Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
+
+ Stockfish is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Stockfish is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "bitboard.h"
+
+#include
+#include
+#include
+
+#include "misc.h"
+
+namespace Stockfish {
+
+uint8_t PopCnt16[1 << 16];
+uint8_t SquareDistance[SQUARE_NB][SQUARE_NB];
+
+Bitboard LineBB[SQUARE_NB][SQUARE_NB];
+Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
+Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB];
+Bitboard PawnAttacks[COLOR_NB][SQUARE_NB];
+
+alignas(64) Magic Magics[SQUARE_NB][2];
+
+namespace {
+
+Bitboard RookTable[0x19000]; // To store rook attacks
+Bitboard BishopTable[0x1480]; // To store bishop attacks
+
+void init_magics(PieceType pt, Bitboard table[], Magic magics[][2]);
+
+// Returns the bitboard of target square for the given step
+// from the given square. If the step is off the board, returns empty bitboard.
+Bitboard safe_destination(Square s, int step) {
+ Square to = Square(s + step);
+ return is_ok(to) && distance(s, to) <= 2 ? square_bb(to) : Bitboard(0);
+}
+}
+
+// Returns an ASCII representation of a bitboard suitable
+// to be printed to standard output. Useful for debugging.
+std::string Bitboards::pretty(Bitboard b) {
+
+ std::string s = "+---+---+---+---+---+---+---+---+\n";
+
+ for (Rank r = RANK_8; r >= RANK_1; --r)
+ {
+ for (File f = FILE_A; f <= FILE_H; ++f)
+ s += b & make_square(f, r) ? "| X " : "| ";
+
+ s += "| " + std::to_string(1 + r) + "\n+---+---+---+---+---+---+---+---+\n";
+ }
+ s += " a b c d e f g h\n";
+
+ return s;
+}
+
+
+// Initializes various bitboard tables. It is called at
+// startup and relies on global objects to be already zero-initialized.
+void Bitboards::init() {
+
+ for (unsigned i = 0; i < (1 << 16); ++i)
+ PopCnt16[i] = uint8_t(std::bitset<16>(i).count());
+
+ for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
+ for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2)
+ SquareDistance[s1][s2] = std::max(distance(s1, s2), distance(s1, s2));
+
+ init_magics(ROOK, RookTable, Magics);
+ init_magics(BISHOP, BishopTable, Magics);
+
+ for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
+ {
+ PawnAttacks[WHITE][s1] = pawn_attacks_bb(square_bb(s1));
+ PawnAttacks[BLACK][s1] = pawn_attacks_bb(square_bb(s1));
+
+ for (int step : {-9, -8, -7, -1, 1, 7, 8, 9})
+ PseudoAttacks[KING][s1] |= safe_destination(s1, step);
+
+ for (int step : {-17, -15, -10, -6, 6, 10, 15, 17})
+ PseudoAttacks[KNIGHT][s1] |= safe_destination(s1, step);
+
+ PseudoAttacks[QUEEN][s1] = PseudoAttacks[BISHOP][s1] = attacks_bb(s1, 0);
+ PseudoAttacks[QUEEN][s1] |= PseudoAttacks[ROOK][s1] = attacks_bb(s1, 0);
+
+ for (PieceType pt : {BISHOP, ROOK})
+ for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2)
+ {
+ if (PseudoAttacks[pt][s1] & s2)
+ {
+ LineBB[s1][s2] = (attacks_bb(pt, s1, 0) & attacks_bb(pt, s2, 0)) | s1 | s2;
+ BetweenBB[s1][s2] =
+ (attacks_bb(pt, s1, square_bb(s2)) & attacks_bb(pt, s2, square_bb(s1)));
+ }
+ BetweenBB[s1][s2] |= s2;
+ }
+ }
+}
+
+namespace {
+
+Bitboard sliding_attack(PieceType pt, Square sq, Bitboard occupied) {
+
+ Bitboard attacks = 0;
+ Direction RookDirections[4] = {NORTH, SOUTH, EAST, WEST};
+ Direction BishopDirections[4] = {NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST};
+
+ for (Direction d : (pt == ROOK ? RookDirections : BishopDirections))
+ {
+ Square s = sq;
+ while (safe_destination(s, d))
+ {
+ attacks |= (s += d);
+ if (occupied & s)
+ {
+ break;
+ }
+ }
+ }
+
+ return attacks;
+}
+
+
+// Computes all rook and bishop attacks at startup. Magic
+// bitboards are used to look up attacks of sliding pieces. As a reference see
+// https://www.chessprogramming.org/Magic_Bitboards. In particular, here we use
+// the so called "fancy" approach.
+void init_magics(PieceType pt, Bitboard table[], Magic magics[][2]) {
+
+#ifndef USE_PEXT
+ // Optimal PRNG seeds to pick the correct magics in the shortest time
+ int seeds[][RANK_NB] = {{8977, 44560, 54343, 38998, 5731, 95205, 104912, 17020},
+ {728, 10316, 55013, 32803, 12281, 15100, 16645, 255}};
+
+ Bitboard occupancy[4096];
+ int epoch[4096] = {}, cnt = 0;
+#endif
+ Bitboard reference[4096];
+ int size = 0;
+
+ for (Square s = SQ_A1; s <= SQ_H8; ++s)
+ {
+ // Board edges are not considered in the relevant occupancies
+ Bitboard edges = ((Rank1BB | Rank8BB) & ~rank_bb(s)) | ((FileABB | FileHBB) & ~file_bb(s));
+
+ // Given a square 's', the mask is the bitboard of sliding attacks from
+ // 's' computed on an empty board. The index must be big enough to contain
+ // all the attacks for each possible subset of the mask and so is 2 power
+ // the number of 1s of the mask. Hence we deduce the size of the shift to
+ // apply to the 64 or 32 bits word to get the index.
+ Magic& m = magics[s][pt - BISHOP];
+ m.mask = sliding_attack(pt, s, 0) & ~edges;
+#ifndef USE_PEXT
+ m.shift = (Is64Bit ? 64 : 32) - popcount(m.mask);
+#endif
+ // Set the offset for the attacks table of the square. We have individual
+ // table sizes for each square with "Fancy Magic Bitboards".
+ m.attacks = s == SQ_A1 ? table : magics[s - 1][pt - BISHOP].attacks + size;
+ size = 0;
+
+ // Use Carry-Rippler trick to enumerate all subsets of masks[s] and
+ // store the corresponding sliding attack bitboard in reference[].
+ Bitboard b = 0;
+ do
+ {
+#ifndef USE_PEXT
+ occupancy[size] = b;
+#endif
+ reference[size] = sliding_attack(pt, s, b);
+
+ if (HasPext)
+ m.attacks[pext(b, m.mask)] = reference[size];
+
+ size++;
+ b = (b - m.mask) & m.mask;
+ } while (b);
+
+#ifndef USE_PEXT
+ PRNG rng(seeds[Is64Bit][rank_of(s)]);
+
+ // Find a magic for square 's' picking up an (almost) random number
+ // until we find the one that passes the verification test.
+ for (int i = 0; i < size;)
+ {
+ for (m.magic = 0; popcount((m.magic * m.mask) >> 56) < 6;)
+ m.magic = rng.sparse_rand();
+
+ // A good magic must map every possible occupancy to an index that
+ // looks up the correct sliding attack in the attacks[s] database.
+ // Note that we build up the database for square 's' as a side
+ // effect of verifying the magic. Keep track of the attempt count
+ // and save it in epoch[], little speed-up trick to avoid resetting
+ // m.attacks[] after every failed attempt.
+ for (++cnt, i = 0; i < size; ++i)
+ {
+ unsigned idx = m.index(occupancy[i]);
+
+ if (epoch[idx] < cnt)
+ {
+ epoch[idx] = cnt;
+ m.attacks[idx] = reference[i];
+ }
+ else if (m.attacks[idx] != reference[i])
+ break;
+ }
+ }
+#endif
+ }
+}
+}
+
+} // namespace Stockfish
diff --git a/stockfish/src/bitboard.h b/stockfish/src/bitboard.h
new file mode 100644
index 0000000000000000000000000000000000000000..df15113bda3428b32721893f891d7dc748ae4440
--- /dev/null
+++ b/stockfish/src/bitboard.h
@@ -0,0 +1,374 @@
+/*
+ Stockfish, a UCI chess playing engine derived from Glaurung 2.1
+ Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
+
+ Stockfish is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Stockfish is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef BITBOARD_H_INCLUDED
+#define BITBOARD_H_INCLUDED
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "types.h"
+
+namespace Stockfish {
+
+namespace Bitboards {
+
+void init();
+std::string pretty(Bitboard b);
+
+} // namespace Stockfish::Bitboards
+
+constexpr Bitboard FileABB = 0x0101010101010101ULL;
+constexpr Bitboard FileBBB = FileABB << 1;
+constexpr Bitboard FileCBB = FileABB << 2;
+constexpr Bitboard FileDBB = FileABB << 3;
+constexpr Bitboard FileEBB = FileABB << 4;
+constexpr Bitboard FileFBB = FileABB << 5;
+constexpr Bitboard FileGBB = FileABB << 6;
+constexpr Bitboard FileHBB = FileABB << 7;
+
+constexpr Bitboard Rank1BB = 0xFF;
+constexpr Bitboard Rank2BB = Rank1BB << (8 * 1);
+constexpr Bitboard Rank3BB = Rank1BB << (8 * 2);
+constexpr Bitboard Rank4BB = Rank1BB << (8 * 3);
+constexpr Bitboard Rank5BB = Rank1BB << (8 * 4);
+constexpr Bitboard Rank6BB = Rank1BB << (8 * 5);
+constexpr Bitboard Rank7BB = Rank1BB << (8 * 6);
+constexpr Bitboard Rank8BB = Rank1BB << (8 * 7);
+
+extern uint8_t PopCnt16[1 << 16];
+extern uint8_t SquareDistance[SQUARE_NB][SQUARE_NB];
+
+extern Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
+extern Bitboard LineBB[SQUARE_NB][SQUARE_NB];
+extern Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB];
+extern Bitboard PawnAttacks[COLOR_NB][SQUARE_NB];
+
+
+// Magic holds all magic bitboards relevant data for a single square
+struct Magic {
+ Bitboard mask;
+ Bitboard* attacks;
+#ifndef USE_PEXT
+ Bitboard magic;
+ unsigned shift;
+#endif
+
+ // Compute the attack's index using the 'magic bitboards' approach
+ unsigned index(Bitboard occupied) const {
+
+#ifdef USE_PEXT
+ return unsigned(pext(occupied, mask));
+#else
+ if (Is64Bit)
+ return unsigned(((occupied & mask) * magic) >> shift);
+
+ unsigned lo = unsigned(occupied) & unsigned(mask);
+ unsigned hi = unsigned(occupied >> 32) & unsigned(mask >> 32);
+ return (lo * unsigned(magic) ^ hi * unsigned(magic >> 32)) >> shift;
+#endif
+ }
+
+ Bitboard attacks_bb(Bitboard occupied) const { return attacks[index(occupied)]; }
+};
+
+extern Magic Magics[SQUARE_NB][2];
+
+constexpr Bitboard square_bb(Square s) {
+ assert(is_ok(s));
+ return (1ULL << s);
+}
+
+
+// Overloads of bitwise operators between a Bitboard and a Square for testing
+// whether a given bit is set in a bitboard, and for setting and clearing bits.
+
+inline Bitboard operator&(Bitboard b, Square s) { return b & square_bb(s); }
+inline Bitboard operator|(Bitboard b, Square s) { return b | square_bb(s); }
+inline Bitboard operator^(Bitboard b, Square s) { return b ^ square_bb(s); }
+inline Bitboard& operator|=(Bitboard& b, Square s) { return b |= square_bb(s); }
+inline Bitboard& operator^=(Bitboard& b, Square s) { return b ^= square_bb(s); }
+
+inline Bitboard operator&(Square s, Bitboard b) { return b & s; }
+inline Bitboard operator|(Square s, Bitboard b) { return b | s; }
+inline Bitboard operator^(Square s, Bitboard b) { return b ^ s; }
+
+inline Bitboard operator|(Square s1, Square s2) { return square_bb(s1) | s2; }
+
+constexpr bool more_than_one(Bitboard b) { return b & (b - 1); }
+
+
+// rank_bb() and file_bb() return a bitboard representing all the squares on
+// the given file or rank.
+
+constexpr Bitboard rank_bb(Rank r) { return Rank1BB << (8 * r); }
+
+constexpr Bitboard rank_bb(Square s) { return rank_bb(rank_of(s)); }
+
+constexpr Bitboard file_bb(File f) { return FileABB << f; }
+
+constexpr Bitboard file_bb(Square s) { return file_bb(file_of(s)); }
+
+
+// Moves a bitboard one or two steps as specified by the direction D
+template
+constexpr Bitboard shift(Bitboard b) {
+ return D == NORTH ? b << 8
+ : D == SOUTH ? b >> 8
+ : D == NORTH + NORTH ? b << 16
+ : D == SOUTH + SOUTH ? b >> 16
+ : D == EAST ? (b & ~FileHBB) << 1
+ : D == WEST ? (b & ~FileABB) >> 1
+ : D == NORTH_EAST ? (b & ~FileHBB) << 9
+ : D == NORTH_WEST ? (b & ~FileABB) << 7
+ : D == SOUTH_EAST ? (b & ~FileHBB) >> 7
+ : D == SOUTH_WEST ? (b & ~FileABB) >> 9
+ : 0;
+}
+
+
+// Returns the squares attacked by pawns of the given color
+// from the squares in the given bitboard.
+template
+constexpr Bitboard pawn_attacks_bb(Bitboard b) {
+ return C == WHITE ? shift(b) | shift(b)
+ : shift(b) | shift(b);
+}
+
+inline Bitboard pawn_attacks_bb(Color c, Square s) {
+
+ assert(is_ok(s));
+ return PawnAttacks[c][s];
+}
+
+// Returns a bitboard representing an entire line (from board edge
+// to board edge) that intersects the two given squares. If the given squares
+// are not on a same file/rank/diagonal, the function returns 0. For instance,
+// line_bb(SQ_C4, SQ_F7) will return a bitboard with the A2-G8 diagonal.
+inline Bitboard line_bb(Square s1, Square s2) {
+
+ assert(is_ok(s1) && is_ok(s2));
+ return LineBB[s1][s2];
+}
+
+
+// Returns a bitboard representing the squares in the semi-open
+// segment between the squares s1 and s2 (excluding s1 but including s2). If the
+// given squares are not on a same file/rank/diagonal, it returns s2. For instance,
+// between_bb(SQ_C4, SQ_F7) will return a bitboard with squares D5, E6 and F7, but
+// between_bb(SQ_E6, SQ_F8) will return a bitboard with the square F8. This trick
+// allows to generate non-king evasion moves faster: the defending piece must either
+// interpose itself to cover the check or capture the checking piece.
+inline Bitboard between_bb(Square s1, Square s2) {
+
+ assert(is_ok(s1) && is_ok(s2));
+ return BetweenBB[s1][s2];
+}
+
+// Returns true if the squares s1, s2 and s3 are aligned either on a
+// straight or on a diagonal line.
+inline bool aligned(Square s1, Square s2, Square s3) { return line_bb(s1, s2) & s3; }
+
+
+// distance() functions return the distance between x and y, defined as the
+// number of steps for a king in x to reach y.
+
+template
+inline int distance(Square x, Square y);
+
+template<>
+inline int distance(Square x, Square y) {
+ return std::abs(file_of(x) - file_of(y));
+}
+
+template<>
+inline int distance(Square x, Square y) {
+ return std::abs(rank_of(x) - rank_of(y));
+}
+
+template<>
+inline int distance(Square x, Square y) {
+ return SquareDistance[x][y];
+}
+
+inline int edge_distance(File f) { return std::min(f, File(FILE_H - f)); }
+
+// Returns the pseudo attacks of the given piece type
+// assuming an empty board.
+template
+inline Bitboard attacks_bb(Square s) {
+
+ assert((Pt != PAWN) && (is_ok(s)));
+ return PseudoAttacks[Pt][s];
+}
+
+
+// Returns the attacks by the given piece
+// assuming the board is occupied according to the passed Bitboard.
+// Sliding piece attacks do not continue passed an occupied square.
+template
+inline Bitboard attacks_bb(Square s, Bitboard occupied) {
+
+ assert((Pt != PAWN) && (is_ok(s)));
+
+ switch (Pt)
+ {
+ case BISHOP :
+ case ROOK :
+ return Magics[s][Pt - BISHOP].attacks_bb(occupied);
+ case QUEEN :
+ return attacks_bb(s, occupied) | attacks_bb(s, occupied);
+ default :
+ return PseudoAttacks[Pt][s];
+ }
+}
+
+// Returns the attacks by the given piece
+// assuming the board is occupied according to the passed Bitboard.
+// Sliding piece attacks do not continue passed an occupied square.
+inline Bitboard attacks_bb(PieceType pt, Square s, Bitboard occupied) {
+
+ assert((pt != PAWN) && (is_ok(s)));
+
+ switch (pt)
+ {
+ case BISHOP :
+ return attacks_bb(s, occupied);
+ case ROOK :
+ return attacks_bb(s, occupied);
+ case QUEEN :
+ return attacks_bb(s, occupied) | attacks_bb(s, occupied);
+ default :
+ return PseudoAttacks[pt][s];
+ }
+}
+
+
+// Counts the number of non-zero bits in a bitboard.
+inline int popcount(Bitboard b) {
+
+#ifndef USE_POPCNT
+
+ std::uint16_t indices[4];
+ std::memcpy(indices, &b, sizeof(b));
+ return PopCnt16[indices[0]] + PopCnt16[indices[1]] + PopCnt16[indices[2]]
+ + PopCnt16[indices[3]];
+
+#elif defined(_MSC_VER)
+
+ return int(_mm_popcnt_u64(b));
+
+#else // Assumed gcc or compatible compiler
+
+ return __builtin_popcountll(b);
+
+#endif
+}
+
+// Returns the least significant bit in a non-zero bitboard.
+inline Square lsb(Bitboard b) {
+ assert(b);
+
+#if defined(__GNUC__) // GCC, Clang, ICX
+
+ return Square(__builtin_ctzll(b));
+
+#elif defined(_MSC_VER)
+ #ifdef _WIN64 // MSVC, WIN64
+
+ unsigned long idx;
+ _BitScanForward64(&idx, b);
+ return Square(idx);
+
+ #else // MSVC, WIN32
+ unsigned long idx;
+
+ if (b & 0xffffffff)
+ {
+ _BitScanForward(&idx, int32_t(b));
+ return Square(idx);
+ }
+ else
+ {
+ _BitScanForward(&idx, int32_t(b >> 32));
+ return Square(idx + 32);
+ }
+ #endif
+#else // Compiler is neither GCC nor MSVC compatible
+ #error "Compiler not supported."
+#endif
+}
+
+// Returns the most significant bit in a non-zero bitboard.
+inline Square msb(Bitboard b) {
+ assert(b);
+
+#if defined(__GNUC__) // GCC, Clang, ICX
+
+ return Square(63 ^ __builtin_clzll(b));
+
+#elif defined(_MSC_VER)
+ #ifdef _WIN64 // MSVC, WIN64
+
+ unsigned long idx;
+ _BitScanReverse64(&idx, b);
+ return Square(idx);
+
+ #else // MSVC, WIN32
+
+ unsigned long idx;
+
+ if (b >> 32)
+ {
+ _BitScanReverse(&idx, int32_t(b >> 32));
+ return Square(idx + 32);
+ }
+ else
+ {
+ _BitScanReverse(&idx, int32_t(b));
+ return Square(idx);
+ }
+ #endif
+#else // Compiler is neither GCC nor MSVC compatible
+ #error "Compiler not supported."
+#endif
+}
+
+// Returns the bitboard of the least significant
+// square of a non-zero bitboard. It is equivalent to square_bb(lsb(bb)).
+inline Bitboard least_significant_square_bb(Bitboard b) {
+ assert(b);
+ return b & -b;
+}
+
+// Finds and clears the least significant bit in a non-zero bitboard.
+inline Square pop_lsb(Bitboard& b) {
+ assert(b);
+ const Square s = lsb(b);
+ b &= b - 1;
+ return s;
+}
+
+} // namespace Stockfish
+
+#endif // #ifndef BITBOARD_H_INCLUDED
diff --git a/stockfish/src/engine.cpp b/stockfish/src/engine.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a4c0bb1ebebd77768c43ff9182157a81fe6bcdb8
--- /dev/null
+++ b/stockfish/src/engine.cpp
@@ -0,0 +1,372 @@
+/*
+ Stockfish, a UCI chess playing engine derived from Glaurung 2.1
+ Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
+
+ Stockfish is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Stockfish is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "engine.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "evaluate.h"
+#include "misc.h"
+#include "nnue/network.h"
+#include "nnue/nnue_common.h"
+#include "numa.h"
+#include "perft.h"
+#include "position.h"
+#include "search.h"
+#include "syzygy/tbprobe.h"
+#include "types.h"
+#include "uci.h"
+#include "ucioption.h"
+
+namespace Stockfish {
+
+namespace NN = Eval::NNUE;
+
+constexpr auto StartFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
+constexpr int MaxHashMB = Is64Bit ? 33554432 : 2048;
+int MaxThreads = std::max(1024, 4 * int(get_hardware_concurrency()));
+
+Engine::Engine(std::optional path) :
+ binaryDirectory(path ? CommandLine::get_binary_directory(*path) : ""),
+ numaContext(NumaConfig::from_system()),
+ states(new std::deque(1)),
+ threads(),
+ networks(
+ numaContext,
+ NN::Networks(
+ NN::NetworkBig({EvalFileDefaultNameBig, "None", ""}, NN::EmbeddedNNUEType::BIG),
+ NN::NetworkSmall({EvalFileDefaultNameSmall, "None", ""}, NN::EmbeddedNNUEType::SMALL))) {
+ pos.set(StartFEN, false, &states->back());
+
+
+ options.add( //
+ "Debug Log File", Option("", [](const Option& o) {
+ start_logger(o);
+ return std::nullopt;
+ }));
+
+ options.add( //
+ "NumaPolicy", Option("auto", [this](const Option& o) {
+ set_numa_config_from_option(o);
+ return numa_config_information_as_string() + "\n"
+ + thread_allocation_information_as_string();
+ }));
+
+ options.add( //
+ "Threads", Option(1, 1, MaxThreads, [this](const Option&) {
+ resize_threads();
+ return thread_allocation_information_as_string();
+ }));
+
+ options.add( //
+ "Hash", Option(16, 1, MaxHashMB, [this](const Option& o) {
+ set_tt_size(o);
+ return std::nullopt;
+ }));
+
+ options.add( //
+ "Clear Hash", Option([this](const Option&) {
+ search_clear();
+ return std::nullopt;
+ }));
+
+ options.add( //
+ "Ponder", Option(false));
+
+ options.add( //
+ "MultiPV", Option(1, 1, MAX_MOVES));
+
+ options.add("Skill Level", Option(20, 0, 20));
+
+ options.add("Move Overhead", Option(10, 0, 5000));
+
+ options.add("nodestime", Option(0, 0, 10000));
+
+ options.add("UCI_Chess960", Option(false));
+
+ options.add("UCI_LimitStrength", Option(false));
+
+ options.add("UCI_Elo",
+ Option(Stockfish::Search::Skill::LowestElo, Stockfish::Search::Skill::LowestElo,
+ Stockfish::Search::Skill::HighestElo));
+
+ options.add("UCI_ShowWDL", Option(false));
+
+ options.add( //
+ "SyzygyPath", Option("", [](const Option& o) {
+ Tablebases::init(o);
+ return std::nullopt;
+ }));
+
+ options.add("SyzygyProbeDepth", Option(1, 1, 100));
+
+ options.add("Syzygy50MoveRule", Option(true));
+
+ options.add("SyzygyProbeLimit", Option(7, 0, 7));
+
+ options.add( //
+ "EvalFile", Option(EvalFileDefaultNameBig, [this](const Option& o) {
+ load_big_network(o);
+ return std::nullopt;
+ }));
+
+ options.add( //
+ "EvalFileSmall", Option(EvalFileDefaultNameSmall, [this](const Option& o) {
+ load_small_network(o);
+ return std::nullopt;
+ }));
+
+ load_networks();
+ resize_threads();
+}
+
+std::uint64_t Engine::perft(const std::string& fen, Depth depth, bool isChess960) {
+ verify_networks();
+
+ return Benchmark::perft(fen, depth, isChess960);
+}
+
+void Engine::go(Search::LimitsType& limits) {
+ assert(limits.perft == 0);
+ verify_networks();
+
+ threads.start_thinking(options, pos, states, limits);
+}
+void Engine::stop() { threads.stop = true; }
+
+void Engine::search_clear() {
+ wait_for_search_finished();
+
+ tt.clear(threads);
+ threads.clear();
+
+ // @TODO wont work with multiple instances
+ Tablebases::init(options["SyzygyPath"]); // Free mapped files
+}
+
+void Engine::set_on_update_no_moves(std::function&& f) {
+ updateContext.onUpdateNoMoves = std::move(f);
+}
+
+void Engine::set_on_update_full(std::function&& f) {
+ updateContext.onUpdateFull = std::move(f);
+}
+
+void Engine::set_on_iter(std::function&& f) {
+ updateContext.onIter = std::move(f);
+}
+
+void Engine::set_on_bestmove(std::function&& f) {
+ updateContext.onBestmove = std::move(f);
+}
+
+void Engine::set_on_verify_networks(std::function&& f) {
+ onVerifyNetworks = std::move(f);
+}
+
+void Engine::wait_for_search_finished() { threads.main_thread()->wait_for_search_finished(); }
+
+void Engine::set_position(const std::string& fen, const std::vector& moves) {
+ // Drop the old state and create a new one
+ states = StateListPtr(new std::deque(1));
+ pos.set(fen, options["UCI_Chess960"], &states->back());
+
+ for (const auto& move : moves)
+ {
+ auto m = UCIEngine::to_move(pos, move);
+
+ if (m == Move::none())
+ break;
+
+ states->emplace_back();
+ pos.do_move(m, states->back());
+ }
+}
+
+// modifiers
+
+void Engine::set_numa_config_from_option(const std::string& o) {
+ if (o == "auto" || o == "system")
+ {
+ numaContext.set_numa_config(NumaConfig::from_system());
+ }
+ else if (o == "hardware")
+ {
+ // Don't respect affinity set in the system.
+ numaContext.set_numa_config(NumaConfig::from_system(false));
+ }
+ else if (o == "none")
+ {
+ numaContext.set_numa_config(NumaConfig{});
+ }
+ else
+ {
+ numaContext.set_numa_config(NumaConfig::from_string(o));
+ }
+
+ // Force reallocation of threads in case affinities need to change.
+ resize_threads();
+ threads.ensure_network_replicated();
+}
+
+void Engine::resize_threads() {
+ threads.wait_for_search_finished();
+ threads.set(numaContext.get_numa_config(), {options, threads, tt, networks}, updateContext);
+
+ // Reallocate the hash with the new threadpool size
+ set_tt_size(options["Hash"]);
+ threads.ensure_network_replicated();
+}
+
+void Engine::set_tt_size(size_t mb) {
+ wait_for_search_finished();
+ tt.resize(mb, threads);
+}
+
+void Engine::set_ponderhit(bool b) { threads.main_manager()->ponder = b; }
+
+// network related
+
+void Engine::verify_networks() const {
+ networks->big.verify(options["EvalFile"], onVerifyNetworks);
+ networks->small.verify(options["EvalFileSmall"], onVerifyNetworks);
+}
+
+void Engine::load_networks() {
+ networks.modify_and_replicate([this](NN::Networks& networks_) {
+ networks_.big.load(binaryDirectory, options["EvalFile"]);
+ networks_.small.load(binaryDirectory, options["EvalFileSmall"]);
+ });
+ threads.clear();
+ threads.ensure_network_replicated();
+}
+
+void Engine::load_big_network(const std::string& file) {
+ networks.modify_and_replicate(
+ [this, &file](NN::Networks& networks_) { networks_.big.load(binaryDirectory, file); });
+ threads.clear();
+ threads.ensure_network_replicated();
+}
+
+void Engine::load_small_network(const std::string& file) {
+ networks.modify_and_replicate(
+ [this, &file](NN::Networks& networks_) { networks_.small.load(binaryDirectory, file); });
+ threads.clear();
+ threads.ensure_network_replicated();
+}
+
+void Engine::save_network(const std::pair, std::string> files[2]) {
+ networks.modify_and_replicate([&files](NN::Networks& networks_) {
+ networks_.big.save(files[0].first);
+ networks_.small.save(files[1].first);
+ });
+}
+
+// utility functions
+
+void Engine::trace_eval() const {
+ StateListPtr trace_states(new std::deque(1));
+ Position p;
+ p.set(pos.fen(), options["UCI_Chess960"], &trace_states->back());
+
+ verify_networks();
+
+ sync_cout << "\n" << Eval::trace(p, *networks) << sync_endl;
+}
+
+const OptionsMap& Engine::get_options() const { return options; }
+OptionsMap& Engine::get_options() { return options; }
+
+std::string Engine::fen() const { return pos.fen(); }
+
+void Engine::flip() { pos.flip(); }
+
+std::string Engine::visualize() const {
+ std::stringstream ss;
+ ss << pos;
+ return ss.str();
+}
+
+int Engine::get_hashfull(int maxAge) const { return tt.hashfull(maxAge); }
+
+std::vector> Engine::get_bound_thread_count_by_numa_node() const {
+ auto counts = threads.get_bound_thread_count_by_numa_node();
+ const NumaConfig& cfg = numaContext.get_numa_config();
+ std::vector> ratios;
+ NumaIndex n = 0;
+ for (; n < counts.size(); ++n)
+ ratios.emplace_back(counts[n], cfg.num_cpus_in_numa_node(n));
+ if (!counts.empty())
+ for (; n < cfg.num_numa_nodes(); ++n)
+ ratios.emplace_back(0, cfg.num_cpus_in_numa_node(n));
+ return ratios;
+}
+
+std::string Engine::get_numa_config_as_string() const {
+ return numaContext.get_numa_config().to_string();
+}
+
+std::string Engine::numa_config_information_as_string() const {
+ auto cfgStr = get_numa_config_as_string();
+ return "Available processors: " + cfgStr;
+}
+
+std::string Engine::thread_binding_information_as_string() const {
+ auto boundThreadsByNode = get_bound_thread_count_by_numa_node();
+ std::stringstream ss;
+ if (boundThreadsByNode.empty())
+ return ss.str();
+
+ bool isFirst = true;
+
+ for (auto&& [current, total] : boundThreadsByNode)
+ {
+ if (!isFirst)
+ ss << ":";
+ ss << current << "/" << total;
+ isFirst = false;
+ }
+
+ return ss.str();
+}
+
+std::string Engine::thread_allocation_information_as_string() const {
+ std::stringstream ss;
+
+ size_t threadsSize = threads.size();
+ ss << "Using " << threadsSize << (threadsSize > 1 ? " threads" : " thread");
+
+ auto boundThreadsByNodeStr = thread_binding_information_as_string();
+ if (boundThreadsByNodeStr.empty())
+ return ss.str();
+
+ ss << " with NUMA node thread binding: ";
+ ss << boundThreadsByNodeStr;
+
+ return ss.str();
+}
+}
diff --git a/stockfish/src/engine.h b/stockfish/src/engine.h
new file mode 100644
index 0000000000000000000000000000000000000000..d26844f4ce4a96f0da8d76a25efd54cc1574113f
--- /dev/null
+++ b/stockfish/src/engine.h
@@ -0,0 +1,130 @@
+/*
+ Stockfish, a UCI chess playing engine derived from Glaurung 2.1
+ Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
+
+ Stockfish is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Stockfish is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef ENGINE_H_INCLUDED
+#define ENGINE_H_INCLUDED
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "nnue/network.h"
+#include "numa.h"
+#include "position.h"
+#include "search.h"
+#include "syzygy/tbprobe.h" // for Stockfish::Depth
+#include "thread.h"
+#include "tt.h"
+#include "ucioption.h"
+
+namespace Stockfish {
+
+class Engine {
+ public:
+ using InfoShort = Search::InfoShort;
+ using InfoFull = Search::InfoFull;
+ using InfoIter = Search::InfoIteration;
+
+ Engine(std::optional path = std::nullopt);
+
+ // Cannot be movable due to components holding backreferences to fields
+ Engine(const Engine&) = delete;
+ Engine(Engine&&) = delete;
+ Engine& operator=(const Engine&) = delete;
+ Engine& operator=(Engine&&) = delete;
+
+ ~Engine() { wait_for_search_finished(); }
+
+ std::uint64_t perft(const std::string& fen, Depth depth, bool isChess960);
+
+ // non blocking call to start searching
+ void go(Search::LimitsType&);
+ // non blocking call to stop searching
+ void stop();
+
+ // blocking call to wait for search to finish
+ void wait_for_search_finished();
+ // set a new position, moves are in UCI format
+ void set_position(const std::string& fen, const std::vector& moves);
+
+ // modifiers
+
+ void set_numa_config_from_option(const std::string& o);
+ void resize_threads();
+ void set_tt_size(size_t mb);
+ void set_ponderhit(bool);
+ void search_clear();
+
+ void set_on_update_no_moves(std::function&&);
+ void set_on_update_full(std::function&&);
+ void set_on_iter(std::function&&);
+ void set_on_bestmove(std::function&&);
+ void set_on_verify_networks(std::function&&);
+
+ // network related
+
+ void verify_networks() const;
+ void load_networks();
+ void load_big_network(const std::string& file);
+ void load_small_network(const std::string& file);
+ void save_network(const std::pair, std::string> files[2]);
+
+ // utility functions
+
+ void trace_eval() const;
+
+ const OptionsMap& get_options() const;
+ OptionsMap& get_options();
+
+ int get_hashfull(int maxAge = 0) const;
+
+ std::string fen() const;
+ void flip();
+ std::string visualize() const;
+ std::vector> get_bound_thread_count_by_numa_node() const;
+ std::string get_numa_config_as_string() const;
+ std::string numa_config_information_as_string() const;
+ std::string thread_allocation_information_as_string() const;
+ std::string thread_binding_information_as_string() const;
+
+ private:
+ const std::string binaryDirectory;
+
+ NumaReplicationContext numaContext;
+
+ Position pos;
+ StateListPtr states;
+
+ OptionsMap options;
+ ThreadPool threads;
+ TranspositionTable tt;
+ LazyNumaReplicated networks;
+
+ Search::SearchManager::UpdateContext updateContext;
+ std::function onVerifyNetworks;
+};
+
+} // namespace Stockfish
+
+
+#endif // #ifndef ENGINE_H_INCLUDED
diff --git a/stockfish/src/evaluate.cpp b/stockfish/src/evaluate.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ccb089d977711a63f88da4b5b3c1ac578555c0de
--- /dev/null
+++ b/stockfish/src/evaluate.cpp
@@ -0,0 +1,128 @@
+/*
+ Stockfish, a UCI chess playing engine derived from Glaurung 2.1
+ Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
+
+ Stockfish is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Stockfish is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "evaluate.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "nnue/network.h"
+#include "nnue/nnue_misc.h"
+#include "position.h"
+#include "types.h"
+#include "uci.h"
+#include "nnue/nnue_accumulator.h"
+
+namespace Stockfish {
+
+// Returns a static, purely materialistic evaluation of the position from
+// the point of view of the given color. It can be divided by PawnValue to get
+// an approximation of the material advantage on the board in terms of pawns.
+int Eval::simple_eval(const Position& pos, Color c) {
+ return PawnValue * (pos.count(c) - pos.count(~c))
+ + (pos.non_pawn_material(c) - pos.non_pawn_material(~c));
+}
+
+bool Eval::use_smallnet(const Position& pos) {
+ int simpleEval = simple_eval(pos, pos.side_to_move());
+ return std::abs(simpleEval) > 962;
+}
+
+// Evaluate is the evaluator for the outer world. It returns a static evaluation
+// of the position from the point of view of the side to move.
+Value Eval::evaluate(const Eval::NNUE::Networks& networks,
+ const Position& pos,
+ Eval::NNUE::AccumulatorStack& accumulators,
+ Eval::NNUE::AccumulatorCaches& caches,
+ int optimism) {
+
+ assert(!pos.checkers());
+
+ bool smallNet = use_smallnet(pos);
+ auto [psqt, positional] = smallNet ? networks.small.evaluate(pos, accumulators, &caches.small)
+ : networks.big.evaluate(pos, accumulators, &caches.big);
+
+ Value nnue = (125 * psqt + 131 * positional) / 128;
+
+ // Re-evaluate the position when higher eval accuracy is worth the time spent
+ if (smallNet && (std::abs(nnue) < 236))
+ {
+ std::tie(psqt, positional) = networks.big.evaluate(pos, accumulators, &caches.big);
+ nnue = (125 * psqt + 131 * positional) / 128;
+ smallNet = false;
+ }
+
+ // Blend optimism and eval with nnue complexity
+ int nnueComplexity = std::abs(psqt - positional);
+ optimism += optimism * nnueComplexity / 468;
+ nnue -= nnue * nnueComplexity / 18000;
+
+ int material = 535 * pos.count() + pos.non_pawn_material();
+ int v = (nnue * (77777 + material) + optimism * (7777 + material)) / 77777;
+
+ // Damp down the evaluation linearly when shuffling
+ v -= v * pos.rule50_count() / 212;
+
+ // Guarantee evaluation does not hit the tablebase range
+ v = std::clamp(v, VALUE_TB_LOSS_IN_MAX_PLY + 1, VALUE_TB_WIN_IN_MAX_PLY - 1);
+
+ return v;
+}
+
+// Like evaluate(), but instead of returning a value, it returns
+// a string (suitable for outputting to stdout) that contains the detailed
+// descriptions and values of each evaluation term. Useful for debugging.
+// Trace scores are from white's point of view
+std::string Eval::trace(Position& pos, const Eval::NNUE::Networks& networks) {
+
+ if (pos.checkers())
+ return "Final evaluation: none (in check)";
+
+ Eval::NNUE::AccumulatorStack accumulators;
+ auto caches = std::make_unique(networks);
+
+ accumulators.reset(pos, networks, *caches);
+
+ std::stringstream ss;
+ ss << std::showpoint << std::noshowpos << std::fixed << std::setprecision(2);
+ ss << '\n' << NNUE::trace(pos, networks, *caches) << '\n';
+
+ ss << std::showpoint << std::showpos << std::fixed << std::setprecision(2) << std::setw(15);
+
+ auto [psqt, positional] = networks.big.evaluate(pos, accumulators, &caches->big);
+ Value v = psqt + positional;
+ v = pos.side_to_move() == WHITE ? v : -v;
+ ss << "NNUE evaluation " << 0.01 * UCIEngine::to_cp(v, pos) << " (white side)\n";
+
+ v = evaluate(networks, pos, accumulators, *caches, VALUE_ZERO);
+ v = pos.side_to_move() == WHITE ? v : -v;
+ ss << "Final evaluation " << 0.01 * UCIEngine::to_cp(v, pos) << " (white side)";
+ ss << " [with scaled NNUE, ...]";
+ ss << "\n";
+
+ return ss.str();
+}
+
+} // namespace Stockfish
diff --git a/stockfish/src/evaluate.h b/stockfish/src/evaluate.h
new file mode 100644
index 0000000000000000000000000000000000000000..07b914007ea2688e9803696a175f527671caffea
--- /dev/null
+++ b/stockfish/src/evaluate.h
@@ -0,0 +1,58 @@
+/*
+ Stockfish, a UCI chess playing engine derived from Glaurung 2.1
+ Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
+
+ Stockfish is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Stockfish is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef EVALUATE_H_INCLUDED
+#define EVALUATE_H_INCLUDED
+
+#include
+
+#include "types.h"
+
+namespace Stockfish {
+
+class Position;
+
+namespace Eval {
+
+// The default net name MUST follow the format nn-[SHA256 first 12 digits].nnue
+// for the build process (profile-build and fishtest) to work. Do not change the
+// name of the macro or the location where this macro is defined, as it is used
+// in the Makefile/Fishtest.
+#define EvalFileDefaultNameBig "nn-1c0000000000.nnue"
+#define EvalFileDefaultNameSmall "nn-37f18f62d772.nnue"
+
+namespace NNUE {
+struct Networks;
+struct AccumulatorCaches;
+class AccumulatorStack;
+}
+
+std::string trace(Position& pos, const Eval::NNUE::Networks& networks);
+
+int simple_eval(const Position& pos, Color c);
+bool use_smallnet(const Position& pos);
+Value evaluate(const NNUE::Networks& networks,
+ const Position& pos,
+ Eval::NNUE::AccumulatorStack& accumulators,
+ Eval::NNUE::AccumulatorCaches& caches,
+ int optimism);
+} // namespace Eval
+
+} // namespace Stockfish
+
+#endif // #ifndef EVALUATE_H_INCLUDED
diff --git a/stockfish/src/history.h b/stockfish/src/history.h
new file mode 100644
index 0000000000000000000000000000000000000000..ec245230a76b697802169558acaf2390003a2436
--- /dev/null
+++ b/stockfish/src/history.h
@@ -0,0 +1,171 @@
+/*
+ Stockfish, a UCI chess playing engine derived from Glaurung 2.1
+ Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
+
+ Stockfish is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Stockfish is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef HISTORY_H_INCLUDED
+#define HISTORY_H_INCLUDED
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include // IWYU pragma: keep
+
+#include "misc.h"
+#include "position.h"
+
+namespace Stockfish {
+
+constexpr int PAWN_HISTORY_SIZE = 512; // has to be a power of 2
+constexpr int CORRECTION_HISTORY_SIZE = 32768; // has to be a power of 2
+constexpr int CORRECTION_HISTORY_LIMIT = 1024;
+constexpr int LOW_PLY_HISTORY_SIZE = 4;
+
+static_assert((PAWN_HISTORY_SIZE & (PAWN_HISTORY_SIZE - 1)) == 0,
+ "PAWN_HISTORY_SIZE has to be a power of 2");
+
+static_assert((CORRECTION_HISTORY_SIZE & (CORRECTION_HISTORY_SIZE - 1)) == 0,
+ "CORRECTION_HISTORY_SIZE has to be a power of 2");
+
+enum PawnHistoryType {
+ Normal,
+ Correction
+};
+
+template
+inline int pawn_structure_index(const Position& pos) {
+ return pos.pawn_key() & ((T == Normal ? PAWN_HISTORY_SIZE : CORRECTION_HISTORY_SIZE) - 1);
+}
+
+inline int minor_piece_index(const Position& pos) {
+ return pos.minor_piece_key() & (CORRECTION_HISTORY_SIZE - 1);
+}
+
+template
+inline int non_pawn_index(const Position& pos) {
+ return pos.non_pawn_key(c) & (CORRECTION_HISTORY_SIZE - 1);
+}
+
+// StatsEntry is the container of various numerical statistics. We use a class
+// instead of a naked value to directly call history update operator<<() on
+// the entry. The first template parameter T is the base type of the array,
+// and the second template parameter D limits the range of updates in [-D, D]
+// when we update values with the << operator
+template
+class StatsEntry {
+
+ static_assert(std::is_arithmetic_v, "Not an arithmetic type");
+ static_assert(D <= std::numeric_limits::max(), "D overflows T");
+
+ T entry;
+
+ public:
+ StatsEntry& operator=(const T& v) {
+ entry = v;
+ return *this;
+ }
+ operator const T&() const { return entry; }
+
+ void operator<<(int bonus) {
+ // Make sure that bonus is in range [-D, D]
+ int clampedBonus = std::clamp(bonus, -D, D);
+ entry += clampedBonus - entry * std::abs(clampedBonus) / D;
+
+ assert(std::abs(entry) <= D);
+ }
+};
+
+enum StatsType {
+ NoCaptures,
+ Captures
+};
+
+template
+using Stats = MultiArray, Sizes...>;
+
+// ButterflyHistory records how often quiet moves have been successful or unsuccessful
+// during the current search, and is used for reduction and move ordering decisions.
+// It uses 2 tables (one for each color) indexed by the move's from and to squares,
+// see https://www.chessprogramming.org/Butterfly_Boards (~11 elo)
+using ButterflyHistory = Stats;
+
+// LowPlyHistory is adressed by play and move's from and to squares, used
+// to improve move ordering near the root
+using LowPlyHistory =
+ Stats;
+
+// CapturePieceToHistory is addressed by a move's [piece][to][captured piece type]
+using CapturePieceToHistory = Stats;
+
+// PieceToHistory is like ButterflyHistory but is addressed by a move's [piece][to]
+using PieceToHistory = Stats;
+
+// ContinuationHistory is the combined history of a given pair of moves, usually
+// the current one given a previous one. The nested history table is based on
+// PieceToHistory instead of ButterflyBoards.
+// (~63 elo)
+using ContinuationHistory = MultiArray;
+
+// PawnHistory is addressed by the pawn structure and a move's [piece][to]
+using PawnHistory = Stats;
+
+// Correction histories record differences between the static evaluation of
+// positions and their search score. It is used to improve the static evaluation
+// used by some search heuristics.
+// see https://www.chessprogramming.org/Static_Evaluation_Correction_History
+enum CorrHistType {
+ Pawn, // By color and pawn structure
+ Minor, // By color and positions of minor pieces (Knight, Bishop)
+ NonPawn, // By non-pawn material positions and color
+ PieceTo, // By [piece][to] move
+ Continuation, // Combined history of move pairs
+};
+
+namespace Detail {
+
+template
+struct CorrHistTypedef {
+ using type = Stats;
+};
+
+template<>
+struct CorrHistTypedef {
+ using type = Stats;
+};
+
+template<>
+struct CorrHistTypedef {
+ using type = MultiArray::type, PIECE_NB, SQUARE_NB>;
+};
+
+template<>
+struct CorrHistTypedef {
+ using type =
+ Stats;
+};
+
+}
+
+template
+using CorrectionHistory = typename Detail::CorrHistTypedef::type;
+
+} // namespace Stockfish
+
+#endif // #ifndef HISTORY_H_INCLUDED
diff --git a/stockfish/src/incbin/UNLICENCE b/stockfish/src/incbin/UNLICENCE
new file mode 100644
index 0000000000000000000000000000000000000000..32484ab5e7026f9a1f15c2f8c08b1418802e02a8
--- /dev/null
+++ b/stockfish/src/incbin/UNLICENCE
@@ -0,0 +1,26 @@
+The file "incbin.h" is free and unencumbered software released into
+the public domain by Dale Weiler, see:
+
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+For more information, please refer to
diff --git a/stockfish/src/incbin/incbin.h b/stockfish/src/incbin/incbin.h
new file mode 100644
index 0000000000000000000000000000000000000000..3f662e15dad1864dc6031c6491a21a6815994f1a
--- /dev/null
+++ b/stockfish/src/incbin/incbin.h
@@ -0,0 +1,476 @@
+/**
+ * @file incbin.h
+ * @author Dale Weiler
+ * @brief Utility for including binary files
+ *
+ * Facilities for including binary files into the current translation unit and
+ * making use from them externally in other translation units.
+ */
+#ifndef INCBIN_HDR
+#define INCBIN_HDR
+#include
+#if defined(__AVX512BW__) || \
+ defined(__AVX512CD__) || \
+ defined(__AVX512DQ__) || \
+ defined(__AVX512ER__) || \
+ defined(__AVX512PF__) || \
+ defined(__AVX512VL__) || \
+ defined(__AVX512F__)
+# define INCBIN_ALIGNMENT_INDEX 6
+#elif defined(__AVX__) || \
+ defined(__AVX2__)
+# define INCBIN_ALIGNMENT_INDEX 5
+#elif defined(__SSE__) || \
+ defined(__SSE2__) || \
+ defined(__SSE3__) || \
+ defined(__SSSE3__) || \
+ defined(__SSE4_1__) || \
+ defined(__SSE4_2__) || \
+ defined(__neon__) || \
+ defined(__ARM_NEON) || \
+ defined(__ALTIVEC__)
+# define INCBIN_ALIGNMENT_INDEX 4
+#elif ULONG_MAX != 0xffffffffu
+# define INCBIN_ALIGNMENT_INDEX 3
+# else
+# define INCBIN_ALIGNMENT_INDEX 2
+#endif
+
+/* Lookup table of (1 << n) where `n' is `INCBIN_ALIGNMENT_INDEX' */
+#define INCBIN_ALIGN_SHIFT_0 1
+#define INCBIN_ALIGN_SHIFT_1 2
+#define INCBIN_ALIGN_SHIFT_2 4
+#define INCBIN_ALIGN_SHIFT_3 8
+#define INCBIN_ALIGN_SHIFT_4 16
+#define INCBIN_ALIGN_SHIFT_5 32
+#define INCBIN_ALIGN_SHIFT_6 64
+
+/* Actual alignment value */
+#define INCBIN_ALIGNMENT \
+ INCBIN_CONCATENATE( \
+ INCBIN_CONCATENATE(INCBIN_ALIGN_SHIFT, _), \
+ INCBIN_ALIGNMENT_INDEX)
+
+/* Stringize */
+#define INCBIN_STR(X) \
+ #X
+#define INCBIN_STRINGIZE(X) \
+ INCBIN_STR(X)
+/* Concatenate */
+#define INCBIN_CAT(X, Y) \
+ X ## Y
+#define INCBIN_CONCATENATE(X, Y) \
+ INCBIN_CAT(X, Y)
+/* Deferred macro expansion */
+#define INCBIN_EVAL(X) \
+ X
+#define INCBIN_INVOKE(N, ...) \
+ INCBIN_EVAL(N(__VA_ARGS__))
+/* Variable argument count for overloading by arity */
+#define INCBIN_VA_ARG_COUNTER(_1, _2, _3, N, ...) N
+#define INCBIN_VA_ARGC(...) INCBIN_VA_ARG_COUNTER(__VA_ARGS__, 3, 2, 1, 0)
+
+/* Green Hills uses a different directive for including binary data */
+#if defined(__ghs__)
+# if (__ghs_asm == 2)
+# define INCBIN_MACRO ".file"
+/* Or consider the ".myrawdata" entry in the ld file */
+# else
+# define INCBIN_MACRO "\tINCBIN"
+# endif
+#else
+# define INCBIN_MACRO ".incbin"
+#endif
+
+#ifndef _MSC_VER
+# define INCBIN_ALIGN \
+ __attribute__((aligned(INCBIN_ALIGNMENT)))
+#else
+# define INCBIN_ALIGN __declspec(align(INCBIN_ALIGNMENT))
+#endif
+
+#if defined(__arm__) || /* GNU C and RealView */ \
+ defined(__arm) || /* Diab */ \
+ defined(_ARM) /* ImageCraft */
+# define INCBIN_ARM
+#endif
+
+#ifdef __GNUC__
+/* Utilize .balign where supported */
+# define INCBIN_ALIGN_HOST ".balign " INCBIN_STRINGIZE(INCBIN_ALIGNMENT) "\n"
+# define INCBIN_ALIGN_BYTE ".balign 1\n"
+#elif defined(INCBIN_ARM)
+/*
+ * On arm assemblers, the alignment value is calculated as (1 << n) where `n' is
+ * the shift count. This is the value passed to `.align'
+ */
+# define INCBIN_ALIGN_HOST ".align " INCBIN_STRINGIZE(INCBIN_ALIGNMENT_INDEX) "\n"
+# define INCBIN_ALIGN_BYTE ".align 0\n"
+#else
+/* We assume other inline assembler's treat `.align' as `.balign' */
+# define INCBIN_ALIGN_HOST ".align " INCBIN_STRINGIZE(INCBIN_ALIGNMENT) "\n"
+# define INCBIN_ALIGN_BYTE ".align 1\n"
+#endif
+
+/* INCBIN_CONST is used by incbin.c generated files */
+#if defined(__cplusplus)
+# define INCBIN_EXTERNAL extern "C"
+# define INCBIN_CONST extern const
+#else
+# define INCBIN_EXTERNAL extern
+# define INCBIN_CONST const
+#endif
+
+/**
+ * @brief Optionally override the linker section into which size and data is
+ * emitted.
+ *
+ * @warning If you use this facility, you might have to deal with
+ * platform-specific linker output section naming on your own.
+ */
+#if !defined(INCBIN_OUTPUT_SECTION)
+# if defined(__APPLE__)
+# define INCBIN_OUTPUT_SECTION ".const_data"
+# else
+# define INCBIN_OUTPUT_SECTION ".rodata"
+# endif
+#endif
+
+/**
+ * @brief Optionally override the linker section into which data is emitted.
+ *
+ * @warning If you use this facility, you might have to deal with
+ * platform-specific linker output section naming on your own.
+ */
+#if !defined(INCBIN_OUTPUT_DATA_SECTION)
+# define INCBIN_OUTPUT_DATA_SECTION INCBIN_OUTPUT_SECTION
+#endif
+
+/**
+ * @brief Optionally override the linker section into which size is emitted.
+ *
+ * @warning If you use this facility, you might have to deal with
+ * platform-specific linker output section naming on your own.
+ *
+ * @note This is useful for Harvard architectures where program memory cannot
+ * be directly read from the program without special instructions. With this you
+ * can chose to put the size variable in RAM rather than ROM.
+ */
+#if !defined(INCBIN_OUTPUT_SIZE_SECTION)
+# define INCBIN_OUTPUT_SIZE_SECTION INCBIN_OUTPUT_SECTION
+#endif
+
+#if defined(__APPLE__)
+# include "TargetConditionals.h"
+# if defined(TARGET_OS_IPHONE) && !defined(INCBIN_SILENCE_BITCODE_WARNING)
+# warning "incbin is incompatible with bitcode. Using the library will break upload to App Store if you have bitcode enabled. Add `#define INCBIN_SILENCE_BITCODE_WARNING` before including this header to silence this warning."
+# endif
+/* The directives are different for Apple branded compilers */
+# define INCBIN_SECTION INCBIN_OUTPUT_SECTION "\n"
+# define INCBIN_GLOBAL(NAME) ".globl " INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME "\n"
+# define INCBIN_INT ".long "
+# define INCBIN_MANGLE "_"
+# define INCBIN_BYTE ".byte "
+# define INCBIN_TYPE(...)
+#else
+# define INCBIN_SECTION ".section " INCBIN_OUTPUT_SECTION "\n"
+# define INCBIN_GLOBAL(NAME) ".global " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME "\n"
+# if defined(__ghs__)
+# define INCBIN_INT ".word "
+# else
+# define INCBIN_INT ".int "
+# endif
+# if defined(__USER_LABEL_PREFIX__)
+# define INCBIN_MANGLE INCBIN_STRINGIZE(__USER_LABEL_PREFIX__)
+# else
+# define INCBIN_MANGLE ""
+# endif
+# if defined(INCBIN_ARM)
+/* On arm assemblers, `@' is used as a line comment token */
+# define INCBIN_TYPE(NAME) ".type " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME ", %object\n"
+# elif defined(__MINGW32__) || defined(__MINGW64__)
+/* Mingw doesn't support this directive either */
+# define INCBIN_TYPE(NAME)
+# else
+/* It's safe to use `@' on other architectures */
+# define INCBIN_TYPE(NAME) ".type " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME ", @object\n"
+# endif
+# define INCBIN_BYTE ".byte "
+#endif
+
+/* List of style types used for symbol names */
+#define INCBIN_STYLE_CAMEL 0
+#define INCBIN_STYLE_SNAKE 1
+
+/**
+ * @brief Specify the prefix to use for symbol names.
+ *
+ * @note By default this is "g".
+ *
+ * @code
+ * #define INCBIN_PREFIX incbin
+ * #include "incbin.h"
+ * INCBIN(Foo, "foo.txt");
+ *
+ * // Now you have the following symbols instead:
+ * // const unsigned char incbinFoo[];
+ * // const unsigned char *const incbinFoo;
+ * // const unsigned int incbinFoo;
+ * @endcode
+ */
+#if !defined(INCBIN_PREFIX)
+# define INCBIN_PREFIX g
+#endif
+
+/**
+ * @brief Specify the style used for symbol names.
+ *
+ * Possible options are
+ * - INCBIN_STYLE_CAMEL "CamelCase"
+ * - INCBIN_STYLE_SNAKE "snake_case"
+ *
+ * @note By default this is INCBIN_STYLE_CAMEL
+ *
+ * @code
+ * #define INCBIN_STYLE INCBIN_STYLE_SNAKE
+ * #include "incbin.h"
+ * INCBIN(foo, "foo.txt");
+ *
+ * // Now you have the following symbols:
+ * // const unsigned char foo_data[];
+ * // const unsigned char *const foo_end;
+ * // const unsigned int foo_size;
+ * @endcode
+ */
+#if !defined(INCBIN_STYLE)
+# define INCBIN_STYLE INCBIN_STYLE_CAMEL
+#endif
+
+/* Style lookup tables */
+#define INCBIN_STYLE_0_DATA Data
+#define INCBIN_STYLE_0_END End
+#define INCBIN_STYLE_0_SIZE Size
+#define INCBIN_STYLE_1_DATA _data
+#define INCBIN_STYLE_1_END _end
+#define INCBIN_STYLE_1_SIZE _size
+
+/* Style lookup: returning identifier */
+#define INCBIN_STYLE_IDENT(TYPE) \
+ INCBIN_CONCATENATE( \
+ INCBIN_STYLE_, \
+ INCBIN_CONCATENATE( \
+ INCBIN_EVAL(INCBIN_STYLE), \
+ INCBIN_CONCATENATE(_, TYPE)))
+
+/* Style lookup: returning string literal */
+#define INCBIN_STYLE_STRING(TYPE) \
+ INCBIN_STRINGIZE( \
+ INCBIN_STYLE_IDENT(TYPE)) \
+
+/* Generate the global labels by indirectly invoking the macro with our style
+ * type and concatenating the name against them. */
+#define INCBIN_GLOBAL_LABELS(NAME, TYPE) \
+ INCBIN_INVOKE( \
+ INCBIN_GLOBAL, \
+ INCBIN_CONCATENATE( \
+ NAME, \
+ INCBIN_INVOKE( \
+ INCBIN_STYLE_IDENT, \
+ TYPE))) \
+ INCBIN_INVOKE( \
+ INCBIN_TYPE, \
+ INCBIN_CONCATENATE( \
+ NAME, \
+ INCBIN_INVOKE( \
+ INCBIN_STYLE_IDENT, \
+ TYPE)))
+
+/**
+ * @brief Externally reference binary data included in another translation unit.
+ *
+ * Produces three external symbols that reference the binary data included in
+ * another translation unit.
+ *
+ * The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
+ * "Data", as well as "End" and "Size" after. An example is provided below.
+ *
+ * @param TYPE Optional array type. Omitting this picks a default of `unsigned char`.
+ * @param NAME The name given for the binary data
+ *
+ * @code
+ * INCBIN_EXTERN(Foo);
+ *
+ * // Now you have the following symbols:
+ * // extern const unsigned char Foo[];
+ * // extern const unsigned char *const Foo;
+ * // extern const unsigned int Foo;
+ * @endcode
+ *
+ * You may specify a custom optional data type as well as the first argument.
+ * @code
+ * INCBIN_EXTERN(custom_type, Foo);
+ *
+ * // Now you have the following symbols:
+ * // extern const custom_type Foo[];
+ * // extern const custom_type *const Foo;
+ * // extern const unsigned int Foo;
+ * @endcode
+ */
+#define INCBIN_EXTERN(...) \
+ INCBIN_CONCATENATE(INCBIN_EXTERN_, INCBIN_VA_ARGC(__VA_ARGS__))(__VA_ARGS__)
+#define INCBIN_EXTERN_1(NAME, ...) \
+ INCBIN_EXTERN_2(unsigned char, NAME)
+#define INCBIN_EXTERN_2(TYPE, NAME) \
+ INCBIN_EXTERNAL const INCBIN_ALIGN TYPE \
+ INCBIN_CONCATENATE( \
+ INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
+ INCBIN_STYLE_IDENT(DATA))[]; \
+ INCBIN_EXTERNAL const INCBIN_ALIGN TYPE *const \
+ INCBIN_CONCATENATE( \
+ INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
+ INCBIN_STYLE_IDENT(END)); \
+ INCBIN_EXTERNAL const unsigned int \
+ INCBIN_CONCATENATE( \
+ INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
+ INCBIN_STYLE_IDENT(SIZE))
+
+/**
+ * @brief Externally reference textual data included in another translation unit.
+ *
+ * Produces three external symbols that reference the textual data included in
+ * another translation unit.
+ *
+ * The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
+ * "Data", as well as "End" and "Size" after. An example is provided below.
+ *
+ * @param NAME The name given for the textual data
+ *
+ * @code
+ * INCBIN_EXTERN(Foo);
+ *
+ * // Now you have the following symbols:
+ * // extern const char Foo[];
+ * // extern const char *const Foo;
+ * // extern const unsigned int Foo;
+ * @endcode
+ */
+#define INCTXT_EXTERN(NAME) \
+ INCBIN_EXTERN_2(char, NAME)
+
+/**
+ * @brief Include a binary file into the current translation unit.
+ *
+ * Includes a binary file into the current translation unit, producing three symbols
+ * for objects that encode the data and size respectively.
+ *
+ * The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
+ * "Data", as well as "End" and "Size" after. An example is provided below.
+ *
+ * @param TYPE Optional array type. Omitting this picks a default of `unsigned char`.
+ * @param NAME The name to associate with this binary data (as an identifier.)
+ * @param FILENAME The file to include (as a string literal.)
+ *
+ * @code
+ * INCBIN(Icon, "icon.png");
+ *
+ * // Now you have the following symbols:
+ * // const unsigned char Icon[];
+ * // const unsigned char *const Icon;
+ * // const unsigned int Icon;
+ * @endcode
+ *
+ * You may specify a custom optional data type as well as the first argument.
+ * These macros are specialized by arity.
+ * @code
+ * INCBIN(custom_type, Icon, "icon.png");
+ *
+ * // Now you have the following symbols:
+ * // const custom_type Icon[];
+ * // const custom_type *const Icon;
+ * // const unsigned int Icon;
+ * @endcode
+ *
+ * @warning This must be used in global scope
+ * @warning The identifiers may be different if INCBIN_STYLE is not default
+ *
+ * To externally reference the data included by this in another translation unit
+ * please @see INCBIN_EXTERN.
+ */
+#ifdef _MSC_VER
+# define INCBIN(NAME, FILENAME) \
+ INCBIN_EXTERN(NAME)
+#else
+# define INCBIN(...) \
+ INCBIN_CONCATENATE(INCBIN_, INCBIN_VA_ARGC(__VA_ARGS__))(__VA_ARGS__)
+# if defined(__GNUC__)
+# define INCBIN_1(...) _Pragma("GCC error \"Single argument INCBIN not allowed\"")
+# elif defined(__clang__)
+# define INCBIN_1(...) _Pragma("clang error \"Single argument INCBIN not allowed\"")
+# else
+# define INCBIN_1(...) /* Cannot do anything here */
+# endif
+# define INCBIN_2(NAME, FILENAME) \
+ INCBIN_3(unsigned char, NAME, FILENAME)
+# define INCBIN_3(TYPE, NAME, FILENAME) INCBIN_COMMON(TYPE, NAME, FILENAME, /* No terminator for binary data */)
+# define INCBIN_COMMON(TYPE, NAME, FILENAME, TERMINATOR) \
+ __asm__(INCBIN_SECTION \
+ INCBIN_GLOBAL_LABELS(NAME, DATA) \
+ INCBIN_ALIGN_HOST \
+ INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(DATA) ":\n" \
+ INCBIN_MACRO " \"" FILENAME "\"\n" \
+ TERMINATOR \
+ INCBIN_GLOBAL_LABELS(NAME, END) \
+ INCBIN_ALIGN_BYTE \
+ INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(END) ":\n" \
+ INCBIN_BYTE "1\n" \
+ INCBIN_GLOBAL_LABELS(NAME, SIZE) \
+ INCBIN_ALIGN_HOST \
+ INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(SIZE) ":\n" \
+ INCBIN_INT INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(END) " - " \
+ INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(DATA) "\n" \
+ INCBIN_ALIGN_HOST \
+ ".text\n" \
+ ); \
+ INCBIN_EXTERN(TYPE, NAME)
+#endif
+
+/**
+ * @brief Include a textual file into the current translation unit.
+ *
+ * This behaves the same as INCBIN except it produces char compatible arrays
+ * and implicitly adds a null-terminator byte, thus the size of data included
+ * by this is one byte larger than that of INCBIN.
+ *
+ * Includes a textual file into the current translation unit, producing three
+ * symbols for objects that encode the data and size respectively.
+ *
+ * The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
+ * "Data", as well as "End" and "Size" after. An example is provided below.
+ *
+ * @param NAME The name to associate with this binary data (as an identifier.)
+ * @param FILENAME The file to include (as a string literal.)
+ *
+ * @code
+ * INCTXT(Readme, "readme.txt");
+ *
+ * // Now you have the following symbols:
+ * // const char Readme[];
+ * // const char *const Readme;
+ * // const unsigned int Readme;
+ * @endcode
+ *
+ * @warning This must be used in global scope
+ * @warning The identifiers may be different if INCBIN_STYLE is not default
+ *
+ * To externally reference the data included by this in another translation unit
+ * please @see INCBIN_EXTERN.
+ */
+#if defined(_MSC_VER)
+# define INCTXT(NAME, FILENAME) \
+ INCBIN_EXTERN(NAME)
+#else
+# define INCTXT(NAME, FILENAME) \
+ INCBIN_COMMON(char, NAME, FILENAME, INCBIN_BYTE "0\n")
+#endif
+
+#endif
\ No newline at end of file
diff --git a/stockfish/src/main.cpp b/stockfish/src/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e262f387576a61577836de95b65a2403d2224fe0
--- /dev/null
+++ b/stockfish/src/main.cpp
@@ -0,0 +1,44 @@
+/*
+ Stockfish, a UCI chess playing engine derived from Glaurung 2.1
+ Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
+
+ Stockfish is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Stockfish is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include
+
+#include "bitboard.h"
+#include "misc.h"
+#include "position.h"
+#include "types.h"
+#include "uci.h"
+#include "tune.h"
+
+using namespace Stockfish;
+
+int main(int argc, char* argv[]) {
+
+ std::cout << engine_info() << std::endl;
+
+ Bitboards::init();
+ Position::init();
+
+ UCIEngine uci(argc, argv);
+
+ Tune::init(uci.engine_options());
+
+ uci.loop();
+
+ return 0;
+}
diff --git a/stockfish/src/memory.cpp b/stockfish/src/memory.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..92cb650f26fb66d5afaabb1f179fdaee133e4e65
--- /dev/null
+++ b/stockfish/src/memory.cpp
@@ -0,0 +1,268 @@
+/*
+ Stockfish, a UCI chess playing engine derived from Glaurung 2.1
+ Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
+
+ Stockfish is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Stockfish is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "memory.h"
+
+#include
+
+#if __has_include("features.h")
+ #include
+#endif
+
+#if defined(__linux__) && !defined(__ANDROID__)
+ #include
+#endif
+
+#if defined(__APPLE__) || defined(__ANDROID__) || defined(__OpenBSD__) \
+ || (defined(__GLIBCXX__) && !defined(_GLIBCXX_HAVE_ALIGNED_ALLOC) && !defined(_WIN32)) \
+ || defined(__e2k__)
+ #define POSIXALIGNEDALLOC
+ #include
+#endif
+
+#ifdef _WIN32
+ #if _WIN32_WINNT < 0x0601
+ #undef _WIN32_WINNT
+ #define _WIN32_WINNT 0x0601 // Force to include needed API prototypes
+ #endif
+
+ #ifndef NOMINMAX
+ #define NOMINMAX
+ #endif
+
+ #include // std::hex, std::dec
+ #include // std::cerr
+ #include // std::endl
+ #include
+
+// The needed Windows API for processor groups could be missed from old Windows
+// versions, so instead of calling them directly (forcing the linker to resolve
+// the calls at compile time), try to load them at runtime. To do this we need
+// first to define the corresponding function pointers.
+
+extern "C" {
+using OpenProcessToken_t = bool (*)(HANDLE, DWORD, PHANDLE);
+using LookupPrivilegeValueA_t = bool (*)(LPCSTR, LPCSTR, PLUID);
+using AdjustTokenPrivileges_t =
+ bool (*)(HANDLE, BOOL, PTOKEN_PRIVILEGES, DWORD, PTOKEN_PRIVILEGES, PDWORD);
+}
+#endif
+
+
+namespace Stockfish {
+
+// Wrappers for systems where the c++17 implementation does not guarantee the
+// availability of aligned_alloc(). Memory allocated with std_aligned_alloc()
+// must be freed with std_aligned_free().
+
+void* std_aligned_alloc(size_t alignment, size_t size) {
+#if defined(_ISOC11_SOURCE)
+ return aligned_alloc(alignment, size);
+#elif defined(POSIXALIGNEDALLOC)
+ void* mem = nullptr;
+ posix_memalign(&mem, alignment, size);
+ return mem;
+#elif defined(_WIN32) && !defined(_M_ARM) && !defined(_M_ARM64)
+ return _mm_malloc(size, alignment);
+#elif defined(_WIN32)
+ return _aligned_malloc(size, alignment);
+#else
+ return std::aligned_alloc(alignment, size);
+#endif
+}
+
+void std_aligned_free(void* ptr) {
+
+#if defined(POSIXALIGNEDALLOC)
+ free(ptr);
+#elif defined(_WIN32) && !defined(_M_ARM) && !defined(_M_ARM64)
+ _mm_free(ptr);
+#elif defined(_WIN32)
+ _aligned_free(ptr);
+#else
+ free(ptr);
+#endif
+}
+
+// aligned_large_pages_alloc() will return suitably aligned memory,
+// if possible using large pages.
+
+#if defined(_WIN32)
+
+static void* aligned_large_pages_alloc_windows([[maybe_unused]] size_t allocSize) {
+
+ #if !defined(_WIN64)
+ return nullptr;
+ #else
+
+ HANDLE hProcessToken{};
+ LUID luid{};
+ void* mem = nullptr;
+
+ const size_t largePageSize = GetLargePageMinimum();
+ if (!largePageSize)
+ return nullptr;
+
+ // Dynamically link OpenProcessToken, LookupPrivilegeValue and AdjustTokenPrivileges
+
+ HMODULE hAdvapi32 = GetModuleHandle(TEXT("advapi32.dll"));
+
+ if (!hAdvapi32)
+ hAdvapi32 = LoadLibrary(TEXT("advapi32.dll"));
+
+ auto OpenProcessToken_f =
+ OpenProcessToken_t((void (*)()) GetProcAddress(hAdvapi32, "OpenProcessToken"));
+ if (!OpenProcessToken_f)
+ return nullptr;
+ auto LookupPrivilegeValueA_f =
+ LookupPrivilegeValueA_t((void (*)()) GetProcAddress(hAdvapi32, "LookupPrivilegeValueA"));
+ if (!LookupPrivilegeValueA_f)
+ return nullptr;
+ auto AdjustTokenPrivileges_f =
+ AdjustTokenPrivileges_t((void (*)()) GetProcAddress(hAdvapi32, "AdjustTokenPrivileges"));
+ if (!AdjustTokenPrivileges_f)
+ return nullptr;
+
+ // We need SeLockMemoryPrivilege, so try to enable it for the process
+
+ if (!OpenProcessToken_f( // OpenProcessToken()
+ GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hProcessToken))
+ return nullptr;
+
+ if (LookupPrivilegeValueA_f(nullptr, "SeLockMemoryPrivilege", &luid))
+ {
+ TOKEN_PRIVILEGES tp{};
+ TOKEN_PRIVILEGES prevTp{};
+ DWORD prevTpLen = 0;
+
+ tp.PrivilegeCount = 1;
+ tp.Privileges[0].Luid = luid;
+ tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+ // Try to enable SeLockMemoryPrivilege. Note that even if AdjustTokenPrivileges()
+ // succeeds, we still need to query GetLastError() to ensure that the privileges
+ // were actually obtained.
+
+ if (AdjustTokenPrivileges_f(hProcessToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &prevTp,
+ &prevTpLen)
+ && GetLastError() == ERROR_SUCCESS)
+ {
+ // Round up size to full pages and allocate
+ allocSize = (allocSize + largePageSize - 1) & ~size_t(largePageSize - 1);
+ mem = VirtualAlloc(nullptr, allocSize, MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES,
+ PAGE_READWRITE);
+
+ // Privilege no longer needed, restore previous state
+ AdjustTokenPrivileges_f(hProcessToken, FALSE, &prevTp, 0, nullptr, nullptr);
+ }
+ }
+
+ CloseHandle(hProcessToken);
+
+ return mem;
+
+ #endif
+}
+
+void* aligned_large_pages_alloc(size_t allocSize) {
+
+ // Try to allocate large pages
+ void* mem = aligned_large_pages_alloc_windows(allocSize);
+
+ // Fall back to regular, page-aligned, allocation if necessary
+ if (!mem)
+ mem = VirtualAlloc(nullptr, allocSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
+
+ return mem;
+}
+
+#else
+
+void* aligned_large_pages_alloc(size_t allocSize) {
+
+ #if defined(__linux__)
+ constexpr size_t alignment = 2 * 1024 * 1024; // 2MB page size assumed
+ #else
+ constexpr size_t alignment = 4096; // small page size assumed
+ #endif
+
+ // Round up to multiples of alignment
+ size_t size = ((allocSize + alignment - 1) / alignment) * alignment;
+ void* mem = std_aligned_alloc(alignment, size);
+ #if defined(MADV_HUGEPAGE)
+ madvise(mem, size, MADV_HUGEPAGE);
+ #endif
+ return mem;
+}
+
+#endif
+
+bool has_large_pages() {
+
+#if defined(_WIN32)
+
+ constexpr size_t page_size = 2 * 1024 * 1024; // 2MB page size assumed
+ void* mem = aligned_large_pages_alloc_windows(page_size);
+ if (mem == nullptr)
+ {
+ return false;
+ }
+ else
+ {
+ aligned_large_pages_free(mem);
+ return true;
+ }
+
+#elif defined(__linux__)
+
+ #if defined(MADV_HUGEPAGE)
+ return true;
+ #else
+ return false;
+ #endif
+
+#else
+
+ return false;
+
+#endif
+}
+
+
+// aligned_large_pages_free() will free the previously memory allocated
+// by aligned_large_pages_alloc(). The effect is a nop if mem == nullptr.
+
+#if defined(_WIN32)
+
+void aligned_large_pages_free(void* mem) {
+
+ if (mem && !VirtualFree(mem, 0, MEM_RELEASE))
+ {
+ DWORD err = GetLastError();
+ std::cerr << "Failed to free large page memory. Error code: 0x" << std::hex << err
+ << std::dec << std::endl;
+ exit(EXIT_FAILURE);
+ }
+}
+
+#else
+
+void aligned_large_pages_free(void* mem) { std_aligned_free(mem); }
+
+#endif
+} // namespace Stockfish
diff --git a/stockfish/src/memory.h b/stockfish/src/memory.h
new file mode 100644
index 0000000000000000000000000000000000000000..4dc23287835b85983ea24a062a91bbc0f01fd2f0
--- /dev/null
+++ b/stockfish/src/memory.h
@@ -0,0 +1,218 @@
+/*
+ Stockfish, a UCI chess playing engine derived from Glaurung 2.1
+ Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
+
+ Stockfish is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Stockfish is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef MEMORY_H_INCLUDED
+#define MEMORY_H_INCLUDED
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "types.h"
+
+namespace Stockfish {
+
+void* std_aligned_alloc(size_t alignment, size_t size);
+void std_aligned_free(void* ptr);
+
+// Memory aligned by page size, min alignment: 4096 bytes
+void* aligned_large_pages_alloc(size_t size);
+void aligned_large_pages_free(void* mem);
+
+bool has_large_pages();
+
+// Frees memory which was placed there with placement new.
+// Works for both single objects and arrays of unknown bound.
+template
+void memory_deleter(T* ptr, FREE_FUNC free_func) {
+ if (!ptr)
+ return;
+
+ // Explicitly needed to call the destructor
+ if constexpr (!std::is_trivially_destructible_v)
+ ptr->~T();
+
+ free_func(ptr);
+ return;
+}
+
+// Frees memory which was placed there with placement new.
+// Works for both single objects and arrays of unknown bound.
+template
+void memory_deleter_array(T* ptr, FREE_FUNC free_func) {
+ if (!ptr)
+ return;
+
+
+ // Move back on the pointer to where the size is allocated
+ const size_t array_offset = std::max(sizeof(size_t), alignof(T));
+ char* raw_memory = reinterpret_cast(ptr) - array_offset;
+
+ if constexpr (!std::is_trivially_destructible_v)
+ {
+ const size_t size = *reinterpret_cast(raw_memory);
+
+ // Explicitly call the destructor for each element in reverse order
+ for (size_t i = size; i-- > 0;)
+ ptr[i].~T();
+ }
+
+ free_func(raw_memory);
+}
+
+// Allocates memory for a single object and places it there with placement new
+template
+inline std::enable_if_t, T*> memory_allocator(ALLOC_FUNC alloc_func,
+ Args&&... args) {
+ void* raw_memory = alloc_func(sizeof(T));
+ ASSERT_ALIGNED(raw_memory, alignof(T));
+ return new (raw_memory) T(std::forward(args)...);
+}
+
+// Allocates memory for an array of unknown bound and places it there with placement new
+template
+inline std::enable_if_t, std::remove_extent_t*>
+memory_allocator(ALLOC_FUNC alloc_func, size_t num) {
+ using ElementType = std::remove_extent_t;
+
+ const size_t array_offset = std::max(sizeof(size_t), alignof(ElementType));
+
+ // Save the array size in the memory location
+ char* raw_memory =
+ reinterpret_cast(alloc_func(array_offset + num * sizeof(ElementType)));
+ ASSERT_ALIGNED(raw_memory, alignof(T));
+
+ new (raw_memory) size_t(num);
+
+ for (size_t i = 0; i < num; ++i)
+ new (raw_memory + array_offset + i * sizeof(ElementType)) ElementType();
+
+ // Need to return the pointer at the start of the array so that
+ // the indexing in unique_ptr works.
+ return reinterpret_cast(raw_memory + array_offset);
+}
+
+//
+//
+// aligned large page unique ptr
+//
+//
+
+template
+struct LargePageDeleter {
+ void operator()(T* ptr) const { return memory_deleter(ptr, aligned_large_pages_free); }
+};
+
+template
+struct LargePageArrayDeleter {
+ void operator()(T* ptr) const { return memory_deleter_array(ptr, aligned_large_pages_free); }
+};
+
+template
+using LargePagePtr =
+ std::conditional_t,
+ std::unique_ptr>>,
+ std::unique_ptr>>;
+
+// make_unique_large_page for single objects
+template
+std::enable_if_t, LargePagePtr> make_unique_large_page(Args&&... args) {
+ static_assert(alignof(T) <= 4096,
+ "aligned_large_pages_alloc() may fail for such a big alignment requirement of T");
+
+ T* obj = memory_allocator(aligned_large_pages_alloc, std::forward(args)...);
+
+ return LargePagePtr(obj);
+}
+
+// make_unique_large_page for arrays of unknown bound
+template
+std::enable_if_t, LargePagePtr> make_unique_large_page(size_t num) {
+ using ElementType = std::remove_extent_t;
+
+ static_assert(alignof(ElementType) <= 4096,
+ "aligned_large_pages_alloc() may fail for such a big alignment requirement of T");
+
+ ElementType* memory = memory_allocator(aligned_large_pages_alloc, num);
+
+ return LargePagePtr(memory);
+}
+
+//
+//
+// aligned unique ptr
+//
+//
+
+template
+struct AlignedDeleter {
+ void operator()(T* ptr) const { return memory_deleter(ptr, std_aligned_free); }
+};
+
+template
+struct AlignedArrayDeleter {
+ void operator()(T* ptr) const { return memory_deleter_array(ptr, std_aligned_free); }
+};
+
+template
+using AlignedPtr =
+ std::conditional_t,
+ std::unique_ptr>>,
+ std::unique_ptr>>;
+
+// make_unique_aligned for single objects
+template
+std::enable_if_t, AlignedPtr> make_unique_aligned(Args&&... args) {
+ const auto func = [](size_t size) { return std_aligned_alloc(alignof(T), size); };
+ T* obj = memory_allocator(func, std::forward(args)...);
+
+ return AlignedPtr(obj);
+}
+
+// make_unique_aligned for arrays of unknown bound
+template