Compare commits

...

680 Commits

Author SHA1 Message Date
Disservin e67cc979fd Stockfish 16.1
Official release version of Stockfish 16.1

Bench: 1303971

---

Stockfish 16.1

Today, we have the pleasure to announce Stockfish 16.1. As always, you can
freely download it at https://stockfishchess.org/download and use it in the GUI
of your choice[1].

Don't forget to join our Discord server[2] to get in touch with the community of
developers and users of the project!

*Quality of chess play*

In our testing against its predecessor, Stockfish 16.1 shows a notable
improvement in performance, with an Elo gain of up to 27 points and winning over
2 times more game pairs[3] than it loses.

*Update highlights*

*Improved evaluation*

- Updated neural network architecture: The neural network architecture has
  undergone two updates and is currently in its 8th version[4].
- Removal of handcrafted evaluation (HCE): This release marks the removal of the
  traditional handcrafted evaluation and the transition to a fully neural
  network-based approach[5].
- Dual NNUE: For the first time, Stockfish includes a secondary neural
  network[6], used to quickly evaluate positions that are easily decided.

*UCI Options removed*

`Use NNUE` and `UCI_AnalyseMode`[7] have been removed as they no longer had any
effect. `SlowMover`[8] has also been removed in favor of `Move Overhead`.

*More binaries*

We now offer 13 new binaries. These new binaries include `avx512`, `vnni256`,
`vnni512`, `m1-apple-silicon`, and `armv8-dotprod`, which take advantage of
specific CPU instructions for improved performance.
For most users, using `sse41-popcnt` (formerly `modern`), `avx2`, or `bmi2`
should be enough, but if your CPU supports these new instructions, feel free to
try them!

*Development changes*

- Updated testing book: This new book[9], now derived exclusively from the open
  Lichess database[10], is 10 times larger than its predecessor, and has been
  used to test potential improvements to Stockfish over the past few months.
- Consolidation of repositories: Aiming to simplify access to our resources, we
  have moved most Stockfish-related repositories into the official Stockfish
  organization[11] on GitHub.
- Growing maintainer team: We welcome Disservin[12] to the team of maintainers
  of the project! This extra pair of hands will ensure the lasting success of
  Stockfish.

*Thank you*

The Stockfish project builds on a thriving community of enthusiasts (thanks
everybody!) who contribute their expertise, time, and resources to build a free
and open-source chess engine that is robust, widely available, and very strong.

We would like to express our gratitude for the 10k stars[13] that light up our
GitHub project! Thank you for your support and encouragement – your recognition
means a lot to us.

We invite our chess fans to join the Fishtest testing framework[14], and
programmers to contribute to the project either directly to Stockfish[15] (C++),
to Fishtest[16] (HTML, CSS, JavaScript, and Python), to our trainer
nnue-pytorch[17] (C++ and Python), or to our website[18] (HTML, CSS/SCSS, and
JavaScript).

The Stockfish team

[1] https://github.com/official-stockfish/Stockfish/wiki/Download-and-usage#download-a-chess-gui
[2] https://discord.gg/GWDRS3kU6R
[3] https://tests.stockfishchess.org/tests/view/65d666051d8e83c78bfddbd8
[4] https://github.com/official-stockfish/nnue-pytorch/blob/master/docs/nnue.md#sfnnv8-architecture
[5] https://github.com/official-stockfish/Stockfish/commit/af110e0
[6] https://github.com/official-stockfish/Stockfish/commit/584d9ef
[7] https://github.com/official-stockfish/Stockfish/commit/c53d2ec
[8] https://github.com/official-stockfish/Stockfish/commit/536d692
[9] https://github.com/official-stockfish/books/commit/426eca4
[10] https://database.lichess.org/
[11] https://github.com/official-stockfish/
[12] https://github.com/Disservin
[13] https://github.com/official-stockfish/Stockfish/stargazers
[14] https://github.com/official-stockfish/fishtest/wiki/Running-the-worker
[15] https://github.com/official-stockfish/Stockfish
[16] https://github.com/official-stockfish/fishtest
[17] https://github.com/official-stockfish/nnue-pytorch
[18] https://github.com/official-stockfish/stockfish-web
2024-02-24 18:15:04 +01:00
Robert Nurnberg @ elitebook 5c2b385957 Update the WDL model
Based on 130M positions from 2.1M games.

```
Look recursively in directory pgns for games from SPRT tests using books
matching "UHO_4060_v..epd|UHO_Lichess_4852_v1.epd" for SF revisions
between 8e75548f2a (from 2024-02-17
17:11:46 +0100) and HEAD (from 2024-02-17 17:13:07 +0100). Based on
127920843 positions from 2109240 games, NormalizeToPawnValue should
change from 345 to 356.
```

The patch only affects the UCI-reported cp and wdl values.

closes https://github.com/official-stockfish/Stockfish/pull/5070

No functional change
2024-02-24 17:59:41 +01:00
Disservin bec83a1869 Update Top CPU Contributors
closes https://github.com/official-stockfish/Stockfish/pull/5069

No functional change
2024-02-24 17:58:44 +01:00
Disservin d07033d5da Expose EvalFileSmall option for small net
Since https://github.com/official-stockfish/fishtest/pull/1870 has been merged
it's time for this update.

5k Fixed Games showed no problems.
https://tests.stockfishchess.org/tests/view/65d9cc274c0e22b904f574d7

closes https://github.com/official-stockfish/Stockfish/pull/5068

No functional change
2024-02-24 17:57:49 +01:00
cj5716 fc41f64dfd Simplify PV node reduction
Reduce less on PV nodes even with an upperbound TT entry.

Passed STC:
https://tests.stockfishchess.org/tests/view/65cb3a861d8e83c78bfd0497
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 118752 W: 30441 L: 30307 D: 58004
Ptnml(0-2): 476, 14179, 29921, 14335, 465

Passed LTC:
https://tests.stockfishchess.org/tests/view/65cd3b951d8e83c78bfd2b0d
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 155058 W: 38549 L: 38464 D: 78045
Ptnml(0-2): 85, 17521, 42219, 17632, 72

closes https://github.com/official-stockfish/Stockfish/pull/5057

Bench: 1303971
2024-02-17 17:13:07 +01:00
Linmiao Xu 8e75548f2a Update default main net to nn-b1a57edbea57.nnue
Created by retraining the previous main net `nn-baff1edbea57.nnue` with:
- some of the same options as before: ranger21, more WDL skipping
- the addition of T80 nov+dec 2023 data
- increasing loss by 15% when prediction is too high, up from 10%
- use of torch.compile to speed up training by over 25%

```yaml
experiment-name: 2560--S9-514G-T80-augtodec2023-more-wdl-skip-15p-more-loss-high-q-sk28

training-dataset:
  # https://github.com/official-stockfish/Stockfish/pull/4782
  - /data/S6-514G-1ee1aba5ed.binpack
  - /data/test80-aug2023-2tb7p.v6.min.binpack
  - /data/test80-sep2023-2tb7p.binpack
  - /data/test80-oct2023-2tb7p.binpack
  - /data/test80-nov2023-2tb7p.binpack
  - /data/test80-dec2023-2tb7p.binpack
early-fen-skipping: 28

start-from-engine-test-net: True
nnue-pytorch-branch: linrock/nnue-pytorch/r21-more-wdl-skip-15p-more-loss-high-q-torch-compile

num-epochs: 1000
lr: 4.375e-4
gamma: 0.995
start-lambda: 1.0
end-lambda: 0.7
```

Epoch 819 trained with the above config led to this PR. Use of torch.compile
decorators in nnue-pytorch model.py was found to speed up training by at least
25% on Ampere gpus when using recent pytorch compiled with cuda 12:
https://catalog.ngc.nvidia.com/orgs/nvidia/containers/pytorch

See recent main net PRs for more info on
- ranger21 and more WDL skipping: https://github.com/official-stockfish/Stockfish/pull/4942
- increasing loss when Q is too high: https://github.com/official-stockfish/Stockfish/pull/4972

Training data can be found at:
https://robotmoon.com/nnue-training-data/

Passed STC:
https://tests.stockfishchess.org/tests/view/65cd76151d8e83c78bfd2f52
LLR: 2.98 (-2.94,2.94) <0.00,2.00>
Total: 78336 W: 20504 L: 20115 D: 37717
Ptnml(0-2): 317, 9225, 19721, 9562, 343

Passed LTC:
https://tests.stockfishchess.org/tests/view/65ce5be61d8e83c78bfd43e9
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 41016 W: 10492 L: 10159 D: 20365
Ptnml(0-2): 22, 4533, 11071, 4854, 28

closes https://github.com/official-stockfish/Stockfish/pull/5056

Bench: 1351997
2024-02-17 17:11:46 +01:00
cj5716 f3df0cfb84 Simplify TT PV reduction
This also removes some incorrect fail-high logic.

Passed STC:
https://tests.stockfishchess.org/tests/view/65cb3b641d8e83c78bfd04a9
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 87968 W: 22634 L: 22468 D: 42866
Ptnml(0-2): 315, 10436, 22323, 10588, 322

Passed LTC:
https://tests.stockfishchess.org/tests/view/65cccee21d8e83c78bfd222c
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 70794 W: 17846 L: 17672 D: 35276
Ptnml(0-2): 44, 7980, 19189, 8126, 58

closes https://github.com/official-stockfish/Stockfish/pull/5055

Bench: 1474424
2024-02-17 17:10:13 +01:00
Gahtan Nahdi 9d61822b5d Remove penalty for quiet ttMove that fails low
Passed STC non-reg:
https://tests.stockfishchess.org/tests/view/65c691a7c865510db0286e6e
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 234336 W: 60258 L: 60255 D: 113823
Ptnml(0-2): 966, 28141, 58918, 28210, 933

Passed LTC non-reg:
https://tests.stockfishchess.org/tests/view/65c8d0d31d8e83c78bfcd4a6
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 235206 W: 59134 L: 59132 D: 116940
Ptnml(0-2): 135, 26908, 63517, 26906, 137

https://github.com/official-stockfish/Stockfish/pull/5054

Bench: 1287996
2024-02-17 17:08:01 +01:00
Disservin bf2c7306ac Use node counting to early stop search
This introduces a form of node counting which can
be used to further tweak the usage of our search
time.
The current approach stops the search when almost
all nodes are searched on a single move.

The idea originally came from Koivisto, but the
implemention is a bit different, Koivisto scales
the optimal time by the nodes effort and then
determines if the search should be stopped.
We just scale down the `totalTime` and stop the
search if we exceed it and the effort is large
enough.

Passed STC:
https://tests.stockfishchess.org/tests/view/65c8e0661d8e83c78bfcd5ec
LLR: 2.97 (-2.94,2.94) <0.00,2.00>
Total: 88672 W: 22907 L: 22512 D: 43253
Ptnml(0-2): 310, 10163, 23041, 10466, 356

Passed LTC:
https://tests.stockfishchess.org/tests/view/65ca632b1d8e83c78bfcf554
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 170856 W: 42910 L: 42320 D: 85626
Ptnml(0-2): 104, 18337, 47960, 18919, 108

closes https://github.com/official-stockfish/Stockfish/pull/5053

Bench: 1198939
2024-02-14 21:39:31 +01:00
Tierynn Byrnes f4f0b32d55 Refactor timeman.cpp
Move optExtra, optConstant and maxConstant into lower scope.

closes https://github.com/official-stockfish/Stockfish/pull/5052

No functional change
2024-02-14 21:38:17 +01:00
Muzhen Gaming 5c03883107 VVLTC search tune
Search parameters were tuned using 16k games at
VVLTC. They were tuned starting with the new
parameters (in search only) of PR #5039.

Passed VVLTC:
https://tests.stockfishchess.org/tests/view/65c8a8fc1d8e83c78bfcd163
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 20826 W: 5355 L: 5100 D: 10371
Ptnml(0-2): 1, 1941, 6275, 2194, 2

Passed 2nd VVLTC:
https://tests.stockfishchess.org/tests/view/65cadc2d1d8e83c78bfcfdaf
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 17710 W: 4611 L: 4352 D: 8747
Ptnml(0-2): 1, 1586, 5422, 1845, 1

STC Elo estimate:
https://tests.stockfishchess.org/tests/view/65cb6aed1d8e83c78bfd0802
Elo: -1.46 ± 1.8 (95%) LOS: 5.5%
Total: 40000 W: 10267 L: 10435 D: 19298
Ptnml(0-2): 200, 4860, 10023, 4742, 175
nElo: -2.77 ± 3.4 (95%) PairsRatio: 0.97

Bench: 1198939
2024-02-14 21:27:55 +01:00
Disservin 7ccde25baf Format code using clang-format
No functional change
2024-02-11 20:13:19 +01:00
Gahtan Nahdi c115e5171e Remove quiet tt move extensions
Passed STC:
https://tests.stockfishchess.org/tests/view/65c6934cc865510db0286e90
LLR: 2.99 (-2.94,2.94) <-1.75,0.25>
Total: 54016 W: 14065 L: 13854 D: 26097
Ptnml(0-2): 231, 6381, 13581, 6576, 239

Passed LTC:
https://tests.stockfishchess.org/tests/view/65c72b91c865510db0287a1a
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 55098 W: 13850 L: 13658 D: 27590
Ptnml(0-2): 37, 6257, 14777, 6433, 45

closes https://github.com/official-stockfish/Stockfish/pull/5049

Bench: 1027182
2024-02-11 19:58:35 +01:00
mstembera 531747ee78 Improve thread voting inefficiencies
Initialize the unordered map to a reasonable
number of buckets and make the move hashes well
distributed. For more see
https://github.com/official-stockfish/Stockfish/pull/4958#issuecomment-1937351190
Also make bestThreadPV and newThreadPV references
so we don't copy entire vectors.

closes https://github.com/official-stockfish/Stockfish/pull/5048

No functional change
2024-02-11 19:55:26 +01:00
Michael Chaly 91a4cea437 Adjust best value in main search depending on depth
This patch does similar thing to how it's done for
qsearch - in case of fail high adjust result to
lower value. Difference is that it is done only
for non-pv nodes and it's depth dependent - so
lower depth entries will have bigger adjustment
and higher depth entries will have smaller
adjustment.

Passed STC:
https://tests.stockfishchess.org/tests/view/65c3c0cbc865510db0283b21
LLR: 2.96 (-2.94,2.94) <0.00,2.00>
Total: 112032 W: 29142 L: 28705 D: 54185
Ptnml(0-2): 479, 13152, 28326, 13571, 488

Passed LTC:
https://tests.stockfishchess.org/tests/view/65c52e62c865510db02855d5
LLR: 2.96 (-2.94,2.94) <0.50,2.50>
Total: 132480 W: 33457 L: 32936 D: 66087
Ptnml(0-2): 67, 14697, 36222, 15156, 98

closes https://github.com/official-stockfish/Stockfish/pull/5047

Bench: 1168241
2024-02-11 19:53:45 +01:00
Disservin 9068fdc57b Assorted cleanups
Assorted cleanups

closes https://github.com/official-stockfish/Stockfish/pull/5046

No functional change

Co-Authored-By: Shahin M. Shahin <41402573+peregrineshahin@users.noreply.github.com>
Co-Authored-By: cj5716 <125858804+cj5716@users.noreply.github.com>
2024-02-11 19:52:00 +01:00
GoldenRare 3d5b16df7c Remove unnecessary assignments related to adjusted static evaluation
In both search and qsearch, there are instances
where we do unadjustedStaticEval = ss->staticEval
= eval/bestValue = tte->eval(), but immediately
after re-assign ss-static and eval/bestValue to
some new value, which makes the initial assignment
redundant.

closes https://github.com/official-stockfish/Stockfish/pull/5045

No functional change
2024-02-11 19:46:55 +01:00
Disservin 21dff6c276 Update CI actions
- Update codeql to v3
- Switch from dev-drprasad to native github cli
- Update softprops/action-gh-release to node 20 commit

`thollander/actions-comment-pull-request` needs to
be bumped to node20 too, but the author hasnt done
so atm

closes https://github.com/official-stockfish/Stockfish/pull/5044

No functional change
2024-02-11 19:40:33 +01:00
mstembera 9699f4f79a Fix the alignment of the transformer buffer
Fixes the issue mentioned in
https://github.com/official-stockfish/Stockfish/commit/584d9efedcde330eeb96a99215552ddfb06f52ba#r138417600.
Thanks to @cj5716 and @peregrineshahin for
spotting this!

closes https://github.com/official-stockfish/Stockfish/pull/5042

No functional change
2024-02-09 19:06:25 +01:00
Muzhen Gaming 96837bc439 Remove check extension
Passed simplification STC:
https://tests.stockfishchess.org/tests/view/65c38d2ac865510db02836cf
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 52288 W: 13578 L: 13371 D: 25339
Ptnml(0-2): 197, 6171, 13265, 6250, 261

Passed simplification LTC:
https://tests.stockfishchess.org/tests/view/65c4470ec865510db0284473
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 44958 W: 11255 L: 11055 D: 22648
Ptnml(0-2): 37, 4962, 12274, 5176, 30

closes https://github.com/official-stockfish/Stockfish/pull/5041

Bench: 1116591
2024-02-09 19:06:25 +01:00
gahtan-syarif 15093d43c4 Simplify opponent movecount reduction
This removes the reduction decrease that occured
when the previous ply had a movecount greater than
7.

Passed STC:
https://tests.stockfishchess.org/tests/view/65c3f6dac865510db0283ef6
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 11968 W: 3205 L: 2953 D: 5810
Ptnml(0-2): 38, 1310, 3064, 1506, 66

Passed LTC:
https://tests.stockfishchess.org/tests/view/65c42377c865510db0284217
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 35676 W: 9113 L: 8905 D: 17658
Ptnml(0-2): 22, 3893, 9802, 4097, 24

closes https://github.com/official-stockfish/Stockfish/pull/5040

Bench: 1148379
2024-02-09 19:06:25 +01:00
cj5716 c0107b3c27 Remove simple eval
With the recent introduction of the dual NNUE, the
need for simple eval is no longer there.

Passed STC:
https://tests.stockfishchess.org/tests/view/65c1f735c865510db0281652
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 85312 W: 22009 L: 21837 D: 41466
Ptnml(0-2): 334, 10155, 21567, 10205, 395

Passed LTC:
https://tests.stockfishchess.org/tests/view/65c2d64bc865510db0282810
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 49956 W: 12596 L: 12402 D: 24958
Ptnml(0-2): 28, 5553, 13624, 5743, 30

closes https://github.com/official-stockfish/Stockfish/pull/5037

Bench 1213676
2024-02-09 19:06:25 +01:00
Stefan Geschwentner f2984471c9 Tweak capture scoring for move ordering
Move divisor from capture scoring to good capture
check and sligthly increase it.

This has several effects:
- its a speedup because for quience and probcut
  search the division now never happens. For main
  search its delayed and can be avoided if a good
  capture triggers a cutoff
- through the higher resolution of scores we have
  a more granular sorting

STC: https://tests.stockfishchess.org/tests/view/65bf2a93c865510db027dc27
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 470016 W: 122150 L: 121173 D: 226693
Ptnml(0-2): 2133, 55705, 118374, 56644, 2152

LTC: https://tests.stockfishchess.org/tests/view/65c1d16dc865510db0281339
LLR: 2.96 (-2.94,2.94) <0.50,2.50>
Total: 98988 W: 25121 L: 24667 D: 49200
Ptnml(0-2): 77, 10998, 26884, 11464, 71

closes https://github.com/official-stockfish/Stockfish/pull/5036

Bench: 1233867
2024-02-09 19:06:25 +01:00
Disservin a20726eb0b Refactor the CI workflows
This refactors the CI workflows to group some
logic and makes sure that all (pre)release
binaries are actually tested.

The screenshot below shows the execution logic of
the reworked ci,
https://github.com/Disservin/Stockfish/actions/runs/7773581379.
You can also hover over the cards to see the
execution flow.

The `matrix.json` and `arm_matrix.json` define the
binaries which will be uploaded to GitHub.
Afterwards a matrix is created and each job
compiles a profile guided build for that arch and
uploads that as an artifact to GitHub. The
Binaries/ARM_Binaries workflow's are called when
the previous step has been completed, and uploads
all artifacts to the (pre)release.

This also fixes some indentations and renames the
workflows, see
https://github.com/official-stockfish/Stockfish/actions,
where every workflow is called `Stockfish` vs
https://github.com/Disservin/Stockfish/actions. It
also increases the parallel compilation used for
make from `-j2 to -j4`.

It now also prevents the prerelease action from
running on forks.

A test release can be viewed here
https://github.com/Disservin/Stockfish/releases.

closes https://github.com/official-stockfish/Stockfish/pull/5035

No functional change
2024-02-09 19:06:25 +01:00
FauziAkram 59691d46a1 Assorted trivial cleanups
Renaming doubleExtensions variable to multiExtensions, since now we have also triple extensions.

Some extra cleanups.

Recent tests used to measure the elo worth:
https://tests.stockfishchess.org/tests/view/659fd0c379aa8af82b96abc3
https://tests.stockfishchess.org/tests/view/65a8f3da79aa8af82b9751e3
https://tests.stockfishchess.org/tests/view/65b51824c865510db0272740
https://tests.stockfishchess.org/tests/view/65b58fbfc865510db0272f5b

closes https://github.com/official-stockfish/Stockfish/pull/5032

No functional change
2024-02-09 19:06:24 +01:00
Muzhen Gaming ededadcd6f VVLTC search tune
Search parameters were tuned at 60+0.6 8-thread.
Link to the tuning attempt: https://tests.stockfishchess.org/tests/view/65b84e8dc865510db0276030

The most significant change is the triple extension parameter, from 200 to 78. This presumably improves scaling.
Additionally, the value < singularBeta - 2 condition for double extensions was removed.
This can simply be considered a parameter tweak from 2 to 0.

Passed VVLTC: https://tests.stockfishchess.org/tests/view/65baec69c865510db0278f19
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 26136 W: 6564 L: 6305 D: 13267
Ptnml(0-2): 2, 2413, 7977, 2676, 0

Passed VVLTC vs passed PR #5027: https://tests.stockfishchess.org/tests/view/65bc2adfc865510db027a561
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 52968 W: 13372 L: 13046 D: 26550
Ptnml(0-2): 4, 4944, 16265, 5264, 7

STC Elo estimate: https://tests.stockfishchess.org/tests/view/65be5514c865510db027cbc5

closes https://github.com/official-stockfish/Stockfish/pull/5029

Bench: 1478189
2024-02-03 17:40:07 +01:00
gab8192 e815227c30 Simplify LMR condition
Apply LMR on captures the same way it is applied on quiets

Passed Non-Reg STC:
https://tests.stockfishchess.org/tests/view/65bbf39bc865510db027a14a
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 77152 W: 19970 L: 19791 D: 37391
Ptnml(0-2): 304, 9159, 19496, 9288, 329

Passed Non-Reg LTC:
https://tests.stockfishchess.org/tests/view/65bc8889c865510db027ac9e
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 103230 W: 25997 L: 25858 D: 51375
Ptnml(0-2): 71, 11687, 27958, 11830, 69

Hit rate of removed condition (!ss->ttPv || !capture || (cutNode && (ss - 1)->moveCount > 1))
Total 1253801 Hits 1228904 Hit Rate (%) 98.0143

Hit rate of previous LMR (depth >= 2 && moveCount > 1 + rootNode && ...)
Total 1253801 Hits 727234 Hit Rate (%) 58.0023

Hit rate of simplified LMR (depth >= 2 && moveCount > 1 + rootNode)
Total 1201839 Hits 713540 Hit Rate (%) 59.3707

closes https://github.com/official-stockfish/Stockfish/pull/5028

Bench: 1438224
2024-02-03 17:30:41 +01:00
Viren6 f2b6b5cfc9 Introduce Triple Extensions
This replaces singularquietLMR with triple instead of double extending non-capture ttmoves that have value far below singularBeta. This threshold value is initially set to 200, there is scope for more scaling by reducing it as occured with double extensions.

Passed STC:
https://tests.stockfishchess.org/tests/view/65b683b8c865510db0274074
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 222912 W: 58141 L: 57535 D: 107236
Ptnml(0-2): 1063, 26244, 56154, 27014, 981

Passed LTC:
https://tests.stockfishchess.org/tests/view/65bae6d4c865510db0278eb5
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 66306 W: 16825 L: 16440 D: 33041
Ptnml(0-2): 40, 7374, 17952, 7735, 52

closes https://github.com/official-stockfish/Stockfish/pull/5027

bench 1394701
2024-02-03 17:26:42 +01:00
FauziAkram 56b342f9b2 Simplify the extension formula
Simplify the extension formula in the case of cutNode by removing the depth condition and always setting extension to -2.

Passed STC:
LLR: 2.97 (-2.94,2.94) <-1.75,0.25>
Total: 277280 W: 70760 L: 70802 D: 135718
Ptnml(0-2): 971, 31775, 73153, 31807, 934
https://tests.stockfishchess.org/tests/view/65ad08f779aa8af82b979dd6

Passed LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 452976 W: 112992 L: 113215 D: 226769
Ptnml(0-2): 266, 51041, 124112, 50788, 281
https://tests.stockfishchess.org/tests/view/65ae466fc865510db026a760

closes https://github.com/official-stockfish/Stockfish/pull/5021

Bench: 1492957
2024-02-03 17:09:05 +01:00
Disservin 3cce4c4cf4 Add Apple Silicon Runners to CI
GitHub CI runners are available for macOS 14, these runners are using apple silicon chips (M1).
https://github.blog/changelog/2024-01-30-github-actions-introducing-the-new-m1-macos-runner-available-to-open-source/

closes https://github.com/official-stockfish/Stockfish/pull/5025

No functional change
2024-02-03 16:55:10 +01:00
Disservin 16afec0582 Refactor pv printing
Also fix the case which is currently printing depth 0.

fixes #5019
closes https://github.com/official-stockfish/Stockfish/pull/5020

No functional change
2024-02-03 16:50:31 +01:00
Disservin 13eb023fc0 Simplify array initializations
also retire a few std::memset calls.

Passed non-regresion STC:
https://tests.stockfishchess.org/tests/view/65b8e162c865510db0276901
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 97504 W: 25294 L: 25140 D: 47070
Ptnml(1-2): 378, 11102, 25667, 11198, 407

closes https://github.com/official-stockfish/Stockfish/pull/5018

No functional change
2024-02-03 16:43:23 +01:00
Viren6 fcbb02ffde Use ttPv in depth condition of singular extensions
This replaces the PvNode condition and tte Pv call previously with using
the precomputed ttPv, and also removes the multiplier of 2.  This new
depth condition occurs with approximately equal frequency (47%) to the
old depth condition (measured when the other conditions in the if are
true), so non-linear scaling behaviour isn't expected.

Passed Non-Reg STC:
https://tests.stockfishchess.org/tests/view/65b0e132c865510db026da27
LLR: 2.97 (-2.94,2.94) <-1.75,0.25>
Total: 243232 W: 62432 L: 62437 D: 118363
Ptnml(0-2): 910, 28937, 61900, 28986, 883

Passed Non-Reg LTC:
https://tests.stockfishchess.org/tests/view/65b2053bc865510db026eea1
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 190596 W: 47666 L: 47618 D: 95312
Ptnml(0-2): 115, 21710, 51596, 21766, 111

closes https://github.com/official-stockfish/Stockfish/pull/5015

Bench: 1492957
2024-01-26 21:15:07 +01:00
Ahmed Kerimov c17ec9524d Move OnChange callback in Option ctors
Parameter 'f' is passed by value and only copied once. Moving it to
avoid unnecessary copies.

closes https://github.com/official-stockfish/Stockfish/pull/5014

No functional change
2024-01-26 21:00:41 +01:00
Michael Chaly 37bd1e774e Do more double extensions
Parameter tweak from Black Marlin chess engine. Choose a significantly
lower value that triggers in 95% of cases, compared to the usual 84% in
standard benchmark runs.

Since the introduction by
https://github.com/official-stockfish/Stockfish/commit/33a858eaa1f792b3413384a3d0993dba36aca92e
this constant has only decreased in value over time.
2-16-17-18-21-22-25-26-52-71-75-93-140

Failed STC really fast:
https://tests.stockfishchess.org/tests/view/65b11d05c865510db026df7b
LLR: -2.94 (-2.94,2.94) <0.00,2.00>
Total: 13216 W: 3242 L: 3485 D: 6489
Ptnml(0-2): 50, 1682, 3371, 1471, 34

Was reasonable at LTC:

https://tests.stockfishchess.org/tests/view/65b13e20c865510db026e210
Elo: 1.18 ± 1.5 (95%) LOS: 94.3%
Total: 50000 W: 12517 L: 12347 D: 25136
Ptnml(0-2): 31, 5598, 13579, 5754, 38
nElo: 2.45 ± 3.0 (95%) PairsRatio: 1.03

Passed VLTC with STC bounds:
https://tests.stockfishchess.org/tests/view/65b18870c865510db026e769
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 30456 W: 7726 L: 7448 D: 15282
Ptnml(0-2): 6, 3111, 8717, 3387, 7

Passed VVLTC with LTC bounds:
https://tests.stockfishchess.org/tests/view/65b20b95c865510db026eef0
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 36134 W: 9158 L: 8859 D: 18117
Ptnml(0-2): 3, 3455, 10850, 3758, 1

closes https://github.com/official-stockfish/Stockfish/pull/5013

Bench: 1503692
2024-01-26 20:55:16 +01:00
Disservin 1dfbde2d10 Move perft out of search
This splits the logic of search and perft. Before, threads were started,
which then constructed a search object, which then started perft and
returned immediately. All of this is unnecessary, instead uci should
start perft right away.

closes https://github.com/official-stockfish/Stockfish/pull/5008

No functional change
2024-01-26 20:52:26 +01:00
FauziAkram 3d49a99aaf Refactor history score calculation
Passed STC:
https://tests.stockfishchess.org/tests/view/65ad08b179aa8af82b979dd1
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 161376 W: 41582 L: 41498 D: 78296
Ptnml(0-2): 633, 19354, 40611, 19476, 614

Passed LTC:
https://tests.stockfishchess.org/tests/view/65af966fc865510db026c0f0
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 116526 W: 29269 L: 29143 D: 58114
Ptnml(0-2): 71, 13252, 31509, 13342, 89

closes https://github.com/official-stockfish/Stockfish/pull/5006

Bench: 1317504
2024-01-26 20:44:16 +01:00
FauziAkram 2b62c4452d Remove redundant max operation on lmrDepth
Removed a restriction that prohibited history heuristics sum in futility
pruning to exceed some negative value.

Passed STC:
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 279040 W: 71095 L: 71143 D: 136802
Ptnml(0-2): 949, 33574, 70474, 33622, 901
https://tests.stockfishchess.org/tests/view/65aaef4c79aa8af82b977631

Passed LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 75156 W: 18884 L: 18715 D: 37557
Ptnml(0-2): 52, 8445, 20408, 8628, 45
https://tests.stockfishchess.org/tests/view/65ae7ef3c865510db026abf5

closes https://github.com/official-stockfish/Stockfish/pull/5004

Bench: 1566543
2024-01-26 20:40:22 +01:00
Muzhen Gaming a6fd17f27d VLTC search tune
Search parameters were tuned using 152k games at 180+1.8.

Passed VLTC:
https://tests.stockfishchess.org/tests/view/65a7a81979aa8af82b973a20
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 117338 W: 29244 L: 28848 D: 59246
Ptnml(0-2): 24, 12474, 33267, 12890, 14

Passed VVLTC:
https://tests.stockfishchess.org/tests/view/65ab246679aa8af82b977982
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 28164 W: 7239 L: 6957 D: 13968
Ptnml(0-2): 3, 2651, 8490, 2937, 1

STC Elo estimate:
https://tests.stockfishchess.org/tests/view/65ac7c0979aa8af82b9792a6
Elo: -0.53 ± 2.0 (95%) LOS: 30.4%
Total: 30000 W: 7688 L: 7734 D: 14578
Ptnml(0-2): 102, 3617, 7614, 3559, 108
nElo: -1.03 ± 3.9 (95%) PairsRatio: 0.99

closes https://github.com/official-stockfish/Stockfish/pull/5003

Bench: 1235377
2024-01-21 12:49:30 +01:00
Robert Nurnberg @ elitebook a901474bf9 Update the WDL model
Update the internal WDL model. After the dual net merge, the internal
evaluations have drifted upwards a bit. With this PR
`NormalizeToPawnValue` changes from `328` to `345`.

The new model was fitted based on about 200M positions extracted from
3.4M fishtest LTC games from the last two weeks, involving SF versions
from 6deb88728f to current master.

Apart from the WDL model parameter update, this PR implements the
following changes:

WDL Model:
- an incorrect 8-move shift in master's WDL model has been fixed
- the polynomials `p_a` and `p_b` are fitted over the move range [8, 120]
- the coefficients for `p_a` and `p_b` are optimized by maximizing the
  probability of predicting the observed outcome (credits to @vondele)

SF code:
- for wdl values, move will be clamped to `max(8, min(120, move))`
- no longer clamp the internal eval to [-4000,4000]
- compute `NormalizeToPawnValue` with `round`, not `trunc`

The PR only affects displayed `cp` and `wdl` values.

closes https://github.com/official-stockfish/Stockfish/pull/5002

No functional change
2024-01-21 12:45:03 +01:00
Shahin M. Shahin ad9fcbc496 Refactor get_best_thread
Make get_best_thread function easier to understand.

Passed non-reg SMP STC:
https://tests.stockfishchess.org/tests/view/65a91c6679aa8af82b975500
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 186000 W: 46379 L: 46325 D: 93296
Ptnml(0-2): 269, 21374, 49634, 21480, 243

closes https://github.com/official-stockfish/Stockfish/pull/5001

No functional change
2024-01-21 12:42:28 +01:00
rn5f107s2 e860f620aa Reduce futility_margin further when improving
The idea of this is to unroll the futility_margin calculation to allow
for the improving flag to have a greater effect on the futility margin.
The current factor is 1.5 instead of the previous 1 resulting in a
deduction of an extra margin/2 from futilit_margin if improving. The
chosen value was not tuned, meaning that there is room for tweaking it.
This patch is partially inspired by @Vizvezdenec, who, although quite
different in execution, tested another idea where the futility_margin is
lowered further when improving [1].

[1]: (first take) https://tests.stockfishchess.org/tests/view/65a56b1879aa8af82b97164b

Passed STC:
https://tests.stockfishchess.org/tests/live_elo/65a8bfc179aa8af82b974e3c
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 161152 W: 41321 L: 40816 D: 79015
Ptnml(0-2): 559, 19030, 40921, 19479, 587

Passed rebased LTC:
https://tests.stockfishchess.org/tests/live_elo/65a8b9ef79aa8af82b974dc0
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 96024 W: 24172 L: 23728 D: 48124
Ptnml(0-2): 56, 10598, 26275, 11012, 71

closes https://github.com/official-stockfish/Stockfish/pull/5000

Bench: 1281703
2024-01-21 12:42:07 +01:00
Viren6 aa15a9179b Refactor ttPv reduction conditions
closes https://github.com/official-stockfish/Stockfish/pull/4999

No functional change
2024-01-21 12:33:08 +01:00
Disservin 856e60d12f Refactor NativeThread start_routine
Removes the free function and fixes the formatting for the function
call.

closes https://github.com/official-stockfish/Stockfish/pull/4995

No functional change
2024-01-21 12:21:01 +01:00
Viren6 c8bc2ce4fa Improve ttPv reduction
This patch allows a partial reduction decrease when a node is likely to
fail low, and increases the reduction decrease when a node has failed
high.

Passed STC:
https://tests.stockfishchess.org/tests/view/65a626e779aa8af82b9722bc
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 157824 W: 40332 L: 39835 D: 77657
Ptnml(0-2): 543, 18617, 40098, 19108, 546

Passed LTC:
https://tests.stockfishchess.org/tests/view/65a7290279aa8af82b97328a
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 57228 W: 14475 L: 14111 D: 28642
Ptnml(0-2): 34, 6278, 15633, 6628, 41

closes https://github.com/official-stockfish/Stockfish/pull/4994

Bench: 1364759
2024-01-17 18:56:37 +01:00
FauziAkram 9a9702d668 Remove threatenedByPawn from rook threat
Can be simplified away.

Passed STC:
https://tests.stockfishchess.org/tests/view/65a3fa4179aa8af82b96face
LLR: 2.92 (-2.94,2.94) <-1.75,0.25>
Total: 30592 W: 7903 L: 7674 D: 15015
Ptnml(0-2): 96, 3590, 7711, 3787, 112

Passed LTC:
https://tests.stockfishchess.org/tests/view/65a42b9a79aa8af82b96fe88
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 73656 W: 18382 L: 18212 D: 37062
Ptnml(0-2): 47, 8287, 19981, 8475, 38

closes https://github.com/official-stockfish/Stockfish/pull/4993

Bench: 1430061
2024-01-17 18:55:44 +01:00
pb00067 0fbad56c50 Refactor code for correcting unadjustedStaticEval
Passed non-regression STC:
https://tests.stockfishchess.org/tests/live_elo/65a4df6a79aa8af82b970ca0
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 43328 W: 11103 L: 10892 D: 21333
Ptnml(0-2): 120, 4920, 11407, 5063, 154

https://github.com/official-stockfish/Stockfish/pull/4992

No functional change
2024-01-17 18:51:03 +01:00
Torsten Hellwig 6c02329860 Fix dotprod detection
This fixes the detection of dotprod capable CPUs. Previously it looked
for the `dotprod` flag, but this does not exist
(https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/arch/arm64/kernel/cpuinfo.c#n50).
The correct flag that specifies the dotprod capability is the `asimddp`
flag.

fixes #4931

closes https://github.com/official-stockfish/Stockfish/pull/4991

No functional change
2024-01-17 18:32:20 +01:00
Shahin M. Shahin 0c7f56dea6 Fix mated-in behaviour
This addresses the issue where Stockfish may output non-proven checkmate
scores if the search is prematurely halted, either due to a time control
or node limit, before it explores other possibilities where the
checkmate score could have been delayed or refuted.

The fix also replaces staving off from proven mated scores in a
multithread environment making use of the threads instead of a negative
effect with multithreads (1t was better in proving mated in scores than
more threads).

Issue reported on mate tracker repo by and this PR is co-authored with
@robertnurnberg Special thanks to @AndyGrant for outlining that a fix is
eventually possible.

Passed Adj off SMP STC:
https://tests.stockfishchess.org/tests/view/65a125d779aa8af82b96c3eb
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 303256 W: 75823 L: 75892 D: 151541
Ptnml(0-2): 406, 35269, 80395, 35104, 454

Passed Adj off SMP LTC:
https://tests.stockfishchess.org/tests/view/65a37add79aa8af82b96f0f7
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 56056 W: 13951 L: 13770 D: 28335
Ptnml(0-2): 11, 5910, 16002, 6097, 8

Passed all tests in matetrack without any better mate for opponent found in 1t and multithreads.

Fixed bugs in https://github.com/official-stockfish/Stockfish/pull/4976

closes https://github.com/official-stockfish/Stockfish/pull/4990

Bench: 1308279

Co-Authored-By: Robert Nürnberg <28635489+robertnurnberg@users.noreply.github.com>
2024-01-17 18:12:16 +01:00
Disservin f15e4f50aa Update installation guide links in CONTRIBUTING.md
Link to more user friendly installation guides, these are shorter and
easier to follow.

closes https://github.com/official-stockfish/Stockfish/pull/4985

No functional change
2024-01-17 18:06:20 +01:00
Disservin a5675f19d8 Remove global TB variables from search.cpp
Follow up cleanup of #4968, removes the global variables from search and
instead uses a dedicated tb config struct.

closes https://github.com/official-stockfish/Stockfish/pull/4982

No functional change
2024-01-17 18:05:00 +01:00
mstembera 32e46fc47f Remove some outdated SIMD functions
Since https://github.com/official-stockfish/Stockfish/pull/4391 the x2
SIMD functions no longer serve any useful purpose.

Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/659cf42579aa8af82b966d55
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 67392 W: 17222 L: 17037 D: 33133
Ptnml(0-2): 207, 7668, 17762, 7851, 208

closes https://github.com/official-stockfish/Stockfish/pull/4974

No functional change
2024-01-17 18:04:29 +01:00
Disservin b5e8169a85 Add ignoreRevsFile to CONTRIBUTING.md
closes https://github.com/official-stockfish/Stockfish/pull/4980

No functional change
2024-01-14 10:46:13 +01:00
Disservin 88331add0d Remove the dependency on a Worker from evaluate
Also remove dead code, `rootSimpleEval` is no longer used since the introduction of dual net.
`iterBestValue` is also no longer used in evaluate and can be reduced to a local variable.

closes https://github.com/official-stockfish/Stockfish/pull/4979

No functional change
2024-01-14 10:46:13 +01:00
Disservin 12e97701b2 Fix UCI options
Fixes the type for 'Clear Hash' and uses MAX_MOVES for 'MultiPV' as we
had before.

No functional change
2024-01-14 10:46:13 +01:00
Disservin cf5b070913 Remove unused method
init() is no longer used, and was previously replaced by the clear
function.

fixes https://github.com/official-stockfish/Stockfish/issues/4981

No functional change
2024-01-14 00:30:06 +01:00
mstembera eec361f64c Simplify bad quiets
The main difference is that instead of returning the first bad quiet as
a good one we fall through. This is actually more correct and simpler
to implement.

Non regression STC:
https://tests.stockfishchess.org/tests/view/659bbb3479aa8af82b964ec7
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 150944 W: 38399 L: 38305 D: 74240
Ptnml(0-2): 485, 18042, 38298, 18188, 459

Non regression LTC:
https://tests.stockfishchess.org/tests/view/659c6e6279aa8af82b9660eb
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 192060 W: 47871 L: 47823 D: 96366
Ptnml(0-2): 144, 21912, 51845, 22010, 119

The cutoff is now -8K instead of -7.5K.
-7.5K failed. https://tests.stockfishchess.org/tests/view/659a1f4b79aa8af82b962a0e
This was likely a false negative.

closes https://github.com/official-stockfish/Stockfish/pull/4975

Bench: 1308279
2024-01-13 19:40:53 +01:00
FauziAkram 3372ee9c26 Remove threatenedByPawn term for queen threats
Passed STC:
https://tests.stockfishchess.org/tests/view/659d614c79aa8af82b9677d0
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 151776 W: 38690 L: 38597 D: 74489
Ptnml(0-2): 522, 17841, 39015, 18042, 468

Passed LTC:
https://tests.stockfishchess.org/tests/view/659d94d379aa8af82b967cb2
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 91908 W: 23075 L: 22924 D: 45909
Ptnml(0-2): 70, 10311, 25037, 10470, 66

closes https://github.com/official-stockfish/Stockfish/pull/4977

Bench: 1266493
2024-01-13 19:40:53 +01:00
Disservin a107910951 Refactor global variables
This aims to remove some of the annoying global structure which Stockfish has.

Overall there is no major elo regression to be expected.

Non regression SMP STC (paused, early version):
https://tests.stockfishchess.org/tests/view/65983d7979aa8af82b9608f1
LLR: 0.23 (-2.94,2.94) <-1.75,0.25>
Total: 76232 W: 19035 L: 19096 D: 38101
Ptnml(0-2): 92, 8735, 20515, 8690, 84

Non regression STC (early version):
https://tests.stockfishchess.org/tests/view/6595b3a479aa8af82b95da7f
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 185344 W: 47027 L: 46972 D: 91345
Ptnml(0-2): 571, 21285, 48943, 21264, 609

Non regression SMP STC:
https://tests.stockfishchess.org/tests/view/65a0715c79aa8af82b96b7e4
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 142936 W: 35761 L: 35662 D: 71513
Ptnml(0-2): 209, 16400, 38135, 16531, 193

These global structures/variables add hidden dependencies and allow data
to be mutable from where it shouldn't it be (i.e. options). They also
prevent Stockfish from internal selfplay, which would be a nice thing to
be able to do, i.e. instantiate two Stockfish instances and let them
play against each other. It will also allow us to make Stockfish a
library, which can be easier used on other platforms.

For consistency with the old search code, `thisThread` has been kept,
even though it is not strictly necessary anymore. This the first major
refactor of this kind (in recent time), and future changes are required,
to achieve the previously described goals. This includes cleaning up the
dependencies, transforming the network to be self contained and coming
up with a plan to deal with proper tablebase memory management (see
comments for more information on this).

The removal of these global structures has been discussed in parts with
Vondele and Sopel.

closes https://github.com/official-stockfish/Stockfish/pull/4968

No functional change
2024-01-13 19:40:53 +01:00
Linmiao Xu 6deb88728f Update default main net to nn-baff1edbea57.nnue
Created by retraining the previous main net nn-b1e55edbea57.nnue with:
- some of the same options as before: ranger21 optimizer, more WDL
  skipping
- adding T80 aug filter-v6, sep, and oct 2023 data to the previous best
  dataset
- increasing training loss for positions where predicted win rates were
  higher than estimated match results from training data position scores

```yaml
experiment-name: 2560--S8-r21-more-wdl-skip-10p-more-loss-high-q-sk28

training-dataset:
  # https://github.com/official-stockfish/Stockfish/pull/4782
  - /data/S6-1ee1aba5ed.binpack
  - /data/test80-aug2023-2tb7p.v6.min.binpack
  - /data/test80-sep2023-2tb7p.binpack
  - /data/test80-oct2023-2tb7p.binpack
early-fen-skipping: 28

start-from-engine-test-net: True
nnue-pytorch-branch: linrock/nnue-pytorch/r21-more-wdl-skip-10p-more-loss-high-q

num-epochs: 1000
lr: 4.375e-4
gamma: 0.995
start-lambda: 1.0
end-lambda: 0.7
```

Training data can be found at:
https://robotmoon.com/nnue-training-data/

Training loss was increased by 10% for positions where predicted win
rates were higher than suggested by the win rate model based on the
training data, by multiplying with: ((qf > pt) * 0.1 + 1). This was a
variant of experiments from Sopel's NNUE training & experimentation log:
https://docs.google.com/document/d/1gTlrr02qSNKiXNZ_SuO4-RjK4MXBiFlLE6jvNqqMkAY
Experiment 302 - increase loss when prediction too high, vondele’s idea
Experiment 309 - increase loss when prediction too high, normalize in a
batch

Passed STC:
https://tests.stockfishchess.org/tests/view/6597a21c79aa8af82b95fd5c
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 148320 W: 37960 L: 37475 D: 72885
Ptnml(0-2): 542, 17565, 37383, 18206, 464

Passed LTC:
https://tests.stockfishchess.org/tests/view/659834a679aa8af82b960845
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 55188 W: 13955 L: 13592 D: 27641
Ptnml(0-2): 34, 6162, 14834, 6535, 29

closes https://github.com/official-stockfish/Stockfish/pull/4972

Bench: 1219824
2024-01-08 18:34:36 +01:00
Disservin 99cdb920fc Cleanup Evalfile handling
This cleans up the EvalFile handling after the merge of #4915,
which has become a bit confusing on what it is actually doing.

closes https://github.com/official-stockfish/Stockfish/pull/4971

No functional change
2024-01-08 18:33:38 +01:00
Disservin 7c5e3f2865 Prefix abs with std:: 2024-01-07 21:41:52 +01:00
Linmiao Xu f09adaa4a4 Update smallnet to nn-baff1ede1f90.nnue with wider eval range
Created by training an L1-128 net from scratch with a wider range of
evals in the training data and wld-fen-skipping disabled during
training. The differences in this training data compared to the first
dual nnue PR are:

- removal of all positions with 3 pieces
- when piece count >= 16, keep positions with simple eval above 750
- when piece count < 16, remove positions with simple eval above 3000

The asymmetric data filtering was meant to flatten the training data
piece count distribution, which was previously heavily skewed towards
positions with low piece counts.

Additionally, the simple eval range where the smallnet is used was
widened to cover more positions previously evaluated by the big net and
simple eval.

```yaml
experiment-name: 128--S1-hse-S7-v4-S3-v1-no-wld-skip

training-dataset:
  - /data/hse/S3/leela96-filt-v2.min.high-simple-eval-1k.binpack
  - /data/hse/S3/dfrc99-16tb7p-eval-filt-v2.min.high-simple-eval-1k.binpack
  - /data/hse/S3/test80-apr2022-16tb7p.min.high-simple-eval-1k.binpack

  - /data/hse/S7/test60-2020-2tb7p.v6-3072.high-simple-eval-v4.binpack
  - /data/hse/S7/test60-novdec2021-12tb7p-filter-v6-dd.min-mar2023.unmin.high-simple-eval-v4.binpack

  - /data/hse/S7/test77-nov2021-2tb7p.v6-3072.min.high-simple-eval-v4.binpack
  - /data/hse/S7/test77-dec2021-16tb7p-filter-v6-dd.min-mar2023.unmin.high-simple-eval-v4.binpack
  - /data/hse/S7/test77-jan2022-2tb7p.high-simple-eval-v4.binpack

  - /data/hse/S7/test78-jantomay2022-16tb7p-filter-v6-dd.min-mar2023.unmin.high-simple-eval-v4.binpack
  - /data/hse/S7/test78-juntosep2022-16tb7p-filter-v6-dd.min-mar2023.unmin.high-simple-eval-v4.binpack

  - /data/hse/S7/test79-apr2022-16tb7p-filter-v6-dd.min-mar2023.unmin.high-simple-eval-v4.binpack
  - /data/hse/S7/test79-may2022-16tb7p-filter-v6-dd.min-mar2023.unmin.high-simple-eval-v4.binpack

  - /data/hse/S7/test80-may2022-16tb7p.high-simple-eval-v4.binpack
  - /data/hse/S7/test80-jun2022-16tb7p-filter-v6-dd.min-mar2023.unmin.high-simple-eval-v4.binpack
  - /data/hse/S7/test80-jul2022-16tb7p.v6-dd.min.high-simple-eval-v4.binpack
  - /data/hse/S7/test80-aug2022-16tb7p-filter-v6-dd.min-mar2023.unmin.high-simple-eval-v4.binpack
  - /data/hse/S7/test80-sep2022-16tb7p-filter-v6-dd.min-mar2023.unmin.high-simple-eval-v4.binpack
  - /data/hse/S7/test80-oct2022-16tb7p.v6-dd.high-simple-eval-v4.binpack
  - /data/hse/S7/test80-nov2022-16tb7p-v6-dd.min.high-simple-eval-v4.binpack

  - /data/hse/S7/test80-jan2023-3of3-16tb7p-filter-v6-dd.min-mar2023.unmin.high-simple-eval-v4.binpack
  - /data/hse/S7/test80-feb2023-16tb7p-filter-v6-dd.min-mar2023.unmin.high-simple-eval-v4.binpack
  - /data/hse/S7/test80-mar2023-2tb7p.v6-sk16.min.high-simple-eval-v4.binpack
  - /data/hse/S7/test80-apr2023-2tb7p-filter-v6-sk16.min.high-simple-eval-v4.binpack
  - /data/hse/S7/test80-may2023-2tb7p.v6.min.high-simple-eval-v4.binpack
  - /data/hse/S7/test80-jun2023-2tb7p.v6-3072.min.high-simple-eval-v4.binpack
  - /data/hse/S7/test80-jul2023-2tb7p.v6-3072.min.high-simple-eval-v4.binpack
  - /data/hse/S7/test80-aug2023-2tb7p.v6.min.high-simple-eval-v4.binpack
  - /data/hse/S7/test80-sep2023-2tb7p.high-simple-eval-v4.binpack
  - /data/hse/S7/test80-oct2023-2tb7p.high-simple-eval-v4.binpack

wld-fen-skipping: False
start-from-engine-test-net: False

nnue-pytorch-branch: linrock/nnue-pytorch/L1-128
engine-test-branch: linrock/Stockfish/L1-128-nolazy
engine-base-branch: linrock/Stockfish/L1-128

num-epochs: 500
start-lambda: 1.0
end-lambda: 1.0
```

Experiment yaml configs converted to easy_train.sh commands with:
https://github.com/linrock/nnue-tools/blob/4339954/yaml_easy_train.py

Binpacks interleaved at training time with:
https://github.com/official-stockfish/nnue-pytorch/pull/259

FT weights permuted with 10k positions from fishpack32.binpack with:
https://github.com/official-stockfish/nnue-pytorch/pull/254

Data filtered for high simple eval positions (v4) with:
https://github.com/linrock/Stockfish/blob/b9c8440/src/tools/transform.cpp#L640-L675

Training data can be found at:
https://robotmoon.com/nnue-training-data/

Local elo at 25k nodes per move of
L1-128 smallnet (nnue-only eval) vs. L1-128 trained on standard S1 data:
nn-epoch319.nnue : -241.7 +/- 3.2

Passed STC vs. 36db936:
https://tests.stockfishchess.org/tests/view/6576b3484d789acf40aabbfe
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 21920 W: 5680 L: 5381 D: 10859
Ptnml(0-2): 82, 2488, 5520, 2789, 81

Passed LTC vs. DualNNUE #4915:
https://tests.stockfishchess.org/tests/view/65775c034d789acf40aac7e3
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 147606 W: 36619 L: 36063 D: 74924
Ptnml(0-2): 98, 16591, 39891, 17103, 120

closes https://github.com/official-stockfish/Stockfish/pull/4919

Bench: 1438336
2024-01-07 21:20:15 +01:00
Linmiao Xu 584d9efedc Dual NNUE with L1-128 smallnet
Credit goes to @mstembera for:
- writing the code enabling dual NNUE:
  https://github.com/official-stockfish/Stockfish/pull/4898
- the idea of trying L1-128 trained exclusively on high simple eval
  positions

The L1-128 smallnet is:
- epoch 399 of a single-stage training from scratch
- trained only on positions from filtered data with high material
  difference
  - defined by abs(simple_eval) > 1000

```yaml
experiment-name: 128--S1-only-hse-v2

training-dataset:
  - /data/hse/S3/dfrc99-16tb7p-eval-filt-v2.min.high-simple-eval-1k.binpack
  - /data/hse/S3/leela96-filt-v2.min.high-simple-eval-1k.binpack
  - /data/hse/S3/test80-apr2022-16tb7p.min.high-simple-eval-1k.binpack

  - /data/hse/S7/test60-2020-2tb7p.v6-3072.high-simple-eval-1k.binpack
  - /data/hse/S7/test60-novdec2021-12tb7p-filter-v6-dd.min-mar2023.unmin.high-simple-eval-1k.binpack

  - /data/hse/S7/test77-nov2021-2tb7p.v6-3072.min.high-simple-eval-1k.binpack
  - /data/hse/S7/test77-dec2021-16tb7p-filter-v6-dd.min-mar2023.unmin.high-simple-eval-1k.binpack
  - /data/hse/S7/test77-jan2022-2tb7p.high-simple-eval-1k.binpack

  - /data/hse/S7/test78-jantomay2022-16tb7p-filter-v6-dd.min-mar2023.unmin.high-simple-eval-1k.binpack
  - /data/hse/S7/test78-juntosep2022-16tb7p-filter-v6-dd.min-mar2023.unmin.high-simple-eval-1k.binpack

  - /data/hse/S7/test79-apr2022-16tb7p-filter-v6-dd.min-mar2023.unmin.high-simple-eval-1k.binpack
  - /data/hse/S7/test79-may2022-16tb7p-filter-v6-dd.min-mar2023.unmin.high-simple-eval-1k.binpack

  # T80 2022
  - /data/hse/S7/test80-may2022-16tb7p.high-simple-eval-1k.binpack
  - /data/hse/S7/test80-jun2022-16tb7p-filter-v6-dd.min-mar2023.unmin.high-simple-eval-1k.binpack
  - /data/hse/S7/test80-jul2022-16tb7p.v6-dd.min.high-simple-eval-1k.binpack
  - /data/hse/S7/test80-aug2022-16tb7p-filter-v6-dd.min-mar2023.unmin.high-simple-eval-1k.binpack
  - /data/hse/S7/test80-sep2022-16tb7p-filter-v6-dd.min-mar2023.unmin.high-simple-eval-1k.binpack
  - /data/hse/S7/test80-oct2022-16tb7p.v6-dd.high-simple-eval-1k.binpack
  - /data/hse/S7/test80-nov2022-16tb7p-v6-dd.min.high-simple-eval-1k.binpack

  # T80 2023
  - /data/hse/S7/test80-jan2023-3of3-16tb7p-filter-v6-dd.min-mar2023.unmin.high-simple-eval-1k.binpack
  - /data/hse/S7/test80-feb2023-16tb7p-filter-v6-dd.min-mar2023.unmin.high-simple-eval-1k.binpack
  - /data/hse/S7/test80-mar2023-2tb7p.v6-sk16.min.high-simple-eval-1k.binpack
  - /data/hse/S7/test80-apr2023-2tb7p-filter-v6-sk16.min.high-simple-eval-1k.binpack
  - /data/hse/S7/test80-may2023-2tb7p.v6.min.high-simple-eval-1k.binpack
  - /data/hse/S7/test80-jun2023-2tb7p.v6-3072.min.high-simple-eval-1k.binpack
  - /data/hse/S7/test80-jul2023-2tb7p.v6-3072.min.high-simple-eval-1k.binpack
  - /data/hse/S7/test80-aug2023-2tb7p.v6.min.high-simple-eval-1k.binpack
  - /data/hse/S7/test80-sep2023-2tb7p.high-simple-eval-1k.binpack
  - /data/hse/S7/test80-oct2023-2tb7p.high-simple-eval-1k.binpack

start-from-engine-test-net: False

nnue-pytorch-branch: linrock/nnue-pytorch/L1-128
engine-test-branch: linrock/Stockfish/L1-128-nolazy
engine-base-branch: linrock/Stockfish/L1-128

num-epochs: 500
lambda: 1.0
```

Experiment yaml configs converted to easy_train.sh commands with:
https://github.com/linrock/nnue-tools/blob/4339954/yaml_easy_train.py

Binpacks interleaved at training time with:
https://github.com/official-stockfish/nnue-pytorch/pull/259

Data filtered for high simple eval positions with:
https://github.com/linrock/nnue-data/blob/32d6a68/filter_high_simple_eval_plain.py
https://github.com/linrock/Stockfish/blob/61dbfe/src/tools/transform.cpp#L626-L655

Training data can be found at:
https://robotmoon.com/nnue-training-data/

Local elo at 25k nodes per move of
L1-128 smallnet (nnue-only eval) vs. L1-128 trained on standard S1 data:
nn-epoch399.nnue : -318.1 +/- 2.1

Passed STC:
https://tests.stockfishchess.org/tests/view/6574cb9d95ea6ba1fcd49e3b
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 62432 W: 15875 L: 15521 D: 31036
Ptnml(0-2): 177, 7331, 15872, 7633, 203

Passed LTC:
https://tests.stockfishchess.org/tests/view/6575da2d4d789acf40aaac6e
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 64830 W: 16118 L: 15738 D: 32974
Ptnml(0-2): 43, 7129, 17697, 7497, 49

closes https://github.com/official-stockfish/Stockfish/pulls

Bench: 1330050

Co-Authored-By: mstembera <5421953+mstembera@users.noreply.github.com>
2024-01-07 21:15:52 +01:00
mstembera a5a76a6370 Introduce BAD_QUIET movepicker stage
Split quiets into good and bad as we do with captures. When we find
the first quiet move below a certain threshold that has been sorted we
consider all subsequent quiets bad.  Inspired by @locutus2 idea to skip
bad captures.

Passed STC:
https://tests.stockfishchess.org/tests/view/6597759f79aa8af82b95fa17
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 138688 W: 35566 L: 35096 D: 68026
Ptnml(0-2): 476, 16367, 35183, 16847, 471

Passed LTC:
https://tests.stockfishchess.org/tests/view/6598583c79aa8af82b960ad0
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 84108 W: 21468 L: 21048 D: 41592
Ptnml(0-2): 38, 9355, 22858, 9755, 48

closes https://github.com/official-stockfish/Stockfish/pull/4970

Bench: 1336907
2024-01-07 13:41:50 +01:00
Disservin 19f9a197be Add .git-blame-ignore-revs
Add a `.git-blame-ignore-revs` file which can be used to skip specified
commits when blaming, this is useful to ignore formatting commits, like
clang-format #4790.

Github blame automatically supports this file format, as well as other
third party tools. Git itself needs to be told about the file name to
work, the following command will add it to the current git repo. `git
config blame.ignoreRevsFile .git-blame-ignore-revs`, alternatively one
has to specify it with every blame. `git blame --ignore-revs-file
.git-blame-ignore-revs search.cpp`

Supported since git 2.23.

closes https://github.com/official-stockfish/Stockfish/pull/4969

No functional change
2024-01-07 13:38:55 +01:00
Michael Chaly 6f9071c643 Tweak usage of correction history
Instead of using linear formula use quadratic one. Maximum impact of
correction history is doubled this way, it breaks even with previous
formula on half of maximum value.

Passed STC:
https://tests.stockfishchess.org/tests/view/659591e579aa8af82b95d7e8
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 225216 W: 57616 L: 57019 D: 110581
Ptnml(0-2): 747, 26677, 57201, 27198, 785

Passed LTC:
https://tests.stockfishchess.org/tests/view/6596ee0b79aa8af82b95f08a
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 73314 W: 18524 L: 18125 D: 36665
Ptnml(0-2): 41, 8159, 19875, 8524, 58

closes https://github.com/official-stockfish/Stockfish/pull/4967

Bench: 1464785
2024-01-07 13:37:28 +01:00
Miguel Lahoz a5f7386efb Remove unneeded operator overload macros
Only Direction type is using two of the enable overload macros.
Aside from this, only two of the overloads are even being used.

Therefore, we can just define the needed overloads and remove the macros.

closes https://github.com/official-stockfish/Stockfish/pull/4966

No functional change.
2024-01-07 13:37:12 +01:00
FauziAkram 8b4583bce7 Remove redundant int cast
Remove a redundant int cast in the calculation of fwdOut. The variable
OutputType is already defined as std::int32_t, which is an integer type, making
the cast unnecessary.

closes https://github.com/official-stockfish/Stockfish/pull/4961

No functional change
2024-01-04 15:56:53 +01:00
Disservin b987d4f033 Use type aliases instead of enums for Value types
The primary rationale behind this lies in the fact that enums were not
originally designed to be employed in the manner we currently utilize them.

The Value enum was used like a type alias throughout the code and was often
misused. Furthermore, changing the underlying size of the enum to int16_t broke
everything, mostly because of the operator overloads for the Value enum, were
causing data to be truncated. Since Value is now a type alias, the operator
overloads are no longer required.

Passed Non-Regression STC:
https://tests.stockfishchess.org/tests/view/6593b8bb79aa8af82b95b401
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 235296 W: 59919 L: 59917 D: 115460
Ptnml(0-2): 743, 27085, 62054, 26959, 807

closes https://github.com/official-stockfish/Stockfish/pull/4960

No functional change
2024-01-04 15:54:23 +01:00
RainRat 4930892985 Fix typo in tbprobe.cpp
closes https://github.com/official-stockfish/Stockfish/pull/4959

No functional change
2024-01-04 15:51:56 +01:00
Disservin cafbe8e8e8 Change the Move enum to a class
This changes the Move enum to a class, this way
all move related functions can be moved into the class
and be more self contained.

closes https://github.com/official-stockfish/Stockfish/pull/4958

No functional change
2024-01-04 15:51:04 +01:00
Viren6 28f8663f39 Modify ttPV reduction
This patch modifies ttPV reduction by reducing 1 more unless ttValue is above alpha.

Inspired from @pb00068 https://tests.stockfishchess.org/tests/view/658060796a3b4f6202215f1f

Passed STC:
https://tests.stockfishchess.org/tests/view/6591867679aa8af82b958328
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 37856 W: 9727 L: 9407 D: 18722
Ptnml(0-2): 99, 4444, 9568, 4672, 145

Passed LTC:
https://tests.stockfishchess.org/tests/view/6591d9b679aa8af82b958a6c
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 128256 W: 32152 L: 31639 D: 64465
Ptnml(0-2): 64, 14364, 34772, 14851, 77

closes https://github.com/official-stockfish/Stockfish/pull/4957

Bench: 1176235
2024-01-04 15:49:33 +01:00
FauziAkram 5546bc0a26 Simplification of partial_insertion_sort formula.
Passed STC:
https://tests.stockfishchess.org/tests/view/6590110879aa8af82b9562e9
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 134880 W: 34468 L: 34355 D: 66057
Ptnml(0-2): 476, 16060, 34220, 16243, 441

Passed LTC:
https://tests.stockfishchess.org/tests/view/659156ca79aa8af82b957f07
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 60780 W: 15179 L: 14996 D: 30605
Ptnml(0-2): 27, 6847, 16464, 7020, 32

closes https://github.com/official-stockfish/Stockfish/pull/4955

Bench: 1338331
2024-01-04 15:47:37 +01:00
Disservin 444f03ee95 Update copyright year
closes https://github.com/official-stockfish/Stockfish/pull/4954

No functional change
2024-01-04 15:47:10 +01:00
Disservin a25f48a236 Silence security alert warning about possible infinite loop
As some have noticed, a security alert has been complaining about a for loop in
our TB code for quite some now. Though it was never a real issue, so not of high
importance.

A few lines earlier the symlen vector is resized
`d->symlen.resize(number<uint16_t, LittleEndian>(data));` while this code seems
odd at first, it resizes the array to at most (2 << 16) - 1 elements, basically
making the infinite loop issue impossible to occur.

closes https://github.com/official-stockfish/Stockfish/pull/4953

No functional change
2024-01-04 15:45:33 +01:00
Joseph Huang 154abb337e Lower MultiPV max to MAX_MOVES
Link max value of MultiPV to that of MAX_MOVES which is 256

closes https://github.com/official-stockfish/Stockfish/pull/4951

No functional change
2024-01-04 15:45:03 +01:00
Disservin 0fca5605fa Fix formatting in search.cpp
fixes the formatting for 1fe562fdf3
2024-01-01 02:31:25 +01:00
Stefan Geschwentner 3cfaef7431 Tweak static eval history update
Modify the applied static eval bonus for main and pawn history with different
factors for positive and negative values.

Passed STC:
https://tests.stockfishchess.org/tests/view/659132e179aa8af82b957bb0
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 12512 W: 3308 L: 3027 D: 6177
Ptnml(0-2): 32, 1372, 3189, 1609, 54

Passed LTC:
https://tests.stockfishchess.org/tests/view/65913e3d79aa8af82b957cd2
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 35946 W: 9128 L: 8809 D: 18009
Ptnml(0-2): 19, 3879, 9862, 4190, 23

closes https://github.com/official-stockfish/Stockfish/pull/4952

Bench: 1392883
2023-12-31 20:09:09 +01:00
Michael Chaly b4d995d0d9 Introduce static evaluation correction history
Idea from Caissa (https://github.com/Witek902/Caissa) chess engine.

With given pawn structure collect data with how often search result and by how
much it was better / worse than static evalution of position and use it to
adjust static evaluation of positions with given pawn structure. Details:

1. excludes positions with fail highs and moves producing it being a capture;
2. update value is function of not only difference between best value and static
   evaluation but also is multiplied by linear function of depth;
3. maximum update value is maximum value of correction history divided by 2;
4. correction history itself is divided by 32 when applied so maximum value of
   static evaluation adjustment is 32 internal units.

Passed STC:
https://tests.stockfishchess.org/tests/view/658fc7b679aa8af82b955cac
LLR: 2.96 (-2.94,2.94) <0.00,2.00>
Total: 128672 W: 32757 L: 32299 D: 63616
Ptnml(0-2): 441, 15241, 32543, 15641, 470

Passed LTC:
https://tests.stockfishchess.org/tests/view/65903f6979aa8af82b9566f1
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 97422 W: 24626 L: 24178 D: 48618
Ptnml(0-2): 41, 10837, 26527, 11245, 61

closes https://github.com/official-stockfish/Stockfish/pull/4950

Bench: 1157852
2023-12-31 20:00:06 +01:00
FauziAkram 4ff297a6df Mark square_bb() as constexpr
closes https://github.com/official-stockfish/Stockfish/pull/4949

No functional change
2023-12-31 19:58:10 +01:00
FauziAkram 1fe562fdf3 Simplify the improving flag calculation
Passed STC:
https://tests.stockfishchess.org/tests/view/658ec29979aa8af82b9547f6
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 93408 W: 23747 L: 23587 D: 46074
Ptnml(0-2): 340, 11178, 23527, 11300, 359

Passed LTC:
https://tests.stockfishchess.org/tests/view/658f73e479aa8af82b9555b6
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 64026 W: 15984 L: 15806 D: 32236
Ptnml(0-2): 31, 7113, 17552, 7281, 36

closes https://github.com/official-stockfish/Stockfish/pull/4948

Bench: 1143749
2023-12-31 19:57:34 +01:00
FauziAkram 833a2e2bc0 Cleanup comments
Tests used to derive some Elo worth comments:
https://tests.stockfishchess.org/tests/view/656a7f4e136acbc573555a31
https://tests.stockfishchess.org/tests/view/6585fb455457644dc984620f

closes https://github.com/official-stockfish/Stockfish/pull/4945

No functional change
2023-12-31 19:54:27 +01:00
Tobias Steinmann 4f99dfcae2 Update Makefile for android x86-64 builds
For developing an Android GUI it can be helpful to use the Emulator on Windows.
Therefor an android_x86-64 library of Stockfish is needed. It would be nice to
compile it "out-of-the-box".

This change is originally suggested by Craftyawesome

closes https://github.com/official-stockfish/Stockfish/pull/4927

No functional change
2023-12-31 19:51:04 +01:00
Shahin M. Shahin 1a69efbb40 Fix scores from reverse futility pruning
This fixes futility pruning return values after recent tweaks, `eval` is
guaranteed to be less than the mate-in range but it can be as low value such
that the average between eval and beta can still fall in the mated-in range when
beta is as low in mated range. i.e. (eval + beta) / 2 being at mated-range which
can break mates.

Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/658f3eed79aa8af82b955139
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 117408 W: 29891 L: 29761 D: 57756
Ptnml(0-2): 386, 13355, 31120, 13429, 414

Passed non-regression LTC:
https://tests.stockfishchess.org/tests/view/658f8b7a79aa8af82b9557bd
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 60240 W: 14962 L: 14786 D: 30492
Ptnml(0-2): 22, 6257, 17390, 6425, 26

changes signature at higher depth e.g. `128 1 15`

closes https://github.com/official-stockfish/Stockfish/pull/4944

Bench: 1304666
2023-12-30 12:19:48 +01:00
Linmiao Xu f12035c88c Update default net to nn-b1e55edbea57.nnue
Created by retraining the master big net `nn-0000000000a0.nnue` on the same
dataset with the ranger21 optimizer and more WDL skipping at training time.

More WDL skipping is meant to increase lambda accuracy and train on fewer
misevaluated positions where position scores are unlikely to correlate
with game outcomes. Inspired by:
- repeated reports in discord #events-discuss about SF misplaying due to wrong endgame
  evals, possibly due to Leela's endgame weaknesses reflected in training data
- an attempt to reduce the skewed dataset piece count distribution where there
  are much more positions with less than 16 pieces, since the target piece count
  distribution in the trainer is symmetric around 16

The faster convergence seen with ranger21 is meant to:
- prune experiment ideas more quickly since fewer epochs are needed to reach elo maxima
- research faster potential trainings by shortening each run

```yaml
experiment-name: 2560-S7-Re-514G-ranger21-more-wdl-skip
training-dataset: /data/S6-514G.binpack
early-fen-skipping: 28

start-from-engine-test-net: True
nnue-pytorch-branch: linrock/nnue-pytorch/r21-more-wdl-skip

num-epochs: 1200
lr: 4.375e-4
gamma: 0.995
start-lambda: 1.0
end-lambda: 0.7
```

Experiment yaml configs converted to easy_train.sh commands with:
https://github.com/linrock/nnue-tools/blob/4339954/yaml_easy_train.py

Implementations based off of Sopel's NNUE training & experimentation log:
https://docs.google.com/document/d/1gTlrr02qSNKiXNZ_SuO4-RjK4MXBiFlLE6jvNqqMkAY
- Experiment 336 - ranger21 https://github.com/Sopel97/nnue-pytorch/tree/experiment_336
- Experiment 351 - more WDL skipping

The version of the ranger21 optimizer used is:
https://github.com/lessw2020/Ranger21/blob/b507df6/ranger21/ranger21.py

The dataset is the exact same as in:
https://github.com/official-stockfish/Stockfish/pull/4782

Local elo at 25k nodes per move:
nn-epoch619.nnue : 6.2 +/- 4.2

Passed STC:
https://tests.stockfishchess.org/tests/view/658a029779aa8af82b94fbe6
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 46528 W: 11985 L: 11650 D: 22893
Ptnml(0-2): 154, 5489, 11688, 5734, 199

Passed LTC:
https://tests.stockfishchess.org/tests/view/658a448979aa8af82b95010f
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 265326 W: 66378 L: 65574 D: 133374
Ptnml(0-2): 153, 30175, 71254, 30877, 204

This was additionally tested with the latest DualNNUE and passed SPRTs:

Passed STC vs. https://github.com/official-stockfish/Stockfish/pull/4919
https://tests.stockfishchess.org/tests/view/658bcd5c79aa8af82b951846
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 296128 W: 76273 L: 75554 D: 144301
Ptnml(0-2): 1223, 35768, 73617, 35979, 1477

Passed LTC vs. https://github.com/official-stockfish/Stockfish/pull/4919
https://tests.stockfishchess.org/tests/view/658c988d79aa8af82b95240f
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 75618 W: 19085 L: 18680 D: 37853
Ptnml(0-2): 45, 8420, 20497, 8779, 68

closes https://github.com/official-stockfish/Stockfish/pull/4942

Bench: 1304666
2023-12-30 11:08:03 +01:00
FauziAkram bab1cc300c Refactor bestvalue adjustment in qsearch
closes https://github.com/official-stockfish/Stockfish/pull/4935

No functional change
2023-12-30 11:05:19 +01:00
Michael Chaly f388e41809 Adjust value returned after TT cutoff
Instead of returning value from TT in case of a fail high return mix between it
and beta.

Passed STC:
https://tests.stockfishchess.org/tests/view/658465395457644dc98446c7
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 220704 W: 56404 L: 55811 D: 108489
Ptnml(0-2): 750, 26214, 55921, 26627, 840

Passed LTC:
https://tests.stockfishchess.org/tests/view/6585c3f55457644dc9845db9
LLR: 2.97 (-2.94,2.94) <0.50,2.50>
Total: 124980 W: 31169 L: 30658 D: 63153
Ptnml(0-2): 57, 14147, 33603, 14594, 89

closes https://github.com/official-stockfish/Stockfish/pull/4934

Bench: 1191093
2023-12-30 11:01:32 +01:00
peregrineshahin 3f5adc037e Fix wrong mate/tb scores from probCut
This fixes returning wrong mated-in scores, or losing a proven mate-in score
from probCut after recent tweaks. The issue reported by @cj5716 on discord.

Passed non-reg STC:
https://tests.stockfishchess.org/tests/view/6583c36b5457644dc9843afe
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 295936 W: 75011 L: 75075 D: 145850
Ptnml(0-2): 978, 33947, 78146, 33955, 942

Passed non-reg LTC:
https://tests.stockfishchess.org/tests/view/658513075457644dc98451cd
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 55932 W: 13970 L: 13786 D: 28176
Ptnml(0-2): 33, 5933, 15837, 6143, 20

closes https://github.com/official-stockfish/Stockfish/pull/4933

Bench: 1308739
2023-12-30 10:57:48 +01:00
FauziAkram fbdf5d94a9 Tweak quiet move bonus
Improving quiet move bonus by replacing bestvalue and alpha comparison, with
checking the statScore of the previous search step instead.

Inspired by @locutus2

Passed STC:
https://tests.stockfishchess.org/tests/view/657f22fb893104ee25b614e8
LLR: 2.96 (-2.94,2.94) <0.00,2.00>
Total: 51296 W: 13121 L: 12774 D: 25401
Ptnml(0-2): 225, 5986, 12868, 6355, 214

Passed LTC:
https://tests.stockfishchess.org/tests/view/658024a2893104ee25b62587
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 82758 W: 20606 L: 20189 D: 41963
Ptnml(0-2): 51, 9149, 22555, 9580, 44

closes https://github.com/official-stockfish/Stockfish/pull/4930

Bench: 1312822
2023-12-22 11:51:08 +01:00
Disservin 358a853790 Revert "Adjust stand pat in qsearch on pv nodes"
This reverts commit d9ec82e743.

Bench: 1249544
2023-12-22 11:48:43 +01:00
Michael Chaly 9be0360aa4 Adjust return value in qsearch after fail high
Instead of returning strict fail soft fail high return value between value from
search and beta (somewhat by analogy to futility pruning and probcut).

This seems to be somewhat depth sensitive heuristic which performed much worse
at LTC while performing much better at STC if it is more aggressive, passed
version is the least aggressive one.

Passed STC:
https://tests.stockfishchess.org/tests/view/657b06414d789acf40ab1475
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 212352 W: 53900 L: 53315 D: 105137
Ptnml(0-2): 809, 25236, 53520, 25783, 828

Passed LTC:
https://tests.stockfishchess.org/tests/view/657ce36f393ac02e79120a7c
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 319362 W: 79541 L: 78630 D: 161191
Ptnml(0-2): 202, 35839, 86709, 36708, 223

closes https://github.com/official-stockfish/Stockfish/pull/4928

Bench: 974739
2023-12-19 18:22:10 +01:00
FauziAkram a069a1bbbf Use std::abs over abs
closes https://github.com/official-stockfish/Stockfish/pull/4926
closes https://github.com/official-stockfish/Stockfish/pull/4909

No functional change

Co-Authored-By: fffelix-huang <72808219+fffelix-huang@users.noreply.github.com>
2023-12-19 18:22:10 +01:00
FauziAkram 07a2619b62 Improvement of Time Management Parameters
Passed STC:
https://tests.stockfishchess.org/tests/view/6579c5574d789acf40aaf914
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 44672 W: 11354 L: 11030 D: 22288
Ptnml(0-2): 140, 5033, 11685, 5319, 159

Passed LTC:
https://tests.stockfishchess.org/tests/view/657ad7f44d789acf40ab105e
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 40932 W: 10275 L: 9950 D: 20707
Ptnml(0-2): 21, 4316, 11473, 4629, 27

Passed non-regression Sudden death 10+0:
https://tests.stockfishchess.org/tests/view/657b9b9e393ac02e7911f1a8
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 21384 W: 5171 L: 4925 D: 11288
Ptnml(0-2): 112, 2420, 5409, 2612, 139

closes https://github.com/official-stockfish/Stockfish/pull/4923

No functional change
2023-12-19 18:22:10 +01:00
Michael Chaly d9ec82e743 Adjust stand pat in qsearch on pv nodes
Instead of immediately returning a fail high do this only at non-pv nodes, for
pv nodes adjust bestValue to value between alpha and beta and continue
searching. Idea is to do it the same way as it's done in search where we don't
return positive beta cutoffs after ttHits / zero window search at PvNodes and
instead fully search lines.

Passed STC:
https://tests.stockfishchess.org/tests/view/65739b0af09ce1261f122f33
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 189216 W: 48142 L: 47598 D: 93476
Ptnml(0-2): 584, 22463, 48051, 22845, 665

Passed LTC:
https://tests.stockfishchess.org/tests/view/657701214d789acf40aac194
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 82506 W: 20689 L: 20269 D: 41548
Ptnml(0-2): 56, 9236, 22268, 9618, 75

Two issues had to be resolved:
    - in rare cases it set alpha to the same value as beta and thus broke some asserts;
    - messed up with returning tb win values.

      Fix passed non-regression LTC vs this patch:
      https://tests.stockfishchess.org/tests/view/6578113b4d789acf40aad544
      LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
      Total: 277308 W: 68839 L: 68880 D: 139589
      Ptnml(0-2): 167, 31580, 75212, 31517, 178

closes https://github.com/official-stockfish/Stockfish/pull/4922

Bench: 1069503

Co-Authored-By: Muzhen Gaming <61100393+XInTheDark@users.noreply.github.com>
Co-Authored-By: Shahin M. Shahin <41402573+peregrineshahin@users.noreply.github.com>
Co-Authored-By: fffelix-huang <72808219+fffelix-huang@users.noreply.github.com>
2023-12-19 18:22:10 +01:00
Muzhen Gaming c53d2ec253 Remove UCI_AnalyseMode Option
Simplify away the useless option, as documented: "An option handled by your GUI.
This currently doesn't do anything."

The option was originally added with the introduction of contempt
(https://github.com/official-stockfish/Stockfish/commit/e9aeaad05266ca557a9496b5a17b4c5f82f0e946),
but it is now no longer used.

closes https://github.com/official-stockfish/Stockfish/pull/4918

No functional change
2023-12-14 18:50:51 +01:00
FauziAkram 536d692a30 Remove SlowMover Option
The SlowMover option allows users to modify the timeLeft variant, impacting the
engine's time management. However, this feature, while theoretically flexible,
doesn't offer substantial benefits. Instead, it introduces the risk of
non-experienced users altering values without a clear understanding of the
effects, potentially leading to a weaker engine.

The vast majority of SF users don't use it anyway, and based on tests conducted
by fauzi several months ago suggest that changing it would only lose Elo.

Examples:
https://tests.stockfishchess.org/tests/view/651f309bac57711436726bba
https://tests.stockfishchess.org/tests/view/651fea29ac57711436727d85
https://tests.stockfishchess.org/tests/view/65257c343125598fc7eb68a1
https://tests.stockfishchess.org/tests/view/652296c83125598fc7eb2ad7
Tune:
https://tests.stockfishchess.org/tests/view/652a70313125598fc7ebd706
(keeping the value at 100, zz2)

closes https://github.com/official-stockfish/Stockfish/pull/4917

No functional change
2023-12-14 18:44:46 +01:00
Disservin 9fc064e872 Fix action deprecation warning for dev-drprasad
closes https://github.com/official-stockfish/Stockfish/pull/4914

No functional change
2023-12-14 18:43:02 +01:00
WangXiang cdfafb3426 Add loongarch64 support
Adding support for LoongArch64 architecture. Tested on Loongson 3A6000 EVB
Board. Since Loongson's SIMD extended instruction set
([LSX](https://gcc.gnu.org/onlinedocs/gcc/LoongArch-SX-Vector-Intrinsics.html),
[LASX](https://gcc.gnu.org/onlinedocs/gcc/LoongArch-ASX-Vector-Intrinsics.html))
is already supported by GCC, more optimizations are being developed.

Here's the benchmark result for Loongson 3A6000 (4c8t, 2.5Ghz) without SIMD
optimizations.
```
Total time (ms) : 17903
Nodes searched  : 1244386
Nodes/second    : 69507
```

closes https://github.com/official-stockfish/Stockfish/pull/4913

No functional change
2023-12-14 18:41:53 +01:00
peregrineshahin 7885fa5bd3 Track seldepth in qsearch too
Sometimes if we count the reported PV length, it turns out to be longer than the
selective depth reported. This fixes this behavior by applying the selective
depth to qsearch since we do report PVs from it as well.

Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/656cf5b66980e15f69c7499d
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 223648 W: 56372 L: 56356 D: 110920
Ptnml(0-2): 710, 25580, 59231, 25590, 713

closes https://github.com/official-stockfish/Stockfish/pull/4903

No functional change
2023-12-14 18:36:45 +01:00
Shahin M. Shahin 282e15bf75 Fix TB score output in UCI without using TB
This is a rewrite of the fix introduced for
https://github.com/official-stockfish/Stockfish/issues/4413 in
https://github.com/official-stockfish/Stockfish/pull/4591 by @windfishballad it
targets only the relevant part of this issue that returns TB scores (CP 20000)
without using TB due to the downgrading of potentially false mates from the TT
to an optimal TB score.

the difference is that it is a much clearer code that introduces a separate
TB_VALUE constant to account for a correct distance from the TB_VALUE with
MAX_PLY.

the originally posted position in the issue does not trigger the problem
anymore, so here is a new position to test:
```
position fen 3k4/8/8/8/8/8/3BN3/3K4 w - - 0 1
go infinite
```

Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/65578994136acbc57353b258
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 119264 W: 29993 L: 29863 D: 59408
Ptnml(0-2): 372, 13692, 31379, 13812, 377

Passed non-regression LTC:
https://tests.stockfishchess.org/tests/view/6558323f136acbc57353c1ca
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 237834 W: 58791 L: 58792 D: 120251
Ptnml(0-2): 193, 26200, 66111, 26241, 172

fixes https://github.com/official-stockfish/Stockfish/issues/4413
closes https://github.com/official-stockfish/Stockfish/pull/4591
closes https://github.com/official-stockfish/Stockfish/pull/4882

Bench: 1305821
2023-12-14 18:35:38 +01:00
Muzhen Gaming 36db936e76 VLTC Search parameters tune
The SPSA tuning was done for 44k games at 120+1.2.
https://tests.stockfishchess.org/tests/view/656ee2a76980e15f69c7767f.

Note that the tune was originally done in combination with the recent dual NNUE
idea (see #4910).

VLTC:
https://tests.stockfishchess.org/tests/view/65731ccbf09ce1261f12246e
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 52806 W: 13069 L: 12760 D: 26977
Ptnml(0-2): 19, 5498, 15056, 5815, 15

VLTC SMP:
https://tests.stockfishchess.org/tests/view/65740ffaf09ce1261f1239ba
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 27630 W: 6934 L: 6651 D: 14045
Ptnml(0-2): 1, 2643, 8243, 2928, 0

Estimated close to neutral at LTC:
https://tests.stockfishchess.org/tests/view/6575485a8ec68176cf7d9423
Elo: -0.59 ± 1.8 (95%) LOS: 26.6%
Total: 32060 W: 7859 L: 7913 D: 16288
Ptnml(0-2): 20, 3679, 8676, 3645, 10
nElo: -1.21 ± 3.8 (95%) PairsRatio: 0.99

closes https://github.com/official-stockfish/Stockfish/pull/4912

Bench: 1283323
2023-12-10 23:23:28 +01:00
ppigazzini 8724503d9c Simplify the code to get the native flags
closes https://github.com/official-stockfish/Stockfish/pull/4908

No functional change
2023-12-10 23:18:21 +01:00
Taras Vuk 53ad6d23b0 Remove moveMalus
Passed STC:
https://tests.stockfishchess.org/tests/view/656e0bb86980e15f69c763fa
LLR: 3.15 (-2.94,2.94) <-1.75,0.25>
Total: 123008 W: 30973 L: 30831 D: 61204
Ptnml(0-2): 368, 14032, 32568, 14162, 374

closes https://github.com/official-stockfish/Stockfish/pull/4905

No functional change
2023-12-10 23:17:14 +01:00
Disservin dadff46986 Revert "Temporarily disable CI include checks"
This reverts commit 8f65953583.

closes https://github.com/official-stockfish/Stockfish/pull/4904

No functional change
2023-12-10 23:16:12 +01:00
FauziAkram 7a8bcfc229 Remove cutNode condition
cutNode condition seems to be irrelevant.

Passed STC:
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 24224 W: 6206 L: 5970 D: 12048
Ptnml(0-2): 69, 2818, 6122, 3014, 89
https://tests.stockfishchess.org/tests/view/65686910136acbc5735529ec

Passed LTC:
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 236538 W: 58624 L: 58622 D: 119292
Ptnml(0-2): 136, 26955, 64091, 26945, 142
https://tests.stockfishchess.org/tests/view/6568925a136acbc573552d8f

closes https://github.com/official-stockfish/Stockfish/pull/4901

Bench: 1244386
2023-12-04 11:33:58 +01:00
ppigazzini 0ff2ea6549 Update GitHub workflows
- Use the latest version of the actions
- Use commit hash for actions from little providers
- Update Intel SDE to 9.27

closes https://github.com/official-stockfish/Stockfish/pull/4900

No functional change
2023-12-04 11:27:28 +01:00
Sebastian Buchwald 8f65953583 Temporarily disable CI include checks
The include checks currently fail because of broken LLVM nightly
packages: https://github.com/llvm/llvm-project/issues/73402.

closes https://github.com/official-stockfish/Stockfish/pull/4899

No functional change
2023-12-04 11:26:09 +01:00
lonfom169 08cdbca56f Tweak return value in futility pruning
In futility pruning, return the average between eval and beta.

Passed STC:
https://tests.stockfishchess.org/tests/view/65680bb6136acbc5735521d7
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 15200 W: 3926 L: 3642 D: 7632
Ptnml(0-2): 36, 1699, 3867, 1941, 57

Passed LTC:
https://tests.stockfishchess.org/tests/view/656817fc136acbc573552304
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 200376 W: 49700 L: 49036 D: 101640
Ptnml(0-2): 110, 22584, 54137, 23246, 111

closes https://github.com/official-stockfish/Stockfish/pull/4897

Bench: 1403703
2023-12-02 11:46:44 +01:00
cj5716 15d47a2b38 Remove recaptures stage in qsearch
Simplify an old commit
https://github.com/official-stockfish/Stockfish/commit/72760c05c64d1fb2bb71c2ac54acfbeecf513b87.

Search is not stuck on the test position given
r1n1n1b1/1P1P1P1P/1N1N1N2/2RnQrRq/2pKp3/3BNQbQ/k7/4Bq2 w - - 0 1

Passed STC:
https://tests.stockfishchess.org/tests/view/6567050d136acbc573550919
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 236160 W: 59475 L: 59475 D: 117210
Ptnml(0-2): 841, 28266, 59816, 28366, 791

Passed LTC:
https://tests.stockfishchess.org/tests/view/6567d133136acbc573551c78
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 201690 W: 49630 L: 49593 D: 102467
Ptnml(0-2): 128, 23214, 54122, 23255, 126

closes https://github.com/official-stockfish/Stockfish/pull/4896

Bench: 1604361
2023-12-02 11:45:38 +01:00
Taras Vuk 85403a89ba Skip LMR for 2nd move at the root only
This patch reverts commit by Vizvezdenec:
https://github.com/official-stockfish/Stockfish/commit/27139dedac14af400f5b18e2ab50aca3f8cf0e33

Passed STC:
https://tests.stockfishchess.org/tests/view/65660b4a136acbc57354f13d
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 301952 W: 76271 L: 76344 D: 149337
Ptnml(0-2): 1053, 36293, 76348, 36238, 1044

Passed LTC:
https://tests.stockfishchess.org/tests/view/656738ab136acbc573550e39
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 25050 W: 6283 L: 6063 D: 12704
Ptnml(0-2): 10, 2756, 6775, 2972, 12

closes https://github.com/official-stockfish/Stockfish/pull/4895

Bench: 1722961
2023-12-02 11:41:31 +01:00
FauziAkram 7dc40ac643 Simplify quietMoveMalus malus
Use a simple depth instead of depth + 1 in the quietMoveMalus formula.

Passed STC:
https://tests.stockfishchess.org/tests/view/65636bf0136acbc57354b662
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 105248 W: 26680 L: 26532 D: 52036
Ptnml(0-2): 409, 12590, 26481, 12732, 412

Passed LTC:
https://tests.stockfishchess.org/tests/view/6563b5db136acbc57354bcab
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 204204 W: 50200 L: 50166 D: 103838
Ptnml(0-2): 123, 23331, 55145, 23395, 108

closes https://github.com/official-stockfish/Stockfish/pull/4893

Bench: 1717495
2023-12-02 11:40:36 +01:00
cj5716 883163395e Simplify promotion move generation
closes https://github.com/official-stockfish/Stockfish/pull/4892

No functional change
2023-12-02 11:38:18 +01:00
FauziAkram f17db4641e Simplify doDeeperSearch
Removing dependence on d simplifies the doDeeperSearch formula and eliminates a
variable that is not necessary in this context.

Passed STC:
https://tests.stockfishchess.org/tests/view/65647980136acbc57354c9f6
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 37440 W: 9558 L: 9334 D: 18548
Ptnml(0-2): 127, 4439, 9375, 4641, 138

Passed LTC:
https://tests.stockfishchess.org/tests/view/6564c3f0136acbc57354d126
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 113946 W: 27993 L: 27864 D: 58089
Ptnml(0-2): 67, 12975, 30783, 13058, 90

closes https://github.com/official-stockfish/Stockfish/pull/4888

Bench: 1427733
2023-12-02 11:35:28 +01:00
Muzhen Gaming 757ae2ff53 Simplify move history reduction
Recent VLTC search tuning has suggested that the depth limit can be increased
by a lot. This patch simplifies away the depth-based bonus from statScore
reduction, making the divisor a constant.

Passed STC:
https://tests.stockfishchess.org/tests/view/656201f5136acbc573549791
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 91520 W: 23130 L: 22967 D: 45423
Ptnml(0-2): 282, 10947, 23141, 11106, 284

Passed LTC:
https://tests.stockfishchess.org/tests/view/6562b43a136acbc57354a581
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 352902 W: 86796 L: 86917 D: 179189
Ptnml(0-2): 190, 40227, 95741, 40100, 193

closes https://github.com/official-stockfish/Stockfish/pull/4886

Bench: 1297179
2023-12-02 11:30:47 +01:00
Stefan Geschwentner 13426a93c1 Simplify history update.
Removal of the slowdown factor from the history update formula with
corresponding adjustment of the stat bonus used in the search.

Passed STC:
https://tests.stockfishchess.org/tests/view/655e1079136acbc573544744
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 128096 W: 32355 L: 32235 D: 63506
Ptnml(0-2): 466, 15187, 32573, 15405, 417

Passed LTC:
https://tests.stockfishchess.org/tests/view/655f4e60136acbc573546266
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 50652 W: 12653 L: 12459 D: 25540
Ptnml(0-2): 28, 5666, 13751, 5846, 35

closes https://github.com/official-stockfish/Stockfish/pull/4883

Bench: 1303857
2023-12-02 11:23:15 +01:00
FauziAkram b4e9ee72e3 Reformat some comments
Tests used to derive some Elo worth comments:

https://tests.stockfishchess.org/tests/view/653cf6b7cc309ae83956263a
https://tests.stockfishchess.org/tests/view/655250b7136acbc573534711
https://tests.stockfishchess.org/tests/view/65525767136acbc5735347b9
https://tests.stockfishchess.org/tests/view/65525aa1136acbc573534801

closes https://github.com/official-stockfish/Stockfish/pull/4879

No functional change
2023-11-20 19:10:38 +01:00
FauziAkram b59786e750 Remove doEvenDeeperSearch
Passed STC:
LLR: 2.98 (-2.94,2.94) <-1.75,0.25>
Total: 51040 W: 13014 L: 12804 D: 25222
Ptnml(0-2): 166, 6032, 12917, 6236, 169
https://tests.stockfishchess.org/tests/view/65525aa1136acbc573534801

Passed LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 165168 W: 40863 L: 40789 D: 83516
Ptnml(0-2): 73, 18783, 44792, 18869, 67
https://tests.stockfishchess.org/tests/view/65535af5136acbc573535c84

closes https://github.com/official-stockfish/Stockfish/pull/4880

Bench: 1477007
2023-11-20 19:00:47 +01:00
FauziAkram 504bf0e8b8 Change depth - 1 to newDepth
Replacing 'depth - 1' with 'newDepth' in the singularbeta formula
utilizes existing variables more succinctly.

closes https://github.com/official-stockfish/Stockfish/pull/4876

No functional change
2023-11-20 18:59:01 +01:00
Stefan Geschwentner 7970236e9e Fix undefined behavior in search.
We use following line to clamp the search depth in some range:
Depth d = std::clamp(newDepth - r, 1, newDepth + 1);

Through negative extension its possible that the maximum value becomes smaller than the minimum value but then the behavior is undefined (see https://en.cppreference.com/w/cpp/algorithm/clamp). So replace this line with a safe implementation.

Remark:
We have in recent master already one line where up to 3 negative extensions are possible which could trigger this undefined behavior but this can only be happen for completed depth > 24 so its not discovered by our default bench. Recent negative extension tests by @fauzi shows then this undefined behavior with wrong bench numbers.

closes https://github.com/official-stockfish/Stockfish/pull/4877

No functional change
2023-11-16 09:10:20 +01:00
Joost VandeVondele d89217766b CI updates
- updates the SDE action to v2.2
- removes the linux x86-32 builds, which were almost unused,
  and the build process under SDE started failing recently,
  possibly related to glibc update (The futex facility returned an unexpected error code.)

closes https://github.com/official-stockfish/Stockfish/pull/4875

No functional change
2023-11-16 09:01:57 +01:00
Joost VandeVondele f9d8717844 Symmetrize optimism
Removes some additional parameters, making the term more logical at the same
time.

Passed STC:
https://tests.stockfishchess.org/tests/view/6550e896136acbc5735328ed
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 271104 W: 68441 L: 68480 D: 134183
Ptnml(0-2): 827, 32590, 68816, 32433, 886

Passed LTC:
https://tests.stockfishchess.org/tests/view/65523858136acbc5735344f7
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 198954 W: 49250 L: 49211 D: 100493
Ptnml(0-2): 93, 22565, 54117, 22614, 88

closes https://github.com/official-stockfish/Stockfish/pull/4874

Bench: 1334248
2023-11-15 19:35:14 +01:00
Taras Vuk 863a1f2b4c Introduce recapture extensions
When in a PV-node this patch extends ttMove if it is a recapture and has a good
history.

Passed STC:
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 83840 W: 21560 L: 21166 D: 41114
Ptnml(0-2): 343, 9905, 21027, 10305, 340
https://tests.stockfishchess.org/tests/view/654f4b02136acbc5735308ab

Passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 165318 W: 41068 L: 40476 D: 83774
Ptnml(0-2): 98, 18670, 44517, 19290, 84
https://tests.stockfishchess.org/tests/view/654fde04136acbc5735314e0

closes https://github.com/official-stockfish/Stockfish/pull/4872

Bench: 1393911
2023-11-15 19:32:59 +01:00
Linmiao Xu fbc6b27505 Simplify away optimism average score offset params
Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/654abf6b136acbc57352ac4b
LLR: 2.97 (-2.94,2.94) <-1.75,0.25>
Total: 49664 W: 12687 L: 12477 D: 24500
Ptnml(0-2): 138, 5840, 12703, 5976, 175

Passed non-regression LTC:
https://tests.stockfishchess.org/tests/view/654b638e136acbc57352b961
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 347166 W: 85561 L: 85676 D: 175929
Ptnml(0-2): 206, 39569, 94150, 39450, 208

closes https://github.com/official-stockfish/Stockfish/pull/4871

bench 1257641
2023-11-11 15:26:56 +01:00
Stefan Geschwentner 80b0e37543 Double weight of pawn history for quiet move ordering.
I measured on my 1000 position bench the average additional added pawn history per depth.
This shows on average negative value with even smaller values with increaing depth.

A linear regression against depth get following formula:

-1960 - 130 * depth

For compensation add this to the used sort limit to maintain roughly the same proportion of sorted quiet moves.

Remarks:
1. using no compensation failed here https://tests.stockfishchess.org/tests/view/6547664f136acbc5735265f0
2. using only the compensation failed at LTC:
   passed STC: https://tests.stockfishchess.org/tests/view/65477457136acbc5735266f8
   failed LTC: https://tests.stockfishchess.org/tests/view/65487fc8136acbc573527d1c

STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 98528 W: 25109 L: 24699 D: 48720
Ptnml(0-2): 334, 11586, 25009, 12006, 329
https://tests.stockfishchess.org/tests/view/65475873136acbc5735264f7

LTC:
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 69726 W: 17467 L: 17073 D: 35186
Ptnml(0-2): 39, 7814, 18769, 8196, 45
https://tests.stockfishchess.org/tests/view/6547e759136acbc573527071

closes https://github.com/official-stockfish/Stockfish/pull/4866

Bench: 1379422
2023-11-07 08:28:43 +01:00
Taras Vuk d0e87104aa Remove pawn history from ProbCut constructor
use same style as other history tables

Passed STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 184672 W: 46953 L: 46896 D: 90823
Ptnml(0-2): 604, 21095, 48887, 21140, 610
https://tests.stockfishchess.org/tests/view/654766b4136acbc573526602

closes https://github.com/official-stockfish/Stockfish/pull/4865

No functional change
2023-11-07 08:23:11 +01:00
Taras Vuk 442c294a07 Use stat_malus when decreasing stats
This patch applies stat_bonus when increasing and stat_malus when decreasing stats.

Passed STC:
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 133792 W: 34221 L: 33758 D: 65813
Ptnml(0-2): 477, 15764, 33959, 16211, 485
https://tests.stockfishchess.org/tests/view/654699f3136acbc5735256b2

Passed LTC:
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 67374 W: 16912 L: 16523 D: 33939
Ptnml(0-2): 42, 7528, 18171, 7891, 55
https://tests.stockfishchess.org/tests/view/65474558136acbc5735263ab

closes https://github.com/official-stockfish/Stockfish/pull/4864

bench: 1114417
2023-11-05 19:54:59 +01:00
FauziAkram d4b46ea6db Set reduction to 0 if the move is a TT move
The reduction formula currently decreases by 1 if the move is a TT move.
This changes this by just setting the reduction to 0 instead.

Passed STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 83136 W: 21145 L: 20758 D: 41233
Ptnml(0-2): 279, 9772, 21090, 10137, 290
https://tests.stockfishchess.org/tests/view/653c0fbacc309ae839561584

Passed LTC:
LLR: 2.96 (-2.94,2.94) <0.50,2.50>
Total: 273150 W: 67987 L: 67171 D: 137992
Ptnml(0-2): 155, 30730, 73966, 31592, 132
https://tests.stockfishchess.org/tests/view/653d9d02cc309ae839562fdf

closes https://github.com/official-stockfish/Stockfish/pull/4863

bench: 1110556
2023-11-05 19:53:15 +01:00
Shahin M. Shahin 791419aab5 Enhance some comments
This documents some code and makes some hard code easier to understand for new developers.

closes https://github.com/official-stockfish/Stockfish/pull/4862

No functional change
2023-11-05 19:51:02 +01:00
FauziAkram 7f97ba775e Tweaking the futility pruning formula
Huge credit goes also to candirufish,
as the idea was first tried by him, and then tuned by me at multiple phases.

Tweaking the futility pruning formula to be a bit more selective about when pruning is applied.
Adjust the value added to the static eval based on the bestValue relative to ss->staticEval. If bestValue is significantly lower, we add a larger value.

Passed STC:
LLR: 2.98 (-2.94,2.94) <0.00,2.00>
Total: 37120 W: 9590 L: 9266 D: 18264
Ptnml(0-2): 130, 4301, 9385, 4603, 141
https://tests.stockfishchess.org/tests/view/6544cf90136acbc573523247

Passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 49632 W: 12381 L: 12033 D: 25218
Ptnml(0-2): 30, 5429, 13549, 5779, 29
https://tests.stockfishchess.org/tests/view/65453bc1136acbc573523a3c

closes https://github.com/official-stockfish/Stockfish/pull/4861

bench: 1107118
2023-11-04 17:34:35 +01:00
Michael Chaly b4b704e686 Update pawn history based on static eval difference
Use the same logic as in main history but with 1/4 multiplier.

Passed STC:
https://tests.stockfishchess.org/tests/view/653c1282cc309ae8395615bf
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 306624 W: 77811 L: 77094 D: 151719
Ptnml(0-2): 975, 36411, 77830, 37114, 982

Passed LTC:
https://tests.stockfishchess.org/tests/view/654258e2cc309ae83956818d
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 99150 W: 24681 L: 24228 D: 50241
Ptnml(0-2): 56, 11107, 26792, 11568, 52

closes https://github.com/official-stockfish/Stockfish/pull/4859

bench 1330590
2023-11-03 22:50:05 +01:00
Stefan Geschwentner 1cb9afbdc0 Remove razoring history update.
The recently commit 'Rewarding Quiet Moves that Enable Razoring' add a history update if razoring. But its contains also many tuned values all over the search. Following tests shows that the tuned values and not the added history update is responsible for the elo gain. So remove later.

Passed STC:
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 29376 W: 7641 L: 7410 D: 14325
Ptnml(0-2): 100, 3411, 7451, 3610, 116
https://tests.stockfishchess.org/tests/view/653c9fe1cc309ae839562070

Passed LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 242922 W: 59879 L: 59885 D: 123158
Ptnml(0-2): 129, 27764, 65688, 27744, 136
https://tests.stockfishchess.org/tests/view/653d06cbcc309ae839562735

closes https://github.com/official-stockfish/Stockfish/pull/4858

Bench: 1286104
2023-11-03 22:47:31 +01:00
FauziAkram 101d2bb8ea Simplifying two formulas
by eliminating two multiplication operations.

Passed STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 60000 W: 15193 L: 14996 D: 29811
Ptnml(0-2): 199, 7100, 15215, 7277, 209
https://tests.stockfishchess.org/tests/view/653beb69cc309ae83956129d

Passed LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 122910 W: 30471 L: 30353 D: 62086
Ptnml(0-2): 68, 13961, 33271, 14095, 60
https://tests.stockfishchess.org/tests/view/653c5848cc309ae839561ae7

closes https://github.com/official-stockfish/Stockfish/pull/4857

bench: 1216779
2023-11-03 22:40:43 +01:00
cj5716 e277dda716 Prefetch TT entries in probcut
Passed STC:
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 101344 W: 25893 L: 25491 D: 49960
Ptnml(0-2): 303, 11350, 26991, 11698, 330
https://tests.stockfishchess.org/tests/view/6540daa6cc309ae83956669b

slight speedup:
```
Result of 100 runs
==================
base (./stockfish.master       ) =    1170705  +/- 3133
test (./stockfish.patch        ) =    1174545  +/- 2895
diff                             =      +3841  +/- 3196

speedup        = +0.0033
P(speedup > 0) =  0.9907
```

closes https://github.com/official-stockfish/Stockfish/pull/4856

No functional change
2023-11-03 22:39:04 +01:00
Muzhen Gaming 908811c24a Introduce asymmetric optimism
Introduce asymmetric optimism for both side to move and opponent. Parameter tuning was done with 200k LTC games.

STC: https://tests.stockfishchess.org/tests/view/653cc08fcc309ae8395622b3
LLR: 2.96 (-2.94,2.94) <0.00,2.00>
Total: 98336 W: 25074 L: 24661 D: 48601
Ptnml(0-2): 339, 11612, 24890, 11951, 376

LTC: https://tests.stockfishchess.org/tests/view/653db595cc309ae839563140
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 83244 W: 20760 L: 20339 D: 42145
Ptnml(0-2): 51, 9306, 22498, 9705, 62

closes https://github.com/official-stockfish/Stockfish/pull/4853

Bench: 1371690
2023-10-30 07:51:27 +01:00
cj5716 38aa70adcf Small cleanups
Corrects some incorrect or outdated comments.
Credit is shared with yaneurao (see 38e830a#commitcomment-131131500) and locutus2

closes #4852

No functional change.
2023-10-30 07:49:15 +01:00
Disservin 347d613b0e remove outdated comment
Bench: 1258079
2023-10-27 18:35:52 +02:00
Disservin 08ed4c90db Format Code
No functional change
2023-10-27 17:33:59 +02:00
FauziAkram d30af4f669 Rewarding Quiet Moves that Enable Razoring
The main idea of the patch comes from @peregrineshahin :
https://tests.stockfishchess.org/tests/view/65205363ac57711436728781

Another small idea (tuning) comes from @Vizvezdenec
https://tests.stockfishchess.org/tests/view/652e071ade6d262d08d318f4 And a long
phases of tuning and tests was done by me in order to make the patch be able to
pass both tests.

The idea, as mentioned by Peregrine is that in our standard code, if no best
move found after searching all moves, we give a bonus to the previous move that
caused the fail high. So in razoring we assume no bestmove will be found so we
might as well do the same.

Passed STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 82336 W: 20997 L: 20610 D: 40729
Ptnml(0-2): 288, 9710, 20753, 10161, 256
https://tests.stockfishchess.org/tests/view/6538fafbcc309ae83955d8f0

Passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 46584 W: 11753 L: 11411 D: 23420
Ptnml(0-2): 21, 5133, 12642, 5475, 21
https://tests.stockfishchess.org/tests/view/653a3f2ccc309ae83955f223

closes https://github.com/official-stockfish/Stockfish/pull/4850

Bench: 1258079

Co-Authored-By: Shahin M. Shahin <41402573+peregrineshahin@users.noreply.github.com>
2023-10-27 17:32:19 +02:00
Michael Chaly b0658f09b9 Introduce pawn structure based history
Original idea by Seer chess engine https://github.com/connormcmonigle/seer-nnue,
coding done by @Disservin, code refactoring done by @locutus2 to match the style
of other histories.

This patch introduces pawn structure based history, which assings moves values
based on last digits of pawn structure hash and piece type of moved piece and
landing square of the move. Idea is that good places for pieces are quite often
determined by pawn structure of position. Used in 3 different places
- sorting of quiet moves, sorting of quiet check evasions and in history based
pruning in search.

Passed STC:
https://tests.stockfishchess.org/tests/view/65391d08cc309ae83955dbaf
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 155488 W: 39408 L: 38913 D: 77167
Ptnml(0-2): 500, 18427, 39408, 18896, 513

Passed LTC:
https://tests.stockfishchess.org/tests/view/653a36a2cc309ae83955f181
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 70110 W: 17548 L: 17155 D: 35407
Ptnml(0-2): 33, 7859, 18889, 8230, 44

closes https://github.com/official-stockfish/Stockfish/pull/4849

Bench: 1257882

Co-Authored-By: Disservin <disservin.social@gmail.com>
Co-Authored-By: Stefan Geschwentner <locutus2@users.noreply.github.com>
2023-10-27 17:24:25 +02:00
Taras Vuk 871ab55f01 Simplify futility pruning formula
closes https://github.com/official-stockfish/Stockfish/pull/4848

No functional change
2023-10-27 17:16:28 +02:00
Linmiao Xu 0024133b08 Update 5 search params for pruning at shallow depth
Found by spsa tuning at 45+0.45 with:

```
int fpcEvalOffset = 188;
int fpcLmrDepthMult = 206;
int histDepthMult = -3232;
int histDenom = 5793;
int fpEvalOffset = 115;
int negSeeDepthMultSq = -27;
TUNE(SetRange(0, 394), fpcEvalOffset);
TUNE(SetRange(0, 412), fpcLmrDepthMult);
TUNE(SetRange(-6464, -1616), histDepthMult);
TUNE(SetRange(2896, 11586), histDenom);
TUNE(SetRange(0, 230), fpEvalOffset);
TUNE(SetRange(-54, 0), negSeeDepthMultSq);
```

Passed STC:
https://tests.stockfishchess.org/tests/view/6535551de746e058e6c0165d
LLR: 2.98 (-2.94,2.94) <0.00,2.00>
Total: 109056 W: 28025 L: 27599 D: 53432
Ptnml(0-2): 357, 12669, 28038, 13119, 345

Passed LTC:
https://tests.stockfishchess.org/tests/view/65364c6ff127f3553505175d
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 61290 W: 15316 L: 14941 D: 31033
Ptnml(0-2): 34, 6849, 16498, 7236, 28

closes https://github.com/official-stockfish/Stockfish/pull/4847

bench 1167412
2023-10-24 17:46:18 +02:00
Joost VandeVondele ec02714b62 Cleanup comments and some code reorg.
passed STC:
https://tests.stockfishchess.org/tests/view/6536dc7dcc309ae83955b04d
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 58048 W: 14693 L: 14501 D: 28854
Ptnml(0-2): 200, 6399, 15595, 6669, 161

closes https://github.com/official-stockfish/Stockfish/pull/4846

No functional change
2023-10-24 17:43:05 +02:00
cj5716 d6a5c2b085 Small formatting improvements
Changes some C style casts to C++ style, and fixes some incorrect comments and variable names.

closes #4845

No functional change
2023-10-24 17:42:13 +02:00
Joost VandeVondele 49ece9f791 Follow up Makefile changes for clang-format
as reported on various OS, these changes help portability

closes https://github.com/official-stockfish/Stockfish/pull/4844

No functional change.
2023-10-23 20:39:48 +02:00
Muzhen Gaming cf3dbcb5ac Time management improvements
1. Tune time management parameters.
2. Scale the optimum time and maximum time parameters based on the amount of
   time left, using a logarithmic scale.

Many acknowledgements to @FauziAkram for tuning the parameters and for the
original idea (see
https://tests.stockfishchess.org/tests/view/652f0356de6d262d08d333c5).

STC: https://tests.stockfishchess.org/tests/view/6533938fde6d262d08d39e4d
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 44320 W: 11301 L: 10982 D: 22037
Ptnml(0-2): 146, 4810, 11920, 5147, 137

LTC: https://tests.stockfishchess.org/tests/view/653477e4de6d262d08d3ae06
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 146442 W: 37338 L: 36811 D: 72293
Ptnml(0-2): 60, 14975, 42645, 15460, 81

Verification runs:
3+0.03: https://tests.stockfishchess.org/tests/view/65364e7ef127f3553505178a
10+0: https://tests.stockfishchess.org/tests/view/65364e9ff127f3553505178f
180+1.8: https://tests.stockfishchess.org/tests/view/65364ec3f127f35535051794

closes https://github.com/official-stockfish/Stockfish/pull/4843

No functional change.

Co-Authored-By: FauziAkram <11150271+FauziAkram@users.noreply.github.com>
2023-10-23 20:39:48 +02:00
Disservin a105978bbd remove blank line between function and it's description
- remove the blank line between the declaration of the function and it's
  comment, leads to better IDE support when hovering over a function to see it's
  description
- remove the unnecessary duplication of the function name in the functions
  description
- slightly refactored code for lsb, msb in bitboard.h There are still a few
  things we can be improved later on, move the description of a function where
  it was declared (instead of implemented) and add descriptions to functions
  which are behind macros ifdefs

closes https://github.com/official-stockfish/Stockfish/pull/4840

No functional change
2023-10-23 20:39:48 +02:00
Disservin b187622233 use expanded variables for shell commands
Performance improvement for the shell commands in the Makefile.
By using expanded variables, the shell commands are only
evaluated once, instead of every time they are used.

closes https://github.com/official-stockfish/Stockfish/pull/4838

No functional change
2023-10-23 20:39:48 +02:00
MinetaS 40c6a84434 Fix a compiler bug on Clang 15+ with AVX-512
fixes https://github.com/official-stockfish/Stockfish/issues/4450
closes https://github.com/official-stockfish/Stockfish/pull/4830

No functional change.
2023-10-23 20:39:48 +02:00
Taras Vuk b7b7800e2b Simplify futilityBase formula
This patch replaces std::min(ss->staticEval, bestValue) with ss->staticEval in the futilityBase formula.
Original idea by Vizvezdenec: https://tests.stockfishchess.org/tests/view/64ce66795b17f7c21c0d85f3

Passed STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 116928 W: 29925 L: 29793 D: 57210
Ptnml(0-2): 399, 13558, 30446, 13634, 427
https://tests.stockfishchess.org/tests/view/653285aade6d262d08d385dd

Passed LTC:
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 50868 W: 12947 L: 12757 D: 25164
Ptnml(0-2): 30, 5414, 14355, 5606, 29
https://tests.stockfishchess.org/tests/view/65336ffbde6d262d08d39ba0

closes https://github.com/official-stockfish/Stockfish/pull/4837

bench: 1241996
2023-10-22 16:16:02 +02:00
Disservin 2d0237db3f add clang-format
This introduces clang-format to enforce a consistent code style for Stockfish.

Having a documented and consistent style across the code will make contributing easier
for new developers, and will make larger changes to the codebase easier to make.

To facilitate formatting, this PR includes a Makefile target (`make format`) to format the code,
this requires clang-format (version 17 currently) to be installed locally.

Installing clang-format is straightforward on most OS and distros
(e.g. with https://apt.llvm.org/, brew install clang-format, etc), as this is part of quite commonly
used suite of tools and compilers (llvm / clang).

Additionally, a CI action is present that will verify if the code requires formatting,
and comment on the PR as needed. Initially, correct formatting is not required, it will be
done by maintainers as part of the merge or in later commits, but obviously this is encouraged.

fixes https://github.com/official-stockfish/Stockfish/issues/3608
closes https://github.com/official-stockfish/Stockfish/pull/4790

Co-Authored-By: Joost VandeVondele <Joost.VandeVondele@gmail.com>
2023-10-22 16:06:27 +02:00
mstembera 8366ec48ae Scale down stat bonus
STC https://tests.stockfishchess.org/tests/view/652eff58de6d262d08d33353
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 88224 W: 22618 L: 22228 D: 43378
Ptnml(0-2): 282, 10177, 22783, 10609, 261

LTC https://tests.stockfishchess.org/tests/view/652fd13bde6d262d08d3481a
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 143508 W: 36674 L: 36142 D: 70692
Ptnml(0-2): 92, 15240, 40534, 15820, 68

Reduces the stat bonus by 20%. Maybe future patches can tune the actual bonus calculations for different histories.

closes https://github.com/official-stockfish/Stockfish/pull/4836

bench: 1185932
2023-10-21 10:37:27 +02:00
Taras Vuk e18619d078 Subtract the margin from the value returned by ProbCut
This patch subtracts the margin from the value returned by ProbCut.

Passed STC:
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 46112 W: 11940 L: 11610 D: 22562
Ptnml(0-2): 131, 5318, 11842, 5620, 145
https://tests.stockfishchess.org/tests/view/652ea42ade6d262d08d329dd

Passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 86880 W: 22192 L: 21776 D: 42912
Ptnml(0-2): 43, 9213, 24510, 9633, 41
https://tests.stockfishchess.org/tests/view/652f70ffde6d262d08d33e8d

closes https://github.com/official-stockfish/Stockfish/pull/4835

bench: 1135313
2023-10-21 10:34:12 +02:00
FauziAkram 90c18b0b50 Removing history condition
Removing the bad history condition from the skip futility pruning formula.

Passed STC:
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 142688 W: 36420 L: 36317 D: 69951
Ptnml(0-2): 481, 16653, 36970, 16762, 478
https://tests.stockfishchess.org/tests/view/65270a663125598fc7eb8c67

Passed LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 435378 W: 110723 L: 110925 D: 213730
Ptnml(0-2): 278, 47251, 122788, 47139, 233
https://tests.stockfishchess.org/tests/view/6528595f3125598fc7eba8f5

closes https://github.com/official-stockfish/Stockfish/pull/4834

Bench: 1110579
2023-10-21 10:31:51 +02:00
mstembera d3d0c69dc1 Remove outdated Tile naming.
cleanup variable naming after  #4816

closes #4833

No functional change
2023-10-21 10:28:55 +02:00
Shahin M. Shahin 057046cc9a Cleanup qsearch continuation histories
Only (ss-1) and (ss-2) are used in qsearch.

closes https://github.com/official-stockfish/Stockfish/pull/4828

No functional change
2023-10-21 10:26:09 +02:00
FauziAkram edb4ab924f Standardize Comments
use double slashes (//) only for comments.

closes #4820

No functional change.
2023-10-21 10:25:03 +02:00
Stéphane Nicolet fe53a18f7a Reformat some comments and conditions
closes https://github.com/official-stockfish/Stockfish/pull/4814

No functional change
2023-10-21 10:15:48 +02:00
Shahin M. Shahin a4fedd8152 Fix greater than TB scores in null move pruning.
This patch is a simplification and a fix to dealing with null moves scores that returns proven mates or TB scores by preventing 'null move pruning' if the nullvalue is in that range.

Current solution downgrades nullValues on the non-PV node but the value can be used in a transposed PV-node to the same position afterwards (Triangulation), the later is prone to propagate a wrong score (96.05) to root that will not be refuted unless we search further.

Score of (96.05) can be obtained be two methods,

maxim static-eval returned on Pv update (mostly qSearch)
this downgrade (clamp) in NMP
and theoretically can happen with or without TBs but the second scenario is more dangerous than the first.
This fixes the reproducible case in very common scenarios with TBs as shown in the debugging at discord.

Fixes: #4699

Passed STC:
https://tests.stockfishchess.org/tests/view/64c1eca8dc56e1650abba6f9
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 670048 W: 171132 L: 171600 D: 327316
Ptnml(0-2): 2134, 75687, 179820, 75279, 2104

Passed LTC:
https://tests.stockfishchess.org/tests/view/64c5e130dc56e1650abc0438
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 92868 W: 23642 L: 23499 D: 45727
Ptnml(0-2): 52, 9509, 27171, 9648, 54

closes https://github.com/official-stockfish/Stockfish/pull/4715

Bench: 1327410
2023-10-21 10:01:26 +02:00
Michael Chaly 38e830af4b Use more continuation histories.
This patch allows stats updates and movepicker bonuses for continuation history 3 plies deep - so counter counter move.
Updates and movepicker usage are done with 1/4 multiplier compared to other histories.

Passed STC:
https://tests.stockfishchess.org/tests/view/6528f28d3125598fc7ebb5a3
LLR: 2.96 (-2.94,2.94) <0.00,2.00>
Total: 161344 W: 41369 L: 40868 D: 79107
Ptnml(0-2): 535, 18720, 41679, 19185, 553

Passed LTC:
https://tests.stockfishchess.org/tests/view/652a397a3125598fc7ebd1d6
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 48564 W: 12556 L: 12215 D: 23793
Ptnml(0-2): 25, 5149, 13595, 5486, 27

closes https://github.com/official-stockfish/Stockfish/pull/4827

bench 1327410
2023-10-14 16:52:35 +02:00
Muzhen Gaming 002636362e Search parameters tune at 180+1.8
Passed VLTC: https://tests.stockfishchess.org/tests/view/65200c58ac577114367280bc
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 146180 W: 37407 L: 36988 D: 71785
Ptnml(0-2): 21, 14474, 43675, 14905, 15

Passed VLTC SMP: https://tests.stockfishchess.org/tests/view/652403da3125598fc7eb4b6d
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 57580 W: 15061 L: 14739 D: 27780
Ptnml(0-2): 2, 5001, 18460, 5327, 0

closes https://github.com/official-stockfish/Stockfish/pull/4826

Bench: 1099336
2023-10-10 17:45:32 +02:00
Taras Vuk 7a4de96159 Skip futility pruning if ttMove has bad history
Passed STC:
LLR: 2.96 (-2.94,2.94) <0.00,2.00>
Total: 52416 W: 13465 L: 13128 D: 25823
Ptnml(0-2): 128, 6024, 13604, 6287, 165
https://tests.stockfishchess.org/tests/view/651fadd4ac577114367277bf

Passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 87348 W: 22234 L: 21818 D: 43296
Ptnml(0-2): 38, 9240, 24698, 9664, 34
https://tests.stockfishchess.org/tests/view/65201932ac57711436728218

closes https://github.com/official-stockfish/Stockfish/pull/4825

bench: 1246560
2023-10-08 07:56:07 +02:00
gabe f7fbc6880e Avoid recomputing moveCountPruning
In search, when moveCountPruning becomes true, it can never turn false again.

Passed STC https://tests.stockfishchess.org/tests/view/652075ceac57711436728aac
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 136448 W: 34923 L: 34472 D: 67053
Ptnml(0-2): 420, 15094, 36767, 15501, 442

closes https://github.com/official-stockfish/Stockfish/pull/4823

Non functional change
2023-10-08 07:52:16 +02:00
candirufish 25d444ed60 Razor more if ss+1 cutoffCnt > 3
STC:
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 221760 W: 56726 L: 56144 D: 108890
Ptnml(0-2): 655, 25453, 58123, 25953, 696
https://tests.stockfishchess.org/tests/view/651d34dbcff46e538ee05d91

LTC:
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 130326 W: 33188 L: 32681 D: 64457
Ptnml(0-2): 69, 13949, 36620, 14456, 69
https://tests.stockfishchess.org/tests/view/651f844eac577114367273d5

closes https://github.com/official-stockfish/Stockfish/pull/4822

bench: 1291708
2023-10-08 07:50:03 +02:00
Stefan Geschwentner 008d59512a Simplify collection of bad moves for history updates.
1. collect only the first 32 moves searched and ignore the rest. So late bad moves get no further negative history updates.
2. collect now for quiet moves also at most 32 bad moves

STC:
https://tests.stockfishchess.org/tests/view/6517b3aeb3e74811c8af5651
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 51168 W: 13013 L: 12810 D: 25345
Ptnml(0-2): 120, 6006, 13186, 6095, 177

LTC:
https://tests.stockfishchess.org/tests/view/651adafecff46e538ee02734
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 109866 W: 27786 L: 27656 D: 54424
Ptnml(0-2): 52, 11816, 31069, 11942, 54

closes https://github.com/official-stockfish/Stockfish/pull/4818

Bench: 1338617
2023-10-08 07:46:26 +02:00
mstembera c17a657b04 Optimize the most common update accumalator cases w/o tiling
In the most common case where we only update a single state
it's faster to not use temporary accumulation registers and tiling.
(Also includes a couple of small cleanups.)

passed STC
https://tests.stockfishchess.org/tests/view/651918e3cff46e538ee0023b
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 34944 W: 8989 L: 8687 D: 17268
Ptnml(0-2): 88, 3743, 9512, 4037, 92

A simpler version
https://tests.stockfishchess.org/tests/view/65190dfacff46e538ee00155
also passed but this version is stronger still
https://tests.stockfishchess.org/tests/view/6519b95fcff46e538ee00fa2

closes https://github.com/official-stockfish/Stockfish/pull/4816

No functional change
2023-10-08 07:42:39 +02:00
Stéphane Nicolet 040dfedb34 Remove one test in the move loop
Simplification passed STC test:
https://tests.stockfishchess.org/tests/view/6519fc91cff46e538ee014f6
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 191264 W: 48550 L: 48501 D: 94213
Ptnml(0-2): 576, 21529, 51392, 21540, 595

closes #4815

Non functional change
2023-10-08 07:41:16 +02:00
Robert Nurnberg @ elitebook f1ce1cd475 Update links in license
matches https://www.gnu.org/licenses/gpl-3.0.txt

closes https://github.com/official-stockfish/Stockfish/pull/4813

No functional change
2023-10-08 07:38:13 +02:00
mstembera 8a912951de Remove handcrafted MMX code
too small a benefit to maintain this old target

closes https://github.com/official-stockfish/Stockfish/pull/4804

No functional change
2023-10-08 07:37:01 +02:00
Linmiao Xu afe7f4d9b0 Update default net to nn-0000000000a0.nnue
This is a later epoch from the same experiment that led to the previous
master net. In training stage 6, max-epoch was raised to 1,200 near the
end of the first 1,000 epochs.

For more details, see https://github.com/official-stockfish/Stockfish/pull/4795

Local elo at 25k nodes per move (vs. L1-2048 nn-1ee1aba5ed4c.nnue)
ep1079 : 15.6 +/- 1.2

Passed STC:
https://tests.stockfishchess.org/tests/view/651503b3b3e74811c8af1e2a
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 29408 W: 7607 L: 7304 D: 14497
Ptnml(0-2): 97, 3277, 7650, 3586, 94

Passed LTC:
https://tests.stockfishchess.org/tests/view/651585ceb3e74811c8af2a5f
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 73164 W: 18828 L: 18440 D: 35896
Ptnml(0-2): 30, 7749, 20644, 8121, 38

closes https://github.com/official-stockfish/Stockfish/pull/4810

Bench: 1453057
2023-09-29 22:30:27 +02:00
cj5716 660da1ca7b Skip moves-loop pruning in qsearch if we have only pawns
At first my idea was only to cover movecount and futility pruning, but
@peregrineshahin suggested to test it on all moves-loop pruning and it worked.

Passed STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 167968 W: 42970 L: 42480 D: 82518
Ptnml(0-2): 444, 18324, 46002, 18726, 488
https://tests.stockfishchess.org/tests/view/6511181a55b420c569d0d54c

Passed LTC:
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 40794 W: 10496 L: 10182 D: 20116
Ptnml(0-2): 12, 4021, 12025, 4319, 20
https://tests.stockfishchess.org/tests/view/6512ccc4b3e74811c8aee86c

closes https://github.com/official-stockfish/Stockfish/pull/4809

Bench: 1338472
2023-09-29 22:28:34 +02:00
Sebastian Buchwald 4f0fecad8a Use C++17 variable templates for type traits
The C++17 variable templates are slightly more readable and allow us to
remove the typename keyword in a few cases.

closes https://github.com/official-stockfish/Stockfish/pull/4806

No functional change
2023-09-29 22:22:40 +02:00
mstembera 31d0b7fe93 Remove unused see_ge() code
closes https://github.com/official-stockfish/Stockfish/pull/4805

No functional change
2023-09-29 22:19:08 +02:00
FauziAkram 243f7b264a Improve grammar of comments
closes https://github.com/official-stockfish/Stockfish/pull/4801

No functional change
2023-09-29 22:18:17 +02:00
FauziAkram 9739ed7a97 Simplify pawn count in evaluation
This simplifies the evaluation by removing the unnecessary pawn count term when
combining nnue and optimism values.

Passed STC
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 61472 W: 15748 L: 15554 D: 30170
Ptnml(0-2): 191, 7123, 15933, 7279, 210
https://tests.stockfishchess.org/tests/view/650c34cf7ca0d3f7bbf264ff

Passed LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 81264 W: 20657 L: 20500 D: 40107
Ptnml(0-2): 30, 8713, 22997, 8854, 38
https://tests.stockfishchess.org/tests/view/650cc30efb151d43ae6d5987

closes https://github.com/official-stockfish/Stockfish/pull/4800

Bench: 1530568
2023-09-29 22:12:46 +02:00
Jasper Shovelton ce99b4b2ef Increment minor section number from 3.7.1 to 3.8.1.
Pext has nothing to do with git commit sha/date, so separate the two
sub-sections.

closes https://github.com/official-stockfish/Stockfish/pull/4785

No functional change
2023-09-29 22:07:10 +02:00
Joost VandeVondele 22cdb6c1ea Explicitly invoke shell
in some cases the permission on the script might be incorrect (zip downloads?).
Explicitly invoke the shell

closes https://github.com/official-stockfish/Stockfish/pull/4803

No functional change
2023-09-24 20:04:42 +02:00
Linmiao Xu 70ba9de85c Update NNUE architecture to SFNNv8: L1-2560 nn-ac1dbea57aa3.nnue
Creating this net involved:
- a 6-stage training process from scratch. The datasets used in stages 1-5 were fully minimized.
- permuting L1 weights with https://github.com/official-stockfish/nnue-pytorch/pull/254

A strong epoch after each training stage was chosen for the next. The 6 stages were:

```
1. 400 epochs, lambda 1.0, default LR and gamma
   UHOx2-wIsRight-multinet-dfrc-n5000 (135G)
     nodes5000pv2_UHO.binpack
     data_pv-2_diff-100_nodes-5000.binpack
     wrongIsRight_nodes5000pv2.binpack
     multinet_pv-2_diff-100_nodes-5000.binpack
     dfrc_n5000.binpack

2. 800 epochs, end-lambda 0.75, LR 4.375e-4, gamma 0.995, skip 12
   LeelaFarseer-T78juntoaugT79marT80dec.binpack (141G)
     T60T70wIsRightFarseerT60T74T75T76.binpack
     test78-junjulaug2022-16tb7p.no-db.min.binpack
     test79-mar2022-16tb7p.no-db.min.binpack
     test80-dec2022-16tb7p.no-db.min.binpack

3. 800 epochs, end-lambda 0.725, LR 4.375e-4, gamma 0.995, skip 20
   leela93-v1-dfrc99-v2-T78juntosepT80jan-v6dd-T78janfebT79aprT80aprmay.min.binpack
     leela93-filt-v1.min.binpack
     dfrc99-16tb7p-filt-v2.min.binpack
     test78-juntosep2022-16tb7p-filter-v6-dd.min-mar2023.binpack
     test80-jan2023-3of3-16tb7p-filter-v6-dd.min-mar2023.binpack
     test78-janfeb2022-16tb7p.min.binpack
     test79-apr2022-16tb7p.min.binpack
     test80-apr2022-16tb7p.min.binpack
     test80-may2022-16tb7p.min.binpack

4. 800 epochs, end-lambda 0.7, LR 4.375e-4, gamma 0.995, skip 24
   leela96-dfrc99-v2-T78juntosepT79mayT80junsepnovjan-v6dd-T80mar23-v6-T60novdecT77decT78aprmayT79aprT80may23.min.binpack
     leela96-filt-v2.min.binpack
     dfrc99-16tb7p-filt-v2.min.binpack
     test78-juntosep2022-16tb7p-filter-v6-dd.min-mar2023.binpack
     test79-may2022-16tb7p.filter-v6-dd.min.binpack
     test80-jun2022-16tb7p.filter-v6-dd.min.binpack
     test80-sep2022-16tb7p.filter-v6-dd.min.binpack
     test80-nov2022-16tb7p.filter-v6-dd.min.binpack
     test80-jan2023-3of3-16tb7p-filter-v6-dd.min-mar2023.binpack
     test80-mar2023-2tb7p.v6-sk16.min.binpack
     test60-novdec2021-16tb7p.min.binpack
     test77-dec2021-16tb7p.min.binpack
     test78-aprmay2022-16tb7p.min.binpack
     test79-apr2022-16tb7p.min.binpack
     test80-may2023-2tb7p.min.binpack

5. 960 epochs, end-lambda 0.7, LR 4.375e-4, gamma 0.995, skip 28
   Increased max-epoch to 960 near the end of the first 800 epochs
   5af11540bbfe dataset: https://github.com/official-stockfish/Stockfish/pull/4635

6. 1000 epochs, end-lambda 0.7, LR 4.375e-4, gamma 0.995, skip 28
   Increased max-epoch to 1000 near the end of the first 800 epochs
   1ee1aba5ed dataset: https://github.com/official-stockfish/Stockfish/pull/4782
```

L1 weights permuted with:
```bash
python3 serialize.py $nnue $nnue_permuted \
  --features=HalfKAv2_hm \
  --ft_optimize \
  --ft_optimize_data=/data/fishpack32.binpack \
  --ft_optimize_count=10000
```

Speed measurements from 100 bench runs at depth 13 with profile-build x86-64-avx2:
```
sf_base =  1329051 +/-   2224 (95%)
sf_test =  1163344 +/-   2992 (95%)
diff    =  -165706 +/-   4913 (95%)
speedup = -12.46807% +/- 0.370% (95%)
```

Training data can be found at:
https://robotmoon.com/nnue-training-data/

Local elo at 25k nodes per move (vs. L1-2048 nn-1ee1aba5ed4c.nnue)
ep959 : 16.2 +/- 2.3

Failed 10+0.1 STC:
https://tests.stockfishchess.org/tests/view/6501beee2cd016da89abab21
LLR: -2.92 (-2.94,2.94) <0.00,2.00>
Total: 13184 W: 3285 L: 3535 D: 6364
Ptnml(0-2): 85, 1662, 3334, 1440, 71

Failed 180+1.8 VLTC:
https://tests.stockfishchess.org/tests/view/6505cf9a72620bc881ea908e
LLR: -2.94 (-2.94,2.94) <0.00,2.00>
Total: 64248 W: 16224 L: 16374 D: 31650
Ptnml(0-2): 26, 6788, 18640, 6650, 20

Passed 60+0.6 th 8 VLTC SMP (STC bounds):
https://tests.stockfishchess.org/tests/view/65084a4618698b74c2e541dc
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 90630 W: 23372 L: 23033 D: 44225
Ptnml(0-2): 13, 8490, 27968, 8833, 11

Passed 60+0.6 th 8 VLTC SMP:
https://tests.stockfishchess.org/tests/view/6501d45d2cd016da89abacdb
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 137804 W: 35764 L: 35276 D: 66764
Ptnml(0-2): 31, 13006, 42326, 13522, 17

closes https://github.com/official-stockfish/Stockfish/pull/4795

bench 1246812
2023-09-22 19:26:16 +02:00
Stefan Geschwentner 154b8d3ecb Remove VALUE_KNOWN_WIN.
After removing classic evaluation VALUE_KNOWN_WIN is not anymore returned explicit evaluation. So remove and replace it with VALUE_TB_WIN_IN_MAX_PLY.

Measurement on my big bench (bench 16 1 16 pos1000.fen) verifies that at least with current net the calculated evaluation lies always in the open interval  (-VALUE_KNOWN_WIN, VALUE_KNOWN_WIN).
So i consider this a non-functional change. But to be safe i tested this also at LTC as requested by Stephane Nicolet.

STC:
https://tests.stockfishchess.org/tests/view/64f9db40eaf01be8259a6ed5
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 455296 W: 115981 L: 116217 D: 223098
Ptnml(0-2): 1415, 50835, 123420, 50527, 1451

LTC:
https://tests.stockfishchess.org/tests/view/650bfd867ca0d3f7bbf25feb
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 35826 W: 9170 L: 8973 D: 17683
Ptnml(0-2): 12, 3523, 10645, 3722, 11

closes https://github.com/official-stockfish/Stockfish/pull/4792

Bench: 1603079
2023-09-22 19:25:57 +02:00
mstembera 95fe2b9a9d Reduce SIMD register count from 32 to 16
in the case of avx512 and vnni512 archs.

Up to 17% speedup, depending on the compiler, e.g.

```
AMD pro 7840u (zen4 phoenix apu 4nm)
bash bench_parallel.sh ./stockfish_avx512_gcc13 ./stockfish_avx512_pr_gcc13 20 10
sf_base =  1077737 +/-   8446 (95%)
sf_test =  1264268 +/-   8543 (95%)
diff    =   186531 +/-   4280 (95%)
speedup =  17.308% +/- 0.397% (95%)
```

Prior to this patch, it appears gcc spills registers.

closes https://github.com/official-stockfish/Stockfish/pull/4796

No functional change
2023-09-22 19:15:34 +02:00
cj5716 fce4cc1829 Make casting styles consistent
Make casting styles consistent with the rest of the code.

closes https://github.com/official-stockfish/Stockfish/pull/4793

No functional change
2023-09-22 19:14:29 +02:00
Sebastian Buchwald 952740b36c Let CI check C++ includes
The commit adds a CI workflow that uses the included-what-you-use (IWYU)
tool to check for missing or superfluous includes in .cpp files and
their corresponding .h files. This means that some .h files (especially
in the nnue folder) are not checked yet.

The CI setup looks like this:
- We build IWYU from source to include some yet unreleased fixes.
  This IWYU version targets LLVM 17. Thus, we get the latest release
  candidate of LLVM 17 from LLVM's nightly packages.
- The Makefile now has an analyze target that just build the object
  files (without linking)
- The CI uses the analyze target with the IWYU tool as compiler to
  analyze the compiled .cpp file and its corresponding .h file.
- If IWYU suggests a change the build fails (-Xiwyu --error).
- To avoid false positives we use LLVM's libc++ as standard library
- We have a custom mappings file that adds some mappings that are
  missing in IWYU's default mappings

We also had to add one IWYU pragma to prevent a false positive in
movegen.h.

https://github.com/official-stockfish/Stockfish/pull/4783

No functional change
2023-09-22 19:12:53 +02:00
Stéphane Nicolet e594aa7429 Export makefile ARCH in binary
Example of the `./stockfish compiler` command:

Compiled by                : g++ (GNUC) 10.3.0 on Apple
Compilation architecture   : x86-64-bmi2
Compilation settings       : 64bit BMI2 AVX2 SSE41 SSSE3 SSE2 POPCNT
Compiler __VERSION__ macro : 10.3.0

closes https://github.com/official-stockfish/Stockfish/pull/4789

no functional change
2023-09-22 19:09:20 +02:00
Joost VandeVondele 708319a433 Enable a default native ARCH
uses a posix compatible script to find the native arch.
(based on ppigazzini's https://github.com/ppigazzini/stockfish-downloader )
use that native arch by default, no changes if ARCH is specified explicitly.

SF can now be compiled in an optimal way simply using

make -j profile-build

closes https://github.com/official-stockfish/Stockfish/pull/4777

No functional change
2023-09-22 19:06:37 +02:00
mstembera 97f706ecc1 Sparse impl of affine_transform_non_ssse3()
deal with the general case

About a 8.6% speedup (for general arch)

Results for 200 tests for each version:

            Base      Test      Diff
    Mean    141741    153998    -12257
    StDev   2990      3042      3742

p-value: 0.999
speedup: 0.086

closes https://github.com/official-stockfish/Stockfish/pull/4786

No functional change
2023-09-22 19:03:47 +02:00
peregrineshahin 0e32287af4 Reorder some lines
Now that qsearch has its own repetition detection we can flip the order of lines and remove the guard of depth < 0 which is not needed after reordering (i.e. it was there to prevent checking repetition again at depth ==0).

Passed STC:
https://tests.stockfishchess.org/tests/view/6502ecbb2cd016da89abc3fb
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 69536 W: 17668 L: 17490 D: 34378
Ptnml(0-2): 190, 7652, 18929, 7784, 213

Passed LTC:
https://tests.stockfishchess.org/tests/view/6505ce9072620bc881ea9086
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 52116 W: 13294 L: 13113 D: 25709
Ptnml(0-2): 26, 5176, 15471, 5361, 24

closes https://github.com/official-stockfish/Stockfish/pull/4791

No functional change
2023-09-22 19:02:18 +02:00
Stéphane Nicolet 3f7fb5ac1d Reformat some comments
Also include the bench to make Continuation Integration happy on Github.

Bench: 1603079
2023-09-11 23:19:06 +02:00
Sebastian Buchwald b9319c4fa4 Cleanup code after dropping ICC support in favor of ICX
The commit removes all uses of ICC's __INTEL_COMPILER macro and other
references to ICC. It also adds ICX info to the compiler command and
fixes two typos in Makefile's help output.

closes https://github.com/official-stockfish/Stockfish/pull/4769

No functional change
2023-09-11 22:46:01 +02:00
Linmiao Xu 3d1b067d85 Update default net to nn-1ee1aba5ed4c.nnue
Created by retraining the master net on a dataset composed by:
- adding Leela data from T60 jul-dec 2020, T77 nov 2021, T80 jun-jul 2023
- deduplicating and unminimizing parts of the dataset before interleaving

Trained initially with max epoch 800, then increased near the end of training
twice. First to 960, then 1200. After training, post-processing involved:
- greedy permuting L1 weights with https://github.com/official-stockfish/Stockfish/pull/4620
- greedy 2- and 3- cycle permuting with https://github.com/official-stockfish/Stockfish/pull/4640

  python3 easy_train.py \
    --experiment-name 2048-retrain-S6-sk28 \
    --training-dataset /data/S6.binpack \
    --early-fen-skipping 28 \
    --start-from-engine-test-net True \
    --max_epoch 1200 \
    --lr 4.375e-4 \
    --gamma 0.995 \
    --start-lambda 1.0 \
    --end-lambda 0.7 \
    --tui False \
    --seed $RANDOM \
    --gpus 0

In the list of datasets below, periods in the filename represent the sequence of
steps applied to arrive at the particular binpack. For example:

test77-dec2021-16tb7p.filter-v6-dd.min-mar2023.unminimized.binpack
1. test77 dec2021 data rescored with 16 TB of syzygy tablebases during data conversion
2. filtered with csv_filter_v6_dd.py - v6 filtering and deduplication in one step
3. minimized with the original mar2023 implementation of `minimize_binpack` in
   the tools branch
4. unminimized by removing all positions with score == 32002 (`VALUE_NONE`)

Binpacks were:
- filtered with: https://github.com/linrock/nnue-data
- unminimized with: https://github.com/linrock/Stockfish/tree/tools-unminify
- deduplicated with: https://github.com/linrock/Stockfish/tree/tools-dd

  DATASETS=(
    leela96-filt-v2.min.unminimized.binpack
    dfrc99-16tb7p-eval-filt-v2.min.unminimized.binpack

    # most of the 0dd1cebea57 v6-dd dataset (without test80-jul2022)
    # https://github.com/official-stockfish/Stockfish/pull/4606
    test60-novdec2021-12tb7p.filter-v6-dd.min-mar2023.unminimized.binpack
    test77-dec2021-16tb7p.filter-v6-dd.min-mar2023.unminimized.binpack
    test78-jantomay2022-16tb7p.filter-v6-dd.min-mar2023.unminimized.binpack
    test78-juntosep2022-16tb7p.filter-v6-dd.min-mar2023.unminimized.binpack
    test79-apr2022-16tb7p.filter-v6-dd.min-mar2023.unminimized.binpack
    test79-may2022-16tb7p.filter-v6-dd.min-mar2023.unminimized.binpack
    test80-jun2022-16tb7p.filter-v6-dd.min-mar2023.unminimized.binpack
    test80-aug2022-16tb7p.filter-v6-dd.min-mar2023.unminimized.binpack
    test80-sep2022-16tb7p.filter-v6-dd.min-mar2023.unminimized.binpack
    test80-oct2022-16tb7p.filter-v6-dd.min.binpack
    test80-nov2022-16tb7p.filter-v6-dd.min.binpack
    test80-jan2023-3of3-16tb7p.filter-v6-dd.min-mar2023.unminimized.binpack
    test80-feb2023-16tb7p.filter-v6-dd.min-mar2023.unminimized.binpack

    # older Leela data, recently converted
    test60-octnovdec2020-2tb7p.min.unminimized.binpack
    test60-julaugsep2020-2tb7p.min.binpack
    test77-nov2021-2tb7p.min.dd.binpack

    # newer Leela data
    test80-mar2023-2tb7p.min.unminimized.binpack
    test80-apr2023-2tb7p.filter-v6-sk16.min.unminimized.binpack
    test80-may2023-2tb7p.min.dd.binpack
    test80-jun2023-2tb7p.min.binpack
    test80-jul2023-2tb7p.binpack
  )
  python3 interleave_binpacks.py ${DATASETS[@]} /data/S6.binpack

Training data can be found at:
https://robotmoon.com/nnue-training-data/

Local elo at 25k nodes per move:
nn-epoch1059 : 2.7 +/- 1.6

Passed STC:
https://tests.stockfishchess.org/tests/view/64fc8d705dab775b5359db42
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 168352 W: 43216 L: 42704 D: 82432
Ptnml(0-2): 599, 19672, 43134, 20160, 611

Passed LTC:
https://tests.stockfishchess.org/tests/view/64fd44a75dab775b5359f065
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 154194 W: 39436 L: 38881 D: 75877
Ptnml(0-2): 78, 16577, 43238, 17120, 84

closes https://github.com/official-stockfish/Stockfish/pull/4782

Bench: 1603079
2023-09-11 22:37:39 +02:00
Michael Chaly ef22829616 Do more futility pruning in qsearch
This patch introduces a third futility pruning heuristic in qsearch. The idea is
that the static exchange evaluation is much worse than the difference between
futility base and alpha. Thus we can assume that the probability of the move
being good enough to beat alpha is low so it can be pruned.

Passed STC:
https://tests.stockfishchess.org/tests/view/64fc982a5dab775b5359dc83
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 36576 W: 9484 L: 9170 D: 17922
Ptnml(0-2): 121, 4119, 9495, 4431, 122

Passed LTC:
https://tests.stockfishchess.org/tests/view/64fcc7935dab775b5359e1a9
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 135408 W: 34556 L: 34041 D: 66811
Ptnml(0-2): 56, 14462, 38165, 14953, 68

closes https://github.com/official-stockfish/Stockfish/pull/4781

Bench: 1330793
2023-09-11 22:36:26 +02:00
cj5716 6d85f43e26 Simplify cutnode depth condition
With this patch, the depth condition for the cutnodes reduction is loosened from
tte->depth() >= depth + 3 to just tte->depth() >= depth.

Passed STC:
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 101152 W: 25830 L: 25682 D: 49640
Ptnml(0-2): 312, 11788, 26258, 11876, 342
https://tests.stockfishchess.org/tests/view/64fd15635dab775b5359eaa6

Passed LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 82542 W: 20980 L: 20824 D: 40738
Ptnml(0-2): 42, 8795, 23440, 8953, 41
https://tests.stockfishchess.org/tests/view/64fda3545dab775b5359fbf1

closes https://github.com/official-stockfish/Stockfish/pull/4780

Bench: 1479029
2023-09-11 22:30:57 +02:00
Sebastian Buchwald 46a5cedc11 Cleanup git checkout actions
We now fetch only the current commit for jobs that don't need the git
history. For the Prerelease job, we don't checkout the code at all.

closes https://github.com/official-stockfish/Stockfish/pull/4779

No functional change
2023-09-11 22:15:22 +02:00
Tomasz Sobczyk 1461d861c8 Prevent usage of AVX-512 for the last layer.
Add more static checks regarding the SIMD width match.

STC: https://tests.stockfishchess.org/tests/view/64f5c568a9bc5a78c669e70e
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 125216 W: 31756 L: 31636 D: 61824
Ptnml(0-2): 327, 13993, 33848, 14113, 327

Fixes a bug introduced in 2f2f45f, where with AVX-512 the weights and input to
the last layer were being read out of bounds. Now AVX-512 is only used for the
layers it can be used for. Additional static assertions have been added to
prevent more errors like this in the future.

closes https://github.com/official-stockfish/Stockfish/pull/4773

No functional change
2023-09-11 22:11:30 +02:00
Sebastian Buchwald a8b4fd1671 Avoid "using namespace std"
This is a cleanup PR that prepares the automatic checking of missing or
superfluous #include directives via the include-what-you-use (IWYU) tool
on the CI. Unfortunately, IWYU proposes additional includes for
"namespace std" although we don't need them.

To avoid the problem, the commit removes all "using namespace std"
statements from the code and directly uses the std:: prefix instead.
Alternatively, we could add specific usings (e.g. "using std::string")
foreach used type. Also, a mix of both approaches would be possible.
I decided for the prefix approach because most of the files were already
using the std:: prefixes despite the "using namespace std".

closes https://github.com/official-stockfish/Stockfish/pull/4772

No functional change
2023-09-11 22:07:55 +02:00
Stéphane Nicolet b25d68f6ee Introduce simple_eval() for lazy evaluations
This patch implements the pure materialistic evaluation called simple_eval()
to gain a speed-up during Stockfish search.

We use the so-called lazy evaluation trick: replace the accurate but slow
NNUE network evaluation by the super-fast simple_eval() if the position
seems to be already won (high material advantage). To guard against some
of the most obvious blunders introduced by this idea, this patch uses the
following features which will raise the lazy evaluation threshold in some
situations:

- avoid lazy evals on shuffling branches in the search tree
- avoid lazy evals if the position at root already has a material imbalance
- avoid lazy evals if the search value at root is already winning/losing.

Moreover, we add a small random noise to the simple_eval() term. This idea
(stochastic mobility in the minimax tree) was worth about 200 Elo in the pure
simple_eval() player on Lichess.

Overall, the current implementation in this patch evaluates about 2% of the
leaves in the search tree lazily.

--------------------------------------------

STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 60352 W: 15585 L: 15234 D: 29533
Ptnml(0-2): 216, 6906, 15578, 7263, 213
https://tests.stockfishchess.org/tests/view/64f1d9bcbd9967ffae366209

LTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 35106 W: 8990 L: 8678 D: 17438
Ptnml(0-2): 14, 3668, 9887, 3960, 24
https://tests.stockfishchess.org/tests/view/64f25204f5b0c54e3f04c0e7

verification run at VLTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 74362 W: 19088 L: 18716 D: 36558
Ptnml(0-2): 6, 7226, 22348, 7592, 9
https://tests.stockfishchess.org/tests/view/64f2ecdbf5b0c54e3f04d3ae

All three tests above were run with adjudication off, we also verified that
there was no regression on matetracker (thanks Disservin!).

----------------------------------------------

closes https://github.com/official-stockfish/Stockfish/pull/4771

Bench: 1393714
2023-09-03 09:28:16 +02:00
FauziAkram adf29b3fd6 Rename one variable
To enhance code clarity and prevent potential confusion with the
'r' variable assigned to reduction later in the code, this pull
request renames it to 'reductionScale' when we use the same name
in the reduction() function.

Using distinct variable names for separate functions improves code
readability and maintainability.

closes https://github.com/official-stockfish/Stockfish/pull/4765

No functional change
2023-09-03 09:10:27 +02:00
pb00067 1f7ff8406d Simplify slider_blocker calculation
Now that classical evaluation was removed, we can adapt this method
to the needs of set_check_info.

STC:
2.95 (-2.94,2.94) <-1.75,0.25>
Total: 298176 W: 75802 L: 75868 D: 146506
Ptnml(0-2): 908, 33608, 80192, 33402, 978
https://tests.stockfishchess.org/tests/view/64e70b899009777747557b43

closes https://github.com/official-stockfish/Stockfish/pull/4753

no functional change
2023-09-03 08:57:43 +02:00
Disservin 4f7fe255c7 Simplify README
The UCI protocol is rather technical and has little value in our README. Instead
it should be explained in our wiki. "Contributing" is moved above "Compiling
Stockfish" to make it more prominent.

Also move the CONTRIBUTING.md into the root directory and include it in the
distributed artifacts/releases.

closes https://github.com/official-stockfish/Stockfish/pull/4766

No functional change
2023-09-03 08:40:08 +02:00
Disservin 3c0e86a91e Cleanup includes
Reorder a few includes, include "position.h" where it was previously missing
and apply include-what-you-use suggestions. Also make the order of the includes
consistent, in the following way:

1. Related header (for .cpp files)
2. A blank line
3. C/C++ headers
4. A blank line
5. All other header files

closes https://github.com/official-stockfish/Stockfish/pull/4763
fixes https://github.com/official-stockfish/Stockfish/issues/4707

No functional change
2023-09-03 08:24:51 +02:00
ttruscott 8cd5cbf693 Omit two unneeded tests
These redundant tests were intended as a speed-up, but they do not seem
to provide any speed anymore.

STC: https://tests.stockfishchess.org/tests/view/64e9079c85e3e95030fd8259
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 134688 W: 34338 L: 34226 D: 66124
Ptnml(0-2): 426, 15122, 36124, 15258, 414

closes https://github.com/official-stockfish/Stockfish/pull/4767

No functional change
2023-09-03 08:07:59 +02:00
Stéphane Nicolet 4c4cb185aa Play turbulent when defending, simpler when attacking
This patch decays a little the evaluation (up to a few percent) for
positions which have a large complexity measure (material imbalance,
positional compensations, etc).

This may have nice consequences on the playing style, as it modifies
the search differently for attack and defense, both effects being
desirable:

- to see the effect on positions when Stockfish is defending, let us
suppose for instance that the side to move is Stockfish and the nnue
evaluation on the principal variation is -100 : this patch will decay
positions with an evaluation of -103 (say) to the same level, provided
they have huge material imbalance or huge positional compensation.
In other words, chaotic positions with an evaluation of -103 are now
comparable in our search tree to stable positions with an evaluation
of -100, and chaotic positions with an evaluation of -102 are now
preferred to stable positions with an evaluation of -100.

- the effect on positions when Stockfish is attacking is the opposite.
Let us suppose for instance that the side to move is Stockfish and the
nnue evaluation on the principal variation is +100 : this patch will
decay the evaluation to +97 if the positions on the principal variation
have huge material imbalance or huge positional compensation. In other
words, stable positions with an evaluation of +97 are now comparable
in our search tree to chaotic positions with an evaluation of +100,
and stable positions with an evaluation of +98 are now preferred to
chaotic positions with an evaluation of +100.

So the effect of this small change of evaluation on the playing style
is that Stockfish should now play a little bit more turbulent when
defending, and choose slightly simpler lines when attacking.

passed STC:
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 268448 W: 68713 L: 68055 D: 131680
Ptnml(0-2): 856, 31514, 68943, 31938, 973
https://tests.stockfishchess.org/tests/view/64e252bb99700912526653ed

passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 141060 W: 36066 L: 35537 D: 69457
Ptnml(0-2): 71, 15179, 39522, 15666, 92
https://tests.stockfishchess.org/tests/view/64e4447a9009777747553725

closes https://github.com/official-stockfish/Stockfish/pull/4762

Bench: 1426295
2023-08-24 08:11:17 +02:00
Shahin M. Shahin 440feecb4d Reduce repetitions branches
Increase reduction on retrying a move we just retreated that falls in a repetition:
if current move can be the same move from previous previous turn then we retreated
that move on the previous turn, this patch increases reduction if retrying that move
results in a repetition.

How to continue from there? Maybe we some variants of this idea could bring Elo too
(only testing the destination square, or triangulations, etc.)

Passed STC:
https://tests.stockfishchess.org/tests/view/64e1aede883cbb7cbd9ad976
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 424000 W: 108675 L: 107809 D: 207516
Ptnml(0-2): 1296, 47350, 113896, 48108, 1350

Passed LTC:
https://tests.stockfishchess.org/tests/view/64e32d629970091252666872
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 89682 W: 22976 L: 22569 D: 44137
Ptnml(0-2): 39, 8843, 26675, 9240, 44

closes https://github.com/official-stockfish/Stockfish/pull/4757

bench: 1574347
2023-08-22 11:32:51 +02:00
cj5716 030b87182a Do more full window searches
Remove the value < beta condition for doing full window searches.
As an added bonus the condition for full-window search is now much
more similar to other fail-soft engines.

Passed STC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 244608 W: 62286 L: 62294 D: 120028
Ptnml(0-2): 758, 28772, 63214, 28840, 720
https://tests.stockfishchess.org/tests/view/64d72d365b17f7c21c0e6675

Passed LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 311460 W: 78909 L: 78985 D: 153566
Ptnml(0-2): 129, 33959, 87656, 33831, 155
https://tests.stockfishchess.org/tests/view/64dca2265b17f7c21c0ee06c

closes https://github.com/official-stockfish/Stockfish/pull/4755

Bench: 1624221
2023-08-22 11:22:15 +02:00
Gian-Carlo Pascutto c6f62363a6 Simplify Square Clipped ReLU code.
Squared numbers are never negative, so barring any wraparound there
is no need to clamp to 0. From reading the code, there's no obvious
way to get wraparound, so the entire operation can be simplified
away. Updated original truncated code comments to be sensible.

Verified by running ./stockfish bench 128 1 24 and by the following test:

STC: https://tests.stockfishchess.org/tests/view/64da4db95b17f7c21c0eabe7
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 60224 W: 15425 L: 15236 D: 29563
Ptnml(0-2): 195, 6576, 16382, 6763, 196

closes https://github.com/official-stockfish/Stockfish/pull/4751

No functional change
2023-08-22 11:14:19 +02:00
Stéphane Nicolet 4c5919fa95 Fix some tabs in Makefile
Avoid mixing spaces and tabs for indentation in Makefile

closes https://github.com/official-stockfish/Stockfish/pull/4759

No functional change
2023-08-22 10:59:39 +02:00
Joost VandeVondele fe7353f702 Update links to fishtest
Fishtest has moved to https://github.com/official-stockfish/fishtest/

closes https://github.com/official-stockfish/Stockfish/pull/4758

No functional change
2023-08-22 10:53:49 +02:00
Matthies 9abef246a9 Allow compilation on Raspi (for ARMv8)
Current master fails to compile for ARMv8 on Raspi cause gcc (version 10.2.1)
does not like to cast between signed and unsigned vector types. This patch
fixes it by using unsigned vector pointer for ARM to avoid implicite cast.

closes https://github.com/official-stockfish/Stockfish/pull/4752

No functional change
2023-08-22 10:43:51 +02:00
Stéphane Nicolet a9a0dbbcd0 Fix some 'possible loss of data' warnings
Patch by Maxim Masiutin

closes https://github.com/official-stockfish/Stockfish/pull/4440

No functional change
2023-08-22 10:39:03 +02:00
Disservin 46756996e7 Add -funroll-loops to CXXFLAGS
Optimize profiling data accuracy by enabling -funroll-loops during the profile
generation phase, in addition to its default activation by -fprofile-use.
This seems to produce a slightly faster binary, for most compilers.

make -j profile-build ARCH=x86-64-avx2

sf_base =  1392875 +/-   5905 (95%)
sf_test =  1402332 +/-   7303 (95%)
diff    =     9457 +/-   4413 (95%)
speedup = 0.67896% +/- 0.317% (95%)

STC:
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 34784 W: 8970 L: 8665 D: 17149
Ptnml(0-2): 115, 3730, 9405, 4019, 123
https://tests.stockfishchess.org/tests/view/64d944815b17f7c21c0e92e1

closes https://github.com/official-stockfish/Stockfish/pull/4750

No functional change
2023-08-16 21:25:42 +02:00
Muzhen Gaming fe0dca12f1 Simplify PvNode Reduction
Remove the depth condition for PvNode reduction.

Simplification STC:
https://tests.stockfishchess.org/tests/view/64d308fa5b17f7c21c0e0303
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 38976 W: 10106 L: 9889 D: 18981
Ptnml(0-2): 129, 4479, 10040, 4726, 114

Simplification LTC:
https://tests.stockfishchess.org/tests/view/64d457db5b17f7c21c0e236f
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 156402 W: 39727 L: 39645 D: 77030
Ptnml(0-2): 71, 17143, 43696, 17215, 76

closes https://github.com/official-stockfish/Stockfish/pull/4747

Bench: 1493904
2023-08-16 21:24:58 +02:00
SzilBalazs 3e5a817fd2 Fix dead link to compression algorithm in tbprobe
closes https://github.com/official-stockfish/Stockfish/pull/4746

No functional change
2023-08-16 21:24:58 +02:00
Disservin a77a8448ff Add CONTRIBUTING.md
closes https://github.com/official-stockfish/Stockfish/pull/4741

No functional change
2023-08-16 21:24:54 +02:00
mstembera 9b80897657 Simplify material difference in evaluate
STC: https://tests.stockfishchess.org/tests/view/64d166235b17f7c21c0ddc15
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 100032 W: 25698 L: 25547 D: 48787
Ptnml(0-2): 308, 11748, 25771, 11863, 326

LTC: https://tests.stockfishchess.org/tests/view/64d28c085b17f7c21c0df775
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 123870 W: 31463 L: 31348 D: 61059
Ptnml(0-2): 63, 13487, 34719, 13604, 62

Besides rebasing I replaced PawnValueMg w/ 126 explicitly to decouple from https://tests.stockfishchess.org/tests/view/64d212de5b17f7c21c0debbb by @peregrineshahin which also passed. #4734

closes https://github.com/official-stockfish/Stockfish/pull/4731

Bench: 1447866
2023-08-13 11:59:06 +02:00
Shahin M. Shahin 3322349c1a Simplify pieceValue to one phase.
Simplifies the usage of pieceValues to mg values with the exception of pawnValues, After the removal of PSQT.

passed STC:
https://tests.stockfishchess.org/tests/view/64d147845b17f7c21c0dd86c
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 197248 W: 50168 L: 50125 D: 96955
Ptnml(0-2): 651, 23029, 51222, 23070, 652

passed LTC:
https://tests.stockfishchess.org/tests/view/64d212de5b17f7c21c0debbb
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 181170 W: 45949 L: 45893 D: 89328
Ptnml(0-2): 84, 19656, 51052, 19706, 87

closes https://github.com/official-stockfish/Stockfish/pull/4734

Bench: 1494401
2023-08-13 11:58:08 +02:00
Stéphane Nicolet 495852fecd Simplify SEE pruning for captures
It seems that the current search is smart enough to allow us to remove
(again) the block of code that checks for discovered attacks after the
first pruning condition for captures.

STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 278848 W: 70856 L: 70903 D: 137089
Ptnml(0-2): 960, 32829, 71894, 32780, 961
https://tests.stockfishchess.org/tests/view/64d0af095b17f7c21c0dc440

LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 100704 W: 25564 L: 25425 D: 49715
Ptnml(0-2): 56, 10858, 28381, 11005, 52
https://tests.stockfishchess.org/tests/view/64d293e85b17f7c21c0df844

closes https://github.com/official-stockfish/Stockfish/pull/4736

Bench: 1470572
2023-08-13 11:52:47 +02:00
FauziAkram c02ee70927 Simplify prior countermove bonus
Swapping a multiplication operation between two terms with a simple constant

Passed STC:
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 60512 W: 15424 L: 15231 D: 29857
Ptnml(0-2): 200, 6985, 15712, 7140, 219
https://tests.stockfishchess.org/tests/view/64d2addf5b17f7c21c0dfae6

Passed LTC:
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 108456 W: 27545 L: 27414 D: 53497
Ptnml(0-2): 63, 11629, 30698, 11790, 48
https://tests.stockfishchess.org/tests/view/64d3ab6e5b17f7c21c0e1188

closes https://github.com/official-stockfish/Stockfish/pull/4738

Bench: 1636213
2023-08-13 11:48:32 +02:00
ppigazzini 796d9df643 Check compiler for docker builds in CI
closes https://github.com/official-stockfish/Stockfish/pull/4739

No functional change
2023-08-13 11:47:52 +02:00
Gabrik 84e97a38a3 Remove the unused enum ScaleFactor
closes https://github.com/official-stockfish/Stockfish/pull/4740

No functional change
2023-08-13 11:46:48 +02:00
Shahin M. Shahin b7b7a3f3fa Detect repetitions before they happen in qsearch
Passed STC:
https://tests.stockfishchess.org/tests/view/64d495995b17f7c21c0e29ed
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 340288 W: 86664 L: 85910 D: 167714
Ptnml(0-2): 1030, 38855, 89697, 39455, 1107

Passed LTC:
https://tests.stockfishchess.org/tests/view/64d5e1085b17f7c21c0e4ab5
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 193230 W: 49235 L: 48606 D: 95389
Ptnml(0-2): 98, 20432, 54921, 21071, 93

closes https://github.com/official-stockfish/Stockfish/pull/4742

Bench: 1579576
2023-08-13 11:44:17 +02:00
cj5716 222f3ea55b Simplify a depth condition
As the negative extension term has sensitive scaling, it would make more sense to allow more negative extension also at lower depth, and not just a region between low and high depth.

Passed STC:
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 124096 W: 31611 L: 31485 D: 61000
Ptnml(0-2): 422, 14437, 32205, 14561, 423
https://tests.stockfishchess.org/tests/view/64d205d75b17f7c21c0dea82

Passed LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 387882 W: 97840 L: 97993 D: 192049
Ptnml(0-2): 198, 42004, 109668, 41895, 176
https://tests.stockfishchess.org/tests/view/64d333f85b17f7c21c0e06c6

closes https://github.com/official-stockfish/Stockfish/pull/4743

Bench: 1542357
2023-08-13 11:40:35 +02:00
Michael Chaly d97a02ea2b Give extra bonus to main history for moves that caused a fail low. #4744
Current master gives this type of bonuses to continuation history, this patch also gives them to main history.

Passed STC:
https://tests.stockfishchess.org/tests/view/64d4802a5b17f7c21c0e27b3
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 480768 W: 122767 L: 121798 D: 236203
Ptnml(0-2): 1563, 56190, 123834, 57309, 1488

Passed LTC:
https://tests.stockfishchess.org/tests/view/64d7e4c05b17f7c21c0e7456
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 32052 W: 8329 L: 8022 D: 15701
Ptnml(0-2): 19, 3335, 9015, 3634, 23

closes https://github.com/official-stockfish/Stockfish/pull/4744

Bench: 1711793
2023-08-13 11:38:24 +02:00
Joost VandeVondele 4be94f41a6 Update sanitizer CI to ubuntu 22.04
might fix the tsan errors

closes https://github.com/official-stockfish/Stockfish/pull/4745

No functional change
2023-08-13 11:34:00 +02:00
Joost VandeVondele 8192945870 Improve testing coverage, remove unused code
a) Add further tests to CI to cover most features. This uncovered a potential race
in case setoption was sent between two searches. As the UCI protocol requires
this sent to be went the engine is not searching, setoption now ensures that
this is the case.

b) Remove some unused code

closes https://github.com/official-stockfish/Stockfish/pull/4730

No functional change
2023-08-11 19:27:46 +02:00
Tomasz Sobczyk 0d2ddb81ef Fix Makefile for incorrect nnue file
If an incorrect network file is present at the start of the compilation stage, the
Makefile script now correctly removes it before trying to download a clean version.

closes https://github.com/official-stockfish/Stockfish/pull/4726

No functional change
2023-08-11 19:20:29 +02:00
Cody Ho e64b817e0a Remove all references to Score type
Score is obsolete with the removal of psqt.

No functional change.

Signed-off-by: Cody Ho <codyho@stanford.edu>

closes https://github.com/official-stockfish/Stockfish/pull/4724
2023-08-09 18:27:16 +02:00
Michael Chaly 5c2111cc30 Adjust futility pruning base in qsearch
Current master used value from transposition table there if it existed,
this patch uses minimum between this tt value and the static eval instead
(this thus is closer to the main search function, which uses the static eval).

Passed STC:
https://tests.stockfishchess.org/tests/view/64cd57285b17f7c21c0d6a8c
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 252544 W: 64671 L: 64039 D: 123834
Ptnml(0-2): 839, 29207, 65575, 29785, 866

Passed LTC:
https://tests.stockfishchess.org/tests/view/64cf6c915b17f7c21c0d9fcb
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 60150 W: 15374 L: 15012 D: 29764
Ptnml(0-2): 24, 6321, 17024, 6681, 25

closes https://github.com/official-stockfish/Stockfish/pull/4725

Bench: 1573024
2023-08-07 07:24:11 +02:00
FauziAkram a26f8d37e1 Tweak formula for pruning moves losing material
Simplify the "Prune moves with negative SEE" formula,
by removing one multiplication and subtraction operation.

Passed STC:
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 214272 W: 54596 L: 54572 D: 105104
Ptnml(0-2): 741, 25160, 55320, 25164, 751
https://tests.stockfishchess.org/tests/view/64c430d1dc56e1650abbdbf6

Passed LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 238380 W: 60600 L: 60601 D: 117179
Ptnml(0-2): 132, 26069, 66791, 26064, 134
https://tests.stockfishchess.org/tests/view/64c81f155b17f7c21c0cee2b

closes https://github.com/official-stockfish/Stockfish/pull/4721

bench: 1655337
2023-08-06 22:25:58 +02:00
Linmiao Xu 0ad9b51dea Remove classical psqt
Based on vondele's deletepsqt branch:
https://github.com/vondele/Stockfish/commit/369f5b051

This huge simplification uses a weighted material differences instead of
the positional piece square tables (psqt) in the semi-classical complexity
calculation. Tuned weights using spsa at 45+0.45 with:

int pawnMult = 100;
int knightMult = 325;
int bishopMult = 350;
int rookMult = 500;
int queenMult = 900;
TUNE(SetRange(0, 200), pawnMult);
TUNE(SetRange(0, 650), knightMult);
TUNE(SetRange(0, 700), bishopMult);
TUNE(SetRange(200, 800), rookMult);
TUNE(SetRange(600, 1200), queenMult);

The values obtained via this tuning session were for a model where
the psqt replacement formula was always from the point of view of White,
even if the side to move was Black. We re-used the same values for an
implementation with a psqt replacement from the point of view of the side
to move, testing the result both on our standard book on positions with
a strong White bias, and an alternate book with positions with a strong
Black bias.

We note that with the patch the last use of the venerable "Score" type
disappears in Stockfish codebase (the Score type was used in classical
evaluation to get a tampered eval interpolating values smoothly from the
early midgame stage to the endgame stage). We leave it to another commit
to clean all occurrences of Score in the code and the comments.

-------

Passed non-regression LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 142542 W: 36264 L: 36168 D: 70110
Ptnml(0-2): 76, 15578, 39856, 15696, 65
https://tests.stockfishchess.org/tests/view/64c8cb495b17f7c21c0cf9f8

Passed non-regression LTC (with a book with Black bias):
https://tests.stockfishchess.org/tests/view/64c8f9295b17f7c21c0cfdaf
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 494814 W: 125565 L: 125827 D: 243422
Ptnml(0-2): 244, 53926, 139346, 53630, 261

------

closes https://github.com/official-stockfish/Stockfish/pull/4713

Bench: 1655985
2023-08-06 22:16:52 +02:00
AndrovT a6d9a302b8 Implement AffineTransformSparseInput for armv8
Implements AffineTransformSparseInput layer for the NNUE evaluation
for the armv8 and armv8-dotprod architectures. We measured some nice
speed improvements via 10 runs of our benchmark:

armv8, Cortex-X1                  :   18.5% speed-up
armv8, Cortex-A76                 :   13.2% speed-up
armv8-dotprod, Cortex-X1          :   27.1% speed-up
armv8-dotprod, Cortex-A76         :   12.1% speed-up
armv8, Cortex-A72, Raspberry Pi 4 :    8.2% speed-up (thanks Torom!)

closes https://github.com/official-stockfish/Stockfish/pull/4719

No functional change
2023-08-06 21:22:37 +02:00
ppigazzini 4c43e1e27c Add new CPU archs in CI Tests workflow
Add CPU archs: armv8-dotprod, riscv64 and ppc64le.
The last two archs are built using QEMU multiarch docker container.

References:
https://docs.docker.com/build/building/multi-platform/
https://github.com/docker/setup-buildx-action
https://github.com/docker/setup-qemu-action
https://github.com/tonistiigi/binfmt
https://stackoverflow.com/questions/72444103/what-does-running-the-multiarch-qemu-user-static-does-before-building-a-containe

closes https://github.com/official-stockfish/Stockfish/pull/4718

No functional change
2023-08-06 21:17:33 +02:00
Niklas Fiekas 002a50457c Identify NEON_DOTPROD in compiler_info()
closes https://github.com/official-stockfish/Stockfish/pull/4712

No functional change
2023-08-06 21:14:39 +02:00
rn5f107s2 65ece7d985 Malus during move ordering for putting pieces en prise
The original idea is the reverse of a previous patch [1] which added bonuses
in our move picker to moves escaping threats. In this patch, in addition to
bonuses for evading threats, we apply penalties to moves moving to threatened
squares.

Further tweaks of that basic idea resulted in this specific version which
further increases the penalty of moves moving to squares threatend depending
on the piece threatening it. So for example a queen moving to a square attacked
by a pawn would receive a larger penalty than a queen moving to square attacked
by a rook.

[1]: https://github.com/official-stockfish/Stockfish/commit/08e0f52b77edb929989c68c49e954b9bc5d7d67e

--------

Passed STC:
https://tests.stockfishchess.org/tests/live_elo/64c11269dc56e1650abb935d
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 95552 W: 24654 L: 24250 D: 46648
Ptnml(0-2): 322, 11098, 24562, 11442, 352

Passed LTC:
https://tests.stockfishchess.org/tests/live_elo/64c2004ddc56e1650abba8b3
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 190230 W: 48806 L: 48178 D: 93246
Ptnml(0-2): 90, 20439, 53453, 21019, 114

-------

closes https://github.com/official-stockfish/Stockfish/pull/4711

Bench: 1350831
2023-07-29 00:56:26 +02:00
Stéphane Nicolet f84eb1f3ef Improve some comments
- clarify the examples for the bench command
- typo  in search.cpp

closes https://github.com/official-stockfish/Stockfish/pull/4710

No functional change
2023-07-28 23:38:49 +02:00
mstembera cb22520a9c Remove unused return type from propagate()
Also make two get_weight_index() static methods constexpr, for
consistency with the other static get_hash_value() method right above.
Tested for speed by user Torom (thanks).

closes https://github.com/official-stockfish/Stockfish/pull/4708

No functional change
2023-07-28 23:24:42 +02:00
FauziAkram 2667316ffc Simplify one multicut extension
Simplify away the ttValue <= alpha extension in the multicut block.

Passed STC:
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 318336 W: 81307 L: 81398 D: 155631
Ptnml(0-2): 1088, 37291, 82469, 37264, 1056
https://tests.stockfishchess.org/tests/view/64b8589fdc56e1650abad61d

Passed LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 89388 W: 22925 L: 22775 D: 43688
Ptnml(0-2): 34, 9635, 25210, 9777, 38
https://tests.stockfishchess.org/tests/view/64bc41d0dc56e1650abb29cb

closes https://github.com/official-stockfish/Stockfish/pull/4709

bench: 1604592
2023-07-25 16:43:35 +02:00
Stephen Touset 027713c4b4 Remove Zobrist::noPawns
Zobrist::noPawns is no longer used.

closes https://github.com/official-stockfish/Stockfish/pull/4344

no functional change
2023-07-25 00:13:38 +02:00
Stefan Geschwentner 76e1e8fd39 Simplify TT cutoff
Remove the exact bound condition from TT depth check.

STC:
https://tests.stockfishchess.org/tests/view/64b30b320cdec37b957359e9
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 332928 W: 84895 L: 85003 D: 163030
Ptnml(0-2): 1242, 39200, 85604, 39260, 1158

LTC:
https://tests.stockfishchess.org/tests/view/64b74e2adc56e1650abac0b6
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 92946 W: 23628 L: 23482 D: 45836
Ptnml(0-2): 38, 10033, 26192, 10165, 45

closes https://github.com/official-stockfish/Stockfish/pull/4702

Bench: 1601764
2023-07-24 02:23:43 +02:00
windfishballad 78e3d2ad78 Simplify some qsearch conditions
Use the assert which ensures that beta == alpha+1 at PVNodes
to simplify a little bit the conditions further down in the code.

passed STC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 56160 W: 14370 L: 14173 D: 27617
Ptnml(0-2): 210, 6192, 15076, 6395, 207
https://tests.stockfishchess.org/tests/view/64bc769cdc56e1650abb2e26

closes https://tests.stockfishchess.org/tests/view/64bc769cdc56e1650abb2e26

No functional change
2023-07-24 02:09:44 +02:00
Joost VandeVondele 4b2979760f Check clock more often
This patch changes the frequency with which the time is checked, changing
frequency from every 1024 counted nodes to every 512 counted nodes. The
master value was tuned for the old classical eval, the patch takes the
roughly 2x slowdown in nps with SFNNUEv7 into account. This could reduce
a bit the losses on time on fishtest, but they are probably unrelated.

passed STC:
https://tests.stockfishchess.org/tests/view/64bb8ae5dc56e1650abb1b11
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 76576 W: 19677 L: 19501 D: 37398
Ptnml(0-2): 274, 8592, 20396, 8736, 290

closes https://github.com/official-stockfish/Stockfish/pull/4704

No functional change
2023-07-24 01:56:20 +02:00
Michael Chaly 5ea1cbc778 Do more futility pruning for cutNodes that are not in TT
This is somewhat similar to IIR for cutnodes but instead of reducing
depth for cutnodes that don't have tt move we reduce margin multiplier
in futility pruning for cutnodes that are not in TT.

Passed STC:
https://tests.stockfishchess.org/tests/view/64b244b90cdec37b95734c5b
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 75552 W: 19404 L: 19029 D: 37119
Ptnml(0-2): 233, 8806, 19378, 9071, 288

Passed LTC:
https://tests.stockfishchess.org/tests/view/64b3ae5a0cdec37b95736516
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 104988 W: 27152 L: 26697 D: 51139
Ptnml(0-2): 41, 11259, 29446, 11700, 48

closes https://github.com/official-stockfish/Stockfish/pull/4700

bench 1727577
2023-07-19 21:40:38 +02:00
mstembera 1444837887 Remove inline assembly
closes https://github.com/official-stockfish/Stockfish/pull/4698

No functional change
2023-07-19 21:39:51 +02:00
Cody Ho 3fe0d5c533 Unused code cleanup
closes https://github.com/official-stockfish/Stockfish/pull/4696

No functional change
2023-07-19 21:38:39 +02:00
Jorge 6abd0bd9fb Add CodeQL workflow
add CI tooling to detect security bugs.

closes https://github.com/official-stockfish/Stockfish/pull/4659

No functional change
2023-07-19 21:36:38 +02:00
rn5f107s2 42d28424bc Removes a few Bitboards and functions
No longer used

closes https://github.com/official-stockfish/Stockfish/pull/4695

No functional change
2023-07-18 08:10:11 +02:00
Robert Nurnberg @ elitebook 6a31f54d3c remove evalType from bench
no longer used

closes https://github.com/official-stockfish/Stockfish/pull/4694

No functional change
2023-07-18 08:09:52 +02:00
Joost VandeVondele 34d0c1b527 Switch to macos 13 for CI
allows for building x86-64-avx2 and x86-64-bmi2 binaries for mac

install coreutils
show hardware capabilities as seen by the compilers
move some tests from sse41 to avx2 as platforms support it

closes https://github.com/official-stockfish/Stockfish/pull/4692

No functional change
2023-07-16 22:27:13 +02:00
Joost VandeVondele d70a905ce3 Deprecate the x86-64-modern arch
Explicitly describe the architecture as deprecated,
it remains available as its current alias x86-64-sse41-popcnt

CPUs that support just this instruction set are now years old,
any few years old Intel or AMD CPU supports x86-64-avx2. However,
naming things 'modern' doesn't age well, so instead use explicit names.

Adjust CI accordingly. Wiki, fishtest, downloader done as well.

closes https://github.com/official-stockfish/Stockfish/pull/4691

No functional change.
2023-07-16 17:47:25 +02:00
Michael Chaly 913574f421 Remove improvement variable
No longer used in a meaningful way.
Improve comments.

Closes https://github.com/official-stockfish/Stockfish/pull/4688

No functional change
2023-07-16 15:18:41 +02:00
maxim 18fdc2df3c Remove pawnKey from StateInfo
Remove pawnKey since it is not used anymore.

Passed Non-regression STC:
https://tests.stockfishchess.org/tests/view/64b023110cdec37b9573265c
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 334848 W: 85440 L: 85545 D: 163863
Ptnml(0-2): 1134, 38101, 89075, 37964, 1150

closes https://github.com/official-stockfish/Stockfish/pull/4687

No functional change
2023-07-16 15:16:14 +02:00
Joost VandeVondele e8a5c64988 Consolidate to centipawns conversion
avoid doing this calculations in multiple places.

closes https://github.com/official-stockfish/Stockfish/pull/4686

No functional change
2023-07-16 15:14:50 +02:00
Joost VandeVondele e89469925d Remove some CI parts not yet working
downgrading compiler didn't work for windows build. Stick to gcc 13 for now.
Windows x86-32 not a 32bit binary, remove.

closes https://github.com/official-stockfish/Stockfish/pull/4685

No functional change
2023-07-16 15:13:24 +02:00
AndrovT a42ab95e1f remove large input specialization
Removes unused large input specialization for dense affine transform. It has been obsolete since #4612 was merged.

closes https://github.com/official-stockfish/Stockfish/pull/4684

No functional change
2023-07-16 15:12:21 +02:00
Linmiao Xu ee53f8ed2f Reintroduce nnue eval pawn count multipliers again
With separate multipliers for nnue eval and optimism scaling.
This patch used 4 out of 7 params tuned with spsa at 30+0.3
using this tuning config:

Value LazyThreshold1 = Value(3622);
Value LazyThreshold2 = Value(1962);
int psqThresh = 2048;
int nnueNpmBase = 945;
int nnuePcMult = 0;
int optNpmBase = 150;
int optPcMult = 0;
TUNE(SetRange(3322, 3922), LazyThreshold1);
TUNE(SetRange(1662, 2262), LazyThreshold2);
TUNE(SetRange(1748, 2348), psqThresh);
TUNE(SetRange(745, 1145), nnueNpmBase);
TUNE(SetRange(-16, 16), nnuePcMult);
TUNE(SetRange(0, 300), optNpmBase);
TUNE(SetRange(-16, 16), optPcMult);

Passed STC:
https://tests.stockfishchess.org/tests/view/64a5a9b402cd07745c60ed07
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 173632 W: 44417 L: 43903 D: 85312
Ptnml(0-2): 547, 20025, 45068, 20719, 457

Passed LTC:
https://tests.stockfishchess.org/tests/view/64a972a302cd07745c6136af
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 277644 W: 70955 L: 70147 D: 136542
Ptnml(0-2): 193, 29902, 77787, 30784, 156

closes https://github.com/official-stockfish/Stockfish/pull/4681

bench 1556301
2023-07-15 09:16:09 +02:00
Joost VandeVondele a3a91f3f9f Build and test more binaries in CI
use a fixed compiler on Linux and Windows (right now gcc 11).
build avxvnni on Windows (Linux needs updated core utils)
build x86-32 on Linux (Windows needs other mingw)
fix a Makefile issue where a failed PGOBENCH would not stop the build
reuse the WINE_PATH for SDE as we do for QEMU
use WINE_PATH variable also for the signature
verify the bench for each of the binaries
do not build x86-64-avx2 on macos

closes https://github.com/official-stockfish/Stockfish/pull/4682

No functional change
2023-07-15 09:15:16 +02:00
FauziAkram acdbf45171 Use more expressive names for bonus1 and bonus2
closes https://github.com/official-stockfish/Stockfish/pull/4683

No functional change
2023-07-15 09:13:02 +02:00
Joost VandeVondele f5ab5832c6 Generate binaries for more advanced architectures
use intel's Software Development Emulator (SDE) in the actions that build the binaries.
This allows for building on Windows and Linux binaries for
- x86-64-avx512
- x86-64-vnni256
- x86-64-vnni512

(x86-64-avxvnni needs more recent gcc in the actions)

also build x86-64-avx2 on macos.

closes https://github.com/official-stockfish/Stockfish/pull/4679

No functional change
2023-07-13 08:21:17 +02:00
mstembera 529d3be8e2 More simplifications and cleanup in affine_transform_sparse_input.h
closes https://github.com/official-stockfish/Stockfish/pull/4677

No functional change
2023-07-13 08:20:33 +02:00
Sebastian Buchwald f972947492 Cleanup code after removal of classical evaluation
This includes the following changes:
- Remove declaration of removed global variable
- Adapt string that mentions removed UCI option

closes https://github.com/official-stockfish/Stockfish/pull/4675

No functional change
2023-07-13 08:19:37 +02:00
Joost VandeVondele af110e02ec Remove classical evaluation
since the introduction of NNUE (first released with Stockfish 12), we
have maintained the classical evaluation as part of SF in frozen form.
The idea that this code could lead to further inputs to the NN or
search did not materialize. Now, after five releases, this PR removes
the classical evaluation from SF. Even though this evaluation is
probably the best of its class, it has become unimportant for the
engine's strength, and there is little need to maintain this
code (roughly 25% of SF) going forward, or to expend resources on
trying to improve its integration in the NNUE eval.

Indeed, it had still a very limited use in the current SF, namely
for the evaluation of positions that are nearly decided based on
material difference, where the speed of the classical evaluation
outweights its inaccuracies. This impact on strength is small,
roughly 2Elo, and probably decreasing in importance as the TC grows.

Potentially, removal of this code could lead to the development of
techniques to have faster, but less accurate NN evaluation,
for certain positions.

STC
https://tests.stockfishchess.org/tests/view/64a320173ee09aa549c52157
Elo: -2.35 ± 1.1 (95%) LOS: 0.0%
Total: 100000 W: 24916 L: 25592 D: 49492
Ptnml(0-2): 287, 12123, 25841, 11477, 272
nElo: -4.62 ± 2.2 (95%) PairsRatio: 0.95

LTC
https://tests.stockfishchess.org/tests/view/64a320293ee09aa549c5215b
 Elo: -1.74 ± 1.0 (95%) LOS: 0.0%
Total: 100000 W: 25010 L: 25512 D: 49478
Ptnml(0-2): 44, 11069, 28270, 10579, 38
nElo: -3.72 ± 2.2 (95%) PairsRatio: 0.96

VLTC SMP
https://tests.stockfishchess.org/tests/view/64a3207c3ee09aa549c52168
 Elo: -1.70 ± 0.9 (95%) LOS: 0.0%
Total: 100000 W: 25673 L: 26162 D: 48165
Ptnml(0-2): 8, 9455, 31569, 8954, 14
nElo: -3.95 ± 2.2 (95%) PairsRatio: 0.95

closes https://github.com/official-stockfish/Stockfish/pull/4674

Bench: 1444646
2023-07-11 22:56:49 +02:00
Muzhen Gaming 6a8767a0d5 Simplify PvNode reduction
Simplification STC: https://tests.stockfishchess.org/tests/view/64a415803ee09aa549c539c3
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 37856 W: 9719 L: 9504 D: 18633
Ptnml(0-2): 98, 4277, 9977, 4464, 112

Simplification LTC: https://tests.stockfishchess.org/tests/view/64a5ffe202cd07745c60f360
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 55878 W: 14323 L: 14138 D: 27417
Ptnml(0-2): 21, 5993, 15732, 6166, 27

closes https://github.com/official-stockfish/Stockfish/pull/4673

Bench: 2604965
2023-07-11 22:55:00 +02:00
Joost VandeVondele ee023d7fd7 Fix CI output
closes https://github.com/official-stockfish/Stockfish/pull/4669

No functional change
2023-07-11 22:53:15 +02:00
Linmiao Xu e699fee513 Update default net to nn-c38c3d8d3920.nnue
This was a later epoch from the same experiment that led to the
previous master net. After training, it was prepared the same way:

1. greedy permuting L1 weights with https://github.com/official-stockfish/Stockfish/pull/4620
2. leb128 compression with https://github.com/glinscott/nnue-pytorch/pull/251
3. greedy 2- and 3- cycle permuting with https://github.com/official-stockfish/Stockfish/pull/4640

Local elo at 25k nodes per move (vs. L1-1536 nn-fdc1d0fe6455.nnue):
nn-epoch739.nnue : 20.2 +/- 1.7

Passed STC:
https://tests.stockfishchess.org/tests/view/64a050b33ee09aa549c4e4c8
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 195552 W: 49977 L: 49430 D: 96145
Ptnml(0-2): 556, 22775, 50607, 23242, 596

Passed LTC:
https://tests.stockfishchess.org/tests/view/64a127bd3ee09aa549c4f60c
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 235452 W: 60327 L: 59609 D: 115516
Ptnml(0-2): 119, 25173, 66426, 25887, 121

closes https://github.com/official-stockfish/Stockfish/pull/4666

bench 2427629
2023-07-06 23:03:58 +02:00
Joost VandeVondele 9ba24912c1 Add armv8-dotprod to CI binaries
also generate binaries for more recent Android hardware.

closes https://github.com/official-stockfish/Stockfish/pull/4663

No functional change
2023-07-06 23:03:16 +02:00
mstembera f8e65d82eb Simplify away lookup_count.
https://tests.stockfishchess.org/tests/view/64a3c1a93ee09aa549c53167
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 32832 W: 8497 L: 8280 D: 16055
Ptnml(0-2): 80, 3544, 8967, 3729, 96

closes https://github.com/official-stockfish/Stockfish/pull/4662

No functional change
2023-07-06 23:02:11 +02:00
Joost VandeVondele 19e2a88504 Revise extract bench from git log in CI
order commits differently

closes https://github.com/official-stockfish/Stockfish/pull/4668

No functional change
2023-07-06 23:01:27 +02:00
ppigazzini e87e103ca9 Remove leftover braces for if conditional in CI
closes https://github.com/official-stockfish/Stockfish/pull/4660

No functional change
2023-07-03 20:17:14 +02:00
ppigazzini ca5d9a5ff0 Extract bench according to wiki instructions
- loop through the commits starting from the latest one
- read the bench value from the last match, if any, of the template
  in the commit body text

closes https://github.com/official-stockfish/Stockfish/pull/4627

No functional change
2023-07-03 19:07:06 +02:00
rn5f107s2 95ce443aaa simplified gives check castling
tested verifying perft and bench is unchanged
on a larger set of epds for both standard and FRC chess.

Passed non-regression STC:
https://tests.stockfishchess.org/tests/live_elo/648587be65ffe077ca123d78
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 153632 W: 41015 L: 40928 D: 71689
Ptnml(0-2): 377, 16077, 43816, 16174, 372

closes https://github.com/official-stockfish/Stockfish/pull/4628

No functional change
2023-07-03 18:54:22 +02:00
FauziAkram 9cd563cb54 Improving grammar and readability of comments
closes https://github.com/official-stockfish/Stockfish/pull/4643

No functional change
2023-07-03 18:38:41 +02:00
Muzhen Gaming 5f8480a730 Simplify score improvement reduction
Reduce depth by 2 based on score improvement, only for depths 3 to 11.

Simplification STC: https://tests.stockfishchess.org/tests/view/64929a53dc7002ce609c7807
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 238912 W: 63466 L: 63468 D: 111978
Ptnml(0-2): 564, 26262, 65805, 26262, 563

Simplification LTC: https://tests.stockfishchess.org/tests/view/64942e47dc7002ce609c9e07
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 64452 W: 17485 L: 17320 D: 29647
Ptnml(0-2): 19, 6161, 19706, 6316, 24

closes https://github.com/official-stockfish/Stockfish/pull/4637

Bench: 2740142
2023-07-03 18:33:27 +02:00
Muzhen Gaming eb9aaf9489 Simplify away improvement term in null move search
passed STC:
https://tests.stockfishchess.org/tests/view/649c0d2edc7002ce609d33b5
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 271104 W: 72181 L: 72217 D: 126706
Ptnml(0-2): 691, 30042, 74129, 29992, 698

passed LTC:
https://tests.stockfishchess.org/tests/view/649d0dd7dc7002ce609d4efa
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 183120 W: 49469 L: 49418 D: 84233
Ptnml(0-2): 84, 17636, 56063, 17699, 78

closes https://github.com/official-stockfish/Stockfish/pull/4650

Bench: 2642851
2023-07-03 18:27:33 +02:00
peregrineshahin fa143922ae Fix pruning to (in TB loss) in Null move pruning.
Current logic can apply Null move pruning
on a dead-lost position returning an unproven loss
(i.e. in TB loss score or mated in losing score) on nonPv nodes.

on a default bench, this can be observed by adding this debugging line:
```
if (nullValue >= beta)
{
    // Do not return unproven mate or TB scores
    nullValue = std::min(nullValue, VALUE_TB_WIN_IN_MAX_PLY-1);
    dbg_hit_on(nullValue <= VALUE_TB_LOSS_IN_MAX_PLY); // Hit #0: Total 73983 Hits 1 Hit Rate (%) 0.00135166
    if (thisThread->nmpMinPly || depth < 14)
        return nullValue;
```

This fixes this very rare issue (happens at ~0.00135166% of the time) by
eliminating the need to try Null Move Pruning with dead-lost positions
and leaving it to be determined by a normal searching flow.

The previous try to fix was not as safe enough because it was capping
the returned value to (out of TB range) thus reviving the dead-lost position
based on an artificial clamp (i.e. the in TB score/mate score can be lost on that nonPv node):
https://tests.stockfishchess.org/tests/view/649756d5dc7002ce609cd794

Final fix:
Passed STC:
https://tests.stockfishchess.org/tests/view/649a5446dc7002ce609d1049
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 577280 W: 153613 L: 153965 D: 269702
Ptnml(0-2): 1320, 60594, 165190, 60190, 1346

Passed LTC:
https://tests.stockfishchess.org/tests/view/649cd048dc7002ce609d4801
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 246432 W: 66769 L: 66778 D: 112885
Ptnml(0-2): 83, 22105, 78847, 22100, 81

closes https://github.com/official-stockfish/Stockfish/pull/4649

Bench: 2425978
2023-07-03 18:24:41 +02:00
mstembera 80564bcfcd Simplify lookup_count and clean up pieces().
https://github.com/official-stockfish/Stockfish/pull/4656

No functional change
2023-07-03 18:20:10 +02:00
disservin 8634717c64 Add bmi2 to CI generated binaries
verify bench for avx2 and bmi2 as well

closes https://github.com/official-stockfish/Stockfish/pull/4658

No functional change
2023-07-03 18:17:20 +02:00
ppigazzini 9a2d50eccc Make posix and msys2 shells consistent in CI
In CI, it is typical for the process to halt immediately when an error
is encountered. However, with our `shell: bash {0}` configuration,
the process continues despite errors for posix shells.
This commit updates the behavior of posix and msys2 shells to ensure
consistency in terms of pipeline exit codes and stop conditions.
We adopt the most appropriate default behavior as recommended
by the GitHub documentation.

Update the code that searches for the bench value in the git log:
- to be compatible with the new shell settings
- to retry the value from the first line that contains
  only the template and spaces/tabs/newlines

see also

https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsshell
https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#exit-codes-and-error-action-preference
https://github.com/msys2/setup-msys2/blob/main/main.js

closes https://github.com/official-stockfish/Stockfish/pull/4653

No functional change
2023-07-02 10:32:36 +02:00
Linmiao Xu 915532181f Update NNUE architecture to SFNNv7 with larger L1 size of 2048
Creating this net involved:
- a 5-step training process from scratch
- greedy permuting L1 weights with https://github.com/official-stockfish/Stockfish/pull/4620
- leb128 compression with https://github.com/glinscott/nnue-pytorch/pull/251
- greedy 2- and 3- cycle permuting with https://github.com/official-stockfish/Stockfish/pull/4640

The 5 training steps were:

1. 400 epochs, lambda 1.0, lr 9.75e-4
   UHOx2-wIsRight-multinet-dfrc-n5000-largeGensfen-d9.binpack (178G)
     nodes5000pv2_UHO.binpack
     data_pv-2_diff-100_nodes-5000.binpack
     wrongIsRight_nodes5000pv2.binpack
     multinet_pv-2_diff-100_nodes-5000.binpack
     dfrc_n5000.binpack
     large_gensfen_multipvdiff_100_d9.binpack
   ep399 chosen as start model for step2

2. 800 epochs, end-lambda 0.75, skip 16
   LeelaFarseer-T78juntoaugT79marT80dec.binpack (141G)
     T60T70wIsRightFarseerT60T74T75T76.binpack
     test78-junjulaug2022-16tb7p.no-db.min.binpack
     test79-mar2022-16tb7p.no-db.min.binpack
     test80-dec2022-16tb7p.no-db.min.binpack
   ep559 chosen as start model for step3

3. 800 epochs, end-lambda 0.725, skip 20
   leela96-dfrc99-v2-T80dectofeb-sk20-mar-v6-T77decT78janfebT79apr.binpack (223G)
     leela96-filt-v2.min.binpack
     dfrc99-16tb7p-eval-filt-v2.min.binpack
     test80-dec2022-16tb7p-filter-v6-sk20.min-mar2023.binpack
     test80-jan2023-16tb7p-filter-v6-sk20.min-mar2023.binpack
     test80-feb2023-16tb7p-filter-v6-sk20.min-mar2023.binpack
     test80-mar2023-2tb7p-filter-v6.min.binpack
     test77-dec2021-16tb7p.no-db.min.binpack
     test78-janfeb2022-16tb7p.no-db.min.binpack
     test79-apr2022-16tb7p.no-db.min.binpack
   ep499 chosen as start model for step4

4. 800 epochs, end-lambda 0.7, skip 24
   0dd1cebea57 dataset https://github.com/official-stockfish/Stockfish/pull/4606
   ep599 chosen as start model for step5

5. 800 epochs, end-lambda 0.7, skip 28
   same dataset as step4
   ep619 became nn-1b951f8b449d.nnue

For the final step5 training:

python3 easy_train.py \
  --experiment-name L1-2048-S5-sameData-sk28-S4-0dd1cebea57-shuffled-S3-leela96-dfrc99-v2-T80dectofeb-sk20-mar-v6-T77decT78janfebT79apr-sk20-S2-LeelaFarseerT78T79T80-ep399-S1-UHOx2-wIsRight-multinet-dfrc-n5000-largeGensfen-d9 \
  --training-dataset /data/leela96-dfrc99-T60novdec-v2-T80juntonovjanfebT79aprmayT78jantosepT77dec-v6dd-T80apr.binpack \
  --early-fen-skipping 28 \
  --nnue-pytorch-branch linrock/nnue-pytorch/misc-fixes-L1-2048 \
  --engine-test-branch linrock/Stockfish/L1-2048 \
  --start-from-engine-test-net False \
  --start-from-model /data/experiments/experiment_L1-2048-S4-0dd1cebea57-shuffled-S3-leela96-dfrc99-v2-T80dectofeb-sk20-mar-v6-T77decT78janfebT79apr-sk20-S2-LeelaFarseerT78T79T80-ep399-S1-UHOx2-wIsRight-multinet-dfrc-n5000-largeGensfen-d9/training/run_0/nn-epoch599.nnue
  --max_epoch 800 \
  --lr 4.375e-4 \
  --gamma 0.995 \
  --start-lambda 1.0 \
  --end-lambda 0.7 \
  --tui False \
  --seed $RANDOM \
  --gpus 0

SF training data components for the step1 dataset:
https://drive.google.com/drive/folders/1yLCEmioC3Xx9KQr4T7uB6GnLm5icAYGU

Leela training data for steps 2-5 can be found at:
https://robotmoon.com/nnue-training-data/

Due to larger L1 size and slower inference, the speed penalty loses elo
at STC. Measurements from 100 bench runs at depth 13 with x86-64-modern
on Intel Core i5-1038NG7 2.00GHz:

sf_base =  1240730  +/-   3443 (95%)
sf_test =  1153341  +/-   2832 (95%)
diff    =   -87388  +/-   1616 (95%)
speedup = -7.04330% +/- 0.130% (95%)

Local elo at 25k nodes per move (vs. L1-1536 nn-fdc1d0fe6455.nnue):
nn-epoch619.nnue : 21.1 +/- 3.2

Failed STC:
https://tests.stockfishchess.org/tests/view/6498ee93dc7002ce609cf979
LLR: -2.95 (-2.94,2.94) <0.00,2.00>
Total: 11680 W: 3058 L: 3299 D: 5323
Ptnml(0-2): 44, 1422, 3149, 1181, 44

LTC:
https://tests.stockfishchess.org/tests/view/649b32f5dc7002ce609d20cf
Elo: 0.68 ± 1.5 (95%) LOS: 80.5%
Total: 40000 W: 10887 L: 10809 D: 18304
Ptnml(0-2): 36, 3938, 11958, 4048, 20
nElo: 1.50 ± 3.4 (95%) PairsRatio: 1.02

Passed VLTC 180+1.8:
https://tests.stockfishchess.org/tests/view/64992b43dc7002ce609cfd20
LLR: 3.06 (-2.94,2.94) <0.00,2.00>
Total: 38086 W: 10612 L: 10338 D: 17136
Ptnml(0-2): 9, 3316, 12115, 3598, 5

Passed VLTC SMP 60+0.6 th 8:
https://tests.stockfishchess.org/tests/view/649a21fedc7002ce609d0c7d
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 38936 W: 11091 L: 10820 D: 17025
Ptnml(0-2): 1, 2948, 13305, 3207, 7

closes https://github.com/official-stockfish/Stockfish/pull/4646

Bench: 2505168
2023-07-01 13:34:30 +02:00
cj5716 e551964ef6 Negative extension on cutNodes based on depth
This patch was inspired by candirufish original attempt at negative extensions
here that failed yellow: https://tests.stockfishchess.org/tests/view/6486529065ffe077ca124f32

I tested some variations of the idea and tuned a depth condition for
a modified version of it here https://tests.stockfishchess.org/tests/view/648db80a91c58631ce31fe00
after noticing abnormal scaling (ie many passed STC but not LTC)
After some small tweaks I got the final version here

Passed STC:
LLR: 2.98 (-2.94,2.94) <0.00,2.00>
Total: 122208 W: 32776 L: 32350 D: 57082
Ptnml(0-2): 310, 13250, 33553, 13686, 305
https://tests.stockfishchess.org/tests/view/64997934dc7002ce609d01e3

Passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 145092 W: 39617 L: 39115 D: 66360
Ptnml(0-2): 54, 13691, 44552, 14197, 52
https://tests.stockfishchess.org/tests/view/649a1c5ddc7002ce609d0bff

closes https://github.com/official-stockfish/Stockfish/pull/4644

Bench: 2637784
2023-07-01 13:06:49 +02:00
Stéphane Nicolet e355c70594 Document the LEB128 patch
Add some comments and harmonize style for the LEB128 patch.

closes https://github.com/official-stockfish/Stockfish/pull/4642

No functional change
2023-07-01 13:01:28 +02:00
Daniel Monroe ef94f77f8c Update default net to nn-a3d1bfca1672.nnue
faster permutation of master net weights

Activation data taken from https://drive.google.com/drive/folders/1Ec9YuuRx4N03GPnVPoQOW70eucOKngQe?usp=sharing
Permutation found using https://github.com/Ergodice/nnue-pytorch/blob/836387a0e5e690431d404158c46648710f13904d/ftperm.py
See also https://github.com/glinscott/nnue-pytorch/pull/254

The algorithm greedily selects 2- and 3-cycles that can be permuted to increase the number of runs of zeroes. The percent of zero runs from the master net increased from 68.46 to 70.11 from 2-cycles and only increased to 70.32 when considering 3-cycles. Interestingly, allowing both halves of L1 to intermix when creating zero runs can give another 0.5% zero-run density increase with this method.

Measured speedup:

```
CPU: 16 x AMD Ryzen 9 3950X 16-Core Processor
Result of 50 runs

base (./stockfish.master ) = 1561556 +/- 5439
test (./stockfish.patch ) = 1575788 +/- 5427
diff = +14231 +/- 2636

speedup = +0.0091
P(speedup > 0) = 1.0000
```

closes https://github.com/official-stockfish/Stockfish/pull/4640

No functional change
2023-07-01 12:59:28 +02:00
Joost VandeVondele 0fd186fb28 Restore development
closes https://github.com/official-stockfish/Stockfish/pull/4651

No functional change
2023-07-01 12:52:31 +02:00
Joost VandeVondele 68e1e9b381 Stockfish 16
Official release version of Stockfish 16

Bench: 2593605

---

Stockfish 16

A new major release of Stockfish is now available at

https://stockfishchess.org/download/

*Quality of chess play*

Stockfish continues to demonstrate its ability to discover superior moves
with remarkable speed. In self-play against Stockfish 15, this new
release gains up to 50 Elo[1] and wins up to 12 times more game pairs[2]
than it loses. In major chess engine tournaments, Stockfish reliably tops
the rankings[3] winning the TCEC season 24 Superfinal, Swiss, Fischer
Random, and Double Random Chess tournaments and the CCC 19 Bullet,
20 Blitz, and 20 Rapid competitions. Leela Chess Zero[4] was the
challenger in most finals, putting top-engine chess now firmly in the
hands of teams embracing free and open-source software.

*Progress made*

This updated version of Stockfish introduces several enhancements,
including an upgraded neural net architecture (SFNNv6)[5], improved
implementation, and refined parameterization. The ongoing utilization
of Leela’s data combined with a novel inference approach exploiting
sparsity[6], and network compression[7] ensure a speedy evaluation and
modest binary sizes while allowing for more weights and higher accuracy.
The search has undergone more optimization, leading to improved
performance, particularly in longer analyses[8]. Additionally,
the Fishtest framework has been improved and is now able to run the
tests needed to validate new ideas with 10000s of CPU cores.

*Usability improvements*

Stockfish now comes with documentation, found in the wiki folder when
downloading it or on GitHub[9]. Additionally, Stockfish now includes
a clear and consistent forced tablebase win score, displaying a value
of 200 minus the number of plies required to reach a tablebase win[10].
Furthermore, the UCI_Elo option, to reduce its strength, has been
calibrated[11]. It is worth noting that the evaluation system remains
consistent with Stockfish 15.1[12], maintaining the choice that 100cp
means a 50% chance of winning the game against an equal opponent[13].
Finally, binaries of our latest development version are now provided
continuously as pre-releases on GitHub making it easier for
enthusiasts to download the latest and strongest version of
the program[14], we thank Roman Korba for having provided a similar
service for a long time.

*Thank you*

The success of the Stockfish project relies on the vibrant community
of passionate enthusiasts (we appreciate each and every one of you!)
who generously contribute their knowledge, time, and resources.
Together, this dedicated community works towards the common goal of
developing a powerful, freely accessible, and open-source chess engine.
We invite all chess enthusiasts to join the Fishtest testing framework
and contribute to the project[15].

The Stockfish team

[1] https://tests.stockfishchess.org/tests/view/649409f0dc7002ce609c99cc
[2] https://tests.stockfishchess.org/tests/view/649409d7dc7002ce609c99c6
[3] https://en.wikipedia.org/wiki/Stockfish_(chess)#Competition_results
[4] https://lczero.org/
[5] https://github.com/official-stockfish/Stockfish/commit/c1fff71
[6] https://github.com/official-stockfish/Stockfish/commit/38e6166
[7] https://github.com/official-stockfish/Stockfish/commit/a46087e
[8] https://github.com/official-stockfish/Stockfish/commit/472e726
[9] https://github.com/official-stockfish/Stockfish/wiki/
[10] https://github.com/official-stockfish/Stockfish/commit/def2966
[11] https://github.com/official-stockfish/Stockfish/commit/a08b8d4
[12] https://github.com/official-stockfish/Stockfish/commit/52e84e4
[13] https://github.com/official-stockfish/Stockfish/wiki/Stockfish-FAQ#interpretation-of-the-stockfish-evaluation
[14] https://github.com/official-stockfish/Stockfish/releases?q=prerelease%3Atrue
[15] https://stockfishchess.org/get-involved/
2023-06-29 08:00:10 +02:00
Linmiao Xu a49b3ba7ed Update default net to nn-5af11540bbfe.nnue
Created by retraining the sparsified master net (nn-cd2ff4716c34.nnue) on
a 100% minified dataset including Leela transformers data from T80 may2023.

Weights permuted with the exact methods and code in:
https://github.com/official-stockfish/Stockfish/pull/4620

LEB128 compression done with the new serialize.py param in:
https://github.com/glinscott/nnue-pytorch/pull/251

Initially trained with max epoch 800. Around epoch 780, training was paused
and max epoch raised to 960.

python3 easy_train.py \
  --experiment-name L1-1536-sparse-master-retrain \
  --training-dataset /data/leela96-dfrc99-v2-T60novdecT77decT78jantosepT79aprmayT80juntonovjan-v6dd-T80febtomay2023.min.binpack \
  --early-fen-skipping 27 \
  --start-from-engine-test-net True \
  --max_epoch 960 \
  --lr 4.375e-4 \
  --gamma 0.995 \
  --start-lambda 1.0 \
  --end-lambda 0.7 \
  --tui False \
  --seed $RANDOM \
  --gpus 0

For preparing the training dataset (interleaved size 328G):

python3 interleave_binpacks.py \
  leela96-filt-v2.min.binpack \
  dfrc99-16tb7p-eval-filt-v2.min.binpack \
  filt-v6-dd-min/test60-novdec2021-12tb7p-filter-v6-dd.min.binpack \
  filt-v6-dd-min/test77-dec2021-16tb7p-filter-v6-dd.min.binpack \
  filt-v6-dd-min/test78-jantomay2022-16tb7p-filter-v6-dd.min.binpack \
  filt-v6-dd-min/test78-juntosep2022-16tb7p-filter-v6-dd.min.binpack \
  filt-v6-dd-min/test79-apr2022-16tb7p-filter-v6-dd.min.binpack \
  filt-v6-dd-min/test79-may2022-16tb7p-filter-v6-dd.min.binpack \
  filt-v6-dd-min/test80-jun2022-16tb7p-filter-v6-dd.min.binpack \
  filt-v6-dd-min/test80-jul2022-16tb7p-filter-v6-dd.min.binpack \
  filt-v6-dd-min/test80-aug2022-16tb7p-filter-v6-dd.min.binpack \
  filt-v6-dd-min/test80-sep2022-16tb7p-filter-v6-dd.min.binpack \
  filt-v6-dd-min/test80-oct2022-16tb7p-filter-v6-dd.min.binpack \
  filt-v6-dd-min/test80-nov2022-16tb7p-filter-v6-dd.min.binpack \
  filt-v6-dd-min/test80-jan2023-16tb7p-filter-v6-dd.min.binpack \
  test80-2023/test80-feb2023-16tb7p-no-db.min.binpack \
  test80-2023/test80-mar2023-2tb7p-no-db.min.binpack \
  test80-2023/test80-apr2023-2tb7p-no-db.min.binpack \
  test80-2023/test80-may2023-2tb7p-no-db.min.binpack \
  /data/leela96-dfrc99-v2-T60novdecT77decT78jantosepT79aprmayT80juntonovjan-v6dd-T80febtomay2023.min.binpack

Minified binpacks and Leela T80 training data from 2023 available at:
https://robotmoon.com/nnue-training-data/

Local elo at 25k nodes per move:
nn-epoch879.nnue : 3.9 +/- 5.7

Passed STC:
https://tests.stockfishchess.org/tests/view/64928c1bdc7002ce609c7690
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 72000 W: 19242 L: 18889 D: 33869
Ptnml(0-2): 182, 7787, 19716, 8126, 189

Passed LTC:
https://tests.stockfishchess.org/tests/view/64930a37dc7002ce609c82e3
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 54552 W: 14978 L: 14647 D: 24927
Ptnml(0-2): 23, 5123, 16650, 5460, 20

closes https://github.com/official-stockfish/Stockfish/pull/4635

bench 2593605
2023-06-22 10:33:19 +02:00
peregrineshahin 48f7c74f15 Fix Potential in TB cutoffs for NMP.
Removes the second dependency on beta and caps the return value to VALUE_TB_WIN_IN_MAX_PLY - 1

Earlier tests:

STC:
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 193632 W: 51372 L: 51326 D: 90934
Ptnml(0-2): 447, 20111, 55687, 20091, 480
https://tests.stockfishchess.org/tests/view/6486ee4465ffe077ca125bc1

LTC:
LLR: 2.97 (-2.94,2.94) <-1.75,0.25>
Total: 331758 W: 89538 L: 89624 D: 152596
Ptnml(0-2): 114, 30121, 105516, 29993, 135
https://tests.stockfishchess.org/tests/view/6489401af42a44347ed7be42

updated constant:
LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 100260 W: 27143 L: 27017 D: 46100
Ptnml(0-2): 34, 8842, 32248, 8976, 30
https://tests.stockfishchess.org/tests/view/6492fcafdc7002ce609c818c

closes: https://github.com/official-stockfish/Stockfish/pull/4632
fixes: https://github.com/official-stockfish/Stockfish/issues/4598

bench: 2370027
2023-06-22 10:26:17 +02:00
Joost VandeVondele 52e84e4b46 Update winrate model with June data
Retained 748191776 scored positions for analysis

const int NormalizeToPawnValue = 328;
Corresponding spread = 60;
Corresponding normalized spread = 0.18337766691628035;
Draw rate at 0.0 eval at move 32 = 0.9914715947898592;

closes https://github.com/official-stockfish/Stockfish/pull/4636

No functional change
2023-06-22 10:17:44 +02:00
Joost VandeVondele 02728736ed Update top CPU contributors
closes https://github.com/official-stockfish/Stockfish/pull/4629

No functional change
2023-06-22 10:15:51 +02:00
disservin aec8fb3fde Fix failing CI of pull requests
adds a guard to prevent pull requests from trying to delete the previous pre-release

closing https://github.com/official-stockfish/Stockfish/pull/4631

No functional change.
2023-06-20 18:50:12 +02:00
Joerg Oster 6eaa1c3ecd Fix indentation in qsearch.
https://github.com/official-stockfish/Stockfish/pull/4630

No functional change.
2023-06-20 10:47:07 +02:00
disservin a68a1c1154 create prereleases upon push to master
using github actions, create a prerelease for the latest commit to master.
As such a development version will be available on github, in addition to the latest release.

closes https://github.com/official-stockfish/Stockfish/pull/4622

No functional change
2023-06-20 08:55:54 +02:00
maxim a46087ee30 Compressed network parameters
Implemented LEB128 (de)compression for the feature transformer.
Reduces embedded network size from 70 MiB to 39 Mib.

The new nn-78bacfcee510.nnue corresponds to the master net compressed.

closes https://github.com/official-stockfish/Stockfish/pull/4617

No functional change
2023-06-19 21:37:23 +02:00
cj5716 0187546275 Small cleanup
This non-functional change keeps formatting consistent.

closes https://github.com/official-stockfish/Stockfish/pull/4623

Bench 2370027
2023-06-16 19:14:58 +02:00
AndrovT 32d3284df5 Permute master net weights to increase sparsity
Activation data collection using https://github.com/AndrovT/Stockfish/commit/ac468039ab544b03ad9a22c859a4217729c10a77 run as

bench 16 1 13 varied_1000.epd depth NNUE log.bin

on FENs from https://gist.github.com/AndrovT/7eae6918eb50764227e2bafe7938953c.

Permutation found using https://gist.github.com/AndrovT/359c831b7223c637e9156b01eb96949e.
Uses a greedy algorithm that goes sequentially through the output positions and
chooses a neuron for that position such that the number of nonzero quartets is the smallest.

Net weights permuted using https://gist.github.com/AndrovT/9e3fbaebb7082734dc84d27e02094cb3.

Benchmark:

Result of 100 runs of 'bench 16 1 13 default depth NNUE'
========================================================
base (...kfish-master) =     885869  +/- 7395
test (./stockfish    ) =     895885  +/- 7368
diff                   =     +10016  +/- 2984

speedup        = +0.0113
P(speedup > 0) =  1.0000

Passed STC:
https://tests.stockfishchess.org/tests/view/648866c4713491385c804728
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 126784 W: 34003 L: 33586 D: 59195
Ptnml(0-2): 283, 13001, 36437, 13358, 313

closes https://github.com/official-stockfish/Stockfish/pull/4620

No functional change.
2023-06-14 18:36:39 +02:00
peregrineshahin 14bfec2a98 Consistent bench extraction with fishtest.
Consistent with recent fishtest commit https://github.com/glinscott/fishtest/commit/c0d174396f7fb1c0b3243aaa6cc73769079f3ff9

closes https://github.com/official-stockfish/Stockfish/pull/4619

No functional change
2023-06-14 18:34:57 +02:00
Viren6 887bbd8b3d Remove setting of static to none if in check in qsearch
Small simplification

Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/6487924d713491385c8034ae
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 59616 W: 15885 L: 15703 D: 28028
Ptnml(0-2): 144, 6130, 17086, 6296, 152

closes https://github.com/official-stockfish/Stockfish/pull/4618

No functional change.
2023-06-14 18:33:56 +02:00
Andreas Matthies 7922e07af8 Fix for MSVC compilation.
MSVC needs two more explicit casts to compile new affine_transform_sparse_input.
See https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_castsi256_ps
and https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_castsi128_ps

closes https://github.com/official-stockfish/Stockfish/pull/4616

No functional change
2023-06-13 08:45:25 +02:00
Stéphane Nicolet 92c949e12e Clean-up code indentation in qsearch
closes https://github.com/official-stockfish/Stockfish/pull/4615

No functional change
2023-06-13 08:42:55 +02:00
Michael Chaly ece90bca9c Improve comments
Fix comments for IIR, also document non-linear scaling in extensions.
Also add explicitly the bench, to fix an issue after the last commit.

closes https://github.com/official-stockfish/Stockfish/pull/4614

bench 2370027
2023-06-12 21:17:31 +02:00
AndrovT 38e61663d8 Use block sparse input for the first layer.
Use block sparse input for the first fully connected layer on architectures with at least SSSE3.

Depending on the CPU architecture, this yields a speedup of up to 10%, e.g.

```
Result of 100 runs of 'bench 16 1 13 default depth NNUE'

base (...ockfish-base) =     959345  +/- 7477
test (...ckfish-patch) =    1054340  +/- 9640
diff                   =     +94995  +/- 3999

speedup        = +0.0990
P(speedup > 0) =  1.0000

CPU: 8 x AMD Ryzen 7 5700U with Radeon Graphics
Hyperthreading: on
```

Passed STC:
https://tests.stockfishchess.org/tests/view/6485aa0965ffe077ca12409c
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 8864 W: 2479 L: 2223 D: 4162
Ptnml(0-2): 13, 829, 2504, 1061, 25

This commit includes a net with reordered weights, to increase the likelihood of block sparse inputs,
but otherwise equivalent to the previous master net (nn-ea57bea57e32.nnue).

Activation data collected with https://github.com/AndrovT/Stockfish/tree/log-activations, running bench 16 1 13 varied_1000.epd depth NNUE on this data. Net parameters permuted with https://gist.github.com/AndrovT/9e3fbaebb7082734dc84d27e02094cb3.

closes https://github.com/official-stockfish/Stockfish/pull/4612

No functional change
2023-06-12 20:41:27 +02:00
Joost VandeVondele b7ee7290b5 Add network export to CI
verify the network written by export_net matches the original

closes https://github.com/official-stockfish/Stockfish/pull/4613

No functional change
2023-06-12 20:35:44 +02:00
Linmiao Xu 932f5a2d65 Update default net to nn-ea57bea57e32.nnue
Created by retraining an earlier epoch (ep659) of the experiment that led to the first SFNNv6 net:
- First retrained on the nn-0dd1cebea573 dataset
- Then retrained with skip 20 on a smaller dataset containing unfiltered Leela data
- And then retrained again with skip 27 on the nn-0dd1cebea573 dataset

The equivalent 7-step training sequence from scratch that led here was:

1. max-epoch 400, lambda 1.0, constant LR 9.75e-4, T79T77-filter-v6-dd.min.binpack
   ep379 chosen for retraining in step2

2. max-epoch 800, end-lambda 0.75, T60T70wIsRightFarseerT60T74T75T76.binpack
   ep679 chosen for retraining in step3

3. max-epoch 800, end-lambda 0.75, skip 28, nn-e1fb1ade4432 dataset
   ep799 chosen for retraining in step4

4. max-epoch 800, end-lambda 0.7, skip 28, nn-e1fb1ade4432 dataset
   ep759 became nn-8d69132723e2.nnue (first SFNNv6 net)
   ep659 chosen for retraining in step5

5. max-epoch 800, end-lambda 0.7, skip 28, nn-0dd1cebea573 dataset
   ep759 chosen for retraining in step6

6. max-epoch 800, end-lambda 0.7, skip 20, leela-dfrc-v2-T77decT78janfebT79aprT80apr.binpack
   ep639 chosen for retraining in step7

7. max-epoch 800, end-lambda 0.7, skip 27, nn-0dd1cebea573 dataset
   ep619 became nn-ea57bea57e32.nnue

For the last retraining (step7):

python3 easy_train.py
  --experiment-name L1-1536-Re6-masterShuffled-ep639-sk27-Re5-leela-dfrc-v2-T77toT80small-Re4-masterShuffled-ep659-Re3-sameAs-Re2-leela96-dfrc99-16t-v2-T60novdecT80juntonovjanfebT79aprmayT78jantosepT77dec-v6dd-Re1-LeelaFarseer-new-T77T79 \
  --training-dataset /data/leela96-dfrc99-T60novdec-v2-T80juntonovjanfebT79aprmayT78jantosepT77dec-v6dd-T80apr.binpack \
  --nnue-pytorch-branch linrock/nnue-pytorch/misc-fixes-L1-1536 \
  --early-fen-skipping 27 \
  --start-lambda 1.0 \
  --end-lambda 0.7 \
  --max_epoch 800 \
  --start-from-engine-test-net False \
  --start-from-model /data/L1-1536-Re5-leela-dfrc-v2-T77toT80small-epoch639.nnue \
  --lr 4.375e-4 \
  --gamma 0.995 \
  --tui False \
  --seed $RANDOM \
  --gpus "0,"

For preparing the step6 leela-dfrc-v2-T77decT78janfebT79aprT80apr.binpack dataset:

python3 interleave_binpacks.py \
  leela96-filt-v2.binpack \
  dfrc99-16tb7p-eval-filt-v2.binpack \
  test77-dec2021-16tb7p.no-db.min-mar2023.binpack \
  test78-janfeb2022-16tb7p.no-db.min-mar2023.binpack \
  test79-apr2022-16tb7p-filter-v6-dd.binpack \
  test80-apr2022-16tb7p.no-db.min-mar2023.binpack \
  /data/leela-dfrc-v2-T77decT78janfebT79aprT80apr.binpack

The unfiltered Leela data used for the step6 dataset can be found at:
https://robotmoon.com/nnue-training-data

Local elo at 25k nodes per move:
nn-epoch619.nnue : 2.3 +/- 1.9

Passed STC:
https://tests.stockfishchess.org/tests/view/6480d43c6e6ce8d9fc6d7cc8
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 40992 W: 11017 L: 10706 D: 19269
Ptnml(0-2): 113, 4400, 11170, 4689, 124

Passed LTC:
https://tests.stockfishchess.org/tests/view/648119ac6e6ce8d9fc6d8208
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 129174 W: 35059 L: 34579 D: 59536
Ptnml(0-2): 66, 12548, 38868, 13050, 55

closes https://github.com/official-stockfish/Stockfish/pull/4611

bench: 2370027
2023-06-11 15:23:52 +02:00
Guenther Demetz e1dd005583 Reintroduce SEE verification against discovered attacks
Reintroduces https://github.com/official-stockfish/Stockfish/pull/4453
along with https://github.com/official-stockfish/Stockfish/pull/4469

Leaving out
https://github.com/official-stockfish/Stockfish/pull/4533
https://github.com/official-stockfish/Stockfish/pull/4572

Passed STC:
https://tests.stockfishchess.org/tests/view/647d8c37726f6b400e408a0a
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 143168 W: 38346 L: 37892 D: 66930
Ptnml(0-2): 352, 15672, 39164, 15962, 434

Passed LTC:
https://tests.stockfishchess.org/tests/view/647ee8c528c4431bcb58e432
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 71538 W: 19560 L: 19190 D: 32788
Ptnml(0-2): 49, 6905, 21499, 7259, 57

closes https://github.com/official-stockfish/Stockfish/pull/4609

bench: 2595430
2023-06-11 15:13:57 +02:00
cj5716 a9a6915e08 Simplify multiplier for improvement
This simplifies a `* 99 / 1300` term into just `/ 13`.

Passed non-regression STC:
LLR: 2.92 (-2.94,2.94) <-1.75,0.25>
Total: 58816 W: 15727 L: 15540 D: 27549
Ptnml(0-2): 149, 6370, 16203, 6517, 169
https://tests.stockfishchess.org/tests/view/647d25e4726f6b400e408165

Passed non-regression LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 154386 W: 41749 L: 41669 D: 70968
Ptnml(0-2): 94, 14992, 46956, 15042, 109
https://tests.stockfishchess.org/tests/view/647d9b3c726f6b400e408b2a

closes https://github.com/official-stockfish/Stockfish/pull/4608

Bench:  2511327
2023-06-11 15:05:54 +02:00
Linmiao Xu 54ad986768 Remove optimism multiplier in nnue eval calculation
The same formula had passed SPRT against an earlier version of master.

Passed non-regression STC vs. d99942f:
https://tests.stockfishchess.org/tests/view/6478e76654dd118e1d98f72e
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 118720 W: 31402 L: 31277 D: 56041
Ptnml(0-2): 301, 13148, 32344, 13259, 308

Passed non-regression LTC vs. d99942f:
https://tests.stockfishchess.org/tests/view/647a22c154dd118e1d991146
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 74286 W: 20019 L: 19863 D: 34404
Ptnml(0-2): 31, 7189, 22540, 7359, 24

The earlier patch had conflicted with a faster SPRT passer, so this
was tested again after rebasing on latest master.

Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/647d6e46726f6b400e408790
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 166176 W: 44309 L: 44234 D: 77633
Ptnml(0-2): 461, 18252, 45557, 18387, 431

Passed non-regression LTC:
https://tests.stockfishchess.org/tests/view/647eb00ba268d1bc11255e7b
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 28170 W: 7713 L: 7513 D: 12944
Ptnml(0-2): 14, 2609, 8635, 2817, 10

closes https://github.com/official-stockfish/Stockfish/pull/4607

bench 2503095
2023-06-06 21:21:56 +02:00
Linmiao Xu 373359b44d Update default net to nn-0dd1cebea573.nnue
Created by retraining an earlier epoch of the experiment leading to the first SFNNv6 net
on a more-randomized version of the nn-e1fb1ade4432.nnue dataset mixed with unfiltered
T80 apr2023 data. Trained using early-fen-skipping 28 and max-epoch 960.

The trainer settings and epochs used in the 5-step training sequence leading here were:
1. train from scratch for 400 epochs, lambda 1.0, constant LR 9.75e-4, T79T77-filter-v6-dd.min.binpack
2. retrain ep379, max-epoch 800, end-lambda 0.75, T60T70wIsRightFarseerT60T74T75T76.binpack
3. retrain ep679, max-epoch 800, end-lambda 0.75, skip 28, nn-e1fb1ade4432 dataset
4. retrain ep799, max-epoch 800, end-lambda 0.7, skip 28, nn-e1fb1ade4432 dataset
5. retrain ep439, max-epoch 960, end-lambda 0.7, skip 28, shuffled nn-e1fb1ade4432 + T80 apr2023

This net was epoch 559 of the final (step 5) retraining:

```bash
python3 easy_train.py \
  --experiment-name L1-1536-Re4-leela96-dfrc99-T60novdec-v2-T80juntonovjanfebT79aprmayT78jantosepT77dec-v6dd-T80apr-shuffled-sk28 \
  --training-dataset /data/leela96-dfrc99-T60novdec-v2-T80juntonovjanfebT79aprmayT78jantosepT77dec-v6dd-T80apr.binpack \
  --nnue-pytorch-branch linrock/nnue-pytorch/misc-fixes-L1-1536 \
  --early-fen-skipping 28 \
  --start-lambda 1.0 \
  --end-lambda 0.7 \
  --max_epoch 960 \
  --start-from-engine-test-net False \
  --start-from-model /data/L1-1536-Re3-nn-epoch439.nnue \
  --engine-test-branch linrock/Stockfish/L1-1536 \
  --lr 4.375e-4 \
  --gamma 0.995 \
  --tui False \
  --seed $RANDOM \
  --gpus "0,"
```

During data preparation, most binpacks were unminimized by removing positions with
score 32002 (`VALUE_NONE`). This makes the tradeoff of increasing dataset filesize
on disk to increase the randomness of positions in interleaved datasets.
The code used for unminimizing is at:
https://github.com/linrock/Stockfish/tree/tools-unminify

For preparing the dataset used in this experiment:

```bash
python3 interleave_binpacks.py \
  leela96-filt-v2.binpack \
  dfrc99-16tb7p-eval-filt-v2.binpack \
  filt-v6-dd-min/test60-novdec2021-12tb7p-filter-v6-dd.min-mar2023.unmin.binpack \
  filt-v6-dd-min/test80-aug2022-16tb7p-filter-v6-dd.min-mar2023.unmin.binpack \
  filt-v6-dd-min/test80-sep2022-16tb7p-filter-v6-dd.min-mar2023.unmin.binpack \
  filt-v6-dd-min/test80-jun2022-16tb7p-filter-v6-dd.min-mar2023.unmin.binpack \
  filt-v6-dd/test80-jul2022-16tb7p-filter-v6-dd.binpack \
  filt-v6-dd/test80-oct2022-16tb7p-filter-v6-dd.binpack \
  filt-v6-dd/test80-nov2022-16tb7p-filter-v6-dd.binpack \
  filt-v6-dd-min/test80-jan2023-3of3-16tb7p-filter-v6-dd.min-mar2023.unmin.binpack \
  filt-v6-dd-min/test80-feb2023-16tb7p-filter-v6-dd.min-mar2023.unmin.binpack \
  filt-v6-dd/test79-apr2022-16tb7p-filter-v6-dd.binpack \
  filt-v6-dd/test79-may2022-16tb7p-filter-v6-dd.binpack \
  filt-v6-dd-min/test78-jantomay2022-16tb7p-filter-v6-dd.min-mar2023.unmin.binpack \
  filt-v6-dd/test78-juntosep2022-16tb7p-filter-v6-dd.binpack \
  filt-v6-dd/test77-dec2021-16tb7p-filter-v6-dd.binpack \
  test80-apr2023-2tb7p.binpack \
  /data/leela96-dfrc99-T60novdec-v2-T80juntonovjanfebT79aprmayT78jantosepT77dec-v6dd-T80apr.binpack
```

T80 apr2023 data was converted using lc0-rescorer with ~2tb of tablebases and can be found at:
https://robotmoon.com/nnue-training-data/

Local elo at 25k nodes per move vs. nn-e1fb1ade4432.nnue (L1 size 1024):
nn-epoch559.nnue : 25.7 +/- 1.6

Passed STC:
https://tests.stockfishchess.org/tests/view/647cd3b87cf638f0f53f9cbb
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 59200 W: 16000 L: 15660 D: 27540
Ptnml(0-2): 159, 6488, 15996, 6768, 189

Passed LTC:
https://tests.stockfishchess.org/tests/view/647d58de726f6b400e4085d8
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 58800 W: 16002 L: 15657 D: 27141
Ptnml(0-2): 44, 5607, 17748, 5962, 39

closes https://github.com/official-stockfish/Stockfish/pull/4606

bench 2141197
2023-06-06 21:17:36 +02:00
disservin 295f57829e Add binaries to releases with github actions
when a release is made with a tag matching sf_* the binaries will also be uploaded to the release as assets.

closes https://github.com/official-stockfish/Stockfish/pull/4596

No functional change.
2023-06-06 21:12:24 +02:00
peregrineshahin b60738e01b Fix no previous moves on root.
guards against no previous move existing if qSearch is called on the root node (i.e. when razoring).

Passed Non-regression STC:
https://tests.stockfishchess.org/tests/view/647d242d726f6b400e408143
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 53120 W: 14167 L: 13976 D: 24977
Ptnml(0-2): 109, 5597, 14981, 5740, 133

closes https://github.com/official-stockfish/Stockfish/pull/4604

Bench: 2551691
2023-06-06 21:07:43 +02:00
Michael Chaly 8dea070538 Move internal iterative reduction before probcut
This patch moves IIR before probcut which allows probcut
to be produced at lower depths. Comments in IIR are also slightly updated.

Passed STC:
https://tests.stockfishchess.org/tests/view/6472d604d29264e4cfa749fd
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 387616 W: 103295 L: 102498 D: 181823
Ptnml(0-2): 976, 42322, 106381, 43187, 942

Passed LTC:
https://tests.stockfishchess.org/tests/view/6475eb8c4a36543c4c9f42e8
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 202836 W: 54901 L: 54281 D: 93654
Ptnml(0-2): 85, 19609, 61422, 20205, 97

closes https://github.com/official-stockfish/Stockfish/pull/4597

bench 2551691
2023-06-04 23:12:23 +02:00
Linmiao Xu ced0311890 Remove static eval threshold for extensions when giving check
Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/647685d54a36543c4c9f4f2a
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 114688 W: 30701 L: 30571 D: 53416
Ptnml(0-2): 336, 12708, 31136, 12818, 346

Passed non-regression LTC:
https://tests.stockfishchess.org/tests/view/64774b02b81f005b572de770
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 107310 W: 28920 L: 28796 D: 49594
Ptnml(0-2): 33, 10427, 32621, 10531, 43

closes https://github.com/official-stockfish/Stockfish/pull/4599

bench 2597974
2023-06-04 23:05:28 +02:00
Guenther Demetz 5930c0defb Simplify away SEE verification
After 4 simplificatons over PR#4453 the idea does not yield significant
improvement anymore. Maybe also
https://tests.stockfishchess.org/tests/view/640c88092644b62c3394c1c5 was
a fluke.

Passed non-regression bounds:

STC:
https://tests.stockfishchess.org/tests/view/64705389c079b6583146d873
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 131936 W: 35040 L: 34930 D: 61966
Ptnml(0-2): 336, 14559, 36035, 14735, 303

LTC:
https://tests.stockfishchess.org/tests/view/6471a2ade549d9cf2fb213cd
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 407700 W: 109999 L: 110164 D: 187537
Ptnml(0-2): 279, 39913, 123689, 39632, 337

closes https://github.com/official-stockfish/Stockfish/pull/4595

bench: 2675974
2023-06-04 23:01:14 +02:00
Linmiao Xu 6cf8d938c5 Simplify blending nnue complexity with optimism
Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/6478a26d54dd118e1d98f21c
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 241248 W: 64058 L: 64063 D: 113127
Ptnml(0-2): 644, 26679, 65960, 26720, 621

Passed non-regression LTC:
https://tests.stockfishchess.org/tests/view/647b464854dd118e1d9928b2
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 24336 W: 6658 L: 6451 D: 11227
Ptnml(0-2): 8, 2316, 7312, 2525, 7

closes https://github.com/official-stockfish/Stockfish/pull/4602

bench 2425813
2023-06-04 22:56:44 +02:00
Muzhen Gaming 06186b786e Search tuning at very long time control with new net
The most significant change would be the singularBeta formula.
It was first tested by cj5716 (see https://tests.stockfishchess.org/tests/view/647317c9d29264e4cfa74ec7),
and I took much inspiration from that idea.

LTC (fixed games): https://tests.stockfishchess.org/tests/view/6479d8da54dd118e1d990b12
Elo: 0.61 ± 1.2 (95%) LOS: 83.4%
Total: 60000 W: 16278 L: 16172 D: 27550
Ptnml(0-2): 16, 5845, 18179, 5937, 23
nElo: 1.38 ± 2.8 (95%) PairsRatio: 1.02

VLTC 180+1.8: https://tests.stockfishchess.org/tests/view/6479da1454dd118e1d990b2b
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 33224 W: 9261 L: 8984 D: 14979
Ptnml(0-2): 5, 2809, 10710, 3080, 8

SMP VLTC 8-thread: https://tests.stockfishchess.org/tests/view/647b0fe354dd118e1d992425
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 61398 W: 17386 L: 17081 D: 26931
Ptnml(0-2): 7, 4571, 21232, 4888, 1

closes https://github.com/official-stockfish/Stockfish/pull/4603

Bench: 2805878
2023-06-04 22:54:13 +02:00
Michael Chaly d99942f254 Small simplification for probcut in check
Remove depth condition from there as not longer needed.

Passed STC:
https://tests.stockfishchess.org/tests/view/647367cad29264e4cfa753e6
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 254336 W: 67830 L: 67847 D: 118659
Ptnml(0-2): 580, 28181, 69697, 28096, 614

Passed LTC:
https://tests.stockfishchess.org/tests/view/647576184a36543c4c9f3af7
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 80706 W: 22048 L: 21898 D: 36760
Ptnml(0-2): 28, 7721, 24712, 7857, 35

closes https://github.com/official-stockfish/Stockfish/pull/4594

bench 2381945
2023-05-31 09:06:30 +02:00
Linmiao Xu 07bd8adcbc Simplify nnue eval complexity calculation
Remove a multiplier when blending nnue complexity with semi-classical complexity.

Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/6473a71dd29264e4cfa75839
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 124768 W: 33180 L: 33060 D: 58528
Ptnml(0-2): 314, 13797, 34030, 13941, 302

Passed non-regression LTC:
https://tests.stockfishchess.org/tests/view/6474af3dd29264e4cfa768f4
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 108180 W: 29008 L: 28884 D: 50288
Ptnml(0-2): 29, 10420, 33075, 10530, 36

closes https://github.com/official-stockfish/Stockfish/pull/4592

bench 2316827
2023-05-31 08:54:38 +02:00
Linmiao Xu c1fff71650 Update NNUE architecture to SFNNv6 with larger L1 size of 1536
Created by training a new net from scratch with L1 size increased from 1024 to 1536.
Thanks to Vizvezdenec for the idea of exploring larger net sizes after recent
training data improvements.

A new net was first trained with lambda 1.0 and constant LR 8.75e-4. Then a strong net
from a later epoch in the training run was chosen for retraining with start-lambda 1.0
and initial LR 4.375e-4 decaying with gamma 0.995. Retraining was performed a total of
3 times, for this 4-step process:

1. 400 epochs, lambda 1.0 on filtered T77+T79 v6 deduplicated data
2. 800 epochs, end-lambda 0.75 on T60T70wIsRightFarseerT60T74T75T76.binpack
3. 800 epochs, end-lambda 0.75 and early-fen-skipping 28 on the master dataset
4. 800 epochs, end-lambda 0.7 and early-fen-skipping 28 on the master dataset

In the training sequence that reached the new nn-8d69132723e2.nnue net,
the epochs used for the 3x retraining runs were:

1. epoch 379 trained on T77T79-filter-v6-dd.min.binpack
2. epoch 679 trained on T60T70wIsRightFarseerT60T74T75T76.binpack
3. epoch 799 trained on the master dataset

For training from scratch:

python3 easy_train.py \
  --experiment-name new-L1-1536-T77T79-filter-v6dd \
  --training-dataset /data/T77T79-filter-v6-dd.min.binpack \
  --max_epoch 400 \
  --lambda 1.0 \
  --start-from-engine-test-net False \
  --engine-test-branch linrock/Stockfish/L1-1536 \
  --nnue-pytorch-branch linrock/Stockfish/misc-fixes-L1-1536 \
  --tui False \
  --gpus "0," \
  --seed $RANDOM

Retraining commands were similar to each other. For the 3rd retraining run:

python3 easy_train.py \
  --experiment-name L1-1536-T77T79-v6dd-Re1-LeelaFarseer-Re2-masterDataset-Re3-sameData \
  --training-dataset /data/leela96-dfrc99-v2-T60novdecT80juntonovjanfebT79aprmayT78jantosepT77dec-v6dd.binpack \
  --early-fen-skipping 28 \
  --max_epoch 800 \
  --start-lambda 1.0 \
  --end-lambda 0.7 \
  --lr 4.375e-4 \
  --gamma 0.995 \
  --start-from-engine-test-net False \
  --start-from-model /data/L1-1536-T77T79-v6dd-Re1-LeelaFarseer-Re2-masterDataset-nn-epoch799.nnue \
  --engine-test-branch linrock/Stockfish/L1-1536 \
  --nnue-pytorch-branch linrock/nnue-pytorch/misc-fixes-L1-1536 \
  --tui False \
  --gpus "0," \
  --seed $RANDOM

The T77+T79 data used is a subset of the master dataset available at:
https://robotmoon.com/nnue-training-data/

T60T70wIsRightFarseerT60T74T75T76.binpack is available at:
https://drive.google.com/drive/folders/1S9-ZiQa_3ApmjBtl2e8SyHxj4zG4V8gG

Local elo at 25k nodes per move vs. nn-e1fb1ade4432.nnue (L1 size 1024):
nn-epoch759.nnue : 26.9 +/- 1.6

Failed STC
https://tests.stockfishchess.org/tests/view/64742485d29264e4cfa75f97
LLR: -2.94 (-2.94,2.94) <0.00,2.00>
Total: 13728 W: 3588 L: 3829 D: 6311
Ptnml(0-2): 71, 1661, 3610, 1482, 40

Failing LTC
https://tests.stockfishchess.org/tests/view/64752d7c4a36543c4c9f3618
LLR: -1.91 (-2.94,2.94) <0.50,2.50>
Total: 35424 W: 9522 L: 9603 D: 16299
Ptnml(0-2): 24, 3579, 10585, 3502, 22

Passed VLTC 180+1.8
https://tests.stockfishchess.org/tests/view/64752df04a36543c4c9f3638
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 47616 W: 13174 L: 12863 D: 21579
Ptnml(0-2): 13, 4261, 14952, 4566, 16

Passed VLTC SMP 60+0.6 th 8
https://tests.stockfishchess.org/tests/view/647446ced29264e4cfa761e5
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 19942 W: 5694 L: 5451 D: 8797
Ptnml(0-2): 6, 1504, 6707, 1749, 5

closes https://github.com/official-stockfish/Stockfish/pull/4593

bench 2222567
2023-05-31 08:51:22 +02:00
windfishballad 7e9b131efb Removed quadratic term in optimism
Remove term which is quadratic in optimism in the eval.
Simplifies and should also remove the bias towards side to move making the eval better for analysis.

STC: https://tests.stockfishchess.org/tests/view/6470a9d8c29e0d4352b0bca5
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 154432 W: 41127 L: 41040 D: 72265
Ptnml(0-2): 380, 17094, 42190, 17163, 389

LTC: https://tests.stockfishchess.org/tests/view/6471e9b3e549d9cf2fb219ef
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 127926 W: 34474 L: 34369 D: 59083
Ptnml(0-2): 43, 12505, 38776, 12582, 57

closes https://github.com/official-stockfish/Stockfish/pull/4590

Bench: 2541211
2023-05-28 20:05:50 +02:00
Joost VandeVondele 7f0b19dedf Update CPU contributors list
update CPU contributors list, the previous update was a couple of months ago,
and unfortunately, was not quite accurate for the number of games played.

This version is based clean calculation from the DB and
an updated script that tracks things (see https://github.com/glinscott/fishtest/pull/1702).

closes https://github.com/official-stockfish/Stockfish/pull/4589

No functional change
2023-05-28 20:03:33 +02:00
cj5716 c701745cf2 Remove ss->ttHit condition where ttValue != VALUE_NONE
Simplification is done at 3 separate places in the code.
Thanks to peregrineshahin for helping me find 2 of such places.
(See original PR #4584)

Passed non-regression test
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 120256 W: 32204 L: 32085 D: 55967
Ptnml(0-2): 292, 12473, 34483, 12584, 296
https://tests.stockfishchess.org/tests/view/646f045968661bfd984325e3

closes https://github.com/official-stockfish/Stockfish/pull/4587

No functional change
2023-05-25 20:49:11 +02:00
FauziAkram cedd73f4aa Simplify Futility pruning for captures
Passed STC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 412928 W: 109433 L: 109620 D: 193875
Ptnml(0-2): 1071, 45929, 112650, 45744, 1070
https://tests.stockfishchess.org/tests/view/6468eac40db5177f2b76ef4d

Passed LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 190200 W: 51465 L: 51420 D: 87315
Ptnml(0-2): 58, 18585, 57788, 18592, 77
https://tests.stockfishchess.org/tests/view/646b66520db5177f2b772a84

closes https://github.com/official-stockfish/Stockfish/pull/4583

bench: 2486604
2023-05-25 20:42:43 +02:00
FauziAkram a989aa1825 Simplify Prune moves with negative SEE
Passed STC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 57760 W: 15472 L: 15286 D: 27002
Ptnml(0-2): 123, 6025, 16430, 6147, 155
https://tests.stockfishchess.org/tests/view/6468eb6b0db5177f2b76ef62

Passed LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 93966 W: 25274 L: 25141 D: 43551
Ptnml(0-2): 33, 8498, 29792, 8623, 37
https://tests.stockfishchess.org/tests/view/6469570b0db5177f2b76f81b

closes: https://github.com/official-stockfish/Stockfish/pull/4579

Bench: 2304063
2023-05-25 20:40:09 +02:00
Muzhen Gaming b64c97825e Simplify delta calculation in aspiration window
Simplification STC: https://tests.stockfishchess.org/tests/view/6468cb200db5177f2b76ecbb
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 220416 W: 58503 L: 58487 D: 103426
Ptnml(0-2): 596, 24384, 60188, 24488, 552

Simplification LTC: https://tests.stockfishchess.org/tests/view/646a15840db5177f2b770704
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 177756 W: 47882 L: 47825 D: 82049
Ptnml(0-2): 55, 17430, 53858, 17473, 62

closes https://github.com/official-stockfish/Stockfish/pull/4581

Bench: 2304063
2023-05-25 20:37:53 +02:00
candirufish d7e72d801f More Depth Reduction
Reduce more for depth > 3 and depth < 12

LTC: https://tests.stockfishchess.org/tests/view/646c5abbd1f14fd69a6f2fab
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 197280 W: 53405 L: 52797 D: 91078
Ptnml(0-2): 62, 19025, 59886, 19577, 90

STC: https://tests.stockfishchess.org/tests/view/646bee71d1f14fd69a6f259d
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 100832 W: 26861 L: 26466 D: 47505
Ptnml(0-2): 240, 10985, 27622, 11278, 291

https://github.com/official-stockfish/Stockfish/pull/4585

bench: 2276617
2023-05-25 20:35:13 +02:00
Michael Chaly df0fb8471e Small simplification in low depth pruning
Uncap low depth pruning lmr depth.
It's anyway capped for most cases apart from futility pruning for captures - removes one std::min call.

Passed STC:
https://tests.stockfishchess.org/tests/view/645e8fa6d55cccb2e64225a1
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 184064 W: 49039 L: 48982 D: 86043
Ptnml(0-2): 462, 20353, 50349, 20402, 466

Passed LTC:
https://tests.stockfishchess.org/tests/view/645f4d48d55cccb2e6423335
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 83886 W: 22613 L: 22465 D: 38808
Ptnml(0-2): 31, 8090, 25546, 8252, 24

closes https://github.com/official-stockfish/Stockfish/pull/4566

bench 3201883
2023-05-20 10:19:03 +02:00
pb00067 7cd650f435 Simplify SEE verfication logic
Passed STC
https://tests.stockfishchess.org/tests/view/6461d51887f6567dd4df27d0
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 177056 W: 47181 L: 47118 D: 82757
Ptnml(0-2): 456, 19381, 48792, 19442, 457

Passed LTC
https://tests.stockfishchess.org/tests/view/64631a9287f6567dd4df4502
2.94 (-2.94,2.94) <-1.75,0.25>
Total: 104346 W: 28062 L: 27935 D: 48349
Ptnml(0-2): 25, 10190, 31631, 10287, 40

closes https://github.com/official-stockfish/Stockfish/pull/4578

bench: 2903251
2023-05-20 10:16:04 +02:00
xoto10 4b085c4777 Simplify optimism calculation
This change removes one of the constants in the calculation of optimism. It also changes the 2 constants used with the scale value so that they are independent, instead of applying a constant to the scale and then adjusting it again when it is applied to the optimism. This might make the tuning of these constants cleaner and more reliable in the future.

STC 10+0.1 (accidentally run as an Elo gainer:
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 154080 W: 41119 L: 40651 D: 72310
Ptnml(0-2): 375, 16840, 42190, 17212, 423
https://tests.stockfishchess.org/tests/live_elo/64653eabf3b1a4e86c317f77

LTC 60+0.6:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 217434 W: 58382 L: 58363 D: 100689
Ptnml(0-2): 66, 21075, 66419, 21088, 69
https://tests.stockfishchess.org/tests/live_elo/6465d077f3b1a4e86c318d6c

closes https://github.com/official-stockfish/Stockfish/pull/4576

bench: 3190961
2023-05-20 10:05:19 +02:00
Stefan Geschwentner 4f24ee0868 Small simplification in history pruning.
Remove the constant term of the history threshold which lowers the chance that pruning occurs.
As compensation allow pruning at a slightly higher depth.

Passed STC:
https://tests.stockfishchess.org/tests/view/64634c9a87f6567dd4df4901
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 101536 W: 27156 L: 27012 D: 47368
Ptnml(0-2): 266, 11165, 27772, 11289, 276

Passed LTC:
https://tests.stockfishchess.org/tests/view/6463d68b17982fde89d2bc2b
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 32154 W: 8741 L: 8543 D: 14870
Ptnml(0-2): 8, 3093, 9687, 3271, 18

Passed LTC: retest on top of VLTC tuning PR 4571 because this changes the history depth factor (use this new factor here)
https://tests.stockfishchess.org/tests/view/6467300e165c4b29ec0afd3f
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 99270 W: 26840 L: 26707 D: 45723
Ptnml(0-2): 36, 9753, 29928, 9878, 40

closes https://github.com/official-stockfish/Stockfish/pull/4578

Bench: 2984341
2023-05-20 09:58:51 +02:00
Muzhen Gaming f030a1c592 Search tuning at very long time control
Many search parameter changes, tuned
(https://tests.stockfishchess.org/tests/view/645e4c67d55cccb2e64220ff)
at ~300k games @ VLTC (120+1.2).

Failed STC:
https://tests.stockfishchess.org/tests/view/6465fcd77968ca827c1410c2
LLR: -2.95 (-2.94,2.94) <0.00,2.00>
Total: 33824 W: 8863 L: 9067 D: 15894
Ptnml(0-2): 89, 3833, 9266, 3641, 83

Neutral LTC:
https://tests.stockfishchess.org/tests/view/646385ce87f6567dd4df4e37
Elo: -0.48 +-1.2 (95%) LOS: 22.2%
Total: 60000 W: 16235 L: 16318 D: 27447
Ptnml(0-2): 27, 5831, 18366, 5750, 26
nElo: -1.08 +-2.8 (95%) PairsRatio: 0.99

Passed VLTC 180+1.8:
https://tests.stockfishchess.org/tests/view/646385f787f6567dd4df4e3e
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 126448 W: 34704 L: 34258 D: 57486
Ptnml(0-2): 9, 10970, 40825, 11406, 14

Passed VLTC SMP 60+0.6 8thread:
https://tests.stockfishchess.org/tests/view/646628de884ce93b65df2ac9
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 59456 W: 16791 L: 16487 D: 26178
Ptnml(0-2): 5, 4473, 20467, 4779, 4

closes https://github.com/official-stockfish/Stockfish/pull/4574

Bench: 3347573
2023-05-20 09:21:46 +02:00
Joost VandeVondele 5f7b26aaa0 Update WLD model
using data of May, recalibrate the WLD model.

closes https://github.com/official-stockfish/Stockfish/pull/4577

No functional change
2023-05-20 09:16:46 +02:00
Michael Chaly 65e2150501 Refine deeper post-lmr searches
This patch improves logic conditions for performing deeper searches after passed LMR.

Instead of exceeding alpha by some margin now it requires to exceed the
current best value - which may be lower than alpha (but never bigger since we
update alpha with bestvalue if it exceeds alpha).

Passed STC:
https://tests.stockfishchess.org/tests/view/6455f78008858de8313775b6
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 209344 W: 55993 L: 55448 D: 97903
Ptnml(0-2): 507, 22798, 57526, 23325, 516

Passed LTC:
https://tests.stockfishchess.org/tests/view/64572d46eb75932ccfebff97
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 66288 W: 17867 L: 17514 D: 30907
Ptnml(0-2): 21, 6240, 20269, 6593, 21

closes https://github.com/official-stockfish/Stockfish/pull/4559

bench 3808503
2023-05-07 22:36:57 +02:00
Michael Chaly 464ebdf127 Small cleanup
In search remove one condition check and reorder conditions. Removes some code.

Passed non-regression test:
https://tests.stockfishchess.org/tests/view/64548fa06206ee34ebf853ad
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 282976 W: 75327 L: 75374 D: 132275
Ptnml(0-2): 604, 29673, 80995, 29598, 618

closes https://github.com/official-stockfish/Stockfish/pull/4557

No functional change
2023-05-07 22:32:21 +02:00
peregrineshahin 28442195c7 Clean up after "Simplify away complexity in evaluation"
closes https://github.com/official-stockfish/Stockfish/pull/4555

No functional change.
2023-05-07 22:31:03 +02:00
Michael Chaly 2429e16289 Reduce more if current node has a lot of refuted moves.
This patch refines idea of cutoff count - in master we reduce more if current node has at least 4 moves that are refuted by search, this patch increases this count by 1 if refutation happened without having a tt move.

Passed STC:
https://tests.stockfishchess.org/tests/view/645363c36206ee34ebf8191d
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 67616 W: 18220 L: 17874 D: 31522
Ptnml(0-2): 142, 7346, 18504, 7656, 160

Passed LTC:
https://tests.stockfishchess.org/tests/view/6453a0ea6206ee34ebf82796
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 195228 W: 52741 L: 52140 D: 90347
Ptnml(0-2): 53, 18718, 59482, 19297, 64

closes https://github.com/official-stockfish/Stockfish/pull/4556

bench 3448916
2023-05-05 07:12:47 +02:00
candirufish 72d542f000 Adjust reductions
Decrease further on cutNodes with tte->depth() >= depth + 3 condition.

LTC: https://tests.stockfishchess.org/tests/view/644dc84bccf5e93df5e50c13
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 155346 W: 42184 L: 41660 D: 71502
Ptnml(0-2): 59, 14765, 47504, 15283, 62

STC: https://tests.stockfishchess.org/tests/view/644d05de68e01d8194cd9bbb
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 121888 W: 32868 L: 32444 D: 56576
Ptnml(0-2): 332, 13273, 33343, 13631, 365

closes https://github.com/official-stockfish/Stockfish/pull/4552

bench: 3739675
2023-05-03 20:41:33 +02:00
Linmiao Xu 21d6b69f7c Update 7 eval and optimism params
Params found using spsa at 30+0.3 with this tuning config:

```
// evaluate.cpp
int nnueOptScaleBase = 1001;
int nnueComplexityMult = 406;
int nnueComplexityOptOffset = 424;
int evalOptComplexityOffset = 272;
int evalOptScaleOffset = 748;
TUNE(SetRange(801, 1201), nnueOptScaleBase);
TUNE(SetRange(306, 506), nnueComplexityMult);
TUNE(SetRange(324, 524), nnueComplexityOptOffset);
TUNE(SetRange(172, 372), evalOptComplexityOffset);
TUNE(SetRange(648, 848), evalOptScaleOffset);

// search.cpp
int searchOptBase = 120;
int searchOptDenom = 161;
TUNE(SetRange(20, 220), searchOptBase);
TUNE(SetRange(111, 211), searchOptDenom);
```

Passed STC:
https://tests.stockfishchess.org/tests/view/644dda8accf5e93df5e50cbe
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 136800 W: 36682 L: 36237 D: 63881
Ptnml(0-2): 353, 14910, 37492, 15229, 416

Passed LTC:
https://tests.stockfishchess.org/tests/view/644eaedb3f31c3bbe4a3d345
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 64548 W: 17624 L: 17272 D: 29652
Ptnml(0-2): 33, 6112, 19631, 6466, 32

closes https://github.com/official-stockfish/Stockfish/pull/4550

bench 3670343
2023-05-03 20:37:57 +02:00
Linmiao Xu 41f50b2c83 Update default net to nn-e1fb1ade4432.nnue
Created by retraining nn-dabb1ed23026.nnue with a dataset composed of:

* The previous best dataset (nn-1ceb1a57d117.nnue dataset)
* Adding de-duplicated T80 data from feb2023 and the last 10 days of jan2023, filtered with v6-dd

Initially trained with the same options as the recent master net (nn-1ceb1a57d117.nnue).
Around epoch 890, training was manually stopped and max epoch increased to 1000.

```
python3 easy_train.py \
  --experiment-name leela96-dfrc99-T60novdec-v2-T80augsep-v6-T80junjuloctnovjanfebT79aprmayT78jantosepT77dec-v6dd \
  --training-dataset /data/leela96-dfrc99-T60novdec-v2-T80augsep-v6-T80junjuloctnovjanfebT79aprmayT78jantosepT77dec-v6dd.binpack \
  --nnue-pytorch-branch linrock/nnue-pytorch/misc-fixes \
  --start-from-engine-test-net True \
  --early-fen-skipping 30 \
  --start-lambda 1.0 \
  --end-lambda 0.7 \
  --max_epoch 900 \
  --lr 4.375e-4 \
  --gamma 0.995 \
  --tui False \
  --gpus "0," \
  --seed $RANDOM
```

The same v6-dd filtering and binpack minimizer was used for preparing the recent nn-1ceb1a57d117.nnue dataset.

```
python3 interleave_binpacks.py \
  leela96-filt-v2.binpack \
  dfrc99-filt-v2.binpack \
  T60-nov2021-12tb7p-eval-filt-v2.binpack \
  T60-dec2021-12tb7p-eval-filt-v2.binpack \
  filt-v6/test80-aug2022-16tb7p-filter-v6.min-mar2023.binpack \
  filt-v6/test80-sep2022-16tb7p-filter-v6.min-mar2023.binpack \
  filt-v6-dd/test80-jun2022-16tb7p-filter-v6-dd.min-mar2023.binpack \
  filt-v6-dd/test80-jul2022-16tb7p-filter-v6-dd.binpack \
  filt-v6-dd/test80-oct2022-16tb7p-filter-v6-dd.binpack \
  filt-v6-dd/test80-nov2022-16tb7p-filter-v6-dd.binpack \
  filt-v6-dd/test80-jan2022-3of3-16tb7p-filter-v6-dd.min-mar2023.binpack \
  filt-v6-dd/test80-feb2023-16tb7p-filter-v6-dd.min-mar2023.binpack \
  filt-v6-dd/test79-apr2022-16tb7p-filter-v6-dd.binpack \
  filt-v6-dd/test79-may2022-16tb7p-filter-v6-dd.binpack \
  filt-v6-dd/test78-jantomay2022-16tb7p-filter-v6-dd.min-mar2023.binpack \
  filt-v6-dd/test78-juntosep2022-16tb7p-filter-v6-dd.binpack \
  filt-v6-dd/test77-dec2021-16tb7p-filter-v6-dd.binpack \
  /data/leela96-dfrc99-T60novdec-v2-T80augsep-v6-T80junjuloctnovjanfebT79aprmayT78jantosepT77dec-v6dd.binpack
```

Links for downloading the training data components can be found at:
https://robotmoon.com/nnue-training-data/

Local elo at 25k nodes per move:
nn-epoch919.nnue : 2.6 +/- 2.8

Passed STC vs. nn-dabb1ed23026.nnue
https://tests.stockfishchess.org/tests/view/644420df94ff3db5625f2af5
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 125960 W: 33898 L: 33464 D: 58598
Ptnml(0-2): 351, 13920, 34021, 14320, 368

Passed LTC vs. nn-1ceb1a57d117.nnue
https://tests.stockfishchess.org/tests/view/64469f128d30316529b3dc46
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 24544 W: 6817 L: 6542 D: 11185
Ptnml(0-2): 8, 2252, 7488, 2505, 19

closes https://github.com/official-stockfish/Stockfish/pull/4546

bench 3714847
2023-04-25 08:19:00 +02:00
Linmiao Xu c3ce220408 Created by retraining the master net with these changes to the dataset:
* Extending v6 filtering to data from T77 dec2021, T79 may2022, and T80 nov2022
* Reducing the number of duplicate positions, prioritizing position scores seen later in time
* Using a binpack minimizer to reduce the overall data size

Trained the same way as the previous master net, aside from the dataset changes:

```
python3 easy_train.py \
  --experiment-name leela96-dfrc99-T60novdec-v2-T80augsep-v6-T80junjuloctnovT79aprmayT78jantosepT77dec-v6dd \
  --training-dataset /data/leela96-dfrc99-T60novdec-v2-T80augsep-v6-T80junjuloctnovT79aprmayT78jantosepT77dec-v6dd.binpack \
  --nnue-pytorch-branch linrock/nnue-pytorch/misc-fixes \
  --start-from-engine-test-net True \
  --early-fen-skipping 30 \
  --start-lambda 1.0 \
  --end-lambda 0.7 \
  --max_epoch 900 \
  --lr 4.375e-4 \
  --gamma 0.995 \
  --tui False \
  --gpus "0," \
  --seed $RANDOM
```

The new v6-dd filtering reduces duplicate positions by iterating over hourly data files within leela test runs, starting with the most recent, then keeping positions the first time they're seen and ignoring positions that are seen again. This ordering was done with the assumption that position scores seen later in time are generally more accurate than scores seen earlier in the test run. Positions are de-duplicated based on piece orientations, the first token in fen strings.

The binpack minimizer was run with default settings after first merging monthly data into single binpacks.

```
python3 interleave_binpacks.py \
  leela96-filt-v2.binpack \
  dfrc99-filt-v2.binpack \
  T60-nov2021-12tb7p-eval-filt-v2.binpack \
  T60-dec2021-12tb7p-eval-filt-v2.binpack \
  filt-v6/test80-aug2022-16tb7p-filter-v6.min-mar2023.binpack \
  filt-v6/test80-sep2022-16tb7p-filter-v6.min-mar2023.binpack \
  filt-v6-dd/test80-jun2022-16tb7p-filter-v6-dd.min-mar2023.binpack \
  filt-v6-dd/test80-jul2022-16tb7p-filter-v6-dd.binpack \
  filt-v6-dd/test80-oct2022-16tb7p-filter-v6-dd.binpack \
  filt-v6-dd/test80-nov2022-16tb7p-filter-v6-dd.binpack \
  filt-v6-dd/test79-apr2022-16tb7p-filter-v6-dd.binpack \
  filt-v6-dd/test79-may2022-16tb7p-filter-v6-dd.binpack \
  filt-v6-dd/test78-jantomay2022-16tb7p-filter-v6-dd.min-mar2023.binpack \
  filt-v6-dd/test78-juntosep2022-16tb7p-filter-v6-dd.binpack \
  filt-v6-dd/test77-dec2021-16tb7p-filter-v6-dd.binpack \
  /data/leela96-dfrc99-T60novdec-v2-T80augsep-v6-T80junjuloctnovT79aprmayT78jantosepT77dec-v6dd.binpack
```

The code for v6-dd filtering is available along with training data preparation scripts at:
https://github.com/linrock/nnue-data

Links for downloading the training data components:
https://robotmoon.com/nnue-training-data/

The binpack minimizer is from: #4447

Local elo at 25k nodes per move:
nn-epoch859.nnue : 1.2 +/- 2.6

Passed STC:
https://tests.stockfishchess.org/tests/view/643aad7db08900ff1bc5a832
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 565040 W: 150225 L: 149162 D: 265653
Ptnml(0-2): 1875, 62137, 153229, 63608, 1671

Passed LTC:
https://tests.stockfishchess.org/tests/view/643ecf2fa43cf30e719d2042
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 1014840 W: 274645 L: 272456 D: 467739
Ptnml(0-2): 515, 98565, 306970, 100956, 414

closes https://github.com/official-stockfish/Stockfish/pull/4545

bench 3476305
2023-04-25 08:17:22 +02:00
Boštjan Mejak b22a1b10bb Update AUTHORS
Improved some comments in the AUTHORS file, sort contributors

closes https://github.com/official-stockfish/Stockfish/pull/4520

No functional change
2023-04-25 08:08:48 +02:00
Stefan Geschwentner ba06c480a7 Less reduction for tt move.
This idea is a result of my second condition combination tuning for reductions:
https://tests.stockfishchess.org/tests/view/643ed5573806eca398f06d61

There were used two parameters per combination: one for the 'sign' of the first and the second condition in a combination. Values >= 50 indicate using a condition directly and values <= -50 means use the negation of a condition.

Each condition pair (X,Y) had two occurances dependent of the order of the two conditions:
- if X < Y the parameters used for more reduction
- if X > Y the parameters used for less reduction
- if X = Y then only one condition is present and A[X][X][0]/A[X][X][1] stands for using more/less reduction for only this condition.

The parameter pair A[7][2][0] (value = -94.70) and A[7][2][1] (value = 93.60) was one of the strongest signals with values near 100/-100.
Here condition nr. 7 was '(ss+1)->cutoffCnt > 3' and condition nr. 2 'move == ttMove'. For condition nr. 7 the negation is used because A[7][2][0] is negative.

This translates finally to less reduction (because 7 > 2) for tt moves if child cutoffs <= 3.

STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 65728 W: 17704 L: 17358 D: 30666
Ptnml(0-2): 184, 7092, 18008, 7354, 226
https://tests.stockfishchess.org/tests/view/643ff767ef2529086a7ed042

LTC:
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 139200 W: 37776 L: 37282 D: 64142
Ptnml(0-2): 58, 13241, 42509, 13733, 59
https://tests.stockfishchess.org/tests/view/6440bfa9ef2529086a7edbc7

closes https://github.com/official-stockfish/Stockfish/pull/4538

Bench: 3548023
2023-04-22 11:04:09 +02:00
Muzhen Gaming d64d4ac426 Simplify away depth condition for aspiration window adjust
Simplification STC:
https://tests.stockfishchess.org/tests/view/64351654596a20f264276ded
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 374664 W: 98942 L: 99089 D: 176633
Ptnml(0-2): 1049, 41767, 101878, 41558, 1080

Simplification LTC:
https://tests.stockfishchess.org/tests/view/6439499f605991a801b4f684
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 457880 W: 123021 L: 123233 D: 211626
Ptnml(0-2): 166, 44739, 139335, 44541, 159

closes https://github.com/official-stockfish/Stockfish/pull/4534

Bench: 3879281
2023-04-22 10:59:33 +02:00
Guenther Demetz 7b9b793fd5 Simplification of SEE verification logic
Use same logic for all handled pieces.
Don't prune the move if opponent King, Queen, Rook gets a discovered
attack while or after the exchanges.

remove an obsolete comment in position.cpp

Passed STC non regression:
https://tests.stockfishchess.org/tests/view/6437907594daa91835c290d0
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 107432 W: 28359 L: 28221 D: 50852
Ptnml(0-2): 298, 11724, 29524, 11882, 288

Passed LTC non-regression:
https://tests.stockfishchess.org/tests/view/6438ed2ebd1a5470263c51e8
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 236288 W: 63656 L: 63656 D: 108976
Ptnml(0-2): 99, 22960, 72011, 22990, 84

closes https://github.com/official-stockfish/Stockfish/pull/4533

bench: 3741125
2023-04-22 10:47:51 +02:00
Muzhen Gaming c90dd38903 Simplify away complexity in evaluation
Simplification STC: https://tests.stockfishchess.org/tests/view/64394bc0605991a801b4f6f0
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 72360 W: 19313 L: 19138 D: 33909
Ptnml(0-2): 206, 7883, 19800, 8112, 179

Simplification LTC: https://tests.stockfishchess.org/tests/view/6439e788c233ce943b6bdac1
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 224992 W: 60665 L: 60654 D: 103673
Ptnml(0-2): 96, 21875, 68526, 21920, 79

closes https://github.com/official-stockfish/Stockfish/pull/4530

Bench: 3709369
2023-04-22 10:43:29 +02:00
Torom f9d9c69bc3 Set the length of GIT_SHA to 8 characters
Previously, the length of git commit hashes could vary depending on the git environment.

closes https://github.com/official-stockfish/Stockfish/pull/4527

No functional change
2023-04-22 10:38:25 +02:00
MinetaS 96b6c0b36f Remove some conditions at PV improvement reduction
Non-regression STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 63664 W: 17007 L: 16823 D: 29834
Ptnml(0-2): 163, 6998, 17336, 7162, 173
https://tests.stockfishchess.org/tests/view/6430b124028b029b01ac99f2

Non-regression LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 90016 W: 24399 L: 24258 D: 41359
Ptnml(0-2): 52, 8672, 27405, 8841, 38
https://tests.stockfishchess.org/tests/view/64310e74028b029b01ad3131

closes https://github.com/official-stockfish/Stockfish/pull/4526

Bench: 3661938
2023-04-22 10:37:14 +02:00
Michael Chaly acb0d204d5 Simplify stats assignment for Pv nodes
This patch is a simplification of my recent elo gainer.
Logically the Elo gainer didn't make much sense and this patch simplifies it into smth more logical.
Instead of assigning negative bonuses to all non-first moves that enter PV nodes
we assign positive bonuses in full depth search after LMR only for moves that
will result in a fail high - thus not assigning positive bonuses
for moves that will go to pv search - so doing "almost" the same as we do in master now for them.
Logic differs for some other moves, though, but this removes some lines of code.

Passed STC:
https://tests.stockfishchess.org/tests/view/642cf5cf77ff3301150dc5ec
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 409320 W: 109124 L: 109308 D: 190888
Ptnml(0-2): 1149, 45385, 111751, 45251, 1124

Passed LTC:
https://tests.stockfishchess.org/tests/view/642fe75d20eb941419bde200
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 260336 W: 70280 L: 70303 D: 119753
Ptnml(0-2): 99, 25236, 79528, 25199, 106

closes https://github.com/official-stockfish/Stockfish/pull/4522

Bench:  4286815
2023-04-12 20:45:34 +02:00
Stefan Geschwentner 9829bceda9 Remove good killer reduction rule.
STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 246544 W: 65646 L: 65657 D: 115241
Ptnml(0-2): 706, 27350, 67138, 27405, 673
https://tests.stockfishchess.org/tests/view/642e253277ff3301150e9aa2

LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 165136 W: 44878 L: 44809 D: 75449
Ptnml(0-2): 64, 15991, 50378, 16082, 53
https://tests.stockfishchess.org/tests/view/6430db07028b029b01acd87f

closes https://github.com/official-stockfish/Stockfish/pull/4519

Bench: 3746080
2023-04-12 20:43:08 +02:00
Dubslow f66c36277f Remove nmpColor
no benefit seen, neither in game play nor for zugzwang test positions

STC: https://tests.stockfishchess.org/tests/view/642e293977ff3301150e9b55
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 161848 W: 43332 L: 43254 D: 75262
Ptnml(0-2): 418, 16987, 46058, 17021, 440

LTC: https://tests.stockfishchess.org/tests/view/642fea9420eb941419bde296
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 120208 W: 32529 L: 32418 D: 55261
Ptnml(0-2): 35, 11424, 37080, 11525, 40

closes https://github.com/official-stockfish/Stockfish/pull/4511

bench 3979409
2023-04-12 20:40:53 +02:00
peregrineshahin 4ad2713e19 Fix capturing underpromotions issue
Fix underpromotion captures are generated amongst quiets although dealt with as a capture_stage in search, this makes not skipping them when move count pruning kicks-in consistent with updating their histories amongst captures.

Passed STC:
https://tests.stockfishchess.org/tests/view/6415579f65775d3b539e7537
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 118896 W: 31678 L: 31553 D: 55665
Ptnml(0-2): 356, 12911, 32793, 13028, 360

Passed LTC:
https://tests.stockfishchess.org/tests/view/641633b965775d3b539e9e95
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 126800 W: 34255 L: 34148 D: 58397
Ptnml(0-2): 57, 12216, 38763, 12291, 73

see also discussion in https://github.com/official-stockfish/Stockfish/pull/4436
closes https://github.com/official-stockfish/Stockfish/pull/4452

bench: 3979409
2023-04-12 20:38:43 +02:00
Linmiao Xu 7bd23d4d04 Simplify away nnue scale pawn count multiplier
Removes 2x multipliers in nnue scale calculation along with the pawn count term that was recently reintroduced.

Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/64305bc720eb941419bdf72e
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 38008 W: 10234 L: 10021 D: 17753
Ptnml(0-2): 96, 4151, 10323, 4312, 122

Passed non-regression LTC:
https://tests.stockfishchess.org/tests/view/6430b76a028b029b01ac9bfd
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 91232 W: 24686 L: 24547 D: 41999
Ptnml(0-2): 30, 8721, 27986, 8838, 41

closes https://github.com/official-stockfish/Stockfish/pull/4510

bench 4017320
2023-04-10 11:03:52 +02:00
Maxim Masiutin 1a64afb1c6 Do no initialize TM in all cases
Avoid doing full TM initialization if it won't be used, avoids division by zero.

closes https://github.com/official-stockfish/Stockfish/pull/4484

No functional change
2023-04-10 10:56:42 +02:00
mstembera 7a9f67747f Reduce Position::pieces() overloads
Reduce the number of overloads for pieces() by using a more general template implementation.
Secondly simplify some code in search.cpp using the new general functionality.

TC https://tests.stockfishchess.org/tests/view/642ce27877ff3301150dc193
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 269640 W: 71775 L: 71809 D: 126056
Ptnml(0-2): 687, 27294, 78885, 27274, 680

closes https://github.com/official-stockfish/Stockfish/pull/4501

No functional change.
2023-04-10 10:51:45 +02:00
Maxim Masiutin 2f2f45f9f4 Made two specializations for affine transform easier to understand.
Added AVX-512 for the specialization for small inputs

closes https://github.com/official-stockfish/Stockfish/pull/4502

No functional change
2023-04-10 09:29:52 +02:00
MinetaS a5643b89fd Remove extraReduction
Since bestValue becomes value and beta - alpha is always non-negative,
extraReduction is always false, hence it has no effect.

This patch includes small changes to improve readability.

closes https://github.com/official-stockfish/Stockfish/pull/4505

No functional change
2023-04-10 09:28:37 +02:00
MinetaS 6e63dd63a4 Use int conversion for Option class
The current implementation generates warnings on MSVC. However, we have
no real use cases for double-typed UCI option values now. Also parameter
tuning only accepts following three types:

  int, Value, Score

closes https://github.com/official-stockfish/Stockfish/pull/4505

No functional change
2023-04-10 09:27:35 +02:00
Maxim Masiutin 5d258e168f Fix linking / character types of windows API calls
ensures large pages can be allocated again.

closes https://github.com/official-stockfish/Stockfish/pull/4509

No functional change
2023-04-10 09:22:15 +02:00
Joost VandeVondele b36d39de3d Fix rootComplexity calculation
The calculation of rootComplexity can't call eval when in check.
Doing so triggers an assert if compiled in debug mode when
the rootpos is evaluated using classical eval.

Fixes https://github.com/official-stockfish/Stockfish/issues/4512

Passed STC:
https://tests.stockfishchess.org/tests/view/6432697431feee5c6d306876
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 41096 W: 11017 L: 10815 D: 19264
Ptnml(0-2): 113, 4172, 11780, 4366, 117

Running LTC:
https://tests.stockfishchess.org/tests/view/6432974d31feee5c6d306fc0
LLR: 1.76 (-2.94,2.94) <-1.75,0.25>
Total: 73200 W: 19792 L: 19728 D: 33680
Ptnml(0-2): 24, 6659, 23182, 6699, 36

closes https://github.com/official-stockfish/Stockfish/pull/4515

No functional change
2023-04-09 15:19:49 +02:00
FauziAkram 59f2085469 Depth Tweak and tuning
tunes reduction related parameters, and introduces more reduction on found good moves.

credit for this patch goes also to candirufish Yoshie2000 dubslow peregrineshahin Vizvezdenec

Passed STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 38424 W: 10346 L: 10040 D: 18038
Ptnml(0-2): 103, 4111, 10473, 4427, 98
https://tests.stockfishchess.org/tests/view/642ca74277ff3301150db511

Passed LTC:
LLR: 2.97 (-2.94,2.94) <0.50,2.50>
Total: 136968 W: 37151 L: 36660 D: 63157
Ptnml(0-2): 43, 13052, 41808, 13533, 48
https://tests.stockfishchess.org/tests/view/642d632377ff3301150dddbe

closes https://github.com/official-stockfish/Stockfish/pull/4499

bench: 3672914
2023-04-07 09:56:35 +02:00
Michael Chaly 510aca1ef6 Assign negative stat bonuses for quiet moves at Pv nodes
This patch assigns negative stat bonuses for quiet moves
at pv nodes which are searched at depth greater than
this node assumes, so are extended.

Passed STC:
https://tests.stockfishchess.org/tests/view/6426198bdb43ab2ba6f9cfa2
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 548944 W: 147287 L: 146254 D: 255403
Ptnml(0-2): 1662, 59772, 150671, 60605, 1762

Passed LTC:
https://tests.stockfishchess.org/tests/view/642be4f177ff3301150d892d
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 93352 W: 25400 L: 24994 D: 42958
Ptnml(0-2): 44, 8817, 28547, 9225, 43

closes https://github.com/official-stockfish/Stockfish/pull/4495

bench 5044536
2023-04-05 08:23:54 +02:00
Muzhen Gaming a2737d8bb5 Simplify away piece count condition for useClassical
Simplify away the piece count condition for useClassical. In compensation, the psq requirement is increased by 15%.

Also updated the Elo estimate for useClassical, based on recent testing.

Simplification STC:
https://tests.stockfishchess.org/tests/view/642acbb577ff3301150d3ef5
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 51984 W: 13906 L: 13707 D: 24371
Ptnml(0-2): 150, 5638, 14227, 5817, 160

Simplification LTC:
https://tests.stockfishchess.org/tests/view/642b9c5777ff3301150d778a
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 119696 W: 32412 L: 32300 D: 54984
Ptnml(0-2): 53, 11529, 36567, 11651, 48

closes https://github.com/official-stockfish/Stockfish/pull/4494

Bench: 5089321
2023-04-05 08:18:53 +02:00
FauziAkram 9a42bbdf31 Parameters Tweak
Passed STC
LLR: 3.22 (-2.94,2.94) <0.00,2.00>
Total: 664048 W: 177526 L: 176301 D: 310221
Ptnml(0-2): 2002, 72968, 180891, 74129, 2034
https://tests.stockfishchess.org/tests/view/64219901db43ab2ba6f901fa

Passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 77576 W: 21125 L: 20750 D: 35701
Ptnml(0-2): 24, 7350, 23669, 7717, 28
https://tests.stockfishchess.org/tests/view/642abe3377ff3301150d3a16

closes https://github.com/official-stockfish/Stockfish/pull/4493

bench: 4522076
2023-04-05 08:15:34 +02:00
Dubslow 77e2b915e1 Simplifiy TM's root complexity
Also requires moving optimism initialization, this is a very early `evaluate()` call.

STC: https://tests.stockfishchess.org/tests/view/6428c39677ff3301150ca0d7
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 51256 W: 13805 L: 13612 D: 23839
Ptnml(0-2): 145, 5283, 14592, 5450, 158

LTC: https://tests.stockfishchess.org/tests/view/64296ff377ff3301150cc519
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 106968 W: 28951 L: 28830 D: 49187
Ptnml(0-2): 47, 9746, 33789, 9843, 59

closes https://github.com/official-stockfish/Stockfish/pull/4492

no functional change
2023-04-05 08:13:34 +02:00
Miguel Lahoz 1fee996999 Remove unneeded bitboard from MP
Recent simplification has removed the need for an extra bitboard in MP struct.
Use a local variable instead.

STC: Passed Non-regression test
https://tests.stockfishchess.org/tests/view/64294ae677ff3301150cba16
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 64872 W: 17383 L: 17203 D: 30286
Ptnml(0-2): 179, 6675, 18546, 6859, 177

closes https://github.com/official-stockfish/Stockfish/pull/4490

No functional change.
2023-04-05 08:10:34 +02:00
FauziAkram 6a6e32dfc8 Decrease Depth more for positions not in TT.
If the position is not in TT, decrease depth by 2
or by 4 if the TT entry for the current position was hit
and the stored depth is greater than or equal to the current depth.

Many thanks to Vizvezdenec as the main idea was his.

Passed STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 70664 W: 18995 L: 18639 D: 33030
Ptnml(0-2): 228, 7712, 19090, 8080, 222
https://tests.stockfishchess.org/tests/view/64258a8bdb43ab2ba6f9b682

Passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 85040 W: 23227 L: 22836 D: 38977
Ptnml(0-2): 26, 8115, 25867, 8466, 46
https://tests.stockfishchess.org/tests/view/64262057db43ab2ba6f9d0e7

closes https://github.com/official-stockfish/Stockfish/pull/4482

bench: 4380438
2023-04-01 16:28:52 +02:00
Maxim Masiutin bc50378ff1 Replace deprecated icc with icx
Replace the deprecated Intel compiler icc with its newer icx variant.
This newer compiler is based on clang, and yields good performance.
As before, currently only linux is supported.

closes https://github.com/official-stockfish/Stockfish/pull/4478

No functional change
2023-04-01 16:16:48 +02:00
MinetaS 38a80c0b47 Simplify away complexityAverage
Instead of tracking the average of complexity values, calculate
complexity of root position at the beginning of the search and use it as
a scaling factor in time management.

Passed non-regression STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 58752 W: 15738 L: 15551 D: 27463
Ptnml(0-2): 164, 6194, 16478, 6371, 169
https://tests.stockfishchess.org/tests/view/6423010edb43ab2ba6f9424a

Passed non-regression LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 92872 W: 24865 L: 24729 D: 43278
Ptnml(0-2): 38, 8652, 28929, 8770, 47
https://tests.stockfishchess.org/tests/view/6423c1f0db43ab2ba6f9644f

closes https://github.com/official-stockfish/Stockfish/pull/4472

No functional change
2023-04-01 16:14:30 +02:00
Joost VandeVondele 66bf45b99e Stringify the git info passed
avoid escaping the string in the Makefile.

Alternative to https://github.com/official-stockfish/Stockfish/pull/4476

closes https://github.com/official-stockfish/Stockfish/pull/4481

No functional change.
2023-04-01 15:58:05 +02:00
Muzhen Gaming c3c46feebb Remove reduction for moving threatened piece
Simplify away "Decrease reduction if we move a threatened piece".

Running a dbg_hit_on() shows that this line is only called ~0.12% of the time.

Simplification STC: https://tests.stockfishchess.org/tests/view/641ec2dcdb43ab2ba6f88103
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 146128 W: 39168 L: 39070 D: 67890
Ptnml(0-2): 466, 16117, 39830, 16155, 496

Simplification LTC: https://tests.stockfishchess.org/tests/view/64200689db43ab2ba6f8bca8
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 248016 W: 66703 L: 66714 D: 114599
Ptnml(0-2): 105, 24202, 75406, 24189, 106

closes https://github.com/official-stockfish/Stockfish/pull/4471

Bench: 4961236
2023-04-01 15:53:46 +02:00
Maxim Masiutin e8742bdab3 Made advanced Windows API calls dynamically linked
Made advanced Windows API calls (those from Advapi32.dll) dynamically
linked to avoid link errors when compiling using
Intel icx compiler for Windows.

https://github.com/official-stockfish/Stockfish/pull/4467

No functional change
2023-04-01 15:48:47 +02:00
Maxim Masiutin 7a6fa34f5f Improve compatibility
this makes it easier to compile under MSVC, even though we recommend gcc/clang for production compiles at the moment.

In Win32 API, by default, most null-terminated character strings arguments are of wchar_t (UTF16, formerly UCS16-LE) type, i.e. 2 bytes (at least) per character. So, src/misc.cpp should have proper type. Respectively, for src/syzygy/tbprobe.cpp, in Widows, file paths should be std::wstring rather than std::string. However, this requires a very big number of changes, since the config files are also keeping the 8-bit-per-character std::string strings. Therefore, just one change of using 8-byte-per-character CreateFileA make it compile under MSVC.

closes https://github.com/official-stockfish/Stockfish/pull/4438

No functional change
2023-04-01 15:36:08 +02:00
peregrineshahin 3f01e3f41f Allow PvNode in futility pruning for captures.
Passed non-regression STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 148128 W: 39428 L: 39333 D: 69367
Ptnml(0-2): 492, 16326, 40315, 16457, 474
https://tests.stockfishchess.org/tests/view/641c2dbfdb43ab2ba6f804e8

Passed non-regression LTC:
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 376256 W: 100906 L: 101039 D: 174311
Ptnml(0-2): 186, 36697, 114494, 36566, 185
https://tests.stockfishchess.org/tests/view/641d33b2db43ab2ba6f83338

closes https://github.com/official-stockfish/Stockfish/pull/4470

bench: 4935616
2023-03-29 21:46:23 +02:00
Miguel Lahoz a9c26357de Clean up repetitive declarations for see_ge
The occupied bitboard is only used in one place and is otherwise thrown away.
To simplify use, see_ge function can instead be overloaded.
Repetitive declarations for occupied bitboard can be removed.

Passed non-regression test
https://tests.stockfishchess.org/tests/view/6421c286db43ab2ba6f908eb
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 48912 W: 13196 L: 13001 D: 22715
Ptnml(0-2): 146, 5003, 13967, 5190, 150

closes https://github.com/official-stockfish/Stockfish/pull/4469

No functional change.
2023-03-29 21:43:07 +02:00
Linmiao Xu 37160c4b16 Update default net to nn-dabb1ed23026.nnue
Created by retraining the master net with these modifications:

* New filtering methods for existing data from T80 sep+oct2022, T79 apr2022, T78 jun+jul+aug+sep2022, T77 dec2021
* Adding new filtered data from T80 aug2022 and T78 apr+may2022
* Increasing early-fen-skipping from 28 to 30

```
python3 easy_train.py \
  --experiment-name leela96-dfrc99-T80novT79mayT60novdec-v2-T80augsepoctT79aprT78aprtosep-v6-T77dec-v3-sk30 \
  --training-dataset /data/leela96-dfrc99-T80novT79mayT60novdec-v2-T80augsepoctT79aprT78aprtosep-v6-T77dec-v3.binpack \
  --nnue-pytorch-branch linrock/nnue-pytorch/misc-fixes \
  --start-from-engine-test-net True \
  --early-fen-skipping 30 \
  --max_epoch 900 \
  --start-lambda 1.0 \
  --end-lambda 0.7 \
  --lr 4.375e-4 \
  --gamma 0.995 \
  --tui False \
  --gpus "0," \
  --seed $RANDOM
```

The v3 filtering used for data from T77dec 2021 differs from v2 filtering in that:

* To improve binpack compression, positions after ply 28 were skipped during training by setting position scores to VALUE_NONE (32002) instead of removing them entirely
* All early-game positions with ply <= 28 were removed to maximize binpack compression
* Only bestmove captures at d6pv2 search were skipped, not 2nd bestmove captures
* Binpack compression was repaired for the remaining positions by effectively replacing bestmoves with "played moves" to maintain contiguous sequences of positions in the training game data

After improving binpack compression, The T77 dec2021 data size was reduced from 95G to 19G.

The v6 filtering used for data from T80augsepoctT79aprT78aprtosep 2022 differs from v2 in that:

* All positions with only one legal move were removed
* Tighter score differences at d6pv2 search were used to remove more positions with only one good move than before
* d6pv2 search was not used to remove positions where the best 2 moves were captures

```
python3 interleave_binpacks.py \
  nn-547-dataset/leela96-eval-filt-v2.binpack \
  nn-547-dataset/dfrc99-eval-filt-v2.binpack \
  nn-547-dataset/test80-nov2022-12tb7p-eval-filt-v2-d6.binpack \
  nn-547-dataset/T79-may2022-12tb7p-eval-filt-v2.binpack \
  nn-547-dataset/T60-nov2021-12tb7p-eval-filt-v2.binpack \
  nn-547-dataset/T60-dec2021-12tb7p-eval-filt-v2.binpack \
  filt-v6/test80-aug2022-16tb7p-filter-v6.binpack \
  filt-v6/test80-sep2022-16tb7p-filter-v6.binpack \
  filt-v6/test80-oct2022-16tb7p-filter-v6.binpack \
  filt-v6/test79-apr2022-16tb7p-filter-v6.binpack \
  filt-v6/test78-aprmay2022-16tb7p-filter-v6.binpack \
  filt-v6/test78-junjulaug2022-16tb7p-filter-v6.binpack \
  filt-v6/test78-sep2022-16tb7p-filter-v6.binpack \
  filt-v3/test77-dec2021-16tb7p-filt-v3.binpack \
  /data/leela96-dfrc99-T80novT79mayT60novdec-v2-T80augsepoctT79aprT78aprtosep-v6-T77dec-v3.binpack
```

The code for the new data filtering methods is available at:
https://github.com/linrock/Stockfish/tree/nnue-data-v3/nnue-data

The code for giving hexword names to .nnue files is at:
https://github.com/linrock/nnue-namer

Links for downloading the training data components can be found at:
https://robotmoon.com/nnue-training-data/

Local elo at 25k nodes per move:
nn-epoch779.nnue : 0.6 +/- 3.1

Passed STC:
https://tests.stockfishchess.org/tests/view/64212412db43ab2ba6f8efb0
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 82256 W: 22185 L: 21809 D: 38262
Ptnml(0-2): 286, 9065, 22067, 9407, 303

Passed LTC:
https://tests.stockfishchess.org/tests/view/64223726db43ab2ba6f91d6c
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 30840 W: 8437 L: 8149 D: 14254
Ptnml(0-2): 14, 2891, 9323, 3177, 15

closes https://github.com/official-stockfish/Stockfish/pull/4465

bench 5101970
2023-03-29 21:37:52 +02:00
Sebastian Buchwald 43108a6198 Reuse existing functions to read/write array of network parameters
closes https://github.com/official-stockfish/Stockfish/pull/4463

No functional change
2023-03-29 21:36:27 +02:00
MinetaS 587bc647d7 Remove non_pawn_material in NNUE::evaluate
After "Use NNUE complexity in search, retune related parameters" commit,
the effect of non-pawn material adjustment has been nearly diminished.
This patch removes pos.non_pawn_material as a simplification, which
passed non-regression tests with both STC and LTC.

Passed non-regression STC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 75152 W: 20030 L: 19856 D: 35266
Ptnml(0-2): 215, 8281, 20459, 8357, 264
https://tests.stockfishchess.org/tests/view/641ab471db43ab2ba6f7bc58

Passed non-regression LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 193864 W: 51870 L: 51829 D: 90165
Ptnml(0-2): 86, 18968, 58794, 18987, 97
https://tests.stockfishchess.org/tests/view/641b4fe6db43ab2ba6f7db96

closes https://github.com/official-stockfish/Stockfish/pull/4461

Bench: 5020718
2023-03-25 09:25:49 +01:00
Michael Chaly 1b5738e0c9 Simplify statScore initialization
This patch simplifies initialization of statScore to "always set it up to 0" instead of setting it up to 0 two plies deeper.
Reason for why it was done in previous way partially was because of LMR usage of previous statScore which was simplified long time ago so it makes sense to make in more simple there.

Passed STC:
https://tests.stockfishchess.org/tests/view/641a86d1db43ab2ba6f7b31d
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 115648 W: 30895 L: 30764 D: 53989
Ptnml(0-2): 368, 12741, 31473, 12876, 366

Passed LTC:
https://tests.stockfishchess.org/tests/view/641b1c31db43ab2ba6f7d17a
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 175576 W: 47122 L: 47062 D: 81392
Ptnml(0-2): 91, 17077, 53390, 17141, 89

closes https://github.com/official-stockfish/Stockfish/pull/4460

bench 5081969
2023-03-25 09:22:25 +01:00
FauziAkram b973e40e45 Update Elo estimates for terms in search
Setting the Elo value of some functions which were not set before.
All tests run at 10+0.1 (STC), 25000 games (Same as #4294).
Book used: UHO_XXL_+0.90_+1.19.epd

Values are rounded to the nearest non-negative integer.

Test links:
https://tests.stockfishchess.org/tests/view/6419ab5b65775d3b539f46c6
https://tests.stockfishchess.org/tests/view/6419adb465775d3b539f4730
https://tests.stockfishchess.org/tests/view/6419ae9c65775d3b539f4756
https://tests.stockfishchess.org/tests/view/6419b03f65775d3b539f47a8
https://tests.stockfishchess.org/tests/view/6419b35d65775d3b539f4860
https://tests.stockfishchess.org/tests/view/6419b6b965775d3b539f48e6
https://tests.stockfishchess.org/tests/view/6419cade65775d3b539f4cd5
https://tests.stockfishchess.org/tests/view/6419cbb565775d3b539f4d01
https://tests.stockfishchess.org/tests/view/6419cc6965775d3b539f4d1e

closes https://github.com/official-stockfish/Stockfish/pull/4459

No functional change
2023-03-25 09:20:58 +01:00
pb00067 24b37e4586 Verified SEE pruning for capturing and checking moves.
Patch analyzes field after SEE exchanges concluded with a recapture by
the opponent:
if opponent Queen/Rook/King results under attack after the exchanges, we
consider the move sharp and don't prune it.

Important note:
By accident I forgot to adjust 'occupied' when the king takes part in
the exchanges.
As result of this a move is considered sharp too, when opponent king
apparently can evade check by recapturing.
Surprisingly this seems contribute to patch's strength.

STC:
https://tests.stockfishchess.org/tests/view/640b16132644b62c33947397
LLR: 2.96 (-2.94,2.94) <0.00,2.00>
Total: 116400 W: 31239 L: 30817 D: 54344
Ptnml(0-2): 350, 12742, 31618, 13116, 374

LTC:
https://tests.stockfishchess.org/tests/view/640c88092644b62c3394c1c5
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 177600 W: 47988 L: 47421 D: 82191
Ptnml(0-2): 62, 16905, 54317, 17436, 80

closes https://github.com/official-stockfish/Stockfish/pull/4453

bench: 5012145
2023-03-25 09:17:44 +01:00
pb00067 02e4697055 Remove 'si' StateInfo variable/parameter.
Since st is a member of position we don't need to pass it separately as
parameter.

While being there also remove some line in pos_is_ok, where
a copy of StateInfo was made by using default copy constructor and
then verified it's correctedness by doing a memcmp.
There is no point in doing that.

Passed non-regression test
https://tests.stockfishchess.org/tests/view/64098d562644b62c33942b35
LLR: 3.24 (-2.94,2.94) <-1.75,0.25>
Total: 548960 W: 145834 L: 146134 D: 256992
Ptnml(0-2): 1617, 57652, 156261, 57314, 1636

closes https://github.com/official-stockfish/Stockfish/pull/4444

No functional change
2023-03-19 11:29:35 +01:00
disservin af4b62a593 NNUE namespace cleanup
This patch moves the nnue namespace in the appropiate header that correspondes with the definition.
It also makes navigation a bit easier.

closes https://github.com/official-stockfish/Stockfish/pull/4445

No functional change
2023-03-19 11:27:15 +01:00
peregrineshahin 515b66f188 Fix null move issue
Fix altering for stats landing on B1 Square after a null move and fix considering counter-moves on A1 for root node.

fixes https://github.com/official-stockfish/Stockfish/issues/4333 by preventing calls to from_sq and to_sq functions over null-moves and none-moves.

closes https://github.com/official-stockfish/Stockfish/pull/4448

bench: 4980082
2023-03-19 11:25:48 +01:00
pb00067 f0556dcbe3 Small cleanups
remove some unneeded assignments, typos, incorrect comments, add authors entry.

closes https://github.com/official-stockfish/Stockfish/pull/4417

no functional change
2023-03-14 08:38:02 +01:00
mstembera 7077fbdd14 Remove redundant condition from capture_stage()
Change a non functional promotion check to an assert.

closes https://github.com/official-stockfish/Stockfish/pull/4436

No functional change
2023-03-14 08:29:19 +01:00
Sebastian Buchwald d1e17989b5 Fix Makefile for clang 16
The clang 16 release will remove the -fexperimental-new-pass-manager
flag (see https://github.com/llvm/llvm-project/commit/69b2b7282e92a1b576b7bd26f3b16716a5027e8e).
Thus, the commit adapts the Makefile to use this flag only for older
clang versions.

closes https://github.com/official-stockfish/Stockfish/pull/4437

No functional change
2023-03-14 08:25:14 +01:00
Alfredo Menezes 55896a1384 Change mode of incbin.h
Keep incbin.h with the same mode as the other source files.

A mode diff might show up when working with patch files or sending the source code between devices.
This patch should fix such behaviour.

closes https://github.com/official-stockfish/Stockfish/pull/4442

No functional change
2023-03-14 08:23:50 +01:00
Michael Chaly 78532af9dc Do more singular extensions
This patch continues trend of last VLTC tuning - as measured by dubslow
most of it gains was in lowering marging in calculation of singularBeta.
This patch is a manual adjustment on top of it - it lowers multiplier
of depth in calculation of singularBeta even further, from 2/3 to 1,5/2,5.

Was negative at STC:
https://tests.stockfishchess.org/tests/view/64089c632644b62c3393fc12
Elo: -2.49 +-1.7 (95%) LOS: 0.2%
Total: 40000 W: 10601 L: 10888 D: 18511
Ptnml(0-2): 123, 4580, 10875, 4305, 117
nElo: -5.03 +-3.4 (95%) PairsRatio: 0.94

Passed 180+1.8 SPRT:
https://tests.stockfishchess.org/tests/view/640096dae74a12625bcf3b33
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 160952 W: 43753 L: 43342 D: 73857
Ptnml(0-2): 25, 13984, 52039, 14411, 17

Passed 60+0.6 8 threads SPRT:
https://tests.stockfishchess.org/tests/view/640dca8e65775d3b539cb7f6
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 38824 W: 10825 L: 10554 D: 17445
Ptnml(0-2): 0, 2939, 13268, 3200, 5

closes https://github.com/official-stockfish/Stockfish/pull/4443

bench 4776866
2023-03-14 08:22:40 +01:00
Dubslow a48573e15f More negative extensions on nonsingular nonpv nodes.
Following up the previous gainer also in this nonsingular node
section of code. Credit shared with @FauziAkram for realizing
this nonsingular node stuff had some potential, and @XInTheDark
for reminding us that !PvNodes better handle extensions/reductions
than Pv.

Passed STC: https://tests.stockfishchess.org/tests/view/640a7bb32644b62c339457c3
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 136776 W: 36598 L: 36149 D: 64029
Ptnml(0-2): 439, 14834, 37384, 15301, 430

Passed LTC: https://tests.stockfishchess.org/tests/view/640c43a02644b62c3394b23c
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 79536 W: 21363 L: 20984 D: 37189
Ptnml(0-2): 28, 7525, 24285, 7900, 30

closes https://github.com/official-stockfish/Stockfish/pull/4441

Bench: 4444953
2023-03-14 00:41:42 +01:00
Michael Chaly 39da50ed23 Do more negative extensions
This patch does negatively extend transposition table move if singular search failed and tt value is not bigger than alpha.
Logic is close to what we had before recent simplification of negative extensions but uses or condition instead of and condition.

Passed STC:
https://tests.stockfishchess.org/tests/view/6404c8102644b62c33934607
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 119040 W: 31841 L: 31416 D: 55783
Ptnml(0-2): 356, 13070, 32292, 13397, 405

Passed LTC:
https://tests.stockfishchess.org/tests/view/6405abda2644b62c33937119
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 47216 W: 12816 L: 12496 D: 21904
Ptnml(0-2): 12, 4500, 14286, 4776, 34

closes https://github.com/official-stockfish/Stockfish/pull/4430

bench 4747020
2023-03-08 07:16:09 +01:00
Joost VandeVondele 6ce225bb4c Fix TB after capture_stage fix
https://github.com/official-stockfish/Stockfish/commit/5c75c1c2fbb7bb4f0bf7c44fb855c415b788cbf7
introduced a capture_stage() function, but TB usage needs a pure capture() function.

closes https://github.com/official-stockfish/Stockfish/pull/4428

No functional change.
2023-03-08 07:14:49 +01:00
Maxim Masiutin 70dfa141d5 Clarify the description of the x86-64-vnni256 and x86-64-avxvnni architectures
Now it is clearly explained that "x86-64-vnni256" requires full
support of AVX512-VNNI, but only 256-bit operands are used.

closes https://github.com/official-stockfish/Stockfish/pull/4427

No functional change
2023-03-08 07:14:07 +01:00
Joost VandeVondele cdec775a15 Add CITATION.cff file
Make the stockfish software more easily citable, for example in academic papers.

fixes https://github.com/official-stockfish/Stockfish/issues/4419
closes https://github.com/official-stockfish/Stockfish/pull/4422

No functional change
2023-03-05 16:16:16 +01:00
dav1312 3a634f5282 Update README.md
Update and simplify the readme, removing duplicated and outdated stuff and pointing to the new wiki

closes https://github.com/official-stockfish/Stockfish/pull/4421

No functional change
2023-03-05 16:15:12 +01:00
disservin 5c589142ae Add wiki to artifacts
snapshot the wiki https://github.com/official-stockfish/stockfish/wiki as part of the artifacts generated.
This will allow future release to include the wiki pages as a form of documentation

closes https://github.com/official-stockfish/Stockfish/pull/4420

No functional change
2023-03-05 16:14:07 +01:00
Michael Chaly 5c75c1c2fb Fix duplicated moves generation in movepicker
in a some of cases movepicker returned some moves more than once which lead
to them being searched more than once. This bug was possible because of how
we use queen promotions - they are generated as a captures but are not
included in position function which checks if move is a capture. Thus if
any refutation (killer or countermove) was a queen promotion it was
searched twice - once as a capture and one as a refutation.

This patch affects various things, namely stats assignments for queen promotions
and other moves if best move is queen promotion,
also some heuristics in search and qsearch.

With this patch every queen promotion is now considered a capture.

After this patch number of found duplicated moves is 0 during normal 13 depth bench run.

Passed STC:
https://tests.stockfishchess.org/tests/view/63f77e01e74a12625bcd87d7
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 80920 W: 21455 L: 21289 D: 38176
Ptnml(0-2): 198, 8839, 22241, 8963, 219

Passed LTC:
https://tests.stockfishchess.org/tests/view/63f7e020e74a12625bcd9a76
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 89712 W: 23674 L: 23533 D: 42505
Ptnml(0-2): 24, 8737, 27202, 8860, 33

closes https://github.com/official-stockfish/Stockfish/pull/4405

bench 4681731
2023-03-05 16:06:03 +01:00
Linmiao Xu 876906965b Update default net to nn-52471d67216a.nnue
Created by retraining the master net with modifications to the previous best dataset:

* Improving T80 oct+nov 2022 endgame lambda accuracy by rescoring with 12-16tb of syzygy 7p tablebases
* Filtering T78 jun+jul+aug 2022 with d6pv2 search to remove positions with bestmove captures or one good move
* Adding T80 sep 2022 data, rescored with 16tb of 7p tablebases, unfiltered

Trained with max-epoch 900, end-lambda 0.7, and early-fen-skipping 28.

```
python3 easy_train.py \
  --experiment-name leela96-dfrc99-T80octnovT79aprmayT78junjulaugT60novdec-filt-v2-T78sep12tb7p-T77decT80sep16tb7p-lambda7-sk28 \
  --training-dataset /data/leela96-dfrc99-T80octnovT79aprmayT78junjulaugT60novdec-filt-v2-T78sep12tb7p-T77decT80sep16tb7p.binpack \
  --nnue-pytorch-branch linrock/nnue-pytorch/easy-train-early-fen-skipping \
  --early-fen-skipping 28 \
  --start-from-engine-test-net True \
  --gpus "0," \
  --max_epoch 900 \
  --start-lambda 1.0 \
  --end-lambda 0.7 \
  --gamma 0.995 \
  --lr 4.375e-4 \
  --tui False \
  --seed $RANDOM
```

Training data was rescored and d6pv2 filtered in the same way as recent best datasets.
For preparing the merged training dataset:

```
python3 interleave_binpacks.py \
  leela96-eval-filt-v2.binpack \
  dfrc99-eval-filt-v2.binpack \
  test80-oct2022-16tb7p-eval-filt-v2-d6.binpack \
  test80-nov2022-12tb7p-eval-filt-v2-d6.binpack \
  T79-apr2022-12tb7p-eval-filt-v2.binpack \
  T79-may2022-12tb7p-eval-filt-v2.binpack \
  test78-junjulaug2022-16tb7p-eval-filt-v2-d6.binpack \
  T60-nov2021-12tb7p-eval-filt-v2.binpack \
  T60-dec2021-12tb7p-eval-filt-v2.binpack \
  T78-sep2022-12tb7p.binpack \
  test77-dec2021-16gb7p.binpack \
  test80-sep2022-16tb7p.binpack \
  /data/leela96-dfrc99-T80octnovT79aprmayT78junjulaugT60novdec-filt-v2-T78sep12tb7p-T77decT80sep16tb7p.binpack
```

Links for downloading the training data components can be found at:
https://robotmoon.com/nnue-training-data/

Local elo at 25k nodes per move:
nn-epoch839.nnue : 0.6 +/- 1.4

Passed STC:
https://tests.stockfishchess.org/tests/view/63f9ab4be74a12625bcdf02e
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 84656 W: 22681 L: 22302 D: 39673
Ptnml(0-2): 271, 9343, 22734, 9696, 284

Passed LTC:
https://tests.stockfishchess.org/tests/view/63fa3833e74a12625bce0c0e
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 184664 W: 49933 L: 49344 D: 85387
Ptnml(0-2): 111, 17977, 55561, 18578, 105

closes https://github.com/official-stockfish/Stockfish/pull/4416

bench: 4814343
2023-02-27 22:07:52 +01:00
Dubslow 6adbc6fa05 Late counter bonus: boost underestimated moves
The idea here is very intuitive: since we've just proven that the move is good, then if it previously had poor stats, boost those stats more than otherwise.

Passed STC: https://tests.stockfishchess.org/tests/view/63fb504ce74a12625bce4154
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 21128 W: 5763 L: 5481 D: 9884
Ptnml(0-2): 52, 2212, 5759, 2484, 57

Passed LTC: https://tests.stockfishchess.org/tests/view/63fb7825e74a12625bce491b
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 91904 W: 24764 L: 24359 D: 42781
Ptnml(0-2): 45, 8735, 27984, 9146, 42

closes https://github.com/official-stockfish/Stockfish/pull/4415

bench 4318808
2023-02-27 22:03:50 +01:00
Sebastian Buchwald 564456a6a8 Unify type alias declarations
The commit unifies the declaration of type aliases by replacing all
typedefs with corresponding using statements.

closing https://github.com/official-stockfish/Stockfish/pull/4412

No functional change
2023-02-27 08:29:47 +01:00
Stefan Geschwentner ff5a6f8df1 NNUE accumulator update in probcut.
Call the recently added hint function for NNUE accumulator update after a failed probcut search.
In this case we already searched at least some captures and tt move which, however, is not sufficient for a cutoff.
So it seems we have a greater chance that the full search will also have no cutoff and hence all moves have to be searched.

STC: https://tests.stockfishchess.org/tests/view/63fa74a4e74a12625bce1823
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 70096 W: 18770 L: 18423 D: 32903
Ptnml(0-2): 191, 7342, 19654, 7651, 210

To be sure that we have no heavy interaction retest on top of #4410.

Rebased STC: https://tests.stockfishchess.org/tests/view/63fb2f62e74a12625bce3b03
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 137688 W: 36790 L: 36349 D: 64549
Ptnml(0-2): 397, 14373, 38919, 14702, 453

closes https://github.com/official-stockfish/Stockfish/pull/4411

No functional change
2023-02-27 08:28:45 +01:00
pb00067 728b963614 Use common_parent_position hint also at PVNodes TT hits.
Credits to Stefan Geschwentner (locutus2) showing that the hint
is useful on PvNodes. In contrast to his test,
this version avoids to use the hint when in check.
I believe checking positions aren't good candidates for the hint
because:
- evasion moves are rather few, so a checking pos. has much less childs
than a normal position
- if the king has to move the NNUE eval can't use incremental updates,
  so the child nodes have to do a full refresh anyway.

Passed STC:
https://tests.stockfishchess.org/tests/view/63f9c5b1e74a12625bcdf585
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 124472 W: 33268 L: 32846 D: 58358
Ptnml(0-2): 350, 12986, 35170, 13352, 378

closes https://github.com/official-stockfish/Stockfish/pull/4410

no functional change
2023-02-27 08:27:26 +01:00
Alfredo Menezes 98dafda6c8 Simplify condition in step 15
Remove 'ttValue <= alpha' check for negative extension in singular search.
Also apply some small code style changes.

STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 127888 W: 33766 L: 33651 D: 60471
Ptnml(0-2): 303, 14082, 35089, 14137, 333
https://tests.stockfishchess.org/tests/view/63f79528e74a12625bcd8c05

LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 89048 W: 23924 L: 23782 D: 41342
Ptnml(0-2): 27, 8635, 27065, 8763, 34
https://tests.stockfishchess.org/tests/view/63f82177e74a12625bcda6f4

LTC (retest):
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 196360 W: 52514 L: 52475 D: 91371
Ptnml(0-2): 103, 19066, 59780, 19151, 80
https://tests.stockfishchess.org/tests/view/63f934bfe74a12625bcdd929

closes https://github.com/official-stockfish/Stockfish/pull/4407

Bench: 5310866
2023-02-27 08:26:29 +01:00
Michael Chaly 472e726bff Search tuning at very long time control
This patch is a result of tuning session of approximately 100k games at 120+1.2.
Biggest changes are in extensions, stat bonus and depth reduction for nodes without a tt move.

Failed STC:
https://tests.stockfishchess.org/tests/view/63f72c72e74a12625bcd7938
LLR: -2.94 (-2.94,2.94) <0.00,2.00>
Total: 13872 W: 3535 L: 3769 D: 6568
Ptnml(0-2): 56, 1621, 3800, 1419, 40

Close to neutral at LTC:
https://tests.stockfishchess.org/tests/view/63f738f5e74a12625bcd7b8a
Elo: 0.80 +-1.2 (95%) LOS: 90.0%
Total: 60000 W: 16213 L: 16074 D: 27713
Ptnml(0-2): 24, 5718, 18379, 5853, 26
nElo: 1.82 +-2.8 (95%) PairsRatio: 1.02

Passed 180+1.8 VLTC:
https://tests.stockfishchess.org/tests/view/63f868f3e74a12625bcdb33e
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 15864 W: 4449 L: 4202 D: 7213
Ptnml(0-2): 1, 1301, 5083, 1544, 3

Passed 60+0.6 8 threads SMP VLTC:
https://tests.stockfishchess.org/tests/view/63f8a5d6e74a12625bcdbdb3
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 6288 W: 1821 L: 1604 D: 2863
Ptnml(0-2): 0, 402, 2123, 619, 0

closes https://github.com/official-stockfish/Stockfish/pull/4406

bench 4705194
2023-02-24 20:14:44 +01:00
Sebastian Buchwald 29b5ad5dea Fix typo in method name
closes https://github.com/official-stockfish/Stockfish/pull/4404

No functional change
2023-02-24 20:12:53 +01:00
Linmiao Xu 69639d764b Reintroduce nnue pawn scaling with lower lazy thresholds
Params found with the nevergrad TBPSA optimizer via nevergrad4sf modified to:

* use SPRT LLR with fishtest STC elo gainer bounds [0, 2] as the objective function
* increase the game batch size after each new optimal point is found

The params were the optimal point after TBPSA iteration 7 and 160 nevergrad evaluations with:

* initial batch size of 96 games per evaluation
* batch size increase of 64 games after each iteration
* a budget of 512 evaluations
* TC: fixed 1.5 million nodes per move, no time limit

nevergrad4sf enables optimizing stockfish params with TBPSA:
https://github.com/vondele/nevergrad4sf

Using pentanomial game results with smaller game batch sizes was inspired by:

Use of SPRT LLR calculated from pentanomial game results as the objective function was an experiment at maximizing the information from game batches to reduce the computational cost for TBPSA to converge on good parameters.

For the exact code used to find the params:
https://github.com/linrock/tuning-fork

Passed STC:
https://tests.stockfishchess.org/tests/view/63f4ef5ee74a12625bcd114a
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 66552 W: 17736 L: 17390 D: 31426
Ptnml(0-2): 164, 7229, 18166, 7531, 186

Passed LTC:
https://tests.stockfishchess.org/tests/view/63f56028e74a12625bcd2550
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 71264 W: 19150 L: 18787 D: 33327
Ptnml(0-2): 23, 6728, 21771, 7083, 27

closes https://github.com/official-stockfish/Stockfish/pull/4401

bench 3687580
2023-02-23 13:27:57 +01:00
Joost VandeVondele 08385527dd Introduce a function to compute NNUE accumulator
This patch introduces `hint_common_parent_position()` to signal that potentially several child nodes will require an NNUE eval. By populating explicitly the accumulator, these subsequent evaluations can be performed more efficiently.

This was based on the observation that calculating the evaluation in an excluded move position yielded a significant Elo gain, even though the evaluation itself was already available (work by pb00067).

Sopel wrote the code to perform just the accumulator update. This PR is based on cleaned up code that

passed STC:
https://tests.stockfishchess.org/tests/view/63f62f9be74a12625bcd4aa0
 LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 110368 W: 29607 L: 29167 D: 51594
Ptnml(0-2): 41, 10551, 33572, 10967, 53

and in an the earlier (equivalent) version

passed STC:
https://tests.stockfishchess.org/tests/view/63f3c3fee74a12625bcce2a6
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 47552 W: 12786 L: 12467 D: 22299
Ptnml(0-2): 120, 5107, 12997, 5438, 114

passed LTC:
https://tests.stockfishchess.org/tests/view/63f45cc2e74a12625bccfa63
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 110368 W: 29607 L: 29167 D: 51594
Ptnml(0-2): 41, 10551, 33572, 10967, 53

closes https://github.com/official-stockfish/Stockfish/pull/4402

Bench: 3726250
2023-02-23 13:25:35 +01:00
Sebastian Buchwald 77dfcbedce Remove unused macros
closes https://github.com/official-stockfish/Stockfish/pull/4397

No functional change
2023-02-23 13:24:37 +01:00
Sebastian Buchwald b4ad3a3c4b Add support for ARM dot product instructions
The sdot instruction computes (and accumulates) a signed dot product,
which is quite handy for Stockfish's NNUE code. The instruction is
optional for Armv8.2 and Armv8.3, and mandatory for Armv8.4 and above.

The commit adds a new 'arm-dotprod' architecture with enabled dot
product support. It also enables dot product support for the existing
'apple-silicon' architecture, which is at least Armv8.5.

The following local speed test was performed on an Apple M1 with
ARCH=apple-silicon. I had to remove CPU pinning from the benchmark
script. However, the results were still consistent: Checking both
binaries against themselves reported a speedup of +0.0000 and +0.0005,
respectively.

```
Result of 100 runs
==================
base (...ish.037ef3e1) =    1917997  +/- 7152
test (...fish.dotprod) =    2159682  +/- 9066
diff                   =    +241684  +/- 2923

speedup        = +0.1260
P(speedup > 0) =  1.0000

CPU: 10 x arm
Hyperthreading: off
```

Fixes #4193

closes https://github.com/official-stockfish/Stockfish/pull/4400

No functional change
2023-02-23 13:22:03 +01:00
Dubslow 037ef3e18d Remove one reduction call
even though bench is unchanged to depth 28,
due to adjusting depth in singular extensions this might be functional.

STC: https://tests.stockfishchess.org/tests/view/63ec21affe833123fef34153
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 195712 W: 51625 L: 51581 D: 92506
Ptnml(0-2): 504, 20527, 55779, 20513, 533

LTC: https://tests.stockfishchess.org/tests/view/63ed3487fe833123fef375ed
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 32176 W: 8631 L: 8442 D: 15103
Ptnml(0-2): 5, 2794, 10309, 2967, 13

closes https://github.com/official-stockfish/Stockfish/pull/4395

Bench 4283297
2023-02-18 14:01:08 +01:00
Dubslow 085cace457 Simplify late countermove bonus condition
STC: https://tests.stockfishchess.org/tests/view/63d53ac6a67dd929a555e1e2
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 216096 W: 56862 L: 56839 D: 102395
Ptnml(0-2): 648, 24033, 58650, 24082, 635

LTC: https://tests.stockfishchess.org/tests/view/63d7f9a6a67dd929a5565991
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 808512 W: 214060 L: 214610 D: 379842
Ptnml(0-2): 301, 79448, 245293, 78928, 286

closes https://github.com/official-stockfish/Stockfish/pull/4392

Bench: 4283297
2023-02-18 13:34:40 +01:00
mstembera 29c1e072b6 Simplify nnueComplexity calculation.
further simplification after https://github.com/official-stockfish/Stockfish/pull/4377

STC https://tests.stockfishchess.org/tests/view/63e02a3773223e7f52ad8190
LLR: 2.97 (-2.94,2.94) <-1.75,0.25>
Total: 359072 W: 94605 L: 94733 D: 169734
Ptnml(0-2): 994, 39874, 97958, 39686, 1024

LTC https://tests.stockfishchess.org/tests/view/63e3fd12b5f425d71f77002a
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 248424 W: 66020 L: 66030 D: 116374
Ptnml(0-2): 113, 24653, 74689, 24645, 112

closes https://github.com/official-stockfish/Stockfish/pull/4390

bench: 4098325
2023-02-18 13:30:48 +01:00
MinetaS 2c36d1e7e7 Fix overflow in add_dpbusd_epi32x2
This patch fixes 16bit overflow in *_add_dpbusd_epi32x2 functions,
that can be triggered in rare cases depending on the NNUE weights.

While the code leads to some slowdown on affected architectures
(most notably avx2), the fix is simpler than some of the other
options discussed in
https://github.com/official-stockfish/Stockfish/pull/4394

Code suggested by Sopel97.

Result of "bench 4096 1 30 default depth nnue":

| Architecture        | master    | patch (gcc) | patch (clang) |
|---------------------|-----------|-------------|---------------|
| x86-64-vnni512      | 762122798 | 762122798   | 762122798     |
| x86-64-avx512       | 769723503 | 762122798   | 762122798     |
| x86-64-bmi2         | 769723503 | 762122798   | 762122798     |
| x86-64-ssse3        | 769723503 | 762122798   | 762122798     |
| x86-64              | 762122798 | 762122798   | 762122798     |

Following architectures will experience ~4% slowdown due to an
additional instruction in the middle of hot path:

* x86-64-avx512
* x86-64-bmi2
* x86-64-avx2
* x86-64-sse41-popcnt (x86-64-modern)
* x86-64-ssse3
* x86-32-sse41-popcnt

This patch clearly loses Elo against master with both STC and LTC.

Failed non-regression STC (256bit fix only):
LLR: -2.95 (-2.94,2.94) <-1.75,0.25>
Total: 33528 W: 8769 L: 9049 D: 15710
Ptnml(0-2): 96, 3616, 9600, 3376, 76
https://tests.stockfishchess.org/tests/view/63e6a5b44299542b1e26a485

60+0.6 @ 30000 games:
Elo: -1.67 +-1.7 (95%) LOS: 2.8%
Total: 30000 W: 7848 L: 7992 D: 14160
Ptnml(0-2): 12, 2847, 9436, 2683, 22
nElo: -3.84 +-3.9 (95%) PairsRatio: 0.95
https://tests.stockfishchess.org/tests/view/63e7ac716d0e1db55f35a660

However, a test against nn-a3dc078bafc7.nnue, which is the latest "safe"
network not causing the bug, passed with regular bounds.

Passed STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 160456 W: 42658 L: 42175 D: 75623
Ptnml(0-2): 487, 17638, 43469, 18173, 461
https://tests.stockfishchess.org/tests/view/63e89836d62a5d02b0fa82c8

closes https://github.com/official-stockfish/Stockfish/pull/4391
closes https://github.com/official-stockfish/Stockfish/pull/4394

No functional change
2023-02-18 13:23:18 +01:00
disservin 852330ee50 update cuckoo link
use webarchive to link to the cycle detection paper by Kervinck.

closes https://github.com/official-stockfish/Stockfish/pull/4389

No functional change
2023-02-18 13:14:24 +01:00
borg323 e5f6d71b96 Fix build on arm windows
avoids the use of _mm_malloc on arm windows.

fixes #4379
closes https://github.com/official-stockfish/Stockfish/pull/4388

No functional change
2023-02-18 13:14:05 +01:00
Linmiao Xu 05dea2ca46 Update default net to nn-1337b1adec5b.nnue
Created by retraining the master net on a dataset composed of:

* Most of the previous best dataset filtered to remove positions likely having only one good move
* Adding training data from Leela T77 dec2021 rescored with 16tb of 7-piece tablebases

Trained with end lambda 0.7 and max epoch 900. Positions with ply <= 28 were removed from most of the previous best dataset before training began. A new nnue-pytorch trainer param for skipping early plies was used to skip plies <= 24 in the unfiltered and additional Leela T77 parts of the dataset.

```
python easy_train.py \
  --experiment-name leela96-dfrc99-T80octnovT79aprmayT60novdec-eval-filt-v2-T78augsep-12tb-T77dec-16tb-lambda7-sk24 \
  --training-dataset /data/leela96-dfrc99-T80octnovT79aprmayT60novdec-eval-filt-v2-T78augsep-12tb-T77dec-16tb.binpack \
  --nnue-pytorch-branch linrock/nnue-pytorch/easy-train-early-fen-skipping \
  --early-fen-skipping 24 \
  --gpus "0," \
  --start-from-engine-test-net True \
  --start-lambda 1.0 \
  --end-lambda 0.7 \
  --gamma 0.995 \
  --lr 4.375e-4 \
  --tui False \
  --seed $RANDOM \
  --max_epoch 900
```

The depth6 multipv2 search filtering method is the same as the one used for filtering recent best datasets, with a lower eval difference threshold to remove slightly more positions than before. These parts of the dataset were filtered:

* 96% of T60T70wIsRightFarseerT60T74T75T76.binpack
* 99% of dfrc_n5000.binpack
* T80 oct + nov 2022 data, no positions with castling flags, rescored with ~600gb 7p tablebases
* T79 apr + may 2022 data, rescored with 12tb 7p tablebases
* T60 nov + dec 2021 data, rescored with 12tb 7p tablebases

These parts of the dataset were not filtered. Positions with ply <= 24 were skipped during training:

* T78 aug + sep 2022 data, rescored with 12tb 7p tablebases
* 84% of T77 dec 2021 data, rescored with 16tb 7p tablebases

The code and exact evaluation thresholds used for data filtering can be found at:
https://github.com/linrock/Stockfish/tree/tools-filter-multipv2-eval-diff-t2/src/filter

The exact training data used can be found at:
https://robotmoon.com/nnue-training-data/

Local elo at 25k nodes per move:
nn-epoch859.nnue : 3.5 +/ 1.2

Passed STC:
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
https://tests.stockfishchess.org/tests/view/63dfeefc73223e7f52ad769f
Total: 219744 W: 58572 L: 58002 D: 103170
Ptnml(0-2): 609, 24446, 59284, 24832, 701

Passed LTC:
https://tests.stockfishchess.org/tests/view/63e268fc73223e7f52ade7b6
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 91256 W: 24528 L: 24121 D: 42607
Ptnml(0-2): 48, 8863, 27390, 9288, 39

closes https://github.com/official-stockfish/Stockfish/pull/4387

bench 3841998
2023-02-09 07:50:27 +01:00
Dubslow e25bcaed3c Update complexityAverage in all branches of static eval
STC: https://tests.stockfishchess.org/tests/view/63dda49573223e7f52ad0f8c
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 117416 W: 31173 L: 31049 D: 55194
Ptnml(0-2): 290, 12246, 33533, 12328, 311

LTC: https://tests.stockfishchess.org/tests/view/63dfa90873223e7f52ad69b8
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 44416 W: 11924 L: 11744 D: 20748
Ptnml(0-2): 5, 4036, 13968, 4172, 27

closes https://github.com/official-stockfish/Stockfish/pull/4385

bench 4758694
2023-02-09 07:46:41 +01:00
Michael Chaly 8f843633db Cleanup and reorder in qsearch
This patch is a simplification / code normalisation in qsearch.

Adds steps in comments the same way we have in search;

Makes a separate "pruning" stage instead of heuristics randomly being spread over qsearch code;
Reorders pruning heuristics from least taxing ones to more taxing ones;
Removes repeated check for best value not being mated, instead uses 1 check - thus removes some lines of code.
Moves prefetch and move setup after pruning - makes no sense to do them if move will actually get pruned.

Passed non-regression test:
https://tests.stockfishchess.org/tests/view/63dd2c5ff9a50a69252c1413
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 113504 W: 29898 L: 29770 D: 53836
Ptnml(0-2): 287, 11861, 32327, 11991, 286

https://github.com/official-stockfish/Stockfish/pull/4382

Non-functional change.
2023-02-09 07:45:05 +01:00
Disservin d5817a5896 remove unnecessary variable
pinned already has to be true for the bitwise &

closes https://github.com/official-stockfish/Stockfish/pull/4381

No functional change
2023-02-09 07:42:52 +01:00
pb00067 8d3457a996 Improve excluded move logic
PR consists of 2 improvements on nodes with excludeMove:

1. Remove xoring the posKey with make_key(excludedMove)

   Since we never call tte->save anymore with excludedMove,
   the unique left purpose of the xoring was to avoid a TT hit.
   Nevertheless on a normal bench run this produced ~25 false positives
   (key collisions)
   To avoid that we now forbid early TT cutoff's with excludeMove
   Maybe these accesses to TT with xored key caused useless misses
   in the CPU caches (L1, L2 ...)
   Now doing the probe with the same key as the enclosing search does,
   should hit the CPU cache.

2. Don't probe Tablebases with excludedMove.

   This can't be tested on fishtest, but it's obvious that
   tablebases don't deliver any information about suboptimal moves.

Side note:
   Very surprisingly it looks like we cannot use static eval's from
   TT since they slightly differ over time due to changing optimism.
   Attempts to use static eval's from TT did loose about 13 ELO.
   This is something about to investigate.

LTC: https://tests.stockfishchess.org/tests/view/63dc0f8de9d4cdfbe672d0c6
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 44736 W: 12046 L: 11733 D: 20957
Ptnml(0-2): 12, 4212, 13617, 4505, 22

An analogue of this passed STC & LTC
see PR #4374 (thanks Dubslow for reviewing!)

closes https://github.com/official-stockfish/Stockfish/pull/4380

Bench: 4758694
2023-02-03 20:18:50 +01:00
Muzhen Gaming d2f79ff0e0 Remove reduced LMR capture bonus
In LMR, simplify away the reduced capture bonus (i.e. if (capture) bonus /= 6).

Non-regression STC: https://tests.stockfishchess.org/tests/view/63da1da9bbadd17b3787dced
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 28152 W: 7521 L: 7296 D: 13335
Ptnml(0-2): 76, 3069, 7568, 3280, 83

Non-regression LTC: https://tests.stockfishchess.org/tests/view/63da6ad4bbadd17b3787e98c
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 52472 W: 14120 L: 13941 D: 24411
Ptnml(0-2): 16, 5071, 15887, 5242, 20

closes https://github.com/official-stockfish/Stockfish/pull/4378

Bench: 4034016
2023-02-03 20:15:09 +01:00
Michael Chaly 1cdc0f78bd Simplify usage of optimism in complexity
This patch removes one condition in optimism usage in complexity, now negative optimism also impacts it.

Passed STC:
https://tests.stockfishchess.org/tests/view/63d34f43721fe2bff692fb12
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 204920 W: 54343 L: 54309 D: 96268
Ptnml(0-2): 598, 22648, 55897, 22756, 561

Passed LTC:
https://tests.stockfishchess.org/tests/view/63d612a2a67dd929a556075c
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 200712 W: 53207 L: 53172 D: 94333
Ptnml(0-2): 58, 19664, 60901, 19651, 82

closes https://github.com/official-stockfish/Stockfish/pull/4377

bench 4204964
2023-02-03 20:10:08 +01:00
MinetaS 5a30b087c3 Expand statistics tools for engine development
This patch adds more debugging slots up to 32 per type and provide tools
to calculate standard deviation and Pearson's correlation coefficient.

However, due to slot being 0 at default, dbg_hit_on(c, b) has to be removed.

Initial idea from snicolet/Stockfish@d8ab604

closes https://github.com/official-stockfish/Stockfish/pull/4354

No functional change
2023-02-03 20:07:56 +01:00
Michael Chaly da8513f0ea Do less SEE pruning in qsearch
Current master prunes all moves with negative SEE values in qsearch.
This patch sets constant negative threshold thus allowing some moves with negative SEE values to be searched.
Value of threshold is completely arbitrary and can be tweaked - also it as function of depth can be tried.
Original idea by author of Alexandria engine.

Passed STC
https://tests.stockfishchess.org/tests/view/63d79a59a67dd929a5564976
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 34864 W: 9392 L: 9086 D: 16386
Ptnml(0-2): 113, 3742, 9429, 4022, 126

Passed LTC
https://tests.stockfishchess.org/tests/view/63d8074aa67dd929a5565bc2
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 91616 W: 24532 L: 24126 D: 42958
Ptnml(0-2): 32, 8840, 27662, 9238, 36

closes https://github.com/official-stockfish/Stockfish/pull/4376

Bench: 4010877
2023-02-02 18:00:14 +01:00
Joost VandeVondele 3589bd008a Update WLD model
update the WLD model with about 400M positions extracted from recent LTC games after the net updates.
This ensures that the 50% win rate is again at 1.0 eval.

closes https://github.com/official-stockfish/Stockfish/pull/4373

No functional change.
2023-02-02 17:58:05 +01:00
MinetaS 7fc0f589d6 Add -Wconditional-uninitialized when using Clang
Add -Wconditional-uninitialized as it is not controlled by -Wall.

closes https://github.com/official-stockfish/Stockfish/pull/4371

No functional change
2023-02-02 17:49:23 +01:00
Muzhen Gaming 0827e00f10 Decrease reduction for killer moves with good history
If move is a main killer and we have a good history, decrease reduction.

STC: https://tests.stockfishchess.org/tests/view/63d38b37721fe2bff693069a
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 46688 W: 12542 L: 12222 D: 21924
Ptnml(0-2): 126, 5013, 12769, 5287, 149

LTC: https://tests.stockfishchess.org/tests/view/63d471e2bde6e5f3cb4be5d3
LLR: 2.93 (-2.94,2.94) <0.50,2.50>
Total: 130976 W: 35033 L: 34555 D: 61388
Ptnml(0-2): 38, 12551, 39833, 13027, 39

closes https://github.com/official-stockfish/Stockfish/pull/4369

Bench: 4069938
2023-02-02 17:45:57 +01:00
MinetaS e4e61cd9cc Remove maxNextDepth
This patch allows full PV search to have double extensions as well when
extension == 1 && doDeeperSearch && doEvenDeeperSearch && !doShallowerSearch
is true, which is extremely rare to occur.

Passed non-regression STC (master 3d2381d):
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 370824 W: 97835 L: 97974 D: 175015
Ptnml(0-2): 1073, 38814, 105731, 38767, 1027
https://tests.stockfishchess.org/tests/view/63c89416a83c702aac08314c

Passed non-regression LTC (master 3d2381d):
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 306048 W: 81173 L: 81237 D: 143638
Ptnml(0-2): 117, 27977, 96901, 27911, 118
https://tests.stockfishchess.org/tests/view/63cc4e84344bb01c191b2658

Bench: 4208265
2023-01-28 16:54:30 +01:00
Dubslow d4d1cec296 Remove previousDepth in favor of completedDepth + 2
Beyond the simplification, this could be considered a bugfix from a certain point of view.
However, the effect is very subtle and essentially impossible for users to notice.
5372f81cc8 added about 2 Elo at LTC, but only for second and later `go` commands; now, with
this patch, the first `go` command will also benefit from that gain. Games under time
controls are unaffected (as per the tests).

STC: https://tests.stockfishchess.org/tests/view/63c3d291330c0d3d051d48a8
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 473792 W: 124858 L: 125104 D: 223830
Ptnml(0-2): 1338, 49653, 135063, 49601, 1241

LTC: https://tests.stockfishchess.org/tests/view/63c8cd56a83c702aac083bc9
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 290728 W: 76926 L: 76978 D: 136824
Ptnml(0-2): 106, 27987, 89221, 27953, 97

closes https://github.com/official-stockfish/Stockfish/pull/4361

bench 4208265
2023-01-28 16:50:46 +01:00
Sebastian Buchwald 2f67409506 Remove redundant const qualifiers
The const qualifiers are already implied by the constexpr qualifiers.

closes https://github.com/official-stockfish/Stockfish/pull/4359

No functional change
2023-01-28 16:49:27 +01:00
Sebastian Buchwald 2167942b6e Simplify functions to read/write network parameters
closes https://github.com/official-stockfish/Stockfish/pull/4358

No functional change
2023-01-28 16:47:52 +01:00
disservin def296670d Fixed UCI TB win values
This patch results in search values for a TB win/loss to be reported in a way that does not change with normalization, i.e. will be consistent over time.

A value of 200.00 pawns is now reported upon entering a TB won position. Values smaller than 200.00 relate to the distance in plies from the root to the probed position position,
with 1 cp being 1 ply distance.

closes https://github.com/official-stockfish/Stockfish/pull/4353

No functional change
2023-01-28 16:37:29 +01:00
Michael Chaly d3860f8d5e Rebalance usage of history heuristics in pruning
This patch has multiple effects:

* history heuristics sum in futility pruning now can't exceed some negative value so futility pruning for moves with negative histories should become slightly less aggressive;

* history heuristics are now used in SEE pruning for quiet moves;

Passed STC:
https://tests.stockfishchess.org/tests/view/63cde339c93e8828d0f02e3a
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 88424 W: 23681 L: 23303 D: 41440
Ptnml(0-2): 258, 9559, 24219, 9899, 277

Passed LTC:
https://tests.stockfishchess.org/tests/view/63ce9009c93e8828d0f04e4f
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 79536 W: 21223 L: 20843 D: 37470
Ptnml(0-2): 22, 7599, 24146, 7979, 22

closes https://github.com/official-stockfish/Stockfish/pull/4355

Bench: 4208265
2023-01-25 07:51:19 +01:00
Dubslow 3dd0a7a7cd stat_bonus: replace quadratic with nearly identical line
passed stc: https://tests.stockfishchess.org/tests/view/63ca58c90eefe8694a0c4eac
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 287960 W: 76146 L: 76201 D: 135613
Ptnml(0-2): 947, 31890, 78307, 31943, 893

passed ltc: https://tests.stockfishchess.org/tests/view/63cc8a51344bb01c191b30f0
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 73784 W: 19559 L: 19402 D: 34823
Ptnml(0-2): 33, 7171, 22327, 7328, 33

closes https://github.com/official-stockfish/Stockfish/pull/4352

bench 3990490
2023-01-25 07:48:39 +01:00
Linmiao Xu 596a528c6a Update default net to nn-bc24c101ada0.nnue
Created by retraining the master net with Leela T78 data from Aug+Sep 2022 added to the previous best dataset. Trained with end lambda 0.7 and started with max epoch 800. All positions with ply <= 28 were skipped:

```
python easy_train.py \
  --experiment-name leela95-dfrc96-filt-only-T80octnov-T60novdecT78augsepT79aprmay-12tb7p-sk28-lambda7 \
  --training-dataset /data/leela95-dfrc96-filt-only-T80octnov-T60novdecT78augsepT79aprmay-12tb7p.binpack \
  --nnue-pytorch-branch linrock/nnue-pytorch/misc-fixes-skip-ply-lteq-28 \
  --start-from-engine-test-net True \
  --gpus "0," \
  --start-lambda 1.0 \
  --end-lambda 0.7 \
  --gamma 0.995 \
  --lr 4.375e-4 \
  --tui False \
  --seed $RANDOM \
  --max_epoch 800
```

Around epoch 750, training was manually paused and max epoch increased to 950 before resuming. The additional Leela training data from T78 was prepared in the same way as the previous best dataset.

The exact training data used can be found at:
https://robotmoon.com/nnue-training-data/

While the local elo ratings during this experiment were much lower than in recent master nets, several later epochs had a consistent elo above zero, and this was hypothesized to represent potential strength at slower time controls.

Local elo at 25k nodes per move
leela95-dfrc96-filt-only-T80octnov-T60novdecT78augsepT79aprmay-12tb7p-sk28-lambda7
nn-epoch819.nnue : 0.4 +/- 1.1 (nn-bc24c101ada0.nnue)
nn-epoch799.nnue : 0.3 +/- 1.2
nn-epoch759.nnue : 0.3 +/- 1.1
nn-epoch839.nnue : 0.2 +/- 1.4

Passed STC
https://tests.stockfishchess.org/tests/view/63cabf6f0eefe8694a0c6013
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 41608 W: 11161 L: 10848 D: 19599
Ptnml(0-2): 116, 4496, 11281, 4781, 130

Passed LTC
https://tests.stockfishchess.org/tests/view/63cb1856344bb01c191af263
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 76760 W: 20517 L: 20137 D: 36106
Ptnml(0-2): 34, 7435, 23070, 7799, 42

closes https://github.com/official-stockfish/Stockfish/pull/4351

bench 3941848
2023-01-23 07:01:32 +01:00
Jonathan a2038c1a01 apply if constexpr to additional instances
as a form of documentation, and a hint to the compiler.

closes https://github.com/official-stockfish/Stockfish/pull/4345

No functional change
2023-01-22 13:15:46 +01:00
Stephen Touset 734315ff30 Remove precomputed SquareBB
Bit-shifting is a single instruction, and should be faster than an array lookup
on supported architectures. Besides (ever so slightly) speeding up the
conversion of a square into a bitboard, we may see minor general performance
improvements due to preserving more of the CPU's existing cache.

passed STC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 47280 W: 12469 L: 12271 D: 22540
Ptnml(0-2): 128, 4893, 13402, 5087, 130
https://tests.stockfishchess.org/tests/view/63c5cfe618c20f4929c5fe46

Small speedup locally:

```
Result of  20 runs
==================
base (./stockfish.master       ) =    1752135  +/- 10943
test (./stockfish.patch        ) =    1763939  +/- 10818
diff                             =     +11804  +/- 4731

speedup        = +0.0067
P(speedup > 0) =  1.0000

CPU: 16 x AMD Ryzen 9 3950X 16-Core Processor
```

Closes https://github.com/official-stockfish/Stockfish/pull/4343

Bench: 4106793
2023-01-22 10:55:32 +01:00
Joost VandeVondele a08b8d4e97 Update UCI_Elo parameterization
The old parameterization (https://github.com/official-stockfish/Stockfish/pull/2225/files) has now become quite inaccurate.
This updates the formula based on updated results with master. The formula is based on a fit of the Elo results for games
played between master at various skill levels, and various versions of the Stash engine, which have been ranked at CCRL.

```
   # PLAYER             :  RATING  ERROR  POINTS  PLAYED   (%)
   1 master-skill-19    :  3191.1   40.4   940.0    1707    55
   2 master-skill-18    :  3170.3   39.3  1343.0    2519    53
   3 master-skill-17    :  3141.3   37.8  2282.0    4422    52
   4 master-skill-16    :  3111.2   37.1  2773.0    5423    51
   5 master-skill-15    :  3069.5   37.2  2728.5    5386    51
   6 master-skill-14    :  3024.8   36.1  2702.0    5339    51
   7 master-skill-13    :  2972.9   35.4  2645.5    5263    50
   8 master-skill-12    :  2923.1   35.0  2653.5    5165    51
   9 master-skill-11    :  2855.5   33.6  2524.0    5081    50
  10 master-skill-10    :  2788.3   32.0  2724.5    5511    49
  11 stash-bot-v25.0    :  2744.0   31.5  1952.5    3840    51
  12 master-skill-9     :  2702.8   30.5  2670.0    5018    53
  13 master-skill-8     :  2596.2   28.5  2669.5    4975    54
  14 stash-bot-v21.0    :  2561.2   30.0  1338.0    3366    40
  15 master-skill-7     :  2499.5   28.5  1934.0    4178    46
  16 stash-bot-v20.0    :  2452.6   27.7  1606.5    3378    48
  17 stash-bot-v19.0    :  2425.3   26.7  1787.0    3365    53
  18 master-skill-6     :  2363.2   26.4  2510.5    4379    57
  19 stash-bot-v17.0    :  2280.7   25.4  2209.0    4378    50
  20 master-skill-5     :  2203.7   25.3  2859.5    5422    53
  21 stash-bot-v15.3    :  2200.0   25.4  1757.0    4383    40
  22 stash-bot-v14      :  2145.9   25.5  2890.0    5167    56
  23 stash-bot-v13      :  2042.7   25.8  2263.5    4363    52
  24 stash-bot-v12      :  1963.4   25.8  1769.5    4210    42
  25 master-skill-4     :  1922.9   25.9  2690.0    5399    50
  26 stash-bot-v11      :  1873.0   26.3  2203.5    4335    51
  27 stash-bot-v10      :  1783.8   27.8  2568.5    4301    60
  28 master-skill-3     :  1742.3   27.8  1909.5    4439    43
  29 master-skill-2     :  1608.4   29.4  2064.5    4389    47
  30 stash-bot-v9       :  1582.6   30.2  2130.0    4230    50
  31 master-skill-1     :  1467.6   31.3  2015.5    4244    47
  32 stash-bot-v8       :  1452.8   31.5  1953.5    3780    52
  33 master-skill-0     :  1320.1   32.9   651.5    2083    31
```

Skill 0 .. 19, now covers CCRL Blitz Elo from 1320 to 3190, approximately.
Indeed, the Elo of stash in this analysis is only to within +- 100 Elo of CCRL,
probably because it depends quite a bit on the opponent pool.

To obtain a skill level for a given Elo number, the above data is fit as a 3rd
degree polynomial Skill(Elo). A quick test confirms the correspondence to the above table:

```
Score of master-elo-2721 vs stash-bot-v21.0: 51 - 16 - 19  [0.703] 86
Elo difference: 150.1 +/- 70.2, LOS: 100.0 %, DrawRatio: 22.1 %
```

closes https://github.com/official-stockfish/Stockfish/pull/4341

No functional change.
2023-01-22 10:54:15 +01:00
Sebastian Buchwald da5bcec481 Fix asm modifiers in add_dpbusd_epi32x2 implementations
The accumulator should be an earlyclobber because it is written before
all input operands are read. Otherwise, the asm code computes a wrong
result if the accumulator shares a register with one of the other input
operands (which happens if we pass in the same expression for the
accumulator and the operand).

Closes https://github.com/official-stockfish/Stockfish/pull/4339

No functional change
2023-01-22 10:51:02 +01:00
Linmiao Xu 3d2381d76d Update default net to nn-1e7ca356472e.nnue
Created by retraining the master net on a dataset composed of:

* The Leela-dfrc_n5000.binpack dataset filtered with depth6 multipv2 search to remove positions with only one good move, in addition to removing positions where either of the two best moves are captures
* The same Leela T80 oct+nov 2022 training data used in recent best datasets
* Additional Leela training data from T60 nov+dec 2021 and T79 apr+may 2022

Trained with end lambda 0.7 and started with max epoch 800. All positions with ply <= 28 were skipped:

```
python easy_train.py \
  --experiment-name leela95-dfrc96-mpv-eval-fonly-T80octnov-T79aprmayT60novdec-12tb7p-sk28-lambda7 \
  --training-dataset /data/leela95-dfrc96-mpv-eval-fonly-T80octnov-T79aprmayT60novdec-12tb7p.binpack \
  --nnue-pytorch-branch linrock/nnue-pytorch/misc-fixes-skip-ply-lteq-28 \
  --start-from-engine-test-net True \
  --gpus "0," \
  --start-lambda 1.0 \
  --end-lambda 0.7 \
  --gamma 0.995 \
  --lr 4.375e-4 \
  --tui False \
  --seed $RANDOM \
  --max_epoch 800
```

Around epoch 780, training was manually paused and max epoch increased to 920 before resuming.

During depth6 multipv2 data filtering, positions were considered to have only one good move if the score of the best move was significantly better than the 2nd best move in a way that changes the outcome of the game:

* the best move leads to a significant advantage while the 2nd best move equalizes or loses
* the best move is about equal while the 2nd best move loses

The modified stockfish branch and exact score thresholds used for filtering are at:
https://github.com/linrock/Stockfish/tree/tools-filter-multipv2-eval-diff/src/filter

About 95% of the Leela portion and 96% of the DFRC portion of the Leela-dfrc_n5000.binpack dataset was filtered. Unfiltered parts of the dataset were left out.

The additional Leela training data from T60 nov+dec 2021 and T79 apr+may 2022 was WDL-rescored with about 12TB of syzygy 7-piece tablebases where the material difference is less than around 6 pawns. Best moves were exported to .plain data files during data conversion with the lc0 rescorer.

The exact training data can be found at:
https://robotmoon.com/nnue-training-data/

Local elo at 25k nodes per move
experiment_leela95-dfrc96-mpv-eval-fonly-T80octnov-T79aprmayT60novdec-12tb7p-sk28-lambda7
run_0/nn-epoch899.nnue : 3.8 +/- 1.6

Passed STC
https://tests.stockfishchess.org/tests/view/63bed1f540aa064159b9c89b
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 103344 W: 27392 L: 26991 D: 48961
Ptnml(0-2): 333, 11223, 28099, 11744, 273

Passed LTC
https://tests.stockfishchess.org/tests/view/63c010415705810de2deb3ec
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 21712 W: 5891 L: 5619 D: 10202
Ptnml(0-2): 12, 2022, 6511, 2304, 7

closes https://github.com/official-stockfish/Stockfish/pull/4338

bench 4106793
2023-01-14 08:12:11 +01:00
Sebastian Buchwald 4f4e652eca Avoid unnecessary string copies
closes https://github.com/official-stockfish/Stockfish/pull/4326

also fixes typo, closes https://github.com/official-stockfish/Stockfish/pull/4332

No functional change
2023-01-09 20:32:58 +01:00
Sebastian Buchwald e9e7a7b83f Replace some std::string occurrences with std::string_view
std::string_view is more lightweight than std::string. Furthermore,
std::string_view variables can be declared constexpr.

closes https://github.com/official-stockfish/Stockfish/pull/4328

No functional change
2023-01-09 20:28:24 +01:00
Stefano Di Martino 5a88c5bb9b Modernize code base a little bit
Removed sprintf() which generated a warning, because of security reasons.
Replace NULL with nullptr
Replace typedef with using
Do not inherit from std::vector. Use composition instead.
optimize mutex-unlocking

closes https://github.com/official-stockfish/Stockfish/pull/4327

No functional change
2023-01-09 20:25:13 +01:00
Sebastian Buchwald 31acd6bab7 Warn if a global function has no previous declaration
If a global function has no previous declaration, either the declaration
is missing in the corresponding header file or the function should be
declared static. Static functions are local to the translation unit,
which allows the compiler to apply some optimizations earlier (when
compiling the translation unit rather than during link-time
optimization).

The commit enables the warning for gcc, clang, and mingw. It also fixes
the reported warnings by declaring the functions static or by adding a
header file (benchmark.h).

closes https://github.com/official-stockfish/Stockfish/pull/4325

No functional change
2023-01-09 20:18:39 +01:00
Jake Senne fcee83810a Only close file if already open
Ensures that the tablebase file is only closed if already open.

Fixes #4268
Closes https://github.com/official-stockfish/Stockfish/pull/4321

No functional change
2023-01-09 20:16:17 +01:00
candirufish 4101893a28 On step 18 increase reduction by 2 if not ttmove and cutnode
stc: https://tests.stockfishchess.org/tests/view/63babc9fcd3db0c8d399f723
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 43104 W: 11711 L: 11389 D: 20004
Ptnml(0-2): 211, 4518, 11793, 4798, 232

ltc: https://tests.stockfishchess.org/tests/view/63bb1857cd3db0c8d39a0661
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 127104 W: 33810 L: 33339 D: 59955
Ptnml(0-2): 39, 12155, 38702, 12608, 48

closes https://github.com/official-stockfish/Stockfish/pull/4334

Bench: 4035725
2023-01-09 20:15:08 +01:00
Dubslow ea0f34120f Late countermove bonus: remove "extraBonus &&"
passed stc: https://tests.stockfishchess.org/tests/view/63a71e409c0589b83751dc25
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 432480 W: 113846 L: 114055 D: 204579
Ptnml(0-2): 1164, 48205, 117701, 48016, 1154

passed ltc: https://tests.stockfishchess.org/tests/view/63aba66639af998100ce1aa9
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 245344 W: 65309 L: 65317 D: 114718
Ptnml(0-2): 117, 24257, 73903, 24307, 88

closes https://github.com/official-stockfish/Stockfish/pull/4322

bench 4379218
2023-01-09 20:12:01 +01:00
mstembera 9fe9ff0082 Fix stack initialization
This fixes a bug where on line 278 the Stack::staticEvals are
initialized to 0. However VALUE_NONE is defined to be 32002 so
this is a bug in master. It is probably due to the calculation
of improvement, where staticEval prior to rootPos can be accessed.

https://tests.stockfishchess.org/tests/view/63ab91cf39af998100ce1666
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 53736 W: 14285 L: 13955 D: 25496
Ptnml(0-2): 121, 5921, 14500, 6159, 167

https://tests.stockfishchess.org/tests/view/63b2af5ee28ed36c814bed52
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 33776 W: 9130 L: 8934 D: 15712
Ptnml(0-2): 14, 3240, 10185, 3434, 15

closes https://github.com/official-stockfish/Stockfish/pull/4320

Bench: 4068510
2023-01-04 09:37:02 +01:00
FauziAkram fc5b59b88b Parameter Tweaks
This patch is a parameter tweak that passed both STC and LTC tests.

STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 80944 W: 21557 L: 21189 D: 38198
Ptnml(0-2): 192, 8883, 22028, 9103, 266
https://tests.stockfishchess.org/tests/view/63b07fe2d421d8f75795a03b

LTC:
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 30440 W: 8296 L: 8007 D: 14137
Ptnml(0-2): 6, 2893, 9143, 3162, 16
https://tests.stockfishchess.org/tests/view/63b167d02ab1290f961644db

closes https://github.com/official-stockfish/Stockfish/pull/4318

Bench: 4182223
2023-01-02 19:14:05 +01:00
Linmiao Xu a6fa683418 Update default net to nn-a3dc078bafc7.nnue
This is a later epoch (epoch 859) from the same experiment run that trained yesterday's master net nn-60fa44e376d9.nnue (epoch 779). The experiment was manually paused around epoch 790 and unpaused with max epoch increased to 900 mainly to get more local elo data without letting the GPU idle.

nn-60fa44e376d9.nnue is from #4314
nn-335a9b2d8a80.nnue is from #4295

Local elo vs. nn-335a9b2d8a80.nnue at 25k nodes per move:
experiment_leela93-dfrc99-filt-only-T80-oct-nov-skip28
run_0/nn-epoch779.nnue (nn-60fa44e376d9.nnue) : 5.0 +/- 1.2
run_0/nn-epoch859.nnue (nn-a3dc078bafc7.nnue) : 5.6 +/- 1.6

Passed STC vs. nn-335a9b2d8a80.nnue
https://tests.stockfishchess.org/tests/view/63ae10495bd1e5f27f13d94f
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 37536 W: 10088 L: 9781 D: 17667
Ptnml(0-2): 110, 4006, 10223, 4325, 104

An LTC test vs. nn-335a9b2d8a80.nnue was paused due to nn-60fa44e376d9.nnue passing LTC first:
https://tests.stockfishchess.org/tests/view/63ae5d34331d5fca5113703b

Passed LTC vs. nn-60fa44e376d9.nnue
https://tests.stockfishchess.org/tests/view/63af1e41465d2b022dbce4e7
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 148704 W: 39672 L: 39155 D: 69877
Ptnml(0-2): 59, 14443, 44843, 14936, 71

closes https://github.com/official-stockfish/Stockfish/pull/4319

bench 3984365
2023-01-02 19:10:14 +01:00
Sebastian Buchwald b60f9cc451 Update copyright years
Happy New Year!

closes https://github.com/official-stockfish/Stockfish/pull/4315

No functional change
2023-01-02 19:07:38 +01:00
Linmiao Xu be9bc420af Update default net to nn-60fa44e376d9.nnue
Created by retraining the master net on the previous best dataset with additional filtering. No new data was added.

More of the Leela-dfrc_n5000.binpack part of the dataset was pre-filtered with depth6 multipv2 search to remove bestmove captures. About 93% of the previous Leela/SF data and 99% of the SF dfrc data was filtered. Unfiltered parts of the dataset were left out. The new Leela T80 oct+nov data is the same as before. All early game positions with ply count <= 28 were skipped during training by modifying the training data loader in nnue-pytorch.

Trained in a similar way as recent master nets, with a different nnue-pytorch branch for early ply skipping:

python3 easy_train.py \
  --experiment-name=leela93-dfrc99-filt-only-T80-oct-nov-skip28 \
  --training-dataset=/data/leela93-dfrc99-filt-only-T80-oct-nov.binpack \
  --start-from-engine-test-net True \
  --nnue-pytorch-branch=linrock/nnue-pytorch/misc-fixes-skip-ply-lteq-28 \
  --gpus="0," \
  --start-lambda=1.0 \
  --end-lambda=0.75 \
  --gamma=0.995 \
  --lr=4.375e-4 \
  --tui=False \
  --seed=$RANDOM \
  --max_epoch=800 \
  --network-testing-threads 20 \
  --num-workers 6

For the exact training data used: https://robotmoon.com/nnue-training-data/
Details about the previous best dataset: #4295

Local testing at a fixed 25k nodes:
experiment_leela93-dfrc99-filt-only-T80-oct-nov-skip28
Local Elo: run_0/nn-epoch779.nnue : 5.1 +/- 1.5

Passed STC
https://tests.stockfishchess.org/tests/view/63adb3acae97a464904fd4e8
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 36504 W: 9847 L: 9538 D: 17119
Ptnml(0-2): 108, 3981, 9784, 4252, 127

Passed LTC
https://tests.stockfishchess.org/tests/view/63ae0ae25bd1e5f27f13d884
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 36592 W: 10017 L: 9717 D: 16858
Ptnml(0-2): 17, 3461, 11037, 3767, 14

closes https://github.com/official-stockfish/Stockfish/pull/4314

bench 4015511
2023-01-01 12:28:51 +01:00
Sebastian Buchwald 258c13ba8c Remove redundant extern modifier for function declarations
Functions have external linkage by default, so there's no need to
declare them extern.

closes https://github.com/official-stockfish/Stockfish/pull/4308

No functional change
2023-01-01 12:26:36 +01:00
Sebastian Buchwald f09b391ceb Fix comparison with uninitialized variable
In both modified methods, the variable 'result' is checked to detect
whether the probe operation failed. However, the variable is not
initialized on all paths, so the check might test an uninitialized
value.

A test position (with TB) is given by:

position fen 3K1k2/R7/8/8/8/8/8/R6Q w - - 0 1 moves a1b1 f8g8 b1a1 g8f8 a1b1 f8g8 b1a1

This is now fixed by always initializing the variable.

closes https://github.com/official-stockfish/Stockfish/pull/4309

No functional change
2023-01-01 12:24:42 +01:00
Muzhen Gaming 64656f8583 Add double bonus for prior countermove fail low
Add a double extra bonus for particularly bad fail low cases. Original idea by Yoshie2000.

STC: https://tests.stockfishchess.org/tests/view/63a2f0d86b5bf07ac7fad543
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 146488 W: 38992 L: 38532 D: 68964
Ptnml(0-2): 385, 16036, 39965, 16450, 408

LTC: https://tests.stockfishchess.org/tests/view/63a3eaeb6b5bf07ac7fafdec
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 103992 W: 27853 L: 27423 D: 48716
Ptnml(0-2): 41, 10029, 31435, 10441, 50

closes https://github.com/official-stockfish/Stockfish/pull/4302

Bench: 3801857
2022-12-24 16:01:50 +01:00
FauziAkram b2bd8699ec Update Elo estimates for terms in search
based on 25k games per term, using the UHO_XXL_+0.90_+1.19.epd book, at STC.

More detailed information in the PR.

closes https://github.com/official-stockfish/Stockfish/pull/4294

No functional change
2022-12-24 15:58:51 +01:00
Linmiao Xu c620886181 Update default net to nn-335a9b2d8a80.nnue
Created by retraining the master net with a combination of:

    the previous best dataset (Leela-dfrc_n5000.binpack), with about half the dataset filtered using depth6 multipv2 search to throw away positions where either of the 2 best moves are captures
    Leela T80 Oct and Nov training data rescored with best moves, adding ~9.5 billion positions

Trained effectively the same way as the previous master net:

python3 easy_train.py \
  --experiment-name=leela-dfrc-filtered-T80-oct-nov \
  --training-dataset=/data/leela-dfrc-filtered-T80-oct-nov.binpack \
  --start-from-engine-test-net True \
  --gpus="0," \
  --start-lambda=1.0 \
  --end-lambda=0.75 \
  --gamma=0.995 \
  --lr=4.375e-4 \
  --tui=False \
  --seed=$RANDOM \
  --max_epoch=800 \
  --auto-exit-timeout-on-training-finished=900 \
  --network-testing-threads 20 \
  --num-workers 6

Local testing at a fixed 25k nodes:
experiments/experiment_leela-dfrc-filtered-T80-oct-nov/training/run_0/nn-epoch779.nnue
localElo: run_0/nn-epoch779.nnue : 4.7 +/- 3.1

The new Leela T80 part of the dataset was prepared by downloading test80 training data from all of Oct 2022 and Nov 2022, rescoring with syzygy 6-piece tablebases and ~600 GB of 7-piece tablebases, saving best moves to exported .plain files, removing all positions with castling flags, then converting to binpacks and using interleave_binpacks.py to merge them together. Scripts used in this data conversion process are available at:
https://github.com/linrock/lc0-data-converter

Filtering binpack data using depth6 multipv2 search was done by modifying transform.cpp in the tools branch:
https://github.com/linrock/Stockfish/tree/tools-filter-multipv2-no-rescore

Links for downloading the training data (total size: 338 GB) are available at:
https://robotmoon.com/nnue-training-data/

Passed STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 30544 W: 8244 L: 7947 D: 14353
Ptnml(0-2): 93, 3243, 8302, 3542, 92
https://tests.stockfishchess.org/tests/view/63a0d377264a0cf18f86f82b

Passed LTC:
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 32464 W: 8866 L: 8573 D: 15025
Ptnml(0-2): 19, 3054, 9794, 3345, 20
https://tests.stockfishchess.org/tests/view/63a10bc9fb452d3c44b1e016

closes https://github.com/official-stockfish/Stockfish/pull/4295

Bench 3554904
2022-12-21 07:14:58 +01:00
MinetaS 20b0226462 Fix a dependency bug
Instead of allowing .depend for specific build-related targets, filter
non-build-related targets (i.e. help, clean) so that other targets can
normally execute .depend target.

closes https://github.com/official-stockfish/Stockfish/pull/4293

No functional change
2022-12-20 08:14:19 +01:00
Alfredo Menezes c2d507005c Sometimes do a reduced search if LMR is skipped
If the node doesn't go through LMR and r is too big,
reduce search depth by one ply.

STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 664888 W: 176375 L: 175169 D: 313344
Ptnml(0-2): 1965, 73754, 179851, 74858, 2016
https://tests.stockfishchess.org/tests/view/6399414c93ed41c57ede8fb8

LTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 150784 W: 40553 L: 40031 D: 70200
Ptnml(0-2): 76, 14668, 45387, 15180, 81
https://tests.stockfishchess.org/tests/view/639dee6e11c576d919dc2b38

closes https://github.com/official-stockfish/Stockfish/pull/4290

Bench: 3727508
2022-12-19 20:46:04 +01:00
Joost VandeVondele 61ea1534ff No error if net available but wget/curl missing
do not error out on missing wget/curl if these tools are not needed later on,
i.e. if the net is available already.

closes https://github.com/official-stockfish/Stockfish/pull/4291
closes https://github.com/official-stockfish/Stockfish/pull/4253

No functional change
2022-12-19 18:17:50 +01:00
mstembera 3a32d3e00c Don't reset increaseDepth back to true after it has been set to false
Resetting increaseDepth back to true each time on the very next iteration was not intended so this is a bug fix and a simplification.
See more discussion here #2482 (comment) Thanks to xoto10

STC: https://tests.stockfishchess.org/tests/view/6398c74693ed41c57ede7bfd
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 51128 W: 13543 L: 13220 D: 24365
Ptnml(0-2): 165, 5363, 14174, 5708, 154

LTC: https://tests.stockfishchess.org/tests/view/6399bcd393ed41c57edea750
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 290864 W: 77282 L: 77334 D: 136248
Ptnml(0-2): 107, 28127, 89029, 28049, 120

closes https://github.com/official-stockfish/Stockfish/pull/4288

bench: 3611278
2022-12-19 18:15:09 +01:00
Michael Chaly 39af98c807 Reintroduce doEvenDeeperSearch
This patch is basically the same as a reverted patch
but now has some guarding against search being stuck - the same
way as we do with double extensions. This should help with
search explosions - albeit slowly but they eventually should be resolved.

passed STC:
https://tests.stockfishchess.org/tests/view/639733d0b4e52c95053f3485
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 514048 W: 136423 L: 135435 D: 242190
Ptnml(0-2): 1425, 56945, 139420, 57685, 1549

passed LTC:
https://tests.stockfishchess.org/tests/view/639ab79b93ed41c57eded5c3
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 113800 W: 30642 L: 30190 D: 52968
Ptnml(0-2): 53, 11092, 34178, 11504, 73

closes https://github.com/official-stockfish/Stockfish/pull/4287

bench 3611278
2022-12-19 18:11:12 +01:00
PikaCat 726e90ccfa Badge link fix
Fix the badge link issue mentioned in https://github.com/badges/shields/issues/8671

closes https://github.com/official-stockfish/Stockfish/pull/4285

No functional change
2022-12-19 18:09:52 +01:00
NguyenPham 3659a9fda0 Fixed the help of Makefile
make profile-build more prominent, adjust comments

closes https://github.com/official-stockfish/Stockfish/pull/4284

No functional change
2022-12-19 18:08:12 +01:00
VoyagerOne 7cf93f8b71 Simplify Capture Scoring
The parameters are now in one place for easier tuning.
New formula is very similar to current.

STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 48176 W: 12819 L: 12616 D: 22741
Ptnml(0-2): 139, 5316, 13001, 5467, 165

LTC:
LLR: 2.97 (-2.94,2.94) <-1.75,0.25>
Total: 176752 W: 47364 L: 47304 D: 82084
Ptnml(0-2): 83, 17302, 53536, 17382, 73
https://tests.stockfishchess.org/tests/view/638ec7d068532fcbf79dfa15

closes https://github.com/official-stockfish/Stockfish/pull/4281

Bench: 3410998
2022-12-12 08:20:48 +01:00
ppigazzini 5fe1fa0210 GitHub Actions: install NDK once and clean up yaml
Use Ubuntu 22.04 as runner for NDK to avoid a qemu bug with `profile-build`

closes https://github.com/official-stockfish/Stockfish/pull/4280

No functional change
2022-12-12 08:17:52 +01:00
mstembera 310928e985 Avoid truncated PV in the threaded case
strongly prefer to pick as bestThread those threads with a longer PV,
among those threads that all found the same bestmove.

extended discussion in #4244
closes https://github.com/official-stockfish/Stockfish/pull/4278

No functional change
2022-12-12 08:15:19 +01:00
Joost VandeVondele 955edf1d1d Revert "doEvenDeeperSearch + tuning"
This reverts commit 98965c139d.

The increase of depth could lead to search explosions,
most visible with TB.

fixes https://github.com/official-stockfish/Stockfish/issues/4276
closes https://github.com/official-stockfish/Stockfish/pull/4256

Bench: 3872306
2022-12-12 08:14:26 +01:00
disservin 8f817ef082 Fix lower/upper bounds output
Commit cb0c7a9848 doesnt reset the lower/upper bounds back to false.

fixes #4273
closes https://github.com/official-stockfish/Stockfish/pull/4274

No functional change
2022-12-09 22:58:49 +01:00
Joost VandeVondele 3a30b478d2 CI workflows, install git on windows
ensures the SF dev version is reported correctly

closes https://github.com/official-stockfish/Stockfish/pull/4272

No functional change
2022-12-09 22:58:22 +01:00
Joost VandeVondele aedf0251e6 CI workflows, install git on windows
ensures the SF dev version is reported correctly

No functional change
2022-12-09 17:56:55 +01:00
Douglas Matos Gomes 44ecadee10 Simplify redundant condition.
closes https://github.com/official-stockfish/Stockfish/pull/4270

No functional change
2022-12-09 17:01:16 +01:00
Alfredo Menezes 9d3fd011f1 Extend all moves at low depth if ttMove is doubly extended
If ttMove is doubly extended, we allow a depth growth of the remaining moves.
The idea is to get a more realistic score comparison, because of the depth
difference. We take some care to avoid this extension for high depths,
in order to avoid the cost, since the search result is supposed
to be more accurate in this case.

This pull request includes some small cleanups.

STC:
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 60256 W: 16189 L: 15848 D: 28219
Ptnml(0-2): 182, 6546, 16330, 6889, 181
https://tests.stockfishchess.org/tests/view/639109a1792a529ae8f27777

LTC:
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 106232 W: 28487 L: 28053 D: 49692
Ptnml(0-2): 46, 10224, 32145, 10652, 49
https://tests.stockfishchess.org/tests/view/63914cba792a529ae8f282ee

closes https://github.com/official-stockfish/Stockfish/pull/4271

Bench: 3622368
2022-12-09 16:59:55 +01:00
ppigazzini aa603cfeeb GitHub Action: upload ARM artifacts
And some clean up in other files.

closes https://github.com/official-stockfish/Stockfish/pull/4269

No functional change
2022-12-09 16:54:43 +01:00
MinetaS 74fb936dbd Invoke .depend only on build targets
Add a constraint so that the dependency build only occurs when users
actually run build tasks.

This fixes a bug on some systems where gcc/g++ is not available.

closes https://github.com/official-stockfish/Stockfish/pull/4255

No functional change
2022-12-08 20:48:20 +01:00
Guenther Demetz cb0c7a9848 Correctly output lowerbound/upperbound scores
fixes the lowerbound/upperbound output by avoiding
scores outside the alpha,beta bracket. Since SF search
uses fail-soft we can't simply take the returned value
as score.

closes https://github.com/official-stockfish/Stockfish/pull/4259

No functional change
2022-12-08 20:43:21 +01:00
FauziAkram 98965c139d doEvenDeeperSearch + tuning
Credit for the main idea of doEvenDeeperSearch goes to Vizvezdenec,
tuning by FauziAkram: Expansion of existing logic of doDeeperSearch -
if value from LMR is really really good do full depth search not
1 ply deeper but rather 2 instead.

Passed STC:
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 330048 W: 87672 L: 86942 D: 155434
Ptnml(0-2): 1012, 36739, 88912, 37229, 1132
https://tests.stockfishchess.org/tests/view/638a1cadd2b9c924c4c621d2

Passed LTC:
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 216696 W: 57891 L: 57240 D: 101565
Ptnml(0-2): 72, 21221, 65152, 21790, 113
https://tests.stockfishchess.org/tests/view/638c7d52a971f1f096c68fe2

closes https://github.com/official-stockfish/Stockfish/pull/4256

Bench: 3461830
2022-12-08 20:41:45 +01:00
ppigazzini 9fc203a3d0 Set the right PATH for ARM compiler and build tests in CI
Fix for the GitHub upgrade:
https://github.com/actions/runner-images/issues/5879
that broke our ARM workflows because it changed the value of
the ANDROID_NDK_HOME variable referenced in our PATH.

closes https://github.com/official-stockfish/Stockfish/pull/4267

No functional change
2022-12-08 20:36:52 +01:00
Joost VandeVondele e8caa6640d Restore development version
No functional change
2022-12-08 20:33:32 +01:00
Joost VandeVondele 758f9c9350 Stockfish 15.1
Official release version of Stockfish 15.1

Bench: 3467381

---

Today, we have the pleasure to announce Stockfish 15.1.

As usual, downloads will be freely available at stockfishchess.org/download

*Elo gain and competition results*

With this release, version 5 of the NNUE neural net architecture has
been introduced, and the training data has been extended to include
Fischer random chess (FRC) positions. As a result, Elo gains are largest
for FRC, reaching up to 50 Elo for doubly randomized FRC[1] (DFRC).
More importantly, also for standard chess this release progressed and
will win two times more game pairs than it loses[2] against
Stockfish 15. Stockfish continues to win in a dominating way[3] all
chess engine tournaments, including the TCEC Superfinal, Cup, FRC, DFRC,
and Swiss as well as the CCC Bullet, Blitz, and Rapid events.

*New evaluation*

This release also introduces a new convention for the evaluation that
is reported by search. An evaluation of +1 is now no longer tied to the
value of one pawn, but to the likelihood of winning the game. With
a +1 evaluation, Stockfish has now a 50% chance of winning the game
against an equally strong opponent. This convention scales down
evaluations a bit compared to Stockfish 15 and allows for consistent
evaluations in the future.

*ChessBase settlement*

In this release period, the Stockfish team has successfully enforced
its GPL license against ChessBase. This has been an intense process that
included filing a lawsuit[4], a court hearing[5], and finally
negotiating a settlement[6] that established that ChessBase infringed on
the license by not distributing the Stockfish derivatives Fat Fritz 2
and Houdini 6 as free software, and that ensures ChessBase will respect
the Free Software principles in the future. This settlement has been
covered by major chess sites (see e.g. lichess.org[7] and chess.com[8]),
and we are proud that it has been hailed as a ‘historic violation
settlement[9]’ by the Software Freedom Conservancy.

*Thank you*

The Stockfish project builds on a thriving community of enthusiasts
(thanks everybody!) that contribute their expertise, time, and resources
to build a free and open-source chess engine that is robust, widely
available, and very strong. We invite our chess fans to join the
fishtest testing framework and programmers to contribute to the
project[10].

The Stockfish team

[1] https://tests.stockfishchess.org/tests/view/638a6170d2b9c924c4c62cb4
[2] https://tests.stockfishchess.org/tests/view/638a4dd7d2b9c924c4c6297b
[3] https://en.wikipedia.org/wiki/Stockfish_(chess)#Competition_results
[4] https://stockfishchess.org/blog/2021/our-lawsuit-against-chessbase/
[5] https://stockfishchess.org/blog/2022/public-court-hearing-soon/
[6] https://stockfishchess.org/blog/2022/chessbase-stockfish-agreement/
[7] https://lichess.org/blog/Y3u1mRAAACIApBVn/settlement-reached-in-stockfish-v-chessbase
[8] https://www.chess.com/news/view/chessbase-stockfish-reach-settlement
[9] https://sfconservancy.org/news/2022/nov/28/sfc-named-trusted-party-in-gpl-case/
[10] https://stockfishchess.org/get-involved/
2022-12-04 14:17:15 +01:00
Joost VandeVondele d60f5de967 Fix bestThread selection
If multiple threads have the same best move,
pick the thread with the largest contribution to the confidence vote.
This thread will later be used to display PV, so this patch is
about user-friendliness and/or least surprises, it non-functional for playing strenght.

closes https://github.com/official-stockfish/Stockfish/pull/4246

No functional change
2022-12-02 20:06:59 +01:00
VoyagerOne c7118fb46d Simply do full sort on captures.
STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 42712 W: 11413 L: 11203 D: 20096
Ptnml(0-2): 145, 4661, 11544, 4851, 155
https://tests.stockfishchess.org/tests/view/6384df57d2b9c924c4c53900

LTC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 239072 W: 64065 L: 64067 D: 110940
Ptnml(0-2): 106, 23735, 71859, 23727, 109
https://tests.stockfishchess.org/tests/view/63851120d2b9c924c4c541ee

closes https://github.com/official-stockfish/Stockfish/pull/4249

Bench: 3467381
2022-12-02 20:05:50 +01:00
VoyagerOne 6a6faac04d Remove PvNode Parameter for cutoff LMR
STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 198520 W: 52673 L: 52632 D: 93215
Ptnml(0-2): 645, 22241, 53499, 22178, 697
https://tests.stockfishchess.org/tests/view/63746e8f9849fa7a36a6698f

LTC:
LLR: 2.97 (-2.94,2.94) <-1.75,0.25>
Total: 253568 W: 67487 L: 67501 D: 118580
Ptnml(0-2): 109, 25222, 76141, 25198, 114
https://tests.stockfishchess.org/tests/view/63839859d2b9c924c4c4feb7

closes https://github.com/official-stockfish/Stockfish/pull/4248

Bench: 3733322
2022-12-02 20:03:49 +01:00
Guenther Demetz f5a31b7e57 Correctly output lowerbound/upperbound in threaded searches
fixes the lowerbound/upperbound output by taking the alpha,beta bracket
into account also if a bestThread is selected that is different from the master thread.

Instead of keeping track which bounds where used in the specific search,
in this version we simply store the quality (exact, upperbound,
lowerbound) of the score along with the actual score as information on
rootMove.

closes https://github.com/official-stockfish/Stockfish/pull/4239

No functional change
2022-11-23 21:45:06 +01:00
peregrineshahin 1370127fcd Simplify both quiet check evasions' conditions
passed Non-regression STC:
https://tests.stockfishchess.org/tests/view/6370b647f1b748d4819e0b64
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 162904 W: 43249 L: 43171 D: 76484
Ptnml(0-2): 491, 17089, 46220, 17155, 497

closes https://github.com/official-stockfish/Stockfish/pull/4228

No functional change
2022-11-23 21:36:22 +01:00
VoyagerOne 85ae65db1d Skip full depth search in LMR depending on depth
dynamically adjust newDepth, and skip full depth search if newDepth doesn't exceed the previous search depth.
This affects the used newDepth for future searches, and influences the stat bonus for the move.

Passed STC:
https://tests.stockfishchess.org/tests/view/63795500aa34433735bc1cfe
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 112776 W: 30082 L: 29663 D: 53031
Ptnml(0-2): 352, 12453, 30423, 12744, 416

Passed LTC:
https://tests.stockfishchess.org/tests/view/6379ea39aa34433735bc2f9b
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 83576 W: 22559 L: 22169 D: 38848
Ptnml(0-2): 38, 8011, 25303, 8395, 41

closes https://github.com/official-stockfish/Stockfish/pull/4240

Bench: 4390318
2022-11-23 21:25:14 +01:00
Joost VandeVondele d8f3209fb4 Update Top CPU Contributors
list as of 2022-11-19. Thanks!

closes https://github.com/official-stockfish/Stockfish/pull/4234

No functional change
2022-11-20 10:00:42 +01:00
Joost VandeVondele 3411631162 Update WDL model for current SF
This updates the WDL model based on the LTC statistics  (2M games).

Relatively small change, note that this also adjusts the NormalizeToPawnValue (now 361),
to keep win prob at 50% for 100cp.

closes https://github.com/official-stockfish/Stockfish/pull/4236

No functional change.
2022-11-20 09:59:35 +01:00
Joost VandeVondele d756d97a66 Fix a missing conversion
This conversion to cp was overlooked.

closes https://github.com/official-stockfish/Stockfish/pull/4235

No functional change
2022-11-20 09:58:07 +01:00
VoyagerOne 41c6a74d37 Simplification away Cutoff Reset
STC:
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 150184 W: 39913 L: 39819 D: 70452
Ptnml(0-2): 493, 16796, 40474, 16782, 547
https://tests.stockfishchess.org/tests/view/63723e9e54d69a2f33911d3c

LTC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 58880 W: 15890 L: 15717 D: 27273
Ptnml(0-2): 35, 5765, 17659, 5954, 27
https://tests.stockfishchess.org/tests/view/6373baf49849fa7a36a65427

closes https://github.com/official-stockfish/Stockfish/pull/4231

Bench: 4035152
2022-11-19 09:29:04 +01:00
Michael Chaly 219fa2f0a7 Do shallower search in case of lmr being not successful enough
In case of a move passing LMR but it results being not too far from
the current best search result produce a full depth search with reduced depth.

Original idea by lonfom169 .

Passed STC:
https://tests.stockfishchess.org/tests/view/6373409b54d69a2f33913fbd
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 169504 W: 45351 L: 44848 D: 79305
Ptnml(0-2): 598, 18853, 45353, 19344, 604

Passed LTC:
https://tests.stockfishchess.org/tests/view/6374c58528e3405283eb8d2d
LLR: 2.96 (-2.94,2.94) <0.50,2.50>
Total: 51144 W: 13802 L: 13471 D: 23871
Ptnml(0-2): 19, 4928, 15362, 5229, 34

closes https://github.com/official-stockfish/Stockfish/pull/4230

bench 4277005
2022-11-19 09:23:26 +01:00
disservin 6c1df553fa speedup CI
Github Actions allows us to use up to 20 workers.
This way we can launch multiple different checks
at the same time and optimize the overall time
the CI takes a bit.

closes https://github.com/official-stockfish/Stockfish/pull/4223

No functional change
2022-11-07 21:42:04 +01:00
disservin a413900791 Remove trend
Simplify trend away.

passed Non-regression STC:
https://tests.stockfishchess.org/tests/view/63642a63a90afcecbd1cb887
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 130000 W: 34683 L: 34567 D: 60750
Ptnml(0-2): 455, 14424, 35135, 14522, 464

passed Non-regression LTC:
https://tests.stockfishchess.org/tests/view/636566fda90afcecbd1cded9
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 81592 W: 21938 L: 21787 D: 37867
Ptnml(0-2): 42, 8035, 24490, 8188, 41

closes https://github.com/official-stockfish/Stockfish/pull/4222

Bench: 4239512
2022-11-07 08:00:05 +01:00
disservin e048d11825 Change versioning and save binaries as CI artifacts
For development versions of Stockfish, the version will now look like
dev-20221107-dca9a0533
indicating a development version, the date of the last commit,
and the git SHA of that commit. If git is not available,
the fallback is the date of compilation. Releases will continue to be
versioned as before.

Additionally, this PR extends the CI to create binary artifacts,
i.e. pushes to master will automatically build Stockfish and upload
the binaries to github.

closes https://github.com/official-stockfish/Stockfish/pull/4220

No functional change
2022-11-07 07:56:58 +01:00
Joost VandeVondele ad2aa8c06f Normalize evaluation
Normalizes the internal value as reported by evaluate or search
to the UCI centipawn result used in output. This value is derived from
the win_rate_model() such that Stockfish outputs an advantage of
"100 centipawns" for a position if the engine has a 50% probability to win
from this position in selfplay at fishtest LTC time control.

The reason to introduce this normalization is that our evaluation is, since NNUE,
no longer related to the classical parameter PawnValueEg (=208). This leads to
the current evaluation changing quite a bit from release to release, for example,
the eval needed to have 50% win probability at fishtest LTC (in cp and internal Value):

June 2020  :   113cp (237)
June 2021  :   115cp (240)
April 2022 :   134cp (279)
July 2022  :   167cp (348)

With this patch, a 100cp advantage will have a fixed interpretation,
i.e. a 50% win chance. To keep this value steady, it will be needed to update the win_rate_model()
from time to time, based on fishtest data. This analysis can be performed with
a set of scripts currently available at https://github.com/vondele/WLD_model

fixes https://github.com/official-stockfish/Stockfish/issues/4155
closes https://github.com/official-stockfish/Stockfish/pull/4216

No functional change
2022-11-05 09:15:53 +01:00
Joost VandeVondele 61a2cb84a6 Mark variable as potentially unused
fixes CI when compiled with -Werror

closes https://github.com/official-stockfish/Stockfish/pull/4221

No functional change
2022-11-05 09:15:14 +01:00
kurt22i d09653df0d Adjust reduction less at medium depths
This patch dampens the reduction increase/decrease from statScore at mid-range depths.
Inspired by patterns noticed in this tune: https://tests.stockfishchess.org/tests/view/635188930e5f47a8d0ffe8f5

Passed STC:
https://tests.stockfishchess.org/tests/view/63599dfd6b27ef94d9ec04af
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 87464 W: 23519 L: 23134 D: 40811
Ptnml(0-2): 319, 9599, 23524, 9958, 332

Passed LTC:
https://tests.stockfishchess.org/tests/view/635a73046b27ef94d9ec2313
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 154792 W: 41746 L: 41214 D: 71832
Ptnml(0-2): 79, 15181, 46349, 15703, 84

closes https://github.com/official-stockfish/Stockfish/pull/4213

Bench 4271738
2022-10-30 16:19:09 +01:00
Joost VandeVondele f154ed7a2d Update MacOS CI
move to 12 following actions runner update deprecation
(see https://github.com/actions/runner-images/issues/5583)

closes https://github.com/official-stockfish/Stockfish/pull/4212

No functional change
2022-10-30 16:17:49 +01:00
Clausable 8333b2a94c Fix README typos, update AUTHORS
closes https://github.com/official-stockfish/Stockfish/pull/4208

No functional change
2022-10-27 08:15:46 +02:00
dav1312 a5500edc55 Add issue template
Add an issue template using GitHub's form schema
https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema

closes https://github.com/official-stockfish/Stockfish/pull/4210

No functional change.
2022-10-26 20:28:12 +02:00
Michael Chaly 4ec8945eaf Use TT moves more often in qsearch
During the recapture phase of quiescence search (where we limit the generated moves to recaptures on the last seen capture square),
the move picker will now emit the tt move, even if the tt move is not a recapture.

Passed STC :
https://tests.stockfishchess.org/tests/view/6350df2928d3a71cb1eef838
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 90280 W: 24001 L: 23845 D: 42434
Ptnml(0-2): 273, 9779, 24941, 9813, 334

Passed LTC :
https://tests.stockfishchess.org/tests/view/6351308b28d3a71cb1ef06ce
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 104504 W: 27937 L: 27807 D: 48760
Ptnml(0-2): 54, 10378, 31260, 10504, 56

closes https://github.com/official-stockfish/Stockfish/pull/4206

Bench: 4540268
2022-10-23 20:22:04 +02:00
Clement 5604b255e6 Add RISC-V 64-bit support
adds a riscv64 target architecture to the Makefile to support RISC-V 64-bit.
Compiled and tested on VisionFive 2 board.

closes https://github.com/official-stockfish/Stockfish/pull/4205

No functional change.
2022-10-23 20:18:08 +02:00
disservin 804394b939 enable bit manipulation instruction set 1
bmi1 enables the use of _blsr_u64 for pop_lsb, and is availabe when avx2 is.

verified a small speedup (0.2 - 0.6%)

closes https://github.com/official-stockfish/Stockfish/pull/4202

No functional change
2022-10-23 20:08:18 +02:00
MinetaS 234d2156fd Apply -flto-partition=one / -flto=full
This patch fixes a potential bug derived from an incompatibility between LTO and top-level assembly code (INCBIN).

Passed non-regression STC (master e90341f):
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 119352 W: 31986 L: 31862 D: 55504
Ptnml(0-2): 439, 12624, 33400, 12800, 413
https://tests.stockfishchess.org/tests/view/634aacf84bc7650f0755188b

closes https://github.com/official-stockfish/Stockfish/pull/4201

No functional change
2022-10-23 19:58:47 +02:00
Rodrigo Roim 79c5f3a692 Fix tablebase probe for dtz >1000 w/o 50 move rule
For qn4N1/6R1/3K4/8/B2k4/8/8/8 w - - 0 1, white loses with DTZ 1034.
See https://syzygy-tables.info/?fen=qn4N1/6R1/3K4/8/B2k4/8/8/8_w_-_-_0_1

Prior to this fix, due to a too small hard-coded value, Stockfish interpreted this as winning.
The new value picked (1<<18) is large enough to deal with the largest DTZ values that can be stored in the current syzygy format.

closes https://github.com/official-stockfish/Stockfish/pull/4187

No functional change.
2022-10-16 12:58:48 +02:00
xoto10 9be2977da7 Adjust timeman constants
Adjust timeman constants to use more time in early part of game.

STC @ 10+0.1 th 1 :
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 93984 W: 25177 L: 24787 D: 44020
Ptnml(0-2): 350, 10096, 25729, 10448, 369
https://tests.stockfishchess.org/tests/live_elo/6339077135f43d649ff6162a

LTC @ 60+0.6 th 1 :
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 329368 W: 88953 L: 88093 D: 152322
Ptnml(0-2): 170, 31457, 100594, 32269, 194
https://tests.stockfishchess.org/tests/live_elo/6339baed35f43d649ff63142

Sudden death 10+0 :
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 20400 W: 5908 L: 5588 D: 8904
Ptnml(0-2): 177, 2252, 5128, 2360, 283
https://tests.stockfishchess.org/tests/live_elo/6347c9384bc7650f07549ba7

Sudden death 10+0, no adjudication :
LLR: 2.96 (-2.94,2.94) <0.00,2.00>
Total: 17920 W: 4755 L: 4442 D: 8723
Ptnml(0-2): 137, 1985, 4466, 2172, 200
https://tests.stockfishchess.org/tests/live_elo/634806e84bc7650f0754a639

closes https://github.com/official-stockfish/Stockfish/pull/4188

No functional change
2022-10-16 11:51:41 +02:00
Stéphane Nicolet d6b6360ff5 Tweak the formula for NNUE complexity
Joint work by Ofek Shochat and Stéphane Nicolet.

passed STC:
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 93288 W: 24996 L: 24601 D: 43691
Ptnml(0-2): 371, 10263, 24989, 10642, 379
https://tests.stockfishchess.org/tests/view/63448f4f4bc7650f07541987

passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 84168 W: 22771 L: 22377 D: 39020
Ptnml(0-2): 47, 8181, 25234, 8575, 47
https://tests.stockfishchess.org/tests/view/6345186d4bc7650f07542fbd

================

It seems there are two effects with this patch:

effect A :

If Stockfish is winning at root, we have optimism > 0 for all leaves in
the search tree where Stockfish is to move. There, if (psq - nnue) > 0
(ie if the advantage is more materialistic than positional), then the
product D = optimism * (psq - nnue) will be positive, nnueComplexity will
increase, and the eval will increase from SF point of view.

So the effect A is that if Stockfish is winning at root, she will slightly
favor in the search tree (in other words, search more) the positions where
she can convert her advantage via materialist means.

effect B :

If Stockfish is losing at root, we have optimism > 0 for all leaves in
the search tree where the opponent is to move. There, if (psq - nnue) < 0
(ie if the opponent advantage is more positional than materialistic), then
the product D = optimism * (psq-nnue) will be negative, nnueComplexity will
decrease, and the eval will decrease from the opponent point of view.

So the effect B is that Stockfish will slightly favor in the search tree
(search more) the branches where she can defend by slowly reducing the
opponent positional advantage.

=================

closes https://github.com/official-stockfish/Stockfish/pull/4195

bench: 4673898
2022-10-16 11:49:07 +02:00
Dubslow f97a86e213 Remove depth condition from razoring
The eval condition depends on depth anyways, so this patch is nearly (not quite) non-functional

passed STC:
https://tests.stockfishchess.org/tests/view/63428169fb7ccb2ea9be2629
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 185992 W: 49612 L: 49558 D: 86822
Ptnml(0-2): 618, 19956, 51842, 19914, 666

passed LTC:
https://tests.stockfishchess.org/tests/view/634418b14bc7650f07540760
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 126816 W: 34147 L: 34043 D: 58626
Ptnml(0-2): 74, 11941, 39281, 12031, 81

closes https://github.com/official-stockfish/Stockfish/pull/4196

bench 4148700
2022-10-16 11:45:16 +02:00
mstembera 93f71ecfe1 Optimize make_index() using templates and lookup tables.
https://tests.stockfishchess.org/tests/view/634517e54bc7650f07542f99
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 642672 W: 171819 L: 170658 D: 300195
Ptnml(0-2): 2278, 68077, 179416, 69336, 2229

this also introduces `-flto-partition=one` as suggested by MinetaS (Syine Mineta)
to avoid linking errors due to LTO on 32 bit mingw. This change was tested in isolation as well

https://tests.stockfishchess.org/tests/view/634aacf84bc7650f0755188b
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 119352 W: 31986 L: 31862 D: 55504
Ptnml(0-2): 439, 12624, 33400, 12800, 413

closes https://github.com/official-stockfish/Stockfish/pull/4199

No functional change
2022-10-16 11:42:19 +02:00
Stefan Geschwentner e90341f9c9 Tweak history initialization
Simplify initialization of continuation history by using everywhere the same starting value.

STC:
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 90952 W: 24312 L: 24153 D: 42487
Ptnml(0-2): 356, 10168, 24290, 10285, 377
https://tests.stockfishchess.org/tests/view/633948f235f43d649ff61fd0

LTC:
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 162416 W: 43540 L: 43466 D: 75410
Ptnml(0-2): 77, 16289, 48417, 16333, 92
https://tests.stockfishchess.org/tests/view/6339ee8a35f43d649ff63986

closes  https://github.com/official-stockfish/Stockfish/pull/4186

Bench: 4156027
2022-10-08 18:09:02 +02:00
Giacomo Lorenzetti d5271af0ee Remove old line in "Futility pruning for captures"
The line is no longer needed after https://github.com/official-stockfish/Stockfish/commit/910cf8b21839eb9f1991934a5436eea112021723.
This patch incidentally applies "Futility Pruning for Captures" also in case of en-passant, changing the bench signature.

Passed STC:
https://tests.stockfishchess.org/tests/view/6332c1f1208c26088697b731
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 68760 W: 18440 L: 18256 D: 32064
Ptnml(0-2): 267, 7530, 18595, 7728, 260

Passed LTC:
https://tests.stockfishchess.org/tests/view/633312e9208c26088697c59b
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 455552 W: 121910 L: 122123 D: 211519
Ptnml(0-2): 253, 45439, 136600, 45236, 248

closes https://github.com/official-stockfish/Stockfish/pull/4185

Bench: 4374521
2022-10-08 18:07:30 +02:00
Joost VandeVondele da937e219e Revert "Mix alpha and statScore for reduction"
This reverts commit 8bab09749d.

In this form the patch reduces mate finding effectiveness, as the large alpha value has negative influence on the reductions.

see also https://github.com/official-stockfish/Stockfish/pull/4183

Bench: 4114228
2022-10-05 22:59:05 +02:00
FauziAkram 8bab09749d Mix alpha and statScore for reduction
Idea by @xoto10, and tuning by @FauziAkram.

Passed STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 57832 W: 15540 L: 15199 D: 27093
Ptnml(0-2): 207, 6343, 15477, 6680, 209
https://tests.stockfishchess.org/tests/view/6338db6f35f43d649ff60fdc

passed LTC:
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 50968 W: 13770 L: 13440 D: 23758
Ptnml(0-2): 25, 4905, 15306, 5211, 37
https://tests.stockfishchess.org/tests/view/6339777035f43d649ff62686

Links to the tuning sessions:
https://tests.stockfishchess.org/tests/view/63345725a004bed9a2e47b28
https://tests.stockfishchess.org/tests/view/63345728a004bed9a2e47b2a

closes https://github.com/official-stockfish/Stockfish/pull/4183

Bench: 4426602
2022-10-04 01:07:27 +02:00
disservin f436bf77ad Use less reduction for escaping moves
This patch reuses the threatenedPieces variable (which is calculated in movepicker)
to reduce less in the search tree the moves which escape a capture.

passed STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 314352 W: 84042 L: 83328 D: 146982
Ptnml(0-2): 1105, 35084, 84207, 35552, 1228
https://tests.stockfishchess.org/tests/view/63355f37a004bed9a2e4a17f

passed LTC:
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 90752 W: 24556 L: 24147 D: 42049
Ptnml(0-2): 59, 8855, 27123, 9296, 43
https://tests.stockfishchess.org/tests/view/63383a7735f43d649ff5fa8b

closes https://github.com/official-stockfish/Stockfish/pull/4181

bench: 4114228
2022-10-03 11:50:31 +02:00
peregrineshahin 232bf19be4 Simplify both position calls in useClassical
Simplify the use of classical evaluation when using default settings to only be dependent on piece count and decisive PSQ

passed STC:
https://tests.stockfishchess.org/tests/view/632d32a7006ef9eb96d86ce9
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 108048 W: 28904 L: 28763 D: 50381
Ptnml(0-2): 383, 12060, 29006, 12183, 392

passed LTC:
https://tests.stockfishchess.org/tests/view/632d705a006ef9eb96d87649
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 76600 W: 20671 L: 20516 D: 35413
Ptnml(0-2): 34, 7533, 23023, 7664, 46

Inspired by sorais, credit to him.

closes https://github.com/official-stockfish/Stockfish/pull/4177

bench  4173163
2022-09-27 07:54:36 +02:00
Brad Knox 4339a756ac Update README.md
Adding some svg icons and additional information, insert links as references

closes https://github.com/official-stockfish/Stockfish/pull/4176

No functional change
2022-09-27 07:52:38 +02:00
Torsten Hellwig 70e51a5bc8 Always output hashfull
This removes the restriction that no hashfull information is printed within the first second of a search.
On modern systems, a non-zero value is returned within 6 ms with default settings.

passed STC:
https://tests.stockfishchess.org/tests/view/63277b08b9c0caa5f4a798e4
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 290096 W: 77505 L: 77561 D: 135030
Ptnml(0-2): 1008, 30713, 81592, 30797, 938

closes https://github.com/official-stockfish/Stockfish/pull/4174

No functional change
2022-09-27 07:48:05 +02:00
mstembera 29295ecfd3 Simplify EVASIONS scoring
remove some multipliers & adjust, doesn't change the move ordering

STC https://tests.stockfishchess.org/tests/view/6325c1c9b9c0caa5f4a759ae
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 192760 W: 51528 L: 51482 D: 89750
Ptnml(0-2): 642, 20490, 54148, 20380, 720

Credit to locutus2

closes https://github.com/official-stockfish/Stockfish/pull/4171

No functional change
2022-09-27 07:44:46 +02:00
mstembera dc0c441b7c Prioritize checks in movepicker
give a little bonus for moving pieces to squares where they give check

STC: https://tests.stockfishchess.org/tests/view/631da742162491686d2e40b5
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 80072 W: 21753 L: 21368 D: 36951
Ptnml(0-2): 421, 8876, 21075, 9225, 439

LTC: https://tests.stockfishchess.org/tests/view/631dd9e6b85daa436625de1d
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 263480 W: 70916 L: 70158 D: 122406
Ptnml(0-2): 322, 26156, 78029, 26908, 325

similar ideas have been tested by Viz and Guenther

closes https://github.com/official-stockfish/Stockfish/pull/4165

bench: 4326572
2022-09-17 09:30:52 +02:00
atumanian 154e7afed0 Simplify trend and optimism.
This patch simplifies the formulas used to compute the trend and optimism values before each search iteration.
As a side effect, this removes the parameters which make the relationship between the displayed evaluation value
and the expected game result asymmetric.

I've also provided links to the results of isotonic regression analysis of the relationship between the evaluation and game result (statistical data and a graph) for both tests, which demonstrate that the new version has a more symmetric relationship:

STC: [Data and graph](https://github.com/official-stockfish/Stockfish/discussions/4150#discussioncomment-3548954)
LTC: [Data and graph](https://github.com/official-stockfish/Stockfish/discussions/4150#discussioncomment-3626311)
See also https://github.com/official-stockfish/Stockfish/issues/4142

passed STC:
https://tests.stockfishchess.org/tests/view/6313f44b8202a039920e27e6
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 108016 W: 28903 L: 28760 D: 50353
Ptnml(0-2): 461, 12075, 28850, 12104, 518

passed LTC:
https://tests.stockfishchess.org/tests/view/631de45db85daa436625dfe6
LLR: 3.01 (-2.94,2.94) <-1.75,0.25>
Total: 34792 W: 9412 L: 9209 D: 16171
Ptnml(0-2): 24, 3374, 10397, 3577, 24

Furthermore, this does not measurably impact Elo strength against weaker engines,
as demonstrated in a match of master and patch vs SF13:

This patch vs SF 13:
https://tests.stockfishchess.org/tests/view/631fa34ae1612778c344c6eb
Elo: 141.66 +-1.2 (95%) LOS: 100.0%
Total: 100000 W: 48182 L: 9528 D: 42290
Ptnml(0-2): 96, 1426, 13277, 30130, 5071
nElo: 284.13 +-3.3 (95%) PairsRatio: 23.13

Master vs SF 13:
https://tests.stockfishchess.org/tests/view/631fa3ece1612778c344c6ff
Elo: 143.26 +-1.2 (95%) LOS: 100.0%
Total: 100000 W: 48525 L: 9479 D: 41996
Ptnml(0-2): 94, 1537, 13098, 29771, 5500
nElo: 281.70 +-3.3 (95%) PairsRatio: 21.63

closes: https://github.com/official-stockfish/Stockfish/pull/4163

Bench: 4425574
2022-09-17 09:13:07 +02:00
Joost VandeVondele 5a871e174f Explicitly annotate a few variables
as [[maybe_unused]], avoiding the (void)foo trick.

closes https://github.com/official-stockfish/Stockfish/pull/4162

No functional change
2022-09-17 09:05:35 +02:00
mstembera 82bb21dc7a Optimize AVX2 path in NNUE evaluation
always selecting AffineTransform specialization for small inputs.

A related patch was tested as

Initially tested as a simplification
STC https://tests.stockfishchess.org/tests/view/6317c3f437f41b13973d6dff
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 58072 W: 15619 L: 15425 D: 27028
Ptnml(0-2): 241, 6191, 15992, 6357, 255

Elo gain speedup test
STC https://tests.stockfishchess.org/tests/view/63181c1b37f41b13973d79dc
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 184496 W: 49922 L: 49401 D: 85173
Ptnml(0-2): 851, 19397, 51208, 19964, 828

and this patch gained in testing

speedup        = +0.0071
P(speedup > 0) =  1.0000
on CPU: 16 x AMD Ryzen 9 3950X

closes https://github.com/official-stockfish/Stockfish/pull/4158

No functional change
2022-09-11 14:19:57 +02:00
Michael Chaly 1591e5ac3b Do less singular extensions for former PVnode
Patch is a reintroduction of logic what was simplified a while ago
in a slightly different form. Do bigger extension offset in
case of non-pv node having a pv.

passed STC
https://tests.stockfishchess.org/tests/view/631977c048f27688a06e66d5
LLR: 2.94 (-2.94,2.94) <0.00,2.00>
Total: 23296 W: 6404 L: 6108 D: 10784
Ptnml(0-2): 88, 2539, 6118, 2795, 108

passed LTC
https://tests.stockfishchess.org/tests/view/631989cb48f27688a06e696c
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 235592 W: 63890 L: 63188 D: 108514
Ptnml(0-2): 275, 23392, 69804, 24006, 319

closes https://github.com/official-stockfish/Stockfish/pull/4159

Bench: 3993611
2022-09-11 14:15:54 +02:00
Dubslow 9fa258ee1d Razor also on PV nodes
Simplification introduced by xoto10

blue LTC vs new master:
https://tests.stockfishchess.org/tests/view/631ad4ef9cfa5e9b648d1b4e
LLR: 2.93 (-2.94,2.94) <-1.75,0.25>
Total: 59184 W: 16002 L: 15828 D: 27354
Ptnml(0-2): 65, 5777, 17747, 5925, 78

blue STC vs old master:
https://tests.stockfishchess.org/tests/view/6306b87b902a848543334c25
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 213944 W: 57184 L: 57159 D: 99601
Ptnml(0-2): 877, 23448, 58331, 23405, 911

blue LTC vs old master:
https://tests.stockfishchess.org/tests/view/63070e6b902a8485433357e7
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 192080 W: 52050 L: 52006 D: 88024
Ptnml(0-2): 232, 18981, 57611, 18943, 273

closes https://github.com/official-stockfish/Stockfish/pull/4147

bench 4208975
2022-09-11 14:13:24 +02:00
Michael Chaly eaf2c8207f Further LTC tuning of search parameters
Tuning done by bigpenor with some hand adjustments on top by Viz.

Had a good performance at fixed games 180+1.8:
https://tests.stockfishchess.org/tests/view/631836b437f41b13973d7da1
Elo: 1.35 +-1.2 (95%) LOS: 98.6%
Total: 60000 W: 16422 L: 16189 D: 27389
Ptnml(0-2): 39, 5335, 18992, 5622, 12
nElo: 3.13 +-2.8 (95%) PairsRatio: 1.05

Passed 60+0.6 8 threads SPRT:
https://tests.stockfishchess.org/tests/view/631ba0ff74bc4fe483a99db3
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 29712 W: 8301 L: 8039 D: 13372
Ptnml(0-2): 12, 2318, 9925, 2598, 3

closes https://github.com/official-stockfish/Stockfish/pull/4160

bench 3938073
2022-09-11 14:05:39 +02:00
FauziAkram 5eeb96d0e7 VLTC tuning
Tuning some parameters that scale well with longer time control:

Failed STC:
https://tests.stockfishchess.org/tests/view/6313424d8202a039920e130a
LLR: -2.94 (-2.94,2.94) <-1.75,0.25>
Total: 42680 W: 11231 L: 11540 D: 19909
Ptnml(0-2): 191, 5008, 11232, 4737, 172

Passed LTC:
https://tests.stockfishchess.org/tests/view/6311e2cd874169ca52ae7933
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 53448 W: 14782 L: 14437 D: 24229
Ptnml(0-2): 101, 5214, 15740, 5577, 92

Passed VLTC:
https://tests.stockfishchess.org/tests/view/6312530cfa99a92e3002c927
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 123336 W: 33465 L: 33007 D: 56864
Ptnml(0-2): 38, 11466, 38204, 11920, 40

closes https://github.com/official-stockfish/Stockfish/pull/4154

Bench: 5609606
2022-09-07 07:38:04 +02:00
Joost VandeVondele a4d18d23a9 Provide network download fallback
in case the base infrastructure for providing the networks

https://tests.stockfishchess.org/nns

is down, use an alternate github repo for downloading networks during the build.

fixes #4149
fixes #4140

closes https://github.com/official-stockfish/Stockfish/pull/4151

No functional change
2022-09-07 07:32:53 +02:00
Joost VandeVondele dddf8fc2b4 Increase the maximum number of threads to 1024
relatively soon servers with 512 threads will be available 'quite commonly',
anticipate even more threads, and increase our current maximum from 512 to 1024.

closes https://github.com/official-stockfish/Stockfish/pull/4152

No functional change.
2022-09-07 07:31:48 +02:00
dav1312 97860cb575 Disable ARM CI tests
Temporarily disable ARM CI tests until a mitigation is implemented

closes https://github.com/official-stockfish/Stockfish/pull/4148

No functional change.
2022-08-29 19:15:14 +02:00
mstembera 02ef1f4496 Make key_after() more consistent with key()
STC: https://tests.stockfishchess.org/tests/view/62f8547123d42b50a8dac674
LLR: 2.95 (-2.94,2.94) <0.00,2.00>
Total: 176640 W: 47699 L: 47189 D: 81752
Ptnml(0-2): 776, 18599, 49129, 18971, 845

A bug fix plus non functional speed optimization. Position::key_after(Move m) is now
consistent with Position::key() thus prefetching correct TT entries which speeds things up.
Related PR #3759

closes https://github.com/official-stockfish/Stockfish/pull/4130

No functional change
2022-08-17 19:56:15 +02:00
Joost VandeVondele 15ac117ac4 Simplify the use of classical eval
no benefit of the fallback term (exercised rarely).
Cleanup the associated code.

passed STC
https://tests.stockfishchess.org/tests/view/62f62c2b6f0a08af9f776367
LLR: 2.96 (-2.94,2.94) <-1.75,0.25>
Total: 67832 W: 18334 L: 18148 D: 31350
Ptnml(0-2): 369, 7171, 18609, 7439, 328

passed LTC
https://tests.stockfishchess.org/tests/view/62f68beb6f0a08af9f77710e
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 104664 W: 28363 L: 28233 D: 48068
Ptnml(0-2): 169, 10162, 31511, 10350, 140

closes https://github.com/official-stockfish/Stockfish/pull/4132

Bench: 6079565
2022-08-15 18:01:37 +02:00
Michael Chaly 5f290352cd Simplify away smp adjustment in TT use
Passed STC
https://tests.stockfishchess.org/tests/view/62f7d81f23d42b50a8dab568
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 98160 W: 26307 L: 26165 D: 45688
Ptnml(0-2): 201, 10282, 27960, 10448, 189

Passed LTC
https://tests.stockfishchess.org/tests/view/62f8d1a623d42b50a8dad4fb
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 81544 W: 22346 L: 22200 D: 36998
Ptnml(0-2): 44, 7542, 25446, 7704, 36

closes https://github.com/official-stockfish/Stockfish/pull/4131

No functional change (single threaded).
2022-08-15 17:54:56 +02:00
mckx00 3370f69881 Make LMR code easier to follow
Remove flags doFullDepthSearch and didLMR, and reorder instruction.

Small measured speedup.

Closes https://github.com/official-stockfish/Stockfish/pull/4129

No functional change.
2022-08-15 17:51:51 +02:00
mstembera 4568f6369b Report longest PV lines for multithreaded search
In case several threads find the same bestmove,
report the longest PV line found.

closes https://github.com/official-stockfish/Stockfish/pull/4126

No functional change.
2022-08-15 17:46:27 +02:00
Joost VandeVondele 1054a483ca Remove an unneeded randomization of evals.
most of the effect comes from the randomization of 3-folds.

passed STC:
https://tests.stockfishchess.org/tests/view/62e697e97e84186e5d19af6f
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 572976 W: 153168 L: 153539 D: 266269
Ptnml(0-2): 2505, 64783, 152364, 64250, 2586

passed LTC:
https://tests.stockfishchess.org/tests/view/62ee5977523c86dcd6957154
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 704808 W: 191212 L: 191680 D: 321916
Ptnml(0-2): 1340, 70579, 208972, 70235, 1278

closes https://github.com/official-stockfish/Stockfish/pull/4128

Bench: 5868987
2022-08-12 14:30:33 +02:00
Stefan Geschwentner 0a01dd044f Cleanup code
This PR includes following cleanups:
- Remove the unused depth variable in the thread class.
- cleanup ValueList (added from mstembera)

closes https://github.com/official-stockfish/Stockfish/pull/4127

No functional change.
2022-08-12 14:29:40 +02:00
Joost VandeVondele e639c45577 Update WDL model for current SF
This updates the WDL model based on the LTC statistics for the two weeks (3M games).

for old results see:

https://github.com/official-stockfish/Stockfish/pull/3981
https://github.com/official-stockfish/Stockfish/pull/3582
https://github.com/official-stockfish/Stockfish/pull/2778

closes https://github.com/official-stockfish/Stockfish/pull/4115

No functional change.
2022-08-06 13:57:30 +02:00
Joost VandeVondele 7cc929f437 Update CPU contributors list
Thanks for your contributions!

closes https://github.com/official-stockfish/Stockfish/pull/4116

No functional change
2022-08-06 13:53:55 +02:00
lonfom169 b8f4903fbb Reintroduce singularQuietLMR
STC:
LLR: 2.96 (-2.94,2.94) <0.00,2.00>
Total: 88912 W: 23972 L: 23580 D: 41360
Ptnml(0-2): 365, 9820, 23712, 10176, 383
https://tests.stockfishchess.org/tests/view/62e9537a400addce2c13399b

LTC:
LLR: 2.97 (-2.94,2.94) <0.50,2.50>
Total: 85672 W: 23607 L: 23192 D: 38873
Ptnml(0-2): 219, 8316, 25365, 8703, 233
https://tests.stockfishchess.org/tests/view/62e9a174400addce2c1346e4

closes https://github.com/official-stockfish/Stockfish/pull/4122

Bench: 5921315
2022-08-06 13:52:36 +02:00
Stefan Geschwentner 675f6a038b Tweak history updates
In general the history update bonus is slightly decreased by 11% which gives a slower saturation speed.
In addition only for main history the divisor is halfed (used history values are doubled to maintain same maximum)
which have an effect in the opposite direction on saturation speed.

STC:
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 157088 W: 42673 L: 42168 D: 72247
Ptnml(0-2): 857, 17346, 41642, 17833, 866
https://tests.stockfishchess.org/tests/view/62e5517ab383a712b13867c5

LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 325592 W: 88705 L: 87753 D: 149134
Ptnml(0-2): 594, 32288, 96076, 33248, 590
https://tests.stockfishchess.org/tests/view/62e5e4f4b383a712b1387d53

closes https://github.com/official-stockfish/Stockfish/pull/4119

Bench: 5518728
2022-08-06 13:50:01 +02:00
Michael Chaly 582c88ee94 Do more TT cutoffs in case of exact bound
The idea is that these TT entries are considered move valuable in TT replacement scheme - they are always overwriting other entries. So it makes sence for them to produce more aggressive cutoffs.

passed STC
https://tests.stockfishchess.org/tests/view/62e4d407b383a712b1385410
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 96632 W: 26045 L: 25659 D: 44928
Ptnml(0-2): 434, 10635, 25770, 11065, 412

passed LTC
https://tests.stockfishchess.org/tests/view/62e523e2b383a712b1386193
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 77960 W: 21363 L: 20989 D: 35608
Ptnml(0-2): 190, 7591, 23009, 8035, 155

closes https://github.com/official-stockfish/Stockfish/pull/4114

bench 5820568
2022-07-31 11:03:28 +02:00
Dubslow 18389e269d remove useClassical depth condition
passed STC:
https://tests.stockfishchess.org/tests/view/62e0c3e98e4fa6ae472695ed
LLR: 2.96 (-2.94,2.94) <-2.25,0.25>
Total: 293568 W: 78934 L: 79151 D: 135483
Ptnml(0-2): 1344, 31488, 81366, 31213, 1373

passed LTC:
https://tests.stockfishchess.org/tests/view/62e190aa8e4fa6ae4726b5b5
LLR: 2.98 (-2.94,2.94) <-2.25,0.25>
Total: 187392 W: 50971 L: 51028 D: 85393
Ptnml(0-2): 384, 17801, 57369, 17772, 370

other attempts to otherwise tune this parameter failed, bounds 6,7,10,11 failed STC, 8 passed STC but failed LTC

closes https://github.com/official-stockfish/Stockfish/pull/4112

bench 5796377
2022-07-31 11:00:31 +02:00
Dubslow c4a644922d Simplify reduction condition for cutNodes
LMR: for cutNodes, dont exclude killer moves. This was a prelude to reducing
allNodes, altho that's failed so far.

STC https://tests.stockfishchess.org/tests/view/62d64ad147ae1768b34a27c3
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 37064 W: 10044 L: 9889 D: 17131
Ptnml(0-2): 162, 4115, 9828, 4260, 167

LTC https://tests.stockfishchess.org/tests/view/62d66cc047ae1768b34a2b14
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 39832 W: 10796 L: 10659 D: 18377
Ptnml(0-2): 69, 3969, 11706, 4100, 72

closes https://github.com/official-stockfish/Stockfish/pull/4109

bench: 5697891
2022-07-24 09:18:38 +02:00
Joost VandeVondele 4b4b7d1209 Update default net to nn-ad9b42354671.nnue
using trainer branch https://github.com/glinscott/nnue-pytorch/pull/208 with a slightly
tweaked loss function (power 2.5 instead of 2.6), otherwise same training as in
the previous net update https://github.com/official-stockfish/Stockfish/pull/4100

passed STC:
LLR: 2.97 (-2.94,2.94) <0.00,2.50>
Total: 367536 W: 99465 L: 98573 D: 169498
Ptnml(0-2): 1820, 40994, 97117, 42148, 1689
https://tests.stockfishchess.org/tests/view/62cc43fe50dcbecf5fc1c5b8

passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 25032 W: 6802 L: 6553 D: 11677
Ptnml(0-2): 40, 2424, 7341, 2669, 42
https://tests.stockfishchess.org/tests/view/62ce5f421dacb46e4d5fd277

closes https://github.com/official-stockfish/Stockfish/pull/4107

Bench: 5905619
2022-07-13 18:01:20 +02:00
Michael Chaly 95d24b77df Simplify away some unneeded code in time management
The lower bound of the clamp is never used since complexity can't be negative and thus is unneeded.

closes https://github.com/official-stockfish/Stockfish/pull/4105

No functional change
2022-07-13 18:00:39 +02:00
Joost VandeVondele 2e02dd7936 Limit the researching at same depth.
If the elapsed time is close to the available time, the time management thread can signal that the next iterations should be searched at the same depth (Threads.increaseDepth = false). While the rootDepth increases, the adjustedDepth is kept constant with the searchAgainCounter.

In exceptional cases, when threading is used and the master thread, which controls the time management, signals to not increaseDepth, but by itself takes a long time to finish the iteration, the helper threads can search repeatedly at the same depth. This search finishes more and more quickly, leading to helper threads that report a rootDepth of MAX_DEPTH (245). The latter is not optimal as it is confusing for the user, stops search on these threads, and leads to an incorrect bias in the thread voting scheme. Probably with only a small impact on strength.

This behavior was observed almost two years ago,
see https://github.com/official-stockfish/Stockfish/issues/2717

This patch fixes #2717 by ensuring the effective depth increases at once every four iterations,
even in increaseDepth is false.

Depth 245 searches (for non-trivial positions) were indeed absent with this patch,
but frequent with master in the tests below:
https://discord.com/channels/435943710472011776/813919248455827515/994872720800088095
Total pgns: 2173
Base: 2867
Patch: 0

it passed non-regression testing in various setups:

SMP STC:
https://tests.stockfishchess.org/tests/view/62bfecc96178ffe6394ba036
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 37288 W: 10171 L: 10029 D: 17088
Ptnml(0-2): 75, 3777, 10793, 3929, 70

SMP LTC:
https://tests.stockfishchess.org/tests/view/62c08f6f49b62510394be066
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 190568 W: 52125 L: 52186 D: 86257
Ptnml(0-2): 70, 17854, 59504, 17779, 77

LTC:
https://tests.stockfishchess.org/tests/view/62c08b6049b62510394bdfb6
LLR: 2.96 (-2.94,2.94) <-2.25,0.25>
Total: 48120 W: 13204 L: 13083 D: 21833
Ptnml(0-2): 54, 4458, 14919, 4571, 58

Special thanks to miguel-I,  Disservin, ruicoelhopedro and others for analysing the problem,
the data, and coming up with the key insight, needed to fix this longstanding issue.

closes https://github.com/official-stockfish/Stockfish/pull/4104

Bench: 5182295
2022-07-09 10:58:04 +02:00
Dubslow aa18b68033 Time mgmt fix division.
oversight changed the corresponding float division to integer division in a previous tune https://github.com/official-stockfish/Stockfish/commit/442c40b43de8ede1e424efa674c8d45322e3b43c it is stronger to keep the original float division.

green LTC: https://tests.stockfishchess.org/tests/view/62bf34bc0340fb1e0cc934e7
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 38952 W: 10738 L: 10467 D: 17747
Ptnml(0-2): 46, 3576, 11968, 3833, 53

yellow STC: https://tests.stockfishchess.org/tests/view/62bff6506178ffe6394ba1d1
LLR: -2.95 (-2.94,2.94) <0.00,2.50>
Total: 226960 W: 61265 L: 61062 D: 104633
Ptnml(0-2): 938, 24398, 62582, 24647, 915

further slightly tweaked tests confirm this Elo gain.

closes https://github.com/official-stockfish/Stockfish/pull/4097

No functional change
2022-07-09 10:53:17 +02:00
Michael Chaly c2aaaa65f9 Simplify away FRC correction term
Since new net is trained partially using FRC data this part of adjustment that penalises bishops that are locked in the corner is no longer needed - net should "know" this things itself much better.

STC on FRC book :
https://tests.stockfishchess.org/tests/view/62c3031b9e7d9997a12d852f
LLR: 2.96 (-2.94,2.94) <-2.25,0.25>
Total: 22048 W: 3003 L: 2845 D: 16200
Ptnml(0-2): 96, 1778, 7149, 1874, 127

LTC on FRC book :
https://tests.stockfishchess.org/tests/view/62c32e939e7d9997a12d8c5e
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 36784 W: 3138 L: 3037 D: 30609
Ptnml(0-2): 36, 1842, 14537, 1939, 38

STC on DFRC book :
https://tests.stockfishchess.org/tests/view/62c32efb9e7d9997a12d8c6f
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 20424 W: 3903 L: 3721 D: 12800
Ptnml(0-2): 172, 1984, 5724, 2154, 178

LTC on DFRC book :
https://tests.stockfishchess.org/tests/view/62c358c79e7d9997a12d9319
LLR: 2.93 (-2.94,2.94) <-2.25,0.25>
Total: 53784 W: 7581 L: 7480 D: 38723
Ptnml(0-2): 87, 3887, 18856, 3962, 100

closes https://github.com/official-stockfish/Stockfish/pull/4101

bench 5182295
2022-07-05 13:55:50 +02:00
Joost VandeVondele 85f8ee6199 Update default net to nn-3c0054ea9860.nnu
First things first...

this PR is being made from court. Today, Tord and Stéphane, with broad support
of the developer community are defending their complaint, filed in Munich, against ChessBase.
With their products Houdini 6 and Fat Fritz 2, both Stockfish derivatives,
ChessBase violated repeatedly the Stockfish GPLv3 license. Tord and Stéphane have terminated
their license with ChessBase permanently. Today we have the opportunity to present
our evidence to the judge and enforce that termination. To read up, have a look at our blog post
https://stockfishchess.org/blog/2022/public-court-hearing-soon/ and
https://stockfishchess.org/blog/2021/our-lawsuit-against-chessbase/

This PR introduces a net trained with an enhanced data set and a modified loss function in the trainer.
A slight adjustment for the scaling was needed to get a pass on standard chess.

passed STC:
https://tests.stockfishchess.org/tests/view/62c0527a49b62510394bd610
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 135008 W: 36614 L: 36152 D: 62242
Ptnml(0-2): 640, 15184, 35407, 15620, 653

passed LTC:
https://tests.stockfishchess.org/tests/view/62c17e459e7d9997a12d458e
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 28864 W: 8007 L: 7749 D: 13108
Ptnml(0-2): 47, 2810, 8466, 3056, 53

Local testing at a fixed 25k nodes resulted in
Test run1026/easy_train_data/experiments/experiment_2/training/run_0/nn-epoch799.nnue
localElo: 4.2  +-      1.6

The real strength of the net is in FRC and DFRC chess where it gains significantly.

Tested at STC with slightly different scaling:
FRC:
https://tests.stockfishchess.org/tests/view/62c13a4002ba5d0a774d20d4
Elo: 29.78 +-3.4 (95%) LOS: 100.0%
Total: 10000 W: 2007 L: 1152 D: 6841
Ptnml(0-2): 31, 686, 2804, 1355, 124
nElo: 59.24 +-6.9 (95%) PairsRatio: 2.06

DFRC:
https://tests.stockfishchess.org/tests/view/62c13a5702ba5d0a774d20d9
Elo: 55.25 +-3.9 (95%) LOS: 100.0%
Total: 10000 W: 2984 L: 1407 D: 5609
Ptnml(0-2): 51, 636, 2266, 1779, 268
nElo: 96.95 +-7.2 (95%) PairsRatio: 2.98

Tested at LTC with identical scaling:
FRC:
https://tests.stockfishchess.org/tests/view/62c26a3c9e7d9997a12d6caf
Elo: 16.20 +-2.5 (95%) LOS: 100.0%
Total: 10000 W: 1192 L: 726 D: 8082
Ptnml(0-2): 10, 403, 3727, 831, 29
nElo: 44.12 +-6.7 (95%) PairsRatio: 2.08

DFRC:
https://tests.stockfishchess.org/tests/view/62c26a539e7d9997a12d6cb2
Elo: 40.94 +-3.0 (95%) LOS: 100.0%
Total: 10000 W: 2215 L: 1042 D: 6743
Ptnml(0-2): 10, 410, 3053, 1451, 76
nElo: 92.77 +-6.9 (95%) PairsRatio: 3.64

This is due to the mixing in a significant fraction of DFRC training data in the final training round. The net is
trained using the easy_train.py script in the following way:

```
python easy_train.py \
     --training-dataset=../Leela-dfrc_n5000.binpack \
     --experiment-name=2 \
     --nnue-pytorch-branch=vondele/nnue-pytorch/lossScan4 \
     --additional-training-arg=--param-index=2 \
     --start-lambda=1.0 \
     --end-lambda=0.75 \
     --gamma=0.995 \
     --lr=4.375e-4 \
     --start-from-engine-test-net True \
     --tui=False \
     --seed=$RANDOM \
     --max_epoch=800 \
     --auto-exit-timeout-on-training-finished=900 \
     --network-testing-threads 8  \
     --num-workers 12
```

where the data set used (Leela-dfrc_n5000.binpack) is a combination of our previous best data set (mix of Leela and some SF data) and DFRC data, interleaved to form:
The data is available in https://drive.google.com/drive/folders/1S9-ZiQa_3ApmjBtl2e8SyHxj4zG4V8gG?usp=sharing
Leela mix: https://drive.google.com/file/d/1JUkMhHSfgIYCjfDNKZUMYZt6L5I7Ra6G/view?usp=sharing
DFRC: https://drive.google.com/file/d/17vDaff9LAsVo_1OfsgWAIYqJtqR8aHlm/view?usp=sharing

The training branch used is
https://github.com/vondele/nnue-pytorch/commits/lossScan4
A PR to the main trainer repo will be made later. This contains a revised loss function, now computing the loss from the score based on the win rate model, which is a more accurate representation than what we had before. Scaling constants are tweaked there as well.

closes https://github.com/official-stockfish/Stockfish/pull/4100

Bench: 5186781
2022-07-04 15:42:34 +02:00
Dubslow 442c40b43d Use NNUE complexity in search, retune related parameters
This builds on ideas of xoto10 and mstembera to use more output from NNUE in the search algorithm.

passed STC:
https://tests.stockfishchess.org/tests/view/62ae454fe7ee5525ef88a957
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 89208 W: 24127 L: 23753 D: 41328
Ptnml(0-2): 400, 9886, 23642, 10292, 384

passed LTC:
https://tests.stockfishchess.org/tests/view/62acc6ddd89eb6cf1e0750a1
LLR: 2.93 (-2.94,2.94) <0.50,3.00>
Total: 56352 W: 15430 L: 15115 D: 25807
Ptnml(0-2): 44, 5501, 16782, 5794, 55

closes https://github.com/official-stockfish/Stockfish/pull/4088

bench 5332964
2022-06-20 08:30:57 +02:00
Dubslow 5304b561ab LMR: remove deeper
...apparently it wasn't doing much anymore. inspired by rufish's recent attempts to improve this.

passed STC:
https://tests.stockfishchess.org/tests/view/62abca2cd89eb6cf1e072c04
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 85576 W: 22766 L: 22683 D: 40127
Ptnml(0-2): 362, 9607, 22741, 9742, 336

passed LTC:
https://tests.stockfishchess.org/tests/view/62ac90ffd89eb6cf1e07488f
LLR: 2.93 (-2.94,2.94) <-2.25,0.25>
Total: 48248 W: 13018 L: 12896 D: 22334
Ptnml(0-2): 32, 4773, 14400, 4879, 40

closes https://github.com/official-stockfish/Stockfish/pull/4088

bench 5578988
2022-06-20 08:25:50 +02:00
bmc4 4d6a11a04c Don't change ttPv at probCut
STC:
LLR: 2.96 (-2.94,2.94) <-2.25,0.25>
Total: 35672 W: 9618 L: 9462 D: 16592
Ptnml(0-2): 151, 3890, 9601, 4040, 154
https://tests.stockfishchess.org/tests/view/62ab03f750949cfc241b1965

LTC:
LLR: 2.93 (-2.94,2.94) <-2.25,0.25>
Total: 54160 W: 14626 L: 14511 D: 25023
Ptnml(0-2): 42, 5414, 16056, 5523, 45
https://tests.stockfishchess.org/tests/view/62ab5e6fd89eb6cf1e071b87

closes https://github.com/official-stockfish/Stockfish/pull/4088

bench: 5798229
2022-06-20 08:24:07 +02:00
bmc4 6edc29d720 Simplify away condition in ttSave in probCut
Remove condition for tte->save in probCut so it always saves on probCut cutoff.

STC:
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 47848 W: 12921 L: 12782 D: 22145
Ptnml(0-2): 207, 5340, 12715, 5431, 231
https://tests.stockfishchess.org/tests/view/62a1f7c87bd8e641e44436f7

LTC:
LLR: 2.97 (-2.94,2.94) <-2.25,0.25>
Total: 132736 W: 35895 L: 35881 D: 60960
Ptnml(0-2): 109, 13384, 39360, 13414, 101
https://tests.stockfishchess.org/tests/view/62a2421a7bd8e641e444434f

closes https://github.com/official-stockfish/Stockfish/pull/4069

bench: 5845802
2022-06-16 07:12:01 +02:00
mstembera 2d5dcf3d18 Minor simplifications and cleanup in search
STC: https://tests.stockfishchess.org/tests/view/629d6775593a4a9b6482c1ec
LLR: 2.93 (-2.94,2.94) <-2.25,0.25>
Total: 77416 W: 20683 L: 20589 D: 36144
Ptnml(0-2): 317, 8690, 20620, 8744, 337

LTC: https://tests.stockfishchess.org/tests/view/629db4be593a4a9b6482ceef
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 106544 W: 28752 L: 28705 D: 49087
Ptnml(0-2): 97, 10692, 31641, 10751, 91

closes https://github.com/official-stockfish/Stockfish/pull/4059

Bench: 5913510
2022-06-16 07:06:43 +02:00
ppigazzini d54b85b4bd Restore NDKv21 for GitHub Actions
GitHub updated the versions of NDK installed on the Actions runners
breaking the ARM tests.
Restore the NDKv21 using the GitHub suggested mitigation, see:
https://github.com/actions/virtual-environments/issues/5595

closes https://github.com/official-stockfish/Stockfish/pull/4077

No functional change
2022-06-16 07:03:52 +02:00
candirufish 00297cfef0 Use qsearch on step 11 if depth is equal to or below 0
larger reduction of depth if no TT entry is found, and go in qsearch as needed.

stc:
https://tests.stockfishchess.org/tests/view/629dfacd593a4a9b6482db72
LLR: 2.93 (-2.94,2.94) <0.00,2.50>
Total: 31920 W: 8591 L: 8322 D: 15007
Ptnml(0-2): 127, 3551, 8376, 3738, 168

ltc:
https://tests.stockfishchess.org/tests/view/629e304e593a4a9b6482e451
LLR: 2.95 (-2.94,2.94) <0.50,3.00>
Total: 17488 W: 4842 L: 4614 D: 8032
Ptnml(0-2): 13, 1670, 5151, 1896, 14

closes https://github.com/official-stockfish/Stockfish/pull/4056

Bench: 5870283
2022-06-07 08:34:14 +02:00
Boštjan Mejak 809849fa27 Wording of help output and comments.
Improved the output text that is diplayed when executing the 'help' command.
Also, some comments were fixed along the way.

closes https://github.com/official-stockfish/Stockfish/pull/4048
closes https://github.com/official-stockfish/Stockfish/pull/4044

No functional change
2022-06-07 08:30:07 +02:00
Dubslow 90cf8e7d2b Remove LMR condition for complex pos
Inspired by Kia's similar test: https://tests.stockfishchess.org/tests/view/6292898c1e7cd5f29966fbe0

Passed STC:
https://tests.stockfishchess.org/tests/view/62941588b0d5a7d1b780ed4b
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 266872 W: 70850 L: 71033 D: 124989
Ptnml(0-2): 1180, 30114, 70941, 30111, 1090

Passed LTC:
https://tests.stockfishchess.org/tests/view/62964a754628d33daa24f062
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 70160 W: 18756 L: 18662 D: 32742
Ptnml(0-2): 42, 6976, 20950, 7070, 42

closes https://github.com/official-stockfish/Stockfish/pull/4047

Bench 6237567
2022-06-02 07:49:31 +02:00
xoto10 7f1333ccf8 Blend nnue complexity with classical.
Following mstembera's test of the complexity value derived from nnue values,
this change blends that idea with the old complexity calculation.

STC 10+0.1:
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 42320 W: 11436 L: 11148 D: 19736
Ptnml(0-2): 209, 4585, 11263, 4915, 188
https://tests.stockfishchess.org/tests/live_elo/6295c9239c8c2fcb2bad7fd9

LTC 60+0.6:
LLR: 2.98 (-2.94,2.94) <0.50,3.00>
Total: 34600 W: 9393 L: 9125 D: 16082
Ptnml(0-2): 32, 3323, 10319, 3597, 29
https://tests.stockfishchess.org/tests/view/6295fd5d9c8c2fcb2bad88cf

closes https://github.com/official-stockfish/Stockfish/pull/4046

Bench 6078140
2022-06-02 07:47:23 +02:00
candirufish 653bd0817c cutnode and movecount lmr extension simplification
Passed STC
https://tests.stockfishchess.org/tests/view/6294133cb0d5a7d1b780ece3
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 41072 W: 11052 L: 10908 D: 19112
Ptnml(0-2): 153, 4324, 11461, 4422, 176

Passed LTC
ltc: https://tests.stockfishchess.org/tests/view/62947ae6b0d5a7d1b780fe86
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 102736 W: 27509 L: 27459 D: 47768
Ptnml(0-2): 98, 9734, 31669, 9754, 113

closes https://github.com/official-stockfish/Stockfish/pull/4045

Bench: 6410652
2022-06-02 07:44:22 +02:00
Michael Chaly 8fadbcf1b2 Add info about elo gained from some heuristics
Add info about qsearch and impact of main and continuation histories.

Based on these tests:
https://tests.stockfishchess.org/tests/view/62946ffcb0d5a7d1b780fc7e
https://tests.stockfishchess.org/tests/view/628facb71e7cd5f299669534
https://tests.stockfishchess.org/tests/view/628eade11e7cd5f299666f2e

closes https://github.com/official-stockfish/Stockfish/pull/4041

No functional change.
2022-06-02 07:43:14 +02:00
xoto10 4c7de9e8ab Adjust scale param higher
xoto10's scaleopt tune resulted in a yellow LTC, but the main parameter shift looked almost exactly like the tune rate reduction schedule,
so further increases of that param were tried. Joint work xoto10 and dubslow.

passed LTC:
https://tests.stockfishchess.org/tests/view/628c709372775f382300f03e
LLR: 2.93 (-2.94,2.94) <0.50,3.00>
Total: 70112 W: 18932 L: 18584 D: 32596
Ptnml(0-2): 66, 6904, 20757, 7274, 55

failed STC:
https://tests.stockfishchess.org/tests/view/6290e4441e7cd5f29966bdc8
LLR: -2.96 (-2.94,2.94) <0.00,2.50>
Total: 59976 W: 15919 L: 16018 D: 28039
Ptnml(0-2): 250, 6791, 15974, 6754, 219

similar LTC's were yellow
first yellow LTC: https://tests.stockfishchess.org/tests/view/6288a33f817227d3e5c5b05d
double exaggerate yellow: https://tests.stockfishchess.org/tests/live_elo/628e140372775f38230129a6
triple exaggerate yellow: https://tests.stockfishchess.org/tests/live_elo/628e2caf72775f3823012d45

closes https://github.com/official-stockfish/Stockfish/pull/4036

bench 6410652
2022-05-29 19:14:20 +02:00
proukornew 6ede1bed89 Improve handling of variables set in the make environment
removes duplication on the commandline for example in a profile-build

closes https://github.com/official-stockfish/Stockfish/pull/3859

No functional change
2022-05-29 19:04:25 +02:00
Giacomo Lorenzetti 1a168201bd Small speedup in futility_move_count
The speedup is around 0.25% using gcc 11.3.1 (bmi2, nnue bench, depth 16
and 23) while it is neutral using clang (same conditions).

According to `perf` that integer division was one of the most time-consuming
instructions in search (gcc disassembly).

Passed STC:
https://tests.stockfishchess.org/tests/view/628a17fe24a074e5cd59b3aa
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 22232 W: 5992 L: 5751 D: 10489
Ptnml(0-2): 88, 2235, 6218, 2498, 77

yellow LTC:
https://tests.stockfishchess.org/tests/view/628a35d7ccae0450e35106f7
LLR: -2.95 (-2.94,2.94) <0.50,3.00>
Total: 320168 W: 85853 L: 85326 D: 148989
Ptnml(0-2): 185, 29698, 99821, 30165, 215

This patch also suggests that UHO STC is sensible to small speedups (< 0.50%).

closes https://github.com/official-stockfish/Stockfish/pull/4032

No functional change
2022-05-29 18:54:19 +02:00
Joost VandeVondele 48df0754bc Add command line flags to link to information
This patch provides command line flags `--help` and `--license` as well as the corresponding `help` and `license` commands.

```
$ ./stockfish --help
Stockfish 200522 by the Stockfish developers (see AUTHORS file)

Stockfish is a powerful chess engine and free software licensed under the GNU GPLv3.
Stockfish is normally used with a separate graphical user interface (GUI).
Stockfish implements the universal chess interface (UCI) to exchange information.
For further information see https://github.com/official-stockfish/Stockfish#readme
or the corresponding README.md and Copying.txt files distributed with this program.

```

The idea is to provide a minimal help that links to the README.md file,
not replicating information that is already available elsewhere.

We use this opportunity to explicitly report the license as well.

closes https://github.com/official-stockfish/Stockfish/pull/4027

No functional change.
2022-05-29 18:46:35 +02:00
Giacomo Lorenzetti f7d1491b3d Assorted small cleanups
closes https://github.com/official-stockfish/Stockfish/pull/3973

No functional change
2022-05-29 18:42:48 +02:00
candirufish cc7bcd5303 Simplify a condition
Principal variation depth late move reduction extension simplification.

stc:
https://tests.stockfishchess.org/tests/view/6285a1d19d18a78568e7fa24
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 428536 W: 113433 L: 113851 D: 201252
Ptnml(0-2): 1671, 48606, 114090, 48272, 1629

ltc:
https://tests.stockfishchess.org/tests/view/62871d20375cdc5de8cf5db3
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 56792 W: 15123 L: 15011 D: 26658
Ptnml(0-2): 42, 5681, 16825, 5819, 29

closes https://github.com/official-stockfish/Stockfish/pull/4028

bench: 6501437
2022-05-21 12:42:33 +02:00
xoto10 22b7909809 Tune scale and optimism.
Tune scale and optimism in effort to make stockfish play more aggressively.

STC @ 10+0.1 th 1:
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 27896 W: 7506 L: 7248 D: 13142
Ptnml(0-2): 103, 3047, 7388, 3309, 101
https://tests.stockfishchess.org/tests/live_elo/627fd0cfab44257388ab1f13

LTC @ 60+0.6 th 1:
LLR: 2.93 (-2.94,2.94) <0.50,3.00>
Total: 65576 W: 17512 L: 17178 D: 30886
Ptnml(0-2): 37, 6397, 19587, 6729, 38
https://tests.stockfishchess.org/tests/live_elo/627ff666ab44257388ab256d

closes https://github.com/official-stockfish/Stockfish/pull/4025

Bench 6407734
2022-05-15 20:20:37 +02:00
disservin 5372f81cc8 SE depth scaling using the previous depth
This patch makes the SE depth condition more robust and allows it to scale with completed depth
from a previous search.

At long TC this patch is almost equivalent to https://github.com/official-stockfish/Stockfish/pull/4016 which had

VLTC:
https://tests.stockfishchess.org/tests/view/626abd7e8707aa698c0093a8
Elo: 2.35 +-1.5 (95%) LOS: 99.9%
Total: 40000 W: 10991 L: 10720 D: 18289
Ptnml(0-2): 8, 3534, 12648, 3799, 11
nElo: 5.47 +-3.4 (95%) PairsRatio: 1.08

VLTC multicore:
https://tests.stockfishchess.org/tests/view/6272a6afc8f14123163c1997
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 86808 W: 24165 L: 23814 D: 38829
Ptnml(0-2): 11, 7253, 28524, 7606, 10

however, it is now also gaining at LTC:

LTC:
https://tests.stockfishchess.org/tests/view/627e7cb523c0c72a05b651a9
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 27064 W: 7285 L: 7046 D: 12733
Ptnml(0-2): 8, 2446, 8390, 2675, 13

and should have nearly no influence at STC as depth 27 is rarely reached.
It was noticed that initializing the threshold with MAX_PLY, had an adverse effect,
possibly because the first move is sensitive to this.

closes https://github.com/official-stockfish/Stockfish/pull/4021
closes https://github.com/official-stockfish/Stockfish/pull/4016

Bench: 6481017
2022-05-14 13:17:35 +02:00
Tomasz Sobczyk c079acc26f Update NNUE architecture to SFNNv5. Update network to nn-3c0aa92af1da.nnue.
Architecture changes:

    Duplicated activation after the 1024->15 layer with squared crelu (so 15->15*2). As proposed by vondele.

Trainer changes:

    Added bias to L1 factorization, which was previously missing (no measurable improvement but at least neutral in principle)
    For retraining linearly reduce lambda parameter from 1.0 at epoch 0 to 0.75 at epoch 800.
    reduce max_skipping_rate from 15 to 10 (compared to vondele's outstanding PR)

Note: This network was trained with a ~0.8% error in quantization regarding the newly added activation function.
      This will be fixed in the released trainer version. Expect a trainer PR tomorrow.

Note: The inference implementation cuts a corner to merge results from two activation functions.
       This could possibly be resolved nicer in the future. AVX2 implementation likely not necessary, but NEON is missing.

First training session invocation:

python3 train.py \
    ../nnue-pytorch-training/data/nodes5000pv2_UHO.binpack \
    ../nnue-pytorch-training/data/nodes5000pv2_UHO.binpack \
    --gpus "$3," \
    --threads 4 \
    --num-workers 8 \
    --batch-size 16384 \
    --progress_bar_refresh_rate 20 \
    --random-fen-skipping 3 \
    --features=HalfKAv2_hm^ \
    --lambda=1.0 \
    --max_epochs=400 \
    --default_root_dir ../nnue-pytorch-training/experiment_$1/run_$2

Second training session invocation:

python3 train.py \
    ../nnue-pytorch-training/data/T60T70wIsRightFarseerT60T74T75T76.binpack \
    ../nnue-pytorch-training/data/T60T70wIsRightFarseerT60T74T75T76.binpack \
    --gpus "$3," \
    --threads 4 \
    --num-workers 8 \
    --batch-size 16384 \
    --progress_bar_refresh_rate 20 \
    --random-fen-skipping 3 \
    --features=HalfKAv2_hm^ \
    --start-lambda=1.0 \
    --end-lambda=0.75 \
    --gamma=0.995 \
    --lr=4.375e-4 \
    --max_epochs=800 \
    --resume-from-model /data/sopel/nnue/nnue-pytorch-training/data/exp367/nn-exp367-run3-epoch399.pt \
    --default_root_dir ../nnue-pytorch-training/experiment_$1/run_$2

Passed STC:
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 27288 W: 7445 L: 7178 D: 12665
Ptnml(0-2): 159, 3002, 7054, 3271, 158
https://tests.stockfishchess.org/tests/view/627e8c001919125939623644

Passed LTC:
LLR: 2.95 (-2.94,2.94) <0.50,3.00>
Total: 21792 W: 5969 L: 5727 D: 10096
Ptnml(0-2): 25, 2152, 6294, 2406, 19
https://tests.stockfishchess.org/tests/view/627f2a855734b18b2e2ece47

closes https://github.com/official-stockfish/Stockfish/pull/4020

Bench: 6481017
2022-05-14 12:47:22 +02:00
Stéphane Nicolet 9eb7b607cf Reduce depth after score improvement at PV nodes
STC:
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 73760 W: 19590 L: 19244 D: 34926
Ptnml(0-2): 285, 8352, 19292, 8634, 317
https://tests.stockfishchess.org/tests/view/626eb2dc9116b52aa83b73da

LTC:
LLR: 2.93 (-2.94,2.94) <0.50,3.00>
Total: 114400 W: 30561 L: 30111 D: 53728
Ptnml(0-2): 68, 11432, 33785, 11812, 103
https://tests.stockfishchess.org/tests/view/626f730859e9c431e0b10b21

closes https://github.com/official-stockfish/Stockfish/pull/4008

bench: 6174823
2022-05-04 07:47:56 +02:00
candirufish a32d2086bc Use fail high count for LMR
Increase reduction if next ply has a lot of fail high else reset count to 0

Passed STC:
https://tests.stockfishchess.org/tests/view/626ea8299116b52aa83b71f6
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 144288 W: 38377 L: 37902 D: 68009
Ptnml(0-2): 565, 16298, 38054, 16551, 676

Passed LTC:
https://tests.stockfishchess.org/tests/view/626fa0fb79f761bab2e382f0
LLR: 2.98 (-2.94,2.94) <0.50,3.00>
Total: 74872 W: 20050 L: 19686 D: 35136
Ptnml(0-2): 51, 7541, 21893, 7895, 56

closes https://github.com/official-stockfish/Stockfish/pull/4006

bench: 7084802
2022-05-03 17:58:01 +02:00
Stefan Geschwentner 285a79eaa0 Simplify time management.
Replace the best move instability adjustment factor by a simpler version which doesn't have a dependency on the iteration depth.

STC:
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 30800 W: 8232 L: 8073 D: 14495
Ptnml(0-2): 101, 3309, 8444, 3422, 124
https://tests.stockfishchess.org/tests/view/6266c77bc5b924ba22908d30

LTC:
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 61664 W: 16375 L: 16272 D: 29017
Ptnml(0-2): 40, 5869, 18897, 6000, 26
https://tests.stockfishchess.org/tests/view/6266fc39b3d1812808915f23

closes https://github.com/official-stockfish/Stockfish/pull/3999

Bench: 7729968
2022-05-03 17:54:23 +02:00
candirufish e1f12aa4e6 Negative extension for ttMove that is less than alpha and value
in the context of singular extensions

Passed STC:
https://tests.stockfishchess.org/tests/view/626047e8b03f22647441ade0
LLR: 2.97 (-2.94,2.94) <0.00,2.50>
Total: 50296 W: 13410 L: 13108 D: 23778
Ptnml(0-2): 196, 5548, 13370, 5826, 208

Passed LTC:
https://tests.stockfishchess.org/tests/view/6260a513b03f22647441b970
LLR: 2.96 (-2.94,2.94) <0.50,3.00>
Total: 83896 W: 22433 L: 22054 D: 39409
Ptnml(0-2): 49, 8273, 24938, 8626, 62

closes https://github.com/official-stockfish/Stockfish/pull/3995

bench: 7729968
2022-04-22 08:17:22 +02:00
Michael Chaly e41f727f0f Simplify away best move count logic
the only place where it was used it was true with >99% probability so it seemed to not be doing much any more.

Passed STC:
https://tests.stockfishchess.org/tests/view/625f4778d00da81c22dd4c93
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 85152 W: 22487 L: 22406 D: 40259
Ptnml(0-2): 313, 9035, 23818, 9078, 332

Passed LTC:
https://tests.stockfishchess.org/tests/view/625ff1f1b03f22647441a215
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 66776 W: 17768 L: 17673 D: 31335
Ptnml(0-2): 46, 6200, 20792, 6313, 37

close https://github.com/official-stockfish/Stockfish/pull/3993

bench 7280798
2022-04-22 08:09:40 +02:00
Joost VandeVondele 6e0680efa0 Update default net to nn-d0b74ce1e5eb.nnue
train a net using training data with a
heavier weight on positions having 16 pieces on the board. More specifically,
with a relative weight of `i * (32-i)/(16 * 16)+1` (where i is the number of pieces on the board).

This is done with the trainer branch https://github.com/glinscott/nnue-pytorch/pull/173

The command used is:
```
python train.py $datafile $datafile $restarttype $restartfile --gpus 1 --threads 4 --num-workers 12 --random-fen-skipping=3 --batch-size 16384 --progress_bar_refresh_rate 300 --smart-fen-skipping --features=HalfKAv2_hm^   --lambda=1.00  --max_epochs=$epochs --seed $RANDOM --default_root_dir exp/run_$i
```
The datafile is T60T70wIsRightFarseerT60T74T75T76.binpack, the restart is from the master net.

passed STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 22728 W: 6197 L: 5945 D: 10586
Ptnml(0-2): 105, 2453, 6001, 2695, 110
https://tests.stockfishchess.org/tests/view/625cf944ff677a888877cd90

passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 35664 W: 9535 L: 9264 D: 16865
Ptnml(0-2): 30, 3524, 10455, 3791, 32
https://tests.stockfishchess.org/tests/view/625d3c32ff677a888877d7ca

closes https://github.com/official-stockfish/Stockfish/pull/3989

Bench: 7269563
2022-04-19 19:59:04 +02:00
Joost VandeVondele c4db7fd1f9 Restore development version
No functional change.
2022-04-18 23:05:24 +02:00
Joost VandeVondele e6e324eb28 Stockfish 15
Official release version of Stockfish 15

Bench: 8129754

---

A new major release of Stockfish is now available at https://stockfishchess.org

Stockfish 15 continues to push the boundaries of chess, providing unrivalled
analysis and playing strength. In our testing, Stockfish 15 is ahead of
Stockfish 14 by 36 Elo points and wins nine times more game pairs than it
loses[1].

Improvements to the engine have made it possible for Stockfish to end up
victorious in tournaments at all sorts of time controls ranging from bullet to
classical and even at Fischer random chess[2]. At CCC, Stockfish won all of
the latest tournaments: CCC 16 Bullet, Blitz and Rapid, CCC 960 championship,
and the CCC 17 Rapid. At TCEC, Stockfish won the Season 21, Cup 9, FRC 4 and
in the current Season 22 superfinal, at the time of writing, has won 16 game
pairs and not yet lost a single one.

This progress is the result of a dedicated team of developers that comes up
with new ideas and improvements. For Stockfish 15, we tested nearly 13000
different changes and retained the best 200. These include the fourth
generation of our NNUE network architecture, as well as various search
improvements. To perform these tests, contributors provide CPU time for
testing, and in the last year, they have collectively played roughly a
billion chess games. In the last few years, our distributed testing
framework, Fishtest, has been operated superbly and has been developed and
improved extensively. This work by Pasquale Pigazzini, Tom Vijlbrief, Michel
Van den Bergh, and various other developers[3] is an essential part of the
success of the Stockfish project.

Indeed, the Stockfish project builds on a thriving community of enthusiasts
to offer a free and open-source chess engine that is robust, widely
available, and very strong. We invite our chess fans to join the Fishtest
testing framework and programmers to contribute to the project[4].

The Stockfish team

[1] https://tests.stockfishchess.org/tests/view/625d156dff677a888877d1be
[2] https://en.wikipedia.org/wiki/Stockfish_(chess)#Competition_results
[3] https://github.com/glinscott/fishtest/blob/master/AUTHORS
[4] https://stockfishchess.org/get-involved/
2022-04-18 22:03:20 +02:00
KJE-98 df2f7e7527 Decrease LMR at PV nodes with low depth.
This patch lessens the Late Move Reduction at PV nodes with low depth. Previously the affect of depth on LMR was independant of nodeType. The idea behind this patch is that at PV nodes, LMR at low depth is will miss out on potential alpha-raising moves.

Passed STC:
https://tests.stockfishchess.org/tests/view/625aa867d3367522c4b8965c
LLR: 2.93 (-2.94,2.94) <0.00,2.50>
Total: 19360 W: 5252 L: 5006 D: 9102
Ptnml(0-2): 79, 2113, 5069, 2321, 98

Passed LTC:
https://tests.stockfishchess.org/tests/view/625ae844d3367522c4b8a009
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 39264 W: 10636 L: 10357 D: 18271
Ptnml(0-2): 18, 3928, 11473, 4183, 30

closes https://github.com/official-stockfish/Stockfish/pull/3985

bench: 8129754
2022-04-17 21:38:05 +02:00
FauziAkram c25d4c4887 Tuning classical and NNUE scaling terms
changes to parameters in both classical and NNUE scaling, following up from an earlier successful #3958

passed STC:
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 23936 W: 6490 L: 6234 D: 11212
Ptnml(0-2): 107, 2610, 6306, 2810, 135
https://tests.stockfishchess.org/tests/view/625820aa33c40bb9d964e6ae

passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 50376 W: 13629 L: 13327 D: 23420
Ptnml(0-2): 20, 4979, 14920, 5217, 52
https://tests.stockfishchess.org/tests/view/62584592c1d7f5008a33a4d1

closes https://github.com/official-stockfish/Stockfish/pull/3982

Bench: 6964954
2022-04-16 08:41:51 +02:00
Joost VandeVondele c3b67faf98 Update WDL model for current SF
This updates the WDL model based on the LTC statistics for the last month (8M games).

for old results see:
https://github.com/official-stockfish/Stockfish/pull/3582
https://github.com/official-stockfish/Stockfish/pull/2778

the model changed a bit from the past, some images to follow in the PR

closes https://github.com/official-stockfish/Stockfish/pull/3981

No functional change.
2022-04-16 08:36:37 +02:00
Joost VandeVondele 319af5cf0a Update CPU contributors
closes https://github.com/official-stockfish/Stockfish/pull/3979

No functional change
2022-04-16 08:35:31 +02:00
Topologist 19a90b45bc Use NNUE in low piece endgames close to the root.
This patch enforces that NNUE evaluation is used for endgame positions at shallow depth (depth <= 9).
Classic evaluation will still be used for high imbalance positions when the depth is high or there are many pieces.

Passed STC:
https://tests.stockfishchess.org/tests/view/624c193b3a8a6ac93892dc27
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 255840 W: 68024 L: 67362 D: 120454
Ptnml(0-2): 1074, 27089, 70926, 27763, 1068

Passed LTC:
https://tests.stockfishchess.org/tests/view/624e8675e9e7821808467f77
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 67088 W: 17784 L: 17454 D: 31850
Ptnml(0-2): 45, 6209, 20715, 6521, 54

closes https://github.com/official-stockfish/Stockfish/pull/3978

bench: 6602222
2022-04-12 17:43:50 +02:00
mstembera 9f6bcb38c0 Minor cleanups
simplify and relocate to position.cpp some of the recent threat calculations used in the movepicker.

passed STC:
https://tests.stockfishchess.org/tests/view/62468c301f682ea45ce3b3b9
LLR: 2.96 (-2.94,2.94) <-2.25,0.25>
Total: 76544 W: 20247 L: 20152 D: 36145
Ptnml(0-2): 327, 8113, 21317, 8168, 347

closes https://github.com/official-stockfish/Stockfish/pull/3972

No functional change
2022-04-01 10:55:11 +02:00
Topologist 471d93063a Play more positional in endgames
This patch chooses the delta value (which skews the nnue evaluation between positional and materialistic)
depending on the material: If the material is low, delta will be higher and the evaluation is shifted
to the positional value. If the material is high, the evaluation will be shifted to the psqt value.
I don't think slightly negative values of delta should be a concern.

Passed STC:
https://tests.stockfishchess.org/tests/view/62418513b3b383e86185766f
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 28808 W: 7832 L: 7564 D: 13412
Ptnml(0-2): 147, 3186, 7505, 3384, 182

Passed LTC:
https://tests.stockfishchess.org/tests/view/62419137b3b383e861857842
LLR: 2.96 (-2.94,2.94) <0.50,3.00>
Total: 58632 W: 15776 L: 15450 D: 27406
Ptnml(0-2): 42, 5889, 17149, 6173, 63

closes https://github.com/official-stockfish/Stockfish/pull/3971

Bench: 7588855
2022-03-28 22:43:52 +02:00
Michael Chaly 08e0f52b77 In movepicker increase priority for moves that evade a capture
This idea is a mix of koivisto idea of threat history and heuristic that
was simplified some time ago in LMR - decreasing reduction for moves that evade a capture.
Instead of doing so in LMR this patch does it in movepicker - to do this it
calculates squares that are attacked by different piece types and pieces that are located
on this squares and boosts up weight of moves that make this pieces land on a square that is not under threat.
Boost is greater for pieces with bigger material values.
Special thanks to koivisto and seer authors for explaining me ideas behind threat history.

Passed STC:
https://tests.stockfishchess.org/tests/view/62406e473b32264b9aa1478b
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 19816 W: 5320 L: 5072 D: 9424
Ptnml(0-2): 86, 2165, 5172, 2385, 100

Passed LTC:
https://tests.stockfishchess.org/tests/view/62407f2e3b32264b9aa149c8
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 51200 W: 13805 L: 13500 D: 23895
Ptnml(0-2): 44, 5023, 15164, 5322, 47

closes https://github.com/official-stockfish/Stockfish/pull/3970

bench 7736491
2022-03-28 22:37:09 +02:00
Giacomo Lorenzetti 910cf8b218 Remove pos.capture_or_promotion()
This patch replaces `pos.capture_or_promotion()` with `pos.capture()`
and comes after a few attempts with elo-gaining bounds, two of which
failed yellow at LTC
(https://tests.stockfishchess.org/tests/view/622f8f0cc9e950cbfc237024
and
https://tests.stockfishchess.org/tests/view/62319a8bb3b498ba71a6b2dc).

Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/623aff7eea447151c74828d3
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 246864 W: 65462 L: 65618 D: 115784
Ptnml(0-2): 1201, 28116, 65001, 27866, 1248

Passed non-regression LTC:
https://tests.stockfishchess.org/tests/view/623c1fdcea447151c7484fb0
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 30120 W: 8125 L: 7978 D: 14017
Ptnml(0-2): 22, 2993, 8881, 3144, 20

closes https://github.com/official-stockfish/Stockfish/pull/3968

Bench: 6847732
2022-03-25 20:14:00 +01:00
Stefan Geschwentner e31f97e3ba Remove ttPv tree shrinking.
Via the ttPv flag an implicit tree of current and former PV nodes is maintained. In addition this tree is grown or shrinked at the leafs dependant on the search results. But now the shrinking step has been removed.

As the frequency of ttPv nodes decreases with depth the shown scaling behavior (STC barely passed but LTC scales well) of the tests was expected.

STC:
LLR: 2.93 (-2.94,2.94) <-2.25,0.25>
Total: 270408 W: 71593 L: 71785 D: 127030
Ptnml(0-2): 1339, 31024, 70630, 30912, 1299
https://tests.stockfishchess.org/tests/view/622fbf9dc9e950cbfc2376d6

LTC:
LLR: 2.96 (-2.94,2.94) <-2.25,0.25>
Total: 34368 W: 9135 L: 8992 D: 16241
Ptnml(0-2): 28, 3423, 10135, 3574, 24
https://tests.stockfishchess.org/tests/view/62305257c9e950cbfc238964

closes https://github.com/official-stockfish/Stockfish/pull/3963

Bench: 7044203
2022-03-19 13:40:35 +01:00
mstembera f3a2296e59 Small cleanups (2)
- fix a small compile error under MSVC
- improve sigmoid comment and assert
- fix formatting in README.md

closes https://github.com/official-stockfish/Stockfish/pull/3960

No functional change
2022-03-13 08:17:02 +01:00
Giacomo Lorenzetti 004ea2c25e Small cleanups
Delete cast to int in movepick.
update AUTHORS.
adjust assert in sigmoid.
fix spelling mistakes in README

closes https://github.com/official-stockfish/Stockfish/pull/3922
closes https://github.com/official-stockfish/Stockfish/pull/3948
closes https://github.com/official-stockfish/Stockfish/pull/3942

No functional change
2022-03-12 09:38:34 +01:00
FauziAkram 45f2416db4 Improvements in Evaluation
adjust parameters in classical evaluation and NNUE scaling.

STC:
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 37104 W: 9983 L: 9701 D: 17420
Ptnml(0-2): 154, 4187, 9651, 4343, 217
https://tests.stockfishchess.org/tests/view/6228cb13a9d47c8160e885ba

LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 266792 W: 71101 L: 70295 D: 125396
Ptnml(0-2): 214, 26928, 78353, 27640, 261
https://tests.stockfishchess.org/tests/view/6228d3c4a9d47c8160e887b0

closes https://github.com/official-stockfish/Stockfish/pull/3958

Bench: 6739741
2022-03-12 09:25:58 +01:00
Michael Chaly eae0f8dd06 Decrease reductions in Lmr for some Pv nodes
This patch makes us reduce less in Lmr at pv nodes in case of static eval being far away from static evaluation of position.
Idea is that if it's the case then probably position is pretty complex so we can't be sure about how reliable LMR is so we need to reduce less.

Passed STC:
https://tests.stockfishchess.org/tests/view/6226276aa9d47c8160e81220
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 262696 W: 69944 L: 69239 D: 123513
Ptnml(0-2): 1399, 29702, 68436, 30417, 1394

Passed LTC:
https://tests.stockfishchess.org/tests/view/6226b002a9d47c8160e82b91
LLR: 2.95 (-2.94,2.94) <0.50,3.00>
Total: 64008 W: 17320 L: 16982 D: 29706
Ptnml(0-2): 60, 6378, 18811, 6674, 81

closes https://github.com/official-stockfish/Stockfish/pull/3957

bench 6678390
2022-03-08 20:19:42 +01:00
Ben Chaney 270a0e737f Generalize the feature transform to use vec_t macros
This commit generalizes the feature transform to use vec_t macros
that are architecture defined instead of using a seperate code path for each one.

It should make some old architectures (MMX, including improvements by Fanael) faster
and make further such improvements easier in the future.

Includes some corrections to CI for mingw.

closes https://github.com/official-stockfish/Stockfish/pull/3955
closes https://github.com/official-stockfish/Stockfish/pull/3928

No functional change
2022-03-02 23:39:08 +01:00
Giacomo Lorenzetti 4ac7d726ec Sort captures
This patch (partially) sort captures in analogy to quiet moves. All
three movepickers are affected, hence `depth` is added as an argument in
probcut's.

Passed STC:
https://tests.stockfishchess.org/tests/view/621a4576da649bba32ef6fd4
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 103848 W: 27884 L: 27473 D: 48491
Ptnml(0-2): 587, 11691, 26974, 12068, 604

Passed LTC:
https://tests.stockfishchess.org/tests/view/621aaa5bda649bba32ef7c2d
LLR: 2.96 (-2.94,2.94) <0.50,3.00>
Total: 212032 W: 56420 L: 55739 D: 99873
Ptnml(0-2): 198, 21310, 62348, 21933, 227

closes https://github.com/official-stockfish/Stockfish/pull/3952

Bench: 6833580
2022-03-01 17:51:37 +01:00
Tomasz Sobczyk 174b038bf3 Use dynamic allocation for evaluation scratch TLS buffer.
fixes #3946 an issue related with the toolchain as found in xcode 12 on macOS,
related to previous commit 5f781d36.

closes https://github.com/official-stockfish/Stockfish/pull/3950

No functional change
2022-03-01 17:51:02 +01:00
mstembera 5f781d366e Clean up and simplify some nnue code.
Remove some unnecessary code and it's execution during inference. Also the change on line 49 in nnue_architecture.h results in a more efficient SIMD code path through ClippedReLU::propagate().

passed STC:
https://tests.stockfishchess.org/tests/view/6217d3bfda649bba32ef25d5
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 12056 W: 3281 L: 3092 D: 5683
Ptnml(0-2): 55, 1213, 3312, 1384, 64

passed STC SMP:
https://tests.stockfishchess.org/tests/view/6217f344da649bba32ef295e
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 27376 W: 7295 L: 7137 D: 12944
Ptnml(0-2): 52, 2859, 7715, 3003, 59

closes https://github.com/official-stockfish/Stockfish/pull/3944

No functional change

bench: 6820724
2022-02-25 08:37:57 +01:00
Michael Chaly 27139dedac Adjust usage of LMR for 2nd move in move ordering
Current master prohibits usage of LMR for 2nd move at rootNode. This patch also disables LMR for 2nd move not only at rootNode but also at first PvNode that is a reply to rootNode.

passed STC:
https://tests.stockfishchess.org/tests/view/620e8c9026f5b17ec885143a
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 54096 W: 14305 L: 13996 D: 25795
Ptnml(0-2): 209, 6075, 14192, 6342, 230

passed LTC:
https://tests.stockfishchess.org/tests/view/620eb327b1792e8985f81fb8
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 110864 W: 29602 L: 29156 D: 52106
Ptnml(0-2): 112, 11147, 32455, 11619, 99

closes https://github.com/official-stockfish/Stockfish/pull/3940

bench 6820724
2022-02-20 23:01:22 +01:00
Joost VandeVondele abef3e86f4 Fix clang warning on unused variable
mark variable as used.

fixes https://github.com/official-stockfish/Stockfish/issues/3900
closes https://github.com/official-stockfish/Stockfish/pull/3941

No functional change
2022-02-20 22:59:19 +01:00
ppigazzini 2da1d1bf57 Add ARM NDK to Github Actions matrix
- set the variable only for the required tests to keep simple the yml file
- use NDK 21.x until will be fixed the Stockfish static build problem
  with NDK 23.x
- set the test for armv7, armv7-neon, armv8 builds:
  - use armv7a-linux-androideabi21-clang++ compiler for armv7 armv7-neon
  - enforce a static build
  - silence the Warning for the unused compilation flag "-pie" with
    the static build, otherwise the Github workflow stops
  - use qemu to bench the build and get the signature

Many thanks to @pschneider1968 that made all the hard work with NDK :)

closes https://github.com/official-stockfish/Stockfish/pull/3924

No functional change
2022-02-20 22:56:11 +01:00
Michael Chaly 84b1940fca Tune search at very long time control
This patch is a result of tuning done by user @candirufish after 150k games.

Since the tuned values were really interesting and touched heuristics
that are known for their non-linear scaling I decided to run limited
games LTC match, even if the STC test was really bad (which was expected).
After seeing the results of the LTC match, I also run a VLTC (very long
time control) SPRTtest, which passed.

The main difference is in extensions: this patch allows much more
singular/double extensions, both in terms of allowing them at lower
depths and with lesser margins.

Failed STC:
https://tests.stockfishchess.org/tests/view/620d66643ec80158c0cd3b46
LLR: -2.94 (-2.94,2.94) <0.00,2.50>
Total: 4968 W: 1194 L: 1398 D: 2376
Ptnml(0-2): 47, 633, 1294, 497, 13

Performed well at LTC in a fixed-length match:
https://tests.stockfishchess.org/tests/view/620d66823ec80158c0cd3b4a
ELO: 3.36 +-1.8 (95%) LOS: 100.0%
Total: 30000 W: 7966 L: 7676 D: 14358
Ptnml(0-2): 36, 2936, 8755, 3248, 25

Passed VLTC SPRT test:
https://tests.stockfishchess.org/tests/view/620da11a26f5b17ec884f939
LLR: 2.96 (-2.94,2.94) <0.50,3.00>
Total: 4400 W: 1326 L: 1127 D: 1947
Ptnml(0-2): 13, 309, 1348, 526, 4

closes https://github.com/official-stockfish/Stockfish/pull/3937

Bench: 6318903
2022-02-17 20:45:21 +01:00
Michael Chaly 3ec6e1d245 Big search tuning (version 2)
One more tuning - this one includes newly introduced heuristics and
some other parameters that were not included in previous one. Result
of 400k games at 20+0.2 "as is". Tuning is continuing since there is
probably a lot more elo to gain.

STC:
https://tests.stockfishchess.org/tests/view/620782edd71106ed12a497d1
LLR: 2.99 (-2.94,2.94) <0.00,2.50>
Total: 38504 W: 10260 L: 9978 D: 18266
Ptnml(0-2): 142, 4249, 10230, 4447, 184

LTC:
https://tests.stockfishchess.org/tests/view/6207a243d71106ed12a49d07
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 25176 W: 6793 L: 6546 D: 11837
Ptnml(0-2): 20, 2472, 7360, 2713, 23

closes https://github.com/official-stockfish/Stockfish/pull/3931

Bench: 4784796
2022-02-13 01:05:27 +01:00
Tomasz Sobczyk cb9c2594fc Update architecture to "SFNNv4". Update network to nn-6877cd24400e.nnue.
Architecture:

The diagram of the "SFNNv4" architecture:
https://user-images.githubusercontent.com/8037982/153455685-cbe3a038-e158-4481-844d-9d5fccf5c33a.png

The most important architectural changes are the following:

* 1024x2 [activated] neurons are pairwise, elementwise multiplied (not quite pairwise due to implementation details, see diagram), which introduces a non-linearity that exhibits similar benefits to previously tested sigmoid activation (quantmoid4), while being slightly faster.
* The following layer has therefore 2x less inputs, which we compensate by having 2 more outputs. It is possible that reducing the number of outputs might be beneficial (as we had it as low as 8 before). The layer is now 1024->16.
* The 16 outputs are split into 15 and 1. The 1-wide output is added to the network output (after some necessary scaling due to quantization differences). The 15-wide is activated and follows the usual path through a set of linear layers. The additional 1-wide output is at least neutral, but has shown a slightly positive trend in training compared to networks without it (all 16 outputs through the usual path), and allows possibly an additional stage of lazy evaluation to be introduced in the future.

Additionally, the inference code was rewritten and no longer uses a recursive implementation. This was necessitated by the splitting of the 16-wide intermediate result into two, which was impossible to do with the old implementation with ugly hacks. This is hopefully overall for the better.

First session:

The first session was training a network from scratch (random initialization). The exact trainer used was slightly different (older) from the one used in the second session, but it should not have a measurable effect. The purpose of this session is to establish a strong network base for the second session. Small deviations in strength do not harm the learnability in the second session.

The training was done using the following command:

python3 train.py \
    /home/sopel/nnue/nnue-pytorch-training/data/nodes5000pv2_UHO.binpack \
    /home/sopel/nnue/nnue-pytorch-training/data/nodes5000pv2_UHO.binpack \
    --gpus "$3," \
    --threads 4 \
    --num-workers 4 \
    --batch-size 16384 \
    --progress_bar_refresh_rate 20 \
    --random-fen-skipping 3 \
    --features=HalfKAv2_hm^ \
    --lambda=1.0 \
    --gamma=0.992 \
    --lr=8.75e-4 \
    --max_epochs=400 \
    --default_root_dir ../nnue-pytorch-training/experiment_$1/run_$2

Every 20th net was saved and its playing strength measured against some baseline at 25k nodes per move with pure NNUE evaluation (modified binary). The exact setup is not important as long as it's consistent. The purpose is to sift good candidates from bad ones.

The dataset can be found https://drive.google.com/file/d/1UQdZN_LWQ265spwTBwDKo0t1WjSJKvWY/view

Second session:

The second training session was done starting from the best network (as determined by strength testing) from the first session. It is important that it's resumed from a .pt model and NOT a .ckpt model. The conversion can be performed directly using serialize.py

The LR schedule was modified to use gamma=0.995 instead of gamma=0.992 and LR=4.375e-4 instead of LR=8.75e-4 to flatten the LR curve and allow for longer training. The training was then running for 800 epochs instead of 400 (though it's possibly mostly noise after around epoch 600).

The training was done using the following command:

The training was done using the following command:

python3 train.py \
        /data/sopel/nnue/nnue-pytorch-training/data/T60T70wIsRightFarseerT60T74T75T76.binpack \
        /data/sopel/nnue/nnue-pytorch-training/data/T60T70wIsRightFarseerT60T74T75T76.binpack \
        --gpus "$3," \
        --threads 4 \
        --num-workers 4 \
        --batch-size 16384 \
        --progress_bar_refresh_rate 20 \
        --random-fen-skipping 3 \
        --features=HalfKAv2_hm^ \
        --lambda=1.0 \
        --gamma=0.995 \
        --lr=4.375e-4 \
        --max_epochs=800 \
        --resume-from-model /data/sopel/nnue/nnue-pytorch-training/data/exp295/nn-epoch399.pt \
        --default_root_dir ../nnue-pytorch-training/experiment_$1/run_$run_id

In particular note that we now use lambda=1.0 instead of lambda=0.8 (previous nets), because tests show that WDL-skipping introduced by vondele performs better with lambda=1.0. Nets were being saved every 20th epoch. In total 16 runs were made with these settings and the best nets chosen according to playing strength at 25k nodes per move with pure NNUE evaluation - these are the 4 nets that have been put on fishtest.

The dataset can be found either at ftp://ftp.chessdb.cn/pub/sopel/data_sf/T60T70wIsRightFarseerT60T74T75T76.binpack in its entirety (download might be painfully slow because hosted in China) or can be assembled in the following way:

Get the https://github.com/official-stockfish/Stockfish/blob/5640ad48ae5881223b868362c1cbeb042947f7b4/script/interleave_binpacks.py script.
Download T60T70wIsRightFarseer.binpack https://drive.google.com/file/d/1_sQoWBl31WAxNXma2v45004CIVltytP8/view
Download farseerT74.binpack http://trainingdata.farseer.org/T74-May13-End.7z
Download farseerT75.binpack http://trainingdata.farseer.org/T75-June3rd-End.7z
Download farseerT76.binpack http://trainingdata.farseer.org/T76-Nov10th-End.7z
Run python3 interleave_binpacks.py T60T70wIsRightFarseer.binpack farseerT74.binpack farseerT75.binpack farseerT76.binpack T60T70wIsRightFarseerT60T74T75T76.binpack

Tests:

STC: https://tests.stockfishchess.org/tests/view/6203fb85d71106ed12a407b7
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 16952 W: 4775 L: 4521 D: 7656
Ptnml(0-2): 133, 1818, 4318, 2076, 131

LTC: https://tests.stockfishchess.org/tests/view/62041e68d71106ed12a40e85
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 14944 W: 4138 L: 3907 D: 6899
Ptnml(0-2): 21, 1499, 4202, 1728, 22

closes https://github.com/official-stockfish/Stockfish/pull/3927

Bench: 4919707
2022-02-10 19:54:31 +01:00
Michael Chaly b0b31558a2 Big search tuning
Most credits for this patch should go to @candirufish.
Based on his big search tuning (1M games at 20+0.1s)

https://tests.stockfishchess.org/tests/view/61fc7a6ed508ec6a1c9f4b7d

with some hand polishing on top of it, which includes :

a) correcting trend sigmoid - for some reason original tuning resulted in it being negative. This heuristic was proven to be worth some elo for years so reversing it sign is probably some random artefact;
b) remove changes to continuation history based pruning - this heuristic historically was really good at providing green STCs and then failing at LTC miserably if we tried to make it more strict, original tuning was done at short time control and thus it became more strict - which doesn't scale to longer time controls;
c) remove changes to improvement - not really indended :).

passed STC
https://tests.stockfishchess.org/tests/view/6203526e88ae2c84271c2ee2
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 16840 W: 4604 L: 4363 D: 7873
Ptnml(0-2): 82, 1780, 4449, 2033, 76

passed LTC
https://tests.stockfishchess.org/tests/view/620376e888ae2c84271c35d4
LLR: 2.96 (-2.94,2.94) <0.50,3.00>
Total: 17232 W: 4771 L: 4542 D: 7919
Ptnml(0-2): 14, 1655, 5048, 1886, 13

closes https://github.com/official-stockfish/Stockfish/pull/3926

bench 5030992
2022-02-09 17:17:00 +01:00
Michael Chaly 08ac4e9db5 Do less depth reduction in null move pruning for complex positions
This patch makes us reduce less depth in null move pruning if complexity is high enough.
Thus, null move pruning now depends in two distinct ways on complexity,
while being the only search heuristic that exploits complexity so far.

passed STC
https://tests.stockfishchess.org/tests/view/61fde60fd508ec6a1c9f7754
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 170000 W: 45555 L: 45027 D: 79418
Ptnml(0-2): 760, 19352, 44359, 19658, 871

passed LTC
https://tests.stockfishchess.org/tests/view/61fe91febf46cb834cbd5c90
LLR: 2.96 (-2.94,2.94) <0.50,3.00>
Total: 145272 W: 39182 L: 38651 D: 67439
Ptnml(0-2): 127, 14864, 42157, 15327, 161

closes https://github.com/official-stockfish/Stockfish/pull/3923

bench 4461945
2022-02-07 17:30:35 +01:00
Michael Chaly 4d3950c6eb Reintroduce razoring
Razoring was simplified away some years ago, this patch reintroduces it in a slightly different form.
Now for low depths if eval is far below alpha we check if qsearch can push it above alpha - and if it can't we return a fail low.

passed STC
https://tests.stockfishchess.org/tests/view/61fbf968d508ec6a1c9f3274
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 226120 W: 61106 L: 60472 D: 104542
Ptnml(0-2): 1118, 25592, 59080, 26078, 1192

passed LTC
https://tests.stockfishchess.org/tests/view/61fcc569d508ec6a1c9f5617
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 113128 W: 30851 L: 30397 D: 51880
Ptnml(0-2): 114, 11483, 32926, 11917, 124

closes https://github.com/official-stockfish/Stockfish/pull/3921

bench 4684080
2022-02-05 07:40:21 +01:00
Michael Chaly 95d7369e54 Introduce movecount pruning for quiet check evasions in qsearch
Idea of this patch is that we usually don't consider quiet check evasions as "good" ones and prefer capture based ones instead. So it makes sense to think that if in qsearch 2 quiet check evasions failed to produce anything good 3rd and further ones wouldn't be good either.

passed STC
https://tests.stockfishchess.org/tests/view/61fc1b1ed508ec6a1c9f397c
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 58800 W: 15947 L: 15626 D: 27227
Ptnml(0-2): 273, 6568, 15462, 6759, 338

passed LTC
https://tests.stockfishchess.org/tests/view/61fcc56dd508ec6a1c9f5619
LLR: 2.95 (-2.94,2.94) <0.50,3.00>
Total: 89544 W: 24208 L: 23810 D: 41526
Ptnml(0-2): 81, 9038, 26134, 9440, 79

closes https://github.com/official-stockfish/Stockfish/pull/3920

bench 4830082
2022-02-05 07:38:30 +01:00
ppigazzini e178a09c47 Drop sse from target "x86-32"
have maximal compatibility on legacy target arch, now supporting AMD Athlon

The old behavior can anyway be selected by the user if needed, for example

make -j profile-build ARCH=x86-32 sse=yes

fixes #3904
closes https://github.com/official-stockfish/Stockfish/pull/3918

No functional change
2022-02-05 07:33:34 +01:00
Michael Chaly 50200de5af Cleanup and update CPU contributors
closes https://github.com/official-stockfish/Stockfish/pull/3917

No functional change
2022-02-05 07:30:09 +01:00
Michael Chaly 90d051952f Do stats updates after LMR for captures
Since captures that are in LMR use continuation histories of corresponding quiet moves it makes sense to update this histories if this capture passes LMR by analogy to existing logic for quiet moves.

Passed STC
https://tests.stockfishchess.org/tests/view/61f367eef7fba9f1a4f1318b
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 208464 W: 56006 L: 55407 D: 97051
Ptnml(0-2): 964, 23588, 54655, 23935, 1090

Passed LTC
https://tests.stockfishchess.org/tests/view/61f41e34f7fba9f1a4f15241
LLR: 2.96 (-2.94,2.94) <0.50,3.00>
Total: 69144 W: 18793 L: 18441 D: 31910
Ptnml(0-2): 65, 6982, 20142, 7302, 81

closes https://github.com/official-stockfish/Stockfish/pull/3910

bench 4637392
2022-01-29 08:58:12 +01:00
Michael Chaly 8b4afcf8f7 Scale child node futility pruning with previous move history.
Idea is to do more futility pruning if previous move has bad histories and less if it has good histories.

passed STC
https://tests.stockfishchess.org/tests/view/61e3757fbabab931824e0db7
LLR: 2.96 (-2.94,2.94) <0.00,2.50>
Total: 156816 W: 42282 L: 41777 D: 72757
Ptnml(0-2): 737, 17775, 40913, 18212, 771

passed LTC
https://tests.stockfishchess.org/tests/view/61e43496928632f7813a5535
LLR: 2.95 (-2.94,2.94) <0.50,3.00>
Total: 349968 W: 94612 L: 93604 D: 161752
Ptnml(0-2): 300, 35934, 101550, 36858, 342

closes https://github.com/official-stockfish/Stockfish/pull/3903

bench 4720954
2022-01-25 07:27:52 +01:00
pschneider1968 bddd38c45e Fix Makefile for Android NDK cross-compile
For cross-compiling to Android on windows, the Makefile needs some tweaks.

Tested with Android NDK 23.1.7779620 and 21.4.7075529, using
Windows 10 with clean MSYS2 environment (i.e. no MINGW/GCC/Clang
toolchain in PATH) and Fedora 35, with build target:
build ARCH=armv8 COMP=ndk

The resulting binary runs fine inside Droidfish on my Samsung
Galaxy Note20 Ultra and Samsung Galaxy Tab S7+

Other builds tested to exclude regressions: MINGW64/Clang64 build
on Windows; MINGW64 cross build, native Clang and GCC builds on Fedora.

wiki docs https://github.com/glinscott/fishtest/wiki/Cross-compiling-Stockfish-for-Android-on-Windows-and-Linux

closes https://github.com/official-stockfish/Stockfish/pull/3901

No functional change
2022-01-25 07:27:23 +01:00
J. Oster 9083050be6 Simplify limiting extensions.
Replace the current method for limiting extensions to avoid search getting stuck
with a much simpler method.

the test position in https://github.com/official-stockfish/Stockfish/commit/73018a03375b4b72ee482eb5a4a2152d7e4f0aac
can still be searched without stuck search.

fixes #3815 where the search now makes progress with rootDepth

shows robust behavior in a d10 search for 1M positions.

passed STC
https://tests.stockfishchess.org/tests/view/61e303e3babab931824dfb18
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 57568 W: 15449 L: 15327 D: 26792
Ptnml(0-2): 243, 6211, 15779, 6283, 268

passed LTC
https://tests.stockfishchess.org/tests/view/61e3586cbabab931824e091c
LLR: 2.96 (-2.94,2.94) <-2.25,0.25>
Total: 128200 W: 34632 L: 34613 D: 58955
Ptnml(0-2): 124, 12559, 38710, 12588, 119

closes https://github.com/official-stockfish/Stockfish/pull/3899

Bench: 4550528
2022-01-22 10:48:24 +01:00
Joost VandeVondele 77cf5704b6 Revert -flto=auto on mingw
causes issues on some installations (glinscott/fishtest#1255).

closes https://github.com/official-stockfish/Stockfish/pull/3898

No functional change
2022-01-20 18:34:16 +01:00
ppigazzini 67062637f4 Improve Makefile for Windows native builds
A Windows Native Build (WNB) can be done:
 - on Windows, using a recent mingw-w64 g++/clang compiler
   distributed by msys2, cygwin and others
 - on Linux, using mingw-w64 g++ to cross compile

Improvements:
 - check for a WNB in a proper way and set a variable to simplify the code
 - set the proper EXE for a WNB
 - use the proper name for the mingw-w64 clang compiler
 - use the static linking for a WNB
 - use wine to make a PGO cross compile on Linux (also with Intel SDE)
 - enable the LTO build for mingw-w64 g++ compiler
 - set `lto=auto` to use the make's job server, if available, or otherwise
   to fall back to autodetection of the number of CPU threads
 - clean up all the temporary LTO files saved in the local directory

Tested on:
 - msys2 MINGW64 (g++), UCRT64 (g++), MINGW32 (g++), CLANG64 (clang)
   environments
 - cygwin mingw-w64 g++
 - Ubuntu 18.04 & 21.10 mingw-w64 PGO cross compile (also with Intel SDE)

closes #3891

No functional change
2022-01-19 22:26:20 +01:00
ppigazzini 48bf1a386f Add msys2 Clang x86_64 to GitHub Action matrix
Also use Windows Server 2022 virtual environment for msys2 builds.

closes https://github.com/official-stockfish/Stockfish/pull/3893

No functional change
2022-01-19 19:21:10 +01:00
Rui Coelho 2b0372319d Use average complexity for time management
This patch is a variant of the idea by locutus2 (https://tests.stockfishchess.org/tests/view/61e1f24cb1f9959fe5d88168) to adjust the total time depending on the average complexity of the position.

Passed STC
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 39664 W: 10765 L: 10487 D: 18412
Ptnml(0-2): 162, 4213, 10837, 4425, 195
https://tests.stockfishchess.org/tests/view/61e2df8b65a644da8c9ea708

Passed LTC
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 127656 W: 34505 L: 34028 D: 59123
Ptnml(0-2): 116, 12435, 38261, 12888, 128
https://tests.stockfishchess.org/tests/view/61e31db5babab931824dff5e

closes https://github.com/official-stockfish/Stockfish/pull/3892

Bench: 4464962
2022-01-17 19:48:23 +01:00
proukornew d11101e4c6 Improve logic on mingw
There is no need to point g++, if we explicitly choose mingw.

Now for cygwin:

make COMP=mingw ARCH=x86-64-modern build

closes https://github.com/official-stockfish/Stockfish/pull/3860

No functional change
2022-01-17 19:47:32 +01:00
Rui Coelho 7678d63cf2 Use complexity in search
This patch uses the complexity measure (from #3875) as a heuristic for null move pruning.
Hopefully, there may be room to use it in other pruning techniques.
I would like to thank vondele and locutus2 for the feedback and suggestions during testing.

Passed STC
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 35000 W: 9624 L: 9347 D: 16029
Ptnml(0-2): 156, 3894, 9137, 4143, 170
https://tests.stockfishchess.org/tests/view/61dda784c65bf87d6c45ab80

Passed LTC
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 230776 W: 64227 L: 63454 D: 103095
Ptnml(0-2): 1082, 23100, 66380, 23615, 1211
https://tests.stockfishchess.org/tests/view/61ddd0cf3ddbc32543e72c2b

Closes https://github.com/official-stockfish/Stockfish/pull/3890

Bench: 4464962
2022-01-13 22:25:01 +01:00
pschneider1968 c5d45d3220 Fix Makefile for compilation with clang on Windows
use static compilation and
added exclusion of -latomic for Clang/MSYS2 as per ppigazzini's suggestion

fixes #3872

closes https://github.com/official-stockfish/Stockfish/pull/3873

No functional change
2022-01-13 22:17:27 +01:00
Michael Chaly 44b1ba89a9 Adjust pruning constants
This patch is a modification of original tuning done by vondele that failed yellow.
Value differences are divided by 2.

Passed STC
https://tests.stockfishchess.org/tests/view/61d918239fea7913d9c64cdf
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 98968 W: 26248 L: 25858 D: 46862
Ptnml(0-2): 392, 11085, 26156, 11443, 408

Passed LTC
https://tests.stockfishchess.org/tests/view/61d99e3c9fea7913d9c663e4
LLR: 2.95 (-2.94,2.94) <0.50,3.00>
Total: 215232 W: 58191 L: 57492 D: 99549
Ptnml(0-2): 271, 22124, 62138, 22801, 282

closes https://github.com/official-stockfish/Stockfish/pull/3885

bench 4572746
2022-01-10 19:35:53 +01:00
Joost VandeVondele c5a280c012 Tune FRC trapped Bishop patch
now that fishtest can deal with FRC, retune this correction.

Add an additional fen to bench with cornered B and N.

passed STC:
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 49672 W: 7358 L: 7082 D: 35232
Ptnml(0-2): 241, 4329, 15458, 4529, 279
https://tests.stockfishchess.org/tests/view/61d8b7bf9fea7913d9c63cb7

passed LTC:
LLR: 2.95 (-2.94,2.94) <0.50,3.00>
Total: 86688 W: 8308 L: 8007 D: 70373
Ptnml(0-2): 92, 4943, 32989, 5212, 108
https://tests.stockfishchess.org/tests/view/61d92dcb9fea7913d9c650ad

closes https://github.com/official-stockfish/Stockfish/pull/3884

Bench: 4326560
2022-01-09 15:49:19 +01:00
Joost VandeVondele 9ad0ea7382 Tune a few parameters related to evaluation
based on a SPSA tune (using Autoselect)
https://tests.stockfishchess.org/tests/view/61d5aa63a314fed318a57046

passed STC:
LLR: 2.93 (-2.94,2.94) <0.00,2.50>
Total: 61960 W: 16640 L: 16316 D: 29004
Ptnml(0-2): 278, 6934, 16204, 7314, 250
https://tests.stockfishchess.org/tests/view/61d7fe4af5fd40f357469a8d

passed LTC:
LLR: 2.97 (-2.94,2.94) <0.50,3.00>
Total: 79408 W: 21994 L: 21618 D: 35796
Ptnml(0-2): 106, 7887, 23331, 8285, 95
https://tests.stockfishchess.org/tests/view/61d836b7f5fd40f35746a3d5

closes https://github.com/official-stockfish/Stockfish/pull/3883

Bench: 4266621
2022-01-08 08:44:49 +01:00
Stéphane Nicolet 2efda17c2a Update AUTHORS and CPU contributors files
closes https://github.com/official-stockfish/Stockfish/pull/3882

No functional change
2022-01-08 08:43:14 +01:00
Brad Knox ad926d34c0 Update copyright years
Happy New Year!

closes https://github.com/official-stockfish/Stockfish/pull/3881

No functional change
2022-01-06 15:45:45 +01:00
lonfom169 0b41887527 Simplify away rangeReduction
Remove rangeReduction, introduced in [#3717](https://github.com/official-stockfish/Stockfish/pull/3717),
as it seemingly doesn't bring enough ELO anymore. It might be interesting to add
new forms of reduction or tune the reduction formula in the future.

STC:
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 45008 W: 12114 L: 11972 D: 20922
Ptnml(0-2): 174, 5031, 11952, 5173, 174
https://tests.stockfishchess.org/tests/view/61d08b7b069ca917749c9f6f

LTC:
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 30792 W: 8235 L: 8086 D: 14471
Ptnml(0-2): 24, 3162, 8882, 3297, 31
https://tests.stockfishchess.org/tests/view/61d0a6ad069ca917749ca420

closes https://github.com/official-stockfish/Stockfish/pull/3878

Bench: 4048312
2022-01-02 17:49:44 +01:00
lonfom169 061f98a9e3 Smooth out doDeeperSearch
Adjust threshold based on the difference between newDepth and LMR depth.
With more reduction, bigger fail-high is required in order to perform the deeper search.

STC:
LLR: 2.96 (-2.94,2.94) <0.00,2.50>
Total: 93576 W: 24133 L: 23758 D: 45685
Ptnml(0-2): 260, 10493, 24935, 10812, 288
https://tests.stockfishchess.org/tests/view/61cbb5cee68b2a714b6eaf09

LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 109280 W: 28198 L: 27754 D: 53328
Ptnml(0-2): 60, 11225, 31637, 11647, 71
https://tests.stockfishchess.org/tests/view/61cc03fee68b2a714b6ec091

closes https://github.com/official-stockfish/Stockfish/pull/3877

Bench: 4464723
2021-12-31 07:44:15 +01:00
Stéphane Nicolet 1066119083 Tweak optimism with complexity
This patch increases the optimism bonus for "complex positions", where the
complexity is measured as the absolute value of the difference between material
and the sophisticated NNUE evaluation (idea by Joost VandeVondele).

Also rename some variables in evaluate() while there.

passed STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 88392 W: 23150 L: 22781 D: 42461
Ptnml(0-2): 318, 9961, 23257, 10354, 306
https://tests.stockfishchess.org/tests/view/61cbbedee68b2a714b6eb110

passed LTC:
LLR: 2.93 (-2.94,2.94) <0.50,3.00>
Total: 37848 W: 10043 L: 9766 D: 18039
Ptnml(0-2): 26, 3815, 10961, 4100, 22
https://tests.stockfishchess.org/tests/view/61cc0cc3e68b2a714b6ec28c

Closes https://github.com/official-stockfish/Stockfish/pull/3875
Follow-up from https://github.com/official-stockfish/Stockfish/commit/a5a89b27c8e3225fb453d603bc4515d32bb351c3

Bench: 4125221
2021-12-30 11:59:23 +01:00
bmc4 93b14a17d1 Don't direct prune a move if it's a retake
STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 36304 W: 9499 L: 9226 D: 17579
Ptnml(0-2): 96, 4102, 9508, 4325, 121
https://tests.stockfishchess.org/tests/view/61c7069ae68b2a714b6dca27

LTC:
LLR: 2.95 (-2.94,2.94) <0.50,3.00>
Total: 93824 W: 24478 L: 24068 D: 45278
Ptnml(0-2): 70, 9644, 27082, 10038, 78
https://tests.stockfishchess.org/tests/view/61c725fee68b2a714b6dcfa2

closes https://github.com/official-stockfish/Stockfish/pull/3871

Bench: 4106806
2021-12-27 16:43:44 +01:00
Joost VandeVondele 7d82f0d1f4 Update default net to nn-ac07bd334b62.nnue
Trained with essentially the same data as provided and used by Farseer (mbabigian)
for the previous master net.

T60T70wIsRightFarseerT60T74T75T76.binpack (99GB):
['T60T70wIsRightFarseer.binpack', 'farseerT74.binpack', 'farseerT75.binpack', 'farseerT76.binpack']
using the trainer branch tweakLR1PR (https://github.com/glinscott/nnue-pytorch/pull/158) and
`--gpus 1 --threads 4 --num-workers 4 --batch-size 16384 --progress_bar_refresh_rate 300 --smart-fen-skipping --random-fen-skipping 12 --features=HalfKAv2_hm^   --lambda=1.00` options

passed STC:
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 108280 W: 28042 L: 27636 D: 52602
Ptnml(0-2): 328, 12382, 28401, 12614, 415
https://tests.stockfishchess.org/tests/view/61bcd8c257a0d0f327c34fbd

passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 259296 W: 66974 L: 66175 D: 126147
Ptnml(0-2): 146, 27096, 74452, 27721, 233
https://tests.stockfishchess.org/tests/view/61bda70957a0d0f327c37817

closes https://github.com/official-stockfish/Stockfish/pull/3870

Bench: 4633875
2021-12-22 11:02:34 +01:00
Michael Chaly 0a6168089d Fall back to NNUE if classical evaluation is much lower than threshold
The idea is that if classical eval returns a value much lower than the threshold of
its usage it most likely means that position isn't that simple
so we need the more precise NNUE evaluation.

passed STC:
https://tests.stockfishchess.org/tests/view/61bf3e7557a0d0f327c3c47a
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 108072 W: 28007 L: 27604 D: 52461
Ptnml(0-2): 352, 12147, 28650, 12520, 367

passed LTC:
https://tests.stockfishchess.org/tests/view/61c0581657a0d0f327c3fa0c
LLR: 2.95 (-2.94,2.94) <0.50,3.00>
Total: 155096 W: 40392 L: 39841 D: 74863
Ptnml(0-2): 88, 15983, 44843, 16558, 76

closes https://github.com/official-stockfish/Stockfish/pull/3869

bench 4310422
2021-12-22 08:18:35 +01:00
bmc4 88f17a814d Update Elo estimates for terms in search
This updates estimates from 2yr ago #2401, and adds missing terms.
All tests run at 10+0.1 (STC), 20000 games, error bars +- 1.8 Elo, book 8moves_v3.png.

A table of Elo values with the links to the corresponding tests can be found at the PR

closes https://github.com/official-stockfish/Stockfish/pull/3868

Non-functional Change
2021-12-21 13:47:57 +01:00
bmc4 22e92d23d2 Remove Capture history pruning
Fixed number of games. (book: 8moves_v3.png):
ELO: -0.69 +-1.8 (95%) LOS: 22.1%
Total: 20000 W: 1592 L: 1632 D: 16776
Ptnml(0-2): 44, 1194, 7566, 1150, 46
https://tests.stockfishchess.org/tests/view/61bb8eb657a0d0f327c30ce8

STC:
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 139976 W: 36039 L: 36036 D: 67901
Ptnml(0-2): 435, 16138, 36885, 16049, 481
https://tests.stockfishchess.org/tests/view/61be731857a0d0f327c39ea2

LTC:
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 70656 W: 18284 L: 18189 D: 34183
Ptnml(0-2): 34, 7317, 20529, 7416, 32
https://tests.stockfishchess.org/tests/view/61bf39b657a0d0f327c3c37b

closes https://github.com/official-stockfish/Stockfish/pull/3867

bench: 4281737
2021-12-21 13:42:33 +01:00
bmc4 2c30956a13 Remove Capture Extension
This revert the patch #3692, probably can be simplified after the introduction of #3838.

Fixed-game test:
ELO: -1.41 +-1.8 (95%) LOS: 5.9%
Total: 20000 W: 1552 L: 1633 D: 16815
Ptnml(0-2): 38, 1242, 7517, 1169, 34
https://tests.stockfishchess.org/tests/view/61bc1a2057a0d0f327c32a3c

STC:
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 44528 W: 11619 L: 11478 D: 21431
Ptnml(0-2): 146, 5020, 11771, 5201, 126
https://tests.stockfishchess.org/tests/view/61bc638c57a0d0f327c338fe

LTC:
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 34136 W: 8847 L: 8704 D: 16585
Ptnml(0-2): 23, 3475, 9925, 3626, 19
https://tests.stockfishchess.org/tests/view/61bcb24257a0d0f327c34813

closes https://github.com/official-stockfish/Stockfish/pull/3863

Bench: 4054695
2021-12-21 13:40:57 +01:00
Stéphane Nicolet 74776dbcd5 Simplification in evaluate_nnue.cpp
Removes the test on non-pawn-material before applying the positional/materialistic bonus.

Passed STC:
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 46904 W: 12197 L: 12059 D: 22648
Ptnml(0-2): 170, 5243, 12479, 5399, 161
https://tests.stockfishchess.org/tests/view/61be57cf57a0d0f327c3999d

Passed LTC:
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 18760 W: 4958 L: 4790 D: 9012
Ptnml(0-2): 14, 1942, 5301, 2108, 15
https://tests.stockfishchess.org/tests/view/61bed1fb57a0d0f327c3afa9

closes https://github.com/official-stockfish/Stockfish/pull/3866

Bench: 4826206
2021-12-19 15:44:01 +01:00
George Sobala ca51b45649 Fixes build failure on Apple M1 Silicon
This pull request selectively avoids `-mdynamic-no-pic` for gcc on Apple Silicon
(there was no problem with the default clang compiler).

fixes https://github.com/official-stockfish/Stockfish/issues/3847
closes https://github.com/official-stockfish/Stockfish/pull/3850

No functional change
2021-12-19 11:43:18 +01:00
Michael Chaly fb7d3ab32e Reintroduce futility pruning for captures
This is a reintroduction of an idea that was simplified away approximately 1 year ago.
There are some tweaks to it :
a) exclude promotions;
b) exclude Pv Nodes from it - Pv Nodes logic for captures is really different from non Pv nodes so it makes a lot of sense;
c) use a big grain of capture history - idea is taken from my recent patches in futility pruning.

passed STC
https://tests.stockfishchess.org/tests/view/61bd90f857a0d0f327c373b7
LLR: 2.96 (-2.94,2.94) <0.00,2.50>
Total: 86640 W: 22474 L: 22110 D: 42056
Ptnml(0-2): 268, 9732, 22963, 10082, 275

passed LTC
https://tests.stockfishchess.org/tests/view/61be094457a0d0f327c38aa3
LLR: 2.95 (-2.94,2.94) <0.50,3.00>
Total: 23240 W: 6079 L: 5838 D: 11323
Ptnml(0-2): 14, 2261, 6824, 2512, 9

https://github.com/official-stockfish/Stockfish/pull/3864

bench 4493723
2021-12-19 08:03:41 +01:00
Michael Chaly 0a318cdddf Adjust reductions based on current node delta and root delta
This patch is a follow up of previous 2 patches that introduced more reductions for PV nodes with low delta and more pruning for nodes with low delta. Instead of writing separate heuristics now it adjust reductions based on delta / rootDelta - it allows to remove 3 separate adjustements of pruning/LMR in different places and also makes reduction dependence on delta and rootDelta smoother. Also now it works for all pruning heuristics and not just 2.

Passed STC
https://tests.stockfishchess.org/tests/view/61ba9b6c57a0d0f327c2d48b
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 79192 W: 20513 L: 20163 D: 38516
Ptnml(0-2): 238, 8900, 21024, 9142, 292

passed LTC
https://tests.stockfishchess.org/tests/view/61baf77557a0d0f327c2eb8e
LLR: 2.96 (-2.94,2.94) <0.50,3.00>
Total: 158400 W: 41134 L: 40572 D: 76694
Ptnml(0-2): 101, 16372, 45745, 16828, 154

closes https://github.com/official-stockfish/Stockfish/pull/3862

bench 4651538
2021-12-18 17:19:21 +01:00
George Sobala 939b694bfd Fix for profile-build failure using gcc on MacOS
Fixes https://github.com/official-stockfish/Stockfish/issues/3846 ,
where the profiling SF binary generated by GCC on MacOS would launch
but failed to quit. Tested with gcc-8, gcc9, gcc10, gcc-11.

The problem can be fixed by adding -fvisibility=hidden to the compiler
flags, see for example the following piece of Apple documentation:
https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/CppRuntimeEnv/Articles/SymbolVisibility.html

For instance this now works:
   make -j8 profile-build ARCH=x86-64-avx2 COMP=gcc COMPCXX=g++-11

No functional change
2021-12-17 18:52:09 +01:00
pb00067 dc5d9bdfee Remove lowPly history
Seems that after pull request #3731 (Capping stat bonus at 2000) this
heuristic is no longer useful.

STC:
https://tests.stockfishchess.org/tests/view/61b8d0e2dffbe89a35815444
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 30672 W: 7974 L: 7812 D: 14886
Ptnml(0-2): 106, 3436, 8072, 3634, 88

LTC:
https://tests.stockfishchess.org/tests/view/61b8e90cdffbe89a35815a67
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 42448 W: 10884 L: 10751 D: 20813
Ptnml(0-2): 23, 4394, 12267, 4507, 33

closes https://github.com/official-stockfish/Stockfish/pull/3853

bench: 4474950
2021-12-17 18:37:41 +01:00
bmc4 0889210262 Simplify away singularQuietLMR
While at it, we also update the Elo estimate of reduction at non-PV nodes
(source: https://tests.stockfishchess.org/tests/view/61acf97156fcf33bce7d6303 )

STC:
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 243632 W: 62874 L: 63022 D: 117736
Ptnml(0-2): 810, 28024, 64249, 27970, 763
https://tests.stockfishchess.org/tests/view/61b8b1b7dffbe89a35814c0d

LTC:
LLR: 2.93 (-2.94,2.94) <-2.25,0.25>
Total: 91392 W: 23520 L: 23453 D: 44419
Ptnml(0-2): 51, 9568, 26387, 9643, 47
https://tests.stockfishchess.org/tests/view/61b97316dffbe89a35817da7

closes https://github.com/official-stockfish/Stockfish/pull/3854

bench: 4217785
2021-12-17 18:22:48 +01:00
farseer 3bea736a2a Update default net to nn-4401e826ebcc.nnue
Using data T60 12/1/20 to 11/2/2021, T74 4/22/21 to 7/27/21, T75 6/3/21 to 10/16/21, T76
(half of the randomly interleaved dataset due to a mistake merging) 11/10/21 to 11/21/21,
wrongIsRight_nodes5000pv2.binpack, and WrongIsRight-Reloaded.binpack combined and shuffled
position by position.

Trained with LR=4.375e-4 and WDL filtering enabled:

python train.py --smart-fen-skipping --random-fen-skipping 0 --features=HalfKAv2_hm^
--lambda=1.0 --max_epochs=800 --seed 910688689 --batch-size 16384
--progress_bar_refresh_rate 30 --threads 4 --num-workers 4 --gpus 1
--resume-from-model C:\msys64\home\Mike\nnue-pytorch\9b3d.pt
E:\trainingdata\T60-T74-T75-T76-WiR-WiRR-PbyP.binpack
E:\trainingdata\T60-T74-T75-T76-WiR-WiRR-PbyP.binpack

Passed STC
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 41848 W: 10962 L: 10676 D: 20210 Elo +2.16
Ptnml(0-2): 142, 4699, 11016, 4865, 202
https://tests.stockfishchess.org/tests/view/61ba886857a0d0f327c2cfd6

Passed LTC
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 27776 W: 7208 L: 6953 D: 13615 Elo + 3.00
Ptnml(0-2): 14, 2808, 8007, 3027, 32
https://tests.stockfishchess.org/tests/view/61baae4d57a0d0f327c2d96f

closes https://github.com/official-stockfish/Stockfish/pull/3856

Bench: 4667591
2021-12-17 18:12:47 +01:00
Joost VandeVondele c6edf33f53 Remove NNUE scaling term
remove pawns scaling, probably correlated with piece scaling, and might be less useful with the recent improved nets. Might allow for another tune of the scaling params.

passed STC
https://tests.stockfishchess.org/tests/view/61afdb2e56fcf33bce7df31a
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 280864 W: 72198 L: 72399 D: 136267
Ptnml(0-2): 854, 32356, 74346, 31889, 987

passed LTC
https://tests.stockfishchess.org/tests/view/61b233a606b4c2dcb1b16140
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 400136 W: 102669 L: 103012 D: 194455
Ptnml(0-2): 212, 42005, 116047, 41522, 282

closes https://github.com/official-stockfish/Stockfish/pull/3851

Bench: 4735679
2021-12-14 13:41:12 +01:00
Joost VandeVondele ea1ddb6aef Update default net to nn-d93927199b3d.nnue
Using the same dataset as before but slightly reduced initial LR as in
https://github.com/vondele/nnue-pytorch/tree/tweakLR1

passed STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 51368 W: 13492 L: 13191 D: 24685
Ptnml(0-2): 168, 5767, 13526, 6042, 181
https://tests.stockfishchess.org/tests/view/61b61f43dffbe89a3580b529

passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 45128 W: 11763 L: 11469 D: 21896
Ptnml(0-2): 24, 4583, 13063, 4863, 31
https://tests.stockfishchess.org/tests/view/61b6612edffbe89a3580c447

closes https://github.com/official-stockfish/Stockfish/pull/3848

Bench: 5121336
2021-12-13 07:17:25 +01:00
Stefan Geschwentner d579db34a3 Simplify falling eval time factor.
Remove the difference to previous best score in falling eval calculation. As compensation double the effect of the difference to previous best average score.

STC:
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 86944 W: 22363 L: 22285 D: 42296
Ptnml(0-2): 273, 9227, 24396, 9301, 275
https://tests.stockfishchess.org/tests/view/61b111ce06b4c2dcb1b11546

LTC:
LLR: 2.96 (-2.94,2.94) <-2.25,0.25>
Total: 134944 W: 34606 L: 34596 D: 65742
Ptnml(0-2): 66, 12941, 41456, 12935, 74
https://tests.stockfishchess.org/tests/view/61b19ca206b4c2dcb1b13a8b

closes https://github.com/official-stockfish/Stockfish/pull/3841

Bench: 4729473
2021-12-11 15:56:38 +01:00
Joost VandeVondele 9db6ca8592 Update Top CPU Contributors
closes https://github.com/official-stockfish/Stockfish/pull/3842

No functional change
2021-12-11 15:55:32 +01:00
Michael Chaly 8e82345931 Adjust singular extension depth restriction
This patch is a modification of original idea by lonfom169 which had a good yellow run
- do singular extension search with depth threshold 6 unless this is a PvNode with is a part of a PV line -
for them set threshold to 8 instead.

Passed STC
https://tests.stockfishchess.org/tests/view/61b1080406b4c2dcb1b1128c
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 84352 W: 21917 L: 21555 D: 40880
Ptnml(0-2): 288, 9524, 22185, 9896, 283

Passed LTC
https://tests.stockfishchess.org/tests/view/61b1860a06b4c2dcb1b134a1
LLR: 2.95 (-2.94,2.94) <0.50,3.00>
Total: 63520 W: 16575 L: 16237 D: 30708
Ptnml(0-2): 27, 6519, 18350, 6817, 47

https://github.com/official-stockfish/Stockfish/pull/3840

bench 4729473
2021-12-09 20:50:00 +01:00
Stefan Geschwentner 9451419912 Improve transposition table remplacement strategy
Increase chance that PV node replaces old entry in transposition table.

STC:
LLR: 2.93 (-2.94,2.94) <0.00,2.50>
Total: 46744 W: 12108 L: 11816 D: 22820
Ptnml(0-2): 156, 5221, 12344, 5477, 174
https://tests.stockfishchess.org/tests/view/61ae068356fcf33bce7d99d0

LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 88464 W: 22912 L: 22513 D: 43039
Ptnml(0-2): 84, 9133, 25393, 9544, 78
https://tests.stockfishchess.org/tests/view/61ae973656fcf33bce7db3e1

closes https://github.com/official-stockfish/Stockfish/pull/3839

Bench: 5292488
2021-12-08 17:16:17 +01:00
Michael Chaly c228f3196a Introduce post-lmr extensions
This idea is somewhat similar to extentions in LMR but has a different flavour.
If result of LMR was really good - thus exceeded alpha by some pretty
big given margin, we can extend move after LMR in full depth search with 0 window.
The idea is that this move is probably a fail high with somewhat of a big
probability so extending it makes a lot of sense

passed STC
https://tests.stockfishchess.org/tests/view/61ad45ea56fcf33bce7d74b7
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 59680 W: 15531 L: 15215 D: 28934
Ptnml(0-2): 193, 6711, 15734, 6991, 211

passed LTC
https://tests.stockfishchess.org/tests/view/61ad9ff356fcf33bce7d8646
LLR: 2.95 (-2.94,2.94) <0.50,3.00>
Total: 59104 W: 15321 L: 14992 D: 28791
Ptnml(0-2): 53, 6023, 17065, 6364, 47

closes https://github.com/official-stockfish/Stockfish/pull/3838

bench 4881329
2021-12-07 18:15:06 +01:00
Tomasz Sobczyk 4766dfc395 Optimize FT activation and affine transform for NEON.
This patch optimizes the NEON implementation in two ways.

    The activation layer after the feature transformer is rewritten to make it easier for the compiler to see through dependencies and unroll. This in itself is a minimal, but a positive improvement. Other architectures could benefit from this too in the future. This is not an algorithmic change.
    The affine transform for large matrices (first layer after FT) on NEON now utilizes the same optimized code path as >=SSSE3, which makes the memory accesses more sequential and makes better use of the available registers, which allows for code that has longer dependency chains.

Benchmarks from Redshift#161, profile-build with apple clang

george@Georges-MacBook-Air nets % ./stockfish-b82d93 bench 2>&1 | tail -4 (current master)
===========================
Total time (ms) : 2167
Nodes searched  : 4667742
Nodes/second    : 2154011
george@Georges-MacBook-Air nets % ./stockfish-7377b8 bench 2>&1 | tail -4 (this patch)
===========================
Total time (ms) : 1842
Nodes searched  : 4667742
Nodes/second    : 2534061

This is a solid 18% improvement overall, larger in a bench with NNUE-only, not mixed.

Improvement is also observed on armv7-neon (Raspberry Pi, and older phones), around 5% speedup.

No changes for architectures other than NEON.

closes https://github.com/official-stockfish/Stockfish/pull/3837

No functional changes.
2021-12-07 18:08:54 +01:00
Joost VandeVondele b82d93ece4 Update default net to nn-63376713ba63.nnue.
same data set as previous trained nets, tuned the wdl model slightly for training.
https://github.com/vondele/nnue-pytorch/tree/wdlTweak1

passed STC:
https://tests.stockfishchess.org/tests/view/61abe9e456fcf33bce7d2834
LLR: 2.93 (-2.94,2.94) <0.00,2.50>
Total: 31720 W: 8385 L: 8119 D: 15216
Ptnml(0-2): 117, 3534, 8273, 3838, 98

passed LTC:
https://tests.stockfishchess.org/tests/view/61ac293756fcf33bce7d36cf
LLR: 2.96 (-2.94,2.94) <0.50,3.00>
Total: 136136 W: 35255 L: 34741 D: 66140
Ptnml(0-2): 114, 14217, 38894, 14727, 116

closes https://github.com/official-stockfish/Stockfish/pull/3836

Bench: 4667742
2021-12-07 12:40:48 +01:00
Michael Chaly a3d425cf55 Assign extra bonus for previous move that caused a fail low more often
This patch allows to assign extra bonus for previous move that caused a fail low not only for PvNodes and cutNodes but also fo some allNodes - namely if the best result we could've got from the search is still far below alpha.

passed STC
https://tests.stockfishchess.org/tests/view/61aa26a49e8855bba1a36d96
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 73808 W: 19183 L: 18842 D: 35783
Ptnml(0-2): 251, 8257, 19564, 8564, 268

passed LTC
https://tests.stockfishchess.org/tests/view/61aa7dc29e8855bba1a3814f
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 142416 W: 36717 L: 36192 D: 69507
Ptnml(0-2): 106, 14799, 40862, 15346, 95

closes https://github.com/official-stockfish/Stockfish/pull/3835

bench 4724181
2021-12-06 07:42:04 +01:00
Stefan Geschwentner 7d44b43b3c Tweak history initialization
Initialize continuation history with a slighlty negative value -71 instead of zero.

The idea is, because the most history entries will be later negative anyway, to shift
the starting values a little bit in the "correct" direction. Of course the effect of
initialization dimishes with greater depth so I had the apprehension that the LTC test
would be difficult to pass, but it passed.

STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 34520 W: 9076 L: 8803 D: 16641
Ptnml(0-2): 136, 3837, 9047, 4098, 142
https://tests.stockfishchess.org/tests/view/61aa52e39e8855bba1a3776b

LTC:
LLR: 2.93 (-2.94,2.94) <0.50,3.00>
Total: 75568 W: 19620 L: 19254 D: 36694
Ptnml(0-2): 44, 7773, 21796, 8115, 56
https://tests.stockfishchess.org/tests/view/61aa87d39e8855bba1a383a5

closes https://github.com/official-stockfish/Stockfish/pull/3834

Bench: 4674029
2021-12-05 18:13:49 +01:00
Stefan Geschwentner 18f2b12cd0 Tweak time management
Use for adjustment of the falling eval time factor now also the difference
between previous best average score and current best score.

STC:
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 109216 W: 28296 L: 27900 D: 53020
Ptnml(0-2): 312, 11759, 30148, 11999, 390
https://tests.stockfishchess.org/tests/view/61aafa8d1b31b85bcfa29d9c

LTC:
LLR: 2.93 (-2.94,2.94) <0.50,3.00>
Total: 54096 W: 14091 L: 13787 D: 26218
Ptnml(0-2): 29, 5124, 16447, 5410, 38
https://tests.stockfishchess.org/tests/view/61abbbbd56fcf33bce7d1d64

closes https://github.com/official-stockfish/Stockfish/pull/3833

Bench: 4829419
2021-12-05 17:56:54 +01:00
bmc4 a6a9d828ab Simplifies bestMoveChanges from LMR
As bestMoveChanges is only reset on mainThread and it could change how other
threads search, a multi-threads test was made.

STC:
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 146776 W: 37934 L: 37941 D: 70901
Ptnml(0-2): 477, 15644, 41173, 15597, 497
https://tests.stockfishchess.org/tests/view/61a8f9f34ed77d629d4ea2d6

LTC:
LLR: 3.11 (-2.94,2.94) <-2.25,0.25>
Total: 114040 W: 29314 L: 29269 D: 55457
Ptnml(0-2): 50, 10584, 35722, 10599, 65
https://tests.stockfishchess.org/tests/view/61a9d4bf9e8855bba1a35c4f

(SMP, 8 threads) STC:
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 23888 W: 6308 L: 6143 D: 11437
Ptnml(0-2): 36, 2557, 6600, 2708, 43
https://tests.stockfishchess.org/tests/view/61ac27a756fcf33bce7d3677

closes https://github.com/official-stockfish/Stockfish/pull/3831

bench: 4829419
2021-12-05 17:50:04 +01:00
Joost VandeVondele 327060232a Update default net to nn-cdf1785602d6.nnue
Same process as in https://github.com/official-stockfish/Stockfish/commit/e4a0c6c75950bf27b6dc32490a1102499643126b
with the training started from the current master net.

passed STC:
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 38224 W: 10023 L: 9742 D: 18459
Ptnml(0-2): 133, 4328, 9940, 4547, 164
https://tests.stockfishchess.org/tests/view/61a8611e4ed77d629d4e836e

passed LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 115176 W: 29783 L: 29321 D: 56072
Ptnml(0-2): 68, 12039, 32936, 12453, 92
https://tests.stockfishchess.org/tests/view/61a8963e4ed77d629d4e8d9b

closes https://github.com/official-stockfish/Stockfish/pull/3830

Bench: 4829419
2021-12-04 10:31:22 +01:00
Michael Chaly e4b7403f12 Do more aggressive pruning for some node types
This patch allows more aggressive futility/see based pruning for PV nodes with low delta and non-pv nodes.

Fixes some white space issues.

Passed STC
https://tests.stockfishchess.org/tests/view/61a5ed33d16c530b5dcc27cc
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 182088 W: 47121 L: 46584 D: 88383
Ptnml(0-2): 551, 20687, 48037, 21212, 557

Passed LTC
https://tests.stockfishchess.org/tests/view/61a74dfdbd5c4360bcded0ac
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 87136 W: 22494 L: 22103 D: 42539
Ptnml(0-2): 38, 8918, 25272, 9295, 45

closes https://github.com/official-stockfish/Stockfish/pull/3828
closes https://github.com/official-stockfish/Stockfish/pull/3829

bench 4332259
2021-12-03 08:54:46 +01:00
Gian-Carlo Pascutto c9977aa0a8 Add AVX-VNNI support for Alder Lake and later.
In their infinite wisdom, Intel axed AVX512 from Alder Lake
chips (well, not entirely, but we kind of want to use the Gracemont
cores for chess!) but still added VNNI support.
Confusingly enough, this is not the same as VNNI256 support.

This adds a specific AVX-VNNI target that will use this AVX-VNNI
mode, by prefixing the VNNI instructions with the appropriate VEX
prefix, and avoiding AVX512 usage.

This is about 1% faster on P cores:

Result of  20 runs
==================
base (./clang-bmi2   ) =    3306337  +/- 7519
test (./clang-vnni   ) =    3344226  +/- 7388
diff                   =     +37889  +/- 4153

speedup        = +0.0115
P(speedup > 0) =  1.0000

But a nice 3% faster on E cores:

Result of  20 runs
==================
base (./clang-bmi2   ) =    1938054  +/- 28257
test (./clang-vnni   ) =    1994606  +/- 31756
diff                   =     +56552  +/- 3735

speedup        = +0.0292
P(speedup > 0) =  1.0000

This was measured on Clang 13. GCC 11.2 appears to generate
worse code for Alder Lake, though the speedup on the E cores
is similar.

It is possible to run the engine specifically on the P or E using binding,
for example in linux it is possible to use (for an 8 P + 8 E setup like i9-12900K):
taskset -c 0-15 ./stockfish
taskset -c 16-23 ./stockfish
where the first call binds to the P-cores and the second to the E-cores.

closes https://github.com/official-stockfish/Stockfish/pull/3824

No functional change
2021-12-03 08:51:06 +01:00
bmc4 c1f9a359e8 Correctly reset bestMoveChanges
for searches not using time management (e.g. analysis, fixed node game play etc),
bestMoveChanges was not reset during search iterations. As LMR uses this quantity,
search was somewhat weaker.

Tested using fixed node playing games:
```
./c-chess-cli -each nodes=10000 option.Hash=16 -engine cmd=../Stockfish/src/fix -engine cmd=../Stockfish/src/master -concurrency 6 -openings file=../books/UHO_XXL_+0.90_+1.19.epd -games 10000
Score of Stockfish Fix vs Stockfish Master: 3187 - 3028 - 3785  [0.508] 10000

./c-chess-cli -each nodes=30000 option.Hash=16 -engine cmd=../Stockfish/src/fix -engine cmd=../Stockfish/src/master -concurrency 6 -openings file=../books/UHO_XXL_+0.90_+1.19.epd -games 10000
Score of Stockfish Fix vs Stockfish Master: 2946 - 2834 - 4220  [0.506] 10000
```

closes https://github.com/official-stockfish/Stockfish/pull/3818

bench: 5061979
2021-12-01 18:22:44 +01:00
bmc4 95a2ac1e07 Simplify reduction on rootNode when bestMoveChanges is high
The reduction introduced in #3736 also consider on rootNode, so we don't have to reduce again.

STC:
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 28736 W: 7494 L: 7329 D: 13913
Ptnml(0-2): 95, 3247, 7503, 3444, 79
https://tests.stockfishchess.org/tests/view/61a3abe01b7fdf52228e74d8

LTC:
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 47816 W: 12434 L: 12308 D: 23074
Ptnml(0-2): 37, 4972, 13755, 5116, 28
https://tests.stockfishchess.org/tests/view/61a3c3e39f0c43dae1c71d71

closes https://github.com/official-stockfish/Stockfish/pull/3817

bench: 6331638
2021-12-01 18:10:51 +01:00
Michael Ortmann 4b86ef8c4f Fix typos in comments, adjust readme
closes https://github.com/official-stockfish/Stockfish/pull/3822

also adjusts readme as requested in https://github.com/official-stockfish/Stockfish/pull/3816

No functional change
2021-12-01 18:07:30 +01:00
hengyu 64f21ecdae Small clean-up
remove unneeded calculation.

closes https://github.com/official-stockfish/Stockfish/pull/3807

No functional change.
2021-12-01 17:59:20 +01:00
pb00067 282644f141 Remove depth dependence and use same limit (2000) as stat_bonus
STC:
https://tests.stockfishchess.org/tests/view/619df59dc0a4ea18ba95a424
LLR: 2.96 (-2.94,2.94) <-2.25,0.25>
Total: 83728 W: 21329 L: 21242 D: 41157
Ptnml(0-2): 297, 9669, 21847, 9752, 299

LTC:
https://tests.stockfishchess.org/tests/view/619e64d7c0a4ea18ba95a475
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 79888 W: 20238 L: 20155 D: 39495
Ptnml(0-2): 57, 8391, 22980, 8444, 73

closes https://github.com/official-stockfish/Stockfish/pull/3806

bench: 6792010
2021-12-01 17:55:23 +01:00
noobpwnftw ca3c1c5f3a Enable compilation on older Windows systems
Improve compatibility of the last NUMA patch when running under older versions of Windows,
for instance Windows Server 2003. Reported by user "g3g6" in the following comments:
https://github.com/official-stockfish/Stockfish/commit/7218ec4df9fef1146a451b71f0ed3bfd8123c9f9

Closes https://github.com/official-stockfish/Stockfish/pull/3821

No functional change
2021-11-30 20:57:47 +01:00
Joost VandeVondele e4a0c6c759 Update default net to nn-4f56ecfca5b7.nnue
New net trained with nnue-pytorch, started from a master net on a data set of Leela
(T60.binpack+T74.binpck) Stockfish data (wrongIsRight_nodes5000pv2.binpack), and
Michael Babigian's conversion of T60 Leela data (including TB7 rescoring) (farseer.binpack)
available as a single interleaved binpack:

https://drive.google.com/file/d/1_sQoWBl31WAxNXma2v45004CIVltytP8/view?usp=sharing

The nnue-pytorch branch used is https://github.com/vondele/nnue-pytorch/tree/wdl

passed STC:
https://tests.stockfishchess.org/tests/view/61a3cc729f0c43dae1c71f1b
LLR: 2.95 (-2.94,2.94) <0.00,2.50>
Total: 49152 W: 12842 L: 12544 D: 23766
Ptnml(0-2): 154, 5542, 12904, 5804, 172

passed LTC:
https://tests.stockfishchess.org/tests/view/61a43c6260afd064f2d724f1
LLR: 2.96 (-2.94,2.94) <0.50,3.00>
Total: 25528 W: 6676 L: 6425 D: 12427
Ptnml(0-2): 9, 2593, 7315, 2832, 15

closes https://github.com/official-stockfish/Stockfish/pull/3816

Bench: 6885242
2021-11-29 12:56:01 +01:00
Michael Chaly af050e5eed Refine futility pruning for parent nodes
This patch is a result of refining of tuning vondele did after
new net passed and some hand-made values adjustements - excluding
changes in other pruning heuristics and rounding value of history
divisor to the nearest power of 2.

With this patch futility pruning becomes more aggressive and
history influence on it is doubled again.

passed STC
https://tests.stockfishchess.org/tests/view/61a2c4c1a26505c2278c150d
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 33848 W: 8841 L: 8574 D: 16433
Ptnml(0-2): 100, 3745, 8988, 3970, 121

passed LTC
https://tests.stockfishchess.org/tests/view/61a327ffa26505c2278c26d9
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 22272 W: 5856 L: 5614 D: 10802
Ptnml(0-2): 12, 2230, 6412, 2468, 14

closes https://github.com/official-stockfish/Stockfish/pull/3814

bench 6302543
2021-11-28 14:25:06 +01:00
Michael Chaly 8bb5a436b2 Adjust usage of history in futility pruning
This patch refines 0ac8aca893 that uses history heuristics in futility pruning.
Now it adds main history of the move to in and also increases effect by factor of 2.

passed STC
https://tests.stockfishchess.org/tests/view/61a156829e83391467a2b2c9
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 68464 W: 17920 L: 17587 D: 32957
Ptnml(0-2): 239, 7711, 18025, 7992, 265

passed LTC
https://tests.stockfishchess.org/tests/view/61a1bde99e83391467a2b305
LLR: 2.95 (-2.94,2.94) <0.50,3.00>
Total: 26088 W: 6926 L: 6674 D: 12488
Ptnml(0-2): 18, 2619, 7531, 2845, 31

closes https://github.com/official-stockfish/Stockfish/pull/3812

bench 6804653
2021-11-27 14:47:46 +01:00
Joost VandeVondele 4bb11e823f Tune NNUE scaling params
passed STC:
https://tests.stockfishchess.org/tests/view/61a156f89e83391467a2b2cc
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 22816 W: 5896 L: 5646 D: 11274
Ptnml(0-2): 55, 2567, 5961, 2723, 102

passed LTC:
https://tests.stockfishchess.org/tests/view/61a1cf3d9e83391467a2b30b
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 17904 W: 4658 L: 4424 D: 8822
Ptnml(0-2): 6, 1821, 5079, 2025, 21

closes https://github.com/official-stockfish/Stockfish/pull/3811

Bench: 7218806
2021-11-27 14:26:35 +01:00
Joost VandeVondele 9ee58dc7a7 Update default net to nn-3678835b1d3d.nnue
New net trained with nnue-pytorch, started from the master net on a data set of Leela
(T60.binpack+T74.binpck) and Stockfish data (wrongIsRight_nodes5000pv2.binpack),
available as a single interleaved binpack:

https://drive.google.com/file/d/12uWZIA3F2cNbraAzQNb1jgf3tq_6HkTr/view?usp=sharing

The nnue-pytorch branch used is https://github.com/vondele/nnue-pytorch/tree/wdl, which
has the new feature to filter positions based on the likelihood of the current evaluation
leading to the game outcome. It should make it less likely to try to learn from
misevaluated positions. Standard options have been used, starting from the master net:

   --gpus 1 --threads 4 --num-workers 4 --batch-size 16384 --progress_bar_refresh_rate 300
   --smart-fen-skipping --random-fen-skipping 12 --features=HalfKAv2_hm^   --lambda=1.0

Testing with games shows neutral Elo at STC, and good performance at LTC:

STC:
https://tests.stockfishchess.org/tests/view/619eb597c0a4ea18ba95a4dc
ELO: -0.44 +-1.8 (95%) LOS: 31.2%
Total: 40000 W: 10447 L: 10498 D: 19055
Ptnml(0-2): 254, 4576, 10260, 4787, 123

LTC:
https://tests.stockfishchess.org/tests/view/619f6e87c0a4ea18ba95a53f
ELO: 3.30 +-1.8 (95%) LOS: 100.0%
Total: 33062 W: 8560 L: 8246 D: 16256
Ptnml(0-2): 54, 3358, 9352, 3754, 13

passed LTC SPRT:
https://tests.stockfishchess.org/tests/view/61a0864e8967bbf894416e65
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 29376 W: 7663 L: 7396 D: 14317
Ptnml(0-2): 67, 3017, 8205, 3380, 19

closes https://github.com/official-stockfish/Stockfish/pull/3808

Bench: 7011501
2021-11-26 18:16:04 +01:00
Michael Chaly 0ac8aca893 Use fraction of history heuristics in futility pruning
This idea is somewhat of a respin of smth we had in futility pruning and that was simplified away - dependence of it not only on static evaluation of position but also on move history heuristics.
Instead of aborting it when they are high there we use fraction of their sum to adjust static eval pruning criteria.

passed STC
https://tests.stockfishchess.org/tests/view/619bd438c0a4ea18ba95a27d
LLR: 2.93 (-2.94,2.94) <0.00,2.50>
Total: 113704 W: 29284 L: 28870 D: 55550
Ptnml(0-2): 357, 12884, 30044, 13122, 445

passed LTC
https://tests.stockfishchess.org/tests/view/619cb8f0c0a4ea18ba95a334
LLR: 2.96 (-2.94,2.94) <0.50,3.00>
Total: 147136 W: 37307 L: 36770 D: 73059
Ptnml(0-2): 107, 15279, 42265, 15804, 113

closes https://github.com/official-stockfish/Stockfish/pull/3805

bench 6777918
2021-11-25 19:38:03 +01:00
Stefan Geschwentner 092b27a6d0 Less futility pruning.
Disable futility pruning at former PV nodes stored in the transposition table.

STC:
LLR: 2.96 (-2.94,2.94) <0.00,2.50>
Total: 102256 W: 25708 L: 25318 D: 51230
Ptnml(0-2): 276, 11511, 27168, 11893, 280
https://tests.stockfishchess.org/tests/view/61990b3135c7c6348cb602db

LTC:
LLR: 2.96 (-2.94,2.94) <0.50,3.00>
Total: 183304 W: 46027 L: 45408 D: 91869
Ptnml(0-2): 96, 19029, 52778, 19658, 91
https://tests.stockfishchess.org/tests/view/619a0d1b35c7c6348cb603bc

closes https://github.com/official-stockfish/Stockfish/pull/3804

Bench: 7334766
2021-11-23 21:23:28 +01:00
noobpwnftw 7218ec4df9 Revert and fix earlier windows NUMA patch
revert https://github.com/official-stockfish/Stockfish/commit/9048ac00db12a9ac48bff9b9eb145b30ff88d984 due to core spread problem and fix new OS compatibility with another method.

This code assumes that if one NUMA node has more than one processor groups, they are created equal(having equal amount of cores assigned to each of the groups), and also the total number of available cores contained in such groups are equal to the number of available cores within one NUMA node because of how best_node function works.

closes https://github.com/official-stockfish/Stockfish/pull/3798
fixes https://github.com/official-stockfish/Stockfish/pull/3787

No functional change.
2021-11-22 13:31:13 +01:00
Joost VandeVondele a943b1d28d Remove appveyor CI
retire msvc support and corresponding CI. No active development happens on msvc,
and build is much slower or wrong.

gcc (mingw) is our toolchain of choice also on windows, and the latter is tested.

No functional change
2021-11-21 21:56:13 +01:00
Stéphane Nicolet a5a89b27c8 Introduce Optimism
Current master implements a scaling of the raw NNUE output value with a formula
equivalent to 'eval = alpha * NNUE_output', where the scale factor alpha varies
between 1.8 (for early middle game) and 0.9 (for pure endgames). This feature
allows Stockfish to keep material on the board when she thinks she has the advantage,
and to seek exchanges and simplifications when she thinks she has to defend.

This patch slightly offsets the turning point between these two strategies, by adding
to Stockfish's evaluation a small "optimism" value before actually doing the scaling.
The effect is that SF will play a little bit more risky, trying to keep the tension a
little bit longer when she is defending, and keeping even more material on the board
when she has an advantage.

We note that this patch is similar in spirit to the old "Contempt" idea we used to have
in classical Stockfish, but this implementation differs in two key points:

  a) it has been tested as an Elo-gainer against master;

  b) the values output by the search are not changed on average by the implementation
     (in other words, the optimism value changes the tension/exchange strategy, but a
     displayed value of 1.0 pawn has the same signification before and after the patch).

See the old comment https://github.com/official-stockfish/Stockfish/pull/1361#issuecomment-359165141
for some images illustrating the ideas.

-------

finished yellow at STC:
LLR: -2.94 (-2.94,2.94) <0.00,2.50>
Total: 165048 W: 41705 L: 41611 D: 81732
Ptnml(0-2): 565, 18959, 43245, 19327, 428
https://tests.stockfishchess.org/tests/view/61942a3dcd645dc8291c876b

passed LTC:
LLR: 2.95 (-2.94,2.94) <0.50,3.00>
Total: 121656 W: 30762 L: 30287 D: 60607
Ptnml(0-2): 87, 12558, 35032, 13095, 56
https://tests.stockfishchess.org/tests/view/61962c58cd645dc8291c8877

-------

How to continue from there?

a) the shape (slope and amplitude) of the sigmoid used to compute the optimism value
   could be tweaked to try to gain more Elo, so the parameters of the sigmoid function
   in line 391 of search.cpp could be tuned with SPSA. Manual tweaking is also possible
   using this Desmos page: https://www.desmos.com/calculator/jhh83sqq92

b) in a similar vein, with two recents patches affecting the scaling of the NNUE
   evaluation in evaluate.cpp, now could be a good time to try a round of SPSA tuning
   of the NNUE network;

c) this patch will tend to keep tension in middlegame a little bit longer, so any
   patch improving the defensive aspect of play via search extensions in risky,
   tactical positions would be welcome.

-------

closes https://github.com/official-stockfish/Stockfish/pull/3797

Bench: 6184852
2021-11-21 21:18:08 +01:00
Michael Chaly f5df517145 Simplify Pv nodes related logic in LMR
Instead of having 2 separate conditions for Pv nodes reductions we can actually write them together. Despite it's not being strictly logically the same bench actually doesn't change up to depth 20, so them interacting is really rare and thus it's just a removal of extra PvNode check most of the time.

passed STC:
https://tests.stockfishchess.org/tests/view/618ce27cd7a085ad008ef4e9
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 37488 W: 9424 L: 9279 D: 18785
Ptnml(0-2): 90, 3903, 10634, 4006, 111

passed LTC:
https://tests.stockfishchess.org/tests/view/618d2585d7a085ad008ef527
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 49968 W: 12449 L: 12331 D: 25188
Ptnml(0-2): 27, 4745, 15309, 4889, 14

closes https://github.com/official-stockfish/Stockfish/pull/3792

Bench: 6339548
2021-11-15 18:20:10 +01:00
noobpwnftw 9048ac00db Fix processor group binding under Windows.
Starting with Windows Build 20348 the behavior of the numa API has been changed:
https://docs.microsoft.com/en-us/windows/win32/procthread/numa-support

Old code only worked because there was probably a limit on how many
cores/threads can reside within one NUMA node, and the OS creates extra NUMA
nodes when necessary, however the actual mechanism of core binding is
done by "Processor Groups"(https://docs.microsoft.com/en-us/windows/win32/procthread/processor-groups). With a newer OS, one NUMA node can have many
such "Processor Groups" and we should just consistently use the number
of groups to bind the threads instead of deriving the topology from
the number of NUMA nodes.

This change is required to spread threads on all cores on Windows 11 with
a 3990X CPU. It has only 1 NUMA node with 2 groups of 64 threads each.

closes https://github.com/official-stockfish/Stockfish/pull/3787

No functional change.
2021-11-15 18:19:53 +01:00
Joost VandeVondele 1a5c21dc56 Tune a few NNUE related scaling parameters
passed STC
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 102480 W: 26099 L: 25708 D: 50673
Ptnml(0-2): 282, 11637, 27003, 12044, 274
https://tests.stockfishchess.org/tests/view/618820e3d7a085ad008ef1dd

passed LTC
LLR: 2.93 (-2.94,2.94) <0.50,3.00>
Total: 165512 W: 41689 L: 41112 D: 82711
Ptnml(0-2): 82, 17255, 47510, 17822, 87
https://tests.stockfishchess.org/tests/view/6188b470d7a085ad008ef239

closes https://github.com/official-stockfish/Stockfish/pull/3784

Bench: 6339548
2021-11-11 00:56:57 +01:00
bmc4 c4a1390f4e Simplify away the Reverse Move penalty
This simplifies the penalty for reverse move introduced in
https://github.com/official-stockfish/Stockfish/pull/2294 .

STC:
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 81696 W: 20627 L: 20540 D: 40529
Ptnml(0-2): 221, 9390, 21559, 9437, 241
https://tests.stockfishchess.org/tests/view/618810acd7a085ad008ef1cc

LTC:
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 44136 W: 11021 L: 10890 D: 22225
Ptnml(0-2): 28, 4570, 12746, 4691, 33
https://tests.stockfishchess.org/tests/view/61885686d7a085ad008ef20b

closes https://github.com/official-stockfish/Stockfish/pull/3781

bench: 6547978
2021-11-08 13:14:18 +01:00
Joost VandeVondele 7b278aab9f Reduce use of lazyEval
In case the evaluation at root is large, discourage the use of lazyEval.

This fixes https://github.com/official-stockfish/Stockfish/issues/3772
or at least improves it significantly. In this case, poor play with large
odds can be observed, in extreme cases leading to a loss despite large
advantage:

r1bq1b1r/ppp3p1/3p1nkp/n3p3/2B1P2N/2NPB3/PPP2PPP/R3K2R b KQ - 5 9

With this patch the poor move is only considered up to depth 13, in master
up to depth 28.

The patch did not pass at LTC with Elo gainer bounds, but with slightly
positive Elo nevertheless (95% LOS).

STC:
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 40368 W: 10318 L: 10041 D: 20009
Ptnml(0-2): 103, 4493, 10725, 4750, 113
https://tests.stockfishchess.org/tests/view/61800ad259e71df00dcc420d

LTC:
LLR: -2.94 (-2.94,2.94) <0.50,3.00>
Total: 212288 W: 52997 L: 52692 D: 106599
Ptnml(0-2): 112, 22038, 61549, 22323, 122
https://tests.stockfishchess.org/tests/view/618050d959e71df00dcc426d

closes https://github.com/official-stockfish/Stockfish/pull/3780

Bench: 7127040
2021-11-08 13:03:52 +01:00
Stefan Geschwentner a0259d8ab9 Tweak initial aspiration window.
Maintain for each root move an exponential average of the search value with a weight ratio of 2:1 (new value vs old values). Then the average score is used as the center of the initial aspiration window instead of the previous score.

Stats indicate (see PR) that the deviation for previous score is in general greater than using average score, so later seems a better estimation of the next search value. This is probably the reason this patch succeded besides smoothing the sometimes wild swings in search score. An additional observation is that at higher depth previous score is above but average score below zero. So for average score more/less fail/low highs should be occur than previous score.

STC:
LLR: 2.97 (-2.94,2.94) <0.00,2.50>
Total: 59792 W: 15106 L: 14792 D: 29894
Ptnml(0-2): 144, 6718, 15869, 7010, 155
https://tests.stockfishchess.org/tests/view/61841612d7a085ad008eef06

LTC:
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 46448 W: 11835 L: 11537 D: 23076
Ptnml(0-2): 21, 4756, 13374, 5050, 23
https://tests.stockfishchess.org/tests/view/618463abd7a085ad008eef3e

closes https://github.com/official-stockfish/Stockfish/pull/3776

Bench: 6719976
2021-11-05 22:22:30 +01:00
Joost VandeVondele 45e5e65a28 do not store qsearch positions in TT as exact.
in qsearch don't store positions in TT with the exact flag.

passed STC:
https://tests.stockfishchess.org/tests/view/617f9a29af49befdeee40231
LLR: 2.95 (-2.94,2.94) <-2.25,0.25>
Total: 155568 W: 39003 L: 39022 D: 77543
Ptnml(0-2): 403, 17854, 41305, 17803, 419

passed LTC:
https://tests.stockfishchess.org/tests/view/6180d47259e71df00dcc42a5
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 79640 W: 19993 L: 19910 D: 39737
Ptnml(0-2): 37, 8356, 22957, 8427, 43

closes https://github.com/official-stockfish/Stockfish/pull/3775

Bench: 7531210
2021-11-05 22:20:37 +01:00
Michael Chaly c2b9134c6e Do more reductions at Pv nodes with low delta
This patch increases reduction for PvNodes that have their delta (difference between beta and alpha) significantly reduced compared to what it was at root.

passed STC
https://tests.stockfishchess.org/tests/view/617f9063af49befdeee40226
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 220840 W: 55752 L: 55150 D: 109938
Ptnml(0-2): 583, 24982, 58712, 25536, 607

passed LTC
https://tests.stockfishchess.org/tests/view/61815de959e71df00dcc42ed
LLR: 2.95 (-2.94,2.94) <0.50,3.00>
Total: 79000 W: 19937 L: 19562 D: 39501
Ptnml(0-2): 36, 8190, 22674, 8563, 37

closes https://github.com/official-stockfish/Stockfish/pull/3774

bench: 6717808
2021-11-05 22:18:59 +01:00
lonfom169 11c6cf720d More futility pruning
Expand maximum allowed eval by 50% in futility pruning, above the VALUE_KNOWN_WIN.

STC:
LLR: 2.95 (-2.94,2.94) <-0.50,2.50>
Total: 128208 W: 32534 L: 32192 D: 63482
Ptnml(0-2): 298, 13484, 36216, 13790, 316
https://tests.stockfishchess.org/tests/view/6179c069a9b1d8fbcc4ee716

LTC:
LLR: 2.96 (-2.94,2.94) <0.50,3.50>
Total: 89816 W: 22645 L: 22265 D: 44906
Ptnml(0-2): 41, 8404, 27650, 8760, 53
https://tests.stockfishchess.org/tests/view/617ad728f411ea45cc39f895

closes https://github.com/official-stockfish/Stockfish/pull/3767

bench: 6804175
2021-11-05 22:15:53 +01:00
Joost VandeVondele 5a223afe4c Restore development version
No functional change
2021-11-01 06:28:37 +01:00
xefoci7612 ef4822aa8d Simplify Skill implementation
Currently we handle the UCI_Elo with a double randomization. This
seems not necessary and a bit involuted.

This patch removes the first randomization and unifies the 2 cases.

closes https://github.com/official-stockfish/Stockfish/pull/3769

No functional change.
2021-10-31 22:43:38 +01:00
Michel Van den Bergh 0e89d6e754 Do not output to stderr during the build.
To help with debugging, the worker sends the output of
stderr (suitable truncated) to the action log on the
server, in case a build fails. For this to work it is
important that there is no spurious output to stderr.

closes https://github.com/official-stockfish/Stockfish/pull/3773

No functional change
2021-10-31 22:40:41 +01:00
Stefan Geschwentner a8330d5c3b Do more deeper LMR searches.
At expected cut nodes allow at least one ply deeper LMR search for the first seventh moves.

STC:
LLR: 2.93 (-2.94,2.94) <-0.50,2.50>
Total: 42880 W: 10964 L: 10738 D: 21178
Ptnml(0-2): 105, 4565, 11883, 4773, 114
https://tests.stockfishchess.org/tests/view/6179abd7a9b1d8fbcc4ee6f4

LTC:
LLR: 2.93 (-2.94,2.94) <0.50,3.50>
Total: 66872 W: 16930 L: 16603 D: 33339
Ptnml(0-2): 36, 6509, 20024, 6826, 41
https://tests.stockfishchess.org/tests/view/617a30fb2fbca9ca65972b5e

closes https://github.com/official-stockfish/Stockfish/pull/3770

Bench: 6295536
2021-10-31 22:31:55 +01:00
Joost VandeVondele 717d6c5ed5 Widen the aspiration window for larger evals
passed STC
LLR: 2.93 (-2.94,2.94) <-0.50,2.50>
Total: 36840 W: 9359 L: 9134 D: 18347
Ptnml(0-2): 111, 4130, 9722, 4337, 120
https://tests.stockfishchess.org/tests/view/617c601301c6d0988731d10a

passed LTC
LLR: 2.98 (-2.94,2.94) <0.50,3.50>
Total: 64824 W: 16377 L: 16043 D: 32404
Ptnml(0-2): 27, 6712, 18618, 7010, 45
https://tests.stockfishchess.org/tests/view/617c720d01c6d0988731d114

closes https://github.com/official-stockfish/Stockfish/pull/3768

Bench: 7683058
2021-10-31 22:30:01 +01:00
86 changed files with 12077 additions and 12790 deletions
+44
View File
@@ -0,0 +1,44 @@
AccessModifierOffset: -1
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: Consecutive
AlignConsecutiveDeclarations: Consecutive
AlignEscapedNewlines: DontAlign
AlignOperands: AlignAfterOperator
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortCaseLabelsOnASingleLine: false
AllowShortEnumsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: false
AlwaysBreakTemplateDeclarations: Yes
BasedOnStyle: WebKit
BitFieldColonSpacing: After
BinPackParameters: false
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeBraces: Custom
BraceWrapping:
AfterFunction: false
AfterClass: false
AfterControlStatement: true
BeforeElse: true
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: AfterColon
BreakStringLiterals: false
ColumnLimit: 100
ContinuationIndentWidth: 2
Cpp11BracedListStyle: true
IndentGotoLabels: false
IndentPPDirectives: BeforeHash
IndentWidth: 4
MaxEmptyLinesToKeep: 2
NamespaceIndentation: None
PackConstructorInitializers: Never
ReflowComments: false
SortIncludes: false
SortUsingDeclarations: false
SpaceAfterCStyleCast: true
SpaceAfterTemplateKeyword: false
SpaceBeforeCaseColon: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeInheritanceColon: false
SpaceInEmptyBlock: false
SpacesBeforeTrailingComments: 2
+7
View File
@@ -0,0 +1,7 @@
# .git-blame-ignore-revs
# Ignore commit which added clang-format
2d0237db3f0e596fb06e3ffbadba84dcc4e018f6
# Post commit formatting fixes
0fca5605fa2e5e7240fde5e1aae50952b2612231
08ed4c90db31959521b7ef3186c026edd1e90307
+65
View File
@@ -0,0 +1,65 @@
name: Report issue
description: Create a report to help us fix issues with the engine
body:
- type: textarea
attributes:
label: Describe the issue
description: A clear and concise description of what you're experiencing.
validations:
required: true
- type: textarea
attributes:
label: Expected behavior
description: A clear and concise description of what you expected to happen.
validations:
required: true
- type: textarea
attributes:
label: Steps to reproduce
description: |
Steps to reproduce the behavior.
You can also use this section to paste the command line output.
placeholder: |
```
position startpos moves g2g4 e7e5 f2f3
go mate 1
info string NNUE evaluation using nn-6877cd24400e.nnue enabled
info depth 1 seldepth 1 multipv 1 score mate 1 nodes 33 nps 11000 tbhits 0 time 3 pv d8h4
bestmove d8h4
```
validations:
required: true
- type: textarea
attributes:
label: Anything else?
description: |
Anything that will give us more context about the issue you are encountering.
You can also use this section to propose ideas on how to solve the issue.
validations:
required: false
- type: dropdown
attributes:
label: Operating system
options:
- All
- Windows
- Linux
- MacOS
- Android
- Other or N/A
validations:
required: true
- type: input
attributes:
label: Stockfish version
description: |
This can be found by running the engine.
You can also use the commit ID.
placeholder: Stockfish 15 / e6e324e
validations:
required: true
+8
View File
@@ -0,0 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Discord server
url: https://discord.gg/GWDRS3kU6R
about: Feel free to ask for support or have a chat with us on our Discord server!
- name: Discussions, Q&A, ideas, show us something...
url: https://github.com/official-stockfish/Stockfish/discussions/new
about: Do you have an idea for Stockfish? Do you want to show something that you made? Please open a discussion about it!
+51
View File
@@ -0,0 +1,51 @@
{
"config": [
{
"name": "Android NDK aarch64",
"os": "ubuntu-22.04",
"simple_name": "android",
"compiler": "aarch64-linux-android21-clang++",
"emu": "qemu-aarch64",
"comp": "ndk",
"shell": "bash",
"archive_ext": "tar"
},
{
"name": "Android NDK arm",
"os": "ubuntu-22.04",
"simple_name": "android",
"compiler": "armv7a-linux-androideabi21-clang++",
"emu": "qemu-arm",
"comp": "ndk",
"shell": "bash",
"archive_ext": "tar"
}
],
"binaries": ["armv8-dotprod", "armv8", "armv7", "armv7-neon"],
"exclude": [
{
"binaries": "armv8-dotprod",
"config": {
"compiler": "armv7a-linux-androideabi21-clang++"
}
},
{
"binaries": "armv8",
"config": {
"compiler": "armv7a-linux-androideabi21-clang++"
}
},
{
"binaries": "armv7",
"config": {
"compiler": "aarch64-linux-android21-clang++"
}
},
{
"binaries": "armv7-neon",
"config": {
"compiler": "aarch64-linux-android21-clang++"
}
}
]
}
+21
View File
@@ -0,0 +1,21 @@
[
# Mappings for libcxx's internal headers
{ include: [ "<__fwd/fstream.h>", private, "<iosfwd>", public ] },
{ include: [ "<__fwd/ios.h>", private, "<iosfwd>", public ] },
{ include: [ "<__fwd/istream.h>", private, "<iosfwd>", public ] },
{ include: [ "<__fwd/ostream.h>", private, "<iosfwd>", public ] },
{ include: [ "<__fwd/sstream.h>", private, "<iosfwd>", public ] },
{ include: [ "<__fwd/streambuf.h>", private, "<iosfwd>", public ] },
{ include: [ "<__fwd/string_view.h>", private, "<string_view>", public ] },
# Mappings for includes between public headers
{ include: [ "<ios>", public, "<iostream>", public ] },
{ include: [ "<streambuf>", public, "<iostream>", public ] },
{ include: [ "<istream>", public, "<iostream>", public ] },
{ include: [ "<ostream>", public, "<iostream>", public ] },
{ include: [ "<iosfwd>", public, "<iostream>", public ] },
# Missing mappings in include-what-you-use's libcxx.imp
{ include: ["@<__condition_variable/.*>", private, "<condition_variable>", public ] },
{ include: ["@<__mutex/.*>", private, "<mutex>", public ] },
]
+160
View File
@@ -0,0 +1,160 @@
{
"config": [
{
"name": "Ubuntu 20.04 GCC",
"os": "ubuntu-20.04",
"simple_name": "ubuntu",
"compiler": "g++",
"comp": "gcc",
"shell": "bash",
"archive_ext": "tar",
"sde": "/home/runner/work/Stockfish/Stockfish/.output/sde-temp-files/sde-external-9.27.0-2023-09-13-lin/sde -future --"
},
{
"name": "MacOS 13 Apple Clang",
"os": "macos-13",
"simple_name": "macos",
"compiler": "clang++",
"comp": "clang",
"shell": "bash",
"archive_ext": "tar"
},
{
"name": "MacOS 14 Apple Clang M1",
"os": "macos-14",
"simple_name": "macos-m1",
"compiler": "clang++",
"comp": "clang",
"shell": "bash",
"archive_ext": "tar"
},
{
"name": "Windows 2022 Mingw-w64 GCC x86_64",
"os": "windows-2022",
"simple_name": "windows",
"compiler": "g++",
"comp": "mingw",
"msys_sys": "mingw64",
"msys_env": "x86_64-gcc",
"shell": "msys2 {0}",
"ext": ".exe",
"sde": "/d/a/Stockfish/Stockfish/.output/sde-temp-files/sde-external-9.27.0-2023-09-13-win/sde.exe -future --",
"archive_ext": "zip"
}
],
"binaries": [
"x86-64",
"x86-64-sse41-popcnt",
"x86-64-avx2",
"x86-64-bmi2",
"x86-64-avxvnni",
"x86-64-avx512",
"x86-64-vnni256",
"x86-64-vnni512",
"apple-silicon"
],
"exclude": [
{
"binaries": "x86-64",
"config": {
"os": "macos-14"
}
},
{
"binaries": "x86-64-sse41-popcnt",
"config": {
"os": "macos-14"
}
},
{
"binaries": "x86-64-avx2",
"config": {
"os": "macos-14"
}
},
{
"binaries": "x86-64-bmi2",
"config": {
"os": "macos-14"
}
},
{
"binaries": "x86-64-avxvnni",
"config": {
"os": "macos-14"
}
},
{
"binaries": "x86-64-avxvnni",
"config": {
"os": "macos-14"
}
},
{
"binaries": "x86-64-avx512",
"config": {
"os": "macos-14"
}
},
{
"binaries": "x86-64-vnni256",
"config": {
"os": "macos-14"
}
},
{
"binaries": "x86-64-vnni512",
"config": {
"os": "macos-14"
}
},
{
"binaries": "x86-64-avxvnni",
"config": {
"ubuntu-20.04": null
}
},
{
"binaries": "x86-64-avxvnni",
"config": {
"os": "macos-13"
}
},
{
"binaries": "x86-64-avx512",
"config": {
"os": "macos-13"
}
},
{
"binaries": "x86-64-vnni256",
"config": {
"os": "macos-13"
}
},
{
"binaries": "x86-64-vnni512",
"config": {
"os": "macos-13"
}
},
{
"binaries": "apple-silicon",
"config": {
"os": "windows-2022"
}
},
{
"binaries": "apple-silicon",
"config": {
"os": "macos-13"
}
},
{
"binaries": "apple-silicon",
"config": {
"os": "ubuntu-20.04"
}
}
]
}
+94
View File
@@ -0,0 +1,94 @@
name: Compilation
on:
workflow_call:
inputs:
matrix:
type: string
required: true
jobs:
Compilation:
name: ${{ matrix.config.name }} ${{ matrix.binaries }}
runs-on: ${{ matrix.config.os }}
env:
COMPILER: ${{ matrix.config.compiler }}
COMP: ${{ matrix.config.comp }}
EMU: ${{ matrix.config.emu }}
EXT: ${{ matrix.config.ext }}
BINARY: ${{ matrix.binaries }}
strategy:
fail-fast: false
matrix: ${{ fromJson(inputs.matrix) }}
defaults:
run:
working-directory: src
shell: ${{ matrix.config.shell }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download required linux packages
if: runner.os == 'Linux'
run: |
sudo apt update
sudo apt install qemu-user
- name: Install NDK
if: runner.os == 'Linux'
run: |
if [ $COMP == ndk ]; then
NDKV="21.4.7075529"
ANDROID_ROOT=/usr/local/lib/android
ANDROID_SDK_ROOT=$ANDROID_ROOT/sdk
SDKMANAGER=$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager
echo "y" | $SDKMANAGER "ndk;$NDKV"
ANDROID_NDK_ROOT=$ANDROID_SDK_ROOT/ndk/$NDKV
ANDROID_NDK_BIN=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin
echo "ANDROID_NDK_BIN=$ANDROID_NDK_BIN" >> $GITHUB_ENV
fi
- name: Extract the bench number from the commit history
run: |
for hash in $(git rev-list -100 HEAD); do
benchref=$(git show -s $hash | tac | grep -m 1 -o -x '[[:space:]]*\b[Bb]ench[ :]\+[1-9][0-9]\{5,7\}\b[[:space:]]*' | sed 's/[^0-9]//g') && break || true
done
[[ -n "$benchref" ]] && echo "benchref=$benchref" >> $GITHUB_ENV && echo "From commit: $hash" && echo "Reference bench: $benchref" || echo "No bench found"
- name: Download the used network from the fishtest framework
run: make net
- name: Check compiler
run: |
if [ $COMP == ndk ]; then
export PATH=${{ env.ANDROID_NDK_BIN }}:$PATH
fi
$COMPILER -v
- name: Test help target
run: make help
- name: Check git
run: git --version
# Compile profile guided builds
- name: Compile ${{ matrix.binaries }} build
run: |
if [ $COMP == ndk ]; then
export PATH=${{ env.ANDROID_NDK_BIN }}:$PATH
export LDFLAGS="-static -Wno-unused-command-line-argument"
fi
make clean
make -j4 profile-build ARCH=$BINARY COMP=$COMP WINE_PATH=$EMU
make strip ARCH=$BINARY COMP=$COMP
WINE_PATH=$EMU ../tests/signature.sh $benchref
mv ./stockfish$EXT ../stockfish-android-$BINARY$EXT
- name: Remove non src files
run: git clean -fx
- name: Upload artifact for (pre)-release
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.config.simple_name }} ${{ matrix.binaries }}
path: .
+51
View File
@@ -0,0 +1,51 @@
# This workflow will run clang-format and comment on the PR.
# Because of security reasons, it is crucial that this workflow
# executes no shell script nor runs make.
# Read this before editing: https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
name: Clang-Format
on:
pull_request_target:
branches:
- "master"
paths:
- "**.cpp"
- "**.h"
jobs:
Clang-Format:
name: Clang-Format
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Run clang-format style check
uses: jidicula/clang-format-action@f62da5e3d3a2d88ff364771d9d938773a618ab5e # @v4.11.0
id: clang-format
continue-on-error: true
with:
clang-format-version: "17"
exclude-regex: "incbin"
- name: Comment on PR
if: steps.clang-format.outcome == 'failure'
uses: thollander/actions-comment-pull-request@1d3973dc4b8e1399c0620d3f2b1aa5e795465308 # @v2.4.3
with:
message: |
clang-format 17 needs to be run on this PR.
If you do not have clang-format installed, the maintainer will run it when merging.
For the exact version please see https://packages.ubuntu.com/mantic/clang-format-17.
_(execution **${{ github.run_id }}** / attempt **${{ github.run_attempt }}**)_
comment_tag: execution
- name: Comment on PR
if: steps.clang-format.outcome != 'failure'
uses: thollander/actions-comment-pull-request@1d3973dc4b8e1399c0620d3f2b1aa5e795465308 # @v2.4.3
with:
message: |
_(execution **${{ github.run_id }}** / attempt **${{ github.run_attempt }}**)_
create_if_not_exists: false
comment_tag: execution
mode: delete
+53
View File
@@ -0,0 +1,53 @@
name: "CodeQL"
on:
push:
branches: ["master"]
pull_request:
# The branches below must be a subset of the branches above
branches: ["master"]
schedule:
- cron: "17 18 * * 1"
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: ["cpp"]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Use only 'java' to analyze code written in Java, Kotlin, or both
# Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
- name: Build
working-directory: src
run: make -j build ARCH=x86-64-modern
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"
+89
View File
@@ -0,0 +1,89 @@
name: Compilation
on:
workflow_call:
inputs:
matrix:
type: string
required: true
jobs:
Compilation:
name: ${{ matrix.config.name }} ${{ matrix.binaries }}
runs-on: ${{ matrix.config.os }}
env:
COMPILER: ${{ matrix.config.compiler }}
COMP: ${{ matrix.config.comp }}
EXT: ${{ matrix.config.ext }}
NAME: ${{ matrix.config.simple_name }}
BINARY: ${{ matrix.binaries }}
SDE: ${{ matrix.config.sde }}
strategy:
fail-fast: false
matrix: ${{ fromJson(inputs.matrix) }}
defaults:
run:
working-directory: src
shell: ${{ matrix.config.shell }}
steps:
- uses: actions/checkout@v4
- name: Install fixed GCC on Linux
if: runner.os == 'Linux'
uses: egor-tensin/setup-gcc@eaa888eb19115a521fa72b65cd94fe1f25bbcaac # @v1.3
with:
version: 11
- name: Setup msys and install required packages
if: runner.os == 'Windows'
uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.config.msys_sys }}
install: mingw-w64-${{ matrix.config.msys_env }} make git zip
- name: Download SDE package
if: runner.os == 'Linux' || runner.os == 'Windows'
uses: petarpetrovt/setup-sde@91a1a03434384e064706634125a15f7446d2aafb # @v2.3
with:
environmentVariableName: SDE_DIR
sdeVersion: 9.27.0
- name: Download the used network from the fishtest framework
run: make net
- name: Check compiler
run: $COMPILER -v
- name: Test help target
run: make help
- name: Check git
run: git --version
- name: Check compiler
run: $COMPILER -v
- name: Show g++ cpu info
if: runner.os != 'macOS'
run: g++ -Q -march=native --help=target
- name: Show clang++ cpu info
if: runner.os == 'macOS'
run: clang++ -E - -march=native -###
# x86-64 with newer extensions tests
- name: Compile ${{ matrix.config.binaries }} build
run: |
make clean
make -j4 profile-build ARCH=$BINARY COMP=$COMP WINE_PATH="$SDE"
make strip ARCH=$BINARY COMP=$COMP
WINE_PATH="$SDE" ../tests/signature.sh $benchref
mv ./stockfish$EXT ../stockfish-$NAME-$BINARY$EXT
- name: Remove non src files
run: git clean -fx
- name: Upload artifact for (pre)-release
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.config.simple_name }} ${{ matrix.binaries }}
path: .
+47
View File
@@ -0,0 +1,47 @@
name: IWYU
on:
workflow_call:
jobs:
Analyzers:
name: Check includes
runs-on: ubuntu-22.04
defaults:
run:
working-directory: Stockfish/src
shell: bash
steps:
- name: Checkout Stockfish
uses: actions/checkout@v4
with:
path: Stockfish
- name: Checkout include-what-you-use
uses: actions/checkout@v4
with:
repository: include-what-you-use/include-what-you-use
ref: f25caa280dc3277c4086ec345ad279a2463fea0f
path: include-what-you-use
- name: Download required linux packages
run: |
sudo add-apt-repository 'deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-17 main'
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
sudo apt update
sudo apt install -y libclang-17-dev clang-17 libc++-17-dev
- name: Set up include-what-you-use
run: |
mkdir build && cd build
cmake -G "Unix Makefiles" -DCMAKE_PREFIX_PATH="/usr/lib/llvm-17" ..
sudo make install
working-directory: include-what-you-use
- name: Check include-what-you-use
run: include-what-you-use --version
- name: Check includes
run: >
make analyze
COMP=clang
CXX=include-what-you-use
CXXFLAGS="-stdlib=libc++ -Xiwyu --comment_style=long -Xiwyu --mapping='${{ github.workspace }}/Stockfish/.github/ci/libcxx17.imp' -Xiwyu --error"
+65
View File
@@ -0,0 +1,65 @@
name: Sanitizers
on:
workflow_call:
jobs:
Test-under-sanitizers:
name: ${{ matrix.sanitizers.name }}
runs-on: ${{ matrix.config.os }}
env:
COMPILER: ${{ matrix.config.compiler }}
COMP: ${{ matrix.config.comp }}
CXXFLAGS: "-Werror"
strategy:
fail-fast: false
matrix:
config:
- name: Ubuntu 22.04 GCC
os: ubuntu-22.04
compiler: g++
comp: gcc
shell: bash
sanitizers:
- name: Run with thread sanitizer
make_option: sanitize=thread
instrumented_option: sanitizer-thread
- name: Run with UB sanitizer
make_option: sanitize=undefined
instrumented_option: sanitizer-undefined
- name: Run under valgrind
make_option: ""
instrumented_option: valgrind
- name: Run under valgrind-thread
make_option: ""
instrumented_option: valgrind-thread
defaults:
run:
working-directory: src
shell: ${{ matrix.config.shell }}
steps:
- uses: actions/checkout@v4
- name: Download required linux packages
run: |
sudo apt update
sudo apt install expect valgrind g++-multilib
- name: Download the used network from the fishtest framework
run: make net
- name: Check compiler
run: $COMPILER -v
- name: Test help target
run: make help
- name: Check git
run: git --version
# Sanitizers
- name: ${{ matrix.sanitizers.name }}
run: |
export CXXFLAGS="-O1 -fno-inline"
make clean
make -j4 ARCH=x86-64-sse41-popcnt ${{ matrix.sanitizers.make_option }} debug=yes optimize=no build > /dev/null
../tests/instrumented.sh --${{ matrix.sanitizers.instrumented_option }}
+58 -259
View File
@@ -1,6 +1,8 @@
name: Stockfish
on:
push:
tags:
- "*"
branches:
- master
- tools
@@ -10,268 +12,65 @@ on:
- master
- tools
jobs:
Stockfish:
name: ${{ matrix.config.name }}
runs-on: ${{ matrix.config.os }}
env:
COMPILER: ${{ matrix.config.compiler }}
COMP: ${{ matrix.config.comp }}
CXXFLAGS: "-Werror"
strategy:
matrix:
config:
- {
name: "Ubuntu 20.04 GCC",
os: ubuntu-20.04,
compiler: g++,
comp: gcc,
run_expensive_tests: true,
run_32bit_tests: true,
run_64bit_tests: true,
shell: 'bash {0}'
}
- {
name: "Ubuntu 20.04 Clang",
os: ubuntu-20.04,
compiler: clang++,
comp: clang,
run_expensive_tests: false,
run_32bit_tests: true,
run_64bit_tests: true,
shell: 'bash {0}'
}
- {
name: "MacOS 10.15 Apple Clang",
os: macos-10.15,
compiler: clang++,
comp: clang,
run_expensive_tests: false,
run_32bit_tests: false,
run_64bit_tests: true,
shell: 'bash {0}'
}
- {
name: "MacOS 10.15 GCC 10",
os: macos-10.15,
compiler: g++-10,
comp: gcc,
run_expensive_tests: false,
run_32bit_tests: false,
run_64bit_tests: true,
shell: 'bash {0}'
}
- {
name: "Windows 2019 Mingw-w64 GCC x86_64",
os: windows-2019,
compiler: g++,
comp: gcc,
run_expensive_tests: false,
run_32bit_tests: false,
run_64bit_tests: true,
msys_sys: 'mingw64',
msys_env: 'x86_64',
shell: 'msys2 {0}'
}
- {
name: "Windows 2019 Mingw-w64 GCC i686",
os: windows-2019,
compiler: g++,
comp: gcc,
run_expensive_tests: false,
run_32bit_tests: true,
run_64bit_tests: false,
msys_sys: 'mingw32',
msys_env: 'i686',
shell: 'msys2 {0}'
}
defaults:
run:
working-directory: src
shell: ${{ matrix.config.shell }}
Prerelease:
if: github.repository == 'official-stockfish/Stockfish' && (github.ref == 'refs/heads/master' || (startsWith(github.ref_name, 'sf_') && github.ref_type == 'tag'))
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Download required linux packages
if: runner.os == 'Linux'
# returns null if no pre-release exists
- name: Get Commit SHA of Latest Pre-release
run: |
sudo apt update
sudo apt install expect valgrind g++-multilib
# Install required packages
sudo apt-get update
sudo apt-get install -y curl jq
- name: Setup msys and install required packages
if: runner.os == 'Windows'
uses: msys2/setup-msys2@v2
with:
msystem: ${{matrix.config.msys_sys}}
install: mingw-w64-${{matrix.config.msys_env}}-gcc make git expect
echo "COMMIT_SHA=$(jq -r 'map(select(.prerelease)) | first | .tag_name' <<< $(curl -s https://api.github.com/repos/${{ github.repository_owner }}/Stockfish/releases))" >> $GITHUB_ENV
- name: Download the used network from the fishtest framework
# delete old previous pre-release and tag
- uses: actions/checkout@v4
- run: gh release delete ${{ env.COMMIT_SHA }} --cleanup-tag
if: env.COMMIT_SHA != 'null'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Matrix:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
arm_matrix: ${{ steps.set-arm-matrix.outputs.arm_matrix }}
steps:
- uses: actions/checkout@v4
- id: set-matrix
run: |
make net
- name: Extract the bench number from the commit history
TASKS=$(echo $(cat .github/ci/matrix.json) )
echo "MATRIX=$TASKS" >> $GITHUB_OUTPUT
- id: set-arm-matrix
run: |
git log HEAD | grep "\b[Bb]ench[ :]\+[0-9]\{7\}" | head -n 1 | sed "s/[^0-9]*\([0-9]*\).*/\1/g" > git_sig
[ -s git_sig ] && echo "benchref=$(cat git_sig)" >> $GITHUB_ENV && echo "Reference bench:" $(cat git_sig) || echo "No bench found"
- name: Check compiler
run: |
$COMPILER -v
- name: Test help target
run: |
make help
# x86-32 tests
- name: Test debug x86-32 build
if: ${{ matrix.config.run_32bit_tests }}
run: |
export CXXFLAGS="-Werror -D_GLIBCXX_DEBUG"
make clean
make -j2 ARCH=x86-32 optimize=no debug=yes build
../tests/signature.sh $benchref
- name: Test x86-32 build
if: ${{ matrix.config.run_32bit_tests }}
run: |
make clean
make -j2 ARCH=x86-32 build
../tests/signature.sh $benchref
- name: Test x86-32-sse41-popcnt build
if: ${{ matrix.config.run_32bit_tests }}
run: |
make clean
make -j2 ARCH=x86-32-sse41-popcnt build
../tests/signature.sh $benchref
- name: Test x86-32-sse2 build
if: ${{ matrix.config.run_32bit_tests }}
run: |
make clean
make -j2 ARCH=x86-32-sse2 build
../tests/signature.sh $benchref
- name: Test general-32 build
if: ${{ matrix.config.run_32bit_tests }}
run: |
make clean
make -j2 ARCH=general-32 build
../tests/signature.sh $benchref
# x86-64 tests
- name: Test debug x86-64-modern build
if: ${{ matrix.config.run_64bit_tests }}
run: |
export CXXFLAGS="-Werror -D_GLIBCXX_DEBUG"
make clean
make -j2 ARCH=x86-64-modern optimize=no debug=yes build
../tests/signature.sh $benchref
- name: Test x86-64-modern build
if: ${{ matrix.config.run_64bit_tests }}
run: |
make clean
make -j2 ARCH=x86-64-modern build
../tests/signature.sh $benchref
- name: Test x86-64-ssse3 build
if: ${{ matrix.config.run_64bit_tests }}
run: |
make clean
make -j2 ARCH=x86-64-ssse3 build
../tests/signature.sh $benchref
- name: Test x86-64-sse3-popcnt build
if: ${{ matrix.config.run_64bit_tests }}
run: |
make clean
make -j2 ARCH=x86-64-sse3-popcnt build
../tests/signature.sh $benchref
- name: Test x86-64 build
if: ${{ matrix.config.run_64bit_tests }}
run: |
make clean
make -j2 ARCH=x86-64 build
../tests/signature.sh $benchref
- name: Test general-64 build
if: matrix.config.run_64bit_tests
run: |
make clean
make -j2 ARCH=general-64 build
../tests/signature.sh $benchref
# x86-64 with newer extensions tests
- name: Compile x86-64-avx2 build
if: ${{ matrix.config.run_64bit_tests }}
run: |
make clean
make -j2 ARCH=x86-64-avx2 build
- name: Compile x86-64-bmi2 build
if: ${{ matrix.config.run_64bit_tests }}
run: |
make clean
make -j2 ARCH=x86-64-bmi2 build
- name: Compile x86-64-avx512 build
if: ${{ matrix.config.run_64bit_tests }}
run: |
make clean
make -j2 ARCH=x86-64-avx512 build
- name: Compile x86-64-vnni512 build
if: ${{ matrix.config.run_64bit_tests }}
run: |
make clean
make -j2 ARCH=x86-64-vnni512 build
- name: Compile x86-64-vnni256 build
if: ${{ matrix.config.run_64bit_tests }}
run: |
make clean
make -j2 ARCH=x86-64-vnni256 build
# Other tests
- name: Check perft and search reproducibility
if: ${{ matrix.config.run_64bit_tests }}
run: |
make clean
make -j2 ARCH=x86-64-modern build
../tests/perft.sh
../tests/reprosearch.sh
# Sanitizers
- name: Run under valgrind
if: ${{ matrix.config.run_expensive_tests }}
run: |
export CXXFLAGS="-O1 -fno-inline"
make clean
make -j2 ARCH=x86-64-modern debug=yes optimize=no build > /dev/null
../tests/instrumented.sh --valgrind
../tests/instrumented.sh --valgrind-thread
- name: Run with UB sanitizer
if: ${{ matrix.config.run_expensive_tests }}
run: |
export CXXFLAGS="-O1 -fno-inline"
make clean
make -j2 ARCH=x86-64-modern sanitize=undefined optimize=no debug=yes build > /dev/null
../tests/instrumented.sh --sanitizer-undefined
- name: Run with thread sanitizer
if: ${{ matrix.config.run_expensive_tests }}
run: |
export CXXFLAGS="-O1 -fno-inline"
make clean
make -j2 ARCH=x86-64-modern sanitize=thread optimize=no debug=yes build > /dev/null
../tests/instrumented.sh --sanitizer-thread
TASKS_ARM=$(echo $(cat .github/ci/arm_matrix.json) )
echo "ARM_MATRIX=$TASKS_ARM" >> $GITHUB_OUTPUT
Compilation:
needs: [Matrix]
uses: ./.github/workflows/compilation.yml
with:
matrix: ${{ needs.Matrix.outputs.matrix }}
ARMCompilation:
needs: [Matrix]
uses: ./.github/workflows/arm_compilation.yml
with:
matrix: ${{ needs.Matrix.outputs.arm_matrix }}
IWYU:
uses: ./.github/workflows/iwyu.yml
Sanitizers:
uses: ./.github/workflows/sanitizers.yml
Tests:
uses: ./.github/workflows/tests.yml
Binaries:
if: github.repository == 'official-stockfish/Stockfish'
needs: [Matrix, Prerelease, Compilation]
uses: ./.github/workflows/upload_binaries.yml
with:
matrix: ${{ needs.Matrix.outputs.matrix }}
ARM_Binaries:
if: github.repository == 'official-stockfish/Stockfish'
needs: [Matrix, Prerelease, ARMCompilation]
uses: ./.github/workflows/upload_binaries.yml
with:
matrix: ${{ needs.Matrix.outputs.arm_matrix }}
+365
View File
@@ -0,0 +1,365 @@
name: Tests
on:
workflow_call:
jobs:
Test-Targets:
name: ${{ matrix.config.name }}
runs-on: ${{ matrix.config.os }}
env:
COMPILER: ${{ matrix.config.compiler }}
COMP: ${{ matrix.config.comp }}
CXXFLAGS: "-Werror"
strategy:
fail-fast: false
matrix:
config:
- name: Ubuntu 20.04 GCC
os: ubuntu-20.04
compiler: g++
comp: gcc
run_32bit_tests: true
run_64bit_tests: true
shell: bash
- name: Ubuntu 20.04 Clang
os: ubuntu-20.04
compiler: clang++
comp: clang
run_32bit_tests: true
run_64bit_tests: true
shell: bash
- name: Android NDK aarch64
os: ubuntu-22.04
compiler: aarch64-linux-android21-clang++
comp: ndk
run_armv8_tests: true
shell: bash
- name: Android NDK arm
os: ubuntu-22.04
compiler: armv7a-linux-androideabi21-clang++
comp: ndk
run_armv7_tests: true
shell: bash
- name: Linux GCC riscv64
os: ubuntu-22.04
compiler: g++
comp: gcc
run_riscv64_tests: true
base_image: "riscv64/alpine:edge"
platform: linux/riscv64
shell: bash
- name: Linux GCC ppc64
os: ubuntu-22.04
compiler: g++
comp: gcc
run_ppc64_tests: true
base_image: "ppc64le/alpine:latest"
platform: linux/ppc64le
shell: bash
- name: MacOS 13 Apple Clang
os: macos-13
compiler: clang++
comp: clang
run_64bit_tests: true
shell: bash
- name: MacOS 14 Apple Clang M1
os: macos-14
compiler: clang++
comp: clang
run_64bit_tests: false
run_m1_tests: true
shell: bash
- name: MacOS 13 GCC 11
os: macos-13
compiler: g++-11
comp: gcc
run_64bit_tests: true
shell: bash
- name: Windows 2022 Mingw-w64 GCC x86_64
os: windows-2022
compiler: g++
comp: mingw
run_64bit_tests: true
msys_sys: mingw64
msys_env: x86_64-gcc
shell: msys2 {0}
- name: Windows 2022 Mingw-w64 GCC i686
os: windows-2022
compiler: g++
comp: mingw
run_32bit_tests: true
msys_sys: mingw32
msys_env: i686-gcc
shell: msys2 {0}
- name: Windows 2022 Mingw-w64 Clang x86_64
os: windows-2022
compiler: clang++
comp: clang
run_64bit_tests: true
msys_sys: clang64
msys_env: clang-x86_64-clang
shell: msys2 {0}
defaults:
run:
working-directory: src
shell: ${{ matrix.config.shell }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download required linux packages
if: runner.os == 'Linux'
run: |
sudo apt update
sudo apt install expect valgrind g++-multilib qemu-user-static
- name: Install NDK
if: runner.os == 'Linux'
run: |
if [ $COMP == ndk ]; then
NDKV="21.4.7075529"
ANDROID_ROOT=/usr/local/lib/android
ANDROID_SDK_ROOT=$ANDROID_ROOT/sdk
SDKMANAGER=$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager
echo "y" | $SDKMANAGER "ndk;$NDKV"
ANDROID_NDK_ROOT=$ANDROID_SDK_ROOT/ndk/$NDKV
ANDROID_NDK_BIN=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin
echo "ANDROID_NDK_BIN=$ANDROID_NDK_BIN" >> $GITHUB_ENV
fi
- name: Set up QEMU
if: matrix.config.base_image
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
if: matrix.config.base_image
uses: docker/setup-buildx-action@v3
- name: Build Docker container
if: matrix.config.base_image
run: |
docker buildx build --load -t sf_builder - << EOF
FROM ${{ matrix.config.base_image }}
WORKDIR /app
RUN apk update && apk add make g++
CMD ["sh", "script.sh"]
EOF
- name: Download required macOS packages
if: runner.os == 'macOS'
run: brew install coreutils
- name: Setup msys and install required packages
if: runner.os == 'Windows'
uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.config.msys_sys }}
install: mingw-w64-${{ matrix.config.msys_env }} make git expect
- name: Download the used network from the fishtest framework
run: make net
- name: Extract the bench number from the commit history
run: |
for hash in $(git rev-list -100 HEAD); do
benchref=$(git show -s $hash | tac | grep -m 1 -o -x '[[:space:]]*\b[Bb]ench[ :]\+[1-9][0-9]\{5,7\}\b[[:space:]]*' | sed 's/[^0-9]//g') && break || true
done
[[ -n "$benchref" ]] && echo "benchref=$benchref" >> $GITHUB_ENV && echo "From commit: $hash" && echo "Reference bench: $benchref" || echo "No bench found"
- name: Check compiler
run: |
if [ -z "${{ matrix.config.base_image }}" ]; then
if [ $COMP == ndk ]; then
export PATH=${{ env.ANDROID_NDK_BIN }}:$PATH
fi
$COMPILER -v
else
echo "$COMPILER -v" > script.sh
docker run --rm --platform ${{ matrix.config.platform }} -v ${{ github.workspace }}/src:/app sf_builder
fi
- name: Test help target
run: make help
- name: Check git
run: git --version
# x86-32 tests
- name: Test debug x86-32 build
if: matrix.config.run_32bit_tests
run: |
export CXXFLAGS="-Werror -D_GLIBCXX_DEBUG"
make clean
make -j4 ARCH=x86-32 optimize=no debug=yes build
../tests/signature.sh $benchref
- name: Test x86-32 build
if: matrix.config.run_32bit_tests
run: |
make clean
make -j4 ARCH=x86-32 build
../tests/signature.sh $benchref
- name: Test x86-32-sse41-popcnt build
if: matrix.config.run_32bit_tests
run: |
make clean
make -j4 ARCH=x86-32-sse41-popcnt build
../tests/signature.sh $benchref
- name: Test x86-32-sse2 build
if: matrix.config.run_32bit_tests
run: |
make clean
make -j4 ARCH=x86-32-sse2 build
../tests/signature.sh $benchref
- name: Test general-32 build
if: matrix.config.run_32bit_tests
run: |
make clean
make -j4 ARCH=general-32 build
../tests/signature.sh $benchref
# x86-64 tests
- name: Test debug x86-64-avx2 build
if: matrix.config.run_64bit_tests
run: |
export CXXFLAGS="-Werror -D_GLIBCXX_DEBUG"
make clean
make -j4 ARCH=x86-64-avx2 optimize=no debug=yes build
../tests/signature.sh $benchref
- name: Test x86-64-bmi2 build
if: matrix.config.run_64bit_tests
run: |
make clean
make -j4 ARCH=x86-64-bmi2 build
../tests/signature.sh $benchref
- name: Test x86-64-avx2 build
if: matrix.config.run_64bit_tests
run: |
make clean
make -j4 ARCH=x86-64-avx2 build
../tests/signature.sh $benchref
# Test a deprecated arch
- name: Test x86-64-modern build
if: matrix.config.run_64bit_tests
run: |
make clean
make -j4 ARCH=x86-64-modern build
../tests/signature.sh $benchref
- name: Test x86-64-sse41-popcnt build
if: matrix.config.run_64bit_tests
run: |
make clean
make -j4 ARCH=x86-64-sse41-popcnt build
../tests/signature.sh $benchref
- name: Test x86-64-ssse3 build
if: matrix.config.run_64bit_tests
run: |
make clean
make -j4 ARCH=x86-64-ssse3 build
../tests/signature.sh $benchref
- name: Test x86-64-sse3-popcnt build
if: matrix.config.run_64bit_tests
run: |
make clean
make -j4 ARCH=x86-64-sse3-popcnt build
../tests/signature.sh $benchref
- name: Test x86-64 build
if: matrix.config.run_64bit_tests
run: |
make clean
make -j4 ARCH=x86-64 build
../tests/signature.sh $benchref
- name: Test general-64 build
if: matrix.config.run_64bit_tests
run: |
make clean
make -j4 ARCH=general-64 build
../tests/signature.sh $benchref
- name: Test apple-silicon build
if: matrix.config.run_m1_tests
run: |
make clean
make -j4 ARCH=apple-silicon build
../tests/signature.sh $benchref
# armv8 tests
- name: Test armv8 build
if: matrix.config.run_armv8_tests
run: |
export PATH=${{ env.ANDROID_NDK_BIN }}:$PATH
export LDFLAGS="-static -Wno-unused-command-line-argument"
make clean
make -j4 ARCH=armv8 build
../tests/signature.sh $benchref
- name: Test armv8-dotprod build
if: matrix.config.run_armv8_tests
run: |
export PATH=${{ env.ANDROID_NDK_BIN }}:$PATH
export LDFLAGS="-static -Wno-unused-command-line-argument"
make clean
make -j4 ARCH=armv8-dotprod build
../tests/signature.sh $benchref
# armv7 tests
- name: Test armv7 build
if: matrix.config.run_armv7_tests
run: |
export PATH=${{ env.ANDROID_NDK_BIN }}:$PATH
export LDFLAGS="-static -Wno-unused-command-line-argument"
make clean
make -j4 ARCH=armv7 build
../tests/signature.sh $benchref
- name: Test armv7-neon build
if: matrix.config.run_armv7_tests
run: |
export PATH=${{ env.ANDROID_NDK_BIN }}:$PATH
export LDFLAGS="-static -Wno-unused-command-line-argument"
make clean
make -j4 ARCH=armv7-neon build
../tests/signature.sh $benchref
# riscv64 tests
- name: Test riscv64 build
if: matrix.config.run_riscv64_tests
run: |
echo "export LDFLAGS='-static' && make clean && make -j4 ARCH=riscv64 build" > script.sh
docker run --rm --platform ${{ matrix.config.platform }} -v ${{ github.workspace }}/src:/app sf_builder
../tests/signature.sh $benchref
# ppc64 tests
- name: Test ppc64 build
if: matrix.config.run_ppc64_tests
run: |
echo "export LDFLAGS='-static' && make clean && make -j4 ARCH=ppc-64 build" > script.sh
docker run --rm --platform ${{ matrix.config.platform }} -v ${{ github.workspace }}/src:/app sf_builder
../tests/signature.sh $benchref
# Other tests
- name: Check perft and search reproducibility
if: matrix.config.run_64bit_tests
run: |
make clean
make -j4 ARCH=x86-64-avx2 build
../tests/perft.sh
../tests/reprosearch.sh
+105
View File
@@ -0,0 +1,105 @@
name: Upload Binaries
on:
workflow_call:
inputs:
matrix:
type: string
required: true
jobs:
Artifacts:
name: ${{ matrix.config.name }} ${{ matrix.binaries }}
runs-on: ${{ matrix.config.os }}
env:
COMPILER: ${{ matrix.config.compiler }}
COMP: ${{ matrix.config.comp }}
EXT: ${{ matrix.config.ext }}
NAME: ${{ matrix.config.simple_name }}
BINARY: ${{ matrix.binaries }}
SDE: ${{ matrix.config.sde }}
strategy:
fail-fast: false
matrix: ${{ fromJson(inputs.matrix) }}
defaults:
run:
shell: ${{ matrix.config.shell }}
steps:
- uses: actions/checkout@v4
- name: Download artifact from compilation
uses: actions/download-artifact@v4
with:
name: ${{ matrix.config.simple_name }} ${{ matrix.binaries }}
path: ${{ matrix.config.simple_name }} ${{ matrix.binaries }}
- name: Setup msys and install required packages
if: runner.os == 'Windows'
uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.config.msys_sys }}
install: mingw-w64-${{ matrix.config.msys_env }} make git zip
- name: Create Package
run: |
mkdir stockfish
- name: Download wiki
run: |
git clone https://github.com/official-stockfish/Stockfish.wiki.git wiki
rm -rf wiki/.git
mv wiki stockfish/
- name: Copy files
run: |
mv "${{ matrix.config.simple_name }} ${{ matrix.binaries }}" stockfish-workflow
cd stockfish-workflow
cp -r src ../stockfish/
cp stockfish-$NAME-$BINARY$EXT ../stockfish/
cp "Top CPU Contributors.txt" ../stockfish/
cp Copying.txt ../stockfish/
cp AUTHORS ../stockfish/
cp CITATION.cff ../stockfish/
cp README.md ../stockfish/
cp CONTRIBUTING.md ../stockfish/
- name: Create tar
if: runner.os != 'Windows'
run: |
tar -cvf stockfish-$NAME-$BINARY.tar stockfish
- name: Create zip
if: runner.os == 'Windows'
run: |
zip -r stockfish-$NAME-$BINARY.zip stockfish
- name: Release
if: startsWith(github.ref_name, 'sf_') && github.ref_type == 'tag'
uses: softprops/action-gh-release@4634c16e79c963813287e889244c50009e7f0981
with:
files: stockfish-${{ matrix.config.simple_name }}-${{ matrix.binaries }}.${{ matrix.config.archive_ext }}
- name: Get last commit sha
id: last_commit
run: echo "COMMIT_SHA=$(git rev-parse HEAD | cut -c 1-8)" >> $GITHUB_ENV
- name: Get commit date
id: commit_date
run: echo "COMMIT_DATE=$(git show -s --date=format:'%Y%m%d' --format=%cd HEAD)" >> $GITHUB_ENV
# Make sure that an old ci that still runs on master doesn't recreate a prerelease
- name: Check Pullable Commits
id: check_commits
run: |
git fetch
CHANGES=$(git rev-list HEAD..origin/master --count)
echo "CHANGES=$CHANGES" >> $GITHUB_ENV
- name: Prerelease
if: github.ref_name == 'master' && env.CHANGES == '0'
continue-on-error: true
uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # @v1
with:
name: Stockfish dev-${{ env.COMMIT_DATE }}-${{ env.COMMIT_SHA }}
tag_name: stockfish-dev-${{ env.COMMIT_DATE }}-${{ env.COMMIT_SHA }}
prerelease: true
files: stockfish-${{ matrix.config.simple_name }}-${{ matrix.binaries }}.${{ matrix.config.archive_ext }}
+62 -24
View File
@@ -1,19 +1,18 @@
# List of authors for Stockfish
# Founders of the Stockfish project and fishtest infrastructure
# Founders of the Stockfish project and Fishtest infrastructure
Tord Romstad (romstad)
Marco Costalba (mcostalba)
Joona Kiiski (zamar)
Gary Linscott (glinscott)
# Authors and inventors of NNUE, training, NNUE port
# Authors and inventors of NNUE, training, and NNUE port
Yu Nasu (ynasu87)
Motohiro Isozaki (yaneurao)
Hisayori Noda (nodchip)
# all other authors of the code in alphabetical order
# All other authors of Stockfish code (in alphabetical order)
Aditya (absimaldata)
Adrian Petrescu (apetresc)
Ahmed Kerimov (wcdbmv)
Ajith Chandy Jose (ajithcj)
Alain Savard (Rocky640)
Alayan Feh (Alayan-stk-2)
@@ -21,6 +20,7 @@ Alexander Kure
Alexander Pagel (Lolligerhans)
Alfredo Menezes (lonfom169)
Ali AlZhrani (Cooffe)
Andreas Matthies (Matthies)
Andrei Vetrov (proukornew)
Andrew Grant (AndyGrant)
Andrey Neporada (nepal)
@@ -30,22 +30,32 @@ Aram Tumanian (atumanian)
Arjun Temurnikar
Artem Solopiy (EntityFX)
Auguste Pop
Balazs Szilagyi
Balint Pfliegel
Ben Chaney (Chaneybenjamini)
Ben Koshy (BKSpurgeon)
Bill Henry (VoyagerOne)
Bojun Guo (noobpwnftw, Nooby)
borg323
Boštjan Mejak (PedanticHacker)
braich
Brian Sheppard (SapphireBrand, briansheppard-toast)
Bruno de Melo Costa (BM123499)
Bruno Pellanda (pellanda)
Bryan Cross (crossbr)
candirufish
Chess13234
Chris Cain (ceebo)
clefrks
Clemens L. (rn5f107s2)
Cody Ho (aesrentai)
Dale Weiler (graphitemaster)
Dan Schmidt (dfannius)
Daniel Axtens (daxtens)
Daniel Dugovic (ddugovic)
Daniel Monroe (Ergodice)
Dan Schmidt (dfannius)
Dariusz Orzechowski (dorzechowski)
David (dav1312)
David Zar
Daylen Yang (daylen)
Deshawn Mohan-Smith (GoldenRare)
@@ -54,55 +64,62 @@ DiscanX
Dominik Schlösser (domschl)
double-beep
Douglas Matos Gomes (dsmsgms)
Dubslow
Eduardo Cáceres (eduherminio)
Eelco de Groot (KingDefender)
Elvin Liu (solarlight2)
erbsenzaehler
Ernesto Gatti
Linmiao Xu (linrock)
Fabian Beuke (madnight)
Fabian Fichter (ianfab)
Fanael Linithien (Fanael)
fanon
Fauzi Akram Dabat (FauziAkram)
Fauzi Akram Dabat (fauzi2)
Felix Wittmann
gamander
Gabriele Lombardo (gabe)
Gahtan Nahdi
Gary Heckman (gheckman)
George Sobala (gsobala)
gguliash
Giacomo Lorenzetti (G-Lorenz)
Gian-Carlo Pascutto (gcp)
Goh CJ (cj5716)
Gontran Lemaire (gonlem)
Goodkov Vasiliy Aleksandrovich (goodkov)
Gregor Cramer
GuardianRM
Günther Demetz (pb00067, pb00068)
Guy Vreuls (gvreuls)
Günther Demetz (pb00067, pb00068)
Henri Wiechers
Hiraoka Takuya (HiraokaTakuya)
homoSapiensSapiens
Hongzhi Cheng
Ivan Ivec (IIvec)
Jacques B. (Timshel)
Jake Senne (w1wwwwww)
Jan Ondruš (hxim)
Jared Kish (Kurtbusch)
Jared Kish (Kurtbusch, kurt22i)
Jarrod Torriero (DU-jdto)
Jean Gauthier (OuaisBla)
Jasper Shovelton (Beanie496)
Jean-Francois Romang (jromang)
Jean Gauthier (OuaisBla)
Jekaa
Jerry Donald Watson (jerrydonaldwatson)
jjoshua2
Jonathan Calovski (Mysseno)
Jonathan Buladas Dumale (SFisGOD)
Jonathan Calovski (Mysseno)
Jonathan McDermid (jonathanmcdermid)
Joost VandeVondele (vondele)
Jörg Oster (joergoster)
Joseph Ellis (jhellis3)
Joseph R. Prostko
Jörg Oster (joergoster)
Julian Willemer (NightlyKing)
jundery
Justin Blanchard (UncombedCoconut)
Kelly Wilson
Ken Takusagawa
Kian E (KJE-98)
kinderchocolate
Kiran Panditrao (Krgp)
Kojirion
@@ -110,6 +127,7 @@ Krystian Kuzniarek (kuzkry)
Leonardo Ljubičić (ICCF World Champion)
Leonid Pechenik (lp--)
Liam Keegan (lkeegan)
Linmiao Xu (linrock)
Linus Arver (listx)
loco-loco
Lub van den Berg (ElbertoOne)
@@ -123,6 +141,8 @@ marotear
Matt Ginsberg (mattginsberg)
Matthew Lai (matthewlai)
Matthew Sullivan (Matt14916)
Max A. (Disservin)
Maxim Masiutin (maximmasiutin)
Maxim Molchanov (Maxim)
Michael An (man)
Michael Byrne (MichaelB7)
@@ -132,39 +152,47 @@ Michael Whiteley (protonspring)
Michel Van den Bergh (vdbergh)
Miguel Lahoz (miguel-l)
Mikael Bäckman (mbootsector)
Mike Babigian (Farseer)
Mira
Miroslav Fontán (Hexik)
Moez Jellouli (MJZ1977)
Mohammed Li (tthsqe12)
Muzhen J (XInTheDark)
Nathan Rugg (nmrugg)
Nick Pelling (nickpelling)
Nguyen Pham (nguyenpham)
Nicklas Persson (NicklasPersson)
Nick Pelling (nickpelling)
Niklas Fiekas (niklasf)
Nikolay Kostov (NikolayIT)
Nguyen Pham (nguyenpham)
Norman Schmidt (FireFather)
notruck
Ofek Shochat (OfekShochat, ghostway)
Ondrej Mosnáček (WOnder93)
Ondřej Mišina (AndrovT)
Oskar Werkelin Ahlin
Pablo Vazquez
Panthee
Pascal Romaret
Pasquale Pigazzini (ppigazzini)
Patrick Jansen (mibere)
pellanda
Peter Schneider (pschneider1968)
Peter Zsifkovits (CoffeeOne)
PikaCat
Praveen Kumar Tummala (praveentml)
Prokop Randáček (ProkopRandacek)
Rahul Dsilva (silversolver1)
Ralph Stößer (Ralph Stoesser)
Raminder Singh
renouve
Reuven Peleg
Richard Lloyd
Reuven Peleg (R-Peleg)
Richard Lloyd (Richard-Lloyd)
Robert Nürnberg (robertnurnberg)
Rodrigo Exterckötter Tjäder
Ron Britvich (Britvich)
Rodrigo Roim (roim)
Ronald de Man (syzygy1, syzygy)
Ron Britvich (Britvich)
rqs
Rui Coelho (ruicoelhopedro)
Ryan Schmitt
Ryan Takker
Sami Kiminki (skiminki)
@@ -173,20 +201,27 @@ Sergei Antonov (saproj)
Sergei Ivanov (svivanov72)
Sergio Vieri (sergiovieri)
sf-x
Shahin M. Shahin (peregrine)
Shane Booth (shane31)
Shawn Varghese (xXH4CKST3RXx)
Siad Daboul (Topologist)
Stefan Geschwentner (locutus2)
Stefano Cardanobile (Stefano80)
Stefano Di Martino (StefanoD)
Steinar Gunderson (sesse)
Stéphane Nicolet (snicolet)
Prokop Randáček (ProkopRandacek)
Stephen Touset (stouset)
Syine Mineta (MinetaS)
Taras Vuk (TarasVuk)
Thanar2
thaspel
theo77186
TierynnB
Ting-Hsuan Huang (fffelix-huang)
Tobias Steinmann
Tomasz Sobczyk (Sopel97)
Tom Truscott
Tom Vijlbrief (tomtor)
Tomasz Sobczyk (Sopel97)
Torsten Franz (torfranz, tfranzer)
Torsten Hellwig (Torom)
Tracey Emery (basepr1me)
@@ -194,10 +229,13 @@ tttak
Unai Corzo (unaiic)
Uri Blass (uriblass)
Vince Negri (cuddlestmonkey)
Viren
windfishballad
xefoci7612
Xiang Wang (KatyushaScarlet)
zz4032
# Additionally, we acknowledge the authors and maintainers of fishtest,
# an amazing and essential framework for the development of Stockfish!
# an amazing and essential framework for Stockfish development!
#
# https://github.com/glinscott/fishtest/blob/master/AUTHORS
# https://github.com/official-stockfish/fishtest/blob/master/AUTHORS
+23
View File
@@ -0,0 +1,23 @@
# This CITATION.cff file was generated with cffinit.
# Visit https://bit.ly/cffinit to generate yours today!
cff-version: 1.2.0
title: Stockfish
message: >-
Please cite this software using the metadata from this
file.
type: software
authors:
- name: The Stockfish developers (see AUTHORS file)
repository-code: 'https://github.com/official-stockfish/Stockfish'
url: 'https://stockfishchess.org/'
repository-artifact: 'https://stockfishchess.org/download/'
abstract: Stockfish is a free and strong UCI chess engine.
keywords:
- chess
- artificial intelligence (AI)
- tree search
- alpha-beta search
- neural networks (NN)
- efficiently updatable neural networks (NNUE)
license: GPL-3.0
+97
View File
@@ -0,0 +1,97 @@
# Contributing to Stockfish
Welcome to the Stockfish project! We are excited that you are interested in
contributing. This document outlines the guidelines and steps to follow when
making contributions to Stockfish.
## Table of Contents
- [Building Stockfish](#building-stockfish)
- [Making Contributions](#making-contributions)
- [Reporting Issues](#reporting-issues)
- [Submitting Pull Requests](#submitting-pull-requests)
- [Code Style](#code-style)
- [Community and Communication](#community-and-communication)
- [License](#license)
## Building Stockfish
In case you do not have a C++ compiler installed, you can follow the
instructions from our wiki.
- [Ubuntu][ubuntu-compiling-link]
- [Windows][windows-compiling-link]
- [macOS][macos-compiling-link]
## Making Contributions
### Reporting Issues
If you find a bug, please open an issue on the
[issue tracker][issue-tracker-link]. Be sure to include relevant information
like your operating system, build environment, and a detailed description of the
problem.
_Please note that Stockfish's development is not focused on adding new features.
Thus any issue regarding missing features will potentially be closed without
further discussion._
### Submitting Pull Requests
- Functional changes need to be tested on fishtest. See
[Creating my First Test][creating-my-first-test] for more details.
The accompanying pull request should include a link to the test results and
the new bench.
- Non-functional changes (e.g. refactoring, code style, documentation) do not
need to be tested on fishtest, unless they might impact performance.
- Provide a clear and concise description of the changes in the pull request
description.
_First time contributors should add their name to [AUTHORS](../AUTHORS)._
_Stockfish's development is not focused on adding new features. Thus any pull
request introducing new features will potentially be closed without further
discussion._
## Code Style
Changes to Stockfish C++ code should respect our coding style defined by
[.clang-format](.clang-format). You can format your changes by running
`make format`. This requires clang-format version 17 to be installed on your system.
## Navigate
For experienced Git users who frequently use git blame, it is recommended to
configure the blame.ignoreRevsFile setting.
This setting is useful for excluding noisy formatting commits.
```bash
git config blame.ignoreRevsFile .git-blame-ignore-revs
```
## Community and Communication
- Join the [Stockfish discord][discord-link] to discuss ideas, issues, and
development.
- Participate in the [Stockfish GitHub discussions][discussions-link] for
broader conversations.
## License
By contributing to Stockfish, you agree that your contributions will be licensed
under the GNU General Public License v3.0. See [Copying.txt][copying-link] for
more details.
Thank you for contributing to Stockfish and helping us make it even better!
[copying-link]: https://github.com/official-stockfish/Stockfish/blob/master/Copying.txt
[discord-link]: https://discord.gg/GWDRS3kU6R
[discussions-link]: https://github.com/official-stockfish/Stockfish/discussions/new
[creating-my-first-test]: https://github.com/official-stockfish/fishtest/wiki/Creating-my-first-test#create-your-test
[issue-tracker-link]: https://github.com/official-stockfish/Stockfish/issues
[ubuntu-compiling-link]: https://github.com/official-stockfish/Stockfish/wiki/Developers#user-content-installing-a-compiler-1
[windows-compiling-link]: https://github.com/official-stockfish/Stockfish/wiki/Developers#user-content-installing-a-compiler
[macos-compiling-link]: https://github.com/official-stockfish/Stockfish/wiki/Developers#user-content-installing-a-compiler-2
+674 -674
View File
File diff suppressed because it is too large Load Diff
+122 -295
View File
@@ -1,327 +1,154 @@
<div align="center">
[![Stockfish][stockfish128-logo]][website-link]
<h3>Stockfish</h3>
A free and strong UCI chess engine.
<br>
<strong>[Explore Stockfish docs »][wiki-link]</strong>
<br>
<br>
[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]
<br>
[![Release][release-badge]][release-link]
[![Commits][commits-badge]][commits-link]
<br>
[![Website][website-badge]][website-link]
[![Fishtest][fishtest-badge]][fishtest-link]
[![Discord][discord-badge]][discord-link]
</div>
## Overview
[![Build Status](https://github.com/official-stockfish/Stockfish/actions/workflows/stockfish.yml/badge.svg)](https://github.com/official-stockfish/Stockfish/actions)
[![Build Status](https://ci.appveyor.com/api/projects/status/github/official-stockfish/Stockfish?branch=master&svg=true)](https://ci.appveyor.com/project/mcostalba/stockfish/branch/master)
[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](https://stockfishchess.org) is a free, powerful UCI chess engine
derived from Glaurung 2.1. Stockfish is not a complete chess program and requires a
UCI-compatible graphical user interface (GUI) (e.g. XBoard with PolyGlot, Scid,
Cute Chess, eboard, Arena, Sigma Chess, Shredder, Chess Partner or Fritz) in order
to be used comfortably. Read the documentation for your GUI of choice for information
about how to use Stockfish with it.
The Stockfish engine features two evaluation functions for chess, the classical
evaluation based on handcrafted terms, and the NNUE evaluation based on efficiently
updatable neural networks. The classical evaluation runs efficiently on almost all
CPU architectures, while the NNUE evaluation benefits from the vector
intrinsics available on most CPUs (sse2, avx2, neon, or similar).
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](https://github.com/official-stockfish/Stockfish/blob/master/README.md), the file you are currently reading.
* [README.md][readme-link], the file you are currently reading.
* [Copying.txt](https://github.com/official-stockfish/Stockfish/blob/master/Copying.txt), a text file containing the GNU General Public License version 3.
* [Copying.txt][license-link], a text file containing the GNU General Public
License version 3.
* [AUTHORS](https://github.com/official-stockfish/Stockfish/blob/master/AUTHORS), a text file with the list of authors for the project
* [AUTHORS][authors-link], a text file with the list of authors for the project.
* [src](https://github.com/official-stockfish/Stockfish/tree/master/src), a subdirectory containing the full source code, including a Makefile
that can be used to compile Stockfish on Unix-like systems.
* [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.
## The UCI protocol and available options
## Contributing
The Universal Chess Interface (UCI) is a standard protocol used to communicate with
a chess engine, and is the recommended way to do so for typical graphical user interfaces
(GUI) or chess tools. Stockfish implements the majority of it options as described
in [the UCI protocol](https://www.shredderchess.com/download/div/uci.zip).
Developers can see the default values for UCI options available in Stockfish by typing
`./stockfish uci` in a terminal, but the majority of users will typically see them and
change them via a chess GUI. This is a list of available UCI options in Stockfish:
* #### Threads
The number of CPU threads used for searching a position. For best performance, set
this equal to the number of CPU cores available.
* #### Hash
The size of the hash table in MB. It is recommended to set Hash after setting Threads.
* #### Clear Hash
Clear the hash table.
* #### Ponder
Let Stockfish ponder its next move while the opponent is thinking.
* #### MultiPV
Output the N best lines (principal variations, PVs) when searching.
Leave at 1 for best performance.
* #### Use NNUE
Toggle between the NNUE and classical evaluation functions. If set to "true",
the network parameters must be available to load from file (see also EvalFile),
if they are not embedded in the binary.
* #### EvalFile
The name of the file of the NNUE evaluation parameters. Depending on the GUI the
filename might have to include the full path to the folder/directory that contains the file.
Other locations, such as the directory that contains the binary and the working directory,
are also searched.
* #### UCI_AnalyseMode
An option handled by your GUI.
* #### UCI_Chess960
An option handled by your GUI. If true, Stockfish will play Chess960.
* #### UCI_ShowWDL
If enabled, show approximate WDL statistics as part of the engine output.
These WDL numbers model expected game outcomes for a given evaluation and
game ply for engine self-play at fishtest LTC conditions (60+0.6s per game).
* #### UCI_LimitStrength
Enable weaker play aiming for an Elo rating as set by UCI_Elo. This option overrides Skill Level.
* #### UCI_Elo
If enabled by UCI_LimitStrength, aim for an engine strength of the given Elo.
This Elo rating has been calibrated at a time control of 60s+0.6s and anchored to CCRL 40/4.
* #### Skill Level
Lower the Skill Level in order to make Stockfish play weaker (see also UCI_LimitStrength).
Internally, MultiPV is enabled, and with a certain probability depending on the Skill Level a
weaker move will be played.
* #### SyzygyPath
Path to the folders/directories storing the Syzygy tablebase files. Multiple
directories are to be separated by ";" on Windows and by ":" on Unix-based
operating systems. Do not use spaces around the ";" or ":".
Example: `C:\tablebases\wdl345;C:\tablebases\wdl6;D:\tablebases\dtz345;D:\tablebases\dtz6`
It is recommended to store .rtbw files on an SSD. There is no loss in storing
the .rtbz files on a regular HD. It is recommended to verify all md5 checksums
of the downloaded tablebase files (`md5sum -c checksum.md5`) as corruption will
lead to engine crashes.
* #### SyzygyProbeDepth
Minimum remaining search depth for which a position is probed. Set this option
to a higher value to probe less aggressively if you experience too much slowdown
(in terms of nps) due to tablebase probing.
* #### Syzygy50MoveRule
Disable to let fifty-move rule draws detected by Syzygy tablebase probes count
as wins or losses. This is useful for ICCF correspondence games.
* #### SyzygyProbeLimit
Limit Syzygy tablebase probing to positions with at most this many pieces left
(including kings and pawns).
* #### Move Overhead
Assume a time delay of x ms due to network and GUI overheads. This is useful to
avoid losses on time in those cases.
* #### Slow Mover
Lower values will make Stockfish take less time in games, higher values will
make it think longer.
* #### nodestime
Tells the engine to use nodes searched instead of wall time to account for
elapsed time. Useful for engine testing.
* #### Debug Log File
Write all communication to and from the engine into a text file.
For developers the following non-standard commands might be of interest, mainly useful for debugging:
* #### bench *ttSize threads limit fenFile limitType evalType*
Performs a standard benchmark using various options. The signature of a version (standard node
count) is obtained using all defaults. `bench` is currently `bench 16 1 13 default depth mixed`.
* #### compiler
Give information about the compiler and environment used for building a binary.
* #### d
Display the current position, with ascii art and fen.
* #### eval
Return the evaluation of the current position.
* #### export_net [filename]
Exports the currently loaded network to a file.
If the currently loaded network is the embedded network and the filename
is not specified then the network is saved to the file matching the name
of the embedded network, as defined in evaluate.h.
If the currently loaded network is not the embedded network (some net set
through the UCI setoption) then the filename parameter is required and the
network is saved into that file.
* #### flip
Flips the side to move.
## A note on classical evaluation versus NNUE evaluation
Both approaches assign a value to a position that is used in alpha-beta (PVS) search
to find the best move. The classical evaluation computes this value as a function
of various chess concepts, handcrafted by experts, tested and tuned using fishtest.
The NNUE evaluation computes this value with a neural network based on basic
inputs (e.g. piece positions only). The network is optimized and trained
on the evaluations of millions of positions at moderate search depth.
The NNUE evaluation was first introduced in shogi, and ported to Stockfish afterward.
It can be evaluated efficiently on CPUs, and exploits the fact that only parts
of the neural network need to be updated after a typical chess move.
[The nodchip repository](https://github.com/nodchip/Stockfish) provides additional
tools to train and develop the NNUE networks. On CPUs supporting modern vector instructions
(avx2 and similar), the NNUE evaluation results in much stronger playing strength, even
if the nodes per second computed by the engine is somewhat lower (roughly 80% of nps
is typical).
Notes:
1) the NNUE evaluation depends on the Stockfish binary and the network parameter
file (see the EvalFile UCI option). Not every parameter file is compatible with a given
Stockfish binary, but the default value of the EvalFile UCI option is the name of a network
that is guaranteed to be compatible with that binary.
2) to use the NNUE evaluation, the additional data file with neural network parameters
needs to be available. Normally, this file is already embedded in the binary or it
can be downloaded. The filename for the default (recommended) net can be found as the default
value of the `EvalFile` UCI option, with the format `nn-[SHA256 first 12 digits].nnue`
(for instance, `nn-c157e0a5755b.nnue`). This file can be downloaded from
```
https://tests.stockfishchess.org/api/nn/[filename]
```
replacing `[filename]` as needed.
## What to expect from the Syzygy tablebases?
If the engine is searching a position that is not in the tablebases (e.g.
a position with 8 pieces), it will access the tablebases during the search.
If the engine reports a very large score (typically 153.xx), this means
it has found a winning line into a tablebase position.
If the engine is given a position to search that is in the tablebases, it
will use the tablebases at the beginning of the search to preselect all
good moves, i.e. all moves that preserve the win or preserve the draw while
taking into account the 50-move rule.
It will then perform a search only on those moves. **The engine will not move
immediately**, unless there is only a single good move. **The engine likely
will not report a mate score, even if the position is known to be won.**
It is therefore clear that this behaviour is not identical to what one might
be used to with Nalimov tablebases. There are technical reasons for this
difference, the main technical reason being that Nalimov tablebases use the
DTM metric (distance-to-mate), while the Syzygy tablebases use a variation of the
DTZ metric (distance-to-zero, zero meaning any move that resets the 50-move
counter). This special metric is one of the reasons that the Syzygy tablebases are
more compact than Nalimov tablebases, while still storing all information
needed for optimal play and in addition being able to take into account
the 50-move rule.
## Large Pages
Stockfish supports large pages on Linux and Windows. Large pages make
the hash access more efficient, improving the engine speed, especially
on large hash sizes. Typical increases are 5..10% in terms of nodes per
second, but speed increases up to 30% have been measured. The support is
automatic. Stockfish attempts to use large pages when available and
will fall back to regular memory allocation when this is not the case.
### Support on Linux
Large page support on Linux is obtained by the Linux kernel
transparent huge pages functionality. Typically, transparent huge pages
are already enabled, and no configuration is needed.
### Support on Windows
The use of large pages requires "Lock Pages in Memory" privilege. See
[Enable the Lock Pages in Memory Option (Windows)](https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/enable-the-lock-pages-in-memory-option-windows)
on how to enable this privilege, then run [RAMMap](https://docs.microsoft.com/en-us/sysinternals/downloads/rammap)
to double-check that large pages are used. We suggest that you reboot
your computer after you have enabled large pages, because long Windows
sessions suffer from memory fragmentation, which may prevent Stockfish
from getting large pages: a fresh session is better in this regard.
## Compiling Stockfish yourself from the sources
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.
```
cd src
make help
make net
make build ARCH=x86-64-modern
```
When not using the Makefile to compile (for instance, with Microsoft MSVC) you
need to manually set/unset some switches in the compiler command line; see
file *types.h* for a quick reference.
When reporting an issue or a bug, please tell us which Stockfish version
and which compiler you used to create your executable. This information
can be found by typing the following command in a console:
```
./stockfish compiler
```
## Understanding the code base and participating in the project
Stockfish's improvement over the last decade has been a great community
effort. There are a few ways to help contribute to its growth.
__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](https://github.com/glinscott/fishtest/wiki/Running-the-worker:-overview)
and view the current tests on [Fishtest](https://tests.stockfishchess.org/tests).
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
If you want to help improve the code, there are several valuable resources:
* [In this wiki,](https://www.chessprogramming.org) many techniques used in
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 section on Stockfish](https://www.chessprogramming.org/Stockfish)
describes many features and techniques used by Stockfish. However, it is
generic rather than being focused on Stockfish's precise implementation.
Nevertheless, a helpful resource.
* The latest source can always be found on [GitHub](https://github.com/official-stockfish/Stockfish).
Discussions about Stockfish take place these days mainly in the [FishCooking](https://groups.google.com/forum/#!forum/fishcooking)
group and on the [Stockfish Discord channel](https://discord.gg/nv8gDtt).
The engine testing is done on [Fishtest](https://tests.stockfishchess.org/tests).
If you want to help improve Stockfish, please read this [guideline](https://github.com/glinscott/fishtest/wiki/Creating-my-first-test)
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 ARCH=x86-64-avx2
```
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**
(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.
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 full source code, or a pointer
to where the source code can be found, to generate the exact binary
you are distributing. If you make any changes to the source code,
these changes must also be made available under the GPL.
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.
For full details, read the copy of the GPL v3 found in the file named
[*Copying.txt*](https://github.com/official-stockfish/Stockfish/blob/master/Copying.txt).
[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
[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
+284 -203
View File
@@ -1,205 +1,286 @@
Contributors to Fishtest with >10,000 CPU hours, as of Jun 29, 2021.
Contributors to Fishtest with >10,000 CPU hours, as of 2024-02-24.
Thank you!
Username CPU Hours Games played
-----------------------------------------------------
noobpwnftw 27649494 1834734733
mlang 1426107 89454622
dew 1380910 82831648
mibere 703840 46867607
grandphish2 692707 41737913
tvijlbrief 669642 42371594
JojoM 597778 35297180
TueRens 519226 31823562
cw 458421 30307421
fastgm 439667 25950040
gvreuls 436599 28177460
crunchy 427035 27344275
CSU_Dynasty 374765 25106278
Fisherman 326901 21822979
ctoks 325477 21767943
velislav 295343 18844324
linrock 292789 10624427
bcross 278584 19488961
okrout 262818 13803272
pemo 245982 11376085
glinscott 217799 13780820
leszek 212346 12959025
nordlandia 211692 13484886
bking_US 198894 11876016
drabel 196463 13450602
robal 195473 12375650
mgrabiak 187226 12016564
Dantist 183202 10990484
Thanar 179852 12365359
vdv 175274 9889046
spams 157128 10319326
marrco 150295 9402141
sqrt2 147963 9724586
mhoram 141278 8901241
CoffeeOne 137100 5024116
vdbergh 137041 8926915
malala 136182 8002293
xoto 133702 9156676
davar 122092 7960001
dsmith 122059 7570238
Data 113305 8220352
BrunoBanani 112960 7436849
MaZePallas 102823 6633619
sterni1971 100532 5880772
ElbertoOne 99028 7023771
brabos 92118 6186135
oz 92100 6486640
psk 89957 5984901
amicic 89156 5392305
sunu 88851 6028873
Vizvezdenec 83761 5344740
0x3C33 82614 5271253
BRAVONE 81239 5054681
racerschmacer 80899 5759262
cuistot 80300 4606144
nssy 76497 5259388
teddybaer 75125 5407666
Pking_cda 73776 5293873
jromang 72192 5057715
solarlight 70517 5028306
dv8silencer 70287 3883992
Bobo1239 68515 4652287
manap 66273 4121774
skiminki 65088 4023328
tinker 64333 4268790
sschnee 60767 3500800
qurashee 57344 3168264
robnjr 57262 4053117
Freja 56938 3733019
ttruscott 56010 3680085
rkl 55132 4164467
renouve 53811 3501516
finfish 51360 3370515
eva42 51272 3599691
rap 49985 3219146
pb00067 49727 3298270
ronaldjerum 47654 3240695
bigpen0r 47653 3335327
eastorwest 47585 3221629
biffhero 46564 3111352
VoyagerOne 45476 3452465
yurikvelo 44834 3034550
speedycpu 43842 3003273
jbwiebe 43305 2805433
Spprtr 42279 2680153
DesolatedDodo 42007 2447516
Antihistamine 41788 2761312
mhunt 41735 2691355
homyur 39893 2850481
gri 39871 2515779
Fifis 38776 2529121
oryx 38724 2966648
SC 37290 2731014
csnodgrass 36207 2688994
jmdana 36157 2210661
strelock 34716 2074055
rpngn 33951 2057395
Garf 33922 2751802
EthanOConnor 33370 2090311
slakovv 32915 2021889
manapbk 30987 1810399
Prcuvu 30377 2170122
anst 30301 2190091
jkiiski 30136 1904470
hyperbolic.tom 29840 2017394
Pyafue 29650 1902349
Wolfgang 29260 1658936
zeryl 28156 1579911
OuaisBla 27636 1578800
DMBK 27051 1999456
chriswk 26902 1868317
achambord 26582 1767323
Patrick_G 26276 1801617
yorkman 26193 1992080
SFTUser 25182 1675689
nabildanial 24942 1519409
Sharaf_DG 24765 1786697
ncfish1 24411 1520927
rodneyc 24227 1409514
agg177 23890 1395014
JanErik 23408 1703875
Isidor 23388 1680691
Norabor 23164 1591830
cisco2015 22897 1762669
Zirie 22542 1472937
team-oh 22272 1636708
MazeOfGalious 21978 1629593
sg4032 21947 1643265
ianh2105 21725 1632562
xor12 21628 1680365
dex 21612 1467203
nesoneg 21494 1463031
sphinx 21211 1384728
jjoshua2 21001 1423089
horst.prack 20878 1465656
Ente 20865 1477066
0xB00B1ES 20590 1208666
j3corre 20405 941444
Adrian.Schmidt123 20316 1281436
wei 19973 1745989
MaxKlaxxMiner 19850 1009176
rstoesser 19569 1293588
gopeto 19491 1174952
eudhan 19274 1283717
jundery 18445 1115855
megaman7de 18377 1067540
iisiraider 18247 1101015
ville 17883 1384026
chris 17698 1487385
purplefishies 17595 1092533
dju 17353 978595
DragonLord 17014 1162790
IgorLeMasson 16064 1147232
ako027ako 15671 1173203
chuckstablers 15289 891576
Nikolay.IT 15154 1068349
Andrew Grant 15114 895539
OssumOpossum 14857 1007129
Karby 14808 867120
enedene 14476 905279
bpfliegel 14298 884523
mpx86 14019 759568
jpulman 13982 870599
crocogoat 13803 1117422
joster 13794 950160
Nesa92 13786 1114691
Hjax 13535 915487
jsys14 13459 785000
Dark_wizzie 13422 1007152
mabichito 12903 749391
thijsk 12886 722107
AdrianSA 12860 804972
Flopzee 12698 894821
fatmurphy 12547 853210
Rudolphous 12520 832340
scuzzi 12511 845761
SapphireBrand 12416 969604
modolief 12386 896470
Machariel 12335 810784
pgontarz 12151 848794
stocky 11954 699440
mschmidt 11941 803401
Maxim 11543 836024
infinity 11470 727027
torbjo 11395 729145
Thomas A. Anderson 11372 732094
savage84 11358 670860
d64 11263 789184
MooTheCow 11237 720174
snicolet 11106 869170
ali-al-zhrani 11086 767926
AndreasKrug 10875 887457
pirt 10806 836519
basepi 10637 744851
michaelrpg 10508 739039
dzjp 10343 732529
aga 10302 622975
ols 10259 570669
lbraesch 10252 647825
FormazChar 10059 757283
Username CPU Hours Games played
------------------------------------------------------------------
noobpwnftw 39302472 3055513453
technologov 20845762 994893444
linrock 8616428 560281417
mlang 3026000 200065824
okrout 2332151 222639518
pemo 1800019 60274069
dew 1689162 100033738
TueRens 1474943 75121774
grandphish2 1463002 91616949
JojoM 1109702 72927902
olafm 978631 71037944
sebastronomy 939955 44920556
tvijlbrief 796125 51897690
gvreuls 711320 49142318
mibere 703840 46867607
oz 646268 46293638
rpngn 572571 38928563
leszek 531858 39316505
cw 518116 34894291
fastgm 503862 30260818
CSU_Dynasty 468784 31385034
ctoks 434591 28520597
maximmasiutin 429983 27066286
crunchy 427414 27371625
bcross 415724 29061187
velislav 342588 22140902
mgrabiak 338763 23999170
Fisherman 327231 21829379
robal 299836 20213182
Dantist 296386 18031762
ncfish1 267604 17881149
nordlandia 249322 16420192
marrco 234581 17714473
tolkki963 233490 19773930
glinscott 208125 13277240
drabel 204167 13930674
mhoram 202894 12601997
bking_US 198894 11876016
Calis007 188631 12795784
Thanar 179852 12365359
Fifis 176209 10638245
vdv 175544 9904472
spams 157128 10319326
DesolatedDodo 156659 10210328
armo9494 155355 10566898
sqrt2 147963 9724586
jcAEie 140086 10603658
vdbergh 139746 9172061
CoffeeOne 137100 5024116
malala 136182 8002293
xoto 133759 9159372
davar 129023 8376525
DMBK 122960 8980062
dsmith 122059 7570238
javran 121564 10144656
amicic 119661 7938029
sschnee 118107 7389266
Wolfgang 114616 8070494
Data 113305 8220352
BrunoBanani 112960 7436849
Wencey 111502 5991676
cuistot 108503 7006992
CypressChess 108331 7759788
skiminki 107583 7218170
MaZePallas 102823 6633619
sterni1971 100532 5880772
sunu 100167 7040199
zeryl 99331 6221261
thirdlife 99156 2245320
ElbertoOne 99028 7023771
Dubslow 98600 6903242
markkulix 97010 7643900
bigpen0r 94809 6529203
brabos 92118 6186135
Maxim 90818 3283364
psk 89957 5984901
megaman7de 88822 6052132
racerschmacer 85805 6122790
maposora 85710 7778146
Vizvezdenec 83761 5344740
0x3C33 82614 5271253
BRAVONE 81239 5054681
nssy 76497 5259388
jromang 76106 5236025
teddybaer 75125 5407666
Pking_cda 73776 5293873
yurikvelo 73516 5036928
MarcusTullius 71053 4803477
Bobo1239 70579 4794999
solarlight 70517 5028306
dv8silencer 70287 3883992
Spprtr 69646 4806763
Mineta 66325 4537742
manap 66273 4121774
szupaw 65468 5669742
tinker 64333 4268790
qurashee 61208 3429862
woutboat 59496 4906352
AGI 58195 4329580
robnjr 57262 4053117
Freja 56938 3733019
MaxKlaxxMiner 56879 3423958
ttruscott 56010 3680085
rkl 55132 4164467
jmdana 54697 4012593
renouve 53811 3501516
notchris 52433 4044590
finfish 51360 3370515
eva42 51272 3599691
eastorwest 51117 3454811
Goatminola 51004 4432492
rap 49985 3219146
pb00067 49733 3298934
GPUex 48686 3684998
OuaisBla 48626 3445134
ronaldjerum 47654 3240695
biffhero 46564 3111352
oryx 45533 3539290
VoyagerOne 45476 3452465
speedycpu 43842 3003273
jbwiebe 43305 2805433
Antihistamine 41788 2761312
mhunt 41735 2691355
homyur 39893 2850481
gri 39871 2515779
Garf 37741 2999686
SC 37299 2731694
Sylvain27 36520 1467082
csnodgrass 36207 2688994
Gaster319 35655 3149442
strelock 34716 2074055
EthanOConnor 33370 2090311
slakovv 32915 2021889
gopeto 31884 2076712
Gelma 31771 1551204
kdave 31157 2198362
manapbk 30987 1810399
ZacHFX 30551 2238078
Prcuvu 30377 2170122
anst 30301 2190091
jkiiski 30136 1904470
spcc 29925 1901692
hyperbolic.tom 29840 2017394
chuckstablers 29659 2093438
Pyafue 29650 1902349
belzedar94 28846 1811530
votoanthuan 27978 2285818
shawnxu 27438 2465810
chriswk 26902 1868317
xwziegtm 26897 2124586
achambord 26582 1767323
Patrick_G 26276 1801617
yorkman 26193 1992080
Ulysses 25397 1701264
Jopo12321 25227 1652482
SFTUser 25182 1675689
nabildanial 25068 1531665
Sharaf_DG 24765 1786697
rodneyc 24376 1416402
jsys14 24297 1721230
agg177 23890 1395014
srowen 23842 1342508
Ente 23752 1678188
jojo2357 23479 2061238
JanErik 23408 1703875
Isidor 23388 1680691
Norabor 23371 1603244
cisco2015 22920 1763301
Zirie 22542 1472937
Nullvalue 22490 1970374
AndreasKrug 22485 1769491
team-oh 22272 1636708
Roady 22220 1465606
MazeOfGalious 21978 1629593
sg4032 21947 1643353
ianh2105 21725 1632562
xor12 21628 1680365
dex 21612 1467203
nesoneg 21494 1463031
user213718 21454 1404128
sphinx 21211 1384728
qoo_charly_cai 21135 1514907
jjoshua2 21001 1423089
Zake9298 20938 1565848
horst.prack 20878 1465656
0xB00B1ES 20590 1208666
Serpensin 20487 1729674
Dinde 20440 1292390
j3corre 20405 941444
Adrian.Schmidt123 20316 1281436
wei 19973 1745989
fishtester 19617 1257388
rstoesser 19569 1293588
eudhan 19274 1283717
vulcan 18871 1729392
Karpovbot 18766 1053178
WoodMan777 18556 1628264
jundery 18445 1115855
ville 17883 1384026
chris 17698 1487385
purplefishies 17595 1092533
dju 17414 981289
ols 17291 1042003
iisiraider 17275 1049015
Skiff84 17111 950248
DragonLord 17014 1162790
redstone59 16842 1461780
Karby 16839 1010124
Alb11747 16787 1213990
pirt 16493 1237199
Naven94 16414 951718
wizardassassin 16392 1148672
IgorLeMasson 16064 1147232
scuzzi 15757 968735
ako027ako 15671 1173203
Nikolay.IT 15154 1068349
Andrew Grant 15114 895539
OssumOpossum 14857 1007129
LunaticBFF57 14525 1190310
enedene 14476 905279
IslandLambda 14393 958196
bpfliegel 14233 882523
YELNAMRON 14230 1128094
mpx86 14019 759568
jpulman 13982 870599
getraideBFF 13871 1172846
Nesa92 13806 1116101
crocogoat 13803 1117422
joster 13710 946160
mbeier 13650 1044928
Hjax 13535 915487
Dark_wizzie 13422 1007152
Rudolphous 13244 883140
Machariel 13010 863104
infinigon 12991 943216
mabichito 12903 749391
thijsk 12886 722107
AdrianSA 12860 804972
Flopzee 12698 894821
mschmidt 12644 863193
korposzczur 12606 838168
tsim67 12570 890180
Jackfish 12553 836958
fatmurphy 12547 853210
Oakwen 12503 853105
SapphireBrand 12416 969604
deflectooor 12386 579392
modolief 12386 896470
TataneSan 12358 609332
Farseer 12249 694108
pgontarz 12151 848794
dbernier 12103 860824
FormazChar 11989 907809
stocky 11954 699440
somethingintheshadows 11940 989472
MooTheCow 11892 776126
3cho 11842 1036786
whelanh 11557 245188
infinity 11470 727027
aga 11412 695127
torbjo 11395 729145
Thomas A. Anderson 11372 732094
savage84 11358 670860
d64 11263 789184
ali-al-zhrani 11245 779246
ckaz 11170 680866
snicolet 11106 869170
dapper 11032 771402
Ethnikoi 10993 945906
Snuuka 10938 435504
Karmatron 10859 678058
basepi 10637 744851
jibarbosa 10628 857100
Cubox 10621 826448
mecevdimitar 10609 787318
michaelrpg 10509 739239
Def9Infinity 10427 686978
OIVAS7572 10420 995586
wxt9861 10412 1013864
Garruk 10365 706465
dzjp 10343 732529
-88
View File
@@ -1,88 +0,0 @@
version: 1.0.{build}
clone_depth: 50
branches:
only:
- master
# Operating system (build VM template)
os: Visual Studio 2019
# Build platform, i.e. x86, x64, AnyCPU. This setting is optional.
platform:
- x86
- x64
# build Configuration, i.e. Debug, Release, etc.
configuration:
- Debug
- Release
matrix:
# The build fail immediately once one of the job fails
fast_finish: true
# Scripts that are called at very beginning, before repo cloning
init:
- cmake --version
- msbuild /version
before_build:
- ps: |
# Get sources
$src = get-childitem -Path *.cpp -Recurse | select -ExpandProperty FullName
$src = $src -join ' '
$src = $src.Replace("\", "/")
# Build CMakeLists.txt
$t = 'cmake_minimum_required(VERSION 3.17)',
'project(Stockfish)',
'set(CMAKE_CXX_STANDARD 17)',
'set(CMAKE_CXX_STANDARD_REQUIRED ON)',
'set (CMAKE_CXX_EXTENSIONS OFF)',
'set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/src)',
'set(source_files', $src, ')',
'add_executable(stockfish ${source_files})'
# Write CMakeLists.txt withouth BOM
$MyPath = (Get-Item -Path "." -Verbose).FullName + '\CMakeLists.txt'
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
[System.IO.File]::WriteAllLines($MyPath, $t, $Utf8NoBomEncoding)
# Obtain bench reference from git log
$b = git log HEAD | sls "\b[Bb]ench[ :]+[0-9]{7}" | select -first 1
$bench = $b -match '\D+(\d+)' | % { $matches[1] }
Write-Host "Reference bench:" $bench
$g = "Visual Studio 16 2019"
If (${env:PLATFORM} -eq 'x64') { $a = "x64" }
If (${env:PLATFORM} -eq 'x86') { $a = "Win32" }
cmake -G "${g}" -A ${a} .
Write-Host "Generated files for: " $g $a
build_script:
- cmake --build . --config %CONFIGURATION% -- /verbosity:minimal
- ps: |
# Download default NNUE net from fishtest
$nnuenet = Get-Content -Path src\evaluate.h | Select-String -CaseSensitive -Pattern "EvalFileDefaultName" | Select-String -CaseSensitive -Pattern "nn-[a-z0-9]{12}.nnue"
$dummy = $nnuenet -match "(?<nnuenet>nn-[a-z0-9]{12}.nnue)"
$nnuenet = $Matches.nnuenet
Write-Host "Default net:" $nnuenet
$nnuedownloadurl = "https://tests.stockfishchess.org/api/nn/$nnuenet"
$nnuefilepath = "src\${env:CONFIGURATION}\$nnuenet"
if (Test-Path -Path $nnuefilepath) {
Write-Host "Already available."
} else {
Write-Host "Downloading $nnuedownloadurl to $nnuefilepath"
Invoke-WebRequest -Uri $nnuedownloadurl -OutFile $nnuefilepath
}
before_test:
- cd src/%CONFIGURATION%
- stockfish bench 2> out.txt >NUL
- ps: |
# Verify bench number
$s = (gc "./out.txt" | out-string)
$r = ($s -match 'Nodes searched \D+(\d+)' | % { $matches[1] })
Write-Host "Engine bench:" $r
Write-Host "Reference bench:" $bench
If ($r -ne $bench) { exit 1 }
+120
View File
@@ -0,0 +1,120 @@
#!/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 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
}
# 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='x86-64-sse41-popcnt' # Supported by Rosetta 2
;;
'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'
;;
'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
;;
*) # 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"
+380 -195
View File
@@ -1,5 +1,5 @@
# Stockfish, a UCI chess playing engine derived from Glaurung 2.1
# Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
# Copyright (C) 2004-2024 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
@@ -19,11 +19,29 @@
### 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 ($(COMP),mingw)
EXE = stockfish.exe
ifeq ($(target_windows),yes)
EXE = stockfish.exe
else
EXE = stockfish
EXE = stockfish
endif
### Installation dir definitions
@@ -31,57 +49,57 @@ PREFIX = /usr/local
BINDIR = $(PREFIX)/bin
### Built-in benchmark for pgo-builds
ifeq ($(SDE_PATH),)
PGOBENCH = ./$(EXE) bench
else
PGOBENCH = $(SDE_PATH) -- ./$(EXE) bench
endif
PGOBENCH = $(WINE_PATH) ./$(EXE) bench
### Source and object files
SRCS = benchmark.cpp bitbase.cpp bitboard.cpp endgame.cpp evaluate.cpp main.cpp \
material.cpp misc.cpp movegen.cpp movepick.cpp pawns.cpp position.cpp psqt.cpp \
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/evaluate_nnue.cpp nnue/features/half_ka_v2_hm.cpp
HEADERS = benchmark.h bitboard.h evaluate.h misc.h movegen.h movepick.h \
nnue/evaluate_nnue.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
OBJS = $(notdir $(SRCS:.cpp=.o))
VPATH = syzygy:nnue:nnue/features
### Establish the operating system name
KERNEL = $(shell uname -s)
ifeq ($(KERNEL),Linux)
OS = $(shell uname -o)
endif
### ==========================================================================
### Section 2. High-level Configuration
### ==========================================================================
#
# flag --- Comp switch --- Description
# flag --- Comp switch --- Description
# ----------------------------------------------------------------------------
#
# debug = yes/no --- -DNDEBUG --- Enable/Disable debug mode
# debug = yes/no --- -DNDEBUG --- Enable/Disable debug mode
# sanitize = none/<sanitizer> ... (-fsanitize )
# --- ( undefined ) --- enable undefined behavior checks
# --- ( thread ) --- enable threading error checks
# --- ( address ) --- enable memory access checks
# --- ...etc... --- see compiler documentation for supported sanitizers
# optimize = yes/no --- (-O3/-fast etc.) --- Enable/Disable optimizations
# arch = (name) --- (-arch) --- Target architecture
# bits = 64/32 --- -DIS_64BIT --- 64-/32-bit operating system
# prefetch = yes/no --- -DUSE_PREFETCH --- Use prefetch asm-instruction
# popcnt = yes/no --- -DUSE_POPCNT --- Use popcnt asm-instruction
# pext = yes/no --- -DUSE_PEXT --- Use pext x86_64 asm-instruction
# sse = yes/no --- -msse --- Use Intel Streaming SIMD Extensions
# mmx = yes/no --- -mmmx --- Use Intel MMX instructions
# sse2 = yes/no --- -msse2 --- Use Intel Streaming SIMD Extensions 2
# ssse3 = yes/no --- -mssse3 --- Use Intel Supplemental Streaming SIMD Extensions 3
# sse41 = yes/no --- -msse4.1 --- Use Intel Streaming SIMD Extensions 4.1
# avx2 = yes/no --- -mavx2 --- Use Intel Advanced Vector Extensions 2
# avx512 = yes/no --- -mavx512bw --- Use Intel Advanced Vector Extensions 512
# vnni256 = yes/no --- -mavx512vnni --- Use Intel Vector Neural Network Instructions 256
# vnni512 = yes/no --- -mavx512vnni --- Use Intel Vector Neural Network Instructions 512
# neon = yes/no --- -DUSE_NEON --- Use ARM SIMD architecture
# --- ( 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
# neon = yes/no --- -DUSE_NEON --- Use ARM SIMD architecture
# dotprod = yes/no --- -DUSE_NEON_DOTPROD --- Use ARM advanced SIMD Int8 dot product instructions
#
# 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
@@ -94,16 +112,20 @@ endif
### 2.1. General and architecture defaults
ifeq ($(ARCH),)
ARCH = x86-64-modern
help_skip_sanity = yes
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-bmi2 x86-64-avx2 \
x86-64-sse41-popcnt x86-64-modern x86-64-ssse3 x86-64-sse3-popcnt \
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-32 e2k \
armv7 armv7-neon armv8 apple-silicon general-64 general-32))
armv7 armv7-neon armv8 armv8-dotprod apple-silicon general-64 general-32 riscv64 loongarch64))
SUPPORTED_ARCH=true
else
SUPPORTED_ARCH=false
@@ -122,12 +144,21 @@ sse2 = no
ssse3 = no
sse41 = no
avx2 = no
avxvnni = no
avx512 = no
vnni256 = no
vnni512 = no
neon = no
dotprod = no
arm_version = 0
STRIP = strip
ifneq ($(shell which clang-format-17 2> /dev/null),)
CLANG-FORMAT = clang-format-17
else
CLANG-FORMAT = clang-format
endif
### 2.2 Architecture specific
ifeq ($(findstring x86,$(ARCH)),x86)
@@ -137,7 +168,7 @@ ifeq ($(findstring x86,$(ARCH)),x86)
ifeq ($(findstring x86-32,$(ARCH)),x86-32)
arch = i386
bits = 32
sse = yes
sse = no
mmx = yes
else
arch = x86_64
@@ -176,6 +207,8 @@ ifeq ($(findstring -sse41,$(ARCH)),-sse41)
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
@@ -192,6 +225,17 @@ ifeq ($(findstring -avx2,$(ARCH)),-avx2)
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
@@ -262,6 +306,7 @@ ifeq ($(ARCH),armv7)
arch = armv7
prefetch = yes
bits = 32
arm_version = 7
endif
ifeq ($(ARCH),armv7-neon)
@@ -270,6 +315,7 @@ ifeq ($(ARCH),armv7-neon)
popcnt = yes
neon = yes
bits = 32
arm_version = 7
endif
ifeq ($(ARCH),armv8)
@@ -277,6 +323,16 @@ ifeq ($(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)
@@ -284,6 +340,8 @@ ifeq ($(ARCH),apple-silicon)
prefetch = yes
popcnt = yes
neon = yes
dotprod = yes
arm_version = 8
endif
ifeq ($(ARCH),ppc-32)
@@ -308,16 +366,30 @@ ifeq ($(findstring e2k,$(ARCH)),e2k)
popcnt = yes
endif
ifeq ($(ARCH),riscv64)
arch = riscv64
endif
ifeq ($(ARCH),loongarch64)
arch = loongarch64
endif
endif
### ==========================================================================
### Section 3. Low-level Configuration
### ==========================================================================
### 3.1 Selecting compiler (default = gcc)
CXXFLAGS += -Wall -Wcast-qual -fno-exceptions -std=c++17 $(EXTRACXXFLAGS)
DEPENDFLAGS += -std=c++17
LDFLAGS += $(EXTRALDFLAGS)
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
@@ -326,13 +398,18 @@ endif
ifeq ($(COMP),gcc)
comp=gcc
CXX=g++
CXXFLAGS += -pedantic -Wextra -Wshadow
CXXFLAGS += -pedantic -Wextra -Wshadow -Wmissing-declarations
ifeq ($(arch),$(filter $(arch),armv7 armv8))
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)
@@ -347,57 +424,64 @@ ifeq ($(COMP),gcc)
endif
endif
ifeq ($(COMP),mingw)
comp=mingw
ifeq ($(KERNEL),Linux)
ifeq ($(bits),64)
ifeq ($(shell which x86_64-w64-mingw32-c++-posix),)
CXX=x86_64-w64-mingw32-c++
else
CXX=x86_64-w64-mingw32-c++-posix
endif
else
ifeq ($(shell which i686-w64-mingw32-c++-posix),)
CXX=i686-w64-mingw32-c++
else
CXX=i686-w64-mingw32-c++-posix
endif
endif
else
CXX=g++
endif
CXXFLAGS += -pedantic -Wextra -Wshadow
ifeq ($(target_windows),yes)
LDFLAGS += -static
endif
ifeq ($(COMP),icc)
comp=icc
CXX=icpc
CXXFLAGS += -diag-disable 1476,10120 -Wcheck -Wabi -Wdeprecated -strict-ansi
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++
CXXFLAGS += -pedantic -Wextra -Wshadow
ifeq ($(target_windows),yes)
CXX=x86_64-w64-mingw32-clang++
endif
ifneq ($(KERNEL),Darwin)
ifneq ($(KERNEL),OpenBSD)
ifneq ($(KERNEL),FreeBSD)
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
endif
ifeq ($(arch),$(filter $(arch),armv7 armv8))
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)
@@ -423,24 +507,43 @@ ifeq ($(COMP),ndk)
ifeq ($(arch),armv7)
CXX=armv7a-linux-androideabi16-clang++
CXXFLAGS += -mthumb -march=armv7-a -mfloat-abi=softfp -mfpu=neon
STRIP=arm-linux-androideabi-strip
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++
STRIP=aarch64-linux-android-strip
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),icc)
profile_make = icc-profile-make
profile_use = icc-profile-use
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
### Travis CI script uses COMPILER to overwrite CXX
@@ -455,8 +558,8 @@ endif
### Sometimes gcc is really clang
ifeq ($(COMP),gcc)
gccversion = $(shell $(CXX) --version)
gccisclang = $(findstring clang,$(gccversion))
gccversion := $(shell $(CXX) --version 2>/dev/null)
gccisclang := $(findstring clang,$(gccversion))
ifneq ($(gccisclang),)
profile_make = clang-profile-make
profile_use = clang-profile-use
@@ -493,7 +596,7 @@ endif
### 3.3 Optimization
ifeq ($(optimize),yes)
CXXFLAGS += -O3
CXXFLAGS += -O3 -funroll-loops
ifeq ($(comp),gcc)
ifeq ($(OS), Android)
@@ -501,14 +604,23 @@ ifeq ($(optimize),yes)
endif
endif
ifeq ($(comp),$(filter $(comp),gcc clang icc))
ifeq ($(KERNEL),Darwin)
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)
CXXFLAGS += -fexperimental-new-pass-manager
clangmajorversion := $(shell $(CXX) -dumpversion 2>/dev/null | cut -f1 -d.)
ifeq ($(shell expr $(clangmajorversion) \< 16),1)
CXXFLAGS += -fexperimental-new-pass-manager
endif
endif
endif
@@ -529,8 +641,6 @@ endif
ifeq ($(popcnt),yes)
ifeq ($(arch),$(filter $(arch),ppc64 armv7 armv8 arm64))
CXXFLAGS += -DUSE_POPCNT
else ifeq ($(comp),icc)
CXXFLAGS += -msse3 -DUSE_POPCNT
else
CXXFLAGS += -msse3 -mpopcnt -DUSE_POPCNT
endif
@@ -539,62 +649,68 @@ endif
### 3.6 SIMD architectures
ifeq ($(avx2),yes)
CXXFLAGS += -DUSE_AVX2
ifeq ($(comp),$(filter $(comp),gcc clang mingw))
CXXFLAGS += -mavx2
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))
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))
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))
CXXFLAGS += -mavx512vnni -mavx512dq -mavx512vl
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))
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))
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))
ifeq ($(comp),$(filter $(comp),gcc clang mingw icx))
CXXFLAGS += -msse2
endif
endif
ifeq ($(mmx),yes)
CXXFLAGS += -DUSE_MMX
ifeq ($(comp),$(filter $(comp),gcc clang mingw))
ifeq ($(comp),$(filter $(comp),gcc clang mingw icx))
CXXFLAGS += -mmmx
endif
endif
ifeq ($(neon),yes)
CXXFLAGS += -DUSE_NEON
CXXFLAGS += -DUSE_NEON=$(arm_version)
ifeq ($(KERNEL),Linux)
ifneq ($(COMP),ndk)
ifneq ($(arch),armv8)
@@ -604,24 +720,46 @@ ifeq ($(neon),yes)
endif
endif
ifeq ($(dotprod),yes)
CXXFLAGS += -march=armv8.2-a+dotprod -DUSE_NEON_DOTPROD
endif
### 3.7 pext
ifeq ($(pext),yes)
CXXFLAGS += -DUSE_PEXT
ifeq ($(comp),$(filter $(comp),gcc clang mingw))
ifeq ($(comp),$(filter $(comp),gcc clang mingw icx))
CXXFLAGS += -mbmi2
endif
endif
### 3.8 Link Time Optimization
### 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),clang)
CXXFLAGS += -flto
ifneq ($(findstring MINGW,$(KERNEL)),)
CXXFLAGS += -fuse-ld=lld
else ifneq ($(findstring MSYS,$(KERNEL)),)
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)
@@ -630,33 +768,23 @@ ifeq ($(debug), no)
# GCC on some systems.
else ifeq ($(comp),gcc)
ifeq ($(gccisclang),)
CXXFLAGS += -flto
CXXFLAGS += -flto -flto-partition=one
LDFLAGS += $(CXXFLAGS) -flto=jobserver
ifneq ($(findstring MINGW,$(KERNEL)),)
LDFLAGS += -save-temps
else ifneq ($(findstring MSYS,$(KERNEL)),)
LDFLAGS += -save-temps
endif
else
CXXFLAGS += -flto
CXXFLAGS += -flto=full
LDFLAGS += $(CXXFLAGS)
endif
# To use LTO and static linking on windows, the tool chain requires a recent gcc:
# gcc version 10.1 in msys2 or TDM-GCC version 9.2 are known to work, older might not.
# So, only enable it for a cross from Linux by default.
# To use LTO and static linking on Windows,
# the tool chain requires gcc version 10.1 or later.
else ifeq ($(comp),mingw)
ifeq ($(KERNEL),Linux)
ifneq ($(arch),i386)
CXXFLAGS += -flto
LDFLAGS += $(CXXFLAGS) -flto=jobserver
endif
endif
CXXFLAGS += -flto -flto-partition=one
LDFLAGS += $(CXXFLAGS) -save-temps
endif
endif
endif
### 3.9 Android 5 can only run position independent executables. Note that this
### 3.10 Android 5 can only run position independent executables. Note that this
### breaks Android 4.0 and earlier.
ifeq ($(OS), Android)
CXXFLAGS += -fPIE
@@ -667,80 +795,87 @@ endif
### Section 4. Public Targets
### ==========================================================================
help:
@echo ""
@echo "To compile stockfish, type: "
@echo ""
@echo "make target ARCH=arch [COMP=compiler] [COMPCXX=cxx]"
@echo "make -j target [ARCH=arch] [COMP=compiler] [COMPCXX=cxx]"
@echo ""
@echo "Supported targets:"
@echo ""
@echo "help > Display architecture details"
@echo "build > Standard build"
@echo "net > Download the default nnue net"
@echo "profile-build > Faster build (with profile-guided optimization)"
@echo "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 "x86-64-vnni512 > x86 64-bit with vnni support 512bit wide"
@echo "x86-64-vnni256 > x86 64-bit with vnni support 256bit wide"
@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 > common modern CPU, currently x86-64-sse41-popcnt"
@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 and popcnt 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 and sse support)"
@echo "x86-32 > x86 32-bit generic (with mmx compile support)"
@echo "ppc-64 > PPC 64-bit"
@echo "ppc-32 > PPC 32-bit"
@echo "armv7 > ARMv7 32-bit"
@echo "armv7-neon > ARMv7 32-bit with popcnt and neon"
@echo "armv8 > ARMv8 64-bit with popcnt and neon"
@echo "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 ""
@echo "Supported compilers:"
@echo ""
@echo "gcc > Gnu compiler (default)"
@echo "mingw > Gnu compiler with MinGW under Windows"
@echo "gcc > GNU compiler (default)"
@echo "mingw > GNU compiler with MinGW under Windows"
@echo "clang > LLVM Clang compiler"
@echo "icc > Intel 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: "
@echo "Simple examples. If you don't know what to do, you likely want to run one of: "
@echo ""
@echo "make -j build ARCH=x86-64 (A portable, slow compile for 64-bit systems)"
@echo "make -j build ARCH=x86-32 (A portable, slow compile for 32-bit systems)"
@echo "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 looking for performance: "
@echo "Advanced examples, for experienced users: "
@echo ""
@echo "make help ARCH=x86-64-bmi2"
@echo "make -j profile-build ARCH=x86-64-bmi2 COMP=gcc COMPCXX=g++-9.0"
@echo "make -j 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 ""
@echo "-------------------------------"
ifeq ($(SUPPORTED_ARCH)$(help_skip_sanity), true)
@echo "The selected architecture $(ARCH) will enable the following configuration: "
@$(MAKE) ARCH=$(ARCH) COMP=$(COMP) config-sanity
else
ifneq ($(SUPPORTED_ARCH), true)
@echo "Specify a supported architecture with the ARCH option for more details"
@echo ""
endif
.PHONY: help build profile-build strip install clean net objclean profileclean \
config-sanity icc-profile-use icc-profile-make gcc-profile-use gcc-profile-make \
clang-profile-use clang-profile-make
.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
@@ -751,7 +886,8 @@ profile-build: net config-sanity objclean profileclean
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) $(profile_make)
@echo ""
@echo "Step 2/4. Running benchmark for pgo-build ..."
$(PGOBENCH) > /dev/null
$(PGOBENCH) > PGOBENCH.out 2>&1
tail -n 4 PGOBENCH.out
@echo ""
@echo "Step 3/4. Building optimized executable ..."
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) objclean
@@ -766,49 +902,84 @@ strip:
install:
-mkdir -p -m 755 $(BINDIR)
-cp $(EXE) $(BINDIR)
-strip $(BINDIR)/$(EXE)
$(STRIP) $(BINDIR)/$(EXE)
# clean all
clean: objclean profileclean
@rm -f .depend *~ core
# evaluation network (nnue)
net:
$(eval nnuenet := $(shell grep EvalFileDefaultName evaluate.h | grep define | sed 's/.*\(nn-[a-z0-9]\{12\}.nnue\).*/\1/'))
@echo "Default net: $(nnuenet)"
$(eval nnuedownloadurl := https://tests.stockfishchess.org/api/nn/$(nnuenet))
$(eval curl_or_wget := $(shell if hash curl 2>/dev/null; then echo "curl -skL"; elif hash wget 2>/dev/null; then echo "wget -qO-"; fi))
@if test -f "$(nnuenet)"; then \
echo "Already available."; \
else \
if [ "x$(curl_or_wget)" = "x" ]; then \
echo "Automatic download failed: neither curl nor wget is installed. Install one of these tools or download the net manually"; exit 1; \
else \
echo "Downloading $(nnuedownloadurl)"; $(curl_or_wget) $(nnuedownloadurl) > $(nnuenet);\
fi; \
fi;
$(eval shasum_command := $(shell if hash shasum 2>/dev/null; then echo "shasum -a 256 "; elif hash sha256sum 2>/dev/null; then echo "sha256sum "; fi))
@if [ "x$(shasum_command)" != "x" ]; then \
if [ "$(nnuenet)" != "nn-"`$(shasum_command) $(nnuenet) | cut -c1-12`".nnue" ]; then \
echo "Failed download or $(nnuenet) corrupted, please delete!"; exit 1; \
fi \
else \
echo "shasum / sha256sum not found, skipping net validation"; \
fi
# clean binaries and objects
objclean:
@rm -f $(EXE) *.o ./syzygy/*.o ./nnue/*.o ./nnue/features/*.o
@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
@rm -f bench.txt *.gcda *.gcno ./syzygy/*.gcda ./nnue/*.gcda ./nnue/features/*.gcda *.s PGOBENCH.out
@rm -f stockfish.profdata *.profraw
@rm -f stockfish.exe.lto_wrapper_args
@rm -f stockfish.exe.ltrans.out
@rm -f stockfish.*args*
@rm -f stockfish.*lt*
@rm -f stockfish.res
@rm -f ./-lstdc++.res
define fetch_network
@echo "Default net: $(nnuenet)"
@if [ "x$(curl_or_wget)" = "x" ]; then \
echo "Neither curl nor wget is installed. Install one of these tools unless the net has been downloaded manually"; \
fi
@if [ "x$(shasum_command)" = "x" ]; then \
echo "shasum / sha256sum not found, skipping net validation"; \
elif test -f "$(nnuenet)"; then \
if [ "$(nnuenet)" != "nn-"`$(shasum_command) $(nnuenet) | cut -c1-12`".nnue" ]; then \
echo "Removing invalid network"; rm -f $(nnuenet); \
fi; \
fi;
@for nnuedownloadurl in "$(nnuedownloadurl1)" "$(nnuedownloadurl2)"; do \
if test -f "$(nnuenet)"; then \
echo "$(nnuenet) available : OK"; break; \
else \
if [ "x$(curl_or_wget)" != "x" ]; then \
echo "Downloading $${nnuedownloadurl}"; $(curl_or_wget) $${nnuedownloadurl} > $(nnuenet);\
else \
echo "No net found and download not possible"; exit 1;\
fi; \
fi; \
if [ "x$(shasum_command)" != "x" ]; then \
if [ "$(nnuenet)" != "nn-"`$(shasum_command) $(nnuenet) | cut -c1-12`".nnue" ]; then \
echo "Removing failed download"; rm -f $(nnuenet); \
fi; \
fi; \
done
@if ! test -f "$(nnuenet)"; then \
echo "Failed to download $(nnuenet)."; \
fi;
@if [ "x$(shasum_command)" != "x" ]; then \
if [ "$(nnuenet)" = "nn-"`$(shasum_command) $(nnuenet) | cut -c1-12`".nnue" ]; then \
echo "Network validated"; break; \
fi; \
fi;
endef
# set up shell variables for the net stuff
define netvariables
$(eval nnuenet := $(shell grep $(1) evaluate.h | grep define | sed 's/.*\(nn-[a-z0-9]\{12\}.nnue\).*/\1/'))
$(eval nnuedownloadurl1 := https://tests.stockfishchess.org/api/nn/$(nnuenet))
$(eval nnuedownloadurl2 := https://github.com/official-stockfish/networks/raw/master/$(nnuenet))
$(eval curl_or_wget := $(shell if hash curl 2>/dev/null; then echo "curl -skL"; elif hash wget 2>/dev/null; then echo "wget -qO-"; fi))
$(eval shasum_command := $(shell if hash shasum 2>/dev/null; then echo "shasum -a 256 "; elif hash sha256sum 2>/dev/null; then echo "sha256sum "; fi))
endef
# evaluation network (nnue)
net:
$(call netvariables, EvalFileDefaultNameBig)
$(call fetch_network)
$(call netvariables, EvalFileDefaultNameSmall)
$(call fetch_network)
format:
$(CLANG-FORMAT) -i $(SRCS) $(HEADERS) -style=file
# default target
default:
help
@@ -837,10 +1008,14 @@ config-sanity: net
@echo "ssse3: '$(ssse3)'"
@echo "sse41: '$(sse41)'"
@echo "avx2: '$(avx2)'"
@echo "avxvnni: '$(avxvnni)'"
@echo "avx512: '$(avx512)'"
@echo "vnni256: '$(vnni256)'"
@echo "vnni512: '$(vnni512)'"
@echo "neon: '$(neon)'"
@echo "dotprod: '$(dotprod)'"
@echo "arm_version: '$(arm_version)'"
@echo "target_windows: '$(target_windows)'"
@echo ""
@echo "Flags:"
@echo "CXX: $(CXX)"
@@ -854,7 +1029,7 @@ config-sanity: net
@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)" = "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"
@@ -869,12 +1044,16 @@ config-sanity: net
@test "$(vnni256)" = "yes" || test "$(vnni256)" = "no"
@test "$(vnni512)" = "yes" || test "$(vnni512)" = "no"
@test "$(neon)" = "yes" || test "$(neon)" = "no"
@test "$(comp)" = "gcc" || test "$(comp)" = "icc" || test "$(comp)" = "mingw" || test "$(comp)" = "clang" \
@test "$(comp)" = "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-instr-generate ' \
@@ -892,27 +1071,33 @@ 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
icc-profile-make:
@mkdir -p profdir
icx-profile-make:
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
EXTRACXXFLAGS='-prof-gen=srcpos -prof_dir ./profdir' \
EXTRACXXFLAGS='-fprofile-instr-generate ' \
EXTRALDFLAGS=' -fprofile-instr-generate' \
all
icc-profile-use:
icx-profile-use:
$(XCRUN) llvm-profdata merge -output=stockfish.profdata *.profraw
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
EXTRACXXFLAGS='-prof_use -prof_dir ./profdir' \
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
+61 -70
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -16,18 +16,19 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "benchmark.h"
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <istream>
#include <vector>
#include "position.h"
using namespace std;
namespace {
const vector<string> Defaults = {
// clang-format off
const std::vector<std::string> 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",
@@ -87,88 +88,78 @@ const vector<string> Defaults = {
// 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
} // namespace
} // namespace
namespace Stockfish {
/// setup_bench() builds a list of UCI commands to be run by bench. There
/// are five parameters: TT size in MB, number of search threads that
/// should be used, the limit value spent for each position, a file name
/// where to look for positions in FEN format, the type of the limit:
/// depth, perft, nodes and movetime (in millisecs), and evaluation type
/// mixed (default), classical, NNUE.
///
/// bench -> search default positions up to depth 13
/// bench 64 1 15 -> search default positions up to depth 15 (TT = 64MB)
/// bench 64 4 5000 current movetime -> search current position with 4 threads for 5 sec
/// bench 64 1 100000 default nodes -> search default positions for 100K nodes each
/// bench 16 1 5 default perft -> run a perft 5 on default positions
// 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<std::string> setup_bench(const Position& current, std::istream& is) {
vector<string> setup_bench(const Position& current, istream& is) {
std::vector<std::string> fens, list;
std::string go, token;
vector<string> fens, list;
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";
// Assign default values to missing arguments
string ttSize = (is >> token) ? token : "16";
string threads = (is >> token) ? token : "1";
string limit = (is >> token) ? token : "13";
string fenFile = (is >> token) ? token : "default";
string limitType = (is >> token) ? token : "depth";
string evalType = (is >> token) ? token : "mixed";
go = limitType == "eval" ? "eval" : "go " + limitType + " " + limit;
go = limitType == "eval" ? "eval" : "go " + limitType + " " + limit;
if (fenFile == "default")
fens = Defaults;
if (fenFile == "default")
fens = Defaults;
else if (fenFile == "current")
fens.push_back(current.fen());
else if (fenFile == "current")
fens.push_back(current.fen());
else
{
std::string fen;
std::ifstream file(fenFile);
else
{
string fen;
ifstream file(fenFile);
if (!file.is_open())
{
std::cerr << "Unable to open file " << fenFile << std::endl;
exit(EXIT_FAILURE);
}
if (!file.is_open())
{
cerr << "Unable to open file " << fenFile << endl;
exit(EXIT_FAILURE);
}
while (getline(file, fen))
if (!fen.empty())
fens.push_back(fen);
while (getline(file, fen))
if (!fen.empty())
fens.push_back(fen);
file.close();
}
file.close();
}
list.emplace_back("setoption name Threads value " + threads);
list.emplace_back("setoption name Hash value " + ttSize);
list.emplace_back("ucinewgame");
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);
}
size_t posCounter = 0;
for (const string& fen : fens)
if (fen.find("setoption") != string::npos)
list.emplace_back(fen);
else
{
if (evalType == "classical" || (evalType == "mixed" && posCounter % 2 == 0))
list.emplace_back("setoption name Use NNUE value false");
else if (evalType == "NNUE" || (evalType == "mixed" && posCounter % 2 != 0))
list.emplace_back("setoption name Use NNUE value true");
list.emplace_back("position fen " + fen);
list.emplace_back(go);
++posCounter;
}
list.emplace_back("setoption name Use NNUE value true");
return list;
return list;
}
} // namespace Stockfish
} // namespace Stockfish
+11 -15
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -16,23 +16,19 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef BENCHMARK_H_INCLUDED
#define BENCHMARK_H_INCLUDED
#ifndef PSQT_H_INCLUDED
#define PSQT_H_INCLUDED
#include <iosfwd>
#include <string>
#include <vector>
namespace Stockfish {
#include "types.h"
class Position;
std::vector<std::string> setup_bench(const Position&, std::istream&);
namespace Stockfish::PSQT
{
} // namespace Stockfish
extern Score psq[PIECE_NB][SQUARE_NB];
// Fill psqt array from a set of internally linked parameters
extern void init();
} // namespace Stockfish::PSQT
#endif // PSQT_H_INCLUDED
#endif // #ifndef BENCHMARK_H_INCLUDED
-172
View File
@@ -1,172 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 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 <http://www.gnu.org/licenses/>.
*/
#include <cassert>
#include <vector>
#include <bitset>
#include "bitboard.h"
#include "types.h"
namespace Stockfish {
namespace {
// There are 24 possible pawn squares: files A to D and ranks from 2 to 7.
// Positions with the pawn on files E to H will be mirrored before probing.
constexpr unsigned MAX_INDEX = 2*24*64*64; // stm * psq * wksq * bksq = 196608
std::bitset<MAX_INDEX> KPKBitbase;
// A KPK bitbase index is an integer in [0, IndexMax] range
//
// Information is mapped in a way that minimizes the number of iterations:
//
// bit 0- 5: white king square (from SQ_A1 to SQ_H8)
// bit 6-11: black king square (from SQ_A1 to SQ_H8)
// bit 12: side to move (WHITE or BLACK)
// bit 13-14: white pawn file (from FILE_A to FILE_D)
// bit 15-17: white pawn RANK_7 - rank (from RANK_7 - RANK_7 to RANK_7 - RANK_2)
unsigned index(Color stm, Square bksq, Square wksq, Square psq) {
return int(wksq) | (bksq << 6) | (stm << 12) | (file_of(psq) << 13) | ((RANK_7 - rank_of(psq)) << 15);
}
enum Result {
INVALID = 0,
UNKNOWN = 1,
DRAW = 2,
WIN = 4
};
Result& operator|=(Result& r, Result v) { return r = Result(r | v); }
struct KPKPosition {
KPKPosition() = default;
explicit KPKPosition(unsigned idx);
operator Result() const { return result; }
Result classify(const std::vector<KPKPosition>& db);
Color stm;
Square ksq[COLOR_NB], psq;
Result result;
};
} // namespace
bool Bitbases::probe(Square wksq, Square wpsq, Square bksq, Color stm) {
assert(file_of(wpsq) <= FILE_D);
return KPKBitbase[index(stm, bksq, wksq, wpsq)];
}
void Bitbases::init() {
std::vector<KPKPosition> db(MAX_INDEX);
unsigned idx, repeat = 1;
// Initialize db with known win / draw positions
for (idx = 0; idx < MAX_INDEX; ++idx)
db[idx] = KPKPosition(idx);
// Iterate through the positions until none of the unknown positions can be
// changed to either wins or draws (15 cycles needed).
while (repeat)
for (repeat = idx = 0; idx < MAX_INDEX; ++idx)
repeat |= (db[idx] == UNKNOWN && db[idx].classify(db) != UNKNOWN);
// Fill the bitbase with the decisive results
for (idx = 0; idx < MAX_INDEX; ++idx)
if (db[idx] == WIN)
KPKBitbase.set(idx);
}
namespace {
KPKPosition::KPKPosition(unsigned idx) {
ksq[WHITE] = Square((idx >> 0) & 0x3F);
ksq[BLACK] = Square((idx >> 6) & 0x3F);
stm = Color ((idx >> 12) & 0x01);
psq = make_square(File((idx >> 13) & 0x3), Rank(RANK_7 - ((idx >> 15) & 0x7)));
// Invalid if two pieces are on the same square or if a king can be captured
if ( distance(ksq[WHITE], ksq[BLACK]) <= 1
|| ksq[WHITE] == psq
|| ksq[BLACK] == psq
|| (stm == WHITE && (pawn_attacks_bb(WHITE, psq) & ksq[BLACK])))
result = INVALID;
// Win if the pawn can be promoted without getting captured
else if ( stm == WHITE
&& rank_of(psq) == RANK_7
&& ksq[WHITE] != psq + NORTH
&& ( distance(ksq[BLACK], psq + NORTH) > 1
|| (distance(ksq[WHITE], psq + NORTH) == 1)))
result = WIN;
// Draw if it is stalemate or the black king can capture the pawn
else if ( stm == BLACK
&& ( !(attacks_bb<KING>(ksq[BLACK]) & ~(attacks_bb<KING>(ksq[WHITE]) | pawn_attacks_bb(WHITE, psq)))
|| (attacks_bb<KING>(ksq[BLACK]) & ~attacks_bb<KING>(ksq[WHITE]) & psq)))
result = DRAW;
// Position will be classified later
else
result = UNKNOWN;
}
Result KPKPosition::classify(const std::vector<KPKPosition>& db) {
// White to move: If one move leads to a position classified as WIN, the result
// of the current position is WIN. If all moves lead to positions classified
// as DRAW, the current position is classified as DRAW, otherwise the current
// position is classified as UNKNOWN.
//
// Black to move: If one move leads to a position classified as DRAW, the result
// of the current position is DRAW. If all moves lead to positions classified
// as WIN, the position is classified as WIN, otherwise the current position is
// classified as UNKNOWN.
const Result Good = (stm == WHITE ? WIN : DRAW);
const Result Bad = (stm == WHITE ? DRAW : WIN);
Result r = INVALID;
Bitboard b = attacks_bb<KING>(ksq[stm]);
while (b)
r |= stm == WHITE ? db[index(BLACK, ksq[BLACK], pop_lsb(b), psq)]
: db[index(WHITE, pop_lsb(b), ksq[WHITE], psq)];
if (stm == WHITE)
{
if (rank_of(psq) < RANK_7) // Single push
r |= db[index(BLACK, ksq[BLACK], ksq[WHITE], psq + NORTH)];
if ( rank_of(psq) == RANK_2 // Double push
&& psq + NORTH != ksq[WHITE]
&& psq + NORTH != ksq[BLACK])
r |= db[index(BLACK, ksq[BLACK], ksq[WHITE], psq + NORTH + NORTH)];
}
return result = r & Good ? Good : r & UNKNOWN ? UNKNOWN : Bad;
}
} // namespace
} // namespace Stockfish
+74 -80
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -16,10 +16,12 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "bitboard.h"
#include <algorithm>
#include <bitset>
#include <initializer_list>
#include "bitboard.h"
#include "misc.h"
namespace Stockfish {
@@ -27,7 +29,6 @@ namespace Stockfish {
uint8_t PopCnt16[1 << 16];
uint8_t SquareDistance[SQUARE_NB][SQUARE_NB];
Bitboard SquareBB[SQUARE_NB];
Bitboard LineBB[SQUARE_NB][SQUARE_NB];
Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB];
@@ -38,93 +39,86 @@ Magic BishopMagics[SQUARE_NB];
namespace {
Bitboard RookTable[0x19000]; // To store rook attacks
Bitboard BishopTable[0x1480]; // To store bishop attacks
Bitboard RookTable[0x19000]; // To store rook attacks
Bitboard BishopTable[0x1480]; // To store bishop attacks
void init_magics(PieceType pt, Bitboard table[], Magic magics[]);
void init_magics(PieceType pt, Bitboard table[], Magic magics[]);
}
/// safe_destination() returns the bitboard of target square for the given step
/// from the given square. If the step is off the board, returns empty bitboard.
inline Bitboard safe_destination(Square s, int step) {
// 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);
}
}
/// Bitboards::pretty() returns an ASCII representation of a bitboard suitable
/// to be printed to standard output. Useful for debugging.
// 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";
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 " : "| ";
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";
s += "| " + std::to_string(1 + r) + "\n+---+---+---+---+---+---+---+---+\n";
}
s += " a b c d e f g h\n";
return s;
return s;
}
/// Bitboards::init() initializes various bitboard tables. It is called at
/// startup and relies on global objects to be already zero-initialized.
// 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 (unsigned i = 0; i < (1 << 16); ++i)
PopCnt16[i] = uint8_t(std::bitset<16>(i).count());
for (Square s = SQ_A1; s <= SQ_H8; ++s)
SquareBB[s] = (1ULL << s);
for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2)
SquareDistance[s1][s2] = std::max(distance<File>(s1, s2), distance<Rank>(s1, s2));
for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2)
SquareDistance[s1][s2] = std::max(distance<File>(s1, s2), distance<Rank>(s1, s2));
init_magics(ROOK, RookTable, RookMagics);
init_magics(BISHOP, BishopTable, BishopMagics);
init_magics(ROOK, RookTable, RookMagics);
init_magics(BISHOP, BishopTable, BishopMagics);
for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
{
PawnAttacks[WHITE][s1] = pawn_attacks_bb<WHITE>(square_bb(s1));
PawnAttacks[BLACK][s1] = pawn_attacks_bb<BLACK>(square_bb(s1));
for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
{
PawnAttacks[WHITE][s1] = pawn_attacks_bb<WHITE>(square_bb(s1));
PawnAttacks[BLACK][s1] = pawn_attacks_bb<BLACK>(square_bb(s1));
for (int step : {-9, -8, -7, -1, 1, 7, 8, 9})
PseudoAttacks[KING][s1] |= safe_destination(s1, step);
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);
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<BISHOP>(s1, 0);
PseudoAttacks[QUEEN][s1] |= PseudoAttacks[ROOK][s1] = attacks_bb<ROOK>(s1, 0);
PseudoAttacks[QUEEN][s1] = PseudoAttacks[BISHOP][s1] = attacks_bb<BISHOP>(s1, 0);
PseudoAttacks[QUEEN][s1] |= PseudoAttacks[ ROOK][s1] = attacks_bb< ROOK>(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;
}
}
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 sliding_attack(PieceType pt, Square sq, Bitboard occupied) {
Bitboard attacks = 0;
Direction RookDirections[4] = {NORTH, SOUTH, EAST, WEST};
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))
@@ -135,22 +129,21 @@ namespace {
}
return attacks;
}
}
// init_magics() computes all rook and bishop attacks at startup. Magic
// bitboards are used to look up attacks of sliding pieces. As a reference see
// www.chessprogramming.org/Magic_Bitboards. In particular, here we use the so
// called "fancy" approach.
void init_magics(PieceType pt, Bitboard table[], Magic magics[]) {
// Computes all rook and bishop attacks at startup. Magic
// bitboards are used to look up attacks of sliding pieces. As a reference see
// www.chessprogramming.org/Magic_Bitboards. In particular, here we use the so
// called "fancy" approach.
void init_magics(PieceType pt, Bitboard table[], Magic magics[]) {
// 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 } };
int seeds[][RANK_NB] = {{8977, 44560, 54343, 38998, 5731, 95205, 104912, 17020},
{728, 10316, 55013, 32803, 12281, 15100, 16645, 255}};
Bitboard occupancy[4096], reference[4096], edges, b;
int epoch[4096] = {}, cnt = 0, size = 0;
int epoch[4096] = {}, cnt = 0, size = 0;
for (Square s = SQ_A1; s <= SQ_H8; ++s)
{
@@ -163,8 +156,8 @@ namespace {
// 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];
m.mask = sliding_attack(pt, s, 0) & ~edges;
m.shift = (Is64Bit ? 64 : 32) - popcount(m.mask);
m.mask = sliding_attack(pt, s, 0) & ~edges;
m.shift = (Is64Bit ? 64 : 32) - popcount(m.mask);
// Set the offset for the attacks table of the square. We have individual
// table sizes for each square with "Fancy Magic Bitboards".
@@ -173,7 +166,8 @@ namespace {
// Use Carry-Rippler trick to enumerate all subsets of masks[s] and
// store the corresponding sliding attack bitboard in reference[].
b = size = 0;
do {
do
{
occupancy[size] = b;
reference[size] = sliding_attack(pt, s, b);
@@ -191,9 +185,9 @@ namespace {
// 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 (int i = 0; i < size;)
{
for (m.magic = 0; popcount((m.magic * m.mask) >> 56) < 6; )
for (m.magic = 0; popcount((m.magic * m.mask) >> 56) < 6;)
m.magic = rng.sparse_rand<Bitboard>();
// A good magic must map every possible occupancy to an index that
@@ -208,7 +202,7 @@ namespace {
if (epoch[idx] < cnt)
{
epoch[idx] = cnt;
epoch[idx] = cnt;
m.attacks[idx] = reference[i];
}
else if (m.attacks[idx] != reference[i])
@@ -216,7 +210,7 @@ namespace {
}
}
}
}
}
}
} // namespace Stockfish
} // namespace Stockfish
+210 -290
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -19,28 +19,23 @@
#ifndef BITBOARD_H_INCLUDED
#define BITBOARD_H_INCLUDED
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <string>
#include "types.h"
namespace Stockfish {
namespace Bitbases {
void init();
bool probe(Square wksq, Square wpsq, Square bksq, Color us);
} // namespace Stockfish::Bitbases
namespace Bitboards {
void init();
void init();
std::string pretty(Bitboard b);
} // namespace Stockfish::Bitboards
constexpr Bitboard AllSquares = ~Bitboard(0);
constexpr Bitboard DarkSquares = 0xAA55AA55AA55AA55ULL;
} // namespace Stockfish::Bitboards
constexpr Bitboard FileABB = 0x0101010101010101ULL;
constexpr Bitboard FileBBB = FileABB << 1;
@@ -60,392 +55,317 @@ constexpr Bitboard Rank6BB = Rank1BB << (8 * 5);
constexpr Bitboard Rank7BB = Rank1BB << (8 * 6);
constexpr Bitboard Rank8BB = Rank1BB << (8 * 7);
constexpr Bitboard QueenSide = FileABB | FileBBB | FileCBB | FileDBB;
constexpr Bitboard CenterFiles = FileCBB | FileDBB | FileEBB | FileFBB;
constexpr Bitboard KingSide = FileEBB | FileFBB | FileGBB | FileHBB;
constexpr Bitboard Center = (FileDBB | FileEBB) & (Rank4BB | Rank5BB);
constexpr Bitboard KingFlank[FILE_NB] = {
QueenSide ^ FileDBB, QueenSide, QueenSide,
CenterFiles, CenterFiles,
KingSide, KingSide, KingSide ^ FileEBB
};
extern uint8_t PopCnt16[1 << 16];
extern uint8_t SquareDistance[SQUARE_NB][SQUARE_NB];
extern Bitboard SquareBB[SQUARE_NB];
extern Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
extern Bitboard LineBB[SQUARE_NB][SQUARE_NB];
extern Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB];
extern Bitboard PawnAttacks[COLOR_NB][SQUARE_NB];
/// Magic holds all magic bitboards relevant data for a single square
// Magic holds all magic bitboards relevant data for a single square
struct Magic {
Bitboard mask;
Bitboard magic;
Bitboard* attacks;
unsigned shift;
Bitboard mask;
Bitboard magic;
Bitboard* attacks;
unsigned shift;
// Compute the attack's index using the 'magic bitboards' approach
unsigned index(Bitboard occupied) const {
// Compute the attack's index using the 'magic bitboards' approach
unsigned index(Bitboard occupied) const {
if (HasPext)
return unsigned(pext(occupied, mask));
if (HasPext)
return unsigned(pext(occupied, mask));
if (Is64Bit)
return unsigned(((occupied & mask) * magic) >> shift);
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;
}
unsigned lo = unsigned(occupied) & unsigned(mask);
unsigned hi = unsigned(occupied >> 32) & unsigned(mask >> 32);
return (lo * unsigned(magic) ^ hi * unsigned(magic >> 32)) >> shift;
}
};
extern Magic RookMagics[SQUARE_NB];
extern Magic BishopMagics[SQUARE_NB];
inline Bitboard square_bb(Square s) {
assert(is_ok(s));
return SquareBB[s];
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.
// Overloads of bitwise operators between a Bitboard and a Square for testing
// whether a given bit is set in a bitboard, and for setting and clearing bits.
inline Bitboard operator&( Bitboard b, Square s) { return b & square_bb(s); }
inline Bitboard operator|( Bitboard b, Square s) { return b | square_bb(s); }
inline Bitboard operator^( Bitboard b, Square s) { return b ^ square_bb(s); }
inline Bitboard operator&(Bitboard b, Square s) { return b & square_bb(s); }
inline Bitboard operator|(Bitboard b, Square s) { return b | square_bb(s); }
inline Bitboard operator^(Bitboard b, Square s) { return b ^ square_bb(s); }
inline Bitboard& operator|=(Bitboard& b, Square s) { return b |= square_bb(s); }
inline Bitboard& operator^=(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 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; }
inline Bitboard operator|(Square s1, Square s2) { return square_bb(s1) | s2; }
constexpr bool more_than_one(Bitboard b) {
return b & (b - 1);
}
constexpr bool more_than_one(Bitboard b) { return b & (b - 1); }
constexpr bool opposite_colors(Square s1, Square s2) {
return (s1 + rank_of(s1) + s2 + rank_of(s2)) & 1;
}
// rank_bb() and file_bb() return a bitboard representing all the squares on
// the given file or rank.
constexpr Bitboard rank_bb(Rank r) { return Rank1BB << (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)); }
/// 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));
}
/// shift() moves a bitboard one or two steps as specified by the direction D
// Moves a bitboard one or two steps as specified by the direction D
template<Direction D>
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;
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;
}
/// pawn_attacks_bb() returns the squares attacked by pawns of the given color
/// from the squares in the given bitboard.
// Returns the squares attacked by pawns of the given color
// from the squares in the given bitboard.
template<Color C>
constexpr Bitboard pawn_attacks_bb(Bitboard b) {
return C == WHITE ? shift<NORTH_WEST>(b) | shift<NORTH_EAST>(b)
: shift<SOUTH_WEST>(b) | shift<SOUTH_EAST>(b);
return C == WHITE ? shift<NORTH_WEST>(b) | shift<NORTH_EAST>(b)
: shift<SOUTH_WEST>(b) | shift<SOUTH_EAST>(b);
}
inline Bitboard pawn_attacks_bb(Color c, Square s) {
assert(is_ok(s));
return PawnAttacks[c][s];
assert(is_ok(s));
return PawnAttacks[c][s];
}
/// pawn_double_attacks_bb() returns the squares doubly attacked by pawns of the
/// given color from the squares in the given bitboard.
template<Color C>
constexpr Bitboard pawn_double_attacks_bb(Bitboard b) {
return C == WHITE ? shift<NORTH_WEST>(b) & shift<NORTH_EAST>(b)
: shift<SOUTH_WEST>(b) & shift<SOUTH_EAST>(b);
}
/// adjacent_files_bb() returns a bitboard representing all the squares on the
/// adjacent files of a given square.
constexpr Bitboard adjacent_files_bb(Square s) {
return shift<EAST>(file_bb(s)) | shift<WEST>(file_bb(s));
}
/// line_bb() returns a bitboard representing an entire line (from board edge
/// to board edge) that intersects the two given squares. If the given squares
/// are not on a same file/rank/diagonal, the function returns 0. For instance,
/// line_bb(SQ_C4, SQ_F7) will return a bitboard with the A2-G8 diagonal.
// 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];
assert(is_ok(s1) && is_ok(s2));
return LineBB[s1][s2];
}
/// between_bb(s1, s2) returns a bitboard representing the squares in the semi-open
/// segment between the squares s1 and s2 (excluding s1 but including s2). If the
/// given squares are not on a same file/rank/diagonal, it returns s2. For instance,
/// between_bb(SQ_C4, SQ_F7) will return a bitboard with squares D5, E6 and F7, but
/// between_bb(SQ_E6, SQ_F8) will return a bitboard with the square F8. This trick
/// allows to generate non-king evasion moves faster: the defending piece must either
/// interpose itself to cover the check or capture the checking piece.
// 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];
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; }
/// forward_ranks_bb() returns a bitboard representing the squares on the ranks in
/// front of the given one, from the point of view of the given color. For instance,
/// forward_ranks_bb(BLACK, SQ_D3) will return the 16 squares on ranks 1 and 2.
constexpr Bitboard forward_ranks_bb(Color c, Square s) {
return c == WHITE ? ~Rank1BB << 8 * relative_rank(WHITE, s)
: ~Rank8BB >> 8 * relative_rank(BLACK, s);
// distance() functions return the distance between x and y, defined as the
// number of steps for a king in x to reach y.
template<typename T1 = Square>
inline int distance(Square x, Square y);
template<>
inline int distance<File>(Square x, Square y) {
return std::abs(file_of(x) - file_of(y));
}
/// forward_file_bb() returns a bitboard representing all the squares along the
/// line in front of the given one, from the point of view of the given color.
constexpr Bitboard forward_file_bb(Color c, Square s) {
return forward_ranks_bb(c, s) & file_bb(s);
template<>
inline int distance<Rank>(Square x, Square y) {
return std::abs(rank_of(x) - rank_of(y));
}
/// pawn_attack_span() returns a bitboard representing all the squares that can
/// be attacked by a pawn of the given color when it moves along its file, starting
/// from the given square.
constexpr Bitboard pawn_attack_span(Color c, Square s) {
return forward_ranks_bb(c, s) & adjacent_files_bb(s);
template<>
inline int distance<Square>(Square x, Square y) {
return SquareDistance[x][y];
}
/// passed_pawn_span() returns a bitboard which can be used to test if a pawn of
/// the given color and on the given square is a passed pawn.
constexpr Bitboard passed_pawn_span(Color c, Square s) {
return pawn_attack_span(c, s) | forward_file_bb(c, s);
}
/// aligned() returns true if the squares s1, s2 and s3 are aligned either on a
/// straight or on a diagonal line.
inline bool aligned(Square s1, Square s2, Square s3) {
return line_bb(s1, s2) & s3;
}
/// distance() functions return the distance between x and y, defined as the
/// number of steps for a king in x to reach y.
template<typename T1 = Square> inline int distance(Square x, Square y);
template<> inline int distance<File>(Square x, Square y) { return std::abs(file_of(x) - file_of(y)); }
template<> inline int distance<Rank>(Square x, Square y) { return std::abs(rank_of(x) - rank_of(y)); }
template<> inline int distance<Square>(Square x, Square y) { return SquareDistance[x][y]; }
inline int edge_distance(File f) { return std::min(f, File(FILE_H - f)); }
inline int edge_distance(Rank r) { return std::min(r, Rank(RANK_8 - r)); }
/// attacks_bb(Square) returns the pseudo attacks of the give piece type
/// assuming an empty board.
// Returns the pseudo attacks of the given piece type
// assuming an empty board.
template<PieceType Pt>
inline Bitboard attacks_bb(Square s) {
assert((Pt != PAWN) && (is_ok(s)));
return PseudoAttacks[Pt][s];
assert((Pt != PAWN) && (is_ok(s)));
return PseudoAttacks[Pt][s];
}
/// attacks_bb(Square, Bitboard) returns the attacks by the given piece
/// assuming the board is occupied according to the passed Bitboard.
/// Sliding piece attacks do not continue passed an occupied square.
// 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<PieceType Pt>
inline Bitboard attacks_bb(Square s, Bitboard occupied) {
assert((Pt != PAWN) && (is_ok(s)));
assert((Pt != PAWN) && (is_ok(s)));
switch (Pt)
{
case BISHOP: return BishopMagics[s].attacks[BishopMagics[s].index(occupied)];
case ROOK : return RookMagics[s].attacks[ RookMagics[s].index(occupied)];
case QUEEN : return attacks_bb<BISHOP>(s, occupied) | attacks_bb<ROOK>(s, occupied);
default : return PseudoAttacks[Pt][s];
}
switch (Pt)
{
case BISHOP :
return BishopMagics[s].attacks[BishopMagics[s].index(occupied)];
case ROOK :
return RookMagics[s].attacks[RookMagics[s].index(occupied)];
case QUEEN :
return attacks_bb<BISHOP>(s, occupied) | attacks_bb<ROOK>(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)));
assert((pt != PAWN) && (is_ok(s)));
switch (pt)
{
case BISHOP: return attacks_bb<BISHOP>(s, occupied);
case ROOK : return attacks_bb< ROOK>(s, occupied);
case QUEEN : return attacks_bb<BISHOP>(s, occupied) | attacks_bb<ROOK>(s, occupied);
default : return PseudoAttacks[pt][s];
}
switch (pt)
{
case BISHOP :
return attacks_bb<BISHOP>(s, occupied);
case ROOK :
return attacks_bb<ROOK>(s, occupied);
case QUEEN :
return attacks_bb<BISHOP>(s, occupied) | attacks_bb<ROOK>(s, occupied);
default :
return PseudoAttacks[pt][s];
}
}
/// popcount() counts the number of non-zero bits in a bitboard
// Counts the number of non-zero bits in a bitboard.
inline int popcount(Bitboard b) {
#ifndef USE_POPCNT
union { Bitboard bb; uint16_t u[4]; } v = { b };
return PopCnt16[v.u[0]] + PopCnt16[v.u[1]] + PopCnt16[v.u[2]] + PopCnt16[v.u[3]];
union {
Bitboard bb;
uint16_t u[4];
} v = {b};
return PopCnt16[v.u[0]] + PopCnt16[v.u[1]] + PopCnt16[v.u[2]] + PopCnt16[v.u[3]];
#elif defined(_MSC_VER) || defined(__INTEL_COMPILER)
#elif defined(_MSC_VER)
return (int)_mm_popcnt_u64(b);
return int(_mm_popcnt_u64(b));
#else // Assumed gcc or compatible compiler
#else // Assumed gcc or compatible compiler
return __builtin_popcountll(b);
return __builtin_popcountll(b);
#endif
}
/// lsb() and msb() return the least/most significant bit in a non-zero bitboard
#if defined(__GNUC__) // GCC, Clang, ICC
// Returns the least significant bit in a non-zero bitboard.
inline Square lsb(Bitboard b) {
assert(b);
return Square(__builtin_ctzll(b));
}
assert(b);
inline Square msb(Bitboard b) {
assert(b);
return Square(63 ^ __builtin_clzll(b));
}
#if defined(__GNUC__) // GCC, Clang, ICX
#elif defined(_MSC_VER) // MSVC
return Square(__builtin_ctzll(b));
#ifdef _WIN64 // MSVC, WIN64
#elif defined(_MSC_VER)
#ifdef _WIN64 // MSVC, WIN64
inline Square lsb(Bitboard b) {
assert(b);
unsigned long idx;
_BitScanForward64(&idx, b);
return (Square) idx;
}
unsigned long idx;
_BitScanForward64(&idx, b);
return Square(idx);
inline Square msb(Bitboard b) {
assert(b);
unsigned long idx;
_BitScanReverse64(&idx, b);
return (Square) idx;
}
#else // MSVC, WIN32
inline Square lsb(Bitboard b) {
assert(b);
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);
}
}
inline Square msb(Bitboard b) {
assert(b);
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 // 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."
#error "Compiler not supported."
#endif
}
/// least_significant_square_bb() returns the bitboard of the least significant
/// square of a non-zero bitboard. It is equivalent to square_bb(lsb(bb)).
// 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;
assert(b);
return b & -b;
}
/// pop_lsb() finds and clears the least significant bit in a non-zero bitboard
// 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;
assert(b);
const Square s = lsb(b);
b &= b - 1;
return s;
}
} // namespace Stockfish
/// frontmost_sq() returns the most advanced square for the given color,
/// requires a non-zero bitboard.
inline Square frontmost_sq(Color c, Bitboard b) {
assert(b);
return c == WHITE ? msb(b) : lsb(b);
}
} // namespace Stockfish
#endif // #ifndef BITBOARD_H_INCLUDED
#endif // #ifndef BITBOARD_H_INCLUDED
-747
View File
@@ -1,747 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 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 <http://www.gnu.org/licenses/>.
*/
#include <cassert>
#include "bitboard.h"
#include "endgame.h"
#include "movegen.h"
namespace Stockfish {
namespace {
// Used to drive the king towards the edge of the board
// in KX vs K and KQ vs KR endgames.
// Values range from 27 (center squares) to 90 (in the corners)
inline int push_to_edge(Square s) {
int rd = edge_distance(rank_of(s)), fd = edge_distance(file_of(s));
return 90 - (7 * fd * fd / 2 + 7 * rd * rd / 2);
}
// Used to drive the king towards A1H8 corners in KBN vs K endgames.
// Values range from 0 on A8H1 diagonal to 7 in A1H8 corners
inline int push_to_corner(Square s) {
return abs(7 - rank_of(s) - file_of(s));
}
// Drive a piece close to or away from another piece
inline int push_close(Square s1, Square s2) { return 140 - 20 * distance(s1, s2); }
inline int push_away(Square s1, Square s2) { return 120 - push_close(s1, s2); }
#ifndef NDEBUG
bool verify_material(const Position& pos, Color c, Value npm, int pawnsCnt) {
return pos.non_pawn_material(c) == npm && pos.count<PAWN>(c) == pawnsCnt;
}
#endif
// Map the square as if strongSide is white and strongSide's only pawn
// is on the left half of the board.
Square normalize(const Position& pos, Color strongSide, Square sq) {
assert(pos.count<PAWN>(strongSide) == 1);
if (file_of(pos.square<PAWN>(strongSide)) >= FILE_E)
sq = flip_file(sq);
return strongSide == WHITE ? sq : flip_rank(sq);
}
} // namespace
namespace Endgames {
std::pair<Map<Value>, Map<ScaleFactor>> maps;
void init() {
add<KPK>("KPK");
add<KNNK>("KNNK");
add<KBNK>("KBNK");
add<KRKP>("KRKP");
add<KRKB>("KRKB");
add<KRKN>("KRKN");
add<KQKP>("KQKP");
add<KQKR>("KQKR");
add<KNNKP>("KNNKP");
add<KRPKR>("KRPKR");
add<KRPKB>("KRPKB");
add<KBPKB>("KBPKB");
add<KBPKN>("KBPKN");
add<KBPPKB>("KBPPKB");
add<KRPPKRP>("KRPPKRP");
}
}
/// Mate with KX vs K. This function is used to evaluate positions with
/// king and plenty of material vs a lone king. It simply gives the
/// attacking side a bonus for driving the defending king towards the edge
/// of the board, and for keeping the distance between the two kings small.
template<>
Value Endgame<KXK>::operator()(const Position& pos) const {
assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
assert(!pos.checkers()); // Eval is never called when in check
// Stalemate detection with lone king
if (pos.side_to_move() == weakSide && !MoveList<LEGAL>(pos).size())
return VALUE_DRAW;
Square strongKing = pos.square<KING>(strongSide);
Square weakKing = pos.square<KING>(weakSide);
Value result = pos.non_pawn_material(strongSide)
+ pos.count<PAWN>(strongSide) * PawnValueEg
+ push_to_edge(weakKing)
+ push_close(strongKing, weakKing);
if ( pos.count<QUEEN>(strongSide)
|| pos.count<ROOK>(strongSide)
||(pos.count<BISHOP>(strongSide) && pos.count<KNIGHT>(strongSide))
|| ( (pos.pieces(strongSide, BISHOP) & ~DarkSquares)
&& (pos.pieces(strongSide, BISHOP) & DarkSquares)))
result = std::min(result + VALUE_KNOWN_WIN, VALUE_TB_WIN_IN_MAX_PLY - 1);
return strongSide == pos.side_to_move() ? result : -result;
}
/// Mate with KBN vs K. This is similar to KX vs K, but we have to drive the
/// defending king towards a corner square that our bishop attacks.
template<>
Value Endgame<KBNK>::operator()(const Position& pos) const {
assert(verify_material(pos, strongSide, KnightValueMg + BishopValueMg, 0));
assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
Square strongKing = pos.square<KING>(strongSide);
Square strongBishop = pos.square<BISHOP>(strongSide);
Square weakKing = pos.square<KING>(weakSide);
// If our bishop does not attack A1/H8, we flip the enemy king square
// to drive to opposite corners (A8/H1).
Value result = (VALUE_KNOWN_WIN + 3520)
+ push_close(strongKing, weakKing)
+ 420 * push_to_corner(opposite_colors(strongBishop, SQ_A1) ? flip_file(weakKing) : weakKing);
assert(abs(result) < VALUE_TB_WIN_IN_MAX_PLY);
return strongSide == pos.side_to_move() ? result : -result;
}
/// KP vs K. This endgame is evaluated with the help of a bitbase
template<>
Value Endgame<KPK>::operator()(const Position& pos) const {
assert(verify_material(pos, strongSide, VALUE_ZERO, 1));
assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
// Assume strongSide is white and the pawn is on files A-D
Square strongKing = normalize(pos, strongSide, pos.square<KING>(strongSide));
Square strongPawn = normalize(pos, strongSide, pos.square<PAWN>(strongSide));
Square weakKing = normalize(pos, strongSide, pos.square<KING>(weakSide));
Color us = strongSide == pos.side_to_move() ? WHITE : BLACK;
if (!Bitbases::probe(strongKing, strongPawn, weakKing, us))
return VALUE_DRAW;
Value result = VALUE_KNOWN_WIN + PawnValueEg + Value(rank_of(strongPawn));
return strongSide == pos.side_to_move() ? result : -result;
}
/// KR vs KP. This is a somewhat tricky endgame to evaluate precisely without
/// a bitbase. The function below returns drawish scores when the pawn is
/// far advanced with support of the king, while the attacking king is far
/// away.
template<>
Value Endgame<KRKP>::operator()(const Position& pos) const {
assert(verify_material(pos, strongSide, RookValueMg, 0));
assert(verify_material(pos, weakSide, VALUE_ZERO, 1));
Square strongKing = pos.square<KING>(strongSide);
Square weakKing = pos.square<KING>(weakSide);
Square strongRook = pos.square<ROOK>(strongSide);
Square weakPawn = pos.square<PAWN>(weakSide);
Square queeningSquare = make_square(file_of(weakPawn), relative_rank(weakSide, RANK_8));
Value result;
// If the stronger side's king is in front of the pawn, it's a win
if (forward_file_bb(strongSide, strongKing) & weakPawn)
result = RookValueEg - distance(strongKing, weakPawn);
// If the weaker side's king is too far from the pawn and the rook,
// it's a win.
else if ( distance(weakKing, weakPawn) >= 3 + (pos.side_to_move() == weakSide)
&& distance(weakKing, strongRook) >= 3)
result = RookValueEg - distance(strongKing, weakPawn);
// If the pawn is far advanced and supported by the defending king,
// the position is drawish
else if ( relative_rank(strongSide, weakKing) <= RANK_3
&& distance(weakKing, weakPawn) == 1
&& relative_rank(strongSide, strongKing) >= RANK_4
&& distance(strongKing, weakPawn) > 2 + (pos.side_to_move() == strongSide))
result = Value(80) - 8 * distance(strongKing, weakPawn);
else
result = Value(200) - 8 * ( distance(strongKing, weakPawn + pawn_push(weakSide))
- distance(weakKing, weakPawn + pawn_push(weakSide))
- distance(weakPawn, queeningSquare));
return strongSide == pos.side_to_move() ? result : -result;
}
/// KR vs KB. This is very simple, and always returns drawish scores. The
/// score is slightly bigger when the defending king is close to the edge.
template<>
Value Endgame<KRKB>::operator()(const Position& pos) const {
assert(verify_material(pos, strongSide, RookValueMg, 0));
assert(verify_material(pos, weakSide, BishopValueMg, 0));
Value result = Value(push_to_edge(pos.square<KING>(weakSide)));
return strongSide == pos.side_to_move() ? result : -result;
}
/// KR vs KN. The attacking side has slightly better winning chances than
/// in KR vs KB, particularly if the king and the knight are far apart.
template<>
Value Endgame<KRKN>::operator()(const Position& pos) const {
assert(verify_material(pos, strongSide, RookValueMg, 0));
assert(verify_material(pos, weakSide, KnightValueMg, 0));
Square weakKing = pos.square<KING>(weakSide);
Square weakKnight = pos.square<KNIGHT>(weakSide);
Value result = Value(push_to_edge(weakKing) + push_away(weakKing, weakKnight));
return strongSide == pos.side_to_move() ? result : -result;
}
/// KQ vs KP. In general, this is a win for the stronger side, but there are a
/// few important exceptions. A pawn on 7th rank and on the A,C,F or H files
/// with a king positioned next to it can be a draw, so in that case, we only
/// use the distance between the kings.
template<>
Value Endgame<KQKP>::operator()(const Position& pos) const {
assert(verify_material(pos, strongSide, QueenValueMg, 0));
assert(verify_material(pos, weakSide, VALUE_ZERO, 1));
Square strongKing = pos.square<KING>(strongSide);
Square weakKing = pos.square<KING>(weakSide);
Square weakPawn = pos.square<PAWN>(weakSide);
Value result = Value(push_close(strongKing, weakKing));
if ( relative_rank(weakSide, weakPawn) != RANK_7
|| distance(weakKing, weakPawn) != 1
|| ((FileBBB | FileDBB | FileEBB | FileGBB) & weakPawn))
result += QueenValueEg - PawnValueEg;
return strongSide == pos.side_to_move() ? result : -result;
}
/// KQ vs KR. This is almost identical to KX vs K: we give the attacking
/// king a bonus for having the kings close together, and for forcing the
/// defending king towards the edge. If we also take care to avoid null move for
/// the defending side in the search, this is usually sufficient to win KQ vs KR.
template<>
Value Endgame<KQKR>::operator()(const Position& pos) const {
assert(verify_material(pos, strongSide, QueenValueMg, 0));
assert(verify_material(pos, weakSide, RookValueMg, 0));
Square strongKing = pos.square<KING>(strongSide);
Square weakKing = pos.square<KING>(weakSide);
Value result = QueenValueEg
- RookValueEg
+ push_to_edge(weakKing)
+ push_close(strongKing, weakKing);
return strongSide == pos.side_to_move() ? result : -result;
}
/// KNN vs KP. Very drawish, but there are some mate opportunities if we can
/// press the weakSide King to a corner before the pawn advances too much.
template<>
Value Endgame<KNNKP>::operator()(const Position& pos) const {
assert(verify_material(pos, strongSide, 2 * KnightValueMg, 0));
assert(verify_material(pos, weakSide, VALUE_ZERO, 1));
Square weakKing = pos.square<KING>(weakSide);
Square weakPawn = pos.square<PAWN>(weakSide);
Value result = PawnValueEg
+ 2 * push_to_edge(weakKing)
- 10 * relative_rank(weakSide, weakPawn);
return strongSide == pos.side_to_move() ? result : -result;
}
/// Some cases of trivial draws
template<> Value Endgame<KNNK>::operator()(const Position&) const { return VALUE_DRAW; }
/// KB and one or more pawns vs K. It checks for draws with rook pawns and
/// a bishop of the wrong color. If such a draw is detected, SCALE_FACTOR_DRAW
/// is returned. If not, the return value is SCALE_FACTOR_NONE, i.e. no scaling
/// will be used.
template<>
ScaleFactor Endgame<KBPsK>::operator()(const Position& pos) const {
assert(pos.non_pawn_material(strongSide) == BishopValueMg);
assert(pos.count<PAWN>(strongSide) >= 1);
// No assertions about the material of weakSide, because we want draws to
// be detected even when the weaker side has some pawns.
Bitboard strongPawns = pos.pieces(strongSide, PAWN);
Bitboard allPawns = pos.pieces(PAWN);
Square strongBishop = pos.square<BISHOP>(strongSide);
Square weakKing = pos.square<KING>(weakSide);
Square strongKing = pos.square<KING>(strongSide);
// All strongSide pawns are on a single rook file?
if (!(strongPawns & ~FileABB) || !(strongPawns & ~FileHBB))
{
Square queeningSquare = relative_square(strongSide, make_square(file_of(lsb(strongPawns)), RANK_8));
if ( opposite_colors(queeningSquare, strongBishop)
&& distance(queeningSquare, weakKing) <= 1)
return SCALE_FACTOR_DRAW;
}
// If all the pawns are on the same B or G file, then it's potentially a draw
if ((!(allPawns & ~FileBBB) || !(allPawns & ~FileGBB))
&& pos.non_pawn_material(weakSide) == 0
&& pos.count<PAWN>(weakSide) >= 1)
{
// Get the least advanced weakSide pawn
Square weakPawn = frontmost_sq(strongSide, pos.pieces(weakSide, PAWN));
// There's potential for a draw if our pawn is blocked on the 7th rank,
// the bishop cannot attack it or they only have one pawn left.
if ( relative_rank(strongSide, weakPawn) == RANK_7
&& (strongPawns & (weakPawn + pawn_push(weakSide)))
&& (opposite_colors(strongBishop, weakPawn) || !more_than_one(strongPawns)))
{
int strongKingDist = distance(weakPawn, strongKing);
int weakKingDist = distance(weakPawn, weakKing);
// It's a draw if the weak king is on its back two ranks, within 2
// squares of the blocking pawn and the strong king is not
// closer. (I think this rule only fails in practically
// unreachable positions such as 5k1K/6p1/6P1/8/8/3B4/8/8 w
// and positions where qsearch will immediately correct the
// problem such as 8/4k1p1/6P1/1K6/3B4/8/8/8 w).
if ( relative_rank(strongSide, weakKing) >= RANK_7
&& weakKingDist <= 2
&& weakKingDist <= strongKingDist)
return SCALE_FACTOR_DRAW;
}
}
return SCALE_FACTOR_NONE;
}
/// KQ vs KR and one or more pawns. It tests for fortress draws with a rook on
/// the third rank defended by a pawn.
template<>
ScaleFactor Endgame<KQKRPs>::operator()(const Position& pos) const {
assert(verify_material(pos, strongSide, QueenValueMg, 0));
assert(pos.count<ROOK>(weakSide) == 1);
assert(pos.count<PAWN>(weakSide) >= 1);
Square strongKing = pos.square<KING>(strongSide);
Square weakKing = pos.square<KING>(weakSide);
Square weakRook = pos.square<ROOK>(weakSide);
if ( relative_rank(weakSide, weakKing) <= RANK_2
&& relative_rank(weakSide, strongKing) >= RANK_4
&& relative_rank(weakSide, weakRook) == RANK_3
&& ( pos.pieces(weakSide, PAWN)
& attacks_bb<KING>(weakKing)
& pawn_attacks_bb(strongSide, weakRook)))
return SCALE_FACTOR_DRAW;
return SCALE_FACTOR_NONE;
}
/// KRP vs KR. This function knows a handful of the most important classes of
/// drawn positions, but is far from perfect. It would probably be a good idea
/// to add more knowledge in the future.
///
/// It would also be nice to rewrite the actual code for this function,
/// which is mostly copied from Glaurung 1.x, and isn't very pretty.
template<>
ScaleFactor Endgame<KRPKR>::operator()(const Position& pos) const {
assert(verify_material(pos, strongSide, RookValueMg, 1));
assert(verify_material(pos, weakSide, RookValueMg, 0));
// Assume strongSide is white and the pawn is on files A-D
Square strongKing = normalize(pos, strongSide, pos.square<KING>(strongSide));
Square strongRook = normalize(pos, strongSide, pos.square<ROOK>(strongSide));
Square strongPawn = normalize(pos, strongSide, pos.square<PAWN>(strongSide));
Square weakKing = normalize(pos, strongSide, pos.square<KING>(weakSide));
Square weakRook = normalize(pos, strongSide, pos.square<ROOK>(weakSide));
File pawnFile = file_of(strongPawn);
Rank pawnRank = rank_of(strongPawn);
Square queeningSquare = make_square(pawnFile, RANK_8);
int tempo = (pos.side_to_move() == strongSide);
// If the pawn is not too far advanced and the defending king defends the
// queening square, use the third-rank defence.
if ( pawnRank <= RANK_5
&& distance(weakKing, queeningSquare) <= 1
&& strongKing <= SQ_H5
&& (rank_of(weakRook) == RANK_6 || (pawnRank <= RANK_3 && rank_of(strongRook) != RANK_6)))
return SCALE_FACTOR_DRAW;
// The defending side saves a draw by checking from behind in case the pawn
// has advanced to the 6th rank with the king behind.
if ( pawnRank == RANK_6
&& distance(weakKing, queeningSquare) <= 1
&& rank_of(strongKing) + tempo <= RANK_6
&& (rank_of(weakRook) == RANK_1 || (!tempo && distance<File>(weakRook, strongPawn) >= 3)))
return SCALE_FACTOR_DRAW;
if ( pawnRank >= RANK_6
&& weakKing == queeningSquare
&& rank_of(weakRook) == RANK_1
&& (!tempo || distance(strongKing, strongPawn) >= 2))
return SCALE_FACTOR_DRAW;
// White pawn on a7 and rook on a8 is a draw if black's king is on g7 or h7
// and the black rook is behind the pawn.
if ( strongPawn == SQ_A7
&& strongRook == SQ_A8
&& (weakKing == SQ_H7 || weakKing == SQ_G7)
&& file_of(weakRook) == FILE_A
&& (rank_of(weakRook) <= RANK_3 || file_of(strongKing) >= FILE_D || rank_of(strongKing) <= RANK_5))
return SCALE_FACTOR_DRAW;
// If the defending king blocks the pawn and the attacking king is too far
// away, it's a draw.
if ( pawnRank <= RANK_5
&& weakKing == strongPawn + NORTH
&& distance(strongKing, strongPawn) - tempo >= 2
&& distance(strongKing, weakRook) - tempo >= 2)
return SCALE_FACTOR_DRAW;
// Pawn on the 7th rank supported by the rook from behind usually wins if the
// attacking king is closer to the queening square than the defending king,
// and the defending king cannot gain tempi by threatening the attacking rook.
if ( pawnRank == RANK_7
&& pawnFile != FILE_A
&& file_of(strongRook) == pawnFile
&& strongRook != queeningSquare
&& (distance(strongKing, queeningSquare) < distance(weakKing, queeningSquare) - 2 + tempo)
&& (distance(strongKing, queeningSquare) < distance(weakKing, strongRook) + tempo))
return ScaleFactor(SCALE_FACTOR_MAX - 2 * distance(strongKing, queeningSquare));
// Similar to the above, but with the pawn further back
if ( pawnFile != FILE_A
&& file_of(strongRook) == pawnFile
&& strongRook < strongPawn
&& (distance(strongKing, queeningSquare) < distance(weakKing, queeningSquare) - 2 + tempo)
&& (distance(strongKing, strongPawn + NORTH) < distance(weakKing, strongPawn + NORTH) - 2 + tempo)
&& ( distance(weakKing, strongRook) + tempo >= 3
|| ( distance(strongKing, queeningSquare) < distance(weakKing, strongRook) + tempo
&& (distance(strongKing, strongPawn + NORTH) < distance(weakKing, strongPawn) + tempo))))
return ScaleFactor( SCALE_FACTOR_MAX
- 8 * distance(strongPawn, queeningSquare)
- 2 * distance(strongKing, queeningSquare));
// If the pawn is not far advanced and the defending king is somewhere in
// the pawn's path, it's probably a draw.
if (pawnRank <= RANK_4 && weakKing > strongPawn)
{
if (file_of(weakKing) == file_of(strongPawn))
return ScaleFactor(10);
if ( distance<File>(weakKing, strongPawn) == 1
&& distance(strongKing, weakKing) > 2)
return ScaleFactor(24 - 2 * distance(strongKing, weakKing));
}
return SCALE_FACTOR_NONE;
}
template<>
ScaleFactor Endgame<KRPKB>::operator()(const Position& pos) const {
assert(verify_material(pos, strongSide, RookValueMg, 1));
assert(verify_material(pos, weakSide, BishopValueMg, 0));
// Test for a rook pawn
if (pos.pieces(PAWN) & (FileABB | FileHBB))
{
Square weakKing = pos.square<KING>(weakSide);
Square weakBishop = pos.square<BISHOP>(weakSide);
Square strongKing = pos.square<KING>(strongSide);
Square strongPawn = pos.square<PAWN>(strongSide);
Rank pawnRank = relative_rank(strongSide, strongPawn);
Direction push = pawn_push(strongSide);
// If the pawn is on the 5th rank and the pawn (currently) is on
// the same color square as the bishop then there is a chance of
// a fortress. Depending on the king position give a moderate
// reduction or a stronger one if the defending king is near the
// corner but not trapped there.
if (pawnRank == RANK_5 && !opposite_colors(weakBishop, strongPawn))
{
int d = distance(strongPawn + 3 * push, weakKing);
if (d <= 2 && !(d == 0 && weakKing == strongKing + 2 * push))
return ScaleFactor(24);
else
return ScaleFactor(48);
}
// When the pawn has moved to the 6th rank we can be fairly sure
// it's drawn if the bishop attacks the square in front of the
// pawn from a reasonable distance and the defending king is near
// the corner
if ( pawnRank == RANK_6
&& distance(strongPawn + 2 * push, weakKing) <= 1
&& (attacks_bb<BISHOP>(weakBishop) & (strongPawn + push))
&& distance<File>(weakBishop, strongPawn) >= 2)
return ScaleFactor(8);
}
return SCALE_FACTOR_NONE;
}
/// KRPP vs KRP. There is just a single rule: if the stronger side has no passed
/// pawns and the defending king is actively placed, the position is drawish.
template<>
ScaleFactor Endgame<KRPPKRP>::operator()(const Position& pos) const {
assert(verify_material(pos, strongSide, RookValueMg, 2));
assert(verify_material(pos, weakSide, RookValueMg, 1));
Square strongPawn1 = lsb(pos.pieces(strongSide, PAWN));
Square strongPawn2 = msb(pos.pieces(strongSide, PAWN));
Square weakKing = pos.square<KING>(weakSide);
// Does the stronger side have a passed pawn?
if (pos.pawn_passed(strongSide, strongPawn1) || pos.pawn_passed(strongSide, strongPawn2))
return SCALE_FACTOR_NONE;
Rank pawnRank = std::max(relative_rank(strongSide, strongPawn1), relative_rank(strongSide, strongPawn2));
if ( distance<File>(weakKing, strongPawn1) <= 1
&& distance<File>(weakKing, strongPawn2) <= 1
&& relative_rank(strongSide, weakKing) > pawnRank)
{
assert(pawnRank > RANK_1 && pawnRank < RANK_7);
return ScaleFactor(7 * pawnRank);
}
return SCALE_FACTOR_NONE;
}
/// K and two or more pawns vs K. There is just a single rule here: if all pawns
/// are on the same rook file and are blocked by the defending king, it's a draw.
template<>
ScaleFactor Endgame<KPsK>::operator()(const Position& pos) const {
assert(pos.non_pawn_material(strongSide) == VALUE_ZERO);
assert(pos.count<PAWN>(strongSide) >= 2);
assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
Square weakKing = pos.square<KING>(weakSide);
Bitboard strongPawns = pos.pieces(strongSide, PAWN);
// If all pawns are ahead of the king on a single rook file, it's a draw.
if ( !(strongPawns & ~(FileABB | FileHBB))
&& !(strongPawns & ~passed_pawn_span(weakSide, weakKing)))
return SCALE_FACTOR_DRAW;
return SCALE_FACTOR_NONE;
}
/// KBP vs KB. There are two rules: if the defending king is somewhere along the
/// path of the pawn, and the square of the king is not of the same color as the
/// stronger side's bishop, it's a draw. If the two bishops have opposite color,
/// it's almost always a draw.
template<>
ScaleFactor Endgame<KBPKB>::operator()(const Position& pos) const {
assert(verify_material(pos, strongSide, BishopValueMg, 1));
assert(verify_material(pos, weakSide, BishopValueMg, 0));
Square strongPawn = pos.square<PAWN>(strongSide);
Square strongBishop = pos.square<BISHOP>(strongSide);
Square weakBishop = pos.square<BISHOP>(weakSide);
Square weakKing = pos.square<KING>(weakSide);
// Case 1: Defending king blocks the pawn, and cannot be driven away
if ( (forward_file_bb(strongSide, strongPawn) & weakKing)
&& ( opposite_colors(weakKing, strongBishop)
|| relative_rank(strongSide, weakKing) <= RANK_6))
return SCALE_FACTOR_DRAW;
// Case 2: Opposite colored bishops
if (opposite_colors(strongBishop, weakBishop))
return SCALE_FACTOR_DRAW;
return SCALE_FACTOR_NONE;
}
/// KBPP vs KB. It detects a few basic draws with opposite-colored bishops
template<>
ScaleFactor Endgame<KBPPKB>::operator()(const Position& pos) const {
assert(verify_material(pos, strongSide, BishopValueMg, 2));
assert(verify_material(pos, weakSide, BishopValueMg, 0));
Square strongBishop = pos.square<BISHOP>(strongSide);
Square weakBishop = pos.square<BISHOP>(weakSide);
if (!opposite_colors(strongBishop, weakBishop))
return SCALE_FACTOR_NONE;
Square weakKing = pos.square<KING>(weakSide);
Square strongPawn1 = lsb(pos.pieces(strongSide, PAWN));
Square strongPawn2 = msb(pos.pieces(strongSide, PAWN));
Square blockSq1, blockSq2;
if (relative_rank(strongSide, strongPawn1) > relative_rank(strongSide, strongPawn2))
{
blockSq1 = strongPawn1 + pawn_push(strongSide);
blockSq2 = make_square(file_of(strongPawn2), rank_of(strongPawn1));
}
else
{
blockSq1 = strongPawn2 + pawn_push(strongSide);
blockSq2 = make_square(file_of(strongPawn1), rank_of(strongPawn2));
}
switch (distance<File>(strongPawn1, strongPawn2))
{
case 0:
// Both pawns are on the same file. It's an easy draw if the defender firmly
// controls some square in the frontmost pawn's path.
if ( file_of(weakKing) == file_of(blockSq1)
&& relative_rank(strongSide, weakKing) >= relative_rank(strongSide, blockSq1)
&& opposite_colors(weakKing, strongBishop))
return SCALE_FACTOR_DRAW;
else
return SCALE_FACTOR_NONE;
case 1:
// Pawns on adjacent files. It's a draw if the defender firmly controls the
// square in front of the frontmost pawn's path, and the square diagonally
// behind this square on the file of the other pawn.
if ( weakKing == blockSq1
&& opposite_colors(weakKing, strongBishop)
&& ( weakBishop == blockSq2
|| (attacks_bb<BISHOP>(blockSq2, pos.pieces()) & pos.pieces(weakSide, BISHOP))
|| distance<Rank>(strongPawn1, strongPawn2) >= 2))
return SCALE_FACTOR_DRAW;
else if ( weakKing == blockSq2
&& opposite_colors(weakKing, strongBishop)
&& ( weakBishop == blockSq1
|| (attacks_bb<BISHOP>(blockSq1, pos.pieces()) & pos.pieces(weakSide, BISHOP))))
return SCALE_FACTOR_DRAW;
else
return SCALE_FACTOR_NONE;
default:
// The pawns are not on the same file or adjacent files. No scaling.
return SCALE_FACTOR_NONE;
}
}
/// KBP vs KN. There is a single rule: if the defending king is somewhere along
/// the path of the pawn, and the square of the king is not of the same color as
/// the stronger side's bishop, it's a draw.
template<>
ScaleFactor Endgame<KBPKN>::operator()(const Position& pos) const {
assert(verify_material(pos, strongSide, BishopValueMg, 1));
assert(verify_material(pos, weakSide, KnightValueMg, 0));
Square strongPawn = pos.square<PAWN>(strongSide);
Square strongBishop = pos.square<BISHOP>(strongSide);
Square weakKing = pos.square<KING>(weakSide);
if ( file_of(weakKing) == file_of(strongPawn)
&& relative_rank(strongSide, strongPawn) < relative_rank(strongSide, weakKing)
&& ( opposite_colors(weakKing, strongBishop)
|| relative_rank(strongSide, weakKing) <= RANK_6))
return SCALE_FACTOR_DRAW;
return SCALE_FACTOR_NONE;
}
/// KP vs KP. This is done by removing the weakest side's pawn and probing the
/// KP vs K bitbase: if the weakest side has a draw without the pawn, it probably
/// has at least a draw with the pawn as well. The exception is when the stronger
/// side's pawn is far advanced and not on a rook file; in this case it is often
/// possible to win (e.g. 8/4k3/3p4/3P4/6K1/8/8/8 w - - 0 1).
template<>
ScaleFactor Endgame<KPKP>::operator()(const Position& pos) const {
assert(verify_material(pos, strongSide, VALUE_ZERO, 1));
assert(verify_material(pos, weakSide, VALUE_ZERO, 1));
// Assume strongSide is white and the pawn is on files A-D
Square strongKing = normalize(pos, strongSide, pos.square<KING>(strongSide));
Square weakKing = normalize(pos, strongSide, pos.square<KING>(weakSide));
Square strongPawn = normalize(pos, strongSide, pos.square<PAWN>(strongSide));
Color us = strongSide == pos.side_to_move() ? WHITE : BLACK;
// If the pawn has advanced to the fifth rank or further, and is not a
// rook pawn, it's too dangerous to assume that it's at least a draw.
if (rank_of(strongPawn) >= RANK_5 && file_of(strongPawn) != FILE_A)
return SCALE_FACTOR_NONE;
// Probe the KPK bitbase with the weakest side's pawn removed. If it's a draw,
// it's probably at least a draw even with the pawn.
return Bitbases::probe(strongKing, strongPawn, weakKing, us) ? SCALE_FACTOR_NONE : SCALE_FACTOR_DRAW;
}
} // namespace Stockfish
-126
View File
@@ -1,126 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 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 <http://www.gnu.org/licenses/>.
*/
#ifndef ENDGAME_H_INCLUDED
#define ENDGAME_H_INCLUDED
#include <memory>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <utility>
#include "position.h"
#include "types.h"
namespace Stockfish {
/// EndgameCode lists all supported endgame functions by corresponding codes
enum EndgameCode {
EVALUATION_FUNCTIONS,
KNNK, // KNN vs K
KNNKP, // KNN vs KP
KXK, // Generic "mate lone king" eval
KBNK, // KBN vs K
KPK, // KP vs K
KRKP, // KR vs KP
KRKB, // KR vs KB
KRKN, // KR vs KN
KQKP, // KQ vs KP
KQKR, // KQ vs KR
SCALING_FUNCTIONS,
KBPsK, // KB and pawns vs K
KQKRPs, // KQ vs KR and pawns
KRPKR, // KRP vs KR
KRPKB, // KRP vs KB
KRPPKRP, // KRPP vs KRP
KPsK, // K and pawns vs K
KBPKB, // KBP vs KB
KBPPKB, // KBPP vs KB
KBPKN, // KBP vs KN
KPKP // KP vs KP
};
/// Endgame functions can be of two types depending on whether they return a
/// Value or a ScaleFactor.
template<EndgameCode E> using
eg_type = typename std::conditional<(E < SCALING_FUNCTIONS), Value, ScaleFactor>::type;
/// Base and derived functors for endgame evaluation and scaling functions
template<typename T>
struct EndgameBase {
explicit EndgameBase(Color c) : strongSide(c), weakSide(~c) {}
virtual ~EndgameBase() = default;
virtual T operator()(const Position&) const = 0;
const Color strongSide, weakSide;
};
template<EndgameCode E, typename T = eg_type<E>>
struct Endgame : public EndgameBase<T> {
explicit Endgame(Color c) : EndgameBase<T>(c) {}
T operator()(const Position&) const override;
};
/// The Endgames namespace handles the pointers to endgame evaluation and scaling
/// base objects in two std::map. We use polymorphism to invoke the actual
/// endgame function by calling its virtual operator().
namespace Endgames {
template<typename T> using Ptr = std::unique_ptr<EndgameBase<T>>;
template<typename T> using Map = std::unordered_map<Key, Ptr<T>>;
extern std::pair<Map<Value>, Map<ScaleFactor>> maps;
void init();
template<typename T>
Map<T>& map() {
return std::get<std::is_same<T, ScaleFactor>::value>(maps);
}
template<EndgameCode E, typename T = eg_type<E>>
void add(const std::string& code) {
StateInfo st;
map<T>()[Position().set(code, WHITE, &st).material_key()] = Ptr<T>(new Endgame<E>(WHITE));
map<T>()[Position().set(code, BLACK, &st).material_key()] = Ptr<T>(new Endgame<E>(BLACK));
}
template<typename T>
const EndgameBase<T>* probe(Key key) {
auto it = map<T>().find(key);
return it != map<T>().end() ? it->second.get() : nullptr;
}
}
} // namespace Stockfish
#endif // #ifndef ENDGAME_H_INCLUDED
+160 -1090
View File
File diff suppressed because it is too large Load Diff
+31 -22
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -20,43 +20,52 @@
#define EVALUATE_H_INCLUDED
#include <string>
#include <optional>
#include <unordered_map>
#include "types.h"
namespace Stockfish {
class Position;
class OptionsMap;
namespace Eval {
std::string trace(Position& pos);
Value evaluate(const Position& pos);
std::string trace(Position& pos);
extern bool useNNUE;
extern std::string currentEvalFileName;
int simple_eval(const Position& pos, Color c);
Value evaluate(const Position& pos, int optimism);
// 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, as it is used in the Makefile.
#define EvalFileDefaultName "nn-13406b1dcbe0.nnue"
// 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, as it is used in the Makefile.
#define EvalFileDefaultNameBig "nn-b1a57edbea57.nnue"
#define EvalFileDefaultNameSmall "nn-baff1ede1f90.nnue"
namespace NNUE {
struct EvalFile {
// UCI option name
std::string optionName;
// Default net name, will use one of the macros above
std::string defaultName;
// Selected net name, either via uci option or default
std::string current;
// Net description extracted from the net file
std::string netDescription;
};
std::string trace(Position& pos);
Value evaluate(const Position& pos, bool adjusted = false);
namespace NNUE {
void init();
void verify();
enum NetSize : int;
bool load_eval(std::string name, std::istream& stream);
bool save_eval(std::ostream& stream);
bool save_eval(const std::optional<std::string>& filename);
using EvalFiles = std::unordered_map<Eval::NNUE::NetSize, EvalFile>;
} // namespace NNUE
EvalFiles load_networks(const std::string&, const OptionsMap&, EvalFiles);
void verify(const OptionsMap&, const EvalFiles&);
} // namespace Eval
} // namespace NNUE
} // namespace Stockfish
} // namespace Eval
#endif // #ifndef EVALUATE_H_INCLUDED
} // namespace Stockfish
#endif // #ifndef EVALUATE_H_INCLUDED
Executable → Regular
+5 -5
View File
@@ -3,8 +3,8 @@
* @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.
* Facilities for including binary files into the current translation unit
* and making use of them externally in other translation units.
*/
#ifndef INCBIN_HDR
#define INCBIN_HDR
@@ -139,7 +139,7 @@
#endif
#if defined(__APPLE__)
/* The directives are different for Apple branded compilers */
/* 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 "
@@ -261,8 +261,8 @@
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. */
/* Generate the global labels by indirectly invoking the macro
* with our style type and concatenate the name against them. */
#define INCBIN_GLOBAL_LABELS(NAME, TYPE) \
INCBIN_INVOKE( \
INCBIN_GLOBAL, \
+17 -22
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -17,37 +17,32 @@
*/
#include <iostream>
#include <unordered_map>
#include "bitboard.h"
#include "endgame.h"
#include "evaluate.h"
#include "misc.h"
#include "position.h"
#include "psqt.h"
#include "search.h"
#include "syzygy/tbprobe.h"
#include "thread.h"
#include "tt.h"
#include "tune.h"
#include "types.h"
#include "uci.h"
using namespace Stockfish;
int main(int argc, char* argv[]) {
std::cout << engine_info() << std::endl;
std::cout << engine_info() << std::endl;
CommandLine::init(argc, argv);
UCI::init(Options);
Tune::init();
PSQT::init();
Bitboards::init();
Position::init();
Bitbases::init();
Endgames::init();
Threads.set(size_t(Options["Threads"]));
Search::clear(); // After threads are up
Eval::NNUE::init();
Bitboards::init();
Position::init();
UCI::loop(argc, argv);
UCI uci(argc, argv);
Threads.set(0);
return 0;
Tune::init(uci.options);
uci.evalFiles = Eval::NNUE::load_networks(uci.workingDirectory(), uci.options, uci.evalFiles);
uci.loop();
return 0;
}
-229
View File
@@ -1,229 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 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 <http://www.gnu.org/licenses/>.
*/
#include <cassert>
#include <cstring> // For std::memset
#include "material.h"
#include "thread.h"
using namespace std;
namespace Stockfish {
namespace {
#define S(mg, eg) make_score(mg, eg)
// Polynomial material imbalance parameters
// One Score parameter for each pair (our piece, another of our pieces)
constexpr Score QuadraticOurs[][PIECE_TYPE_NB] = {
// OUR PIECE 2
// bishop pair pawn knight bishop rook queen
{S(1419, 1455) }, // Bishop pair
{S( 101, 28), S( 37, 39) }, // Pawn
{S( 57, 64), S(249, 187), S(-49, -62) }, // Knight OUR PIECE 1
{S( 0, 0), S(118, 137), S( 10, 27), S( 0, 0) }, // Bishop
{S( -63, -68), S( -5, 3), S(100, 81), S(132, 118), S(-246, -244) }, // Rook
{S(-210, -211), S( 37, 14), S(147, 141), S(161, 105), S(-158, -174), S(-9,-31) } // Queen
};
// One Score parameter for each pair (our piece, their piece)
constexpr Score QuadraticTheirs[][PIECE_TYPE_NB] = {
// THEIR PIECE
// bishop pair pawn knight bishop rook queen
{ }, // Bishop pair
{S( 33, 30) }, // Pawn
{S( 46, 18), S(106, 84) }, // Knight OUR PIECE
{S( 75, 35), S( 59, 44), S( 60, 15) }, // Bishop
{S( 26, 35), S( 6, 22), S( 38, 39), S(-12, -2) }, // Rook
{S( 97, 93), S(100, 163), S(-58, -91), S(112, 192), S(276, 225) } // Queen
};
#undef S
// Endgame evaluation and scaling functions are accessed directly and not through
// the function maps because they correspond to more than one material hash key.
Endgame<KXK> EvaluateKXK[] = { Endgame<KXK>(WHITE), Endgame<KXK>(BLACK) };
Endgame<KBPsK> ScaleKBPsK[] = { Endgame<KBPsK>(WHITE), Endgame<KBPsK>(BLACK) };
Endgame<KQKRPs> ScaleKQKRPs[] = { Endgame<KQKRPs>(WHITE), Endgame<KQKRPs>(BLACK) };
Endgame<KPsK> ScaleKPsK[] = { Endgame<KPsK>(WHITE), Endgame<KPsK>(BLACK) };
Endgame<KPKP> ScaleKPKP[] = { Endgame<KPKP>(WHITE), Endgame<KPKP>(BLACK) };
// Helper used to detect a given material distribution
bool is_KXK(const Position& pos, Color us) {
return !more_than_one(pos.pieces(~us))
&& pos.non_pawn_material(us) >= RookValueMg;
}
bool is_KBPsK(const Position& pos, Color us) {
return pos.non_pawn_material(us) == BishopValueMg
&& pos.count<PAWN>(us) >= 1;
}
bool is_KQKRPs(const Position& pos, Color us) {
return !pos.count<PAWN>(us)
&& pos.non_pawn_material(us) == QueenValueMg
&& pos.count<ROOK>(~us) == 1
&& pos.count<PAWN>(~us) >= 1;
}
/// imbalance() calculates the imbalance by comparing the piece count of each
/// piece type for both colors.
template<Color Us>
Score imbalance(const int pieceCount[][PIECE_TYPE_NB]) {
constexpr Color Them = ~Us;
Score bonus = SCORE_ZERO;
// Second-degree polynomial material imbalance, by Tord Romstad
for (int pt1 = NO_PIECE_TYPE; pt1 <= QUEEN; ++pt1)
{
if (!pieceCount[Us][pt1])
continue;
int v = QuadraticOurs[pt1][pt1] * pieceCount[Us][pt1];
for (int pt2 = NO_PIECE_TYPE; pt2 < pt1; ++pt2)
v += QuadraticOurs[pt1][pt2] * pieceCount[Us][pt2]
+ QuadraticTheirs[pt1][pt2] * pieceCount[Them][pt2];
bonus += pieceCount[Us][pt1] * v;
}
return bonus;
}
} // namespace
namespace Material {
/// Material::probe() looks up the current position's material configuration in
/// the material hash table. It returns a pointer to the Entry if the position
/// is found. Otherwise a new Entry is computed and stored there, so we don't
/// have to recompute all when the same material configuration occurs again.
Entry* probe(const Position& pos) {
Key key = pos.material_key();
Entry* e = pos.this_thread()->materialTable[key];
if (e->key == key)
return e;
std::memset(e, 0, sizeof(Entry));
e->key = key;
e->factor[WHITE] = e->factor[BLACK] = (uint8_t)SCALE_FACTOR_NORMAL;
Value npm_w = pos.non_pawn_material(WHITE);
Value npm_b = pos.non_pawn_material(BLACK);
Value npm = std::clamp(npm_w + npm_b, EndgameLimit, MidgameLimit);
// Map total non-pawn material into [PHASE_ENDGAME, PHASE_MIDGAME]
e->gamePhase = Phase(((npm - EndgameLimit) * PHASE_MIDGAME) / (MidgameLimit - EndgameLimit));
// Let's look if we have a specialized evaluation function for this particular
// material configuration. Firstly we look for a fixed configuration one, then
// for a generic one if the previous search failed.
if ((e->evaluationFunction = Endgames::probe<Value>(key)) != nullptr)
return e;
for (Color c : { WHITE, BLACK })
if (is_KXK(pos, c))
{
e->evaluationFunction = &EvaluateKXK[c];
return e;
}
// OK, we didn't find any special evaluation function for the current material
// configuration. Is there a suitable specialized scaling function?
const auto* sf = Endgames::probe<ScaleFactor>(key);
if (sf)
{
e->scalingFunction[sf->strongSide] = sf; // Only strong color assigned
return e;
}
// We didn't find any specialized scaling function, so fall back on generic
// ones that refer to more than one material distribution. Note that in this
// case we don't return after setting the function.
for (Color c : { WHITE, BLACK })
{
if (is_KBPsK(pos, c))
e->scalingFunction[c] = &ScaleKBPsK[c];
else if (is_KQKRPs(pos, c))
e->scalingFunction[c] = &ScaleKQKRPs[c];
}
if (npm_w + npm_b == VALUE_ZERO && pos.pieces(PAWN)) // Only pawns on the board
{
if (!pos.count<PAWN>(BLACK))
{
assert(pos.count<PAWN>(WHITE) >= 2);
e->scalingFunction[WHITE] = &ScaleKPsK[WHITE];
}
else if (!pos.count<PAWN>(WHITE))
{
assert(pos.count<PAWN>(BLACK) >= 2);
e->scalingFunction[BLACK] = &ScaleKPsK[BLACK];
}
else if (pos.count<PAWN>(WHITE) == 1 && pos.count<PAWN>(BLACK) == 1)
{
// This is a special case because we set scaling functions
// for both colors instead of only one.
e->scalingFunction[WHITE] = &ScaleKPKP[WHITE];
e->scalingFunction[BLACK] = &ScaleKPKP[BLACK];
}
}
// Zero or just one pawn makes it difficult to win, even with a small material
// advantage. This catches some trivial draws like KK, KBK and KNK and gives a
// drawish scale factor for cases such as KRKBP and KmmKm (except for KBBKN).
if (!pos.count<PAWN>(WHITE) && npm_w - npm_b <= BishopValueMg)
e->factor[WHITE] = uint8_t(npm_w < RookValueMg ? SCALE_FACTOR_DRAW :
npm_b <= BishopValueMg ? 4 : 14);
if (!pos.count<PAWN>(BLACK) && npm_b - npm_w <= BishopValueMg)
e->factor[BLACK] = uint8_t(npm_b < RookValueMg ? SCALE_FACTOR_DRAW :
npm_w <= BishopValueMg ? 4 : 14);
// Evaluate the material imbalance. We use PIECE_TYPE_NONE as a place holder
// for the bishop pair "extended piece", which allows us to be more flexible
// in defining bishop pair bonuses.
const int pieceCount[COLOR_NB][PIECE_TYPE_NB] = {
{ pos.count<BISHOP>(WHITE) > 1, pos.count<PAWN>(WHITE), pos.count<KNIGHT>(WHITE),
pos.count<BISHOP>(WHITE) , pos.count<ROOK>(WHITE), pos.count<QUEEN >(WHITE) },
{ pos.count<BISHOP>(BLACK) > 1, pos.count<PAWN>(BLACK), pos.count<KNIGHT>(BLACK),
pos.count<BISHOP>(BLACK) , pos.count<ROOK>(BLACK), pos.count<QUEEN >(BLACK) } };
e->score = (imbalance<WHITE>(pieceCount) - imbalance<BLACK>(pieceCount)) / 16;
return e;
}
} // namespace Material
} // namespace Stockfish
-71
View File
@@ -1,71 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 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 <http://www.gnu.org/licenses/>.
*/
#ifndef MATERIAL_H_INCLUDED
#define MATERIAL_H_INCLUDED
#include "endgame.h"
#include "misc.h"
#include "position.h"
#include "types.h"
namespace Stockfish::Material {
/// Material::Entry contains various information about a material configuration.
/// It contains a material imbalance evaluation, a function pointer to a special
/// endgame evaluation function (which in most cases is NULL, meaning that the
/// standard evaluation function will be used), and scale factors.
///
/// The scale factors are used to scale the evaluation score up or down. For
/// instance, in KRB vs KR endgames, the score is scaled down by a factor of 4,
/// which will result in scores of absolute value less than one pawn.
struct Entry {
Score imbalance() const { return score; }
Phase game_phase() const { return (Phase)gamePhase; }
bool specialized_eval_exists() const { return evaluationFunction != nullptr; }
Value evaluate(const Position& pos) const { return (*evaluationFunction)(pos); }
// scale_factor() takes a position and a color as input and returns a scale factor
// for the given color. We have to provide the position in addition to the color
// because the scale factor may also be a function which should be applied to
// the position. For instance, in KBP vs K endgames, the scaling function looks
// for rook pawns and wrong-colored bishops.
ScaleFactor scale_factor(const Position& pos, Color c) const {
ScaleFactor sf = scalingFunction[c] ? (*scalingFunction[c])(pos)
: SCALE_FACTOR_NONE;
return sf != SCALE_FACTOR_NONE ? sf : ScaleFactor(factor[c]);
}
Key key;
const EndgameBase<Value>* evaluationFunction;
const EndgameBase<ScaleFactor>* scalingFunction[COLOR_NB]; // Could be one for each
// side (e.g. KPKP, KBPsK)
Score score;
int16_t gamePhase;
uint8_t factor[COLOR_NB];
};
typedef HashTable<Entry, 8192> Table;
Entry* probe(const Position& pos);
} // namespace Stockfish::Material
#endif // #ifndef MATERIAL_H_INCLUDED
+506 -394
View File
File diff suppressed because it is too large Load Diff
+123 -125
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -19,192 +19,190 @@
#ifndef MISC_H_INCLUDED
#define MISC_H_INCLUDED
#include <algorithm>
#include <cassert>
#include <chrono>
#include <ostream>
#include <cstddef>
#include <cstdint>
#include <iosfwd>
#include <string>
#include <vector>
#include <cstdint>
#include "types.h"
#define stringify2(x) #x
#define stringify(x) stringify2(x)
namespace Stockfish {
std::string engine_info(bool to_uci = false);
std::string compiler_info();
void prefetch(void* addr);
void start_logger(const std::string& fname);
void* std_aligned_alloc(size_t alignment, size_t size);
void std_aligned_free(void* ptr);
void* aligned_large_pages_alloc(size_t size); // memory aligned by page size, min alignment: 4096 bytes
void aligned_large_pages_free(void* mem); // nop if mem == nullptr
void dbg_hit_on(bool b);
void dbg_hit_on(bool c, bool b);
void dbg_mean_of(int v);
// Preloads the given address in L1/L2 cache. This is a non-blocking
// function that doesn't stall the CPU waiting for data to be loaded from memory,
// which can be quite slow.
void prefetch(void* addr);
void start_logger(const std::string& fname);
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);
// nop if mem == nullptr
void aligned_large_pages_free(void* mem);
void dbg_hit_on(bool cond, int slot = 0);
void dbg_mean_of(int64_t value, int slot = 0);
void dbg_stdev_of(int64_t value, int slot = 0);
void dbg_correl_of(int64_t value1, int64_t value2, int slot = 0);
void dbg_print();
typedef std::chrono::milliseconds::rep TimePoint; // A value in milliseconds
using TimePoint = std::chrono::milliseconds::rep; // A value in milliseconds
static_assert(sizeof(TimePoint) == sizeof(int64_t), "TimePoint should be 64 bits");
inline TimePoint now() {
return std::chrono::duration_cast<std::chrono::milliseconds>
(std::chrono::steady_clock::now().time_since_epoch()).count();
return std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now().time_since_epoch())
.count();
}
template<class Entry, int Size>
struct HashTable {
Entry* operator[](Key key) { return &table[(uint32_t)key & (Size - 1)]; }
private:
std::vector<Entry> table = std::vector<Entry>(Size); // Allocate on the heap
enum SyncCout {
IO_LOCK,
IO_UNLOCK
};
enum SyncCout { IO_LOCK, IO_UNLOCK };
std::ostream& operator<<(std::ostream&, SyncCout);
#define sync_cout std::cout << IO_LOCK
#define sync_endl std::endl << IO_UNLOCK
// align_ptr_up() : get the first aligned element of an array.
// Get the first aligned element of an array.
// ptr must point to an array of size at least `sizeof(T) * N + alignment` bytes,
// where N is the number of elements in the array.
template <uintptr_t Alignment, typename T>
T* align_ptr_up(T* ptr)
{
static_assert(alignof(T) < Alignment);
template<uintptr_t Alignment, typename T>
T* align_ptr_up(T* ptr) {
static_assert(alignof(T) < Alignment);
const uintptr_t ptrint = reinterpret_cast<uintptr_t>(reinterpret_cast<char*>(ptr));
return reinterpret_cast<T*>(reinterpret_cast<char*>((ptrint + (Alignment - 1)) / Alignment * Alignment));
const uintptr_t ptrint = reinterpret_cast<uintptr_t>(reinterpret_cast<char*>(ptr));
return reinterpret_cast<T*>(
reinterpret_cast<char*>((ptrint + (Alignment - 1)) / Alignment * Alignment));
}
// IsLittleEndian : true if and only if the binary is compiled on a little endian machine
static inline const union { uint32_t i; char c[4]; } Le = { 0x01020304 };
// True if and only if the binary is compiled on a little-endian machine
static inline const union {
uint32_t i;
char c[4];
} Le = {0x01020304};
static inline const bool IsLittleEndian = (Le.c[0] == 4);
// RunningAverage : a class to calculate a running average of a series of values.
// For efficiency, all computations are done with integers.
class RunningAverage {
public:
// Constructor
RunningAverage() {}
// Reset the running average to rational value p / q
void set(int64_t p, int64_t q)
{ average = p * PERIOD * RESOLUTION / q; }
// Update average with value v
void update(int64_t v)
{ average = RESOLUTION * v + (PERIOD - 1) * average / PERIOD; }
// Test if average is strictly greater than rational a / b
bool is_greater(int64_t a, int64_t b)
{ return b * average > a * PERIOD * RESOLUTION ; }
private :
static constexpr int64_t PERIOD = 4096;
static constexpr int64_t RESOLUTION = 1024;
int64_t average;
};
template <typename T, std::size_t MaxSize>
template<typename T, std::size_t MaxSize>
class ValueList {
public:
std::size_t size() const { return size_; }
void resize(std::size_t newSize) { size_ = newSize; }
void push_back(const T& value) { values_[size_++] = value; }
T& operator[](std::size_t index) { return values_[index]; }
T* begin() { return values_; }
T* end() { return values_ + size_; }
const T& operator[](std::size_t index) const { return values_[index]; }
const T* begin() const { return values_; }
const T* end() const { return values_ + size_; }
public:
std::size_t size() const { return size_; }
void push_back(const T& value) { values_[size_++] = value; }
const T* begin() const { return values_; }
const T* end() const { return values_ + size_; }
const T& operator[](int index) const { return values_[index]; }
void swap(ValueList& other) {
const std::size_t maxSize = std::max(size_, other.size_);
for (std::size_t i = 0; i < maxSize; ++i) {
std::swap(values_[i], other.values_[i]);
}
std::swap(size_, other.size_);
}
private:
T values_[MaxSize];
std::size_t size_ = 0;
private:
T values_[MaxSize];
std::size_t size_ = 0;
};
/// xorshift64star Pseudo-Random Number Generator
/// This class is based on original code written and dedicated
/// to the public domain by Sebastiano Vigna (2014).
/// It has the following characteristics:
///
/// - Outputs 64-bit numbers
/// - Passes Dieharder and SmallCrush test batteries
/// - Does not require warm-up, no zeroland to escape
/// - Internal state is a single 64-bit integer
/// - Period is 2^64 - 1
/// - Speed: 1.60 ns/call (Core i7 @3.40GHz)
///
/// For further analysis see
/// <http://vigna.di.unimi.it/ftp/papers/xorshift.pdf>
// xorshift64star Pseudo-Random Number Generator
// This class is based on original code written and dedicated
// to the public domain by Sebastiano Vigna (2014).
// It has the following characteristics:
//
// - Outputs 64-bit numbers
// - Passes Dieharder and SmallCrush test batteries
// - Does not require warm-up, no zeroland to escape
// - Internal state is a single 64-bit integer
// - Period is 2^64 - 1
// - Speed: 1.60 ns/call (Core i7 @3.40GHz)
//
// For further analysis see
// <http://vigna.di.unimi.it/ftp/papers/xorshift.pdf>
class PRNG {
uint64_t s;
uint64_t s;
uint64_t rand64() {
uint64_t rand64() {
s ^= s >> 12, s ^= s << 25, s ^= s >> 27;
return s * 2685821657736338717LL;
}
s ^= s >> 12, s ^= s << 25, s ^= s >> 27;
return s * 2685821657736338717LL;
}
public:
PRNG(uint64_t seed) : s(seed) { assert(seed); }
public:
PRNG(uint64_t seed) :
s(seed) {
assert(seed);
}
template<typename T> T rand() { return T(rand64()); }
template<typename T>
T rand() {
return T(rand64());
}
/// Special generator used to fast init magic numbers.
/// Output values only have 1/8th of their bits set on average.
template<typename T> T sparse_rand()
{ return T(rand64() & rand64() & rand64()); }
// Special generator used to fast init magic numbers.
// Output values only have 1/8th of their bits set on average.
template<typename T>
T sparse_rand() {
return T(rand64() & rand64() & rand64());
}
};
inline uint64_t mul_hi64(uint64_t a, uint64_t b) {
#if defined(__GNUC__) && defined(IS_64BIT)
__extension__ typedef unsigned __int128 uint128;
return ((uint128)a * (uint128)b) >> 64;
__extension__ using uint128 = unsigned __int128;
return (uint128(a) * uint128(b)) >> 64;
#else
uint64_t aL = (uint32_t)a, aH = a >> 32;
uint64_t bL = (uint32_t)b, bH = b >> 32;
uint64_t aL = uint32_t(a), aH = a >> 32;
uint64_t bL = uint32_t(b), bH = b >> 32;
uint64_t c1 = (aL * bL) >> 32;
uint64_t c2 = aH * bL + c1;
uint64_t c3 = aL * bH + (uint32_t)c2;
uint64_t c3 = aL * bH + uint32_t(c2);
return aH * bH + (c2 >> 32) + (c3 >> 32);
#endif
}
/// Under Windows it is not possible for a process to run on more than one
/// logical processor group. This usually means to be limited to use max 64
/// cores. To overcome this, some special platform specific API should be
/// called to set group affinity for each thread. Original code from Texel by
/// Peter Österlund.
// Under Windows it is not possible for a process to run on more than one
// logical processor group. This usually means being limited to using max 64
// cores. To overcome this, some special platform-specific API should be
// called to set group affinity for each thread. Original code from Texel by
// Peter Österlund.
namespace WinProcGroup {
void bindThisThread(size_t idx);
void bindThisThread(size_t idx);
}
namespace CommandLine {
void init(int argc, char* argv[]);
extern std::string binaryDirectory; // path of the executable directory
extern std::string workingDirectory; // path of the working directory
struct CommandLine {
public:
CommandLine(int, char**);
int argc;
char** argv;
std::string binaryDirectory; // path of the executable directory
std::string workingDirectory; // path of the working directory
};
namespace Utility {
template<typename T, typename Predicate>
void move_to_front(std::vector<T>& vec, Predicate pred) {
auto it = std::find_if(vec.begin(), vec.end(), pred);
if (it != vec.end())
{
std::rotate(vec.begin(), it, it + 1);
}
}
}
} // namespace Stockfish
} // namespace Stockfish
#endif // #ifndef MISC_H_INCLUDED
#endif // #ifndef MISC_H_INCLUDED
+98 -94
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -16,82 +16,86 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cassert>
#include "movegen.h"
#include <cassert>
#include <initializer_list>
#include "bitboard.h"
#include "position.h"
namespace Stockfish {
namespace {
template<GenType Type, Direction D>
ExtMove* make_promotions(ExtMove* moveList, Square to) {
template<GenType Type, Direction D, bool Enemy>
ExtMove* make_promotions(ExtMove* moveList, [[maybe_unused]] Square to) {
if (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS)
*moveList++ = make<PROMOTION>(to - D, to, QUEEN);
constexpr bool all = Type == EVASIONS || Type == NON_EVASIONS;
if (Type == QUIETS || Type == EVASIONS || Type == NON_EVASIONS)
if constexpr (Type == CAPTURES || all)
*moveList++ = Move::make<PROMOTION>(to - D, to, QUEEN);
if constexpr ((Type == CAPTURES && Enemy) || (Type == QUIETS && !Enemy) || all)
{
*moveList++ = make<PROMOTION>(to - D, to, ROOK);
*moveList++ = make<PROMOTION>(to - D, to, BISHOP);
*moveList++ = make<PROMOTION>(to - D, to, KNIGHT);
*moveList++ = Move::make<PROMOTION>(to - D, to, ROOK);
*moveList++ = Move::make<PROMOTION>(to - D, to, BISHOP);
*moveList++ = Move::make<PROMOTION>(to - D, to, KNIGHT);
}
return moveList;
}
}
template<Color Us, GenType Type>
ExtMove* generate_pawn_moves(const Position& pos, ExtMove* moveList, Bitboard target) {
template<Color Us, GenType Type>
ExtMove* generate_pawn_moves(const Position& pos, ExtMove* moveList, Bitboard target) {
constexpr Color Them = ~Us;
constexpr Bitboard TRank7BB = (Us == WHITE ? Rank7BB : Rank2BB);
constexpr Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB);
constexpr Bitboard TRank7BB = (Us == WHITE ? Rank7BB : Rank2BB);
constexpr Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB);
constexpr Direction Up = pawn_push(Us);
constexpr Direction UpRight = (Us == WHITE ? NORTH_EAST : SOUTH_WEST);
constexpr Direction UpLeft = (Us == WHITE ? NORTH_WEST : SOUTH_EAST);
const Bitboard emptySquares = ~pos.pieces();
const Bitboard enemies = Type == EVASIONS ? pos.checkers()
: pos.pieces(Them);
const Bitboard enemies = Type == EVASIONS ? pos.checkers() : pos.pieces(Them);
Bitboard pawnsOn7 = pos.pieces(Us, PAWN) & TRank7BB;
Bitboard pawnsOn7 = pos.pieces(Us, PAWN) & TRank7BB;
Bitboard pawnsNotOn7 = pos.pieces(Us, PAWN) & ~TRank7BB;
// Single and double pawn pushes, no promotions
if (Type != CAPTURES)
if constexpr (Type != CAPTURES)
{
Bitboard b1 = shift<Up>(pawnsNotOn7) & emptySquares;
Bitboard b1 = shift<Up>(pawnsNotOn7) & emptySquares;
Bitboard b2 = shift<Up>(b1 & TRank3BB) & emptySquares;
if (Type == EVASIONS) // Consider only blocking squares
if constexpr (Type == EVASIONS) // Consider only blocking squares
{
b1 &= target;
b2 &= target;
}
if (Type == QUIET_CHECKS)
if constexpr (Type == QUIET_CHECKS)
{
// To make a quiet check, you either make a direct check by pushing a pawn
// or push a blocker pawn that is not on the same file as the enemy king.
// Discovered check promotion has been already generated amongst the captures.
Square ksq = pos.square<KING>(Them);
Square ksq = pos.square<KING>(Them);
Bitboard dcCandidatePawns = pos.blockers_for_king(Them) & ~file_bb(ksq);
b1 &= pawn_attacks_bb(Them, ksq) | shift< Up>(dcCandidatePawns);
b2 &= pawn_attacks_bb(Them, ksq) | shift<Up+Up>(dcCandidatePawns);
b1 &= pawn_attacks_bb(Them, ksq) | shift<Up>(dcCandidatePawns);
b2 &= pawn_attacks_bb(Them, ksq) | shift<Up + Up>(dcCandidatePawns);
}
while (b1)
{
Square to = pop_lsb(b1);
*moveList++ = make_move(to - Up, to);
Square to = pop_lsb(b1);
*moveList++ = Move(to - Up, to);
}
while (b2)
{
Square to = pop_lsb(b2);
*moveList++ = make_move(to - Up - Up, to);
Square to = pop_lsb(b2);
*moveList++ = Move(to - Up - Up, to);
}
}
@@ -99,38 +103,38 @@ namespace {
if (pawnsOn7)
{
Bitboard b1 = shift<UpRight>(pawnsOn7) & enemies;
Bitboard b2 = shift<UpLeft >(pawnsOn7) & enemies;
Bitboard b3 = shift<Up >(pawnsOn7) & emptySquares;
Bitboard b2 = shift<UpLeft>(pawnsOn7) & enemies;
Bitboard b3 = shift<Up>(pawnsOn7) & emptySquares;
if (Type == EVASIONS)
if constexpr (Type == EVASIONS)
b3 &= target;
while (b1)
moveList = make_promotions<Type, UpRight>(moveList, pop_lsb(b1));
moveList = make_promotions<Type, UpRight, true>(moveList, pop_lsb(b1));
while (b2)
moveList = make_promotions<Type, UpLeft >(moveList, pop_lsb(b2));
moveList = make_promotions<Type, UpLeft, true>(moveList, pop_lsb(b2));
while (b3)
moveList = make_promotions<Type, Up >(moveList, pop_lsb(b3));
moveList = make_promotions<Type, Up, false>(moveList, pop_lsb(b3));
}
// Standard and en passant captures
if (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS)
if constexpr (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS)
{
Bitboard b1 = shift<UpRight>(pawnsNotOn7) & enemies;
Bitboard b2 = shift<UpLeft >(pawnsNotOn7) & enemies;
Bitboard b2 = shift<UpLeft>(pawnsNotOn7) & enemies;
while (b1)
{
Square to = pop_lsb(b1);
*moveList++ = make_move(to - UpRight, to);
Square to = pop_lsb(b1);
*moveList++ = Move(to - UpRight, to);
}
while (b2)
{
Square to = pop_lsb(b2);
*moveList++ = make_move(to - UpLeft, to);
Square to = pop_lsb(b2);
*moveList++ = Move(to - UpLeft, to);
}
if (pos.ep_square() != SQ_NONE)
@@ -146,16 +150,16 @@ namespace {
assert(b1);
while (b1)
*moveList++ = make<EN_PASSANT>(pop_lsb(b1), pos.ep_square());
*moveList++ = Move::make<EN_PASSANT>(pop_lsb(b1), pos.ep_square());
}
}
return moveList;
}
}
template<Color Us, PieceType Pt, bool Checks>
ExtMove* generate_moves(const Position& pos, ExtMove* moveList, Bitboard target) {
template<Color Us, PieceType Pt, bool Checks>
ExtMove* generate_moves(const Position& pos, ExtMove* moveList, Bitboard target) {
static_assert(Pt != KING && Pt != PAWN, "Unsupported piece type in generate_moves()");
@@ -163,43 +167,43 @@ namespace {
while (bb)
{
Square from = pop_lsb(bb);
Bitboard b = attacks_bb<Pt>(from, pos.pieces()) & target;
Square from = pop_lsb(bb);
Bitboard b = attacks_bb<Pt>(from, pos.pieces()) & target;
// To check, you either move freely a blocker or make a direct check.
if (Checks && (Pt == QUEEN || !(pos.blockers_for_king(~Us) & from)))
b &= pos.check_squares(Pt);
while (b)
*moveList++ = make_move(from, pop_lsb(b));
*moveList++ = Move(from, pop_lsb(b));
}
return moveList;
}
}
template<Color Us, GenType Type>
ExtMove* generate_all(const Position& pos, ExtMove* moveList) {
template<Color Us, GenType Type>
ExtMove* generate_all(const Position& pos, ExtMove* moveList) {
static_assert(Type != LEGAL, "Unsupported type in generate_all()");
constexpr bool Checks = Type == QUIET_CHECKS; // Reduce template instantiations
const Square ksq = pos.square<KING>(Us);
Bitboard target;
constexpr bool Checks = Type == QUIET_CHECKS; // Reduce template instantiations
const Square ksq = pos.square<KING>(Us);
Bitboard target;
// Skip generating non-king moves when in double check
if (Type != EVASIONS || !more_than_one(pos.checkers()))
{
target = Type == EVASIONS ? between_bb(ksq, lsb(pos.checkers()))
: Type == NON_EVASIONS ? ~pos.pieces( Us)
: Type == CAPTURES ? pos.pieces(~Us)
: ~pos.pieces( ); // QUIETS || QUIET_CHECKS
target = Type == EVASIONS ? between_bb(ksq, lsb(pos.checkers()))
: Type == NON_EVASIONS ? ~pos.pieces(Us)
: Type == CAPTURES ? pos.pieces(~Us)
: ~pos.pieces(); // QUIETS || QUIET_CHECKS
moveList = generate_pawn_moves<Us, Type>(pos, moveList, target);
moveList = generate_moves<Us, KNIGHT, Checks>(pos, moveList, target);
moveList = generate_moves<Us, BISHOP, Checks>(pos, moveList, target);
moveList = generate_moves<Us, ROOK, Checks>(pos, moveList, target);
moveList = generate_moves<Us, QUEEN, Checks>(pos, moveList, target);
moveList = generate_moves<Us, ROOK, Checks>(pos, moveList, target);
moveList = generate_moves<Us, QUEEN, Checks>(pos, moveList, target);
}
if (!Checks || pos.blockers_for_king(~Us) & ksq)
@@ -209,38 +213,38 @@ namespace {
b &= ~attacks_bb<QUEEN>(pos.square<KING>(~Us));
while (b)
*moveList++ = make_move(ksq, pop_lsb(b));
*moveList++ = Move(ksq, pop_lsb(b));
if ((Type == QUIETS || Type == NON_EVASIONS) && pos.can_castle(Us & ANY_CASTLING))
for (CastlingRights cr : { Us & KING_SIDE, Us & QUEEN_SIDE } )
for (CastlingRights cr : {Us & KING_SIDE, Us & QUEEN_SIDE})
if (!pos.castling_impeded(cr) && pos.can_castle(cr))
*moveList++ = make<CASTLING>(ksq, pos.castling_rook_square(cr));
*moveList++ = Move::make<CASTLING>(ksq, pos.castling_rook_square(cr));
}
return moveList;
}
}
} // namespace
} // namespace
/// <CAPTURES> Generates all pseudo-legal captures plus queen promotions
/// <QUIETS> Generates all pseudo-legal non-captures and underpromotions
/// <EVASIONS> Generates all pseudo-legal check evasions when the side to move is in check
/// <QUIET_CHECKS> Generates all pseudo-legal non-captures giving check, except castling and promotions
/// <NON_EVASIONS> Generates all pseudo-legal captures and non-captures
///
/// Returns a pointer to the end of the move list.
// <CAPTURES> Generates all pseudo-legal captures plus queen promotions
// <QUIETS> Generates all pseudo-legal non-captures and underpromotions
// <EVASIONS> Generates all pseudo-legal check evasions
// <NON_EVASIONS> Generates all pseudo-legal captures and non-captures
// <QUIET_CHECKS> Generates all pseudo-legal non-captures giving check,
// except castling and promotions
//
// Returns a pointer to the end of the move list.
template<GenType Type>
ExtMove* generate(const Position& pos, ExtMove* moveList) {
static_assert(Type != LEGAL, "Unsupported type in generate()");
assert((Type == EVASIONS) == (bool)pos.checkers());
static_assert(Type != LEGAL, "Unsupported type in generate()");
assert((Type == EVASIONS) == bool(pos.checkers()));
Color us = pos.side_to_move();
Color us = pos.side_to_move();
return us == WHITE ? generate_all<WHITE, Type>(pos, moveList)
: generate_all<BLACK, Type>(pos, moveList);
return us == WHITE ? generate_all<WHITE, Type>(pos, moveList)
: generate_all<BLACK, Type>(pos, moveList);
}
// Explicit template instantiations
@@ -251,26 +255,26 @@ template ExtMove* generate<QUIET_CHECKS>(const Position&, ExtMove*);
template ExtMove* generate<NON_EVASIONS>(const Position&, ExtMove*);
/// generate<LEGAL> generates all the legal moves in the given position
// generate<LEGAL> generates all the legal moves in the given position
template<>
ExtMove* generate<LEGAL>(const Position& pos, ExtMove* moveList) {
Color us = pos.side_to_move();
Bitboard pinned = pos.blockers_for_king(us) & pos.pieces(us);
Square ksq = pos.square<KING>(us);
ExtMove* cur = moveList;
Color us = pos.side_to_move();
Bitboard pinned = pos.blockers_for_king(us) & pos.pieces(us);
Square ksq = pos.square<KING>(us);
ExtMove* cur = moveList;
moveList = pos.checkers() ? generate<EVASIONS >(pos, moveList)
: generate<NON_EVASIONS>(pos, moveList);
while (cur != moveList)
if ( ((pinned && pinned & from_sq(*cur)) || from_sq(*cur) == ksq || type_of(*cur) == EN_PASSANT)
&& !pos.legal(*cur))
*cur = (--moveList)->move;
else
++cur;
moveList =
pos.checkers() ? generate<EVASIONS>(pos, moveList) : generate<NON_EVASIONS>(pos, moveList);
while (cur != moveList)
if (((pinned & cur->from_sq()) || cur->from_sq() == ksq || cur->type_of() == EN_PASSANT)
&& !pos.legal(*cur))
*cur = *(--moveList);
else
++cur;
return moveList;
return moveList;
}
} // namespace Stockfish
} // namespace Stockfish
+29 -32
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -19,7 +19,8 @@
#ifndef MOVEGEN_H_INCLUDED
#define MOVEGEN_H_INCLUDED
#include <algorithm>
#include <algorithm> // IWYU pragma: keep
#include <cstddef>
#include "types.h"
@@ -28,50 +29,46 @@ namespace Stockfish {
class Position;
enum GenType {
CAPTURES,
QUIETS,
QUIET_CHECKS,
EVASIONS,
NON_EVASIONS,
LEGAL
CAPTURES,
QUIETS,
QUIET_CHECKS,
EVASIONS,
NON_EVASIONS,
LEGAL
};
struct ExtMove {
Move move;
int value;
struct ExtMove: public Move {
int value;
operator Move() const { return move; }
void operator=(Move m) { move = m; }
void operator=(Move m) { data = m.raw(); }
// Inhibit unwanted implicit conversions to Move
// with an ambiguity that yields to a compile error.
operator float() const = delete;
// Inhibit unwanted implicit conversions to Move
// with an ambiguity that yields to a compile error.
operator float() const = delete;
};
inline bool operator<(const ExtMove& f, const ExtMove& s) {
return f.value < s.value;
}
inline bool operator<(const ExtMove& f, const ExtMove& s) { return f.value < s.value; }
template<GenType>
ExtMove* generate(const Position& pos, ExtMove* moveList);
/// The MoveList struct is a simple wrapper around generate(). It sometimes comes
/// in handy to use this class instead of the low level generate() function.
// The MoveList struct wraps the generate() function and returns a convenient
// list of moves. Using MoveList is sometimes preferable to directly calling
// the lower level generate() function.
template<GenType T>
struct MoveList {
explicit MoveList(const Position& pos) : last(generate<T>(pos, moveList)) {}
const ExtMove* begin() const { return moveList; }
const ExtMove* end() const { return last; }
size_t size() const { return last - moveList; }
bool contains(Move move) const {
return std::find(begin(), end(), move) != end();
}
explicit MoveList(const Position& pos) :
last(generate<T>(pos, moveList)) {}
const ExtMove* begin() const { return moveList; }
const ExtMove* end() const { return last; }
size_t size() const { return last - moveList; }
bool contains(Move move) const { return std::find(begin(), end(), move) != end(); }
private:
ExtMove moveList[MAX_MOVES], *last;
private:
ExtMove moveList[MAX_MOVES], *last;
};
} // namespace Stockfish
} // namespace Stockfish
#endif // #ifndef MOVEGEN_H_INCLUDED
#endif // #ifndef MOVEGEN_H_INCLUDED
+298 -181
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -16,254 +16,371 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cassert>
#include "movepick.h"
#include <algorithm>
#include <cassert>
#include <iterator>
#include <utility>
#include "bitboard.h"
#include "position.h"
namespace Stockfish {
namespace {
enum Stages {
MAIN_TT, CAPTURE_INIT, GOOD_CAPTURE, REFUTATION, QUIET_INIT, QUIET, BAD_CAPTURE,
EVASION_TT, EVASION_INIT, EVASION,
PROBCUT_TT, PROBCUT_INIT, PROBCUT,
QSEARCH_TT, QCAPTURE_INIT, QCAPTURE, QCHECK_INIT, QCHECK
};
enum Stages {
// generate main search moves
MAIN_TT,
CAPTURE_INIT,
GOOD_CAPTURE,
REFUTATION,
QUIET_INIT,
GOOD_QUIET,
BAD_CAPTURE,
BAD_QUIET,
// partial_insertion_sort() sorts moves in descending order up to and including
// a given limit. The order of moves smaller than the limit is left unspecified.
void partial_insertion_sort(ExtMove* begin, ExtMove* end, int limit) {
// generate evasion moves
EVASION_TT,
EVASION_INIT,
EVASION,
// generate probcut moves
PROBCUT_TT,
PROBCUT_INIT,
PROBCUT,
// generate qsearch moves
QSEARCH_TT,
QCAPTURE_INIT,
QCAPTURE,
QCHECK_INIT,
QCHECK
};
// Sort moves in descending order up to and including
// a given limit. The order of moves smaller than the limit is left unspecified.
void partial_insertion_sort(ExtMove* begin, ExtMove* end, int limit) {
for (ExtMove *sortedEnd = begin, *p = begin + 1; p < end; ++p)
if (p->value >= limit)
{
ExtMove tmp = *p, *q;
*p = *++sortedEnd;
*p = *++sortedEnd;
for (q = sortedEnd; q != begin && *(q - 1) < tmp; --q)
*q = *(q - 1);
*q = tmp;
}
}
} // namespace
/// Constructors of the MovePicker class. As arguments we pass information
/// to help it to return the (presumably) good moves first, to decide which
/// moves to return (in the quiescence search, for instance, we only want to
/// search captures, promotions, and some checks) and how important good move
/// ordering is at the current node.
/// MovePicker constructor for the main search
MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHistory* mh, const LowPlyHistory* lp,
const CapturePieceToHistory* cph, const PieceToHistory** ch, Move cm, const Move* killers, int pl)
: pos(p), mainHistory(mh), lowPlyHistory(lp), captureHistory(cph), continuationHistory(ch),
ttMove(ttm), refutations{{killers[0], 0}, {killers[1], 0}, {cm, 0}}, depth(d), ply(pl) {
assert(d > 0);
stage = (pos.checkers() ? EVASION_TT : MAIN_TT) +
!(ttm && pos.pseudo_legal(ttm));
}
/// MovePicker constructor for quiescence search
MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHistory* mh,
const CapturePieceToHistory* cph, const PieceToHistory** ch, Square rs)
: pos(p), mainHistory(mh), captureHistory(cph), continuationHistory(ch), ttMove(ttm), recaptureSquare(rs), depth(d) {
} // namespace
assert(d <= 0);
stage = (pos.checkers() ? EVASION_TT : QSEARCH_TT) +
!( ttm
&& (pos.checkers() || depth > DEPTH_QS_RECAPTURES || to_sq(ttm) == recaptureSquare)
&& pos.pseudo_legal(ttm));
// Constructors of the MovePicker class. As arguments, we pass information
// to help it return the (presumably) good moves first, to decide which
// moves to return (in the quiescence search, for instance, we only want to
// search captures, promotions, and some checks) and how important a good
// move ordering is at the current node.
// MovePicker constructor for the main search
MovePicker::MovePicker(const Position& p,
Move ttm,
Depth d,
const ButterflyHistory* mh,
const CapturePieceToHistory* cph,
const PieceToHistory** ch,
const PawnHistory* ph,
Move cm,
const Move* killers) :
pos(p),
mainHistory(mh),
captureHistory(cph),
continuationHistory(ch),
pawnHistory(ph),
ttMove(ttm),
refutations{{killers[0], 0}, {killers[1], 0}, {cm, 0}},
depth(d) {
assert(d > 0);
stage = (pos.checkers() ? EVASION_TT : MAIN_TT) + !(ttm && pos.pseudo_legal(ttm));
}
/// MovePicker constructor for ProbCut: we generate captures with SEE greater
/// than or equal to the given threshold.
MovePicker::MovePicker(const Position& p, Move ttm, Value th, const CapturePieceToHistory* cph)
: pos(p), captureHistory(cph), ttMove(ttm), threshold(th) {
// Constructor for quiescence search
MovePicker::MovePicker(const Position& p,
Move ttm,
Depth d,
const ButterflyHistory* mh,
const CapturePieceToHistory* cph,
const PieceToHistory** ch,
const PawnHistory* ph) :
pos(p),
mainHistory(mh),
captureHistory(cph),
continuationHistory(ch),
pawnHistory(ph),
ttMove(ttm),
depth(d) {
assert(d <= 0);
assert(!pos.checkers());
stage = PROBCUT_TT + !(ttm && pos.capture(ttm)
&& pos.pseudo_legal(ttm)
&& pos.see_ge(ttm, threshold));
stage = (pos.checkers() ? EVASION_TT : QSEARCH_TT) + !(ttm && pos.pseudo_legal(ttm));
}
/// MovePicker::score() assigns a numerical value to each move in a list, used
/// for sorting. Captures are ordered by Most Valuable Victim (MVV), preferring
/// captures with a good history. Quiets moves are ordered using the histories.
// Constructor for ProbCut: we generate captures with SEE greater
// than or equal to the given threshold.
MovePicker::MovePicker(const Position& p, Move ttm, int th, const CapturePieceToHistory* cph) :
pos(p),
captureHistory(cph),
ttMove(ttm),
threshold(th) {
assert(!pos.checkers());
stage = PROBCUT_TT
+ !(ttm && pos.capture_stage(ttm) && pos.pseudo_legal(ttm) && pos.see_ge(ttm, threshold));
}
// Assigns a numerical value to each move in a list, used
// for sorting. Captures are ordered by Most Valuable Victim (MVV), preferring
// captures with a good history. Quiets moves are ordered using the history tables.
template<GenType Type>
void MovePicker::score() {
static_assert(Type == CAPTURES || Type == QUIETS || Type == EVASIONS, "Wrong type");
static_assert(Type == CAPTURES || Type == QUIETS || Type == EVASIONS, "Wrong type");
for (auto& m : *this)
if constexpr (Type == CAPTURES)
m.value = int(PieceValue[MG][pos.piece_on(to_sq(m))]) * 6
+ (*captureHistory)[pos.moved_piece(m)][to_sq(m)][type_of(pos.piece_on(to_sq(m)))];
[[maybe_unused]] Bitboard threatenedByPawn, threatenedByMinor, threatenedByRook,
threatenedPieces;
if constexpr (Type == QUIETS)
{
Color us = pos.side_to_move();
else if constexpr (Type == QUIETS)
m.value = (*mainHistory)[pos.side_to_move()][from_to(m)]
+ 2 * (*continuationHistory[0])[pos.moved_piece(m)][to_sq(m)]
+ (*continuationHistory[1])[pos.moved_piece(m)][to_sq(m)]
+ (*continuationHistory[3])[pos.moved_piece(m)][to_sq(m)]
+ (*continuationHistory[5])[pos.moved_piece(m)][to_sq(m)]
+ (ply < MAX_LPH ? 6 * (*lowPlyHistory)[ply][from_to(m)] : 0);
threatenedByPawn = pos.attacks_by<PAWN>(~us);
threatenedByMinor =
pos.attacks_by<KNIGHT>(~us) | pos.attacks_by<BISHOP>(~us) | threatenedByPawn;
threatenedByRook = pos.attacks_by<ROOK>(~us) | threatenedByMinor;
else // Type == EVASIONS
{
if (pos.capture(m))
m.value = PieceValue[MG][pos.piece_on(to_sq(m))]
- Value(type_of(pos.moved_piece(m)));
else
m.value = (*mainHistory)[pos.side_to_move()][from_to(m)]
+ 2 * (*continuationHistory[0])[pos.moved_piece(m)][to_sq(m)]
- (1 << 28);
}
// Pieces threatened by pieces of lesser material value
threatenedPieces = (pos.pieces(us, QUEEN) & threatenedByRook)
| (pos.pieces(us, ROOK) & threatenedByMinor)
| (pos.pieces(us, KNIGHT, BISHOP) & threatenedByPawn);
}
for (auto& m : *this)
if constexpr (Type == CAPTURES)
m.value =
7 * int(PieceValue[pos.piece_on(m.to_sq())])
+ (*captureHistory)[pos.moved_piece(m)][m.to_sq()][type_of(pos.piece_on(m.to_sq()))];
else if constexpr (Type == QUIETS)
{
Piece pc = pos.moved_piece(m);
PieceType pt = type_of(pc);
Square from = m.from_sq();
Square to = m.to_sq();
// histories
m.value = 2 * (*mainHistory)[pos.side_to_move()][m.from_to()];
m.value += 2 * (*pawnHistory)[pawn_structure_index(pos)][pc][to];
m.value += 2 * (*continuationHistory[0])[pc][to];
m.value += (*continuationHistory[1])[pc][to];
m.value += (*continuationHistory[2])[pc][to] / 4;
m.value += (*continuationHistory[3])[pc][to];
m.value += (*continuationHistory[5])[pc][to];
// bonus for checks
m.value += bool(pos.check_squares(pt) & to) * 16384;
// bonus for escaping from capture
m.value += threatenedPieces & from ? (pt == QUEEN && !(to & threatenedByRook) ? 50000
: pt == ROOK && !(to & threatenedByMinor) ? 25000
: !(to & threatenedByPawn) ? 15000
: 0)
: 0;
// malus for putting piece en prise
m.value -= !(threatenedPieces & from)
? (pt == QUEEN ? bool(to & threatenedByRook) * 50000
+ bool(to & threatenedByMinor) * 10000
: pt == ROOK ? bool(to & threatenedByMinor) * 25000
: pt != PAWN ? bool(to & threatenedByPawn) * 15000
: 0)
: 0;
}
else // Type == EVASIONS
{
if (pos.capture_stage(m))
m.value =
PieceValue[pos.piece_on(m.to_sq())] - type_of(pos.moved_piece(m)) + (1 << 28);
else
m.value = (*mainHistory)[pos.side_to_move()][m.from_to()]
+ (*continuationHistory[0])[pos.moved_piece(m)][m.to_sq()]
+ (*pawnHistory)[pawn_structure_index(pos)][pos.moved_piece(m)][m.to_sq()];
}
}
/// MovePicker::select() returns the next move satisfying a predicate function.
/// It never returns the TT move.
// Returns the next move satisfying a predicate function.
// It never returns the TT move.
template<MovePicker::PickType T, typename Pred>
Move MovePicker::select(Pred filter) {
while (cur < endMoves)
{
if (T == Best)
std::swap(*cur, *std::max_element(cur, endMoves));
while (cur < endMoves)
{
if constexpr (T == Best)
std::swap(*cur, *std::max_element(cur, endMoves));
if (*cur != ttMove && filter())
return *cur++;
if (*cur != ttMove && filter())
return *cur++;
cur++;
}
return MOVE_NONE;
cur++;
}
return Move::none();
}
/// MovePicker::next_move() is the most important method of the MovePicker class. It
/// returns a new pseudo-legal move every time it is called until there are no more
/// moves left, picking the move with the highest score from a list of generated moves.
// Most important method of the MovePicker class. It
// returns a new pseudo-legal move every time it is called until there are no more
// moves left, picking the move with the highest score from a list of generated moves.
Move MovePicker::next_move(bool skipQuiets) {
auto quiet_threshold = [](Depth d) { return -3330 * d; };
top:
switch (stage) {
switch (stage)
{
case MAIN_TT:
case EVASION_TT:
case QSEARCH_TT:
case PROBCUT_TT:
++stage;
return ttMove;
case MAIN_TT :
case EVASION_TT :
case QSEARCH_TT :
case PROBCUT_TT :
++stage;
return ttMove;
case CAPTURE_INIT:
case PROBCUT_INIT:
case QCAPTURE_INIT:
cur = endBadCaptures = moves;
endMoves = generate<CAPTURES>(pos, cur);
case CAPTURE_INIT :
case PROBCUT_INIT :
case QCAPTURE_INIT :
cur = endBadCaptures = moves;
endMoves = generate<CAPTURES>(pos, cur);
score<CAPTURES>();
++stage;
goto top;
score<CAPTURES>();
partial_insertion_sort(cur, endMoves, std::numeric_limits<int>::min());
++stage;
goto top;
case GOOD_CAPTURE:
if (select<Best>([&](){
return pos.see_ge(*cur, Value(-69 * cur->value / 1024)) ?
// Move losing capture to endBadCaptures to be tried later
true : (*endBadCaptures++ = *cur, false); }))
return *(cur - 1);
case GOOD_CAPTURE :
if (select<Next>([&]() {
// Move losing capture to endBadCaptures to be tried later
return pos.see_ge(*cur, -cur->value / 18) ? true
: (*endBadCaptures++ = *cur, false);
}))
return *(cur - 1);
// Prepare the pointers to loop over the refutations array
cur = std::begin(refutations);
endMoves = std::end(refutations);
// Prepare the pointers to loop over the refutations array
cur = std::begin(refutations);
endMoves = std::end(refutations);
// If the countermove is the same as a killer, skip it
if ( refutations[0].move == refutations[2].move
|| refutations[1].move == refutations[2].move)
--endMoves;
// If the countermove is the same as a killer, skip it
if (refutations[0] == refutations[2] || refutations[1] == refutations[2])
--endMoves;
++stage;
[[fallthrough]];
++stage;
[[fallthrough]];
case REFUTATION:
if (select<Next>([&](){ return *cur != MOVE_NONE
&& !pos.capture(*cur)
&& pos.pseudo_legal(*cur); }))
return *(cur - 1);
++stage;
[[fallthrough]];
case REFUTATION :
if (select<Next>([&]() {
return *cur != Move::none() && !pos.capture_stage(*cur) && pos.pseudo_legal(*cur);
}))
return *(cur - 1);
++stage;
[[fallthrough]];
case QUIET_INIT:
if (!skipQuiets)
{
cur = endBadCaptures;
endMoves = generate<QUIETS>(pos, cur);
case QUIET_INIT :
if (!skipQuiets)
{
cur = endBadCaptures;
endMoves = beginBadQuiets = endBadQuiets = generate<QUIETS>(pos, cur);
score<QUIETS>();
partial_insertion_sort(cur, endMoves, -3000 * depth);
}
score<QUIETS>();
partial_insertion_sort(cur, endMoves, quiet_threshold(depth));
}
++stage;
[[fallthrough]];
++stage;
[[fallthrough]];
case QUIET:
if ( !skipQuiets
&& select<Next>([&](){return *cur != refutations[0].move
&& *cur != refutations[1].move
&& *cur != refutations[2].move;}))
return *(cur - 1);
case GOOD_QUIET :
if (!skipQuiets && select<Next>([&]() {
return *cur != refutations[0] && *cur != refutations[1] && *cur != refutations[2];
}))
{
if ((cur - 1)->value > -8000 || (cur - 1)->value <= quiet_threshold(depth))
return *(cur - 1);
// Prepare the pointers to loop over the bad captures
cur = moves;
endMoves = endBadCaptures;
// Remaining quiets are bad
beginBadQuiets = cur - 1;
}
++stage;
[[fallthrough]];
// Prepare the pointers to loop over the bad captures
cur = moves;
endMoves = endBadCaptures;
case BAD_CAPTURE:
return select<Next>([](){ return true; });
++stage;
[[fallthrough]];
case EVASION_INIT:
cur = moves;
endMoves = generate<EVASIONS>(pos, cur);
case BAD_CAPTURE :
if (select<Next>([]() { return true; }))
return *(cur - 1);
score<EVASIONS>();
++stage;
[[fallthrough]];
// Prepare the pointers to loop over the bad quiets
cur = beginBadQuiets;
endMoves = endBadQuiets;
case EVASION:
return select<Best>([](){ return true; });
++stage;
[[fallthrough]];
case PROBCUT:
return select<Best>([&](){ return pos.see_ge(*cur, threshold); });
case BAD_QUIET :
if (!skipQuiets)
return select<Next>([&]() {
return *cur != refutations[0] && *cur != refutations[1] && *cur != refutations[2];
});
case QCAPTURE:
if (select<Best>([&](){ return depth > DEPTH_QS_RECAPTURES
|| to_sq(*cur) == recaptureSquare; }))
return *(cur - 1);
return Move::none();
// If we did not find any move and we do not try checks, we have finished
if (depth != DEPTH_QS_CHECKS)
return MOVE_NONE;
case EVASION_INIT :
cur = moves;
endMoves = generate<EVASIONS>(pos, cur);
++stage;
[[fallthrough]];
score<EVASIONS>();
++stage;
[[fallthrough]];
case QCHECK_INIT:
cur = moves;
endMoves = generate<QUIET_CHECKS>(pos, cur);
case EVASION :
return select<Best>([]() { return true; });
++stage;
[[fallthrough]];
case PROBCUT :
return select<Next>([&]() { return pos.see_ge(*cur, threshold); });
case QCHECK:
return select<Next>([](){ return true; });
}
case QCAPTURE :
if (select<Next>([]() { return true; }))
return *(cur - 1);
assert(false);
return MOVE_NONE; // Silence warning
// If we did not find any move and we do not try checks, we have finished
if (depth != DEPTH_QS_CHECKS)
return Move::none();
++stage;
[[fallthrough]];
case QCHECK_INIT :
cur = moves;
endMoves = generate<QUIET_CHECKS>(pos, cur);
++stage;
[[fallthrough]];
case QCHECK :
return select<Next>([]() { return true; });
}
assert(false);
return Move::none(); // Silence warning
}
} // namespace Stockfish
} // namespace Stockfish
+141 -104
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -20,144 +20,181 @@
#define MOVEPICK_H_INCLUDED
#include <array>
#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <limits>
#include <type_traits>
#include <type_traits> // IWYU pragma: keep
#include "movegen.h"
#include "position.h"
#include "types.h"
#include "position.h"
namespace Stockfish {
/// StatsEntry stores the stat table value. It is usually a number but could
/// be a move or even a nested history. We use a class instead of naked value
/// to directly call history update operator<<() on the entry so to use stats
/// tables at caller sites as simple multi-dim arrays.
constexpr int PAWN_HISTORY_SIZE = 512; // has to be a power of 2
constexpr int CORRECTION_HISTORY_SIZE = 16384; // has to be a power of 2
constexpr int CORRECTION_HISTORY_LIMIT = 1024;
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<PawnHistoryType T = Normal>
inline int pawn_structure_index(const Position& pos) {
return pos.pawn_key() & ((T == Normal ? PAWN_HISTORY_SIZE : CORRECTION_HISTORY_SIZE) - 1);
}
// StatsEntry stores the stat table value. It is usually a number but could
// be a move or even a nested history. We use a class instead of a naked value
// to directly call history update operator<<() on the entry so to use stats
// tables at caller sites as simple multi-dim arrays.
template<typename T, int D>
class StatsEntry {
T entry;
T entry;
public:
void operator=(const T& v) { entry = v; }
T* operator&() { return &entry; }
T* operator->() { return &entry; }
operator const T&() const { return entry; }
public:
void operator=(const T& v) { entry = v; }
T* operator&() { return &entry; }
T* operator->() { return &entry; }
operator const T&() const { return entry; }
void operator<<(int bonus) {
assert(abs(bonus) <= D); // Ensure range is [-D, D]
static_assert(D <= std::numeric_limits<T>::max(), "D overflows T");
void operator<<(int bonus) {
assert(std::abs(bonus) <= D); // Ensure range is [-D, D]
static_assert(D <= std::numeric_limits<T>::max(), "D overflows T");
entry += bonus - entry * abs(bonus) / D;
entry += bonus - entry * std::abs(bonus) / D;
assert(abs(entry) <= D);
}
assert(std::abs(entry) <= D);
}
};
/// Stats is a generic N-dimensional array used to store various statistics.
/// The first template parameter T is the base type of the array, the second
/// template parameter D limits the range of updates in [-D, D] when we update
/// values with the << operator, while the last parameters (Size and Sizes)
/// encode the dimensions of the array.
template <typename T, int D, int Size, int... Sizes>
struct Stats : public std::array<Stats<T, D, Sizes...>, Size>
{
typedef Stats<T, D, Size, Sizes...> stats;
// Stats is a generic N-dimensional array used to store various statistics.
// 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, while the last parameters (Size and Sizes)
// encode the dimensions of the array.
template<typename T, int D, int Size, int... Sizes>
struct Stats: public std::array<Stats<T, D, Sizes...>, Size> {
using stats = Stats<T, D, Size, Sizes...>;
void fill(const T& v) {
void fill(const T& v) {
// For standard-layout 'this' points to first struct member
assert(std::is_standard_layout<stats>::value);
// For standard-layout 'this' points to the first struct member
assert(std::is_standard_layout_v<stats>);
typedef StatsEntry<T, D> entry;
entry* p = reinterpret_cast<entry*>(this);
std::fill(p, p + sizeof(*this) / sizeof(entry), v);
}
using entry = StatsEntry<T, D>;
entry* p = reinterpret_cast<entry*>(this);
std::fill(p, p + sizeof(*this) / sizeof(entry), v);
}
};
template <typename T, int D, int Size>
struct Stats<T, D, Size> : public std::array<StatsEntry<T, D>, Size> {};
template<typename T, int D, int Size>
struct Stats<T, D, Size>: public std::array<StatsEntry<T, D>, Size> {};
/// In stats table, D=0 means that the template parameter is not used
enum StatsParams { NOT_USED = 0 };
enum StatsType { NoCaptures, Captures };
// In stats table, D=0 means that the template parameter is not used
enum StatsParams {
NOT_USED = 0
};
enum StatsType {
NoCaptures,
Captures
};
/// 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 www.chessprogramming.org/Butterfly_Boards
typedef Stats<int16_t, 14365, COLOR_NB, int(SQUARE_NB) * int(SQUARE_NB)> ButterflyHistory;
// 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 www.chessprogramming.org/Butterfly_Boards (~11 elo)
using ButterflyHistory = Stats<int16_t, 7183, COLOR_NB, int(SQUARE_NB) * int(SQUARE_NB)>;
/// At higher depths LowPlyHistory records successful quiet moves near the root
/// and quiet moves which are/were in the PV (ttPv). LowPlyHistory is populated during
/// iterative deepening and at each new search the data is shifted down by 2 plies
constexpr int MAX_LPH = 4;
typedef Stats<int16_t, 10692, MAX_LPH, int(SQUARE_NB) * int(SQUARE_NB)> LowPlyHistory;
// CounterMoveHistory stores counter moves indexed by [piece][to] of the previous
// move, see www.chessprogramming.org/Countermove_Heuristic
using CounterMoveHistory = Stats<Move, NOT_USED, PIECE_NB, SQUARE_NB>;
/// CounterMoveHistory stores counter moves indexed by [piece][to] of the previous
/// move, see www.chessprogramming.org/Countermove_Heuristic
typedef Stats<Move, NOT_USED, PIECE_NB, SQUARE_NB> CounterMoveHistory;
// CapturePieceToHistory is addressed by a move's [piece][to][captured piece type]
using CapturePieceToHistory = Stats<int16_t, 10692, PIECE_NB, SQUARE_NB, PIECE_TYPE_NB>;
/// CapturePieceToHistory is addressed by a move's [piece][to][captured piece type]
typedef Stats<int16_t, 10692, PIECE_NB, SQUARE_NB, PIECE_TYPE_NB> CapturePieceToHistory;
// PieceToHistory is like ButterflyHistory but is addressed by a move's [piece][to]
using PieceToHistory = Stats<int16_t, 29952, PIECE_NB, SQUARE_NB>;
/// PieceToHistory is like ButterflyHistory but is addressed by a move's [piece][to]
typedef Stats<int16_t, 29952, PIECE_NB, SQUARE_NB> PieceToHistory;
// 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 = Stats<PieceToHistory, NOT_USED, PIECE_NB, SQUARE_NB>;
/// 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.
typedef Stats<PieceToHistory, NOT_USED, PIECE_NB, SQUARE_NB> ContinuationHistory;
// PawnHistory is addressed by the pawn structure and a move's [piece][to]
using PawnHistory = Stats<int16_t, 8192, PAWN_HISTORY_SIZE, PIECE_NB, SQUARE_NB>;
// CorrectionHistory is addressed by color and pawn structure
using CorrectionHistory =
Stats<int16_t, CORRECTION_HISTORY_LIMIT, COLOR_NB, CORRECTION_HISTORY_SIZE>;
/// MovePicker class is used to pick one pseudo-legal move at a time from the
/// current position. The most important method is next_move(), which returns a
/// new pseudo-legal move each time it is called, until there are no moves left,
/// when MOVE_NONE is returned. In order to improve the efficiency of the
/// alpha-beta algorithm, MovePicker attempts to return the moves which are most
/// likely to get a cut-off first.
// MovePicker class is used to pick one pseudo-legal move at a time from the
// current position. The most important method is next_move(), which returns a
// new pseudo-legal move each time it is called, until there are no moves left,
// when Move::none() is returned. In order to improve the efficiency of the
// alpha-beta algorithm, MovePicker attempts to return the moves which are most
// likely to get a cut-off first.
class MovePicker {
enum PickType { Next, Best };
enum PickType {
Next,
Best
};
public:
MovePicker(const MovePicker&) = delete;
MovePicker& operator=(const MovePicker&) = delete;
MovePicker(const Position&, Move, Value, const CapturePieceToHistory*);
MovePicker(const Position&, Move, Depth, const ButterflyHistory*,
const CapturePieceToHistory*,
const PieceToHistory**,
Square);
MovePicker(const Position&, Move, Depth, const ButterflyHistory*,
const LowPlyHistory*,
const CapturePieceToHistory*,
const PieceToHistory**,
Move,
const Move*,
int);
Move next_move(bool skipQuiets = false);
public:
MovePicker(const MovePicker&) = delete;
MovePicker& operator=(const MovePicker&) = delete;
MovePicker(const Position&,
Move,
Depth,
const ButterflyHistory*,
const CapturePieceToHistory*,
const PieceToHistory**,
const PawnHistory*,
Move,
const Move*);
MovePicker(const Position&,
Move,
Depth,
const ButterflyHistory*,
const CapturePieceToHistory*,
const PieceToHistory**,
const PawnHistory*);
MovePicker(const Position&, Move, int, const CapturePieceToHistory*);
Move next_move(bool skipQuiets = false);
private:
template<PickType T, typename Pred> Move select(Pred);
template<GenType> void score();
ExtMove* begin() { return cur; }
ExtMove* end() { return endMoves; }
private:
template<PickType T, typename Pred>
Move select(Pred);
template<GenType>
void score();
ExtMove* begin() { return cur; }
ExtMove* end() { return endMoves; }
const Position& pos;
const ButterflyHistory* mainHistory;
const LowPlyHistory* lowPlyHistory;
const CapturePieceToHistory* captureHistory;
const PieceToHistory** continuationHistory;
Move ttMove;
ExtMove refutations[3], *cur, *endMoves, *endBadCaptures;
int stage;
Square recaptureSquare;
Value threshold;
Depth depth;
int ply;
ExtMove moves[MAX_MOVES];
const Position& pos;
const ButterflyHistory* mainHistory;
const CapturePieceToHistory* captureHistory;
const PieceToHistory** continuationHistory;
const PawnHistory* pawnHistory;
Move ttMove;
ExtMove refutations[3], *cur, *endMoves, *endBadCaptures, *beginBadQuiets, *endBadQuiets;
int stage;
int threshold;
Depth depth;
ExtMove moves[MAX_MOVES];
};
} // namespace Stockfish
} // namespace Stockfish
#endif // #ifndef MOVEPICK_H_INCLUDED
#endif // #ifndef MOVEPICK_H_INCLUDED
+280 -213
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -18,315 +18,375 @@
// Code for calculating NNUE evaluation function
#include <iostream>
#include <set>
#include <sstream>
#include <iomanip>
#include "evaluate_nnue.h"
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <optional>
#include <sstream>
#include <string_view>
#include <type_traits>
#include <unordered_map>
#include "../evaluate.h"
#include "../position.h"
#include "../misc.h"
#include "../uci.h"
#include "../position.h"
#include "../types.h"
#include "evaluate_nnue.h"
#include "../uci.h"
#include "nnue_accumulator.h"
#include "nnue_common.h"
namespace Stockfish::Eval::NNUE {
// Input feature converter
LargePagePtr<FeatureTransformer> featureTransformer;
// Input feature converter
LargePagePtr<FeatureTransformer<TransformedFeatureDimensionsBig, &StateInfo::accumulatorBig>>
featureTransformerBig;
LargePagePtr<FeatureTransformer<TransformedFeatureDimensionsSmall, &StateInfo::accumulatorSmall>>
featureTransformerSmall;
// Evaluation function
AlignedPtr<Network> network[LayerStacks];
// Evaluation function
AlignedPtr<Network<TransformedFeatureDimensionsBig, L2Big, L3Big>> networkBig[LayerStacks];
AlignedPtr<Network<TransformedFeatureDimensionsSmall, L2Small, L3Small>> networkSmall[LayerStacks];
// Evaluation function file name
std::string fileName;
std::string netDescription;
// Evaluation function file names
namespace Detail {
namespace Detail {
// Initialize the evaluation function parameters
template <typename T>
void initialize(AlignedPtr<T>& pointer) {
// Initialize the evaluation function parameters
template<typename T>
void initialize(AlignedPtr<T>& pointer) {
pointer.reset(reinterpret_cast<T*>(std_aligned_alloc(alignof(T), sizeof(T))));
std::memset(pointer.get(), 0, sizeof(T));
}
}
template <typename T>
void initialize(LargePagePtr<T>& pointer) {
template<typename T>
void initialize(LargePagePtr<T>& pointer) {
static_assert(alignof(T) <= 4096, "aligned_large_pages_alloc() may fail for such a big alignment requirement of T");
static_assert(alignof(T) <= 4096,
"aligned_large_pages_alloc() may fail for such a big alignment requirement of T");
pointer.reset(reinterpret_cast<T*>(aligned_large_pages_alloc(sizeof(T))));
std::memset(pointer.get(), 0, sizeof(T));
}
}
// Read evaluation function parameters
template <typename T>
bool read_parameters(std::istream& stream, T& reference) {
// Read evaluation function parameters
template<typename T>
bool read_parameters(std::istream& stream, T& reference) {
std::uint32_t header;
header = read_little_endian<std::uint32_t>(stream);
if (!stream || header != T::get_hash_value()) return false;
if (!stream || header != T::get_hash_value())
return false;
return reference.read_parameters(stream);
}
}
// Write evaluation function parameters
template <typename T>
bool write_parameters(std::ostream& stream, const T& reference) {
// Write evaluation function parameters
template<typename T>
bool write_parameters(std::ostream& stream, const T& reference) {
write_little_endian<std::uint32_t>(stream, T::get_hash_value());
return reference.write_parameters(stream);
}
}
} // namespace Detail
} // namespace Detail
// Initialize the evaluation function parameters
void initialize() {
Detail::initialize(featureTransformer);
for (std::size_t i = 0; i < LayerStacks; ++i)
Detail::initialize(network[i]);
}
// Initialize the evaluation function parameters
static void initialize(NetSize netSize) {
// Read network header
bool read_header(std::istream& stream, std::uint32_t* hashValue, std::string* desc)
{
if (netSize == Small)
{
Detail::initialize(featureTransformerSmall);
for (std::size_t i = 0; i < LayerStacks; ++i)
Detail::initialize(networkSmall[i]);
}
else
{
Detail::initialize(featureTransformerBig);
for (std::size_t i = 0; i < LayerStacks; ++i)
Detail::initialize(networkBig[i]);
}
}
// Read network header
static bool read_header(std::istream& stream, std::uint32_t* hashValue, std::string* desc) {
std::uint32_t version, size;
version = read_little_endian<std::uint32_t>(stream);
*hashValue = read_little_endian<std::uint32_t>(stream);
size = read_little_endian<std::uint32_t>(stream);
if (!stream || version != Version) return false;
version = read_little_endian<std::uint32_t>(stream);
*hashValue = read_little_endian<std::uint32_t>(stream);
size = read_little_endian<std::uint32_t>(stream);
if (!stream || version != Version)
return false;
desc->resize(size);
stream.read(&(*desc)[0], size);
return !stream.fail();
}
}
// Write network header
bool write_header(std::ostream& stream, std::uint32_t hashValue, const std::string& desc)
{
// Write network header
static bool write_header(std::ostream& stream, std::uint32_t hashValue, const std::string& desc) {
write_little_endian<std::uint32_t>(stream, Version);
write_little_endian<std::uint32_t>(stream, hashValue);
write_little_endian<std::uint32_t>(stream, desc.size());
write_little_endian<std::uint32_t>(stream, std::uint32_t(desc.size()));
stream.write(&desc[0], desc.size());
return !stream.fail();
}
}
// Read network parameters
bool read_parameters(std::istream& stream) {
// Read network parameters
static bool read_parameters(std::istream& stream, NetSize netSize, std::string& netDescription) {
std::uint32_t hashValue;
if (!read_header(stream, &hashValue, &netDescription)) return false;
if (hashValue != HashValue) return false;
if (!Detail::read_parameters(stream, *featureTransformer)) return false;
if (!read_header(stream, &hashValue, &netDescription))
return false;
if (hashValue != HashValue[netSize])
return false;
if (netSize == Big && !Detail::read_parameters(stream, *featureTransformerBig))
return false;
if (netSize == Small && !Detail::read_parameters(stream, *featureTransformerSmall))
return false;
for (std::size_t i = 0; i < LayerStacks; ++i)
if (!Detail::read_parameters(stream, *(network[i]))) return false;
{
if (netSize == Big && !Detail::read_parameters(stream, *(networkBig[i])))
return false;
if (netSize == Small && !Detail::read_parameters(stream, *(networkSmall[i])))
return false;
}
return stream && stream.peek() == std::ios::traits_type::eof();
}
}
// Write network parameters
bool write_parameters(std::ostream& stream) {
// Write network parameters
static bool
write_parameters(std::ostream& stream, NetSize netSize, const std::string& netDescription) {
if (!write_header(stream, HashValue, netDescription)) return false;
if (!Detail::write_parameters(stream, *featureTransformer)) return false;
if (!write_header(stream, HashValue[netSize], netDescription))
return false;
if (netSize == Big && !Detail::write_parameters(stream, *featureTransformerBig))
return false;
if (netSize == Small && !Detail::write_parameters(stream, *featureTransformerSmall))
return false;
for (std::size_t i = 0; i < LayerStacks; ++i)
if (!Detail::write_parameters(stream, *(network[i]))) return false;
return (bool)stream;
}
{
if (netSize == Big && !Detail::write_parameters(stream, *(networkBig[i])))
return false;
if (netSize == Small && !Detail::write_parameters(stream, *(networkSmall[i])))
return false;
}
return bool(stream);
}
// Evaluation function. Perform differential calculation.
Value evaluate(const Position& pos, bool adjusted) {
void hint_common_parent_position(const Position& pos) {
int simpleEval = simple_eval(pos, pos.side_to_move());
if (std::abs(simpleEval) > 1050)
featureTransformerSmall->hint_common_access(pos);
else
featureTransformerBig->hint_common_access(pos);
}
// Evaluation function. Perform differential calculation.
template<NetSize Net_Size>
Value evaluate(const Position& pos, bool adjusted, int* complexity) {
// We manually align the arrays on the stack because with gcc < 9.3
// overaligning stack variables with alignas() doesn't work correctly.
constexpr uint64_t alignment = CacheLineSize;
int delta = 7;
constexpr int delta = 24;
#if defined(ALIGNAS_ON_STACK_VARIABLES_BROKEN)
TransformedFeatureType transformedFeaturesUnaligned[
FeatureTransformer::BufferSize + alignment / sizeof(TransformedFeatureType)];
char bufferUnaligned[Network::BufferSize + alignment];
TransformedFeatureType transformedFeaturesUnaligned
[FeatureTransformer < Net_Size == Small ? TransformedFeatureDimensionsSmall
: TransformedFeatureDimensionsBig,
nullptr > ::BufferSize + alignment / sizeof(TransformedFeatureType)];
auto* transformedFeatures = align_ptr_up<alignment>(&transformedFeaturesUnaligned[0]);
auto* buffer = align_ptr_up<alignment>(&bufferUnaligned[0]);
#else
alignas(alignment)
TransformedFeatureType transformedFeatures[FeatureTransformer::BufferSize];
alignas(alignment) char buffer[Network::BufferSize];
alignas(alignment) TransformedFeatureType
transformedFeatures[FeatureTransformer < Net_Size == Small ? TransformedFeatureDimensionsSmall
: TransformedFeatureDimensionsBig,
nullptr > ::BufferSize];
#endif
ASSERT_ALIGNED(transformedFeatures, alignment);
ASSERT_ALIGNED(buffer, alignment);
const std::size_t bucket = (pos.count<ALL_PIECES>() - 1) / 4;
const auto psqt = featureTransformer->transform(pos, transformedFeatures, bucket);
const auto positional = network[bucket]->propagate(transformedFeatures, buffer)[0];
const int bucket = (pos.count<ALL_PIECES>() - 1) / 4;
const auto psqt = Net_Size == Small
? featureTransformerSmall->transform(pos, transformedFeatures, bucket)
: featureTransformerBig->transform(pos, transformedFeatures, bucket);
const auto positional = Net_Size == Small ? networkSmall[bucket]->propagate(transformedFeatures)
: networkBig[bucket]->propagate(transformedFeatures);
// Give more value to positional evaluation when material is balanced
if ( adjusted
&& abs(pos.non_pawn_material(WHITE) - pos.non_pawn_material(BLACK)) <= RookValueMg - BishopValueMg)
return static_cast<Value>(((128 - delta) * psqt + (128 + delta) * positional) / 128 / OutputScale);
if (complexity)
*complexity = std::abs(psqt - positional) / OutputScale;
// Give more value to positional evaluation when adjusted flag is set
if (adjusted)
return static_cast<Value>(((1024 - delta) * psqt + (1024 + delta) * positional)
/ (1024 * OutputScale));
else
return static_cast<Value>((psqt + positional) / OutputScale);
}
return static_cast<Value>((psqt + positional) / OutputScale);
}
struct NnueEvalTrace {
template Value evaluate<Big>(const Position& pos, bool adjusted, int* complexity);
template Value evaluate<Small>(const Position& pos, bool adjusted, int* complexity);
struct NnueEvalTrace {
static_assert(LayerStacks == PSQTBuckets);
Value psqt[LayerStacks];
Value positional[LayerStacks];
Value psqt[LayerStacks];
Value positional[LayerStacks];
std::size_t correctBucket;
};
};
static NnueEvalTrace trace_evaluate(const Position& pos) {
static NnueEvalTrace trace_evaluate(const Position& pos) {
// We manually align the arrays on the stack because with gcc < 9.3
// overaligning stack variables with alignas() doesn't work correctly.
constexpr uint64_t alignment = CacheLineSize;
#if defined(ALIGNAS_ON_STACK_VARIABLES_BROKEN)
TransformedFeatureType transformedFeaturesUnaligned[
FeatureTransformer::BufferSize + alignment / sizeof(TransformedFeatureType)];
char bufferUnaligned[Network::BufferSize + alignment];
TransformedFeatureType transformedFeaturesUnaligned
[FeatureTransformer<TransformedFeatureDimensionsBig, nullptr>::BufferSize
+ alignment / sizeof(TransformedFeatureType)];
auto* transformedFeatures = align_ptr_up<alignment>(&transformedFeaturesUnaligned[0]);
auto* buffer = align_ptr_up<alignment>(&bufferUnaligned[0]);
#else
alignas(alignment)
TransformedFeatureType transformedFeatures[FeatureTransformer::BufferSize];
alignas(alignment) char buffer[Network::BufferSize];
alignas(alignment) TransformedFeatureType
transformedFeatures[FeatureTransformer<TransformedFeatureDimensionsBig, nullptr>::BufferSize];
#endif
ASSERT_ALIGNED(transformedFeatures, alignment);
ASSERT_ALIGNED(buffer, alignment);
NnueEvalTrace t{};
t.correctBucket = (pos.count<ALL_PIECES>() - 1) / 4;
for (std::size_t bucket = 0; bucket < LayerStacks; ++bucket) {
const auto psqt = featureTransformer->transform(pos, transformedFeatures, bucket);
const auto output = network[bucket]->propagate(transformedFeatures, buffer);
for (IndexType bucket = 0; bucket < LayerStacks; ++bucket)
{
const auto materialist = featureTransformerBig->transform(pos, transformedFeatures, bucket);
const auto positional = networkBig[bucket]->propagate(transformedFeatures);
int materialist = psqt;
int positional = output[0];
t.psqt[bucket] = static_cast<Value>( materialist / OutputScale );
t.positional[bucket] = static_cast<Value>( positional / OutputScale );
t.psqt[bucket] = static_cast<Value>(materialist / OutputScale);
t.positional[bucket] = static_cast<Value>(positional / OutputScale);
}
return t;
}
}
static const std::string PieceToChar(" PNBRQK pnbrqk");
constexpr std::string_view PieceToChar(" PNBRQK pnbrqk");
// format_cp_compact() converts a Value into (centi)pawns and writes it in a buffer.
// The buffer must have capacity for at least 5 chars.
static void format_cp_compact(Value v, char* buffer) {
// Converts a Value into (centi)pawns and writes it in a buffer.
// The buffer must have capacity for at least 5 chars.
static void format_cp_compact(Value v, char* buffer) {
buffer[0] = (v < 0 ? '-' : v > 0 ? '+' : ' ');
int cp = std::abs(100 * v / PawnValueEg);
int cp = std::abs(UCI::to_cp(v));
if (cp >= 10000)
{
buffer[1] = '0' + cp / 10000; cp %= 10000;
buffer[2] = '0' + cp / 1000; cp %= 1000;
buffer[3] = '0' + cp / 100; cp %= 100;
buffer[1] = '0' + cp / 10000;
cp %= 10000;
buffer[2] = '0' + cp / 1000;
cp %= 1000;
buffer[3] = '0' + cp / 100;
buffer[4] = ' ';
}
else if (cp >= 1000)
{
buffer[1] = '0' + cp / 1000; cp %= 1000;
buffer[2] = '0' + cp / 100; cp %= 100;
buffer[1] = '0' + cp / 1000;
cp %= 1000;
buffer[2] = '0' + cp / 100;
cp %= 100;
buffer[3] = '.';
buffer[4] = '0' + cp / 10;
}
else
{
buffer[1] = '0' + cp / 100; cp %= 100;
buffer[1] = '0' + cp / 100;
cp %= 100;
buffer[2] = '.';
buffer[3] = '0' + cp / 10; cp %= 10;
buffer[3] = '0' + cp / 10;
cp %= 10;
buffer[4] = '0' + cp / 1;
}
}
}
// format_cp_aligned_dot() converts a Value into (centi)pawns and writes it in a buffer,
// always keeping two decimals. The buffer must have capacity for at least 7 chars.
static void format_cp_aligned_dot(Value v, char* buffer) {
// Converts a Value into pawns, always keeping two decimals
static void format_cp_aligned_dot(Value v, std::stringstream& stream) {
buffer[0] = (v < 0 ? '-' : v > 0 ? '+' : ' ');
const double pawns = std::abs(0.01 * UCI::to_cp(v));
double cp = 1.0 * std::abs(int(v)) / PawnValueEg;
sprintf(&buffer[1], "%6.2f", cp);
}
stream << (v < 0 ? '-'
: v > 0 ? '+'
: ' ')
<< std::setiosflags(std::ios::fixed) << std::setw(6) << std::setprecision(2) << pawns;
}
// trace() returns a string with the value of each piece on a board,
// and a table for (PSQT, Layers) values bucket by bucket.
std::string trace(Position& pos) {
// Returns a string with the value of each piece on a board,
// and a table for (PSQT, Layers) values bucket by bucket.
std::string trace(Position& pos) {
std::stringstream ss;
char board[3*8+1][8*8+2];
char board[3 * 8 + 1][8 * 8 + 2];
std::memset(board, ' ', sizeof(board));
for (int row = 0; row < 3*8+1; ++row)
board[row][8*8+1] = '\0';
for (int row = 0; row < 3 * 8 + 1; ++row)
board[row][8 * 8 + 1] = '\0';
// A lambda to output one box of the board
auto writeSquare = [&board](File file, Rank rank, Piece pc, Value value) {
const int x = ((int)file) * 8;
const int y = (7 - (int)rank) * 3;
for (int i = 1; i < 8; ++i)
board[y][x+i] = board[y+3][x+i] = '-';
for (int i = 1; i < 3; ++i)
board[y+i][x] = board[y+i][x+8] = '|';
board[y][x] = board[y][x+8] = board[y+3][x+8] = board[y+3][x] = '+';
if (pc != NO_PIECE)
board[y+1][x+4] = PieceToChar[pc];
if (value != VALUE_NONE)
format_cp_compact(value, &board[y+2][x+2]);
const int x = int(file) * 8;
const int y = (7 - int(rank)) * 3;
for (int i = 1; i < 8; ++i)
board[y][x + i] = board[y + 3][x + i] = '-';
for (int i = 1; i < 3; ++i)
board[y + i][x] = board[y + i][x + 8] = '|';
board[y][x] = board[y][x + 8] = board[y + 3][x + 8] = board[y + 3][x] = '+';
if (pc != NO_PIECE)
board[y + 1][x + 4] = PieceToChar[pc];
if (value != VALUE_NONE)
format_cp_compact(value, &board[y + 2][x + 2]);
};
// We estimate the value of each piece by doing a differential evaluation from
// the current base eval, simulating the removal of the piece from its square.
Value base = evaluate(pos);
base = pos.side_to_move() == WHITE ? base : -base;
Value base = evaluate<NNUE::Big>(pos);
base = pos.side_to_move() == WHITE ? base : -base;
for (File f = FILE_A; f <= FILE_H; ++f)
for (Rank r = RANK_1; r <= RANK_8; ++r)
{
Square sq = make_square(f, r);
Piece pc = pos.piece_on(sq);
Value v = VALUE_NONE;
if (pc != NO_PIECE && type_of(pc) != KING)
for (Rank r = RANK_1; r <= RANK_8; ++r)
{
auto st = pos.state();
Square sq = make_square(f, r);
Piece pc = pos.piece_on(sq);
Value v = VALUE_NONE;
pos.remove_piece(sq);
st->accumulator.computed[WHITE] = false;
st->accumulator.computed[BLACK] = false;
if (pc != NO_PIECE && type_of(pc) != KING)
{
auto st = pos.state();
Value eval = evaluate(pos);
eval = pos.side_to_move() == WHITE ? eval : -eval;
v = base - eval;
pos.remove_piece(sq);
st->accumulatorBig.computed[WHITE] = false;
st->accumulatorBig.computed[BLACK] = false;
pos.put_piece(pc, sq);
st->accumulator.computed[WHITE] = false;
st->accumulator.computed[BLACK] = false;
Value eval = evaluate<NNUE::Big>(pos);
eval = pos.side_to_move() == WHITE ? eval : -eval;
v = base - eval;
pos.put_piece(pc, sq);
st->accumulatorBig.computed[WHITE] = false;
st->accumulatorBig.computed[BLACK] = false;
}
writeSquare(f, r, pc, v);
}
writeSquare(f, r, pc, v);
}
ss << " NNUE derived piece values:\n";
for (int row = 0; row < 3*8+1; ++row)
for (int row = 0; row < 3 * 8 + 1; ++row)
ss << board[row] << '\n';
ss << '\n';
@@ -341,48 +401,53 @@ namespace Stockfish::Eval::NNUE {
for (std::size_t bucket = 0; bucket < LayerStacks; ++bucket)
{
char buffer[3][8];
std::memset(buffer, '\0', sizeof(buffer));
format_cp_aligned_dot(t.psqt[bucket], buffer[0]);
format_cp_aligned_dot(t.positional[bucket], buffer[1]);
format_cp_aligned_dot(t.psqt[bucket] + t.positional[bucket], buffer[2]);
ss << "| " << bucket << " "
<< " | " << buffer[0] << " "
<< " | " << buffer[1] << " "
<< " | " << buffer[2] << " "
<< " |";
if (bucket == t.correctBucket)
ss << " <-- this bucket is used";
ss << '\n';
ss << "| " << bucket << " ";
ss << " | ";
format_cp_aligned_dot(t.psqt[bucket], ss);
ss << " "
<< " | ";
format_cp_aligned_dot(t.positional[bucket], ss);
ss << " "
<< " | ";
format_cp_aligned_dot(t.psqt[bucket] + t.positional[bucket], ss);
ss << " "
<< " |";
if (bucket == t.correctBucket)
ss << " <-- this bucket is used";
ss << '\n';
}
ss << "+------------+------------+------------+------------+\n";
return ss.str();
}
}
// Load eval, from a file stream or a memory stream
bool load_eval(std::string name, std::istream& stream) {
// Load eval, from a file stream or a memory stream
std::optional<std::string> load_eval(std::istream& stream, NetSize netSize) {
initialize();
fileName = name;
return read_parameters(stream);
}
initialize(netSize);
std::string netDescription;
return read_parameters(stream, netSize, netDescription) ? std::make_optional(netDescription)
: std::nullopt;
}
// Save eval, to a file stream or a memory stream
bool save_eval(std::ostream& stream) {
// Save eval, to a file stream or a memory stream
bool save_eval(std::ostream& stream,
NetSize netSize,
const std::string& name,
const std::string& netDescription) {
if (fileName.empty())
return false;
if (name.empty() || name == "None")
return false;
return write_parameters(stream);
}
return write_parameters(stream, netSize, netDescription);
}
/// Save eval, to a file given by its name
bool save_eval(const std::optional<std::string>& filename) {
// Save eval, to a file given by its name
bool save_eval(const std::optional<std::string>& filename,
NetSize netSize,
const std::unordered_map<Eval::NNUE::NetSize, Eval::EvalFile>& evalFiles) {
std::string actualFilename;
std::string msg;
@@ -391,25 +456,27 @@ namespace Stockfish::Eval::NNUE {
actualFilename = filename.value();
else
{
if (currentEvalFileName != EvalFileDefaultName)
if (evalFiles.at(netSize).current
!= (netSize == Small ? EvalFileDefaultNameSmall : EvalFileDefaultNameBig))
{
msg = "Failed to export a net. A non-embedded net can only be saved if the filename is specified";
msg = "Failed to export a net. "
"A non-embedded net can only be saved if the filename is specified";
sync_cout << msg << sync_endl;
return false;
sync_cout << msg << sync_endl;
return false;
}
actualFilename = EvalFileDefaultName;
actualFilename = (netSize == Small ? EvalFileDefaultNameSmall : EvalFileDefaultNameBig);
}
std::ofstream stream(actualFilename, std::ios_base::binary);
bool saved = save_eval(stream);
bool saved = save_eval(stream, netSize, evalFiles.at(netSize).current,
evalFiles.at(netSize).netDescription);
msg = saved ? "Network saved successfully to " + actualFilename
: "Failed to export a net";
msg = saved ? "Network saved successfully to " + actualFilename : "Failed to export a net";
sync_cout << msg << sync_endl;
return saved;
}
}
} // namespace Stockfish::Eval::NNUE
} // namespace Stockfish::Eval::NNUE
+55 -21
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -21,39 +21,73 @@
#ifndef NNUE_EVALUATE_NNUE_H_INCLUDED
#define NNUE_EVALUATE_NNUE_H_INCLUDED
#include <cstdint>
#include <iosfwd>
#include <memory>
#include <optional>
#include <string>
#include <unordered_map>
#include "../misc.h"
#include "../types.h"
#include "nnue_architecture.h"
#include "nnue_feature_transformer.h"
#include <memory>
namespace Stockfish {
class Position;
namespace Eval {
struct EvalFile;
}
}
namespace Stockfish::Eval::NNUE {
// Hash value of evaluation function structure
constexpr std::uint32_t HashValue =
FeatureTransformer::get_hash_value() ^ Network::get_hash_value();
// Hash value of evaluation function structure
constexpr std::uint32_t HashValue[2] = {
FeatureTransformer<TransformedFeatureDimensionsBig, nullptr>::get_hash_value()
^ Network<TransformedFeatureDimensionsBig, L2Big, L3Big>::get_hash_value(),
FeatureTransformer<TransformedFeatureDimensionsSmall, nullptr>::get_hash_value()
^ Network<TransformedFeatureDimensionsSmall, L2Small, L3Small>::get_hash_value()};
// Deleter for automating release of memory area
template <typename T>
struct AlignedDeleter {
// Deleter for automating release of memory area
template<typename T>
struct AlignedDeleter {
void operator()(T* ptr) const {
ptr->~T();
std_aligned_free(ptr);
ptr->~T();
std_aligned_free(ptr);
}
};
};
template <typename T>
struct LargePageDeleter {
template<typename T>
struct LargePageDeleter {
void operator()(T* ptr) const {
ptr->~T();
aligned_large_pages_free(ptr);
ptr->~T();
aligned_large_pages_free(ptr);
}
};
};
template <typename T>
using AlignedPtr = std::unique_ptr<T, AlignedDeleter<T>>;
template<typename T>
using AlignedPtr = std::unique_ptr<T, AlignedDeleter<T>>;
template <typename T>
using LargePagePtr = std::unique_ptr<T, LargePageDeleter<T>>;
template<typename T>
using LargePagePtr = std::unique_ptr<T, LargePageDeleter<T>>;
std::string trace(Position& pos);
template<NetSize Net_Size>
Value evaluate(const Position& pos, bool adjusted = false, int* complexity = nullptr);
void hint_common_parent_position(const Position& pos);
std::optional<std::string> load_eval(std::istream& stream, NetSize netSize);
bool save_eval(std::ostream& stream,
NetSize netSize,
const std::string& name,
const std::string& netDescription);
bool save_eval(const std::optional<std::string>& filename,
NetSize netSize,
const std::unordered_map<Eval::NNUE::NetSize, Eval::EvalFile>&);
} // namespace Stockfish::Eval::NNUE
#endif // #ifndef NNUE_EVALUATE_NNUE_H_INCLUDED
#endif // #ifndef NNUE_EVALUATE_NNUE_H_INCLUDED
+48 -45
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -20,64 +20,67 @@
#include "half_ka_v2_hm.h"
#include "../../bitboard.h"
#include "../../position.h"
#include "../../types.h"
#include "../nnue_common.h"
namespace Stockfish::Eval::NNUE::Features {
// Orient a square according to perspective (rotates by 180 for black)
inline Square HalfKAv2_hm::orient(Color perspective, Square s, Square ksq) {
return Square(int(s) ^ (bool(perspective) * SQ_A8) ^ ((file_of(ksq) < FILE_E) * SQ_H1));
}
// Index of a feature for a given king position and another piece on some square
template<Color Perspective>
inline IndexType HalfKAv2_hm::make_index(Square s, Piece pc, Square ksq) {
return IndexType((int(s) ^ OrientTBL[Perspective][ksq]) + PieceSquareIndex[Perspective][pc]
+ KingBuckets[Perspective][ksq]);
}
// Index of a feature for a given king position and another piece on some square
inline IndexType HalfKAv2_hm::make_index(Color perspective, Square s, Piece pc, Square ksq) {
Square o_ksq = orient(perspective, ksq, ksq);
return IndexType(orient(perspective, s, ksq) + PieceSquareIndex[perspective][pc] + PS_NB * KingBuckets[o_ksq]);
}
// Get a list of indices for active features
void HalfKAv2_hm::append_active_indices(
const Position& pos,
Color perspective,
IndexList& active
) {
Square ksq = pos.square<KING>(perspective);
Bitboard bb = pos.pieces();
// Get a list of indices for active features
template<Color Perspective>
void HalfKAv2_hm::append_active_indices(const Position& pos, IndexList& active) {
Square ksq = pos.square<KING>(Perspective);
Bitboard bb = pos.pieces();
while (bb)
{
Square s = pop_lsb(bb);
active.push_back(make_index(perspective, s, pos.piece_on(s), ksq));
Square s = pop_lsb(bb);
active.push_back(make_index<Perspective>(s, pos.piece_on(s), ksq));
}
}
}
// Explicit template instantiations
template void HalfKAv2_hm::append_active_indices<WHITE>(const Position& pos, IndexList& active);
template void HalfKAv2_hm::append_active_indices<BLACK>(const Position& pos, IndexList& active);
// append_changed_indices() : get a list of indices for recently changed features
void HalfKAv2_hm::append_changed_indices(
Square ksq,
const DirtyPiece& dp,
Color perspective,
IndexList& removed,
IndexList& added
) {
for (int i = 0; i < dp.dirty_num; ++i) {
if (dp.from[i] != SQ_NONE)
removed.push_back(make_index(perspective, dp.from[i], dp.piece[i], ksq));
if (dp.to[i] != SQ_NONE)
added.push_back(make_index(perspective, dp.to[i], dp.piece[i], ksq));
// Get a list of indices for recently changed features
template<Color Perspective>
void HalfKAv2_hm::append_changed_indices(Square ksq,
const DirtyPiece& dp,
IndexList& removed,
IndexList& added) {
for (int i = 0; i < dp.dirty_num; ++i)
{
if (dp.from[i] != SQ_NONE)
removed.push_back(make_index<Perspective>(dp.from[i], dp.piece[i], ksq));
if (dp.to[i] != SQ_NONE)
added.push_back(make_index<Perspective>(dp.to[i], dp.piece[i], ksq));
}
}
}
int HalfKAv2_hm::update_cost(const StateInfo* st) {
return st->dirtyPiece.dirty_num;
}
// Explicit template instantiations
template void HalfKAv2_hm::append_changed_indices<WHITE>(Square ksq,
const DirtyPiece& dp,
IndexList& removed,
IndexList& added);
template void HalfKAv2_hm::append_changed_indices<BLACK>(Square ksq,
const DirtyPiece& dp,
IndexList& removed,
IndexList& added);
int HalfKAv2_hm::refresh_cost(const Position& pos) {
return pos.count<ALL_PIECES>();
}
int HalfKAv2_hm::update_cost(const StateInfo* st) { return st->dirtyPiece.dirty_num; }
bool HalfKAv2_hm::requires_refresh(const StateInfo* st, Color perspective) {
int HalfKAv2_hm::refresh_cost(const Position& pos) { return pos.count<ALL_PIECES>(); }
bool HalfKAv2_hm::requires_refresh(const StateInfo* st, Color perspective) {
return st->dirtyPiece.piece[0] == make_piece(perspective, KING);
}
}
} // namespace Stockfish::Eval::NNUE::Features
+85 -59
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -21,52 +21,51 @@
#ifndef NNUE_FEATURES_HALF_KA_V2_HM_H_INCLUDED
#define NNUE_FEATURES_HALF_KA_V2_HM_H_INCLUDED
#include <cstdint>
#include "../../misc.h"
#include "../../types.h"
#include "../nnue_common.h"
#include "../../evaluate.h"
#include "../../misc.h"
namespace Stockfish {
struct StateInfo;
struct StateInfo;
class Position;
}
namespace Stockfish::Eval::NNUE::Features {
// Feature HalfKAv2_hm: Combination of the position of own king
// and the position of pieces. Position mirrored such that king always on e..h files.
class HalfKAv2_hm {
// Feature HalfKAv2_hm: Combination of the position of own king and the
// position of pieces. Position mirrored such that king is always on e..h files.
class HalfKAv2_hm {
// unique number for each piece type on each square
// Unique number for each piece type on each square
enum {
PS_NONE = 0,
PS_W_PAWN = 0,
PS_B_PAWN = 1 * SQUARE_NB,
PS_W_KNIGHT = 2 * SQUARE_NB,
PS_B_KNIGHT = 3 * SQUARE_NB,
PS_W_BISHOP = 4 * SQUARE_NB,
PS_B_BISHOP = 5 * SQUARE_NB,
PS_W_ROOK = 6 * SQUARE_NB,
PS_B_ROOK = 7 * SQUARE_NB,
PS_W_QUEEN = 8 * SQUARE_NB,
PS_B_QUEEN = 9 * SQUARE_NB,
PS_KING = 10 * SQUARE_NB,
PS_NB = 11 * SQUARE_NB
PS_NONE = 0,
PS_W_PAWN = 0,
PS_B_PAWN = 1 * SQUARE_NB,
PS_W_KNIGHT = 2 * SQUARE_NB,
PS_B_KNIGHT = 3 * SQUARE_NB,
PS_W_BISHOP = 4 * SQUARE_NB,
PS_B_BISHOP = 5 * SQUARE_NB,
PS_W_ROOK = 6 * SQUARE_NB,
PS_B_ROOK = 7 * SQUARE_NB,
PS_W_QUEEN = 8 * SQUARE_NB,
PS_B_QUEEN = 9 * SQUARE_NB,
PS_KING = 10 * SQUARE_NB,
PS_NB = 11 * SQUARE_NB
};
static constexpr IndexType PieceSquareIndex[COLOR_NB][PIECE_NB] = {
// convention: W - us, B - them
// viewed from other side, W and B are reversed
{ PS_NONE, PS_W_PAWN, PS_W_KNIGHT, PS_W_BISHOP, PS_W_ROOK, PS_W_QUEEN, PS_KING, PS_NONE,
PS_NONE, PS_B_PAWN, PS_B_KNIGHT, PS_B_BISHOP, PS_B_ROOK, PS_B_QUEEN, PS_KING, PS_NONE },
{ PS_NONE, PS_B_PAWN, PS_B_KNIGHT, PS_B_BISHOP, PS_B_ROOK, PS_B_QUEEN, PS_KING, PS_NONE,
PS_NONE, PS_W_PAWN, PS_W_KNIGHT, PS_W_BISHOP, PS_W_ROOK, PS_W_QUEEN, PS_KING, PS_NONE }
};
// Orient a square according to perspective (rotates by 180 for black)
static Square orient(Color perspective, Square s, Square ksq);
// Convention: W - us, B - them
// Viewed from other side, W and B are reversed
{PS_NONE, PS_W_PAWN, PS_W_KNIGHT, PS_W_BISHOP, PS_W_ROOK, PS_W_QUEEN, PS_KING, PS_NONE,
PS_NONE, PS_B_PAWN, PS_B_KNIGHT, PS_B_BISHOP, PS_B_ROOK, PS_B_QUEEN, PS_KING, PS_NONE},
{PS_NONE, PS_B_PAWN, PS_B_KNIGHT, PS_B_BISHOP, PS_B_ROOK, PS_B_QUEEN, PS_KING, PS_NONE,
PS_NONE, PS_W_PAWN, PS_W_KNIGHT, PS_W_BISHOP, PS_W_ROOK, PS_W_QUEEN, PS_KING, PS_NONE}};
// Index of a feature for a given king position and another piece on some square
static IndexType make_index(Color perspective, Square s, Piece pc, Square ksq);
template<Color Perspective>
static IndexType make_index(Square s, Piece pc, Square ksq);
public:
// Feature name
@@ -77,48 +76,75 @@ namespace Stockfish::Eval::NNUE::Features {
// Number of feature dimensions
static constexpr IndexType Dimensions =
static_cast<IndexType>(SQUARE_NB) * static_cast<IndexType>(PS_NB) / 2;
static_cast<IndexType>(SQUARE_NB) * static_cast<IndexType>(PS_NB) / 2;
static constexpr int KingBuckets[64] = {
-1, -1, -1, -1, 31, 30, 29, 28,
-1, -1, -1, -1, 27, 26, 25, 24,
-1, -1, -1, -1, 23, 22, 21, 20,
-1, -1, -1, -1, 19, 18, 17, 16,
-1, -1, -1, -1, 15, 14, 13, 12,
-1, -1, -1, -1, 11, 10, 9, 8,
-1, -1, -1, -1, 7, 6, 5, 4,
-1, -1, -1, -1, 3, 2, 1, 0
#define B(v) (v * PS_NB)
// clang-format off
static constexpr int KingBuckets[COLOR_NB][SQUARE_NB] = {
{ B(28), B(29), B(30), B(31), B(31), B(30), B(29), B(28),
B(24), B(25), B(26), B(27), B(27), B(26), B(25), B(24),
B(20), B(21), B(22), B(23), B(23), B(22), B(21), B(20),
B(16), B(17), B(18), B(19), B(19), B(18), B(17), B(16),
B(12), B(13), B(14), B(15), B(15), B(14), B(13), B(12),
B( 8), B( 9), B(10), B(11), B(11), B(10), B( 9), B( 8),
B( 4), B( 5), B( 6), B( 7), B( 7), B( 6), B( 5), B( 4),
B( 0), B( 1), B( 2), B( 3), B( 3), B( 2), B( 1), B( 0) },
{ B( 0), B( 1), B( 2), B( 3), B( 3), B( 2), B( 1), B( 0),
B( 4), B( 5), B( 6), B( 7), B( 7), B( 6), B( 5), B( 4),
B( 8), B( 9), B(10), B(11), B(11), B(10), B( 9), B( 8),
B(12), B(13), B(14), B(15), B(15), B(14), B(13), B(12),
B(16), B(17), B(18), B(19), B(19), B(18), B(17), B(16),
B(20), B(21), B(22), B(23), B(23), B(22), B(21), B(20),
B(24), B(25), B(26), B(27), B(27), B(26), B(25), B(24),
B(28), B(29), B(30), B(31), B(31), B(30), B(29), B(28) }
};
// clang-format on
#undef B
// clang-format off
// Orient a square according to perspective (rotates by 180 for black)
static constexpr int OrientTBL[COLOR_NB][SQUARE_NB] = {
{ SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1,
SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1,
SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1,
SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1,
SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1,
SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1,
SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1,
SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1 },
{ SQ_H8, SQ_H8, SQ_H8, SQ_H8, SQ_A8, SQ_A8, SQ_A8, SQ_A8,
SQ_H8, SQ_H8, SQ_H8, SQ_H8, SQ_A8, SQ_A8, SQ_A8, SQ_A8,
SQ_H8, SQ_H8, SQ_H8, SQ_H8, SQ_A8, SQ_A8, SQ_A8, SQ_A8,
SQ_H8, SQ_H8, SQ_H8, SQ_H8, SQ_A8, SQ_A8, SQ_A8, SQ_A8,
SQ_H8, SQ_H8, SQ_H8, SQ_H8, SQ_A8, SQ_A8, SQ_A8, SQ_A8,
SQ_H8, SQ_H8, SQ_H8, SQ_H8, SQ_A8, SQ_A8, SQ_A8, SQ_A8,
SQ_H8, SQ_H8, SQ_H8, SQ_H8, SQ_A8, SQ_A8, SQ_A8, SQ_A8,
SQ_H8, SQ_H8, SQ_H8, SQ_H8, SQ_A8, SQ_A8, SQ_A8, SQ_A8 }
};
// clang-format on
// Maximum number of simultaneously active features.
static constexpr IndexType MaxActiveDimensions = 32;
using IndexList = ValueList<IndexType, MaxActiveDimensions>;
using IndexList = ValueList<IndexType, MaxActiveDimensions>;
// Get a list of indices for active features
static void append_active_indices(
const Position& pos,
Color perspective,
IndexList& active);
template<Color Perspective>
static void append_active_indices(const Position& pos, IndexList& active);
// Get a list of indices for recently changed features
static void append_changed_indices(
Square ksq,
const DirtyPiece& dp,
Color perspective,
IndexList& removed,
IndexList& added
);
template<Color Perspective>
static void
append_changed_indices(Square ksq, const DirtyPiece& dp, IndexList& removed, IndexList& added);
// Returns the cost of updating one perspective, the most costly one.
// Assumes no refresh needed.
static int update_cost(const StateInfo* st);
static int refresh_cost(const Position& pos);
// Returns whether the change stored in this StateInfo means that
// a full accumulator refresh is required.
// Returns whether the change stored in this StateInfo means
// that a full accumulator refresh is required.
static bool requires_refresh(const StateInfo* st, Color perspective);
};
};
} // namespace Stockfish::Eval::NNUE::Features
#endif // #ifndef NNUE_FEATURES_HALF_KA_V2_HM_H_INCLUDED
#endif // #ifndef NNUE_FEATURES_HALF_KA_V2_HM_H_INCLUDED
+208 -454
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -21,34 +21,18 @@
#ifndef NNUE_LAYERS_AFFINE_TRANSFORM_H_INCLUDED
#define NNUE_LAYERS_AFFINE_TRANSFORM_H_INCLUDED
#include <cstdint>
#include <iostream>
#include <algorithm>
#include <type_traits>
#include "../nnue_common.h"
#include "../../simd.h"
#include "simd.h"
/*
This file contains the definition for a fully connected layer (aka affine transform).
Two approaches are employed, depending on the sizes of the transform.
Approach 1:
- used when the PaddedInputDimensions >= 128
- uses AVX512 if possible
- processes inputs in batches of 2*InputSimdWidth
- so in batches of 128 for AVX512
- the weight blocks of size InputSimdWidth are transposed such that
access is sequential
- N columns of the weight matrix are processed a time, where N
depends on the architecture (the amount of registers)
- accumulate + hadd is used
Approach 2:
- used when the PaddedInputDimensions < 128
- does not use AVX512
- expected use-case is for when PaddedInputDimensions == 32 and InputDimensions <= 32.
- that's why AVX512 is hard to implement
- expected use-case is small layers
- not optimized as well as the approach 1
- inputs are processed in chunks of 4, weights are respectively transposed
- accumulation happens directly to int32s
*/
@@ -56,499 +40,269 @@
namespace Stockfish::Eval::NNUE::Layers {
// Fallback implementation for older/other architectures.
// Identical for both approaches. Requires the input to be padded to at least 16 values.
// Requires the input to be padded to at least 16 values.
#if !defined(USE_SSSE3)
template <IndexType InputDimensions, IndexType PaddedInputDimensions, IndexType OutputDimensions>
static void affine_transform_non_ssse3(std::int32_t* output, const std::int8_t* weights, const std::int32_t* biases, const std::uint8_t* input)
{
# if defined(USE_SSE2)
template<IndexType InputDimensions, IndexType PaddedInputDimensions, IndexType OutputDimensions>
static void affine_transform_non_ssse3(std::int32_t* output,
const std::int8_t* weights,
const std::int32_t* biases,
const std::uint8_t* input) {
#if defined(USE_SSE2) || defined(USE_NEON_DOTPROD) || defined(USE_NEON)
#if defined(USE_SSE2)
// At least a multiple of 16, with SSE2.
static_assert(PaddedInputDimensions % 16 == 0);
constexpr IndexType NumChunks = PaddedInputDimensions / 16;
const __m128i Zeros = _mm_setzero_si128();
const auto inputVector = reinterpret_cast<const __m128i*>(input);
constexpr IndexType NumChunks = ceil_to_multiple<IndexType>(InputDimensions, 16) / 16;
const __m128i Zeros = _mm_setzero_si128();
const auto inputVector = reinterpret_cast<const __m128i*>(input);
# elif defined(USE_MMX)
static_assert(InputDimensions % 8 == 0);
constexpr IndexType NumChunks = InputDimensions / 8;
const __m64 Zeros = _mm_setzero_si64();
const auto inputVector = reinterpret_cast<const __m64*>(input);
#elif defined(USE_NEON_DOTPROD)
constexpr IndexType NumChunks = ceil_to_multiple<IndexType>(InputDimensions, 16) / 16;
const auto inputVector = reinterpret_cast<const int8x16_t*>(input);
# elif defined(USE_NEON)
static_assert(PaddedInputDimensions % 16 == 0);
constexpr IndexType NumChunks = PaddedInputDimensions / 16;
const auto inputVector = reinterpret_cast<const int8x8_t*>(input);
# endif
#elif defined(USE_NEON)
constexpr IndexType NumChunks = ceil_to_multiple<IndexType>(InputDimensions, 16) / 16;
const auto inputVector = reinterpret_cast<const int8x8_t*>(input);
#endif
for (IndexType i = 0; i < OutputDimensions; ++i) {
const IndexType offset = i * PaddedInputDimensions;
for (IndexType i = 0; i < OutputDimensions; ++i)
{
const IndexType offset = i * PaddedInputDimensions;
# if defined(USE_SSE2)
__m128i sumLo = _mm_cvtsi32_si128(biases[i]);
__m128i sumHi = Zeros;
const auto row = reinterpret_cast<const __m128i*>(&weights[offset]);
for (IndexType j = 0; j < NumChunks; ++j) {
__m128i row_j = _mm_load_si128(&row[j]);
__m128i input_j = _mm_load_si128(&inputVector[j]);
__m128i extendedRowLo = _mm_srai_epi16(_mm_unpacklo_epi8(row_j, row_j), 8);
__m128i extendedRowHi = _mm_srai_epi16(_mm_unpackhi_epi8(row_j, row_j), 8);
__m128i extendedInputLo = _mm_unpacklo_epi8(input_j, Zeros);
__m128i extendedInputHi = _mm_unpackhi_epi8(input_j, Zeros);
__m128i productLo = _mm_madd_epi16(extendedRowLo, extendedInputLo);
__m128i productHi = _mm_madd_epi16(extendedRowHi, extendedInputHi);
sumLo = _mm_add_epi32(sumLo, productLo);
sumHi = _mm_add_epi32(sumHi, productHi);
}
__m128i sum = _mm_add_epi32(sumLo, sumHi);
__m128i sumHigh_64 = _mm_shuffle_epi32(sum, _MM_SHUFFLE(1, 0, 3, 2));
sum = _mm_add_epi32(sum, sumHigh_64);
__m128i sum_second_32 = _mm_shufflelo_epi16(sum, _MM_SHUFFLE(1, 0, 3, 2));
sum = _mm_add_epi32(sum, sum_second_32);
output[i] = _mm_cvtsi128_si32(sum);
#if defined(USE_SSE2)
__m128i sumLo = _mm_cvtsi32_si128(biases[i]);
__m128i sumHi = Zeros;
const auto row = reinterpret_cast<const __m128i*>(&weights[offset]);
for (IndexType j = 0; j < NumChunks; ++j)
{
__m128i row_j = _mm_load_si128(&row[j]);
__m128i input_j = _mm_load_si128(&inputVector[j]);
__m128i extendedRowLo = _mm_srai_epi16(_mm_unpacklo_epi8(row_j, row_j), 8);
__m128i extendedRowHi = _mm_srai_epi16(_mm_unpackhi_epi8(row_j, row_j), 8);
__m128i extendedInputLo = _mm_unpacklo_epi8(input_j, Zeros);
__m128i extendedInputHi = _mm_unpackhi_epi8(input_j, Zeros);
__m128i productLo = _mm_madd_epi16(extendedRowLo, extendedInputLo);
__m128i productHi = _mm_madd_epi16(extendedRowHi, extendedInputHi);
sumLo = _mm_add_epi32(sumLo, productLo);
sumHi = _mm_add_epi32(sumHi, productHi);
}
__m128i sum = _mm_add_epi32(sumLo, sumHi);
__m128i sumHigh_64 = _mm_shuffle_epi32(sum, _MM_SHUFFLE(1, 0, 3, 2));
sum = _mm_add_epi32(sum, sumHigh_64);
__m128i sum_second_32 = _mm_shufflelo_epi16(sum, _MM_SHUFFLE(1, 0, 3, 2));
sum = _mm_add_epi32(sum, sum_second_32);
output[i] = _mm_cvtsi128_si32(sum);
# elif defined(USE_MMX)
__m64 sumLo = _mm_cvtsi32_si64(biases[i]);
__m64 sumHi = Zeros;
const auto row = reinterpret_cast<const __m64*>(&weights[offset]);
for (IndexType j = 0; j < NumChunks; ++j) {
__m64 row_j = row[j];
__m64 input_j = inputVector[j];
__m64 extendedRowLo = _mm_srai_pi16(_mm_unpacklo_pi8(row_j, row_j), 8);
__m64 extendedRowHi = _mm_srai_pi16(_mm_unpackhi_pi8(row_j, row_j), 8);
__m64 extendedInputLo = _mm_unpacklo_pi8(input_j, Zeros);
__m64 extendedInputHi = _mm_unpackhi_pi8(input_j, Zeros);
__m64 productLo = _mm_madd_pi16(extendedRowLo, extendedInputLo);
__m64 productHi = _mm_madd_pi16(extendedRowHi, extendedInputHi);
sumLo = _mm_add_pi32(sumLo, productLo);
sumHi = _mm_add_pi32(sumHi, productHi);
}
__m64 sum = _mm_add_pi32(sumLo, sumHi);
sum = _mm_add_pi32(sum, _mm_unpackhi_pi32(sum, sum));
output[i] = _mm_cvtsi64_si32(sum);
#elif defined(USE_NEON_DOTPROD)
int32x4_t sum = {biases[i]};
const auto row = reinterpret_cast<const int8x16_t*>(&weights[offset]);
for (IndexType j = 0; j < NumChunks; ++j)
{
sum = vdotq_s32(sum, inputVector[j], row[j]);
}
output[i] = vaddvq_s32(sum);
# elif defined(USE_NEON)
int32x4_t sum = {biases[i]};
const auto row = reinterpret_cast<const int8x8_t*>(&weights[offset]);
for (IndexType j = 0; j < NumChunks; ++j) {
int16x8_t product = vmull_s8(inputVector[j * 2], row[j * 2]);
product = vmlal_s8(product, inputVector[j * 2 + 1], row[j * 2 + 1]);
sum = vpadalq_s16(sum, product);
}
output[i] = sum[0] + sum[1] + sum[2] + sum[3];
#elif defined(USE_NEON)
int32x4_t sum = {biases[i]};
const auto row = reinterpret_cast<const int8x8_t*>(&weights[offset]);
for (IndexType j = 0; j < NumChunks; ++j)
{
int16x8_t product = vmull_s8(inputVector[j * 2], row[j * 2]);
product = vmlal_s8(product, inputVector[j * 2 + 1], row[j * 2 + 1]);
sum = vpadalq_s16(sum, product);
}
output[i] = sum[0] + sum[1] + sum[2] + sum[3];
# else
std::int32_t sum = biases[i];
for (IndexType j = 0; j < InputDimensions; ++j) {
sum += weights[offset + j] * input[j];
}
output[i] = sum;
# endif
#endif
}
#else
std::memcpy(output, biases, sizeof(std::int32_t) * OutputDimensions);
# if defined(USE_MMX)
_mm_empty();
# endif
}
// Traverse weights in transpose order to take advantage of input sparsity
for (IndexType i = 0; i < InputDimensions; ++i)
if (input[i])
{
const std::int8_t* w = &weights[i];
const int in = input[i];
for (IndexType j = 0; j < OutputDimensions; ++j)
output[j] += w[j * PaddedInputDimensions] * in;
}
#endif
}
#endif
template <typename PreviousLayer, IndexType OutDims, typename Enabled = void>
class AffineTransform;
// A specialization for large inputs.
template <typename PreviousLayer, IndexType OutDims>
class AffineTransform<PreviousLayer, OutDims, std::enable_if_t<(PreviousLayer::OutputDimensions >= 2*64-1)>> {
template<IndexType InDims, IndexType OutDims>
class AffineTransform {
public:
// Input/output type
using InputType = typename PreviousLayer::OutputType;
using InputType = std::uint8_t;
using OutputType = std::int32_t;
static_assert(std::is_same<InputType, std::uint8_t>::value, "");
// Number of input/output dimensions
static constexpr IndexType InputDimensions = PreviousLayer::OutputDimensions;
static constexpr IndexType InputDimensions = InDims;
static constexpr IndexType OutputDimensions = OutDims;
static constexpr IndexType PaddedInputDimensions =
ceil_to_multiple<IndexType>(InputDimensions, MaxSimdWidth);
static constexpr IndexType PaddedOutputDimensions =
ceil_to_multiple<IndexType>(OutputDimensions, MaxSimdWidth);
static_assert(PaddedInputDimensions >= 128, "Something went wrong. This specialization should not have been chosen.");
#if defined (USE_AVX512)
static constexpr const IndexType InputSimdWidth = 64;
static constexpr const IndexType MaxNumOutputRegs = 16;
#elif defined (USE_AVX2)
static constexpr const IndexType InputSimdWidth = 32;
static constexpr const IndexType MaxNumOutputRegs = 8;
#elif defined (USE_SSSE3)
static constexpr const IndexType InputSimdWidth = 16;
static constexpr const IndexType MaxNumOutputRegs = 8;
#else
// The fallback implementation will not have permuted weights.
// We define these to avoid a lot of ifdefs later.
static constexpr const IndexType InputSimdWidth = 1;
static constexpr const IndexType MaxNumOutputRegs = 1;
#endif
// A big block is a region in the weight matrix of the size [PaddedInputDimensions, NumOutputRegs].
// A small block is a region of size [InputSimdWidth, 1]
static constexpr const IndexType NumOutputRegs = std::min(MaxNumOutputRegs, OutputDimensions);
static constexpr const IndexType SmallBlockSize = InputSimdWidth;
static constexpr const IndexType BigBlockSize = NumOutputRegs * PaddedInputDimensions;
static constexpr const IndexType NumSmallBlocksInBigBlock = BigBlockSize / SmallBlockSize;
static constexpr const IndexType NumSmallBlocksPerOutput = PaddedInputDimensions / SmallBlockSize;
static constexpr const IndexType NumBigBlocks = OutputDimensions / NumOutputRegs;
static_assert(OutputDimensions % NumOutputRegs == 0);
// Size of forward propagation buffer used in this layer
static constexpr std::size_t SelfBufferSize =
ceil_to_multiple(OutputDimensions * sizeof(OutputType), CacheLineSize);
// Size of the forward propagation buffer used from the input layer to this layer
static constexpr std::size_t BufferSize =
PreviousLayer::BufferSize + SelfBufferSize;
using OutputBuffer = OutputType[PaddedOutputDimensions];
// Hash value embedded in the evaluation file
static constexpr std::uint32_t get_hash_value() {
std::uint32_t hashValue = 0xCC03DAE4u;
hashValue += OutputDimensions;
hashValue ^= PreviousLayer::get_hash_value() >> 1;
hashValue ^= PreviousLayer::get_hash_value() << 31;
return hashValue;
static constexpr std::uint32_t get_hash_value(std::uint32_t prevHash) {
std::uint32_t hashValue = 0xCC03DAE4u;
hashValue += OutputDimensions;
hashValue ^= prevHash >> 1;
hashValue ^= prevHash << 31;
return hashValue;
}
/*
Transposes the small blocks within a block.
Effectively means that weights can be traversed sequentially during inference.
*/
static IndexType get_weight_index(IndexType i)
{
const IndexType smallBlock = (i / SmallBlockSize) % NumSmallBlocksInBigBlock;
const IndexType smallBlockCol = smallBlock / NumSmallBlocksPerOutput;
const IndexType smallBlockRow = smallBlock % NumSmallBlocksPerOutput;
const IndexType bigBlock = i / BigBlockSize;
const IndexType rest = i % SmallBlockSize;
const IndexType idx =
bigBlock * BigBlockSize
+ smallBlockRow * SmallBlockSize * NumOutputRegs
+ smallBlockCol * SmallBlockSize
+ rest;
return idx;
static constexpr IndexType get_weight_index_scrambled(IndexType i) {
return (i / 4) % (PaddedInputDimensions / 4) * OutputDimensions * 4
+ i / PaddedInputDimensions * 4 + i % 4;
}
// Read network parameters
bool read_parameters(std::istream& stream) {
if (!previousLayer.read_parameters(stream)) return false;
for (std::size_t i = 0; i < OutputDimensions; ++i)
biases[i] = read_little_endian<BiasType>(stream);
for (std::size_t i = 0; i < OutputDimensions * PaddedInputDimensions; ++i)
weights[get_weight_index(i)] = read_little_endian<WeightType>(stream);
return !stream.fail();
}
// Write network parameters
bool write_parameters(std::ostream& stream) const {
if (!previousLayer.write_parameters(stream)) return false;
for (std::size_t i = 0; i < OutputDimensions; ++i)
write_little_endian<BiasType>(stream, biases[i]);
for (std::size_t i = 0; i < OutputDimensions * PaddedInputDimensions; ++i)
write_little_endian<WeightType>(stream, weights[get_weight_index(i)]);
return !stream.fail();
}
// Forward propagation
const OutputType* propagate(
const TransformedFeatureType* transformedFeatures, char* buffer) const {
const auto input = previousLayer.propagate(
transformedFeatures, buffer + SelfBufferSize);
OutputType* output = reinterpret_cast<OutputType*>(buffer);
#if defined (USE_AVX512)
using vec_t = __m512i;
#define vec_setzero _mm512_setzero_si512
#define vec_set_32 _mm512_set1_epi32
#define vec_add_dpbusd_32 Simd::m512_add_dpbusd_epi32
#define vec_add_dpbusd_32x2 Simd::m512_add_dpbusd_epi32x2
#define vec_hadd Simd::m512_hadd
#define vec_haddx4 Simd::m512_haddx4
#elif defined (USE_AVX2)
using vec_t = __m256i;
#define vec_setzero _mm256_setzero_si256
#define vec_set_32 _mm256_set1_epi32
#define vec_add_dpbusd_32 Simd::m256_add_dpbusd_epi32
#define vec_add_dpbusd_32x2 Simd::m256_add_dpbusd_epi32x2
#define vec_hadd Simd::m256_hadd
#define vec_haddx4 Simd::m256_haddx4
#elif defined (USE_SSSE3)
using vec_t = __m128i;
#define vec_setzero _mm_setzero_si128
#define vec_set_32 _mm_set1_epi32
#define vec_add_dpbusd_32 Simd::m128_add_dpbusd_epi32
#define vec_add_dpbusd_32x2 Simd::m128_add_dpbusd_epi32x2
#define vec_hadd Simd::m128_hadd
#define vec_haddx4 Simd::m128_haddx4
#endif
#if defined (USE_SSSE3)
const vec_t* invec = reinterpret_cast<const vec_t*>(input);
// Perform accumulation to registers for each big block
for (IndexType bigBlock = 0; bigBlock < NumBigBlocks; ++bigBlock)
{
vec_t acc[NumOutputRegs] = { vec_setzero() };
// Each big block has NumOutputRegs small blocks in each "row", one per register.
// We process two small blocks at a time to save on one addition without VNNI.
for (IndexType smallBlock = 0; smallBlock < NumSmallBlocksPerOutput; smallBlock += 2)
{
const vec_t* weightvec =
reinterpret_cast<const vec_t*>(
weights
+ bigBlock * BigBlockSize
+ smallBlock * SmallBlockSize * NumOutputRegs);
const vec_t in0 = invec[smallBlock + 0];
const vec_t in1 = invec[smallBlock + 1];
for (IndexType k = 0; k < NumOutputRegs; ++k)
vec_add_dpbusd_32x2(acc[k], in0, weightvec[k], in1, weightvec[k + NumOutputRegs]);
}
// Horizontally add all accumulators.
if constexpr (NumOutputRegs % 4 == 0)
{
__m128i* outputvec = reinterpret_cast<__m128i*>(output);
const __m128i* biasvec = reinterpret_cast<const __m128i*>(biases);
for (IndexType k = 0; k < NumOutputRegs; k += 4)
{
const IndexType idx = (bigBlock * NumOutputRegs + k) / 4;
outputvec[idx] = vec_haddx4(acc[k+0], acc[k+1], acc[k+2], acc[k+3], biasvec[idx]);
}
}
else
{
for (IndexType k = 0; k < NumOutputRegs; ++k)
{
const IndexType idx = (bigBlock * NumOutputRegs + k);
output[idx] = vec_hadd(acc[k], biases[idx]);
}
}
}
# undef vec_setzero
# undef vec_set_32
# undef vec_add_dpbusd_32
# undef vec_add_dpbusd_32x2
# undef vec_hadd
# undef vec_haddx4
static constexpr IndexType get_weight_index(IndexType i) {
#if defined(USE_SSSE3)
return get_weight_index_scrambled(i);
#else
// Use old implementation for the other architectures.
affine_transform_non_ssse3<
InputDimensions,
PaddedInputDimensions,
OutputDimensions>(output, weights, biases, input);
#endif
return output;
}
private:
using BiasType = OutputType;
using WeightType = std::int8_t;
PreviousLayer previousLayer;
alignas(CacheLineSize) BiasType biases[OutputDimensions];
alignas(CacheLineSize) WeightType weights[OutputDimensions * PaddedInputDimensions];
};
template <typename PreviousLayer, IndexType OutDims>
class AffineTransform<PreviousLayer, OutDims, std::enable_if_t<(PreviousLayer::OutputDimensions < 2*64-1)>> {
public:
// Input/output type
using InputType = typename PreviousLayer::OutputType;
using OutputType = std::int32_t;
static_assert(std::is_same<InputType, std::uint8_t>::value, "");
// Number of input/output dimensions
static constexpr IndexType InputDimensions =
PreviousLayer::OutputDimensions;
static constexpr IndexType OutputDimensions = OutDims;
static constexpr IndexType PaddedInputDimensions =
ceil_to_multiple<IndexType>(InputDimensions, MaxSimdWidth);
static_assert(PaddedInputDimensions < 128, "Something went wrong. This specialization should not have been chosen.");
#if defined (USE_SSSE3)
static constexpr const IndexType OutputSimdWidth = SimdWidth / 4;
static constexpr const IndexType InputSimdWidth = SimdWidth;
#endif
// Size of forward propagation buffer used in this layer
static constexpr std::size_t SelfBufferSize =
ceil_to_multiple(OutputDimensions * sizeof(OutputType), CacheLineSize);
// Size of the forward propagation buffer used from the input layer to this layer
static constexpr std::size_t BufferSize =
PreviousLayer::BufferSize + SelfBufferSize;
// Hash value embedded in the evaluation file
static constexpr std::uint32_t get_hash_value() {
std::uint32_t hashValue = 0xCC03DAE4u;
hashValue += OutputDimensions;
hashValue ^= PreviousLayer::get_hash_value() >> 1;
hashValue ^= PreviousLayer::get_hash_value() << 31;
return hashValue;
}
static IndexType get_weight_index_scrambled(IndexType i)
{
return
(i / 4) % (PaddedInputDimensions / 4) * OutputDimensions * 4 +
i / PaddedInputDimensions * 4 +
i % 4;
}
static IndexType get_weight_index(IndexType i)
{
#if defined (USE_SSSE3)
return get_weight_index_scrambled(i);
#else
return i;
return i;
#endif
}
// Read network parameters
bool read_parameters(std::istream& stream) {
if (!previousLayer.read_parameters(stream)) return false;
for (std::size_t i = 0; i < OutputDimensions; ++i)
biases[i] = read_little_endian<BiasType>(stream);
for (std::size_t i = 0; i < OutputDimensions * PaddedInputDimensions; ++i)
weights[get_weight_index(i)] = read_little_endian<WeightType>(stream);
read_little_endian<BiasType>(stream, biases, OutputDimensions);
for (IndexType i = 0; i < OutputDimensions * PaddedInputDimensions; ++i)
weights[get_weight_index(i)] = read_little_endian<WeightType>(stream);
return !stream.fail();
return !stream.fail();
}
// Write network parameters
bool write_parameters(std::ostream& stream) const {
if (!previousLayer.write_parameters(stream)) return false;
for (std::size_t i = 0; i < OutputDimensions; ++i)
write_little_endian<BiasType>(stream, biases[i]);
write_little_endian<BiasType>(stream, biases, OutputDimensions);
for (std::size_t i = 0; i < OutputDimensions * PaddedInputDimensions; ++i)
write_little_endian<WeightType>(stream, weights[get_weight_index(i)]);
for (IndexType i = 0; i < OutputDimensions * PaddedInputDimensions; ++i)
write_little_endian<WeightType>(stream, weights[get_weight_index(i)]);
return !stream.fail();
return !stream.fail();
}
// Forward propagation
const OutputType* propagate(
const TransformedFeatureType* transformedFeatures, char* buffer) const {
const auto input = previousLayer.propagate(
transformedFeatures, buffer + SelfBufferSize);
const auto output = reinterpret_cast<OutputType*>(buffer);
void propagate(const InputType* input, OutputType* output) const {
#if defined (USE_AVX2)
using vec_t = __m256i;
#define vec_setzero _mm256_setzero_si256
#define vec_set_32 _mm256_set1_epi32
#define vec_add_dpbusd_32 Simd::m256_add_dpbusd_epi32
#define vec_add_dpbusd_32x2 Simd::m256_add_dpbusd_epi32x2
#define vec_add_dpbusd_32x4 Simd::m256_add_dpbusd_epi32x4
#define vec_hadd Simd::m256_hadd
#define vec_haddx4 Simd::m256_haddx4
#elif defined (USE_SSSE3)
using vec_t = __m128i;
#define vec_setzero _mm_setzero_si128
#define vec_set_32 _mm_set1_epi32
#define vec_add_dpbusd_32 Simd::m128_add_dpbusd_epi32
#define vec_add_dpbusd_32x2 Simd::m128_add_dpbusd_epi32x2
#define vec_add_dpbusd_32x4 Simd::m128_add_dpbusd_epi32x4
#define vec_hadd Simd::m128_hadd
#define vec_haddx4 Simd::m128_haddx4
#endif
#if defined(USE_SSSE3)
#if defined (USE_SSSE3)
const auto inputVector = reinterpret_cast<const vec_t*>(input);
static_assert(InputDimensions % 8 == 0);
static_assert(OutputDimensions % OutputSimdWidth == 0 || OutputDimensions == 1);
if constexpr (OutputDimensions % OutputSimdWidth == 0)
{
constexpr IndexType NumChunks = InputDimensions / 4;
constexpr IndexType NumRegs = OutputDimensions / OutputSimdWidth;
const auto input32 = reinterpret_cast<const std::int32_t*>(input);
const vec_t* biasvec = reinterpret_cast<const vec_t*>(biases);
vec_t acc[NumRegs];
for (IndexType k = 0; k < NumRegs; ++k)
acc[k] = biasvec[k];
for (IndexType i = 0; i < NumChunks; i += 2)
if constexpr (OutputDimensions > 1)
{
const vec_t in0 = vec_set_32(input32[i + 0]);
const vec_t in1 = vec_set_32(input32[i + 1]);
const auto col0 = reinterpret_cast<const vec_t*>(&weights[(i + 0) * OutputDimensions * 4]);
const auto col1 = reinterpret_cast<const vec_t*>(&weights[(i + 1) * OutputDimensions * 4]);
for (IndexType k = 0; k < NumRegs; ++k)
vec_add_dpbusd_32x2(acc[k], in0, col0[k], in1, col1[k]);
#if defined(USE_AVX512)
using vec_t = __m512i;
#define vec_setzero _mm512_setzero_si512
#define vec_set_32 _mm512_set1_epi32
#define vec_add_dpbusd_32 Simd::m512_add_dpbusd_epi32
#define vec_hadd Simd::m512_hadd
#elif defined(USE_AVX2)
using vec_t = __m256i;
#define vec_setzero _mm256_setzero_si256
#define vec_set_32 _mm256_set1_epi32
#define vec_add_dpbusd_32 Simd::m256_add_dpbusd_epi32
#define vec_hadd Simd::m256_hadd
#elif defined(USE_SSSE3)
using vec_t = __m128i;
#define vec_setzero _mm_setzero_si128
#define vec_set_32 _mm_set1_epi32
#define vec_add_dpbusd_32 Simd::m128_add_dpbusd_epi32
#define vec_hadd Simd::m128_hadd
#endif
static constexpr IndexType OutputSimdWidth = sizeof(vec_t) / sizeof(OutputType);
static_assert(OutputDimensions % OutputSimdWidth == 0);
constexpr IndexType NumChunks = ceil_to_multiple<IndexType>(InputDimensions, 8) / 4;
constexpr IndexType NumRegs = OutputDimensions / OutputSimdWidth;
const auto input32 = reinterpret_cast<const std::int32_t*>(input);
const vec_t* biasvec = reinterpret_cast<const vec_t*>(biases);
vec_t acc[NumRegs];
for (IndexType k = 0; k < NumRegs; ++k)
acc[k] = biasvec[k];
for (IndexType i = 0; i < NumChunks; ++i)
{
const vec_t in0 = vec_set_32(input32[i]);
const auto col0 =
reinterpret_cast<const vec_t*>(&weights[i * OutputDimensions * 4]);
for (IndexType k = 0; k < NumRegs; ++k)
vec_add_dpbusd_32(acc[k], in0, col0[k]);
}
vec_t* outptr = reinterpret_cast<vec_t*>(output);
for (IndexType k = 0; k < NumRegs; ++k)
outptr[k] = acc[k];
#undef vec_setzero
#undef vec_set_32
#undef vec_add_dpbusd_32
#undef vec_hadd
}
vec_t* outptr = reinterpret_cast<vec_t*>(output);
for (IndexType k = 0; k < NumRegs; ++k)
outptr[k] = acc[k];
}
else if constexpr (OutputDimensions == 1)
{
constexpr IndexType NumChunks = PaddedInputDimensions / SimdWidth;
vec_t sum0 = vec_setzero();
const auto row0 = reinterpret_cast<const vec_t*>(&weights[0]);
for (int j = 0; j < (int)NumChunks; ++j)
else if constexpr (OutputDimensions == 1)
{
const vec_t in = inputVector[j];
vec_add_dpbusd_32(sum0, in, row0[j]);
}
output[0] = vec_hadd(sum0, biases[0]);
}
# undef vec_setzero
# undef vec_set_32
# undef vec_add_dpbusd_32
# undef vec_add_dpbusd_32x2
# undef vec_add_dpbusd_32x4
# undef vec_hadd
# undef vec_haddx4
// We cannot use AVX512 for the last layer because there are only 32 inputs
// and the buffer is not padded to 64 elements.
#if defined(USE_AVX2)
using vec_t = __m256i;
#define vec_setzero _mm256_setzero_si256
#define vec_set_32 _mm256_set1_epi32
#define vec_add_dpbusd_32 Simd::m256_add_dpbusd_epi32
#define vec_hadd Simd::m256_hadd
#elif defined(USE_SSSE3)
using vec_t = __m128i;
#define vec_setzero _mm_setzero_si128
#define vec_set_32 _mm_set1_epi32
#define vec_add_dpbusd_32 Simd::m128_add_dpbusd_epi32
#define vec_hadd Simd::m128_hadd
#endif
const auto inputVector = reinterpret_cast<const vec_t*>(input);
static constexpr IndexType InputSimdWidth = sizeof(vec_t) / sizeof(InputType);
static_assert(PaddedInputDimensions % InputSimdWidth == 0);
constexpr IndexType NumChunks = PaddedInputDimensions / InputSimdWidth;
vec_t sum0 = vec_setzero();
const auto row0 = reinterpret_cast<const vec_t*>(&weights[0]);
for (int j = 0; j < int(NumChunks); ++j)
{
const vec_t in = inputVector[j];
vec_add_dpbusd_32(sum0, in, row0[j]);
}
output[0] = vec_hadd(sum0, biases[0]);
#undef vec_setzero
#undef vec_set_32
#undef vec_add_dpbusd_32
#undef vec_hadd
}
#else
// Use old implementation for the other architectures.
affine_transform_non_ssse3<
InputDimensions,
PaddedInputDimensions,
OutputDimensions>(output, weights, biases, input);
// Use old implementation for the other architectures.
affine_transform_non_ssse3<InputDimensions, PaddedInputDimensions, OutputDimensions>(
output, weights, biases, input);
#endif
return output;
}
private:
using BiasType = OutputType;
using BiasType = OutputType;
using WeightType = std::int8_t;
PreviousLayer previousLayer;
alignas(CacheLineSize) BiasType biases[OutputDimensions];
alignas(CacheLineSize) WeightType weights[OutputDimensions * PaddedInputDimensions];
};
};
} // namespace Stockfish::Eval::NNUE::Layers
#endif // #ifndef NNUE_LAYERS_AFFINE_TRANSFORM_H_INCLUDED
#endif // #ifndef NNUE_LAYERS_AFFINE_TRANSFORM_H_INCLUDED
@@ -0,0 +1,278 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 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 <http://www.gnu.org/licenses/>.
*/
// Definition of layer AffineTransformSparseInput of NNUE evaluation function
#ifndef NNUE_LAYERS_AFFINE_TRANSFORM_SPARSE_INPUT_H_INCLUDED
#define NNUE_LAYERS_AFFINE_TRANSFORM_SPARSE_INPUT_H_INCLUDED
#include <algorithm>
#include <array>
#include <cstdint>
#include <iostream>
#include "../../bitboard.h"
#include "../nnue_common.h"
#include "affine_transform.h"
#include "simd.h"
/*
This file contains the definition for a fully connected layer (aka affine transform) with block sparse input.
*/
namespace Stockfish::Eval::NNUE::Layers {
#if (USE_SSSE3 | (USE_NEON >= 8))
alignas(CacheLineSize) static inline const
std::array<std::array<std::uint16_t, 8>, 256> lookup_indices = []() {
std::array<std::array<std::uint16_t, 8>, 256> v{};
for (unsigned i = 0; i < 256; ++i)
{
std::uint64_t j = i, k = 0;
while (j)
v[i][k++] = pop_lsb(j);
}
return v;
}();
// Find indices of nonzero numbers in an int32_t array
template<const IndexType InputDimensions>
void find_nnz(const std::int32_t* input, std::uint16_t* out, IndexType& count_out) {
#if defined(USE_SSSE3)
#if defined(USE_AVX512)
using vec_t = __m512i;
#define vec_nnz(a) _mm512_cmpgt_epi32_mask(a, _mm512_setzero_si512())
#elif defined(USE_AVX2)
using vec_t = __m256i;
#if defined(USE_VNNI) && !defined(USE_AVXVNNI)
#define vec_nnz(a) _mm256_cmpgt_epi32_mask(a, _mm256_setzero_si256())
#else
#define vec_nnz(a) \
_mm256_movemask_ps( \
_mm256_castsi256_ps(_mm256_cmpgt_epi32(a, _mm256_setzero_si256())))
#endif
#elif defined(USE_SSSE3)
using vec_t = __m128i;
#define vec_nnz(a) \
_mm_movemask_ps(_mm_castsi128_ps(_mm_cmpgt_epi32(a, _mm_setzero_si128())))
#endif
using vec128_t = __m128i;
#define vec128_zero _mm_setzero_si128()
#define vec128_set_16(a) _mm_set1_epi16(a)
#define vec128_load(a) _mm_load_si128(a)
#define vec128_storeu(a, b) _mm_storeu_si128(a, b)
#define vec128_add(a, b) _mm_add_epi16(a, b)
#elif defined(USE_NEON)
using vec_t = uint32x4_t;
static const std::uint32_t Mask[4] = {1, 2, 4, 8};
#define vec_nnz(a) vaddvq_u32(vandq_u32(vtstq_u32(a, a), vld1q_u32(Mask)))
using vec128_t = uint16x8_t;
#define vec128_zero vdupq_n_u16(0)
#define vec128_set_16(a) vdupq_n_u16(a)
#define vec128_load(a) vld1q_u16(reinterpret_cast<const std::uint16_t*>(a))
#define vec128_storeu(a, b) vst1q_u16(reinterpret_cast<std::uint16_t*>(a), b)
#define vec128_add(a, b) vaddq_u16(a, b)
#endif
constexpr IndexType InputSimdWidth = sizeof(vec_t) / sizeof(std::int32_t);
// Inputs are processed InputSimdWidth at a time and outputs are processed 8 at a time so we process in chunks of max(InputSimdWidth, 8)
constexpr IndexType ChunkSize = std::max<IndexType>(InputSimdWidth, 8);
constexpr IndexType NumChunks = InputDimensions / ChunkSize;
constexpr IndexType InputsPerChunk = ChunkSize / InputSimdWidth;
constexpr IndexType OutputsPerChunk = ChunkSize / 8;
const auto inputVector = reinterpret_cast<const vec_t*>(input);
IndexType count = 0;
vec128_t base = vec128_zero;
const vec128_t increment = vec128_set_16(8);
for (IndexType i = 0; i < NumChunks; ++i)
{
// bitmask of nonzero values in this chunk
unsigned nnz = 0;
for (IndexType j = 0; j < InputsPerChunk; ++j)
{
const vec_t inputChunk = inputVector[i * InputsPerChunk + j];
nnz |= unsigned(vec_nnz(inputChunk)) << (j * InputSimdWidth);
}
for (IndexType j = 0; j < OutputsPerChunk; ++j)
{
const auto lookup = (nnz >> (j * 8)) & 0xFF;
const auto offsets =
vec128_load(reinterpret_cast<const vec128_t*>(&lookup_indices[lookup]));
vec128_storeu(reinterpret_cast<vec128_t*>(out + count), vec128_add(base, offsets));
count += popcount(lookup);
base = vec128_add(base, increment);
}
}
count_out = count;
}
#undef vec_nnz
#undef vec128_zero
#undef vec128_set_16
#undef vec128_load
#undef vec128_storeu
#undef vec128_add
#endif
// Sparse input implementation
template<IndexType InDims, IndexType OutDims>
class AffineTransformSparseInput {
public:
// Input/output type
using InputType = std::uint8_t;
using OutputType = std::int32_t;
// Number of input/output dimensions
static constexpr IndexType InputDimensions = InDims;
static constexpr IndexType OutputDimensions = OutDims;
static_assert(OutputDimensions % 16 == 0,
"Only implemented for OutputDimensions divisible by 16.");
static constexpr IndexType PaddedInputDimensions =
ceil_to_multiple<IndexType>(InputDimensions, MaxSimdWidth);
static constexpr IndexType PaddedOutputDimensions =
ceil_to_multiple<IndexType>(OutputDimensions, MaxSimdWidth);
#if (USE_SSSE3 | (USE_NEON >= 8))
static constexpr IndexType ChunkSize = 4;
#else
static constexpr IndexType ChunkSize = 1;
#endif
using OutputBuffer = OutputType[PaddedOutputDimensions];
// Hash value embedded in the evaluation file
static constexpr std::uint32_t get_hash_value(std::uint32_t prevHash) {
std::uint32_t hashValue = 0xCC03DAE4u;
hashValue += OutputDimensions;
hashValue ^= prevHash >> 1;
hashValue ^= prevHash << 31;
return hashValue;
}
static constexpr IndexType get_weight_index_scrambled(IndexType i) {
return (i / ChunkSize) % (PaddedInputDimensions / ChunkSize) * OutputDimensions * ChunkSize
+ i / PaddedInputDimensions * ChunkSize + i % ChunkSize;
}
static constexpr IndexType get_weight_index(IndexType i) {
#if (USE_SSSE3 | (USE_NEON >= 8))
return get_weight_index_scrambled(i);
#else
return i;
#endif
}
// Read network parameters
bool read_parameters(std::istream& stream) {
read_little_endian<BiasType>(stream, biases, OutputDimensions);
for (IndexType i = 0; i < OutputDimensions * PaddedInputDimensions; ++i)
weights[get_weight_index(i)] = read_little_endian<WeightType>(stream);
return !stream.fail();
}
// Write network parameters
bool write_parameters(std::ostream& stream) const {
write_little_endian<BiasType>(stream, biases, OutputDimensions);
for (IndexType i = 0; i < OutputDimensions * PaddedInputDimensions; ++i)
write_little_endian<WeightType>(stream, weights[get_weight_index(i)]);
return !stream.fail();
}
// Forward propagation
void propagate(const InputType* input, OutputType* output) const {
#if (USE_SSSE3 | (USE_NEON >= 8))
#if defined(USE_AVX512)
using invec_t = __m512i;
using outvec_t = __m512i;
#define vec_set_32 _mm512_set1_epi32
#define vec_add_dpbusd_32 Simd::m512_add_dpbusd_epi32
#elif defined(USE_AVX2)
using invec_t = __m256i;
using outvec_t = __m256i;
#define vec_set_32 _mm256_set1_epi32
#define vec_add_dpbusd_32 Simd::m256_add_dpbusd_epi32
#elif defined(USE_SSSE3)
using invec_t = __m128i;
using outvec_t = __m128i;
#define vec_set_32 _mm_set1_epi32
#define vec_add_dpbusd_32 Simd::m128_add_dpbusd_epi32
#elif defined(USE_NEON_DOTPROD)
using invec_t = int8x16_t;
using outvec_t = int32x4_t;
#define vec_set_32(a) vreinterpretq_s8_u32(vdupq_n_u32(a))
#define vec_add_dpbusd_32 Simd::dotprod_m128_add_dpbusd_epi32
#elif defined(USE_NEON)
using invec_t = int8x16_t;
using outvec_t = int32x4_t;
#define vec_set_32(a) vreinterpretq_s8_u32(vdupq_n_u32(a))
#define vec_add_dpbusd_32 Simd::neon_m128_add_dpbusd_epi32
#endif
static constexpr IndexType OutputSimdWidth = sizeof(outvec_t) / sizeof(OutputType);
constexpr IndexType NumChunks = ceil_to_multiple<IndexType>(InputDimensions, 8) / ChunkSize;
constexpr IndexType NumRegs = OutputDimensions / OutputSimdWidth;
std::uint16_t nnz[NumChunks];
IndexType count;
const auto input32 = reinterpret_cast<const std::int32_t*>(input);
// Find indices of nonzero 32-bit blocks
find_nnz<NumChunks>(input32, nnz, count);
const outvec_t* biasvec = reinterpret_cast<const outvec_t*>(biases);
outvec_t acc[NumRegs];
for (IndexType k = 0; k < NumRegs; ++k)
acc[k] = biasvec[k];
for (IndexType j = 0; j < count; ++j)
{
const auto i = nnz[j];
const invec_t in = vec_set_32(input32[i]);
const auto col =
reinterpret_cast<const invec_t*>(&weights[i * OutputDimensions * ChunkSize]);
for (IndexType k = 0; k < NumRegs; ++k)
vec_add_dpbusd_32(acc[k], in, col[k]);
}
outvec_t* outptr = reinterpret_cast<outvec_t*>(output);
for (IndexType k = 0; k < NumRegs; ++k)
outptr[k] = acc[k];
#undef vec_set_32
#undef vec_add_dpbusd_32
#else
// Use dense implementation for the other architectures.
affine_transform_non_ssse3<InputDimensions, PaddedInputDimensions, OutputDimensions>(
output, weights, biases, input);
#endif
}
private:
using BiasType = OutputType;
using WeightType = std::int8_t;
alignas(CacheLineSize) BiasType biases[OutputDimensions];
alignas(CacheLineSize) WeightType weights[OutputDimensions * PaddedInputDimensions];
};
} // namespace Stockfish::Eval::NNUE::Layers
#endif // #ifndef NNUE_LAYERS_AFFINE_TRANSFORM_SPARSE_INPUT_H_INCLUDED
+114 -147
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -21,181 +21,148 @@
#ifndef NNUE_LAYERS_CLIPPED_RELU_H_INCLUDED
#define NNUE_LAYERS_CLIPPED_RELU_H_INCLUDED
#include <algorithm>
#include <cstdint>
#include <iosfwd>
#include "../nnue_common.h"
namespace Stockfish::Eval::NNUE::Layers {
// Clipped ReLU
template <typename PreviousLayer>
class ClippedReLU {
// Clipped ReLU
template<IndexType InDims>
class ClippedReLU {
public:
// Input/output type
using InputType = typename PreviousLayer::OutputType;
using InputType = std::int32_t;
using OutputType = std::uint8_t;
static_assert(std::is_same<InputType, std::int32_t>::value, "");
// Number of input/output dimensions
static constexpr IndexType InputDimensions = PreviousLayer::OutputDimensions;
static constexpr IndexType InputDimensions = InDims;
static constexpr IndexType OutputDimensions = InputDimensions;
static constexpr IndexType PaddedOutputDimensions =
ceil_to_multiple<IndexType>(OutputDimensions, 32);
ceil_to_multiple<IndexType>(OutputDimensions, 32);
// Size of forward propagation buffer used in this layer
static constexpr std::size_t SelfBufferSize =
ceil_to_multiple(OutputDimensions * sizeof(OutputType), CacheLineSize);
// Size of the forward propagation buffer used from the input layer to this layer
static constexpr std::size_t BufferSize =
PreviousLayer::BufferSize + SelfBufferSize;
using OutputBuffer = OutputType[PaddedOutputDimensions];
// Hash value embedded in the evaluation file
static constexpr std::uint32_t get_hash_value() {
std::uint32_t hashValue = 0x538D24C7u;
hashValue += PreviousLayer::get_hash_value();
return hashValue;
static constexpr std::uint32_t get_hash_value(std::uint32_t prevHash) {
std::uint32_t hashValue = 0x538D24C7u;
hashValue += prevHash;
return hashValue;
}
// Read network parameters
bool read_parameters(std::istream& stream) {
return previousLayer.read_parameters(stream);
}
bool read_parameters(std::istream&) { return true; }
// Write network parameters
bool write_parameters(std::ostream& stream) const {
return previousLayer.write_parameters(stream);
}
bool write_parameters(std::ostream&) const { return true; }
// Forward propagation
const OutputType* propagate(
const TransformedFeatureType* transformedFeatures, char* buffer) const {
const auto input = previousLayer.propagate(
transformedFeatures, buffer + SelfBufferSize);
const auto output = reinterpret_cast<OutputType*>(buffer);
void propagate(const InputType* input, OutputType* output) const {
#if defined(USE_AVX2)
if constexpr (InputDimensions % SimdWidth == 0) {
#if defined(USE_AVX2)
if constexpr (InputDimensions % SimdWidth == 0)
{
constexpr IndexType NumChunks = InputDimensions / SimdWidth;
const __m256i Zero = _mm256_setzero_si256();
const __m256i Offsets = _mm256_set_epi32(7, 3, 6, 2, 5, 1, 4, 0);
const auto in = reinterpret_cast<const __m256i*>(input);
const auto out = reinterpret_cast<__m256i*>(output);
for (IndexType i = 0; i < NumChunks; ++i)
{
const __m256i words0 =
_mm256_srai_epi16(_mm256_packs_epi32(_mm256_load_si256(&in[i * 4 + 0]),
_mm256_load_si256(&in[i * 4 + 1])),
WeightScaleBits);
const __m256i words1 =
_mm256_srai_epi16(_mm256_packs_epi32(_mm256_load_si256(&in[i * 4 + 2]),
_mm256_load_si256(&in[i * 4 + 3])),
WeightScaleBits);
_mm256_store_si256(
&out[i], _mm256_permutevar8x32_epi32(
_mm256_max_epi8(_mm256_packs_epi16(words0, words1), Zero), Offsets));
}
}
else
{
constexpr IndexType NumChunks = InputDimensions / (SimdWidth / 2);
const __m128i Zero = _mm_setzero_si128();
const auto in = reinterpret_cast<const __m128i*>(input);
const auto out = reinterpret_cast<__m128i*>(output);
for (IndexType i = 0; i < NumChunks; ++i)
{
const __m128i words0 = _mm_srai_epi16(
_mm_packs_epi32(_mm_load_si128(&in[i * 4 + 0]), _mm_load_si128(&in[i * 4 + 1])),
WeightScaleBits);
const __m128i words1 = _mm_srai_epi16(
_mm_packs_epi32(_mm_load_si128(&in[i * 4 + 2]), _mm_load_si128(&in[i * 4 + 3])),
WeightScaleBits);
const __m128i packedbytes = _mm_packs_epi16(words0, words1);
_mm_store_si128(&out[i], _mm_max_epi8(packedbytes, Zero));
}
}
constexpr IndexType Start = InputDimensions % SimdWidth == 0
? InputDimensions / SimdWidth * SimdWidth
: InputDimensions / (SimdWidth / 2) * (SimdWidth / 2);
#elif defined(USE_SSE2)
constexpr IndexType NumChunks = InputDimensions / SimdWidth;
const __m256i Zero = _mm256_setzero_si256();
const __m256i Offsets = _mm256_set_epi32(7, 3, 6, 2, 5, 1, 4, 0);
const auto in = reinterpret_cast<const __m256i*>(input);
const auto out = reinterpret_cast<__m256i*>(output);
for (IndexType i = 0; i < NumChunks; ++i) {
const __m256i words0 = _mm256_srai_epi16(_mm256_packs_epi32(
_mm256_load_si256(&in[i * 4 + 0]),
_mm256_load_si256(&in[i * 4 + 1])), WeightScaleBits);
const __m256i words1 = _mm256_srai_epi16(_mm256_packs_epi32(
_mm256_load_si256(&in[i * 4 + 2]),
_mm256_load_si256(&in[i * 4 + 3])), WeightScaleBits);
_mm256_store_si256(&out[i], _mm256_permutevar8x32_epi32(_mm256_max_epi8(
_mm256_packs_epi16(words0, words1), Zero), Offsets));
}
} else {
constexpr IndexType NumChunks = InputDimensions / (SimdWidth / 2);
#ifdef USE_SSE41
const __m128i Zero = _mm_setzero_si128();
const auto in = reinterpret_cast<const __m128i*>(input);
#else
const __m128i k0x80s = _mm_set1_epi8(-128);
#endif
const auto in = reinterpret_cast<const __m128i*>(input);
const auto out = reinterpret_cast<__m128i*>(output);
for (IndexType i = 0; i < NumChunks; ++i) {
const __m128i words0 = _mm_srai_epi16(_mm_packs_epi32(
_mm_load_si128(&in[i * 4 + 0]),
_mm_load_si128(&in[i * 4 + 1])), WeightScaleBits);
const __m128i words1 = _mm_srai_epi16(_mm_packs_epi32(
_mm_load_si128(&in[i * 4 + 2]),
_mm_load_si128(&in[i * 4 + 3])), WeightScaleBits);
const __m128i packedbytes = _mm_packs_epi16(words0, words1);
_mm_store_si128(&out[i], _mm_max_epi8(packedbytes, Zero));
for (IndexType i = 0; i < NumChunks; ++i)
{
const __m128i words0 = _mm_srai_epi16(
_mm_packs_epi32(_mm_load_si128(&in[i * 4 + 0]), _mm_load_si128(&in[i * 4 + 1])),
WeightScaleBits);
const __m128i words1 = _mm_srai_epi16(
_mm_packs_epi32(_mm_load_si128(&in[i * 4 + 2]), _mm_load_si128(&in[i * 4 + 3])),
WeightScaleBits);
const __m128i packedbytes = _mm_packs_epi16(words0, words1);
_mm_store_si128(&out[i],
#ifdef USE_SSE41
_mm_max_epi8(packedbytes, Zero)
#else
_mm_subs_epi8(_mm_adds_epi8(packedbytes, k0x80s), k0x80s)
#endif
);
}
}
constexpr IndexType Start =
InputDimensions % SimdWidth == 0
? InputDimensions / SimdWidth * SimdWidth
: InputDimensions / (SimdWidth / 2) * (SimdWidth / 2);
constexpr IndexType Start = NumChunks * SimdWidth;
#elif defined(USE_SSE2)
constexpr IndexType NumChunks = InputDimensions / SimdWidth;
#elif defined(USE_NEON)
constexpr IndexType NumChunks = InputDimensions / (SimdWidth / 2);
const int8x8_t Zero = {0};
const auto in = reinterpret_cast<const int32x4_t*>(input);
const auto out = reinterpret_cast<int8x8_t*>(output);
for (IndexType i = 0; i < NumChunks; ++i)
{
int16x8_t shifted;
const auto pack = reinterpret_cast<int16x4_t*>(&shifted);
pack[0] = vqshrn_n_s32(in[i * 2 + 0], WeightScaleBits);
pack[1] = vqshrn_n_s32(in[i * 2 + 1], WeightScaleBits);
out[i] = vmax_s8(vqmovn_s16(shifted), Zero);
}
constexpr IndexType Start = NumChunks * (SimdWidth / 2);
#else
constexpr IndexType Start = 0;
#endif
#ifdef USE_SSE41
const __m128i Zero = _mm_setzero_si128();
#else
const __m128i k0x80s = _mm_set1_epi8(-128);
#endif
const auto in = reinterpret_cast<const __m128i*>(input);
const auto out = reinterpret_cast<__m128i*>(output);
for (IndexType i = 0; i < NumChunks; ++i) {
const __m128i words0 = _mm_srai_epi16(_mm_packs_epi32(
_mm_load_si128(&in[i * 4 + 0]),
_mm_load_si128(&in[i * 4 + 1])), WeightScaleBits);
const __m128i words1 = _mm_srai_epi16(_mm_packs_epi32(
_mm_load_si128(&in[i * 4 + 2]),
_mm_load_si128(&in[i * 4 + 3])), WeightScaleBits);
const __m128i packedbytes = _mm_packs_epi16(words0, words1);
_mm_store_si128(&out[i],
#ifdef USE_SSE41
_mm_max_epi8(packedbytes, Zero)
#else
_mm_subs_epi8(_mm_adds_epi8(packedbytes, k0x80s), k0x80s)
#endif
);
}
constexpr IndexType Start = NumChunks * SimdWidth;
#elif defined(USE_MMX)
constexpr IndexType NumChunks = InputDimensions / SimdWidth;
const __m64 k0x80s = _mm_set1_pi8(-128);
const auto in = reinterpret_cast<const __m64*>(input);
const auto out = reinterpret_cast<__m64*>(output);
for (IndexType i = 0; i < NumChunks; ++i) {
const __m64 words0 = _mm_srai_pi16(
_mm_packs_pi32(in[i * 4 + 0], in[i * 4 + 1]),
WeightScaleBits);
const __m64 words1 = _mm_srai_pi16(
_mm_packs_pi32(in[i * 4 + 2], in[i * 4 + 3]),
WeightScaleBits);
const __m64 packedbytes = _mm_packs_pi16(words0, words1);
out[i] = _mm_subs_pi8(_mm_adds_pi8(packedbytes, k0x80s), k0x80s);
}
_mm_empty();
constexpr IndexType Start = NumChunks * SimdWidth;
#elif defined(USE_NEON)
constexpr IndexType NumChunks = InputDimensions / (SimdWidth / 2);
const int8x8_t Zero = {0};
const auto in = reinterpret_cast<const int32x4_t*>(input);
const auto out = reinterpret_cast<int8x8_t*>(output);
for (IndexType i = 0; i < NumChunks; ++i) {
int16x8_t shifted;
const auto pack = reinterpret_cast<int16x4_t*>(&shifted);
pack[0] = vqshrn_n_s32(in[i * 2 + 0], WeightScaleBits);
pack[1] = vqshrn_n_s32(in[i * 2 + 1], WeightScaleBits);
out[i] = vmax_s8(vqmovn_s16(shifted), Zero);
}
constexpr IndexType Start = NumChunks * (SimdWidth / 2);
#else
constexpr IndexType Start = 0;
#endif
for (IndexType i = Start; i < InputDimensions; ++i) {
output[i] = static_cast<OutputType>(
std::max(0, std::min(127, input[i] >> WeightScaleBits)));
}
// Affine transform layers expect that there is at least
// ceil_to_multiple(OutputDimensions, 32) initialized values.
// We cannot do this in the affine transform because it requires
// preallocating space here.
for (IndexType i = OutputDimensions; i < PaddedOutputDimensions; ++i) {
output[i] = 0;
}
return output;
for (IndexType i = Start; i < InputDimensions; ++i)
{
output[i] = static_cast<OutputType>(std::clamp(input[i] >> WeightScaleBits, 0, 127));
}
}
private:
PreviousLayer previousLayer;
};
};
} // namespace Stockfish::Eval::NNUE::Layers
#endif // NNUE_LAYERS_CLIPPED_RELU_H_INCLUDED
#endif // NNUE_LAYERS_CLIPPED_RELU_H_INCLUDED
-73
View File
@@ -1,73 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 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 <http://www.gnu.org/licenses/>.
*/
// NNUE evaluation function layer InputSlice definition
#ifndef NNUE_LAYERS_INPUT_SLICE_H_INCLUDED
#define NNUE_LAYERS_INPUT_SLICE_H_INCLUDED
#include "../nnue_common.h"
namespace Stockfish::Eval::NNUE::Layers {
// Input layer
template <IndexType OutDims, IndexType Offset = 0>
class InputSlice {
public:
// Need to maintain alignment
static_assert(Offset % MaxSimdWidth == 0, "");
// Output type
using OutputType = TransformedFeatureType;
// Output dimensionality
static constexpr IndexType OutputDimensions = OutDims;
// Size of forward propagation buffer used from the input layer to this layer
static constexpr std::size_t BufferSize = 0;
// Hash value embedded in the evaluation file
static constexpr std::uint32_t get_hash_value() {
std::uint32_t hashValue = 0xEC42E90Du;
hashValue ^= OutputDimensions ^ (Offset << 10);
return hashValue;
}
// Read network parameters
bool read_parameters(std::istream& /*stream*/) {
return true;
}
// Write network parameters
bool write_parameters(std::ostream& /*stream*/) const {
return true;
}
// Forward propagation
const OutputType* propagate(
const TransformedFeatureType* transformedFeatures,
char* /*buffer*/) const {
return transformedFeatures + Offset;
}
private:
};
} // namespace Stockfish::Eval::NNUE::Layers
#endif // #ifndef NNUE_LAYERS_INPUT_SLICE_H_INCLUDED
+167
View File
@@ -0,0 +1,167 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 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 <http://www.gnu.org/licenses/>.
*/
#ifndef STOCKFISH_SIMD_H_INCLUDED
#define STOCKFISH_SIMD_H_INCLUDED
#if defined(USE_AVX2)
#include <immintrin.h>
#elif defined(USE_SSE41)
#include <smmintrin.h>
#elif defined(USE_SSSE3)
#include <tmmintrin.h>
#elif defined(USE_SSE2)
#include <emmintrin.h>
#elif defined(USE_NEON)
#include <arm_neon.h>
#endif
namespace Stockfish::Simd {
#if defined(USE_AVX512)
[[maybe_unused]] static int m512_hadd(__m512i sum, int bias) {
return _mm512_reduce_add_epi32(sum) + bias;
}
/*
Parameters:
sum0 = [zmm0.i128[0], zmm0.i128[1], zmm0.i128[2], zmm0.i128[3]]
sum1 = [zmm1.i128[0], zmm1.i128[1], zmm1.i128[2], zmm1.i128[3]]
sum2 = [zmm2.i128[0], zmm2.i128[1], zmm2.i128[2], zmm2.i128[3]]
sum3 = [zmm3.i128[0], zmm3.i128[1], zmm3.i128[2], zmm3.i128[3]]
Returns:
ret = [
reduce_add_epi32(zmm0.i128[0]), reduce_add_epi32(zmm1.i128[0]), reduce_add_epi32(zmm2.i128[0]), reduce_add_epi32(zmm3.i128[0]),
reduce_add_epi32(zmm0.i128[1]), reduce_add_epi32(zmm1.i128[1]), reduce_add_epi32(zmm2.i128[1]), reduce_add_epi32(zmm3.i128[1]),
reduce_add_epi32(zmm0.i128[2]), reduce_add_epi32(zmm1.i128[2]), reduce_add_epi32(zmm2.i128[2]), reduce_add_epi32(zmm3.i128[2]),
reduce_add_epi32(zmm0.i128[3]), reduce_add_epi32(zmm1.i128[3]), reduce_add_epi32(zmm2.i128[3]), reduce_add_epi32(zmm3.i128[3])
]
*/
[[maybe_unused]] static __m512i
m512_hadd128x16_interleave(__m512i sum0, __m512i sum1, __m512i sum2, __m512i sum3) {
__m512i sum01a = _mm512_unpacklo_epi32(sum0, sum1);
__m512i sum01b = _mm512_unpackhi_epi32(sum0, sum1);
__m512i sum23a = _mm512_unpacklo_epi32(sum2, sum3);
__m512i sum23b = _mm512_unpackhi_epi32(sum2, sum3);
__m512i sum01 = _mm512_add_epi32(sum01a, sum01b);
__m512i sum23 = _mm512_add_epi32(sum23a, sum23b);
__m512i sum0123a = _mm512_unpacklo_epi64(sum01, sum23);
__m512i sum0123b = _mm512_unpackhi_epi64(sum01, sum23);
return _mm512_add_epi32(sum0123a, sum0123b);
}
[[maybe_unused]] static void m512_add_dpbusd_epi32(__m512i& acc, __m512i a, __m512i b) {
#if defined(USE_VNNI)
acc = _mm512_dpbusd_epi32(acc, a, b);
#else
__m512i product0 = _mm512_maddubs_epi16(a, b);
product0 = _mm512_madd_epi16(product0, _mm512_set1_epi16(1));
acc = _mm512_add_epi32(acc, product0);
#endif
}
#endif
#if defined(USE_AVX2)
[[maybe_unused]] static int m256_hadd(__m256i sum, int bias) {
__m128i sum128 = _mm_add_epi32(_mm256_castsi256_si128(sum), _mm256_extracti128_si256(sum, 1));
sum128 = _mm_add_epi32(sum128, _mm_shuffle_epi32(sum128, _MM_PERM_BADC));
sum128 = _mm_add_epi32(sum128, _mm_shuffle_epi32(sum128, _MM_PERM_CDAB));
return _mm_cvtsi128_si32(sum128) + bias;
}
[[maybe_unused]] static void m256_add_dpbusd_epi32(__m256i& acc, __m256i a, __m256i b) {
#if defined(USE_VNNI)
acc = _mm256_dpbusd_epi32(acc, a, b);
#else
__m256i product0 = _mm256_maddubs_epi16(a, b);
product0 = _mm256_madd_epi16(product0, _mm256_set1_epi16(1));
acc = _mm256_add_epi32(acc, product0);
#endif
}
#endif
#if defined(USE_SSSE3)
[[maybe_unused]] static int m128_hadd(__m128i sum, int bias) {
sum = _mm_add_epi32(sum, _mm_shuffle_epi32(sum, 0x4E)); //_MM_PERM_BADC
sum = _mm_add_epi32(sum, _mm_shuffle_epi32(sum, 0xB1)); //_MM_PERM_CDAB
return _mm_cvtsi128_si32(sum) + bias;
}
[[maybe_unused]] static void m128_add_dpbusd_epi32(__m128i& acc, __m128i a, __m128i b) {
__m128i product0 = _mm_maddubs_epi16(a, b);
product0 = _mm_madd_epi16(product0, _mm_set1_epi16(1));
acc = _mm_add_epi32(acc, product0);
}
#endif
#if defined(USE_NEON_DOTPROD)
[[maybe_unused]] static void
dotprod_m128_add_dpbusd_epi32(int32x4_t& acc, int8x16_t a, int8x16_t b) {
acc = vdotq_s32(acc, a, b);
}
#endif
#if defined(USE_NEON)
[[maybe_unused]] static int neon_m128_reduce_add_epi32(int32x4_t s) {
#if USE_NEON >= 8
return vaddvq_s32(s);
#else
return s[0] + s[1] + s[2] + s[3];
#endif
}
[[maybe_unused]] static int neon_m128_hadd(int32x4_t sum, int bias) {
return neon_m128_reduce_add_epi32(sum) + bias;
}
#endif
#if USE_NEON >= 8
[[maybe_unused]] static void neon_m128_add_dpbusd_epi32(int32x4_t& acc, int8x16_t a, int8x16_t b) {
int16x8_t product0 = vmull_s8(vget_low_s8(a), vget_low_s8(b));
int16x8_t product1 = vmull_high_s8(a, b);
int16x8_t sum = vpaddq_s16(product0, product1);
acc = vpadalq_s16(acc, sum);
}
#endif
}
#endif // STOCKFISH_SIMD_H_INCLUDED
+103
View File
@@ -0,0 +1,103 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 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 <http://www.gnu.org/licenses/>.
*/
// Definition of layer ClippedReLU of NNUE evaluation function
#ifndef NNUE_LAYERS_SQR_CLIPPED_RELU_H_INCLUDED
#define NNUE_LAYERS_SQR_CLIPPED_RELU_H_INCLUDED
#include <algorithm>
#include <cstdint>
#include <iosfwd>
#include "../nnue_common.h"
namespace Stockfish::Eval::NNUE::Layers {
// Clipped ReLU
template<IndexType InDims>
class SqrClippedReLU {
public:
// Input/output type
using InputType = std::int32_t;
using OutputType = std::uint8_t;
// Number of input/output dimensions
static constexpr IndexType InputDimensions = InDims;
static constexpr IndexType OutputDimensions = InputDimensions;
static constexpr IndexType PaddedOutputDimensions =
ceil_to_multiple<IndexType>(OutputDimensions, 32);
using OutputBuffer = OutputType[PaddedOutputDimensions];
// Hash value embedded in the evaluation file
static constexpr std::uint32_t get_hash_value(std::uint32_t prevHash) {
std::uint32_t hashValue = 0x538D24C7u;
hashValue += prevHash;
return hashValue;
}
// Read network parameters
bool read_parameters(std::istream&) { return true; }
// Write network parameters
bool write_parameters(std::ostream&) const { return true; }
// Forward propagation
void propagate(const InputType* input, OutputType* output) const {
#if defined(USE_SSE2)
constexpr IndexType NumChunks = InputDimensions / 16;
static_assert(WeightScaleBits == 6);
const auto in = reinterpret_cast<const __m128i*>(input);
const auto out = reinterpret_cast<__m128i*>(output);
for (IndexType i = 0; i < NumChunks; ++i)
{
__m128i words0 =
_mm_packs_epi32(_mm_load_si128(&in[i * 4 + 0]), _mm_load_si128(&in[i * 4 + 1]));
__m128i words1 =
_mm_packs_epi32(_mm_load_si128(&in[i * 4 + 2]), _mm_load_si128(&in[i * 4 + 3]));
// We shift by WeightScaleBits * 2 = 12 and divide by 128
// which is an additional shift-right of 7, meaning 19 in total.
// MulHi strips the lower 16 bits so we need to shift out 3 more to match.
words0 = _mm_srli_epi16(_mm_mulhi_epi16(words0, words0), 3);
words1 = _mm_srli_epi16(_mm_mulhi_epi16(words1, words1), 3);
_mm_store_si128(&out[i], _mm_packs_epi16(words0, words1));
}
constexpr IndexType Start = NumChunks * 16;
#else
constexpr IndexType Start = 0;
#endif
for (IndexType i = Start; i < InputDimensions; ++i)
{
output[i] = static_cast<OutputType>(
// Really should be /127 but we need to make it fast so we right-shift
// by an extra 7 bits instead. Needs to be accounted for in the trainer.
std::min(127ll, ((long long) (input[i]) * input[i]) >> (2 * WeightScaleBits + 7)));
}
}
};
} // namespace Stockfish::Eval::NNUE::Layers
#endif // NNUE_LAYERS_SQR_CLIPPED_RELU_H_INCLUDED
+11 -7
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -21,17 +21,21 @@
#ifndef NNUE_ACCUMULATOR_H_INCLUDED
#define NNUE_ACCUMULATOR_H_INCLUDED
#include <cstdint>
#include "nnue_architecture.h"
#include "nnue_common.h"
namespace Stockfish::Eval::NNUE {
// Class that holds the result of affine transformation of input features
struct alignas(CacheLineSize) Accumulator {
std::int16_t accumulation[2][TransformedFeatureDimensions];
// Class that holds the result of affine transformation of input features
template<IndexType Size>
struct alignas(CacheLineSize) Accumulator {
std::int16_t accumulation[2][Size];
std::int32_t psqtAccumulation[2][PSQTBuckets];
bool computed[2];
};
bool computed[2];
};
} // namespace Stockfish::Eval::NNUE
#endif // NNUE_ACCUMULATOR_H_INCLUDED
#endif // NNUE_ACCUMULATOR_H_INCLUDED
+104 -22
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -21,40 +21,122 @@
#ifndef NNUE_ARCHITECTURE_H_INCLUDED
#define NNUE_ARCHITECTURE_H_INCLUDED
#include "nnue_common.h"
#include <cstdint>
#include <cstring>
#include <iosfwd>
#include "features/half_ka_v2_hm.h"
#include "layers/input_slice.h"
#include "layers/affine_transform.h"
#include "layers/affine_transform_sparse_input.h"
#include "layers/clipped_relu.h"
#include "layers/sqr_clipped_relu.h"
#include "nnue_common.h"
namespace Stockfish::Eval::NNUE {
// Input features used in evaluation function
using FeatureSet = Features::HalfKAv2_hm;
// Input features used in evaluation function
using FeatureSet = Features::HalfKAv2_hm;
// Number of input feature dimensions after conversion
constexpr IndexType TransformedFeatureDimensions = 1024;
constexpr IndexType PSQTBuckets = 8;
constexpr IndexType LayerStacks = 8;
enum NetSize : int {
Big,
Small
};
namespace Layers {
// Number of input feature dimensions after conversion
constexpr IndexType TransformedFeatureDimensionsBig = 2560;
constexpr int L2Big = 15;
constexpr int L3Big = 32;
// Define network structure
using InputLayer = InputSlice<TransformedFeatureDimensions * 2>;
using HiddenLayer1 = ClippedReLU<AffineTransform<InputLayer, 8>>;
using HiddenLayer2 = ClippedReLU<AffineTransform<HiddenLayer1, 32>>;
using OutputLayer = AffineTransform<HiddenLayer2, 1>;
constexpr IndexType TransformedFeatureDimensionsSmall = 128;
constexpr int L2Small = 15;
constexpr int L3Small = 32;
} // namespace Layers
constexpr IndexType PSQTBuckets = 8;
constexpr IndexType LayerStacks = 8;
using Network = Layers::OutputLayer;
template<IndexType L1, int L2, int L3>
struct Network {
static constexpr IndexType TransformedFeatureDimensions = L1;
static constexpr int FC_0_OUTPUTS = L2;
static constexpr int FC_1_OUTPUTS = L3;
static_assert(TransformedFeatureDimensions % MaxSimdWidth == 0, "");
static_assert(Network::OutputDimensions == 1, "");
static_assert(std::is_same<Network::OutputType, std::int32_t>::value, "");
Layers::AffineTransformSparseInput<TransformedFeatureDimensions, FC_0_OUTPUTS + 1> fc_0;
Layers::SqrClippedReLU<FC_0_OUTPUTS + 1> ac_sqr_0;
Layers::ClippedReLU<FC_0_OUTPUTS + 1> ac_0;
Layers::AffineTransform<FC_0_OUTPUTS * 2, FC_1_OUTPUTS> fc_1;
Layers::ClippedReLU<FC_1_OUTPUTS> ac_1;
Layers::AffineTransform<FC_1_OUTPUTS, 1> fc_2;
// Hash value embedded in the evaluation file
static constexpr std::uint32_t get_hash_value() {
// input slice hash
std::uint32_t hashValue = 0xEC42E90Du;
hashValue ^= TransformedFeatureDimensions * 2;
hashValue = decltype(fc_0)::get_hash_value(hashValue);
hashValue = decltype(ac_0)::get_hash_value(hashValue);
hashValue = decltype(fc_1)::get_hash_value(hashValue);
hashValue = decltype(ac_1)::get_hash_value(hashValue);
hashValue = decltype(fc_2)::get_hash_value(hashValue);
return hashValue;
}
// Read network parameters
bool read_parameters(std::istream& stream) {
return fc_0.read_parameters(stream) && ac_0.read_parameters(stream)
&& fc_1.read_parameters(stream) && ac_1.read_parameters(stream)
&& fc_2.read_parameters(stream);
}
// Write network parameters
bool write_parameters(std::ostream& stream) const {
return fc_0.write_parameters(stream) && ac_0.write_parameters(stream)
&& fc_1.write_parameters(stream) && ac_1.write_parameters(stream)
&& fc_2.write_parameters(stream);
}
std::int32_t propagate(const TransformedFeatureType* transformedFeatures) {
struct alignas(CacheLineSize) Buffer {
alignas(CacheLineSize) typename decltype(fc_0)::OutputBuffer fc_0_out;
alignas(CacheLineSize) typename decltype(ac_sqr_0)::OutputType
ac_sqr_0_out[ceil_to_multiple<IndexType>(FC_0_OUTPUTS * 2, 32)];
alignas(CacheLineSize) typename decltype(ac_0)::OutputBuffer ac_0_out;
alignas(CacheLineSize) typename decltype(fc_1)::OutputBuffer fc_1_out;
alignas(CacheLineSize) typename decltype(ac_1)::OutputBuffer ac_1_out;
alignas(CacheLineSize) typename decltype(fc_2)::OutputBuffer fc_2_out;
Buffer() { std::memset(this, 0, sizeof(*this)); }
};
#if defined(__clang__) && (__APPLE__)
// workaround for a bug reported with xcode 12
static thread_local auto tlsBuffer = std::make_unique<Buffer>();
// Access TLS only once, cache result.
Buffer& buffer = *tlsBuffer;
#else
alignas(CacheLineSize) static thread_local Buffer buffer;
#endif
fc_0.propagate(transformedFeatures, buffer.fc_0_out);
ac_sqr_0.propagate(buffer.fc_0_out, buffer.ac_sqr_0_out);
ac_0.propagate(buffer.fc_0_out, buffer.ac_0_out);
std::memcpy(buffer.ac_sqr_0_out + FC_0_OUTPUTS, buffer.ac_0_out,
FC_0_OUTPUTS * sizeof(typename decltype(ac_0)::OutputType));
fc_1.propagate(buffer.ac_sqr_0_out, buffer.fc_1_out);
ac_1.propagate(buffer.fc_1_out, buffer.ac_1_out);
fc_2.propagate(buffer.ac_1_out, buffer.fc_2_out);
// buffer.fc_0_out[FC_0_OUTPUTS] is such that 1.0 is equal to 127*(1<<WeightScaleBits) in
// quantized form, but we want 1.0 to be equal to 600*OutputScale
std::int32_t fwdOut =
(buffer.fc_0_out[FC_0_OUTPUTS]) * (600 * OutputScale) / (127 * (1 << WeightScaleBits));
std::int32_t outputValue = buffer.fc_2_out[0] + fwdOut;
return outputValue;
}
};
} // namespace Stockfish::Eval::NNUE
#endif // #ifndef NNUE_ARCHITECTURE_H_INCLUDED
#endif // #ifndef NNUE_ARCHITECTURE_H_INCLUDED
+218 -98
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -21,144 +21,264 @@
#ifndef NNUE_COMMON_H_INCLUDED
#define NNUE_COMMON_H_INCLUDED
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <cstring>
#include <iostream>
#include <type_traits>
#include "../misc.h" // for IsLittleEndian
#include "../misc.h"
#if defined(USE_AVX2)
#include <immintrin.h>
#include <immintrin.h>
#elif defined(USE_SSE41)
#include <smmintrin.h>
#include <smmintrin.h>
#elif defined(USE_SSSE3)
#include <tmmintrin.h>
#include <tmmintrin.h>
#elif defined(USE_SSE2)
#include <emmintrin.h>
#elif defined(USE_MMX)
#include <mmintrin.h>
#include <emmintrin.h>
#elif defined(USE_NEON)
#include <arm_neon.h>
#include <arm_neon.h>
#endif
namespace Stockfish::Eval::NNUE {
// Version of the evaluation file
constexpr std::uint32_t Version = 0x7AF32F20u;
// Version of the evaluation file
constexpr std::uint32_t Version = 0x7AF32F20u;
// Constant used in evaluation value calculation
constexpr int OutputScale = 16;
constexpr int WeightScaleBits = 6;
// Constant used in evaluation value calculation
constexpr int OutputScale = 16;
constexpr int WeightScaleBits = 6;
// Size of cache line (in bytes)
constexpr std::size_t CacheLineSize = 64;
// Size of cache line (in bytes)
constexpr std::size_t CacheLineSize = 64;
// SIMD width (in bytes)
#if defined(USE_AVX2)
constexpr std::size_t SimdWidth = 32;
constexpr const char Leb128MagicString[] = "COMPRESSED_LEB128";
constexpr const std::size_t Leb128MagicStringSize = sizeof(Leb128MagicString) - 1;
#elif defined(USE_SSE2)
constexpr std::size_t SimdWidth = 16;
// SIMD width (in bytes)
#if defined(USE_AVX2)
constexpr std::size_t SimdWidth = 32;
#elif defined(USE_MMX)
constexpr std::size_t SimdWidth = 8;
#elif defined(USE_SSE2)
constexpr std::size_t SimdWidth = 16;
#elif defined(USE_NEON)
constexpr std::size_t SimdWidth = 16;
#endif
#elif defined(USE_NEON)
constexpr std::size_t SimdWidth = 16;
#endif
constexpr std::size_t MaxSimdWidth = 32;
constexpr std::size_t MaxSimdWidth = 32;
// Type of input feature after conversion
using TransformedFeatureType = std::uint8_t;
using IndexType = std::uint32_t;
// Type of input feature after conversion
using TransformedFeatureType = std::uint8_t;
using IndexType = std::uint32_t;
// Round n up to be a multiple of base
template <typename IntType>
constexpr IntType ceil_to_multiple(IntType n, IntType base) {
return (n + base - 1) / base * base;
}
// Round n up to be a multiple of base
template<typename IntType>
constexpr IntType ceil_to_multiple(IntType n, IntType base) {
return (n + base - 1) / base * base;
}
// read_little_endian() is our utility to read an integer (signed or unsigned, any size)
// from a stream in little-endian order. We swap the byte order after the read if
// necessary to return a result with the byte ordering of the compiling machine.
template <typename IntType>
inline IntType read_little_endian(std::istream& stream) {
IntType result;
if (IsLittleEndian)
stream.read(reinterpret_cast<char*>(&result), sizeof(IntType));
else
{
std::uint8_t u[sizeof(IntType)];
typename std::make_unsigned<IntType>::type v = 0;
// Utility to read an integer (signed or unsigned, any size)
// from a stream in little-endian order. We swap the byte order after the read if
// necessary to return a result with the byte ordering of the compiling machine.
template<typename IntType>
inline IntType read_little_endian(std::istream& stream) {
IntType result;
stream.read(reinterpret_cast<char*>(u), sizeof(IntType));
for (std::size_t i = 0; i < sizeof(IntType); ++i)
v = (v << 8) | u[sizeof(IntType) - i - 1];
if (IsLittleEndian)
stream.read(reinterpret_cast<char*>(&result), sizeof(IntType));
else
{
std::uint8_t u[sizeof(IntType)];
std::make_unsigned_t<IntType> v = 0;
std::memcpy(&result, &v, sizeof(IntType));
}
stream.read(reinterpret_cast<char*>(u), sizeof(IntType));
for (std::size_t i = 0; i < sizeof(IntType); ++i)
v = (v << 8) | u[sizeof(IntType) - i - 1];
return result;
}
std::memcpy(&result, &v, sizeof(IntType));
}
// write_little_endian() is our utility to write an integer (signed or unsigned, any size)
// to a stream in little-endian order. We swap the byte order before the write if
// necessary to always write in little endian order, independantly of the byte
// ordering of the compiling machine.
template <typename IntType>
inline void write_little_endian(std::ostream& stream, IntType value) {
return result;
}
if (IsLittleEndian)
stream.write(reinterpret_cast<const char*>(&value), sizeof(IntType));
else
{
std::uint8_t u[sizeof(IntType)];
typename std::make_unsigned<IntType>::type v = value;
std::size_t i = 0;
// if constexpr to silence the warning about shift by 8
if constexpr (sizeof(IntType) > 1)
{
// Utility to write an integer (signed or unsigned, any size)
// to a stream in little-endian order. We swap the byte order before the write if
// necessary to always write in little-endian order, independently of the byte
// ordering of the compiling machine.
template<typename IntType>
inline void write_little_endian(std::ostream& stream, IntType value) {
if (IsLittleEndian)
stream.write(reinterpret_cast<const char*>(&value), sizeof(IntType));
else
{
std::uint8_t u[sizeof(IntType)];
std::make_unsigned_t<IntType> v = value;
std::size_t i = 0;
// if constexpr to silence the warning about shift by 8
if constexpr (sizeof(IntType) > 1)
{
for (; i + 1 < sizeof(IntType); ++i)
{
u[i] = v;
u[i] = std::uint8_t(v);
v >>= 8;
}
}
u[i] = v;
}
u[i] = std::uint8_t(v);
stream.write(reinterpret_cast<char*>(u), sizeof(IntType));
}
}
stream.write(reinterpret_cast<char*>(u), sizeof(IntType));
}
}
// read_little_endian(s, out, N) : read integers in bulk from a little indian stream.
// This reads N integers from stream s and put them in array out.
template <typename IntType>
inline void read_little_endian(std::istream& stream, IntType* out, std::size_t count) {
if (IsLittleEndian)
stream.read(reinterpret_cast<char*>(out), sizeof(IntType) * count);
else
for (std::size_t i = 0; i < count; ++i)
out[i] = read_little_endian<IntType>(stream);
}
// write_little_endian(s, values, N) : write integers in bulk to a little indian stream.
// This takes N integers from array values and writes them on stream s.
template <typename IntType>
inline void write_little_endian(std::ostream& stream, const IntType* values, std::size_t count) {
if (IsLittleEndian)
stream.write(reinterpret_cast<const char*>(values), sizeof(IntType) * count);
else
for (std::size_t i = 0; i < count; ++i)
write_little_endian<IntType>(stream, values[i]);
}
// Read integers in bulk from a little-endian stream.
// This reads N integers from stream s and puts them in array out.
template<typename IntType>
inline void read_little_endian(std::istream& stream, IntType* out, std::size_t count) {
if (IsLittleEndian)
stream.read(reinterpret_cast<char*>(out), sizeof(IntType) * count);
else
for (std::size_t i = 0; i < count; ++i)
out[i] = read_little_endian<IntType>(stream);
}
// Write integers in bulk to a little-endian stream.
// This takes N integers from array values and writes them on stream s.
template<typename IntType>
inline void write_little_endian(std::ostream& stream, const IntType* values, std::size_t count) {
if (IsLittleEndian)
stream.write(reinterpret_cast<const char*>(values), sizeof(IntType) * count);
else
for (std::size_t i = 0; i < count; ++i)
write_little_endian<IntType>(stream, values[i]);
}
// Read N signed integers from the stream s, putting them in the array out.
// The stream is assumed to be compressed using the signed LEB128 format.
// See https://en.wikipedia.org/wiki/LEB128 for a description of the compression scheme.
template<typename IntType>
inline void read_leb_128(std::istream& stream, IntType* out, std::size_t count) {
// Check the presence of our LEB128 magic string
char leb128MagicString[Leb128MagicStringSize];
stream.read(leb128MagicString, Leb128MagicStringSize);
assert(strncmp(Leb128MagicString, leb128MagicString, Leb128MagicStringSize) == 0);
static_assert(std::is_signed_v<IntType>, "Not implemented for unsigned types");
const std::uint32_t BUF_SIZE = 4096;
std::uint8_t buf[BUF_SIZE];
auto bytes_left = read_little_endian<std::uint32_t>(stream);
std::uint32_t buf_pos = BUF_SIZE;
for (std::size_t i = 0; i < count; ++i)
{
IntType result = 0;
size_t shift = 0;
do
{
if (buf_pos == BUF_SIZE)
{
stream.read(reinterpret_cast<char*>(buf), std::min(bytes_left, BUF_SIZE));
buf_pos = 0;
}
std::uint8_t byte = buf[buf_pos++];
--bytes_left;
result |= (byte & 0x7f) << shift;
shift += 7;
if ((byte & 0x80) == 0)
{
out[i] = (sizeof(IntType) * 8 <= shift || (byte & 0x40) == 0)
? result
: result | ~((1 << shift) - 1);
break;
}
} while (shift < sizeof(IntType) * 8);
}
assert(bytes_left == 0);
}
// Write signed integers to a stream with LEB128 compression.
// This takes N integers from array values, compresses them with
// the LEB128 algorithm and writes the result on the stream s.
// See https://en.wikipedia.org/wiki/LEB128 for a description of the compression scheme.
template<typename IntType>
inline void write_leb_128(std::ostream& stream, const IntType* values, std::size_t count) {
// Write our LEB128 magic string
stream.write(Leb128MagicString, Leb128MagicStringSize);
static_assert(std::is_signed_v<IntType>, "Not implemented for unsigned types");
std::uint32_t byte_count = 0;
for (std::size_t i = 0; i < count; ++i)
{
IntType value = values[i];
std::uint8_t byte;
do
{
byte = value & 0x7f;
value >>= 7;
++byte_count;
} while ((byte & 0x40) == 0 ? value != 0 : value != -1);
}
write_little_endian(stream, byte_count);
const std::uint32_t BUF_SIZE = 4096;
std::uint8_t buf[BUF_SIZE];
std::uint32_t buf_pos = 0;
auto flush = [&]() {
if (buf_pos > 0)
{
stream.write(reinterpret_cast<char*>(buf), buf_pos);
buf_pos = 0;
}
};
auto write = [&](std::uint8_t byte) {
buf[buf_pos++] = byte;
if (buf_pos == BUF_SIZE)
flush();
};
for (std::size_t i = 0; i < count; ++i)
{
IntType value = values[i];
while (true)
{
std::uint8_t byte = value & 0x7f;
value >>= 7;
if ((byte & 0x40) == 0 ? value == 0 : value == -1)
{
write(byte);
break;
}
write(byte | 0x80);
}
}
flush();
}
} // namespace Stockfish::Eval::NNUE
#endif // #ifndef NNUE_COMMON_H_INCLUDED
#endif // #ifndef NNUE_COMMON_H_INCLUDED
File diff suppressed because it is too large Load Diff
-305
View File
@@ -1,305 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 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 <http://www.gnu.org/licenses/>.
*/
#include <algorithm>
#include <cassert>
#include "bitboard.h"
#include "pawns.h"
#include "position.h"
#include "thread.h"
namespace Stockfish {
namespace {
#define V Value
#define S(mg, eg) make_score(mg, eg)
// Pawn penalties
constexpr Score Backward = S( 9, 22);
constexpr Score Doubled = S(13, 51);
constexpr Score DoubledEarly = S(20, 7);
constexpr Score Isolated = S( 3, 15);
constexpr Score WeakLever = S( 4, 58);
constexpr Score WeakUnopposed = S(13, 24);
// Bonus for blocked pawns at 5th or 6th rank
constexpr Score BlockedPawn[2] = { S(-17, -6), S(-9, 2) };
constexpr Score BlockedStorm[RANK_NB] = {
S(0, 0), S(0, 0), S(75, 78), S(-8, 16), S(-6, 10), S(-6, 6), S(0, 2)
};
// Connected pawn bonus
constexpr int Connected[RANK_NB] = { 0, 5, 7, 11, 23, 48, 87 };
// Strength of pawn shelter for our king by [distance from edge][rank].
// RANK_1 = 0 is used for files where we have no pawn, or pawn is behind our king.
constexpr Value ShelterStrength[int(FILE_NB) / 2][RANK_NB] = {
{ V( -5), V( 82), V( 92), V( 54), V( 36), V( 22), V( 28) },
{ V(-44), V( 63), V( 33), V(-50), V(-30), V(-12), V( -62) },
{ V(-11), V( 77), V( 22), V( -6), V( 31), V( 8), V( -45) },
{ V(-39), V(-12), V(-29), V(-50), V(-43), V(-68), V(-164) }
};
// Danger of enemy pawns moving toward our king by [distance from edge][rank].
// RANK_1 = 0 is used for files where the enemy has no pawn, or their pawn
// is behind our king. Note that UnblockedStorm[0][1-2] accommodate opponent pawn
// on edge, likely blocked by our king.
constexpr Value UnblockedStorm[int(FILE_NB) / 2][RANK_NB] = {
{ V( 87), V(-288), V(-168), V( 96), V( 47), V( 44), V( 46) },
{ V( 42), V( -25), V( 120), V( 45), V( 34), V( -9), V( 24) },
{ V( -8), V( 51), V( 167), V( 35), V( -4), V(-16), V(-12) },
{ V(-17), V( -13), V( 100), V( 4), V( 9), V(-16), V(-31) }
};
// KingOnFile[semi-open Us][semi-open Them] contains bonuses/penalties
// for king when the king is on a semi-open or open file.
constexpr Score KingOnFile[2][2] = {{ S(-21,10), S(-7, 1) },
{ S( 0,-3), S( 9,-4) }};
#undef S
#undef V
/// evaluate() calculates a score for the static pawn structure of the given position.
/// We cannot use the location of pieces or king in this function, as the evaluation
/// of the pawn structure will be stored in a small cache for speed reasons, and will
/// be re-used even when the pieces have moved.
template<Color Us>
Score evaluate(const Position& pos, Pawns::Entry* e) {
constexpr Color Them = ~Us;
constexpr Direction Up = pawn_push(Us);
constexpr Direction Down = -Up;
Bitboard neighbours, stoppers, support, phalanx, opposed;
Bitboard lever, leverPush, blocked;
Square s;
bool backward, passed, doubled;
Score score = SCORE_ZERO;
Bitboard b = pos.pieces(Us, PAWN);
Bitboard ourPawns = pos.pieces( Us, PAWN);
Bitboard theirPawns = pos.pieces(Them, PAWN);
Bitboard doubleAttackThem = pawn_double_attacks_bb<Them>(theirPawns);
e->passedPawns[Us] = 0;
e->kingSquares[Us] = SQ_NONE;
e->pawnAttacks[Us] = e->pawnAttacksSpan[Us] = pawn_attacks_bb<Us>(ourPawns);
e->blockedCount += popcount(shift<Up>(ourPawns) & (theirPawns | doubleAttackThem));
// Loop through all pawns of the current color and score each pawn
while (b)
{
s = pop_lsb(b);
assert(pos.piece_on(s) == make_piece(Us, PAWN));
Rank r = relative_rank(Us, s);
// Flag the pawn
opposed = theirPawns & forward_file_bb(Us, s);
blocked = theirPawns & (s + Up);
stoppers = theirPawns & passed_pawn_span(Us, s);
lever = theirPawns & pawn_attacks_bb(Us, s);
leverPush = theirPawns & pawn_attacks_bb(Us, s + Up);
doubled = ourPawns & (s - Up);
neighbours = ourPawns & adjacent_files_bb(s);
phalanx = neighbours & rank_bb(s);
support = neighbours & rank_bb(s - Up);
if (doubled)
{
// Additional doubled penalty if none of their pawns is fixed
if (!(ourPawns & shift<Down>(theirPawns | pawn_attacks_bb<Them>(theirPawns))))
score -= DoubledEarly;
}
// A pawn is backward when it is behind all pawns of the same color on
// the adjacent files and cannot safely advance.
backward = !(neighbours & forward_ranks_bb(Them, s + Up))
&& (leverPush | blocked);
// Compute additional span if pawn is not backward nor blocked
if (!backward && !blocked)
e->pawnAttacksSpan[Us] |= pawn_attack_span(Us, s);
// A pawn is passed if one of the three following conditions is true:
// (a) there is no stoppers except some levers
// (b) the only stoppers are the leverPush, but we outnumber them
// (c) there is only one front stopper which can be levered.
// (Refined in Evaluation::passed)
passed = !(stoppers ^ lever)
|| ( !(stoppers ^ leverPush)
&& popcount(phalanx) >= popcount(leverPush))
|| ( stoppers == blocked && r >= RANK_5
&& (shift<Up>(support) & ~(theirPawns | doubleAttackThem)));
passed &= !(forward_file_bb(Us, s) & ourPawns);
// Passed pawns will be properly scored later in evaluation when we have
// full attack info.
if (passed)
e->passedPawns[Us] |= s;
// Score this pawn
if (support | phalanx)
{
int v = Connected[r] * (2 + bool(phalanx) - bool(opposed))
+ 22 * popcount(support);
score += make_score(v, v * (r - 2) / 4);
}
else if (!neighbours)
{
if ( opposed
&& (ourPawns & forward_file_bb(Them, s))
&& !(theirPawns & adjacent_files_bb(s)))
score -= Doubled;
else
score -= Isolated
+ WeakUnopposed * !opposed;
}
else if (backward)
score -= Backward
+ WeakUnopposed * !opposed * bool(~(FileABB | FileHBB) & s);
if (!support)
score -= Doubled * doubled
+ WeakLever * more_than_one(lever);
if (blocked && r >= RANK_5)
score += BlockedPawn[r - RANK_5];
}
return score;
}
} // namespace
namespace Pawns {
/// Pawns::probe() looks up the current position's pawns configuration in
/// the pawns hash table. It returns a pointer to the Entry if the position
/// is found. Otherwise a new Entry is computed and stored there, so we don't
/// have to recompute all when the same pawns configuration occurs again.
Entry* probe(const Position& pos) {
Key key = pos.pawn_key();
Entry* e = pos.this_thread()->pawnsTable[key];
if (e->key == key)
return e;
e->key = key;
e->blockedCount = 0;
e->scores[WHITE] = evaluate<WHITE>(pos, e);
e->scores[BLACK] = evaluate<BLACK>(pos, e);
return e;
}
/// Entry::evaluate_shelter() calculates the shelter bonus and the storm
/// penalty for a king, looking at the king file and the two closest files.
template<Color Us>
Score Entry::evaluate_shelter(const Position& pos, Square ksq) const {
constexpr Color Them = ~Us;
Bitboard b = pos.pieces(PAWN) & ~forward_ranks_bb(Them, ksq);
Bitboard ourPawns = b & pos.pieces(Us) & ~pawnAttacks[Them];
Bitboard theirPawns = b & pos.pieces(Them);
Score bonus = make_score(5, 5);
File center = std::clamp(file_of(ksq), FILE_B, FILE_G);
for (File f = File(center - 1); f <= File(center + 1); ++f)
{
b = ourPawns & file_bb(f);
int ourRank = b ? relative_rank(Us, frontmost_sq(Them, b)) : 0;
b = theirPawns & file_bb(f);
int theirRank = b ? relative_rank(Us, frontmost_sq(Them, b)) : 0;
int d = edge_distance(f);
bonus += make_score(ShelterStrength[d][ourRank], 0);
if (ourRank && (ourRank == theirRank - 1))
bonus -= BlockedStorm[theirRank];
else
bonus -= make_score(UnblockedStorm[d][theirRank], 0);
}
// King On File
bonus -= KingOnFile[pos.is_on_semiopen_file(Us, ksq)][pos.is_on_semiopen_file(Them, ksq)];
return bonus;
}
/// Entry::do_king_safety() calculates a bonus for king safety. It is called only
/// when king square changes, which is about 20% of total king_safety() calls.
template<Color Us>
Score Entry::do_king_safety(const Position& pos) {
Square ksq = pos.square<KING>(Us);
kingSquares[Us] = ksq;
castlingRights[Us] = pos.castling_rights(Us);
auto compare = [](Score a, Score b) { return mg_value(a) < mg_value(b); };
Score shelter = evaluate_shelter<Us>(pos, ksq);
// If we can castle use the bonus after castling if it is bigger
if (pos.can_castle(Us & KING_SIDE))
shelter = std::max(shelter, evaluate_shelter<Us>(pos, relative_square(Us, SQ_G1)), compare);
if (pos.can_castle(Us & QUEEN_SIDE))
shelter = std::max(shelter, evaluate_shelter<Us>(pos, relative_square(Us, SQ_C1)), compare);
// In endgame we like to bring our king near our closest pawn
Bitboard pawns = pos.pieces(Us, PAWN);
int minPawnDist = 6;
if (pawns & attacks_bb<KING>(ksq))
minPawnDist = 1;
else while (pawns)
minPawnDist = std::min(minPawnDist, distance(ksq, pop_lsb(pawns)));
return shelter - make_score(0, 16 * minPawnDist);
}
// Explicit template instantiation
template Score Entry::do_king_safety<WHITE>(const Position& pos);
template Score Entry::do_king_safety<BLACK>(const Position& pos);
} // namespace Pawns
} // namespace Stockfish
-70
View File
@@ -1,70 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 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 <http://www.gnu.org/licenses/>.
*/
#ifndef PAWNS_H_INCLUDED
#define PAWNS_H_INCLUDED
#include "misc.h"
#include "position.h"
#include "types.h"
namespace Stockfish::Pawns {
/// Pawns::Entry contains various information about a pawn structure. A lookup
/// to the pawn hash table (performed by calling the probe function) returns a
/// pointer to an Entry object.
struct Entry {
Score pawn_score(Color c) const { return scores[c]; }
Bitboard pawn_attacks(Color c) const { return pawnAttacks[c]; }
Bitboard passed_pawns(Color c) const { return passedPawns[c]; }
Bitboard pawn_attacks_span(Color c) const { return pawnAttacksSpan[c]; }
int passed_count() const { return popcount(passedPawns[WHITE] | passedPawns[BLACK]); }
int blocked_count() const { return blockedCount; }
template<Color Us>
Score king_safety(const Position& pos) {
return kingSquares[Us] == pos.square<KING>(Us) && castlingRights[Us] == pos.castling_rights(Us)
? kingSafety[Us] : (kingSafety[Us] = do_king_safety<Us>(pos));
}
template<Color Us>
Score do_king_safety(const Position& pos);
template<Color Us>
Score evaluate_shelter(const Position& pos, Square ksq) const;
Key key;
Score scores[COLOR_NB];
Bitboard passedPawns[COLOR_NB];
Bitboard pawnAttacks[COLOR_NB];
Bitboard pawnAttacksSpan[COLOR_NB];
Square kingSquares[COLOR_NB];
Score kingSafety[COLOR_NB];
int castlingRights[COLOR_NB];
int blockedCount;
};
typedef HashTable<Entry, 131072> Table;
Entry* probe(const Position& pos);
} // namespace Stockfish::Pawns
#endif // #ifndef PAWNS_H_INCLUDED
+69
View File
@@ -0,0 +1,69 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 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 <http://www.gnu.org/licenses/>.
*/
#ifndef PERFT_H_INCLUDED
#define PERFT_H_INCLUDED
#include <cstdint>
#include "movegen.h"
#include "position.h"
#include "types.h"
#include "uci.h"
namespace Stockfish {
// Utility to verify move generation. All the leaf nodes up
// to the given depth are generated and counted, and the sum is returned.
template<bool Root>
uint64_t perft(Position& pos, Depth depth) {
StateInfo st;
ASSERT_ALIGNED(&st, Eval::NNUE::CacheLineSize);
uint64_t cnt, nodes = 0;
const bool leaf = (depth == 2);
for (const auto& m : MoveList<LEGAL>(pos))
{
if (Root && depth <= 1)
cnt = 1, nodes++;
else
{
pos.do_move(m, st);
cnt = leaf ? MoveList<LEGAL>(pos).size() : perft<false>(pos, depth - 1);
nodes += cnt;
pos.undo_move(m);
}
if (Root)
sync_cout << UCI::move(m, pos.is_chess960()) << ": " << cnt << sync_endl;
}
return nodes;
}
inline void perft(const std::string& fen, Depth depth, bool isChess960) {
StateListPtr states(new std::deque<StateInfo>(1));
Position p;
p.set(fen, isChess960, &states->back());
uint64_t nodes = perft<true>(p, depth);
sync_cout << "\nNodes searched: " << nodes << "\n" << sync_endl;
}
}
#endif // PERFT_H_INCLUDED
+898 -954
View File
File diff suppressed because it is too large Load Diff
+245 -300
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -21,399 +21,344 @@
#include <cassert>
#include <deque>
#include <memory> // For std::unique_ptr
#include <iosfwd>
#include <memory>
#include <string>
#include "bitboard.h"
#include "evaluate.h"
#include "psqt.h"
#include "types.h"
#include "nnue/nnue_accumulator.h"
#include "nnue/nnue_architecture.h"
#include "types.h"
namespace Stockfish {
/// StateInfo struct stores information needed to restore a Position object to
/// its previous state when we retract a move. Whenever a move is made on the
/// board (by calling Position::do_move), a StateInfo object must be passed.
class TranspositionTable;
// StateInfo struct stores information needed to restore a Position object to
// its previous state when we retract a move. Whenever a move is made on the
// board (by calling Position::do_move), a StateInfo object must be passed.
struct StateInfo {
// Copied when making a move
Key pawnKey;
Key materialKey;
Value nonPawnMaterial[COLOR_NB];
int castlingRights;
int rule50;
int pliesFromNull;
Square epSquare;
// Copied when making a move
Key materialKey;
Key pawnKey;
Value nonPawnMaterial[COLOR_NB];
int castlingRights;
int rule50;
int pliesFromNull;
Square epSquare;
// Not copied when making a move (will be recomputed anyhow)
Key key;
Bitboard checkersBB;
StateInfo* previous;
Bitboard blockersForKing[COLOR_NB];
Bitboard pinners[COLOR_NB];
Bitboard checkSquares[PIECE_TYPE_NB];
Piece capturedPiece;
int repetition;
// Not copied when making a move (will be recomputed anyhow)
Key key;
Bitboard checkersBB;
StateInfo* previous;
Bitboard blockersForKing[COLOR_NB];
Bitboard pinners[COLOR_NB];
Bitboard checkSquares[PIECE_TYPE_NB];
Piece capturedPiece;
int repetition;
// Used by NNUE
Eval::NNUE::Accumulator accumulator;
DirtyPiece dirtyPiece;
// Used by NNUE
Eval::NNUE::Accumulator<Eval::NNUE::TransformedFeatureDimensionsBig> accumulatorBig;
Eval::NNUE::Accumulator<Eval::NNUE::TransformedFeatureDimensionsSmall> accumulatorSmall;
DirtyPiece dirtyPiece;
};
/// A list to keep track of the position states along the setup moves (from the
/// start position to the position just before the search starts). Needed by
/// 'draw by repetition' detection. Use a std::deque because pointers to
/// elements are not invalidated upon list resizing.
typedef std::unique_ptr<std::deque<StateInfo>> StateListPtr;
// A list to keep track of the position states along the setup moves (from the
// start position to the position just before the search starts). Needed by
// 'draw by repetition' detection. Use a std::deque because pointers to
// elements are not invalidated upon list resizing.
using StateListPtr = std::unique_ptr<std::deque<StateInfo>>;
/// Position class stores information regarding the board representation as
/// pieces, side to move, hash keys, castling info, etc. Important methods are
/// do_move() and undo_move(), used by the search to update node info when
/// traversing the search tree.
class Thread;
// Position class stores information regarding the board representation as
// pieces, side to move, hash keys, castling info, etc. Important methods are
// do_move() and undo_move(), used by the search to update node info when
// traversing the search tree.
class Position {
public:
static void init();
public:
static void init();
Position() = default;
Position(const Position&) = delete;
Position& operator=(const Position&) = delete;
Position() = default;
Position(const Position&) = delete;
Position& operator=(const Position&) = delete;
// FEN string input/output
Position& set(const std::string& fenStr, bool isChess960, StateInfo* si, Thread* th);
Position& set(const std::string& code, Color c, StateInfo* si);
std::string fen() const;
// FEN string input/output
Position& set(const std::string& fenStr, bool isChess960, StateInfo* si);
Position& set(const std::string& code, Color c, StateInfo* si);
std::string fen() const;
// Position representation
Bitboard pieces(PieceType pt) const;
Bitboard pieces(PieceType pt1, PieceType pt2) const;
Bitboard pieces(Color c) const;
Bitboard pieces(Color c, PieceType pt) const;
Bitboard pieces(Color c, PieceType pt1, PieceType pt2) const;
Piece piece_on(Square s) const;
Square ep_square() const;
bool empty(Square s) const;
template<PieceType Pt> int count(Color c) const;
template<PieceType Pt> int count() const;
template<PieceType Pt> Square square(Color c) const;
bool is_on_semiopen_file(Color c, Square s) const;
// Position representation
Bitboard pieces(PieceType pt = ALL_PIECES) const;
template<typename... PieceTypes>
Bitboard pieces(PieceType pt, PieceTypes... pts) const;
Bitboard pieces(Color c) const;
template<typename... PieceTypes>
Bitboard pieces(Color c, PieceTypes... pts) const;
Piece piece_on(Square s) const;
Square ep_square() const;
bool empty(Square s) const;
template<PieceType Pt>
int count(Color c) const;
template<PieceType Pt>
int count() const;
template<PieceType Pt>
Square square(Color c) const;
// Castling
CastlingRights castling_rights(Color c) const;
bool can_castle(CastlingRights cr) const;
bool castling_impeded(CastlingRights cr) const;
Square castling_rook_square(CastlingRights cr) const;
// Castling
CastlingRights castling_rights(Color c) const;
bool can_castle(CastlingRights cr) const;
bool castling_impeded(CastlingRights cr) const;
Square castling_rook_square(CastlingRights cr) const;
// Checking
Bitboard checkers() const;
Bitboard blockers_for_king(Color c) const;
Bitboard check_squares(PieceType pt) const;
Bitboard pinners(Color c) const;
// Checking
Bitboard checkers() const;
Bitboard blockers_for_king(Color c) const;
Bitboard check_squares(PieceType pt) const;
Bitboard pinners(Color c) const;
// Attacks to/from a given square
Bitboard attackers_to(Square s) const;
Bitboard attackers_to(Square s, Bitboard occupied) const;
Bitboard slider_blockers(Bitboard sliders, Square s, Bitboard& pinners) const;
// Attacks to/from a given square
Bitboard attackers_to(Square s) const;
Bitboard attackers_to(Square s, Bitboard occupied) const;
void update_slider_blockers(Color c) const;
template<PieceType Pt>
Bitboard attacks_by(Color c) const;
// Properties of moves
bool legal(Move m) const;
bool pseudo_legal(const Move m) const;
bool capture(Move m) const;
bool capture_or_promotion(Move m) const;
bool gives_check(Move m) const;
Piece moved_piece(Move m) const;
Piece captured_piece() const;
// Properties of moves
bool legal(Move m) const;
bool pseudo_legal(const Move m) const;
bool capture(Move m) const;
bool capture_stage(Move m) const;
bool gives_check(Move m) const;
Piece moved_piece(Move m) const;
Piece captured_piece() const;
// Piece specific
bool pawn_passed(Color c, Square s) const;
bool opposite_bishops() const;
int pawns_on_same_color_squares(Color c, Square s) const;
// Doing and undoing moves
void do_move(Move m, StateInfo& newSt);
void do_move(Move m, StateInfo& newSt, bool givesCheck);
void undo_move(Move m);
void do_null_move(StateInfo& newSt, TranspositionTable& tt);
void undo_null_move();
// Doing and undoing moves
void do_move(Move m, StateInfo& newSt);
void do_move(Move m, StateInfo& newSt, bool givesCheck);
void undo_move(Move m);
void do_null_move(StateInfo& newSt);
void undo_null_move();
// Static Exchange Evaluation
bool see_ge(Move m, int threshold = 0) const;
// Static Exchange Evaluation
bool see_ge(Move m, Value threshold = VALUE_ZERO) const;
// Accessing hash keys
Key key() const;
Key key_after(Move m) const;
Key material_key() const;
Key pawn_key() const;
// Accessing hash keys
Key key() const;
Key key_after(Move m) const;
Key material_key() const;
Key pawn_key() const;
// Other properties of the position
Color side_to_move() const;
int game_ply() const;
bool is_chess960() const;
bool is_draw(int ply) const;
bool has_game_cycle(int ply) const;
bool has_repeated() const;
int rule50_count() const;
Value non_pawn_material(Color c) const;
Value non_pawn_material() const;
// Other properties of the position
Color side_to_move() const;
int game_ply() const;
bool is_chess960() const;
Thread* this_thread() const;
bool is_draw(int ply) const;
bool has_game_cycle(int ply) const;
bool has_repeated() const;
int rule50_count() const;
Score psq_score() const;
Value non_pawn_material(Color c) const;
Value non_pawn_material() const;
// Position consistency check, for debugging
bool pos_is_ok() const;
void flip();
// Position consistency check, for debugging
bool pos_is_ok() const;
void flip();
// Used by NNUE
StateInfo* state() const;
// Used by NNUE
StateInfo* state() const;
void put_piece(Piece pc, Square s);
void remove_piece(Square s);
void put_piece(Piece pc, Square s);
void remove_piece(Square s);
private:
// Initialization helpers (used while setting up a position)
void set_castling_right(Color c, Square rfrom);
void set_state() const;
void set_check_info() const;
private:
// Initialization helpers (used while setting up a position)
void set_castling_right(Color c, Square rfrom);
void set_state(StateInfo* si) const;
void set_check_info(StateInfo* si) const;
// Other helpers
void move_piece(Square from, Square to);
template<bool Do>
void do_castling(Color us, Square from, Square& to, Square& rfrom, Square& rto);
template<bool AfterMove>
Key adjust_key50(Key k) const;
// Other helpers
void move_piece(Square from, Square to);
template<bool Do>
void do_castling(Color us, Square from, Square& to, Square& rfrom, Square& rto);
// Data members
Piece board[SQUARE_NB];
Bitboard byTypeBB[PIECE_TYPE_NB];
Bitboard byColorBB[COLOR_NB];
int pieceCount[PIECE_NB];
int castlingRightsMask[SQUARE_NB];
Square castlingRookSquare[CASTLING_RIGHT_NB];
Bitboard castlingPath[CASTLING_RIGHT_NB];
Thread* thisThread;
StateInfo* st;
int gamePly;
Color sideToMove;
Score psq;
bool chess960;
// Data members
Piece board[SQUARE_NB];
Bitboard byTypeBB[PIECE_TYPE_NB];
Bitboard byColorBB[COLOR_NB];
int pieceCount[PIECE_NB];
int castlingRightsMask[SQUARE_NB];
Square castlingRookSquare[CASTLING_RIGHT_NB];
Bitboard castlingPath[CASTLING_RIGHT_NB];
StateInfo* st;
int gamePly;
Color sideToMove;
bool chess960;
};
extern std::ostream& operator<<(std::ostream& os, const Position& pos);
std::ostream& operator<<(std::ostream& os, const Position& pos);
inline Color Position::side_to_move() const {
return sideToMove;
}
inline Color Position::side_to_move() const { return sideToMove; }
inline Piece Position::piece_on(Square s) const {
assert(is_ok(s));
return board[s];
assert(is_ok(s));
return board[s];
}
inline bool Position::empty(Square s) const {
return piece_on(s) == NO_PIECE;
inline bool Position::empty(Square s) const { return piece_on(s) == NO_PIECE; }
inline Piece Position::moved_piece(Move m) const { return piece_on(m.from_sq()); }
inline Bitboard Position::pieces(PieceType pt) const { return byTypeBB[pt]; }
template<typename... PieceTypes>
inline Bitboard Position::pieces(PieceType pt, PieceTypes... pts) const {
return pieces(pt) | pieces(pts...);
}
inline Piece Position::moved_piece(Move m) const {
return piece_on(from_sq(m));
inline Bitboard Position::pieces(Color c) const { return byColorBB[c]; }
template<typename... PieceTypes>
inline Bitboard Position::pieces(Color c, PieceTypes... pts) const {
return pieces(c) & pieces(pts...);
}
inline Bitboard Position::pieces(PieceType pt = ALL_PIECES) const {
return byTypeBB[pt];
template<PieceType Pt>
inline int Position::count(Color c) const {
return pieceCount[make_piece(c, Pt)];
}
inline Bitboard Position::pieces(PieceType pt1, PieceType pt2) const {
return pieces(pt1) | pieces(pt2);
template<PieceType Pt>
inline int Position::count() const {
return count<Pt>(WHITE) + count<Pt>(BLACK);
}
inline Bitboard Position::pieces(Color c) const {
return byColorBB[c];
template<PieceType Pt>
inline Square Position::square(Color c) const {
assert(count<Pt>(c) == 1);
return lsb(pieces(c, Pt));
}
inline Bitboard Position::pieces(Color c, PieceType pt) const {
return pieces(c) & pieces(pt);
}
inline Square Position::ep_square() const { return st->epSquare; }
inline Bitboard Position::pieces(Color c, PieceType pt1, PieceType pt2) const {
return pieces(c) & (pieces(pt1) | pieces(pt2));
}
template<PieceType Pt> inline int Position::count(Color c) const {
return pieceCount[make_piece(c, Pt)];
}
template<PieceType Pt> inline int Position::count() const {
return count<Pt>(WHITE) + count<Pt>(BLACK);
}
template<PieceType Pt> inline Square Position::square(Color c) const {
assert(count<Pt>(c) == 1);
return lsb(pieces(c, Pt));
}
inline Square Position::ep_square() const {
return st->epSquare;
}
inline bool Position::is_on_semiopen_file(Color c, Square s) const {
return !(pieces(c, PAWN) & file_bb(s));
}
inline bool Position::can_castle(CastlingRights cr) const {
return st->castlingRights & cr;
}
inline bool Position::can_castle(CastlingRights cr) const { return st->castlingRights & cr; }
inline CastlingRights Position::castling_rights(Color c) const {
return c & CastlingRights(st->castlingRights);
return c & CastlingRights(st->castlingRights);
}
inline bool Position::castling_impeded(CastlingRights cr) const {
assert(cr == WHITE_OO || cr == WHITE_OOO || cr == BLACK_OO || cr == BLACK_OOO);
return pieces() & castlingPath[cr];
assert(cr == WHITE_OO || cr == WHITE_OOO || cr == BLACK_OO || cr == BLACK_OOO);
return pieces() & castlingPath[cr];
}
inline Square Position::castling_rook_square(CastlingRights cr) const {
assert(cr == WHITE_OO || cr == WHITE_OOO || cr == BLACK_OO || cr == BLACK_OOO);
return castlingRookSquare[cr];
assert(cr == WHITE_OO || cr == WHITE_OOO || cr == BLACK_OO || cr == BLACK_OOO);
return castlingRookSquare[cr];
}
inline Bitboard Position::attackers_to(Square s) const {
return attackers_to(s, pieces());
inline Bitboard Position::attackers_to(Square s) const { return attackers_to(s, pieces()); }
template<PieceType Pt>
inline Bitboard Position::attacks_by(Color c) const {
if constexpr (Pt == PAWN)
return c == WHITE ? pawn_attacks_bb<WHITE>(pieces(WHITE, PAWN))
: pawn_attacks_bb<BLACK>(pieces(BLACK, PAWN));
else
{
Bitboard threats = 0;
Bitboard attackers = pieces(c, Pt);
while (attackers)
threats |= attacks_bb<Pt>(pop_lsb(attackers), pieces());
return threats;
}
}
inline Bitboard Position::checkers() const {
return st->checkersBB;
inline Bitboard Position::checkers() const { return st->checkersBB; }
inline Bitboard Position::blockers_for_king(Color c) const { return st->blockersForKing[c]; }
inline Bitboard Position::pinners(Color c) const { return st->pinners[c]; }
inline Bitboard Position::check_squares(PieceType pt) const { return st->checkSquares[pt]; }
inline Key Position::key() const { return adjust_key50<false>(st->key); }
template<bool AfterMove>
inline Key Position::adjust_key50(Key k) const {
return st->rule50 < 14 - AfterMove ? k : k ^ make_key((st->rule50 - (14 - AfterMove)) / 8);
}
inline Bitboard Position::blockers_for_king(Color c) const {
return st->blockersForKing[c];
}
inline Key Position::pawn_key() const { return st->pawnKey; }
inline Bitboard Position::pinners(Color c) const {
return st->pinners[c];
}
inline Key Position::material_key() const { return st->materialKey; }
inline Bitboard Position::check_squares(PieceType pt) const {
return st->checkSquares[pt];
}
inline bool Position::pawn_passed(Color c, Square s) const {
return !(pieces(~c, PAWN) & passed_pawn_span(c, s));
}
inline int Position::pawns_on_same_color_squares(Color c, Square s) const {
return popcount(pieces(c, PAWN) & ((DarkSquares & s) ? DarkSquares : ~DarkSquares));
}
inline Key Position::key() const {
return st->rule50 < 14 ? st->key
: st->key ^ make_key((st->rule50 - 14) / 8);
}
inline Key Position::pawn_key() const {
return st->pawnKey;
}
inline Key Position::material_key() const {
return st->materialKey;
}
inline Score Position::psq_score() const {
return psq;
}
inline Value Position::non_pawn_material(Color c) const {
return st->nonPawnMaterial[c];
}
inline Value Position::non_pawn_material(Color c) const { return st->nonPawnMaterial[c]; }
inline Value Position::non_pawn_material() const {
return non_pawn_material(WHITE) + non_pawn_material(BLACK);
return non_pawn_material(WHITE) + non_pawn_material(BLACK);
}
inline int Position::game_ply() const {
return gamePly;
}
inline int Position::game_ply() const { return gamePly; }
inline int Position::rule50_count() const {
return st->rule50;
}
inline int Position::rule50_count() const { return st->rule50; }
inline bool Position::opposite_bishops() const {
return count<BISHOP>(WHITE) == 1
&& count<BISHOP>(BLACK) == 1
&& opposite_colors(square<BISHOP>(WHITE), square<BISHOP>(BLACK));
}
inline bool Position::is_chess960() const {
return chess960;
}
inline bool Position::capture_or_promotion(Move m) const {
assert(is_ok(m));
return type_of(m) != NORMAL ? type_of(m) != CASTLING : !empty(to_sq(m));
}
inline bool Position::is_chess960() const { return chess960; }
inline bool Position::capture(Move m) const {
assert(is_ok(m));
// Castling is encoded as "king captures rook"
return (!empty(to_sq(m)) && type_of(m) != CASTLING) || type_of(m) == EN_PASSANT;
assert(m.is_ok());
return (!empty(m.to_sq()) && m.type_of() != CASTLING) || m.type_of() == EN_PASSANT;
}
inline Piece Position::captured_piece() const {
return st->capturedPiece;
// Returns true if a move is generated from the capture stage, having also
// queen promotions covered, i.e. consistency with the capture stage move generation
// is needed to avoid the generation of duplicate moves.
inline bool Position::capture_stage(Move m) const {
assert(m.is_ok());
return capture(m) || m.promotion_type() == QUEEN;
}
inline Thread* Position::this_thread() const {
return thisThread;
}
inline Piece Position::captured_piece() const { return st->capturedPiece; }
inline void Position::put_piece(Piece pc, Square s) {
board[s] = pc;
byTypeBB[ALL_PIECES] |= byTypeBB[type_of(pc)] |= s;
byColorBB[color_of(pc)] |= s;
pieceCount[pc]++;
pieceCount[make_piece(color_of(pc), ALL_PIECES)]++;
psq += PSQT::psq[pc][s];
board[s] = pc;
byTypeBB[ALL_PIECES] |= byTypeBB[type_of(pc)] |= s;
byColorBB[color_of(pc)] |= s;
pieceCount[pc]++;
pieceCount[make_piece(color_of(pc), ALL_PIECES)]++;
}
inline void Position::remove_piece(Square s) {
Piece pc = board[s];
byTypeBB[ALL_PIECES] ^= s;
byTypeBB[type_of(pc)] ^= s;
byColorBB[color_of(pc)] ^= s;
board[s] = NO_PIECE;
pieceCount[pc]--;
pieceCount[make_piece(color_of(pc), ALL_PIECES)]--;
psq -= PSQT::psq[pc][s];
Piece pc = board[s];
byTypeBB[ALL_PIECES] ^= s;
byTypeBB[type_of(pc)] ^= s;
byColorBB[color_of(pc)] ^= s;
board[s] = NO_PIECE;
pieceCount[pc]--;
pieceCount[make_piece(color_of(pc), ALL_PIECES)]--;
}
inline void Position::move_piece(Square from, Square to) {
Piece pc = board[from];
Bitboard fromTo = from | to;
byTypeBB[ALL_PIECES] ^= fromTo;
byTypeBB[type_of(pc)] ^= fromTo;
byColorBB[color_of(pc)] ^= fromTo;
board[from] = NO_PIECE;
board[to] = pc;
psq += PSQT::psq[pc][to] - PSQT::psq[pc][from];
Piece pc = board[from];
Bitboard fromTo = from | to;
byTypeBB[ALL_PIECES] ^= fromTo;
byTypeBB[type_of(pc)] ^= fromTo;
byColorBB[color_of(pc)] ^= fromTo;
board[from] = NO_PIECE;
board[to] = pc;
}
inline void Position::do_move(Move m, StateInfo& newSt) {
do_move(m, newSt, gives_check(m));
}
inline void Position::do_move(Move m, StateInfo& newSt) { do_move(m, newSt, gives_check(m)); }
inline StateInfo* Position::state() const {
inline StateInfo* Position::state() const { return st; }
return st;
}
} // namespace Stockfish
} // namespace Stockfish
#endif // #ifndef POSITION_H_INCLUDED
#endif // #ifndef POSITION_H_INCLUDED
-131
View File
@@ -1,131 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 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 <http://www.gnu.org/licenses/>.
*/
#include "psqt.h"
#include <algorithm>
#include "bitboard.h"
#include "types.h"
namespace Stockfish {
namespace
{
auto constexpr S = make_score;
// 'Bonus' contains Piece-Square parameters.
// Scores are explicit for files A to D, implicitly mirrored for E to H.
constexpr Score Bonus[][RANK_NB][int(FILE_NB) / 2] = {
{ },
{ },
{ // Knight
{ S(-175, -96), S(-92,-65), S(-74,-49), S(-73,-21) },
{ S( -77, -67), S(-41,-54), S(-27,-18), S(-15, 8) },
{ S( -61, -40), S(-17,-27), S( 6, -8), S( 12, 29) },
{ S( -35, -35), S( 8, -2), S( 40, 13), S( 49, 28) },
{ S( -34, -45), S( 13,-16), S( 44, 9), S( 51, 39) },
{ S( -9, -51), S( 22,-44), S( 58,-16), S( 53, 17) },
{ S( -67, -69), S(-27,-50), S( 4,-51), S( 37, 12) },
{ S(-201,-100), S(-83,-88), S(-56,-56), S(-26,-17) }
},
{ // Bishop
{ S(-37,-40), S(-4 ,-21), S( -6,-26), S(-16, -8) },
{ S(-11,-26), S( 6, -9), S( 13,-12), S( 3, 1) },
{ S(-5 ,-11), S( 15, -1), S( -4, -1), S( 12, 7) },
{ S(-4 ,-14), S( 8, -4), S( 18, 0), S( 27, 12) },
{ S(-8 ,-12), S( 20, -1), S( 15,-10), S( 22, 11) },
{ S(-11,-21), S( 4, 4), S( 1, 3), S( 8, 4) },
{ S(-12,-22), S(-10,-14), S( 4, -1), S( 0, 1) },
{ S(-34,-32), S( 1,-29), S(-10,-26), S(-16,-17) }
},
{ // Rook
{ S(-31, -9), S(-20,-13), S(-14,-10), S(-5, -9) },
{ S(-21,-12), S(-13, -9), S( -8, -1), S( 6, -2) },
{ S(-25, 6), S(-11, -8), S( -1, -2), S( 3, -6) },
{ S(-13, -6), S( -5, 1), S( -4, -9), S(-6, 7) },
{ S(-27, -5), S(-15, 8), S( -4, 7), S( 3, -6) },
{ S(-22, 6), S( -2, 1), S( 6, -7), S(12, 10) },
{ S( -2, 4), S( 12, 5), S( 16, 20), S(18, -5) },
{ S(-17, 18), S(-19, 0), S( -1, 19), S( 9, 13) }
},
{ // Queen
{ S( 3,-69), S(-5,-57), S(-5,-47), S( 4,-26) },
{ S(-3,-54), S( 5,-31), S( 8,-22), S(12, -4) },
{ S(-3,-39), S( 6,-18), S(13, -9), S( 7, 3) },
{ S( 4,-23), S( 5, -3), S( 9, 13), S( 8, 24) },
{ S( 0,-29), S(14, -6), S(12, 9), S( 5, 21) },
{ S(-4,-38), S(10,-18), S( 6,-11), S( 8, 1) },
{ S(-5,-50), S( 6,-27), S(10,-24), S( 8, -8) },
{ S(-2,-74), S(-2,-52), S( 1,-43), S(-2,-34) }
},
{ // King
{ S(271, 1), S(327, 45), S(271, 85), S(198, 76) },
{ S(278, 53), S(303,100), S(234,133), S(179,135) },
{ S(195, 88), S(258,130), S(169,169), S(120,175) },
{ S(164,103), S(190,156), S(138,172), S( 98,172) },
{ S(154, 96), S(179,166), S(105,199), S( 70,199) },
{ S(123, 92), S(145,172), S( 81,184), S( 31,191) },
{ S( 88, 47), S(120,121), S( 65,116), S( 33,131) },
{ S( 59, 11), S( 89, 59), S( 45, 73), S( -1, 78) }
}
};
constexpr Score PBonus[RANK_NB][FILE_NB] =
{ // Pawn (asymmetric distribution)
{ },
{ S( 2, -8), S( 4, -6), S( 11, 9), S( 18, 5), S( 16, 16), S( 21, 6), S( 9, -6), S( -3,-18) },
{ S( -9, -9), S(-15, -7), S( 11,-10), S( 15, 5), S( 31, 2), S( 23, 3), S( 6, -8), S(-20, -5) },
{ S( -3, 7), S(-20, 1), S( 8, -8), S( 19, -2), S( 39,-14), S( 17,-13), S( 2,-11), S( -5, -6) },
{ S( 11, 12), S( -4, 6), S(-11, 2), S( 2, -6), S( 11, -5), S( 0, -4), S(-12, 14), S( 5, 9) },
{ S( 3, 27), S(-11, 18), S( -6, 19), S( 22, 29), S( -8, 30), S( -5, 9), S(-14, 8), S(-11, 14) },
{ S( -7, -1), S( 6,-14), S( -2, 13), S(-11, 22), S( 4, 24), S(-14, 17), S( 10, 7), S( -9, 7) }
};
} // namespace
namespace PSQT
{
Score psq[PIECE_NB][SQUARE_NB];
// PSQT::init() initializes piece-square tables: the white halves of the tables are
// copied from Bonus[] and PBonus[], adding the piece value, then the black halves of
// the tables are initialized by flipping and changing the sign of the white scores.
void init() {
for (Piece pc : {W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING})
{
Score score = make_score(PieceValue[MG][pc], PieceValue[EG][pc]);
for (Square s = SQ_A1; s <= SQ_H8; ++s)
{
File f = File(edge_distance(file_of(s)));
psq[ pc][s] = score + (type_of(pc) == PAWN ? PBonus[rank_of(s)][file_of(s)]
: Bonus[pc][rank_of(s)][f]);
psq[~pc][flip_rank(s)] = -psq[pc][s];
}
}
}
} // namespace PSQT
} // namespace Stockfish
+1406 -1438
View File
File diff suppressed because it is too large Load Diff
+209 -63
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -19,97 +19,243 @@
#ifndef SEARCH_H_INCLUDED
#define SEARCH_H_INCLUDED
#include <array>
#include <atomic>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <vector>
#include <string>
#include "misc.h"
#include "movepick.h"
#include "position.h"
#include "syzygy/tbprobe.h"
#include "timeman.h"
#include "types.h"
namespace Stockfish {
class Position;
// Different node types, used as a template parameter
enum NodeType {
NonPV,
PV,
Root
};
class TranspositionTable;
class ThreadPool;
class OptionsMap;
namespace Search {
/// Threshold used for countermoves based pruning
constexpr int CounterMovePruneThreshold = 0;
/// Stack struct keeps track of the information we need to remember from nodes
/// shallower and deeper in the tree during the search. Each search thread has
/// its own array of Stack objects, indexed by the current ply.
// Stack struct keeps track of the information we need to remember from nodes
// shallower and deeper in the tree during the search. Each search thread has
// its own array of Stack objects, indexed by the current ply.
struct Stack {
Move* pv;
PieceToHistory* continuationHistory;
int ply;
Move currentMove;
Move excludedMove;
Move killers[2];
Value staticEval;
Depth depth;
int statScore;
int moveCount;
bool inCheck;
bool ttPv;
bool ttHit;
int doubleExtensions;
Move* pv;
PieceToHistory* continuationHistory;
int ply;
Move currentMove;
Move excludedMove;
Move killers[2];
Value staticEval;
int statScore;
int moveCount;
bool inCheck;
bool ttPv;
bool ttHit;
int multipleExtensions;
int cutoffCnt;
};
/// RootMove struct is used for moves at the root of the tree. For each root move
/// we store a score and a PV (really a refutation in the case of moves which
/// fail low). Score is normally set at -VALUE_INFINITE for all non-pv moves.
// RootMove struct is used for moves at the root of the tree. For each root move
// we store a score and a PV (really a refutation in the case of moves which
// fail low). Score is normally set at -VALUE_INFINITE for all non-pv moves.
struct RootMove {
explicit RootMove(Move m) : pv(1, m) {}
bool extract_ponder_from_tt(Position& pos);
bool operator==(const Move& m) const { return pv[0] == m; }
bool operator<(const RootMove& m) const { // Sort in descending order
return m.score != score ? m.score < score
: m.previousScore < previousScore;
}
explicit RootMove(Move m) :
pv(1, m) {}
bool extract_ponder_from_tt(const TranspositionTable& tt, Position& pos);
bool operator==(const Move& m) const { return pv[0] == m; }
// Sort in descending order
bool operator<(const RootMove& m) const {
return m.score != score ? m.score < score : m.previousScore < previousScore;
}
Value score = -VALUE_INFINITE;
Value previousScore = -VALUE_INFINITE;
int selDepth = 0;
int tbRank = 0;
Value tbScore;
std::vector<Move> pv;
Value score = -VALUE_INFINITE;
Value previousScore = -VALUE_INFINITE;
Value averageScore = -VALUE_INFINITE;
Value uciScore = -VALUE_INFINITE;
bool scoreLowerbound = false;
bool scoreUpperbound = false;
int selDepth = 0;
int tbRank = 0;
Value tbScore;
std::vector<Move> pv;
};
typedef std::vector<RootMove> RootMoves;
using RootMoves = std::vector<RootMove>;
/// LimitsType struct stores information sent by GUI about available time to
/// search the current move, maximum depth/time, or if we are in analysis mode.
// LimitsType struct stores information sent by GUI about available time to
// search the current move, maximum depth/time, or if we are in analysis mode.
struct LimitsType {
LimitsType() { // Init explicitly due to broken value-initialization of non POD in MSVC
time[WHITE] = time[BLACK] = inc[WHITE] = inc[BLACK] = npmsec = movetime = TimePoint(0);
movestogo = depth = mate = perft = infinite = 0;
nodes = 0;
}
// Init explicitly due to broken value-initialization of non POD in MSVC
LimitsType() {
time[WHITE] = time[BLACK] = inc[WHITE] = inc[BLACK] = npmsec = movetime = TimePoint(0);
movestogo = depth = mate = perft = infinite = 0;
nodes = 0;
}
bool use_time_management() const {
return time[WHITE] || time[BLACK];
}
bool use_time_management() const { return time[WHITE] || time[BLACK]; }
std::vector<Move> searchmoves;
TimePoint time[COLOR_NB], inc[COLOR_NB], npmsec, movetime, startTime;
int movestogo, depth, mate, perft, infinite;
int64_t nodes;
std::vector<Move> searchmoves;
TimePoint time[COLOR_NB], inc[COLOR_NB], npmsec, movetime, startTime;
int movestogo, depth, mate, perft, infinite;
uint64_t nodes;
};
extern LimitsType Limits;
void init();
void clear();
// The UCI stores the uci options, thread pool, and transposition table.
// This struct is used to easily forward data to the Search::Worker class.
struct SharedState {
SharedState(const OptionsMap& optionsMap,
ThreadPool& threadPool,
TranspositionTable& transpositionTable) :
options(optionsMap),
threads(threadPool),
tt(transpositionTable) {}
} // namespace Search
const OptionsMap& options;
ThreadPool& threads;
TranspositionTable& tt;
};
} // namespace Stockfish
class Worker;
#endif // #ifndef SEARCH_H_INCLUDED
// Null Object Pattern, implement a common interface for the SearchManagers.
// A Null Object will be given to non-mainthread workers.
class ISearchManager {
public:
virtual ~ISearchManager() {}
virtual void check_time(Search::Worker&) = 0;
};
// SearchManager manages the search from the main thread. It is responsible for
// keeping track of the time, and storing data strictly related to the main thread.
class SearchManager: public ISearchManager {
public:
void check_time(Search::Worker& worker) override;
std::string pv(const Search::Worker& worker,
const ThreadPool& threads,
const TranspositionTable& tt,
Depth depth) const;
Stockfish::TimeManagement tm;
int callsCnt;
std::atomic_bool ponder;
std::array<Value, 4> iterValue;
double previousTimeReduction;
Value bestPreviousScore;
Value bestPreviousAverageScore;
bool stopOnPonderhit;
size_t id;
};
class NullSearchManager: public ISearchManager {
public:
void check_time(Search::Worker&) override {}
};
// Search::Worker is the class that does the actual search.
// It is instantiated once per thread, and it is responsible for keeping track
// of the search history, and storing data required for the search.
class Worker {
public:
Worker(SharedState&, std::unique_ptr<ISearchManager>, size_t);
// Called at instantiation to initialize Reductions tables
// Reset histories, usually before a new game
void clear();
// Called when the program receives the UCI 'go' command.
// It searches from the root position and outputs the "bestmove".
void start_searching();
bool is_mainthread() const { return thread_idx == 0; }
// Public because they need to be updatable by the stats
CounterMoveHistory counterMoves;
ButterflyHistory mainHistory;
CapturePieceToHistory captureHistory;
ContinuationHistory continuationHistory[2][2];
PawnHistory pawnHistory;
CorrectionHistory correctionHistory;
private:
void iterative_deepening();
// Main search function for both PV and non-PV nodes
template<NodeType nodeType>
Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, bool cutNode);
// Quiescence search function, which is called by the main search
template<NodeType nodeType>
Value qsearch(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth = 0);
Depth reduction(bool i, Depth d, int mn, int delta);
// Get a pointer to the search manager, only allowed to be called by the
// main thread.
SearchManager* main_manager() const {
assert(thread_idx == 0);
return static_cast<SearchManager*>(manager.get());
}
std::array<std::array<uint64_t, SQUARE_NB>, SQUARE_NB> effort;
LimitsType limits;
size_t pvIdx, pvLast;
std::atomic<uint64_t> nodes, tbHits, bestMoveChanges;
int selDepth, nmpMinPly;
Value optimism[COLOR_NB];
Position rootPos;
StateInfo rootState;
RootMoves rootMoves;
Depth rootDepth, completedDepth;
Value rootDelta;
size_t thread_idx;
// Reductions lookup table initialized at startup
std::array<int, MAX_MOVES> reductions; // [depth or moveNumber]
// The main thread has a SearchManager, the others have a NullSearchManager
std::unique_ptr<ISearchManager> manager;
Tablebases::Config tbConfig;
const OptionsMap& options;
ThreadPool& threads;
TranspositionTable& tt;
friend class Stockfish::ThreadPool;
friend class SearchManager;
};
} // namespace Search
} // namespace Stockfish
#endif // #ifndef SEARCH_H_INCLUDED
-341
View File
@@ -1,341 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 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 <http://www.gnu.org/licenses/>.
*/
#ifndef STOCKFISH_SIMD_H_INCLUDED
#define STOCKFISH_SIMD_H_INCLUDED
#if defined(USE_AVX2)
# include <immintrin.h>
#elif defined(USE_SSE41)
# include <smmintrin.h>
#elif defined(USE_SSSE3)
# include <tmmintrin.h>
#elif defined(USE_SSE2)
# include <emmintrin.h>
#elif defined(USE_MMX)
# include <mmintrin.h>
#elif defined(USE_NEON)
# include <arm_neon.h>
#endif
// The inline asm is only safe for GCC, where it is necessary to get good codegen.
// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101693
// Clang does fine without it.
// Play around here: https://godbolt.org/z/7EWqrYq51
#if (defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER))
#define USE_INLINE_ASM
#endif
namespace Stockfish::Simd {
#if defined (USE_AVX512)
[[maybe_unused]] static int m512_hadd(__m512i sum, int bias) {
return _mm512_reduce_add_epi32(sum) + bias;
}
/*
Parameters:
sum0 = [zmm0.i128[0], zmm0.i128[1], zmm0.i128[2], zmm0.i128[3]]
sum1 = [zmm1.i128[0], zmm1.i128[1], zmm1.i128[2], zmm1.i128[3]]
sum2 = [zmm2.i128[0], zmm2.i128[1], zmm2.i128[2], zmm2.i128[3]]
sum3 = [zmm3.i128[0], zmm3.i128[1], zmm3.i128[2], zmm3.i128[3]]
Returns:
ret = [
reduce_add_epi32(zmm0.i128[0]), reduce_add_epi32(zmm1.i128[0]), reduce_add_epi32(zmm2.i128[0]), reduce_add_epi32(zmm3.i128[0]),
reduce_add_epi32(zmm0.i128[1]), reduce_add_epi32(zmm1.i128[1]), reduce_add_epi32(zmm2.i128[1]), reduce_add_epi32(zmm3.i128[1]),
reduce_add_epi32(zmm0.i128[2]), reduce_add_epi32(zmm1.i128[2]), reduce_add_epi32(zmm2.i128[2]), reduce_add_epi32(zmm3.i128[2]),
reduce_add_epi32(zmm0.i128[3]), reduce_add_epi32(zmm1.i128[3]), reduce_add_epi32(zmm2.i128[3]), reduce_add_epi32(zmm3.i128[3])
]
*/
[[maybe_unused]] static __m512i m512_hadd128x16_interleave(
__m512i sum0, __m512i sum1, __m512i sum2, __m512i sum3) {
__m512i sum01a = _mm512_unpacklo_epi32(sum0, sum1);
__m512i sum01b = _mm512_unpackhi_epi32(sum0, sum1);
__m512i sum23a = _mm512_unpacklo_epi32(sum2, sum3);
__m512i sum23b = _mm512_unpackhi_epi32(sum2, sum3);
__m512i sum01 = _mm512_add_epi32(sum01a, sum01b);
__m512i sum23 = _mm512_add_epi32(sum23a, sum23b);
__m512i sum0123a = _mm512_unpacklo_epi64(sum01, sum23);
__m512i sum0123b = _mm512_unpackhi_epi64(sum01, sum23);
return _mm512_add_epi32(sum0123a, sum0123b);
}
[[maybe_unused]] static __m128i m512_haddx4(
__m512i sum0, __m512i sum1, __m512i sum2, __m512i sum3,
__m128i bias) {
__m512i sum = m512_hadd128x16_interleave(sum0, sum1, sum2, sum3);
__m256i sum256lo = _mm512_castsi512_si256(sum);
__m256i sum256hi = _mm512_extracti64x4_epi64(sum, 1);
sum256lo = _mm256_add_epi32(sum256lo, sum256hi);
__m128i sum128lo = _mm256_castsi256_si128(sum256lo);
__m128i sum128hi = _mm256_extracti128_si256(sum256lo, 1);
return _mm_add_epi32(_mm_add_epi32(sum128lo, sum128hi), bias);
}
[[maybe_unused]] static void m512_add_dpbusd_epi32(
__m512i& acc,
__m512i a,
__m512i b) {
# if defined (USE_VNNI)
# if defined (USE_INLINE_ASM)
asm(
"vpdpbusd %[b], %[a], %[acc]\n\t"
: [acc]"+v"(acc)
: [a]"v"(a), [b]"vm"(b)
);
# else
acc = _mm512_dpbusd_epi32(acc, a, b);
# endif
# else
# if defined (USE_INLINE_ASM)
__m512i tmp = _mm512_maddubs_epi16(a, b);
asm(
"vpmaddwd %[tmp], %[ones], %[tmp]\n\t"
"vpaddd %[acc], %[tmp], %[acc]\n\t"
: [acc]"+v"(acc), [tmp]"+&v"(tmp)
: [ones]"v"(_mm512_set1_epi16(1))
);
# else
__m512i product0 = _mm512_maddubs_epi16(a, b);
product0 = _mm512_madd_epi16(product0, _mm512_set1_epi16(1));
acc = _mm512_add_epi32(acc, product0);
# endif
# endif
}
[[maybe_unused]] static void m512_add_dpbusd_epi32x2(
__m512i& acc,
__m512i a0, __m512i b0,
__m512i a1, __m512i b1) {
# if defined (USE_VNNI)
# if defined (USE_INLINE_ASM)
asm(
"vpdpbusd %[b0], %[a0], %[acc]\n\t"
"vpdpbusd %[b1], %[a1], %[acc]\n\t"
: [acc]"+v"(acc)
: [a0]"v"(a0), [b0]"vm"(b0), [a1]"v"(a1), [b1]"vm"(b1)
);
# else
acc = _mm512_dpbusd_epi32(acc, a0, b0);
acc = _mm512_dpbusd_epi32(acc, a1, b1);
# endif
# else
# if defined (USE_INLINE_ASM)
__m512i tmp0 = _mm512_maddubs_epi16(a0, b0);
__m512i tmp1 = _mm512_maddubs_epi16(a1, b1);
asm(
"vpaddsw %[tmp0], %[tmp1], %[tmp0]\n\t"
"vpmaddwd %[tmp0], %[ones], %[tmp0]\n\t"
"vpaddd %[acc], %[tmp0], %[acc]\n\t"
: [acc]"+v"(acc), [tmp0]"+&v"(tmp0)
: [tmp1]"v"(tmp1), [ones]"v"(_mm512_set1_epi16(1))
);
# else
__m512i product0 = _mm512_maddubs_epi16(a0, b0);
__m512i product1 = _mm512_maddubs_epi16(a1, b1);
product0 = _mm512_adds_epi16(product0, product1);
product0 = _mm512_madd_epi16(product0, _mm512_set1_epi16(1));
acc = _mm512_add_epi32(acc, product0);
# endif
# endif
}
#endif
#if defined (USE_AVX2)
[[maybe_unused]] static int m256_hadd(__m256i sum, int bias) {
__m128i sum128 = _mm_add_epi32(_mm256_castsi256_si128(sum), _mm256_extracti128_si256(sum, 1));
sum128 = _mm_add_epi32(sum128, _mm_shuffle_epi32(sum128, _MM_PERM_BADC));
sum128 = _mm_add_epi32(sum128, _mm_shuffle_epi32(sum128, _MM_PERM_CDAB));
return _mm_cvtsi128_si32(sum128) + bias;
}
[[maybe_unused]] static __m128i m256_haddx4(
__m256i sum0, __m256i sum1, __m256i sum2, __m256i sum3,
__m128i bias) {
sum0 = _mm256_hadd_epi32(sum0, sum1);
sum2 = _mm256_hadd_epi32(sum2, sum3);
sum0 = _mm256_hadd_epi32(sum0, sum2);
__m128i sum128lo = _mm256_castsi256_si128(sum0);
__m128i sum128hi = _mm256_extracti128_si256(sum0, 1);
return _mm_add_epi32(_mm_add_epi32(sum128lo, sum128hi), bias);
}
[[maybe_unused]] static void m256_add_dpbusd_epi32(
__m256i& acc,
__m256i a,
__m256i b) {
# if defined (USE_VNNI)
# if defined (USE_INLINE_ASM)
asm(
"vpdpbusd %[b], %[a], %[acc]\n\t"
: [acc]"+v"(acc)
: [a]"v"(a), [b]"vm"(b)
);
# else
acc = _mm256_dpbusd_epi32(acc, a, b);
# endif
# else
# if defined (USE_INLINE_ASM)
__m256i tmp = _mm256_maddubs_epi16(a, b);
asm(
"vpmaddwd %[tmp], %[ones], %[tmp]\n\t"
"vpaddd %[acc], %[tmp], %[acc]\n\t"
: [acc]"+v"(acc), [tmp]"+&v"(tmp)
: [ones]"v"(_mm256_set1_epi16(1))
);
# else
__m256i product0 = _mm256_maddubs_epi16(a, b);
product0 = _mm256_madd_epi16(product0, _mm256_set1_epi16(1));
acc = _mm256_add_epi32(acc, product0);
# endif
# endif
}
[[maybe_unused]] static void m256_add_dpbusd_epi32x2(
__m256i& acc,
__m256i a0, __m256i b0,
__m256i a1, __m256i b1) {
# if defined (USE_VNNI)
# if defined (USE_INLINE_ASM)
asm(
"vpdpbusd %[b0], %[a0], %[acc]\n\t"
"vpdpbusd %[b1], %[a1], %[acc]\n\t"
: [acc]"+v"(acc)
: [a0]"v"(a0), [b0]"vm"(b0), [a1]"v"(a1), [b1]"vm"(b1)
);
# else
acc = _mm256_dpbusd_epi32(acc, a0, b0);
acc = _mm256_dpbusd_epi32(acc, a1, b1);
# endif
# else
# if defined (USE_INLINE_ASM)
__m256i tmp0 = _mm256_maddubs_epi16(a0, b0);
__m256i tmp1 = _mm256_maddubs_epi16(a1, b1);
asm(
"vpaddsw %[tmp0], %[tmp1], %[tmp0]\n\t"
"vpmaddwd %[tmp0], %[ones], %[tmp0]\n\t"
"vpaddd %[acc], %[tmp0], %[acc]\n\t"
: [acc]"+v"(acc), [tmp0]"+&v"(tmp0)
: [tmp1]"v"(tmp1), [ones]"v"(_mm256_set1_epi16(1))
);
# else
__m256i product0 = _mm256_maddubs_epi16(a0, b0);
__m256i product1 = _mm256_maddubs_epi16(a1, b1);
product0 = _mm256_adds_epi16(product0, product1);
product0 = _mm256_madd_epi16(product0, _mm256_set1_epi16(1));
acc = _mm256_add_epi32(acc, product0);
# endif
# endif
}
#endif
#if defined (USE_SSSE3)
[[maybe_unused]] static int m128_hadd(__m128i sum, int bias) {
sum = _mm_add_epi32(sum, _mm_shuffle_epi32(sum, 0x4E)); //_MM_PERM_BADC
sum = _mm_add_epi32(sum, _mm_shuffle_epi32(sum, 0xB1)); //_MM_PERM_CDAB
return _mm_cvtsi128_si32(sum) + bias;
}
[[maybe_unused]] static __m128i m128_haddx4(
__m128i sum0, __m128i sum1, __m128i sum2, __m128i sum3,
__m128i bias) {
sum0 = _mm_hadd_epi32(sum0, sum1);
sum2 = _mm_hadd_epi32(sum2, sum3);
sum0 = _mm_hadd_epi32(sum0, sum2);
return _mm_add_epi32(sum0, bias);
}
[[maybe_unused]] static void m128_add_dpbusd_epi32(
__m128i& acc,
__m128i a,
__m128i b) {
# if defined (USE_INLINE_ASM)
__m128i tmp = _mm_maddubs_epi16(a, b);
asm(
"pmaddwd %[ones], %[tmp]\n\t"
"paddd %[tmp], %[acc]\n\t"
: [acc]"+v"(acc), [tmp]"+&v"(tmp)
: [ones]"v"(_mm_set1_epi16(1))
);
# else
__m128i product0 = _mm_maddubs_epi16(a, b);
product0 = _mm_madd_epi16(product0, _mm_set1_epi16(1));
acc = _mm_add_epi32(acc, product0);
# endif
}
[[maybe_unused]] static void m128_add_dpbusd_epi32x2(
__m128i& acc,
__m128i a0, __m128i b0,
__m128i a1, __m128i b1) {
# if defined (USE_INLINE_ASM)
__m128i tmp0 = _mm_maddubs_epi16(a0, b0);
__m128i tmp1 = _mm_maddubs_epi16(a1, b1);
asm(
"paddsw %[tmp1], %[tmp0]\n\t"
"pmaddwd %[ones], %[tmp0]\n\t"
"paddd %[tmp0], %[acc]\n\t"
: [acc]"+v"(acc), [tmp0]"+&v"(tmp0)
: [tmp1]"v"(tmp1), [ones]"v"(_mm_set1_epi16(1))
);
# else
__m128i product0 = _mm_maddubs_epi16(a0, b0);
__m128i product1 = _mm_maddubs_epi16(a1, b1);
product0 = _mm_adds_epi16(product0, product1);
product0 = _mm_madd_epi16(product0, _mm_set1_epi16(1));
acc = _mm_add_epi32(acc, product0);
# endif
}
#endif
}
#endif // STOCKFISH_SIMD_H_INCLUDED
+490 -377
View File
File diff suppressed because it is too large Load Diff
+38 -41
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -19,60 +19,57 @@
#ifndef TBPROBE_H
#define TBPROBE_H
#include <ostream>
#include <string>
#include <vector>
#include "../search.h"
namespace Stockfish {
class Position;
class OptionsMap;
using Depth = int;
namespace Search {
struct RootMove;
using RootMoves = std::vector<RootMove>;
}
}
namespace Stockfish::Tablebases {
enum WDLScore {
WDLLoss = -2, // Loss
WDLBlessedLoss = -1, // Loss, but draw under 50-move rule
WDLDraw = 0, // Draw
WDLCursedWin = 1, // Win, but draw under 50-move rule
WDLWin = 2, // Win
struct Config {
int cardinality = 0;
bool rootInTB = false;
bool useRule50 = false;
Depth probeDepth = 0;
};
WDLScoreNone = -1000
enum WDLScore {
WDLLoss = -2, // Loss
WDLBlessedLoss = -1, // Loss, but draw under 50-move rule
WDLDraw = 0, // Draw
WDLCursedWin = 1, // Win, but draw under 50-move rule
WDLWin = 2, // Win
};
// Possible states after a probing operation
enum ProbeState {
FAIL = 0, // Probe failed (missing file table)
OK = 1, // Probe succesful
CHANGE_STM = -1, // DTZ should check the other side
ZEROING_BEST_MOVE = 2 // Best move zeroes DTZ (capture or pawn move)
FAIL = 0, // Probe failed (missing file table)
OK = 1, // Probe successful
CHANGE_STM = -1, // DTZ should check the other side
ZEROING_BEST_MOVE = 2 // Best move zeroes DTZ (capture or pawn move)
};
extern int MaxCardinality;
void init(const std::string& paths);
void init(const std::string& paths);
WDLScore probe_wdl(Position& pos, ProbeState* result);
int probe_dtz(Position& pos, ProbeState* result);
bool root_probe(Position& pos, Search::RootMoves& rootMoves);
bool root_probe_wdl(Position& pos, Search::RootMoves& rootMoves);
void rank_root_moves(Position& pos, Search::RootMoves& rootMoves);
int probe_dtz(Position& pos, ProbeState* result);
bool root_probe(Position& pos, Search::RootMoves& rootMoves, bool rule50);
bool root_probe_wdl(Position& pos, Search::RootMoves& rootMoves, bool rule50);
Config rank_root_moves(const OptionsMap& options, Position& pos, Search::RootMoves& rootMoves);
inline std::ostream& operator<<(std::ostream& os, const WDLScore v) {
os << (v == WDLLoss ? "Loss" :
v == WDLBlessedLoss ? "Blessed loss" :
v == WDLDraw ? "Draw" :
v == WDLCursedWin ? "Cursed win" :
v == WDLWin ? "Win" : "None");
return os;
}
inline std::ostream& operator<<(std::ostream& os, const ProbeState v) {
os << (v == FAIL ? "Failed" :
v == OK ? "Success" :
v == CHANGE_STM ? "Probed opponent side" :
v == ZEROING_BEST_MOVE ? "Best move zeroes DTZ" : "None");
return os;
}
} // namespace Stockfish::Tablebases
} // namespace Stockfish::Tablebases
#endif
+192 -159
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -16,227 +16,260 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cassert>
#include "thread.h"
#include <algorithm> // For std::count
#include <algorithm>
#include <cassert>
#include <deque>
#include <memory>
#include <unordered_map>
#include <utility>
#include <array>
#include "misc.h"
#include "movegen.h"
#include "search.h"
#include "thread.h"
#include "uci.h"
#include "syzygy/tbprobe.h"
#include "timeman.h"
#include "tt.h"
#include "types.h"
#include "ucioption.h"
namespace Stockfish {
ThreadPool Threads; // Global object
// Constructor launches the thread and waits until it goes to sleep
// in idle_loop(). Note that 'searching' and 'exit' should be already set.
Thread::Thread(Search::SharedState& sharedState,
std::unique_ptr<Search::ISearchManager> sm,
size_t n) :
worker(std::make_unique<Search::Worker>(sharedState, std::move(sm), n)),
idx(n),
nthreads(sharedState.options["Threads"]),
stdThread(&Thread::idle_loop, this) {
/// Thread constructor launches the thread and waits until it goes to sleep
/// in idle_loop(). Note that 'searching' and 'exit' should be already set.
Thread::Thread(size_t n) : idx(n), stdThread(&Thread::idle_loop, this) {
wait_for_search_finished();
wait_for_search_finished();
}
/// Thread destructor wakes up the thread in idle_loop() and waits
/// for its termination. Thread should be already waiting.
// Destructor wakes up the thread in idle_loop() and waits
// for its termination. Thread should be already waiting.
Thread::~Thread() {
assert(!searching);
assert(!searching);
exit = true;
start_searching();
stdThread.join();
exit = true;
start_searching();
stdThread.join();
}
/// Thread::clear() reset histories, usually before a new game
void Thread::clear() {
counterMoves.fill(MOVE_NONE);
mainHistory.fill(0);
lowPlyHistory.fill(0);
captureHistory.fill(0);
for (bool inCheck : { false, true })
for (StatsType c : { NoCaptures, Captures })
{
for (auto& to : continuationHistory[inCheck][c])
for (auto& h : to)
h->fill(0);
continuationHistory[inCheck][c][NO_PIECE][0]->fill(Search::CounterMovePruneThreshold - 1);
}
}
/// Thread::start_searching() wakes up the thread that will start the search
// Wakes up the thread that will start the search
void Thread::start_searching() {
std::lock_guard<std::mutex> lk(mutex);
searching = true;
cv.notify_one(); // Wake up the thread in idle_loop()
mutex.lock();
searching = true;
mutex.unlock(); // Unlock before notifying saves a few CPU-cycles
cv.notify_one(); // Wake up the thread in idle_loop()
}
/// Thread::wait_for_search_finished() blocks on the condition variable
/// until the thread has finished searching.
// Blocks on the condition variable
// until the thread has finished searching.
void Thread::wait_for_search_finished() {
std::unique_lock<std::mutex> lk(mutex);
cv.wait(lk, [&]{ return !searching; });
std::unique_lock<std::mutex> lk(mutex);
cv.wait(lk, [&] { return !searching; });
}
/// Thread::idle_loop() is where the thread is parked, blocked on the
/// condition variable, when it has no work to do.
// Thread gets parked here, blocked on the
// condition variable, when it has no work to do.
void Thread::idle_loop() {
// If OS already scheduled us on a different group than 0 then don't overwrite
// the choice, eventually we are one of many one-threaded processes running on
// some Windows NUMA hardware, for instance in fishtest. To make it simple,
// just check if running threads are below a threshold, in this case all this
// NUMA machinery is not needed.
if (Options["Threads"] > 8)
WinProcGroup::bindThisThread(idx);
// If OS already scheduled us on a different group than 0 then don't overwrite
// the choice, eventually we are one of many one-threaded processes running on
// some Windows NUMA hardware, for instance in fishtest. To make it simple,
// just check if running threads are below a threshold, in this case, all this
// NUMA machinery is not needed.
if (nthreads > 8)
WinProcGroup::bindThisThread(idx);
while (true)
{
std::unique_lock<std::mutex> lk(mutex);
searching = false;
cv.notify_one(); // Wake up anyone waiting for search finished
cv.wait(lk, [&]{ return searching; });
while (true)
{
std::unique_lock<std::mutex> lk(mutex);
searching = false;
cv.notify_one(); // Wake up anyone waiting for search finished
cv.wait(lk, [&] { return searching; });
if (exit)
return;
if (exit)
return;
lk.unlock();
lk.unlock();
search();
}
worker->start_searching();
}
}
/// ThreadPool::set() creates/destroys threads to match the requested number.
/// Created and launched threads will immediately go to sleep in idle_loop.
/// Upon resizing, threads are recreated to allow for binding if necessary.
// Creates/destroys threads to match the requested number.
// Created and launched threads will immediately go to sleep in idle_loop.
// Upon resizing, threads are recreated to allow for binding if necessary.
void ThreadPool::set(Search::SharedState sharedState) {
void ThreadPool::set(size_t requested) {
if (threads.size() > 0) // destroy any existing thread(s)
{
main_thread()->wait_for_search_finished();
if (size() > 0) // destroy any existing thread(s)
{
main()->wait_for_search_finished();
while (threads.size() > 0)
delete threads.back(), threads.pop_back();
}
while (size() > 0)
delete back(), pop_back();
}
const size_t requested = sharedState.options["Threads"];
if (requested > 0) // create new thread(s)
{
push_back(new MainThread(0));
if (requested > 0) // create new thread(s)
{
threads.push_back(new Thread(
sharedState, std::unique_ptr<Search::ISearchManager>(new Search::SearchManager()), 0));
while (size() < requested)
push_back(new Thread(size()));
clear();
// Reallocate the hash with the new threadpool size
TT.resize(size_t(Options["Hash"]));
while (threads.size() < requested)
threads.push_back(new Thread(
sharedState, std::unique_ptr<Search::ISearchManager>(new Search::NullSearchManager()),
threads.size()));
clear();
// Init thread number dependent search params.
Search::init();
}
main_thread()->wait_for_search_finished();
// Reallocate the hash with the new threadpool size
sharedState.tt.resize(sharedState.options["Hash"], requested);
}
}
/// ThreadPool::clear() sets threadPool data to initial values
// Sets threadPool data to initial values
void ThreadPool::clear() {
for (Thread* th : *this)
th->clear();
for (Thread* th : threads)
th->worker->clear();
main()->callsCnt = 0;
main()->bestPreviousScore = VALUE_INFINITE;
main()->previousTimeReduction = 1.0;
main_manager()->callsCnt = 0;
main_manager()->bestPreviousScore = VALUE_INFINITE;
main_manager()->bestPreviousAverageScore = VALUE_INFINITE;
main_manager()->previousTimeReduction = 1.0;
main_manager()->tm.clear();
}
/// ThreadPool::start_thinking() wakes up main thread waiting in idle_loop() and
/// returns immediately. Main thread will wake up other threads and start the search.
// Wakes up main thread waiting in idle_loop() and
// returns immediately. Main thread will wake up other threads and start the search.
void ThreadPool::start_thinking(const OptionsMap& options,
Position& pos,
StateListPtr& states,
Search::LimitsType limits,
bool ponderMode) {
void ThreadPool::start_thinking(Position& pos, StateListPtr& states,
const Search::LimitsType& limits, bool ponderMode) {
main_thread()->wait_for_search_finished();
main()->wait_for_search_finished();
main_manager()->stopOnPonderhit = stop = abortedSearch = false;
main_manager()->ponder = ponderMode;
main()->stopOnPonderhit = stop = false;
increaseDepth = true;
main()->ponder = ponderMode;
Search::Limits = limits;
Search::RootMoves rootMoves;
increaseDepth = true;
for (const auto& m : MoveList<LEGAL>(pos))
if ( limits.searchmoves.empty()
|| std::count(limits.searchmoves.begin(), limits.searchmoves.end(), m))
rootMoves.emplace_back(m);
Search::RootMoves rootMoves;
if (!rootMoves.empty())
Tablebases::rank_root_moves(pos, rootMoves);
for (const auto& m : MoveList<LEGAL>(pos))
if (limits.searchmoves.empty()
|| std::count(limits.searchmoves.begin(), limits.searchmoves.end(), m))
rootMoves.emplace_back(m);
// After ownership transfer 'states' becomes empty, so if we stop the search
// and call 'go' again without setting a new position states.get() == NULL.
assert(states.get() || setupStates.get());
Tablebases::Config tbConfig = Tablebases::rank_root_moves(options, pos, rootMoves);
if (states.get())
setupStates = std::move(states); // Ownership transfer, states is now empty
// After ownership transfer 'states' becomes empty, so if we stop the search
// and call 'go' again without setting a new position states.get() == nullptr.
assert(states.get() || setupStates.get());
// We use Position::set() to set root position across threads. But there are
// some StateInfo fields (previous, pliesFromNull, capturedPiece) that cannot
// be deduced from a fen string, so set() clears them and they are set from
// setupStates->back() later. The rootState is per thread, earlier states are shared
// since they are read-only.
for (Thread* th : *this)
{
th->nodes = th->tbHits = th->nmpMinPly = th->bestMoveChanges = 0;
th->rootDepth = th->completedDepth = 0;
th->rootMoves = rootMoves;
th->rootPos.set(pos.fen(), pos.is_chess960(), &th->rootState, th);
th->rootState = setupStates->back();
}
if (states.get())
setupStates = std::move(states); // Ownership transfer, states is now empty
main()->start_searching();
// We use Position::set() to set root position across threads. But there are
// some StateInfo fields (previous, pliesFromNull, capturedPiece) that cannot
// be deduced from a fen string, so set() clears them and they are set from
// setupStates->back() later. The rootState is per thread, earlier states are shared
// since they are read-only.
for (Thread* th : threads)
{
th->worker->limits = limits;
th->worker->nodes = th->worker->tbHits = th->worker->nmpMinPly =
th->worker->bestMoveChanges = 0;
th->worker->rootDepth = th->worker->completedDepth = 0;
th->worker->rootMoves = rootMoves;
th->worker->rootPos.set(pos.fen(), pos.is_chess960(), &th->worker->rootState);
th->worker->rootState = setupStates->back();
th->worker->tbConfig = tbConfig;
th->worker->effort = {};
}
main_thread()->start_searching();
}
Thread* ThreadPool::get_best_thread() const {
Thread* bestThread = front();
std::map<Move, int64_t> votes;
Value minScore = VALUE_NONE;
Thread* bestThread = threads.front();
Value minScore = VALUE_NONE;
// Find minimum score of all threads
for (Thread* th: *this)
minScore = std::min(minScore, th->rootMoves[0].score);
std::unordered_map<Move, int64_t, Move::MoveHash> votes(
2 * std::min(size(), bestThread->worker->rootMoves.size()));
// Find the minimum score of all threads
for (Thread* th : threads)
minScore = std::min(minScore, th->worker->rootMoves[0].score);
// Vote according to score and depth, and select the best thread
for (Thread* th : *this)
{
votes[th->rootMoves[0].pv[0]] +=
(th->rootMoves[0].score - minScore + 14) * int(th->completedDepth);
auto thread_voting_value = [minScore](Thread* th) {
return (th->worker->rootMoves[0].score - minScore + 14) * int(th->worker->completedDepth);
};
if (abs(bestThread->rootMoves[0].score) >= VALUE_TB_WIN_IN_MAX_PLY)
for (Thread* th : threads)
votes[th->worker->rootMoves[0].pv[0]] += thread_voting_value(th);
for (Thread* th : threads)
{
const auto bestThreadScore = bestThread->worker->rootMoves[0].score;
const auto newThreadScore = th->worker->rootMoves[0].score;
const auto& bestThreadPV = bestThread->worker->rootMoves[0].pv;
const auto& newThreadPV = th->worker->rootMoves[0].pv;
const auto bestThreadMoveVote = votes[bestThreadPV[0]];
const auto newThreadMoveVote = votes[newThreadPV[0]];
const bool bestThreadInProvenWin = bestThreadScore >= VALUE_TB_WIN_IN_MAX_PLY;
const bool newThreadInProvenWin = newThreadScore >= VALUE_TB_WIN_IN_MAX_PLY;
const bool bestThreadInProvenLoss =
bestThreadScore != -VALUE_INFINITE && bestThreadScore <= VALUE_TB_LOSS_IN_MAX_PLY;
const bool newThreadInProvenLoss =
newThreadScore != -VALUE_INFINITE && newThreadScore <= VALUE_TB_LOSS_IN_MAX_PLY;
// Note that we make sure not to pick a thread with truncated-PV for better viewer experience.
const bool betterVotingValue =
thread_voting_value(th) * int(newThreadPV.size() > 2)
> thread_voting_value(bestThread) * int(bestThreadPV.size() > 2);
if (bestThreadInProvenWin)
{
// Make sure we pick the shortest mate / TB conversion or stave off mate the longest
if (th->rootMoves[0].score > bestThread->rootMoves[0].score)
// Make sure we pick the shortest mate / TB conversion
if (newThreadScore > bestThreadScore)
bestThread = th;
}
else if ( th->rootMoves[0].score >= VALUE_TB_WIN_IN_MAX_PLY
|| ( th->rootMoves[0].score > VALUE_TB_LOSS_IN_MAX_PLY
&& votes[th->rootMoves[0].pv[0]] > votes[bestThread->rootMoves[0].pv[0]]))
else if (bestThreadInProvenLoss)
{
// Make sure we pick the shortest mated / TB conversion
if (newThreadInProvenLoss && newThreadScore < bestThreadScore)
bestThread = th;
}
else if (newThreadInProvenWin || newThreadInProvenLoss
|| (newThreadScore > VALUE_TB_LOSS_IN_MAX_PLY
&& (newThreadMoveVote > bestThreadMoveVote
|| (newThreadMoveVote == bestThreadMoveVote && betterVotingValue))))
bestThread = th;
}
@@ -244,23 +277,23 @@ Thread* ThreadPool::get_best_thread() const {
}
/// Start non-main threads
// Start non-main threads
// Will be invoked by main thread after it has started searching
void ThreadPool::start_searching() {
for (Thread* th : *this)
if (th != front())
for (Thread* th : threads)
if (th != threads.front())
th->start_searching();
}
/// Wait for non-main threads
// Wait for non-main threads
void ThreadPool::wait_for_search_finished() const {
for (Thread* th : *this)
if (th != front())
for (Thread* th : threads)
if (th != threads.front())
th->wait_for_search_finished();
}
} // namespace Stockfish
} // namespace Stockfish
+75 -91
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -21,117 +21,101 @@
#include <atomic>
#include <condition_variable>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <mutex>
#include <thread>
#include <vector>
#include "material.h"
#include "movepick.h"
#include "pawns.h"
#include "position.h"
#include "search.h"
#include "thread_win32_osx.h"
namespace Stockfish {
/// Thread class keeps together all the thread-related stuff. We use
/// per-thread pawn and material hash tables so that once we get a
/// pointer to an entry its life time is unlimited and we don't have
/// to care about someone changing the entry under our feet.
class OptionsMap;
using Value = int;
// Abstraction of a thread. It contains a pointer to the worker and a native thread.
// After construction, the native thread is started with idle_loop()
// waiting for a signal to start searching.
// When the signal is received, the thread starts searching and when
// the search is finished, it goes back to idle_loop() waiting for a new signal.
class Thread {
public:
Thread(Search::SharedState&, std::unique_ptr<Search::ISearchManager>, size_t);
virtual ~Thread();
std::mutex mutex;
std::condition_variable cv;
size_t idx;
bool exit = false, searching = true; // Set before starting std::thread
NativeThread stdThread;
void idle_loop();
void start_searching();
void wait_for_search_finished();
size_t id() const { return idx; }
public:
explicit Thread(size_t);
virtual ~Thread();
virtual void search();
void clear();
void idle_loop();
void start_searching();
void wait_for_search_finished();
size_t id() const { return idx; }
std::unique_ptr<Search::Worker> worker;
Pawns::Table pawnsTable;
Material::Table materialTable;
size_t pvIdx, pvLast;
RunningAverage doubleExtensionAverage[COLOR_NB];
uint64_t nodesLastExplosive;
uint64_t nodesLastNormal;
std::atomic<uint64_t> nodes, tbHits, bestMoveChanges;
int selDepth, nmpMinPly;
Color nmpColor;
ExplosionState state;
Position rootPos;
StateInfo rootState;
Search::RootMoves rootMoves;
Depth rootDepth, completedDepth;
CounterMoveHistory counterMoves;
ButterflyHistory mainHistory;
LowPlyHistory lowPlyHistory;
CapturePieceToHistory captureHistory;
ContinuationHistory continuationHistory[2][2];
Score trend;
private:
std::mutex mutex;
std::condition_variable cv;
size_t idx, nthreads;
bool exit = false, searching = true; // Set before starting std::thread
NativeThread stdThread;
};
/// MainThread is a derived class specific for main thread
// ThreadPool struct handles all the threads-related stuff like init, starting,
// parking and, most importantly, launching a thread. All the access to threads
// is done through this class.
class ThreadPool {
struct MainThread : public Thread {
public:
~ThreadPool() {
// destroy any existing thread(s)
if (threads.size() > 0)
{
main_thread()->wait_for_search_finished();
using Thread::Thread;
while (threads.size() > 0)
delete threads.back(), threads.pop_back();
}
}
void search() override;
void check_time();
void
start_thinking(const OptionsMap&, Position&, StateListPtr&, Search::LimitsType, bool = false);
void clear();
void set(Search::SharedState);
double previousTimeReduction;
Value bestPreviousScore;
Value iterValue[4];
int callsCnt;
bool stopOnPonderhit;
std::atomic_bool ponder;
Search::SearchManager* main_manager() const {
return static_cast<Search::SearchManager*>(main_thread()->worker.get()->manager.get());
};
Thread* main_thread() const { return threads.front(); }
uint64_t nodes_searched() const { return accumulate(&Search::Worker::nodes); }
uint64_t tb_hits() const { return accumulate(&Search::Worker::tbHits); }
Thread* get_best_thread() const;
void start_searching();
void wait_for_search_finished() const;
std::atomic_bool stop, abortedSearch, increaseDepth;
auto cbegin() const noexcept { return threads.cbegin(); }
auto begin() noexcept { return threads.begin(); }
auto end() noexcept { return threads.end(); }
auto cend() const noexcept { return threads.cend(); }
auto size() const noexcept { return threads.size(); }
auto empty() const noexcept { return threads.empty(); }
private:
StateListPtr setupStates;
std::vector<Thread*> threads;
uint64_t accumulate(std::atomic<uint64_t> Search::Worker::*member) const {
uint64_t sum = 0;
for (Thread* th : threads)
sum += (th->worker.get()->*member).load(std::memory_order_relaxed);
return sum;
}
};
} // namespace Stockfish
/// ThreadPool struct handles all the threads-related stuff like init, starting,
/// parking and, most importantly, launching a thread. All the access to threads
/// is done through this class.
struct ThreadPool : public std::vector<Thread*> {
void start_thinking(Position&, StateListPtr&, const Search::LimitsType&, bool = false);
void clear();
void set(size_t);
MainThread* main() const { return static_cast<MainThread*>(front()); }
uint64_t nodes_searched() const { return accumulate(&Thread::nodes); }
uint64_t tb_hits() const { return accumulate(&Thread::tbHits); }
Thread* get_best_thread() const;
void start_searching();
void wait_for_search_finished() const;
std::atomic_bool stop, increaseDepth;
private:
StateListPtr setupStates;
uint64_t accumulate(std::atomic<uint64_t> Thread::* member) const {
uint64_t sum = 0;
for (Thread* th : *this)
sum += (th->*member).load(std::memory_order_relaxed);
return sum;
}
};
extern ThreadPool Threads;
} // namespace Stockfish
#endif // #ifndef THREAD_H_INCLUDED
#endif // #ifndef THREAD_H_INCLUDED
+37 -33
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -21,54 +21,58 @@
#include <thread>
/// On OSX threads other than the main thread are created with a reduced stack
/// size of 512KB by default, this is too low for deep searches, which require
/// somewhat more than 1MB stack, so adjust it to TH_STACK_SIZE.
/// The implementation calls pthread_create() with the stack size parameter
/// equal to the linux 8MB default, on platforms that support it.
// On OSX threads other than the main thread are created with a reduced stack
// size of 512KB by default, this is too low for deep searches, which require
// somewhat more than 1MB stack, so adjust it to TH_STACK_SIZE.
// The implementation calls pthread_create() with the stack size parameter
// equal to the Linux 8MB default, on platforms that support it.
#if defined(__APPLE__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(USE_PTHREADS)
#include <pthread.h>
#include <pthread.h>
#include <functional>
namespace Stockfish {
static const size_t TH_STACK_SIZE = 8 * 1024 * 1024;
template <class T, class P = std::pair<T*, void(T::*)()>>
void* start_routine(void* ptr)
{
P* p = reinterpret_cast<P*>(ptr);
(p->first->*(p->second))(); // Call member function pointer
delete p;
return NULL;
}
class NativeThread {
pthread_t thread;
pthread_t thread;
static constexpr size_t TH_STACK_SIZE = 8 * 1024 * 1024;
public:
template<class T, class P = std::pair<T*, void(T::*)()>>
explicit NativeThread(void(T::*fun)(), T* obj) {
pthread_attr_t attr_storage, *attr = &attr_storage;
pthread_attr_init(attr);
pthread_attr_setstacksize(attr, TH_STACK_SIZE);
pthread_create(&thread, attr, start_routine<T>, new P(obj, fun));
}
void join() { pthread_join(thread, NULL); }
public:
template<class Function, class... Args>
explicit NativeThread(Function&& fun, Args&&... args) {
auto func = new std::function<void()>(
std::bind(std::forward<Function>(fun), std::forward<Args>(args)...));
pthread_attr_t attr_storage, *attr = &attr_storage;
pthread_attr_init(attr);
pthread_attr_setstacksize(attr, TH_STACK_SIZE);
auto start_routine = [](void* ptr) -> void* {
auto f = reinterpret_cast<std::function<void()>*>(ptr);
// Call the function
(*f)();
delete f;
return nullptr;
};
pthread_create(&thread, attr, start_routine, func);
}
void join() { pthread_join(thread, nullptr); }
};
} // namespace Stockfish
} // namespace Stockfish
#else // Default case: use STL classes
#else // Default case: use STL classes
namespace Stockfish {
typedef std::thread NativeThread;
using NativeThread = std::thread;
} // namespace Stockfish
} // namespace Stockfish
#endif
#endif // #ifndef THREAD_WIN32_OSX_H_INCLUDED
#endif // #ifndef THREAD_WIN32_OSX_H_INCLUDED
+100 -79
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -16,90 +16,111 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "timeman.h"
#include <algorithm>
#include <cfloat>
#include <cassert>
#include <cmath>
#include <cstdint>
#include "search.h"
#include "timeman.h"
#include "uci.h"
#include "ucioption.h"
namespace Stockfish {
TimeManagement Time; // Our global time management object
/// TimeManagement::init() is called at the beginning of the search and calculates
/// the bounds of time allowed for the current game ply. We currently support:
// 1) x basetime (+ z increment)
// 2) x moves in y seconds (+ z increment)
void TimeManagement::init(Search::LimitsType& limits, Color us, int ply) {
TimePoint moveOverhead = TimePoint(Options["Move Overhead"]);
TimePoint slowMover = TimePoint(Options["Slow Mover"]);
TimePoint npmsec = TimePoint(Options["nodestime"]);
// optScale is a percentage of available time to use for the current move.
// maxScale is a multiplier applied to optimumTime.
double optScale, maxScale;
// If we have to play in 'nodes as time' mode, then convert from time
// to nodes, and use resulting values in time management formulas.
// WARNING: to avoid time losses, the given npmsec (nodes per millisecond)
// must be much lower than the real engine speed.
if (npmsec)
{
if (!availableNodes) // Only once at game start
availableNodes = npmsec * limits.time[us]; // Time is in msec
// Convert from milliseconds to nodes
limits.time[us] = TimePoint(availableNodes);
limits.inc[us] *= npmsec;
limits.npmsec = npmsec;
}
startTime = limits.startTime;
// Maximum move horizon of 50 moves
int mtg = limits.movestogo ? std::min(limits.movestogo, 50) : 50;
// Make sure timeLeft is > 0 since we may use it as a divisor
TimePoint timeLeft = std::max(TimePoint(1),
limits.time[us] + limits.inc[us] * (mtg - 1) - moveOverhead * (2 + mtg));
// Use extra time with larger increments
double optExtra = std::clamp(1.0 + 12.0 * limits.inc[us] / limits.time[us], 1.0, 1.12);
// A user may scale time usage by setting UCI option "Slow Mover"
// Default is 100 and changing this value will probably lose elo.
timeLeft = slowMover * timeLeft / 100;
// x basetime (+ z increment)
// If there is a healthy increment, timeLeft can exceed actual available
// game time for the current move, so also cap to 20% of available game time.
if (limits.movestogo == 0)
{
optScale = std::min(0.0084 + std::pow(ply + 3.0, 0.5) * 0.0042,
0.2 * limits.time[us] / double(timeLeft))
* optExtra;
maxScale = std::min(7.0, 4.0 + ply / 12.0);
}
// x moves in y seconds (+ z increment)
else
{
optScale = std::min((0.88 + ply / 116.4) / mtg,
0.88 * limits.time[us] / double(timeLeft));
maxScale = std::min(6.3, 1.5 + 0.11 * mtg);
}
// Never use more than 80% of the available time for this move
optimumTime = TimePoint(optScale * timeLeft);
maximumTime = TimePoint(std::min(0.8 * limits.time[us] - moveOverhead, maxScale * optimumTime));
if (Options["Ponder"])
optimumTime += optimumTime / 4;
TimePoint TimeManagement::optimum() const { return optimumTime; }
TimePoint TimeManagement::maximum() const { return maximumTime; }
TimePoint TimeManagement::elapsed(size_t nodes) const {
return useNodesTime ? TimePoint(nodes) : now() - startTime;
}
} // namespace Stockfish
void TimeManagement::clear() {
availableNodes = 0; // When in 'nodes as time' mode
}
void TimeManagement::advance_nodes_time(std::int64_t nodes) {
assert(useNodesTime);
availableNodes += nodes;
}
// Called at the beginning of the search and calculates
// the bounds of time allowed for the current game ply. We currently support:
// 1) x basetime (+ z increment)
// 2) x moves in y seconds (+ z increment)
void TimeManagement::init(Search::LimitsType& limits,
Color us,
int ply,
const OptionsMap& options) {
// If we have no time, no need to initialize TM, except for the start time,
// which is used by movetime.
startTime = limits.startTime;
if (limits.time[us] == 0)
return;
TimePoint moveOverhead = TimePoint(options["Move Overhead"]);
TimePoint npmsec = TimePoint(options["nodestime"]);
// optScale is a percentage of available time to use for the current move.
// maxScale is a multiplier applied to optimumTime.
double optScale, maxScale;
// If we have to play in 'nodes as time' mode, then convert from time
// to nodes, and use resulting values in time management formulas.
// WARNING: to avoid time losses, the given npmsec (nodes per millisecond)
// must be much lower than the real engine speed.
if (npmsec)
{
useNodesTime = true;
if (!availableNodes) // Only once at game start
availableNodes = npmsec * limits.time[us]; // Time is in msec
// Convert from milliseconds to nodes
limits.time[us] = TimePoint(availableNodes);
limits.inc[us] *= npmsec;
limits.npmsec = npmsec;
}
// Maximum move horizon of 50 moves
int mtg = limits.movestogo ? std::min(limits.movestogo, 50) : 50;
// Make sure timeLeft is > 0 since we may use it as a divisor
TimePoint timeLeft = std::max(TimePoint(1), limits.time[us] + limits.inc[us] * (mtg - 1)
- moveOverhead * (2 + mtg));
// x basetime (+ z increment)
// If there is a healthy increment, timeLeft can exceed actual available
// game time for the current move, so also cap to 20% of available game time.
if (limits.movestogo == 0)
{
// Use extra time with larger increments
double optExtra = std::clamp(1.0 + 12.5 * limits.inc[us] / limits.time[us], 1.0, 1.11);
// Calculate time constants based on current time left.
double optConstant =
std::min(0.00334 + 0.0003 * std::log10(limits.time[us] / 1000.0), 0.0049);
double maxConstant = std::max(3.4 + 3.0 * std::log10(limits.time[us] / 1000.0), 2.76);
optScale = std::min(0.0120 + std::pow(ply + 3.1, 0.44) * optConstant,
0.21 * limits.time[us] / double(timeLeft))
* optExtra;
maxScale = std::min(6.9, maxConstant + ply / 12.2);
}
// x moves in y seconds (+ z increment)
else
{
optScale = std::min((0.88 + ply / 116.4) / mtg, 0.88 * limits.time[us] / double(timeLeft));
maxScale = std::min(6.3, 1.5 + 0.11 * mtg);
}
// Limit the maximum possible time for this move
optimumTime = TimePoint(optScale * timeLeft);
maximumTime =
TimePoint(std::min(0.84 * limits.time[us] - moveOverhead, maxScale * optimumTime)) - 10;
if (options["Ponder"])
optimumTime += optimumTime / 4;
}
} // namespace Stockfish
+29 -20
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -19,33 +19,42 @@
#ifndef TIMEMAN_H_INCLUDED
#define TIMEMAN_H_INCLUDED
#include <cstddef>
#include <cstdint>
#include "misc.h"
#include "search.h"
#include "thread.h"
#include "types.h"
namespace Stockfish {
/// The TimeManagement class computes the optimal time to think depending on
/// the maximum available time, the game move number and other parameters.
class OptionsMap;
namespace Search {
struct LimitsType;
}
// The TimeManagement class computes the optimal time to think depending on
// the maximum available time, the game move number, and other parameters.
class TimeManagement {
public:
void init(Search::LimitsType& limits, Color us, int ply);
TimePoint optimum() const { return optimumTime; }
TimePoint maximum() const { return maximumTime; }
TimePoint elapsed() const { return Search::Limits.npmsec ?
TimePoint(Threads.nodes_searched()) : now() - startTime; }
public:
void init(Search::LimitsType& limits, Color us, int ply, const OptionsMap& options);
int64_t availableNodes; // When in 'nodes as time' mode
TimePoint optimum() const;
TimePoint maximum() const;
TimePoint elapsed(std::size_t nodes) const;
private:
TimePoint startTime;
TimePoint optimumTime;
TimePoint maximumTime;
void clear();
void advance_nodes_time(std::int64_t nodes);
private:
TimePoint startTime;
TimePoint optimumTime;
TimePoint maximumTime;
std::int64_t availableNodes = 0; // When in 'nodes as time' mode
bool useNodesTime = false; // True if we are in 'nodes as time' mode
};
extern TimeManagement Time;
} // namespace Stockfish
} // namespace Stockfish
#endif // #ifndef TIMEMAN_H_INCLUDED
#endif // #ifndef TIMEMAN_H_INCLUDED
+94 -104
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -16,147 +16,137 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cstring> // For std::memset
#include "tt.h"
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <thread>
#include <vector>
#include "bitboard.h"
#include "misc.h"
#include "thread.h"
#include "tt.h"
#include "uci.h"
namespace Stockfish {
TranspositionTable TT; // Our global transposition table
// Populates the TTEntry with a new node's data, possibly
// overwriting an old position. The update is not atomic and can be racy.
void TTEntry::save(
Key k, Value v, bool pv, Bound b, Depth d, Move m, Value ev, uint8_t generation8) {
/// TTEntry::save() populates the TTEntry with a new node's data, possibly
/// overwriting an old position. Update is not atomic and can be racy.
// Preserve any existing move for the same position
if (m || uint16_t(k) != key16)
move16 = m;
void TTEntry::save(Key k, Value v, bool pv, Bound b, Depth d, Move m, Value ev) {
// Overwrite less valuable entries (cheapest checks first)
if (b == BOUND_EXACT || uint16_t(k) != key16 || d - DEPTH_OFFSET + 2 * pv > depth8 - 4)
{
assert(d > DEPTH_OFFSET);
assert(d < 256 + DEPTH_OFFSET);
// Preserve any existing move for the same position
if (m || (uint16_t)k != key16)
move16 = (uint16_t)m;
// Overwrite less valuable entries (cheapest checks first)
if (b == BOUND_EXACT
|| (uint16_t)k != key16
|| d - DEPTH_OFFSET > depth8 - 4)
{
assert(d > DEPTH_OFFSET);
assert(d < 256 + DEPTH_OFFSET);
key16 = (uint16_t)k;
depth8 = (uint8_t)(d - DEPTH_OFFSET);
genBound8 = (uint8_t)(TT.generation8 | uint8_t(pv) << 2 | b);
value16 = (int16_t)v;
eval16 = (int16_t)ev;
}
key16 = uint16_t(k);
depth8 = uint8_t(d - DEPTH_OFFSET);
genBound8 = uint8_t(generation8 | uint8_t(pv) << 2 | b);
value16 = int16_t(v);
eval16 = int16_t(ev);
}
}
/// TranspositionTable::resize() sets the size of the transposition table,
/// measured in megabytes. Transposition table consists of a power of 2 number
/// of clusters and each cluster consists of ClusterSize number of TTEntry.
// Sets the size of the transposition table,
// measured in megabytes. Transposition table consists of a power of 2 number
// of clusters and each cluster consists of ClusterSize number of TTEntry.
void TranspositionTable::resize(size_t mbSize, int threadCount) {
aligned_large_pages_free(table);
void TranspositionTable::resize(size_t mbSize) {
clusterCount = mbSize * 1024 * 1024 / sizeof(Cluster);
Threads.main()->wait_for_search_finished();
table = static_cast<Cluster*>(aligned_large_pages_alloc(clusterCount * sizeof(Cluster)));
if (!table)
{
std::cerr << "Failed to allocate " << mbSize << "MB for transposition table." << std::endl;
exit(EXIT_FAILURE);
}
aligned_large_pages_free(table);
clusterCount = mbSize * 1024 * 1024 / sizeof(Cluster);
table = static_cast<Cluster*>(aligned_large_pages_alloc(clusterCount * sizeof(Cluster)));
if (!table)
{
std::cerr << "Failed to allocate " << mbSize
<< "MB for transposition table." << std::endl;
exit(EXIT_FAILURE);
}
clear();
clear(threadCount);
}
/// TranspositionTable::clear() initializes the entire transposition table to zero,
// in a multi-threaded way.
// Initializes the entire transposition table to zero,
// in a multi-threaded way.
void TranspositionTable::clear(size_t threadCount) {
std::vector<std::thread> threads;
void TranspositionTable::clear() {
for (size_t idx = 0; idx < size_t(threadCount); ++idx)
{
threads.emplace_back([this, idx, threadCount]() {
// Thread binding gives faster search on systems with a first-touch policy
if (threadCount > 8)
WinProcGroup::bindThisThread(idx);
std::vector<std::thread> threads;
// Each thread will zero its part of the hash table
const size_t stride = size_t(clusterCount / threadCount), start = size_t(stride * idx),
len = idx != size_t(threadCount) - 1 ? stride : clusterCount - start;
for (size_t idx = 0; idx < Options["Threads"]; ++idx)
{
threads.emplace_back([this, idx]() {
std::memset(&table[start], 0, len * sizeof(Cluster));
});
}
// Thread binding gives faster search on systems with a first-touch policy
if (Options["Threads"] > 8)
WinProcGroup::bindThisThread(idx);
// Each thread will zero its part of the hash table
const size_t stride = size_t(clusterCount / Options["Threads"]),
start = size_t(stride * idx),
len = idx != Options["Threads"] - 1 ?
stride : clusterCount - start;
std::memset(&table[start], 0, len * sizeof(Cluster));
});
}
for (std::thread& th : threads)
th.join();
for (std::thread& th : threads)
th.join();
}
/// TranspositionTable::probe() looks up the current position in the transposition
/// table. It returns true and a pointer to the TTEntry if the position is found.
/// Otherwise, it returns false and a pointer to an empty or least valuable TTEntry
/// to be replaced later. The replace value of an entry is calculated as its depth
/// minus 8 times its relative age. TTEntry t1 is considered more valuable than
/// TTEntry t2 if its replace value is greater than that of t2.
// Looks up the current position in the transposition
// table. It returns true and a pointer to the TTEntry if the position is found.
// Otherwise, it returns false and a pointer to an empty or least valuable TTEntry
// to be replaced later. The replace value of an entry is calculated as its depth
// minus 8 times its relative age. TTEntry t1 is considered more valuable than
// TTEntry t2 if its replace value is greater than that of t2.
TTEntry* TranspositionTable::probe(const Key key, bool& found) const {
TTEntry* const tte = first_entry(key);
const uint16_t key16 = (uint16_t)key; // Use the low 16 bits as key inside the cluster
TTEntry* const tte = first_entry(key);
const uint16_t key16 = uint16_t(key); // Use the low 16 bits as key inside the cluster
for (int i = 0; i < ClusterSize; ++i)
if (tte[i].key16 == key16 || !tte[i].depth8)
{
tte[i].genBound8 = uint8_t(generation8 | (tte[i].genBound8 & (GENERATION_DELTA - 1))); // Refresh
for (int i = 0; i < ClusterSize; ++i)
if (tte[i].key16 == key16 || !tte[i].depth8)
{
tte[i].genBound8 =
uint8_t(generation8 | (tte[i].genBound8 & (GENERATION_DELTA - 1))); // Refresh
return found = (bool)tte[i].depth8, &tte[i];
}
return found = bool(tte[i].depth8), &tte[i];
}
// Find an entry to be replaced according to the replacement strategy
TTEntry* replace = tte;
for (int i = 1; i < ClusterSize; ++i)
// Due to our packed storage format for generation and its cyclic
// nature we add GENERATION_CYCLE (256 is the modulus, plus what
// is needed to keep the unrelated lowest n bits from affecting
// the result) to calculate the entry age correctly even after
// generation8 overflows into the next cycle.
if ( replace->depth8 - ((GENERATION_CYCLE + generation8 - replace->genBound8) & GENERATION_MASK)
> tte[i].depth8 - ((GENERATION_CYCLE + generation8 - tte[i].genBound8) & GENERATION_MASK))
replace = &tte[i];
// Find an entry to be replaced according to the replacement strategy
TTEntry* replace = tte;
for (int i = 1; i < ClusterSize; ++i)
// Due to our packed storage format for generation and its cyclic
// nature we add GENERATION_CYCLE (256 is the modulus, plus what
// is needed to keep the unrelated lowest n bits from affecting
// the result) to calculate the entry age correctly even after
// generation8 overflows into the next cycle.
if (replace->depth8
- ((GENERATION_CYCLE + generation8 - replace->genBound8) & GENERATION_MASK)
> tte[i].depth8
- ((GENERATION_CYCLE + generation8 - tte[i].genBound8) & GENERATION_MASK))
replace = &tte[i];
return found = false, replace;
return found = false, replace;
}
/// TranspositionTable::hashfull() returns an approximation of the hashtable
/// occupation during a search. The hash is x permill full, as per UCI protocol.
// Returns an approximation of the hashtable
// occupation during a search. The hash is x permill full, as per UCI protocol.
int TranspositionTable::hashfull() const {
int cnt = 0;
for (int i = 0; i < 1000; ++i)
for (int j = 0; j < ClusterSize; ++j)
cnt += table[i].entry[j].depth8 && (table[i].entry[j].genBound8 & GENERATION_MASK) == generation8;
int cnt = 0;
for (int i = 0; i < 1000; ++i)
for (int j = 0; j < ClusterSize; ++j)
cnt += table[i].entry[j].depth8
&& (table[i].entry[j].genBound8 & GENERATION_MASK) == generation8;
return cnt / ClusterSize;
return cnt / ClusterSize;
}
} // namespace Stockfish
} // namespace Stockfish
+66 -63
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -19,89 +19,92 @@
#ifndef TT_H_INCLUDED
#define TT_H_INCLUDED
#include <cstddef>
#include <cstdint>
#include "misc.h"
#include "types.h"
namespace Stockfish {
/// TTEntry struct is the 10 bytes transposition table entry, defined as below:
///
/// key 16 bit
/// depth 8 bit
/// generation 5 bit
/// pv node 1 bit
/// bound type 2 bit
/// move 16 bit
/// value 16 bit
/// eval value 16 bit
// TTEntry struct is the 10 bytes transposition table entry, defined as below:
//
// key 16 bit
// depth 8 bit
// generation 5 bit
// pv node 1 bit
// bound type 2 bit
// move 16 bit
// value 16 bit
// eval value 16 bit
struct TTEntry {
Move move() const { return (Move )move16; }
Value value() const { return (Value)value16; }
Value eval() const { return (Value)eval16; }
Depth depth() const { return (Depth)depth8 + DEPTH_OFFSET; }
bool is_pv() const { return (bool)(genBound8 & 0x4); }
Bound bound() const { return (Bound)(genBound8 & 0x3); }
void save(Key k, Value v, bool pv, Bound b, Depth d, Move m, Value ev);
Move move() const { return Move(move16); }
Value value() const { return Value(value16); }
Value eval() const { return Value(eval16); }
Depth depth() const { return Depth(depth8 + DEPTH_OFFSET); }
bool is_pv() const { return bool(genBound8 & 0x4); }
Bound bound() const { return Bound(genBound8 & 0x3); }
void save(Key k, Value v, bool pv, Bound b, Depth d, Move m, Value ev, uint8_t generation8);
private:
friend class TranspositionTable;
private:
friend class TranspositionTable;
uint16_t key16;
uint8_t depth8;
uint8_t genBound8;
uint16_t move16;
int16_t value16;
int16_t eval16;
uint16_t key16;
uint8_t depth8;
uint8_t genBound8;
Move move16;
int16_t value16;
int16_t eval16;
};
/// A TranspositionTable is an array of Cluster, of size clusterCount. Each
/// cluster consists of ClusterSize number of TTEntry. Each non-empty TTEntry
/// contains information on exactly one position. The size of a Cluster should
/// divide the size of a cache line for best performance, as the cacheline is
/// prefetched when possible.
// A TranspositionTable is an array of Cluster, of size clusterCount. Each
// cluster consists of ClusterSize number of TTEntry. Each non-empty TTEntry
// contains information on exactly one position. The size of a Cluster should
// divide the size of a cache line for best performance, as the cacheline is
// prefetched when possible.
class TranspositionTable {
static constexpr int ClusterSize = 3;
static constexpr int ClusterSize = 3;
struct Cluster {
TTEntry entry[ClusterSize];
char padding[2]; // Pad to 32 bytes
};
struct Cluster {
TTEntry entry[ClusterSize];
char padding[2]; // Pad to 32 bytes
};
static_assert(sizeof(Cluster) == 32, "Unexpected Cluster size");
static_assert(sizeof(Cluster) == 32, "Unexpected Cluster size");
// Constants used to refresh the hash table periodically
static constexpr unsigned GENERATION_BITS = 3; // nb of bits reserved for other things
static constexpr int GENERATION_DELTA = (1 << GENERATION_BITS); // increment for generation field
static constexpr int GENERATION_CYCLE = 255 + (1 << GENERATION_BITS); // cycle length
static constexpr int GENERATION_MASK = (0xFF << GENERATION_BITS) & 0xFF; // mask to pull out generation number
// Constants used to refresh the hash table periodically
static constexpr unsigned GENERATION_BITS = 3; // nb of bits reserved for other things
static constexpr int GENERATION_DELTA =
(1 << GENERATION_BITS); // increment for generation field
static constexpr int GENERATION_CYCLE = 255 + (1 << GENERATION_BITS); // cycle length
static constexpr int GENERATION_MASK =
(0xFF << GENERATION_BITS) & 0xFF; // mask to pull out generation number
public:
~TranspositionTable() { aligned_large_pages_free(table); }
void new_search() { generation8 += GENERATION_DELTA; } // Lower bits are used for other things
TTEntry* probe(const Key key, bool& found) const;
int hashfull() const;
void resize(size_t mbSize);
void clear();
public:
~TranspositionTable() { aligned_large_pages_free(table); }
void new_search() { generation8 += GENERATION_DELTA; } // Lower bits are used for other things
TTEntry* probe(const Key key, bool& found) const;
int hashfull() const;
void resize(size_t mbSize, int threadCount);
void clear(size_t threadCount);
TTEntry* first_entry(const Key key) const {
return &table[mul_hi64(key, clusterCount)].entry[0];
}
TTEntry* first_entry(const Key key) const {
return &table[mul_hi64(key, clusterCount)].entry[0];
}
private:
friend struct TTEntry;
uint8_t generation() const { return generation8; }
size_t clusterCount;
Cluster* table;
uint8_t generation8; // Size must be not bigger than TTEntry::genBound8
private:
friend struct TTEntry;
size_t clusterCount;
Cluster* table = nullptr;
uint8_t generation8 = 0; // Size must be not bigger than TTEntry::genBound8
};
extern TranspositionTable TT;
} // namespace Stockfish
} // namespace Stockfish
#endif // #ifndef TT_H_INCLUDED
#endif // #ifndef TT_H_INCLUDED
+50 -65
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -16,100 +16,88 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "tune.h"
#include <algorithm>
#include <iostream>
#include <map>
#include <sstream>
#include <string>
#include "types.h"
#include "misc.h"
#include "uci.h"
#include "ucioption.h"
using std::string;
namespace Stockfish {
bool Tune::update_on_last;
const UCI::Option* LastOption = nullptr;
bool Tune::update_on_last;
const Option* LastOption = nullptr;
OptionsMap* Tune::options;
static std::map<std::string, int> TuneResults;
string Tune::next(string& names, bool pop) {
string name;
string name;
do {
string token = names.substr(0, names.find(','));
do
{
string token = names.substr(0, names.find(','));
if (pop)
names.erase(0, token.size() + 1);
if (pop)
names.erase(0, token.size() + 1);
std::stringstream ws(token);
name += (ws >> token, token); // Remove trailing whitespace
std::stringstream ws(token);
name += (ws >> token, token); // Remove trailing whitespace
} while ( std::count(name.begin(), name.end(), '(')
- std::count(name.begin(), name.end(), ')'));
} while (std::count(name.begin(), name.end(), '(') - std::count(name.begin(), name.end(), ')'));
return name;
return name;
}
static void on_tune(const UCI::Option& o) {
static void on_tune(const Option& o) {
if (!Tune::update_on_last || LastOption == &o)
Tune::read_options();
if (!Tune::update_on_last || LastOption == &o)
Tune::read_options();
}
static void make_option(const string& n, int v, const SetRange& r) {
static void make_option(OptionsMap* options, const string& n, int v, const SetRange& r) {
// Do not generate option when there is nothing to tune (ie. min = max)
if (r(v).first == r(v).second)
return;
// Do not generate option when there is nothing to tune (ie. min = max)
if (r(v).first == r(v).second)
return;
if (TuneResults.count(n))
v = TuneResults[n];
if (TuneResults.count(n))
v = TuneResults[n];
Options[n] << UCI::Option(v, r(v).first, r(v).second, on_tune);
LastOption = &Options[n];
(*options)[n] << Option(v, r(v).first, r(v).second, on_tune);
LastOption = &((*options)[n]);
// Print formatted parameters, ready to be copy-pasted in Fishtest
std::cout << n << ","
<< v << ","
<< r(v).first << "," << r(v).second << ","
<< (r(v).second - r(v).first) / 20.0 << ","
<< "0.0020"
<< std::endl;
// Print formatted parameters, ready to be copy-pasted in Fishtest
std::cout << n << "," << v << "," << r(v).first << "," << r(v).second << ","
<< (r(v).second - r(v).first) / 20.0 << ","
<< "0.0020" << std::endl;
}
template<> void Tune::Entry<int>::init_option() { make_option(name, value, range); }
template<> void Tune::Entry<int>::read_option() {
if (Options.count(name))
value = int(Options[name]);
template<>
void Tune::Entry<int>::init_option() {
make_option(options, name, value, range);
}
template<> void Tune::Entry<Value>::init_option() { make_option(name, value, range); }
template<> void Tune::Entry<Value>::read_option() {
if (Options.count(name))
value = Value(int(Options[name]));
}
template<> void Tune::Entry<Score>::init_option() {
make_option("m" + name, mg_value(value), range);
make_option("e" + name, eg_value(value), range);
}
template<> void Tune::Entry<Score>::read_option() {
if (Options.count("m" + name))
value = make_score(int(Options["m" + name]), eg_value(value));
if (Options.count("e" + name))
value = make_score(mg_value(value), int(Options["e" + name]));
template<>
void Tune::Entry<int>::read_option() {
if (options->count(name))
value = int((*options)[name]);
}
// Instead of a variable here we have a PostUpdate function: just call it
template<> void Tune::Entry<Tune::PostUpdate>::init_option() {}
template<> void Tune::Entry<Tune::PostUpdate>::read_option() { value(); }
template<>
void Tune::Entry<Tune::PostUpdate>::init_option() {}
template<>
void Tune::Entry<Tune::PostUpdate>::read_option() {
value();
}
} // namespace Stockfish
} // namespace Stockfish
// Init options with tuning session results instead of default values. Useful to
@@ -121,13 +109,10 @@ template<> void Tune::Entry<Tune::PostUpdate>::read_option() { value(); }
//
// Then paste the output below, as the function body
#include <cmath>
namespace Stockfish {
void Tune::read_results() {
/* ...insert your values here... */
void Tune::read_results() { /* ...insert your values here... */
}
} // namespace Stockfish
} // namespace Stockfish
+119 -101
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -19,145 +19,163 @@
#ifndef TUNE_H_INCLUDED
#define TUNE_H_INCLUDED
#include <cstddef>
#include <memory>
#include <string>
#include <type_traits>
#include <type_traits> // IWYU pragma: keep
#include <utility>
#include <vector>
namespace Stockfish {
typedef std::pair<int, int> Range; // Option's min-max values
typedef Range (RangeFun) (int);
class OptionsMap;
using Range = std::pair<int, int>; // Option's min-max values
using RangeFun = Range(int);
// Default Range function, to calculate Option's min-max values
inline Range default_range(int v) {
return v > 0 ? Range(0, 2 * v) : Range(2 * v, 0);
}
inline Range default_range(int v) { return v > 0 ? Range(0, 2 * v) : Range(2 * v, 0); }
struct SetRange {
explicit SetRange(RangeFun f) : fun(f) {}
SetRange(int min, int max) : fun(nullptr), range(min, max) {}
Range operator()(int v) const { return fun ? fun(v) : range; }
explicit SetRange(RangeFun f) :
fun(f) {}
SetRange(int min, int max) :
fun(nullptr),
range(min, max) {}
Range operator()(int v) const { return fun ? fun(v) : range; }
RangeFun* fun;
Range range;
RangeFun* fun;
Range range;
};
#define SetDefaultRange SetRange(default_range)
/// Tune class implements the 'magic' code that makes the setup of a fishtest
/// tuning session as easy as it can be. Mainly you have just to remove const
/// qualifiers from the variables you want to tune and flag them for tuning, so
/// if you have:
///
/// const Score myScore = S(10, 15);
/// const Value myValue[][2] = { { V(100), V(20) }, { V(7), V(78) } };
///
/// If you have a my_post_update() function to run after values have been updated,
/// and a my_range() function to set custom Option's min-max values, then you just
/// remove the 'const' qualifiers and write somewhere below in the file:
///
/// TUNE(SetRange(my_range), myScore, myValue, my_post_update);
///
/// You can also set the range directly, and restore the default at the end
///
/// TUNE(SetRange(-100, 100), myScore, SetDefaultRange);
///
/// In case update function is slow and you have many parameters, you can add:
///
/// UPDATE_ON_LAST();
///
/// And the values update, including post update function call, will be done only
/// once, after the engine receives the last UCI option, that is the one defined
/// and created as the last one, so the GUI should send the options in the same
/// order in which have been defined.
// Tune class implements the 'magic' code that makes the setup of a fishtest tuning
// session as easy as it can be. Mainly you have just to remove const qualifiers
// from the variables you want to tune and flag them for tuning, so if you have:
//
// const Value myValue[][2] = { { V(100), V(20) }, { V(7), V(78) } };
//
// If you have a my_post_update() function to run after values have been updated,
// and a my_range() function to set custom Option's min-max values, then you just
// remove the 'const' qualifiers and write somewhere below in the file:
//
// TUNE(SetRange(my_range), myValue, my_post_update);
//
// You can also set the range directly, and restore the default at the end
//
// TUNE(SetRange(-100, 100), myValue, SetDefaultRange);
//
// In case update function is slow and you have many parameters, you can add:
//
// UPDATE_ON_LAST();
//
// And the values update, including post update function call, will be done only
// once, after the engine receives the last UCI option, that is the one defined
// and created as the last one, so the GUI should send the options in the same
// order in which have been defined.
class Tune {
typedef void (PostUpdate) (); // Post-update function
using PostUpdate = void(); // Post-update function
Tune() { read_results(); }
Tune(const Tune&) = delete;
void operator=(const Tune&) = delete;
void read_results();
Tune() { read_results(); }
Tune(const Tune&) = delete;
void operator=(const Tune&) = delete;
void read_results();
static Tune& instance() { static Tune t; return t; } // Singleton
static Tune& instance() {
static Tune t;
return t;
} // Singleton
// Use polymorphism to accomodate Entry of different types in the same vector
struct EntryBase {
virtual ~EntryBase() = default;
virtual void init_option() = 0;
virtual void read_option() = 0;
};
// Use polymorphism to accommodate Entry of different types in the same vector
struct EntryBase {
virtual ~EntryBase() = default;
virtual void init_option() = 0;
virtual void read_option() = 0;
};
template<typename T>
struct Entry : public EntryBase {
template<typename T>
struct Entry: public EntryBase {
static_assert(!std::is_const<T>::value, "Parameter cannot be const!");
static_assert(!std::is_const_v<T>, "Parameter cannot be const!");
static_assert( std::is_same<T, int>::value
|| std::is_same<T, Value>::value
|| std::is_same<T, Score>::value
|| std::is_same<T, PostUpdate>::value, "Parameter type not supported!");
static_assert(std::is_same_v<T, int> || std::is_same_v<T, PostUpdate>,
"Parameter type not supported!");
Entry(const std::string& n, T& v, const SetRange& r) : name(n), value(v), range(r) {}
void operator=(const Entry&) = delete; // Because 'value' is a reference
void init_option() override;
void read_option() override;
Entry(const std::string& n, T& v, const SetRange& r) :
name(n),
value(v),
range(r) {}
void operator=(const Entry&) = delete; // Because 'value' is a reference
void init_option() override;
void read_option() override;
std::string name;
T& value;
SetRange range;
};
std::string name;
T& value;
SetRange range;
};
// Our facility to fill the container, each Entry corresponds to a parameter
// to tune. We use variadic templates to deal with an unspecified number of
// entries, each one of a possible different type.
static std::string next(std::string& names, bool pop = true);
// Our facility to fill the container, each Entry corresponds to a parameter
// to tune. We use variadic templates to deal with an unspecified number of
// entries, each one of a possible different type.
static std::string next(std::string& names, bool pop = true);
int add(const SetRange&, std::string&&) { return 0; }
int add(const SetRange&, std::string&&) { return 0; }
template<typename T, typename... Args>
int add(const SetRange& range, std::string&& names, T& value, Args&&... args) {
list.push_back(std::unique_ptr<EntryBase>(new Entry<T>(next(names), value, range)));
return add(range, std::move(names), args...);
}
template<typename T, typename... Args>
int add(const SetRange& range, std::string&& names, T& value, Args&&... args) {
list.push_back(std::unique_ptr<EntryBase>(new Entry<T>(next(names), value, range)));
return add(range, std::move(names), args...);
}
// Template specialization for arrays: recursively handle multi-dimensional arrays
template<typename T, size_t N, typename... Args>
int add(const SetRange& range, std::string&& names, T (&value)[N], Args&&... args) {
for (size_t i = 0; i < N; i++)
add(range, next(names, i == N - 1) + "[" + std::to_string(i) + "]", value[i]);
return add(range, std::move(names), args...);
}
// Template specialization for arrays: recursively handle multi-dimensional arrays
template<typename T, size_t N, typename... Args>
int add(const SetRange& range, std::string&& names, T (&value)[N], Args&&... args) {
for (size_t i = 0; i < N; i++)
add(range, next(names, i == N - 1) + "[" + std::to_string(i) + "]", value[i]);
return add(range, std::move(names), args...);
}
// Template specialization for SetRange
template<typename... Args>
int add(const SetRange&, std::string&& names, SetRange& value, Args&&... args) {
return add(value, (next(names), std::move(names)), args...);
}
// Template specialization for SetRange
template<typename... Args>
int add(const SetRange&, std::string&& names, SetRange& value, Args&&... args) {
return add(value, (next(names), std::move(names)), args...);
}
std::vector<std::unique_ptr<EntryBase>> list;
std::vector<std::unique_ptr<EntryBase>> list;
public:
template<typename... Args>
static int add(const std::string& names, Args&&... args) {
return instance().add(SetDefaultRange, names.substr(1, names.size() - 2), args...); // Remove trailing parenthesis
}
static void init() { for (auto& e : instance().list) e->init_option(); read_options(); } // Deferred, due to UCI::Options access
static void read_options() { for (auto& e : instance().list) e->read_option(); }
static bool update_on_last;
public:
template<typename... Args>
static int add(const std::string& names, Args&&... args) {
return instance().add(SetDefaultRange, names.substr(1, names.size() - 2),
args...); // Remove trailing parenthesis
}
static void init(OptionsMap& o) {
options = &o;
for (auto& e : instance().list)
e->init_option();
read_options();
} // Deferred, due to UCI::Options access
static void read_options() {
for (auto& e : instance().list)
e->read_option();
}
static bool update_on_last;
static OptionsMap* options;
};
// Some macro magic :-) we define a dummy int variable that compiler initializes calling Tune::add()
// Some macro magic :-) we define a dummy int variable that the compiler initializes calling Tune::add()
#define STRINGIFY(x) #x
#define UNIQUE2(x, y) x ## y
#define UNIQUE(x, y) UNIQUE2(x, y) // Two indirection levels to expand __LINE__
#define UNIQUE2(x, y) x##y
#define UNIQUE(x, y) UNIQUE2(x, y) // Two indirection levels to expand __LINE__
#define TUNE(...) int UNIQUE(p, __LINE__) = Tune::add(STRINGIFY((__VA_ARGS__)), __VA_ARGS__)
#define UPDATE_ON_LAST() bool UNIQUE(p, __LINE__) = Tune::update_on_last = true
} // namespace Stockfish
} // namespace Stockfish
#endif // #ifndef TUNE_H_INCLUDED
#endif // #ifndef TUNE_H_INCLUDED
+278 -362
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -17,479 +17,395 @@
*/
#ifndef TYPES_H_INCLUDED
#define TYPES_H_INCLUDED
#define TYPES_H_INCLUDED
/// When compiling with provided Makefile (e.g. for Linux and OSX), configuration
/// is done automatically. To get started type 'make help'.
///
/// When Makefile is not used (e.g. with Microsoft Visual Studio) some switches
/// need to be set manually:
///
/// -DNDEBUG | Disable debugging mode. Always use this for release.
///
/// -DNO_PREFETCH | Disable use of prefetch asm-instruction. You may need this to
/// | run on some very old machines.
///
/// -DUSE_POPCNT | Add runtime support for use of popcnt asm-instruction. Works
/// | only in 64-bit mode and requires hardware with popcnt support.
///
/// -DUSE_PEXT | Add runtime support for use of pext asm-instruction. Works
/// | only in 64-bit mode and requires hardware with pext support.
// When compiling with provided Makefile (e.g. for Linux and OSX), configuration
// is done automatically. To get started type 'make help'.
//
// When Makefile is not used (e.g. with Microsoft Visual Studio) some switches
// need to be set manually:
//
// -DNDEBUG | Disable debugging mode. Always use this for release.
//
// -DNO_PREFETCH | Disable use of prefetch asm-instruction. You may need this to
// | run on some very old machines.
//
// -DUSE_POPCNT | Add runtime support for use of popcnt asm-instruction. Works
// | only in 64-bit mode and requires hardware with popcnt support.
//
// -DUSE_PEXT | Add runtime support for use of pext asm-instruction. Works
// | only in 64-bit mode and requires hardware with pext support.
#include <cassert>
#include <cctype>
#include <cstdint>
#include <cstdlib>
#include <algorithm>
#include <cassert>
#include <cstdint>
#if defined(_MSC_VER)
// Disable some silly and noisy warning from MSVC compiler
#pragma warning(disable: 4127) // Conditional expression is constant
#pragma warning(disable: 4146) // Unary minus operator applied to unsigned type
#pragma warning(disable: 4800) // Forcing value to bool 'true' or 'false'
#endif
#if defined(_MSC_VER)
// Disable some silly and noisy warnings from MSVC compiler
#pragma warning(disable: 4127) // Conditional expression is constant
#pragma warning(disable: 4146) // Unary minus operator applied to unsigned type
#pragma warning(disable: 4800) // Forcing value to bool 'true' or 'false'
#endif
/// Predefined macros hell:
///
/// __GNUC__ Compiler is gcc, Clang or Intel on Linux
/// __INTEL_COMPILER Compiler is Intel
/// _MSC_VER Compiler is MSVC or Intel on Windows
/// _WIN32 Building on Windows (any)
/// _WIN64 Building on Windows 64 bit
// Predefined macros hell:
//
// __GNUC__ Compiler is GCC, Clang or ICX
// __clang__ Compiler is Clang or ICX
// __INTEL_LLVM_COMPILER Compiler is ICX
// _MSC_VER Compiler is MSVC
// _WIN32 Building on Windows (any)
// _WIN64 Building on Windows 64 bit
#if defined(__GNUC__ ) && (__GNUC__ < 9 || (__GNUC__ == 9 && __GNUC_MINOR__ <= 2)) && defined(_WIN32) && !defined(__clang__)
#define ALIGNAS_ON_STACK_VARIABLES_BROKEN
#endif
#if defined(__GNUC__) && (__GNUC__ < 9 || (__GNUC__ == 9 && __GNUC_MINOR__ <= 2)) \
&& defined(_WIN32) && !defined(__clang__)
#define ALIGNAS_ON_STACK_VARIABLES_BROKEN
#endif
#define ASSERT_ALIGNED(ptr, alignment) assert(reinterpret_cast<uintptr_t>(ptr) % alignment == 0)
#define ASSERT_ALIGNED(ptr, alignment) assert(reinterpret_cast<uintptr_t>(ptr) % alignment == 0)
#if defined(_WIN64) && defined(_MSC_VER) // No Makefile used
# include <intrin.h> // Microsoft header for _BitScanForward64()
# define IS_64BIT
#endif
#if defined(_WIN64) && defined(_MSC_VER) // No Makefile used
#include <intrin.h> // Microsoft header for _BitScanForward64()
#define IS_64BIT
#endif
#if defined(USE_POPCNT) && (defined(__INTEL_COMPILER) || defined(_MSC_VER))
# include <nmmintrin.h> // Intel and Microsoft header for _mm_popcnt_u64()
#endif
#if defined(USE_POPCNT) && defined(_MSC_VER)
#include <nmmintrin.h> // Microsoft header for _mm_popcnt_u64()
#endif
#if !defined(NO_PREFETCH) && (defined(__INTEL_COMPILER) || defined(_MSC_VER))
# include <xmmintrin.h> // Intel and Microsoft header for _mm_prefetch()
#endif
#if !defined(NO_PREFETCH) && defined(_MSC_VER)
#include <xmmintrin.h> // Microsoft header for _mm_prefetch()
#endif
#if defined(USE_PEXT)
# include <immintrin.h> // Header for _pext_u64() intrinsic
# define pext(b, m) _pext_u64(b, m)
#else
# define pext(b, m) 0
#endif
#if defined(USE_PEXT)
#include <immintrin.h> // Header for _pext_u64() intrinsic
#define pext(b, m) _pext_u64(b, m)
#else
#define pext(b, m) 0
#endif
namespace Stockfish {
#ifdef USE_POPCNT
#ifdef USE_POPCNT
constexpr bool HasPopCnt = true;
#else
#else
constexpr bool HasPopCnt = false;
#endif
#endif
#ifdef USE_PEXT
#ifdef USE_PEXT
constexpr bool HasPext = true;
#else
#else
constexpr bool HasPext = false;
#endif
#endif
#ifdef IS_64BIT
#ifdef IS_64BIT
constexpr bool Is64Bit = true;
#else
#else
constexpr bool Is64Bit = false;
#endif
#endif
typedef uint64_t Key;
typedef uint64_t Bitboard;
using Key = uint64_t;
using Bitboard = uint64_t;
constexpr int MAX_MOVES = 256;
constexpr int MAX_PLY = 246;
/// A move needs 16 bits to be stored
///
/// bit 0- 5: destination square (from 0 to 63)
/// bit 6-11: origin square (from 0 to 63)
/// bit 12-13: promotion piece type - 2 (from KNIGHT-2 to QUEEN-2)
/// bit 14-15: special move flag: promotion (1), en passant (2), castling (3)
/// NOTE: en passant bit is set only when a pawn can be captured
///
/// Special cases are MOVE_NONE and MOVE_NULL. We can sneak these in because in
/// any normal move destination square is always different from origin square
/// while MOVE_NONE and MOVE_NULL have the same origin and destination square.
enum Move : int {
MOVE_NONE,
MOVE_NULL = 65
};
enum MoveType {
NORMAL,
PROMOTION = 1 << 14,
EN_PASSANT = 2 << 14,
CASTLING = 3 << 14
};
enum Color {
WHITE, BLACK, COLOR_NB = 2
WHITE,
BLACK,
COLOR_NB = 2
};
enum CastlingRights {
NO_CASTLING,
WHITE_OO,
WHITE_OOO = WHITE_OO << 1,
BLACK_OO = WHITE_OO << 2,
BLACK_OOO = WHITE_OO << 3,
NO_CASTLING,
WHITE_OO,
WHITE_OOO = WHITE_OO << 1,
BLACK_OO = WHITE_OO << 2,
BLACK_OOO = WHITE_OO << 3,
KING_SIDE = WHITE_OO | BLACK_OO,
QUEEN_SIDE = WHITE_OOO | BLACK_OOO,
WHITE_CASTLING = WHITE_OO | WHITE_OOO,
BLACK_CASTLING = BLACK_OO | BLACK_OOO,
ANY_CASTLING = WHITE_CASTLING | BLACK_CASTLING,
KING_SIDE = WHITE_OO | BLACK_OO,
QUEEN_SIDE = WHITE_OOO | BLACK_OOO,
WHITE_CASTLING = WHITE_OO | WHITE_OOO,
BLACK_CASTLING = BLACK_OO | BLACK_OOO,
ANY_CASTLING = WHITE_CASTLING | BLACK_CASTLING,
CASTLING_RIGHT_NB = 16
};
enum Phase {
PHASE_ENDGAME,
PHASE_MIDGAME = 128,
MG = 0, EG = 1, PHASE_NB = 2
};
enum ScaleFactor {
SCALE_FACTOR_DRAW = 0,
SCALE_FACTOR_NORMAL = 64,
SCALE_FACTOR_MAX = 128,
SCALE_FACTOR_NONE = 255
CASTLING_RIGHT_NB = 16
};
enum Bound {
BOUND_NONE,
BOUND_UPPER,
BOUND_LOWER,
BOUND_EXACT = BOUND_UPPER | BOUND_LOWER
BOUND_NONE,
BOUND_UPPER,
BOUND_LOWER,
BOUND_EXACT = BOUND_UPPER | BOUND_LOWER
};
enum ExplosionState {
EXPLOSION_NONE,
MUST_CALM_DOWN
};
// Value is used as an alias for int16_t, this is done to differentiate between
// a search value and any other integer value. The values used in search are always
// supposed to be in the range (-VALUE_NONE, VALUE_NONE] and should not exceed this range.
using Value = int;
enum Value : int {
VALUE_ZERO = 0,
VALUE_DRAW = 0,
VALUE_KNOWN_WIN = 10000,
VALUE_MATE = 32000,
VALUE_INFINITE = 32001,
VALUE_NONE = 32002,
constexpr Value VALUE_ZERO = 0;
constexpr Value VALUE_DRAW = 0;
constexpr Value VALUE_NONE = 32002;
constexpr Value VALUE_INFINITE = 32001;
VALUE_TB_WIN_IN_MAX_PLY = VALUE_MATE - 2 * MAX_PLY,
VALUE_TB_LOSS_IN_MAX_PLY = -VALUE_TB_WIN_IN_MAX_PLY,
VALUE_MATE_IN_MAX_PLY = VALUE_MATE - MAX_PLY,
VALUE_MATED_IN_MAX_PLY = -VALUE_MATE_IN_MAX_PLY,
constexpr Value VALUE_MATE = 32000;
constexpr Value VALUE_MATE_IN_MAX_PLY = VALUE_MATE - MAX_PLY;
constexpr Value VALUE_MATED_IN_MAX_PLY = -VALUE_MATE_IN_MAX_PLY;
PawnValueMg = 126, PawnValueEg = 208,
KnightValueMg = 781, KnightValueEg = 854,
BishopValueMg = 825, BishopValueEg = 915,
RookValueMg = 1276, RookValueEg = 1380,
QueenValueMg = 2538, QueenValueEg = 2682,
constexpr Value VALUE_TB = VALUE_MATE_IN_MAX_PLY - 1;
constexpr Value VALUE_TB_WIN_IN_MAX_PLY = VALUE_TB - MAX_PLY;
constexpr Value VALUE_TB_LOSS_IN_MAX_PLY = -VALUE_TB_WIN_IN_MAX_PLY;
MidgameLimit = 15258, EndgameLimit = 3915
};
// In the code, we make the assumption that these values
// are such that non_pawn_material() can be used to uniquely
// identify the material on the board.
constexpr Value PawnValue = 208;
constexpr Value KnightValue = 781;
constexpr Value BishopValue = 825;
constexpr Value RookValue = 1276;
constexpr Value QueenValue = 2538;
// clang-format off
enum PieceType {
NO_PIECE_TYPE, PAWN, KNIGHT, BISHOP, ROOK, QUEEN, KING,
ALL_PIECES = 0,
PIECE_TYPE_NB = 8
NO_PIECE_TYPE, PAWN, KNIGHT, BISHOP, ROOK, QUEEN, KING,
ALL_PIECES = 0,
PIECE_TYPE_NB = 8
};
enum Piece {
NO_PIECE,
W_PAWN = PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING,
B_PAWN = PAWN + 8, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING,
PIECE_NB = 16
NO_PIECE,
W_PAWN = PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING,
B_PAWN = PAWN + 8, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING,
PIECE_NB = 16
};
// clang-format on
constexpr Value PieceValue[PHASE_NB][PIECE_NB] = {
{ VALUE_ZERO, PawnValueMg, KnightValueMg, BishopValueMg, RookValueMg, QueenValueMg, VALUE_ZERO, VALUE_ZERO,
VALUE_ZERO, PawnValueMg, KnightValueMg, BishopValueMg, RookValueMg, QueenValueMg, VALUE_ZERO, VALUE_ZERO },
{ VALUE_ZERO, PawnValueEg, KnightValueEg, BishopValueEg, RookValueEg, QueenValueEg, VALUE_ZERO, VALUE_ZERO,
VALUE_ZERO, PawnValueEg, KnightValueEg, BishopValueEg, RookValueEg, QueenValueEg, VALUE_ZERO, VALUE_ZERO }
};
constexpr Value PieceValue[PIECE_NB] = {
VALUE_ZERO, PawnValue, KnightValue, BishopValue, RookValue, QueenValue, VALUE_ZERO, VALUE_ZERO,
VALUE_ZERO, PawnValue, KnightValue, BishopValue, RookValue, QueenValue, VALUE_ZERO, VALUE_ZERO};
typedef int Depth;
using Depth = int;
enum : int {
DEPTH_QS_CHECKS = 0,
DEPTH_QS_NO_CHECKS = -1,
DEPTH_QS_RECAPTURES = -5,
DEPTH_QS_CHECKS = 0,
DEPTH_QS_NO_CHECKS = -1,
DEPTH_NONE = -6,
DEPTH_NONE = -6,
DEPTH_OFFSET = -7 // value used only for TT entry occupancy check
DEPTH_OFFSET = -7 // value used only for TT entry occupancy check
};
// clang-format off
enum Square : int {
SQ_A1, SQ_B1, SQ_C1, SQ_D1, SQ_E1, SQ_F1, SQ_G1, SQ_H1,
SQ_A2, SQ_B2, SQ_C2, SQ_D2, SQ_E2, SQ_F2, SQ_G2, SQ_H2,
SQ_A3, SQ_B3, SQ_C3, SQ_D3, SQ_E3, SQ_F3, SQ_G3, SQ_H3,
SQ_A4, SQ_B4, SQ_C4, SQ_D4, SQ_E4, SQ_F4, SQ_G4, SQ_H4,
SQ_A5, SQ_B5, SQ_C5, SQ_D5, SQ_E5, SQ_F5, SQ_G5, SQ_H5,
SQ_A6, SQ_B6, SQ_C6, SQ_D6, SQ_E6, SQ_F6, SQ_G6, SQ_H6,
SQ_A7, SQ_B7, SQ_C7, SQ_D7, SQ_E7, SQ_F7, SQ_G7, SQ_H7,
SQ_A8, SQ_B8, SQ_C8, SQ_D8, SQ_E8, SQ_F8, SQ_G8, SQ_H8,
SQ_NONE,
SQ_A1, SQ_B1, SQ_C1, SQ_D1, SQ_E1, SQ_F1, SQ_G1, SQ_H1,
SQ_A2, SQ_B2, SQ_C2, SQ_D2, SQ_E2, SQ_F2, SQ_G2, SQ_H2,
SQ_A3, SQ_B3, SQ_C3, SQ_D3, SQ_E3, SQ_F3, SQ_G3, SQ_H3,
SQ_A4, SQ_B4, SQ_C4, SQ_D4, SQ_E4, SQ_F4, SQ_G4, SQ_H4,
SQ_A5, SQ_B5, SQ_C5, SQ_D5, SQ_E5, SQ_F5, SQ_G5, SQ_H5,
SQ_A6, SQ_B6, SQ_C6, SQ_D6, SQ_E6, SQ_F6, SQ_G6, SQ_H6,
SQ_A7, SQ_B7, SQ_C7, SQ_D7, SQ_E7, SQ_F7, SQ_G7, SQ_H7,
SQ_A8, SQ_B8, SQ_C8, SQ_D8, SQ_E8, SQ_F8, SQ_G8, SQ_H8,
SQ_NONE,
SQUARE_ZERO = 0,
SQUARE_NB = 64
SQUARE_ZERO = 0,
SQUARE_NB = 64
};
// clang-format on
enum Direction : int {
NORTH = 8,
EAST = 1,
SOUTH = -NORTH,
WEST = -EAST,
NORTH = 8,
EAST = 1,
SOUTH = -NORTH,
WEST = -EAST,
NORTH_EAST = NORTH + EAST,
SOUTH_EAST = SOUTH + EAST,
SOUTH_WEST = SOUTH + WEST,
NORTH_WEST = NORTH + WEST
NORTH_EAST = NORTH + EAST,
SOUTH_EAST = SOUTH + EAST,
SOUTH_WEST = SOUTH + WEST,
NORTH_WEST = NORTH + WEST
};
enum File : int {
FILE_A, FILE_B, FILE_C, FILE_D, FILE_E, FILE_F, FILE_G, FILE_H, FILE_NB
FILE_A,
FILE_B,
FILE_C,
FILE_D,
FILE_E,
FILE_F,
FILE_G,
FILE_H,
FILE_NB
};
enum Rank : int {
RANK_1, RANK_2, RANK_3, RANK_4, RANK_5, RANK_6, RANK_7, RANK_8, RANK_NB
RANK_1,
RANK_2,
RANK_3,
RANK_4,
RANK_5,
RANK_6,
RANK_7,
RANK_8,
RANK_NB
};
// Keep track of what a move changes on the board (used by NNUE)
struct DirtyPiece {
// Number of changed pieces
int dirty_num;
// Number of changed pieces
int dirty_num;
// Max 3 pieces can change in one move. A promotion with capture moves
// both the pawn and the captured piece to SQ_NONE and the piece promoted
// to from SQ_NONE to the capture square.
Piece piece[3];
// Max 3 pieces can change in one move. A promotion with capture moves
// both the pawn and the captured piece to SQ_NONE and the piece promoted
// to from SQ_NONE to the capture square.
Piece piece[3];
// From and to squares, which may be SQ_NONE
Square from[3];
Square to[3];
// From and to squares, which may be SQ_NONE
Square from[3];
Square to[3];
};
/// Score enum stores a middlegame and an endgame value in a single integer (enum).
/// The least significant 16 bits are used to store the middlegame value and the
/// upper 16 bits are used to store the endgame value. We have to take care to
/// avoid left-shifting a signed int to avoid undefined behavior.
enum Score : int { SCORE_ZERO };
#define ENABLE_INCR_OPERATORS_ON(T) \
inline T& operator++(T& d) { return d = T(int(d) + 1); } \
inline T& operator--(T& d) { return d = T(int(d) - 1); }
constexpr Score make_score(int mg, int eg) {
return Score((int)((unsigned int)eg << 16) + mg);
}
/// Extracting the signed lower and upper 16 bits is not so trivial because
/// according to the standard a simple cast to short is implementation defined
/// and so is a right shift of a signed integer.
inline Value eg_value(Score s) {
union { uint16_t u; int16_t s; } eg = { uint16_t(unsigned(s + 0x8000) >> 16) };
return Value(eg.s);
}
inline Value mg_value(Score s) {
union { uint16_t u; int16_t s; } mg = { uint16_t(unsigned(s)) };
return Value(mg.s);
}
#define ENABLE_BASE_OPERATORS_ON(T) \
constexpr T operator+(T d1, int d2) { return T(int(d1) + d2); } \
constexpr T operator-(T d1, int d2) { return T(int(d1) - d2); } \
constexpr T operator-(T d) { return T(-int(d)); } \
inline T& operator+=(T& d1, int d2) { return d1 = d1 + d2; } \
inline T& operator-=(T& d1, int d2) { return d1 = d1 - d2; }
#define ENABLE_INCR_OPERATORS_ON(T) \
inline T& operator++(T& d) { return d = T(int(d) + 1); } \
inline T& operator--(T& d) { return d = T(int(d) - 1); }
#define ENABLE_FULL_OPERATORS_ON(T) \
ENABLE_BASE_OPERATORS_ON(T) \
constexpr T operator*(int i, T d) { return T(i * int(d)); } \
constexpr T operator*(T d, int i) { return T(int(d) * i); } \
constexpr T operator/(T d, int i) { return T(int(d) / i); } \
constexpr int operator/(T d1, T d2) { return int(d1) / int(d2); } \
inline T& operator*=(T& d, int i) { return d = T(int(d) * i); } \
inline T& operator/=(T& d, int i) { return d = T(int(d) / i); }
ENABLE_FULL_OPERATORS_ON(Value)
ENABLE_FULL_OPERATORS_ON(Direction)
ENABLE_INCR_OPERATORS_ON(Piece)
ENABLE_INCR_OPERATORS_ON(PieceType)
ENABLE_INCR_OPERATORS_ON(Square)
ENABLE_INCR_OPERATORS_ON(File)
ENABLE_INCR_OPERATORS_ON(Rank)
ENABLE_BASE_OPERATORS_ON(Score)
#undef ENABLE_INCR_OPERATORS_ON
#undef ENABLE_FULL_OPERATORS_ON
#undef ENABLE_INCR_OPERATORS_ON
#undef ENABLE_BASE_OPERATORS_ON
constexpr Direction operator+(Direction d1, Direction d2) { return Direction(int(d1) + int(d2)); }
constexpr Direction operator*(int i, Direction d) { return Direction(i * int(d)); }
/// Additional operators to add a Direction to a Square
// Additional operators to add a Direction to a Square
constexpr Square operator+(Square s, Direction d) { return Square(int(s) + int(d)); }
constexpr Square operator-(Square s, Direction d) { return Square(int(s) - int(d)); }
inline Square& operator+=(Square& s, Direction d) { return s = s + d; }
inline Square& operator-=(Square& s, Direction d) { return s = s - d; }
inline Square& operator+=(Square& s, Direction d) { return s = s + d; }
inline Square& operator-=(Square& s, Direction d) { return s = s - d; }
/// Only declared but not defined. We don't want to multiply two scores due to
/// a very high risk of overflow. So user should explicitly convert to integer.
Score operator*(Score, Score) = delete;
// Toggle color
constexpr Color operator~(Color c) { return Color(c ^ BLACK); }
/// Division of a Score must be handled separately for each term
inline Score operator/(Score s, int i) {
return make_score(mg_value(s) / i, eg_value(s) / i);
}
// Swap A1 <-> A8
constexpr Square flip_rank(Square s) { return Square(s ^ SQ_A8); }
/// Multiplication of a Score by an integer. We check for overflow in debug mode.
inline Score operator*(Score s, int i) {
// Swap A1 <-> H1
constexpr Square flip_file(Square s) { return Square(s ^ SQ_H1); }
Score result = Score(int(s) * i);
assert(eg_value(result) == (i * eg_value(s)));
assert(mg_value(result) == (i * mg_value(s)));
assert((i == 0) || (result / i) == s);
return result;
}
/// Multiplication of a Score by a boolean
inline Score operator*(Score s, bool b) {
return b ? s : SCORE_ZERO;
}
constexpr Color operator~(Color c) {
return Color(c ^ BLACK); // Toggle color
}
constexpr Square flip_rank(Square s) { // Swap A1 <-> A8
return Square(s ^ SQ_A8);
}
constexpr Square flip_file(Square s) { // Swap A1 <-> H1
return Square(s ^ SQ_H1);
}
constexpr Piece operator~(Piece pc) {
return Piece(pc ^ 8); // Swap color of piece B_KNIGHT <-> W_KNIGHT
}
// Swap color of piece B_KNIGHT <-> W_KNIGHT
constexpr Piece operator~(Piece pc) { return Piece(pc ^ 8); }
constexpr CastlingRights operator&(Color c, CastlingRights cr) {
return CastlingRights((c == WHITE ? WHITE_CASTLING : BLACK_CASTLING) & cr);
return CastlingRights((c == WHITE ? WHITE_CASTLING : BLACK_CASTLING) & cr);
}
constexpr Value mate_in(int ply) {
return VALUE_MATE - ply;
}
constexpr Value mate_in(int ply) { return VALUE_MATE - ply; }
constexpr Value mated_in(int ply) {
return -VALUE_MATE + ply;
}
constexpr Value mated_in(int ply) { return -VALUE_MATE + ply; }
constexpr Square make_square(File f, Rank r) {
return Square((r << 3) + f);
}
constexpr Square make_square(File f, Rank r) { return Square((r << 3) + f); }
constexpr Piece make_piece(Color c, PieceType pt) {
return Piece((c << 3) + pt);
}
constexpr Piece make_piece(Color c, PieceType pt) { return Piece((c << 3) + pt); }
constexpr PieceType type_of(Piece pc) {
return PieceType(pc & 7);
}
constexpr PieceType type_of(Piece pc) { return PieceType(pc & 7); }
inline Color color_of(Piece pc) {
assert(pc != NO_PIECE);
return Color(pc >> 3);
assert(pc != NO_PIECE);
return Color(pc >> 3);
}
constexpr bool is_ok(Square s) {
return s >= SQ_A1 && s <= SQ_H8;
}
constexpr bool is_ok(Square s) { return s >= SQ_A1 && s <= SQ_H8; }
constexpr File file_of(Square s) {
return File(s & 7);
}
constexpr File file_of(Square s) { return File(s & 7); }
constexpr Rank rank_of(Square s) {
return Rank(s >> 3);
}
constexpr Rank rank_of(Square s) { return Rank(s >> 3); }
constexpr Square relative_square(Color c, Square s) {
return Square(s ^ (c * 56));
}
constexpr Square relative_square(Color c, Square s) { return Square(s ^ (c * 56)); }
constexpr Rank relative_rank(Color c, Rank r) {
return Rank(r ^ (c * 7));
}
constexpr Rank relative_rank(Color c, Rank r) { return Rank(r ^ (c * 7)); }
constexpr Rank relative_rank(Color c, Square s) {
return relative_rank(c, rank_of(s));
}
constexpr Rank relative_rank(Color c, Square s) { return relative_rank(c, rank_of(s)); }
constexpr Direction pawn_push(Color c) {
return c == WHITE ? NORTH : SOUTH;
}
constexpr Direction pawn_push(Color c) { return c == WHITE ? NORTH : SOUTH; }
constexpr Square from_sq(Move m) {
return Square((m >> 6) & 0x3F);
}
constexpr Square to_sq(Move m) {
return Square(m & 0x3F);
}
constexpr int from_to(Move m) {
return m & 0xFFF;
}
constexpr MoveType type_of(Move m) {
return MoveType(m & (3 << 14));
}
constexpr PieceType promotion_type(Move m) {
return PieceType(((m >> 12) & 3) + KNIGHT);
}
constexpr Move make_move(Square from, Square to) {
return Move((from << 6) + to);
}
constexpr Move reverse_move(Move m) {
return make_move(to_sq(m), from_sq(m));
}
template<MoveType T>
constexpr Move make(Square from, Square to, PieceType pt = KNIGHT) {
return Move(T + ((pt - KNIGHT) << 12) + (from << 6) + to);
}
constexpr bool is_ok(Move m) {
return from_sq(m) != to_sq(m); // Catch MOVE_NULL and MOVE_NONE
}
/// Based on a congruential pseudo random number generator
// Based on a congruential pseudo-random number generator
constexpr Key make_key(uint64_t seed) {
return seed * 6364136223846793005ULL + 1442695040888963407ULL;
return seed * 6364136223846793005ULL + 1442695040888963407ULL;
}
} // namespace Stockfish
#endif // #ifndef TYPES_H_INCLUDED
enum MoveType {
NORMAL,
PROMOTION = 1 << 14,
EN_PASSANT = 2 << 14,
CASTLING = 3 << 14
};
#include "tune.h" // Global visibility to tuning setup
// A move needs 16 bits to be stored
//
// bit 0- 5: destination square (from 0 to 63)
// bit 6-11: origin square (from 0 to 63)
// bit 12-13: promotion piece type - 2 (from KNIGHT-2 to QUEEN-2)
// bit 14-15: special move flag: promotion (1), en passant (2), castling (3)
// NOTE: en passant bit is set only when a pawn can be captured
//
// Special cases are Move::none() and Move::null(). We can sneak these in because in
// any normal move destination square is always different from origin square
// while Move::none() and Move::null() have the same origin and destination square.
class Move {
public:
Move() = default;
constexpr explicit Move(std::uint16_t d) :
data(d) {}
constexpr Move(Square from, Square to) :
data((from << 6) + to) {}
template<MoveType T>
static constexpr Move make(Square from, Square to, PieceType pt = KNIGHT) {
return Move(T + ((pt - KNIGHT) << 12) + (from << 6) + to);
}
constexpr Square from_sq() const {
assert(is_ok());
return Square((data >> 6) & 0x3F);
}
constexpr Square to_sq() const {
assert(is_ok());
return Square(data & 0x3F);
}
constexpr int from_to() const { return data & 0xFFF; }
constexpr MoveType type_of() const { return MoveType(data & (3 << 14)); }
constexpr PieceType promotion_type() const { return PieceType(((data >> 12) & 3) + KNIGHT); }
constexpr bool is_ok() const { return none().data != data && null().data != data; }
static constexpr Move null() { return Move(65); }
static constexpr Move none() { return Move(0); }
constexpr bool operator==(const Move& m) const { return data == m.data; }
constexpr bool operator!=(const Move& m) const { return data != m.data; }
constexpr explicit operator bool() const { return data != 0; }
constexpr std::uint16_t raw() const { return data; }
struct MoveHash {
std::size_t operator()(const Move& m) const { return make_key(m.data); }
};
protected:
std::uint16_t data;
};
} // namespace Stockfish
#endif // #ifndef TYPES_H_INCLUDED
#include "tune.h" // Global visibility to tuning setup
+342 -306
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -16,50 +16,296 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cassert>
#include <cmath>
#include <iostream>
#include <sstream>
#include <string>
#include "uci.h"
#include <algorithm>
#include <cassert>
#include <cctype>
#include <cmath>
#include <cstdlib>
#include <deque>
#include <memory>
#include <optional>
#include <sstream>
#include <vector>
#include <cstdint>
#include "benchmark.h"
#include "evaluate.h"
#include "movegen.h"
#include "nnue/evaluate_nnue.h"
#include "nnue/nnue_architecture.h"
#include "position.h"
#include "search.h"
#include "thread.h"
#include "timeman.h"
#include "tt.h"
#include "uci.h"
#include "syzygy/tbprobe.h"
using namespace std;
#include "types.h"
#include "ucioption.h"
#include "perft.h"
namespace Stockfish {
extern vector<string> setup_bench(const Position&, istream&);
constexpr auto StartFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
constexpr int NormalizeToPawnValue = 356;
constexpr int MaxHashMB = Is64Bit ? 33554432 : 2048;
namespace {
UCI::UCI(int argc, char** argv) :
cli(argc, argv) {
// FEN string of the initial position, normal chess
const char* StartFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
evalFiles = {{Eval::NNUE::Big, {"EvalFile", EvalFileDefaultNameBig, "None", ""}},
{Eval::NNUE::Small, {"EvalFileSmall", EvalFileDefaultNameSmall, "None", ""}}};
// position() is called when engine receives the "position" UCI command.
// The function sets up the position described in the given FEN string ("fen")
// or the starting position ("startpos") and then makes the moves given in the
// following move list ("moves").
options["Debug Log File"] << Option("", [](const Option& o) { start_logger(o); });
void position(Position& pos, istringstream& is, StateListPtr& states) {
options["Threads"] << Option(1, 1, 1024, [this](const Option&) {
threads.set({options, threads, tt});
});
Move m;
string token, fen;
options["Hash"] << Option(16, 1, MaxHashMB, [this](const Option& o) {
threads.main_thread()->wait_for_search_finished();
tt.resize(o, options["Threads"]);
});
options["Clear Hash"] << Option([this](const Option&) { search_clear(); });
options["Ponder"] << Option(false);
options["MultiPV"] << Option(1, 1, MAX_MOVES);
options["Skill Level"] << Option(20, 0, 20);
options["Move Overhead"] << Option(10, 0, 5000);
options["nodestime"] << Option(0, 0, 10000);
options["UCI_Chess960"] << Option(false);
options["UCI_LimitStrength"] << Option(false);
options["UCI_Elo"] << Option(1320, 1320, 3190);
options["UCI_ShowWDL"] << Option(false);
options["SyzygyPath"] << Option("<empty>", [](const Option& o) { Tablebases::init(o); });
options["SyzygyProbeDepth"] << Option(1, 1, 100);
options["Syzygy50MoveRule"] << Option(true);
options["SyzygyProbeLimit"] << Option(7, 0, 7);
options["EvalFile"] << Option(EvalFileDefaultNameBig, [this](const Option&) {
evalFiles = Eval::NNUE::load_networks(cli.binaryDirectory, options, evalFiles);
});
options["EvalFileSmall"] << Option(EvalFileDefaultNameSmall, [this](const Option&) {
evalFiles = Eval::NNUE::load_networks(cli.binaryDirectory, options, evalFiles);
});
threads.set({options, threads, tt});
search_clear(); // After threads are up
}
void UCI::loop() {
Position pos;
std::string token, cmd;
StateListPtr states(new std::deque<StateInfo>(1));
pos.set(StartFEN, false, &states->back());
for (int i = 1; i < cli.argc; ++i)
cmd += std::string(cli.argv[i]) + " ";
do
{
if (cli.argc == 1
&& !getline(std::cin, cmd)) // Wait for an input or an end-of-file (EOF) indication
cmd = "quit";
std::istringstream is(cmd);
token.clear(); // Avoid a stale if getline() returns nothing or a blank line
is >> std::skipws >> token;
if (token == "quit" || token == "stop")
threads.stop = true;
// The GUI sends 'ponderhit' to tell that the user has played the expected move.
// So, 'ponderhit' is sent if pondering was done on the same move that the user
// has played. The search should continue, but should also switch from pondering
// to the normal search.
else if (token == "ponderhit")
threads.main_manager()->ponder = false; // Switch to the normal search
else if (token == "uci")
sync_cout << "id name " << engine_info(true) << "\n"
<< options << "\nuciok" << sync_endl;
else if (token == "setoption")
setoption(is);
else if (token == "go")
go(pos, is, states);
else if (token == "position")
position(pos, is, states);
else if (token == "ucinewgame")
search_clear();
else if (token == "isready")
sync_cout << "readyok" << sync_endl;
// Add custom non-UCI commands, mainly for debugging purposes.
// These commands must not be used during a search!
else if (token == "flip")
pos.flip();
else if (token == "bench")
bench(pos, is, states);
else if (token == "d")
sync_cout << pos << sync_endl;
else if (token == "eval")
trace_eval(pos);
else if (token == "compiler")
sync_cout << compiler_info() << sync_endl;
else if (token == "export_net")
{
std::optional<std::string> filename;
std::string f;
if (is >> std::skipws >> f)
filename = f;
Eval::NNUE::save_eval(filename, Eval::NNUE::Big, evalFiles);
}
else if (token == "--help" || token == "help" || token == "--license" || token == "license")
sync_cout
<< "\nStockfish is a powerful chess engine for playing and analyzing."
"\nIt is released as free software licensed under the GNU GPLv3 License."
"\nStockfish is normally used with a graphical user interface (GUI) and implements"
"\nthe Universal Chess Interface (UCI) protocol to communicate with a GUI, an API, etc."
"\nFor any further information, visit https://github.com/official-stockfish/Stockfish#readme"
"\nor read the corresponding README.md and Copying.txt files distributed along with this program.\n"
<< sync_endl;
else if (!token.empty() && token[0] != '#')
sync_cout << "Unknown command: '" << cmd << "'. Type help for more information."
<< sync_endl;
} while (token != "quit" && cli.argc == 1); // The command-line arguments are one-shot
}
void UCI::go(Position& pos, std::istringstream& is, StateListPtr& states) {
Search::LimitsType limits;
std::string token;
bool ponderMode = false;
limits.startTime = now(); // The search starts as early as possible
while (is >> token)
if (token == "searchmoves") // Needs to be the last command on the line
while (is >> token)
limits.searchmoves.push_back(to_move(pos, token));
else if (token == "wtime")
is >> limits.time[WHITE];
else if (token == "btime")
is >> limits.time[BLACK];
else if (token == "winc")
is >> limits.inc[WHITE];
else if (token == "binc")
is >> limits.inc[BLACK];
else if (token == "movestogo")
is >> limits.movestogo;
else if (token == "depth")
is >> limits.depth;
else if (token == "nodes")
is >> limits.nodes;
else if (token == "movetime")
is >> limits.movetime;
else if (token == "mate")
is >> limits.mate;
else if (token == "perft")
is >> limits.perft;
else if (token == "infinite")
limits.infinite = 1;
else if (token == "ponder")
ponderMode = true;
Eval::NNUE::verify(options, evalFiles);
if (limits.perft)
{
perft(pos.fen(), limits.perft, options["UCI_Chess960"]);
return;
}
threads.start_thinking(options, pos, states, limits, ponderMode);
}
void UCI::bench(Position& pos, std::istream& args, StateListPtr& states) {
std::string token;
uint64_t num, nodes = 0, cnt = 1;
std::vector<std::string> list = setup_bench(pos, args);
num = count_if(list.begin(), list.end(),
[](const std::string& s) { return s.find("go ") == 0 || s.find("eval") == 0; });
TimePoint elapsed = now();
for (const auto& cmd : list)
{
std::istringstream is(cmd);
is >> std::skipws >> token;
if (token == "go" || token == "eval")
{
std::cerr << "\nPosition: " << cnt++ << '/' << num << " (" << pos.fen() << ")"
<< std::endl;
if (token == "go")
{
go(pos, is, states);
threads.main_thread()->wait_for_search_finished();
nodes += threads.nodes_searched();
}
else
trace_eval(pos);
}
else if (token == "setoption")
setoption(is);
else if (token == "position")
position(pos, is, states);
else if (token == "ucinewgame")
{
search_clear(); // Search::clear() may take a while
elapsed = now();
}
}
elapsed = now() - elapsed + 1; // Ensure positivity to avoid a 'divide by zero'
dbg_print();
std::cerr << "\n==========================="
<< "\nTotal time (ms) : " << elapsed << "\nNodes searched : " << nodes
<< "\nNodes/second : " << 1000 * nodes / elapsed << std::endl;
}
void UCI::trace_eval(Position& pos) {
StateListPtr states(new std::deque<StateInfo>(1));
Position p;
p.set(pos.fen(), options["UCI_Chess960"], &states->back());
Eval::NNUE::verify(options, evalFiles);
sync_cout << "\n" << Eval::trace(p) << sync_endl;
}
void UCI::search_clear() {
threads.main_thread()->wait_for_search_finished();
tt.clear(options["Threads"]);
threads.clear();
Tablebases::init(options["SyzygyPath"]); // Free mapped files
}
void UCI::setoption(std::istringstream& is) {
threads.main_thread()->wait_for_search_finished();
options.setoption(is);
}
void UCI::position(Position& pos, std::istringstream& is, StateListPtr& states) {
Move m;
std::string token, fen;
is >> token;
if (token == "startpos")
{
fen = StartFEN;
is >> token; // Consume "moves" token if any
is >> token; // Consume the "moves" token, if any
}
else if (token == "fen")
while (is >> token && token != "moves")
@@ -67,317 +313,107 @@ namespace {
else
return;
states = StateListPtr(new std::deque<StateInfo>(1)); // Drop old and create a new one
pos.set(fen, Options["UCI_Chess960"], &states->back(), Threads.main());
states = StateListPtr(new std::deque<StateInfo>(1)); // Drop the old state and create a new one
pos.set(fen, options["UCI_Chess960"], &states->back());
// Parse move list (if any)
while (is >> token && (m = UCI::to_move(pos, token)) != MOVE_NONE)
// Parse the move list, if any
while (is >> token && (m = to_move(pos, token)) != Move::none())
{
states->emplace_back();
pos.do_move(m, states->back());
}
}
}
// trace_eval() prints the evaluation for the current position, consistent with the UCI
// options set so far.
int UCI::to_cp(Value v) { return 100 * v / NormalizeToPawnValue; }
void trace_eval(Position& pos) {
std::string UCI::value(Value v) {
assert(-VALUE_INFINITE < v && v < VALUE_INFINITE);
StateListPtr states(new std::deque<StateInfo>(1));
Position p;
p.set(pos.fen(), Options["UCI_Chess960"], &states->back(), Threads.main());
std::stringstream ss;
Eval::NNUE::verify();
sync_cout << "\n" << Eval::trace(p) << sync_endl;
}
// setoption() is called when engine receives the "setoption" UCI command. The
// function updates the UCI option ("name") to the given value ("value").
void setoption(istringstream& is) {
string token, name, value;
is >> token; // Consume "name" token
// Read option name (can contain spaces)
while (is >> token && token != "value")
name += (name.empty() ? "" : " ") + token;
// Read option value (can contain spaces)
while (is >> token)
value += (value.empty() ? "" : " ") + token;
if (Options.count(name))
Options[name] = value;
else
sync_cout << "No such option: " << name << sync_endl;
}
// go() is called when engine receives the "go" UCI command. The function sets
// the thinking time and other parameters from the input string, then starts
// the search.
void go(Position& pos, istringstream& is, StateListPtr& states) {
Search::LimitsType limits;
string token;
bool ponderMode = false;
limits.startTime = now(); // As early as possible!
while (is >> token)
if (token == "searchmoves") // Needs to be the last command on the line
while (is >> token)
limits.searchmoves.push_back(UCI::to_move(pos, token));
else if (token == "wtime") is >> limits.time[WHITE];
else if (token == "btime") is >> limits.time[BLACK];
else if (token == "winc") is >> limits.inc[WHITE];
else if (token == "binc") is >> limits.inc[BLACK];
else if (token == "movestogo") is >> limits.movestogo;
else if (token == "depth") is >> limits.depth;
else if (token == "nodes") is >> limits.nodes;
else if (token == "movetime") is >> limits.movetime;
else if (token == "mate") is >> limits.mate;
else if (token == "perft") is >> limits.perft;
else if (token == "infinite") limits.infinite = 1;
else if (token == "ponder") ponderMode = true;
Threads.start_thinking(pos, states, limits, ponderMode);
}
// bench() is called when engine receives the "bench" command. Firstly
// a list of UCI commands is setup according to bench parameters, then
// it is run one by one printing a summary at the end.
void bench(Position& pos, istream& args, StateListPtr& states) {
string token;
uint64_t num, nodes = 0, cnt = 1;
vector<string> list = setup_bench(pos, args);
num = count_if(list.begin(), list.end(), [](string s) { return s.find("go ") == 0 || s.find("eval") == 0; });
TimePoint elapsed = now();
for (const auto& cmd : list)
if (std::abs(v) < VALUE_TB_WIN_IN_MAX_PLY)
ss << "cp " << to_cp(v);
else if (std::abs(v) <= VALUE_TB)
{
istringstream is(cmd);
is >> skipws >> token;
if (token == "go" || token == "eval")
{
cerr << "\nPosition: " << cnt++ << '/' << num << " (" << pos.fen() << ")" << endl;
if (token == "go")
{
go(pos, is, states);
Threads.main()->wait_for_search_finished();
nodes += Threads.nodes_searched();
}
else
trace_eval(pos);
}
else if (token == "setoption") setoption(is);
else if (token == "position") position(pos, is, states);
else if (token == "ucinewgame") { Search::clear(); elapsed = now(); } // Search::clear() may take some while
const int ply = VALUE_TB - std::abs(v); // recompute ss->ply
ss << "cp " << (v > 0 ? 20000 - ply : -20000 + ply);
}
else
ss << "mate " << (v > 0 ? VALUE_MATE - v + 1 : -VALUE_MATE - v) / 2;
elapsed = now() - elapsed + 1; // Ensure positivity to avoid a 'divide by zero'
dbg_print(); // Just before exiting
cerr << "\n==========================="
<< "\nTotal time (ms) : " << elapsed
<< "\nNodes searched : " << nodes
<< "\nNodes/second : " << 1000 * nodes / elapsed << endl;
}
// The win rate model returns the probability (per mille) of winning given an eval
// and a game-ply. The model fits rather accurately the LTC fishtest statistics.
int win_rate_model(Value v, int ply) {
// The model captures only up to 240 plies, so limit input (and rescale)
double m = std::min(240, ply) / 64.0;
// Coefficients of a 3rd order polynomial fit based on fishtest data
// for two parameters needed to transform eval to the argument of a
// logistic function.
double as[] = {-3.68389304, 30.07065921, -60.52878723, 149.53378557};
double bs[] = {-2.0181857, 15.85685038, -29.83452023, 47.59078827};
double a = (((as[0] * m + as[1]) * m + as[2]) * m) + as[3];
double b = (((bs[0] * m + bs[1]) * m + bs[2]) * m) + bs[3];
// Transform eval to centipawns with limited range
double x = std::clamp(double(100 * v) / PawnValueEg, -2000.0, 2000.0);
// Return win rate in per mille (rounded to nearest)
return int(0.5 + 1000 / (1 + std::exp((a - x) / b)));
}
} // namespace
/// UCI::loop() waits for a command from stdin, parses it and calls the appropriate
/// function. Also intercepts EOF from stdin to ensure gracefully exiting if the
/// GUI dies unexpectedly. When called with some command line arguments, e.g. to
/// run 'bench', once the command is executed the function returns immediately.
/// In addition to the UCI ones, also some additional debug commands are supported.
void UCI::loop(int argc, char* argv[]) {
Position pos;
string token, cmd;
StateListPtr states(new std::deque<StateInfo>(1));
pos.set(StartFEN, false, &states->back(), Threads.main());
for (int i = 1; i < argc; ++i)
cmd += std::string(argv[i]) + " ";
do {
if (argc == 1 && !getline(cin, cmd)) // Block here waiting for input or EOF
cmd = "quit";
istringstream is(cmd);
token.clear(); // Avoid a stale if getline() returns empty or blank line
is >> skipws >> token;
if ( token == "quit"
|| token == "stop")
Threads.stop = true;
// The GUI sends 'ponderhit' to tell us the user has played the expected move.
// So 'ponderhit' will be sent if we were told to ponder on the same move the
// user has played. We should continue searching but switch from pondering to
// normal search.
else if (token == "ponderhit")
Threads.main()->ponder = false; // Switch to normal search
else if (token == "uci")
sync_cout << "id name " << engine_info(true)
<< "\n" << Options
<< "\nuciok" << sync_endl;
else if (token == "setoption") setoption(is);
else if (token == "go") go(pos, is, states);
else if (token == "position") position(pos, is, states);
else if (token == "ucinewgame") Search::clear();
else if (token == "isready") sync_cout << "readyok" << sync_endl;
// Additional custom non-UCI commands, mainly for debugging.
// Do not use these commands during a search!
else if (token == "flip") pos.flip();
else if (token == "bench") bench(pos, is, states);
else if (token == "d") sync_cout << pos << sync_endl;
else if (token == "eval") trace_eval(pos);
else if (token == "compiler") sync_cout << compiler_info() << sync_endl;
else if (token == "export_net")
{
std::optional<std::string> filename;
std::string f;
if (is >> skipws >> f)
filename = f;
Eval::NNUE::save_eval(filename);
}
else if (!token.empty() && token[0] != '#')
sync_cout << "Unknown command: " << cmd << sync_endl;
} while (token != "quit" && argc == 1); // Command line args are one-shot
return ss.str();
}
/// UCI::value() converts a Value to a string suitable for use with the UCI
/// protocol specification:
///
/// cp <x> The score from the engine's point of view in centipawns.
/// mate <y> Mate in y moves, not plies. If the engine is getting mated
/// use negative values for y.
string UCI::value(Value v) {
assert(-VALUE_INFINITE < v && v < VALUE_INFINITE);
stringstream ss;
if (abs(v) < VALUE_MATE_IN_MAX_PLY)
ss << "cp " << v * 100 / PawnValueEg;
else
ss << "mate " << (v > 0 ? VALUE_MATE - v + 1 : -VALUE_MATE - v) / 2;
return ss.str();
}
/// UCI::wdl() report WDL statistics given an evaluation and a game ply, based on
/// data gathered for fishtest LTC games.
string UCI::wdl(Value v, int ply) {
stringstream ss;
int wdl_w = win_rate_model( v, ply);
int wdl_l = win_rate_model(-v, ply);
int wdl_d = 1000 - wdl_w - wdl_l;
ss << " wdl " << wdl_w << " " << wdl_d << " " << wdl_l;
return ss.str();
}
/// UCI::square() converts a Square to a string in algebraic notation (g1, a7, etc.)
std::string UCI::square(Square s) {
return std::string{ char('a' + file_of(s)), char('1' + rank_of(s)) };
return std::string{char('a' + file_of(s)), char('1' + rank_of(s))};
}
std::string UCI::move(Move m, bool chess960) {
if (m == Move::none())
return "(none)";
/// UCI::move() converts a Move to a string in coordinate notation (g1f3, a7a8q).
/// The only special case is castling, where we print in the e1g1 notation in
/// normal chess mode, and in e1h1 notation in chess960 mode. Internally all
/// castling moves are always encoded as 'king captures rook'.
if (m == Move::null())
return "0000";
string UCI::move(Move m, bool chess960) {
Square from = m.from_sq();
Square to = m.to_sq();
Square from = from_sq(m);
Square to = to_sq(m);
if (m.type_of() == CASTLING && !chess960)
to = make_square(to > from ? FILE_G : FILE_C, rank_of(from));
if (m == MOVE_NONE)
return "(none)";
std::string move = square(from) + square(to);
if (m == MOVE_NULL)
return "0000";
if (m.type_of() == PROMOTION)
move += " pnbrqk"[m.promotion_type()];
if (type_of(m) == CASTLING && !chess960)
to = make_square(to > from ? FILE_G : FILE_C, rank_of(from));
string move = UCI::square(from) + UCI::square(to);
if (type_of(m) == PROMOTION)
move += " pnbrqk"[promotion_type(m)];
return move;
return move;
}
namespace {
// The win rate model returns the probability of winning (in per mille units) given an
// eval and a game ply. It fits the LTC fishtest statistics rather accurately.
int win_rate_model(Value v, int ply) {
/// UCI::to_move() converts a string representing a move in coordinate notation
/// (g1f3, a7a8q) to the corresponding legal Move, if any.
// The fitted model only uses data for moves in [8, 120], and is anchored at move 32.
double m = std::clamp(ply / 2 + 1, 8, 120) / 32.0;
Move UCI::to_move(const Position& pos, string& str) {
// The coefficients of a third-order polynomial fit is based on the fishtest data
// for two parameters that need to transform eval to the argument of a logistic
// function.
constexpr double as[] = {-1.06249702, 7.42016937, 0.89425629, 348.60356174};
constexpr double bs[] = {-5.33122190, 39.57831533, -90.84473771, 123.40620748};
if (str.length() == 5) // Junior could send promotion piece in uppercase
str[4] = char(tolower(str[4]));
// Enforce that NormalizeToPawnValue corresponds to a 50% win rate at move 32.
static_assert(NormalizeToPawnValue == int(0.5 + as[0] + as[1] + as[2] + as[3]));
for (const auto& m : MoveList<LEGAL>(pos))
if (str == UCI::move(m, pos.is_chess960()))
return m;
double a = (((as[0] * m + as[1]) * m + as[2]) * m) + as[3];
double b = (((bs[0] * m + bs[1]) * m + bs[2]) * m) + bs[3];
return MOVE_NONE;
// Return the win rate in per mille units, rounded to the nearest integer.
return int(0.5 + 1000 / (1 + std::exp((a - double(v)) / b)));
}
}
} // namespace Stockfish
std::string UCI::wdl(Value v, int ply) {
std::stringstream ss;
int wdl_w = win_rate_model(v, ply);
int wdl_l = win_rate_model(-v, ply);
int wdl_d = 1000 - wdl_w - wdl_l;
ss << " wdl " << wdl_w << " " << wdl_d << " " << wdl_l;
return ss.str();
}
Move UCI::to_move(const Position& pos, std::string& str) {
if (str.length() == 5)
str[4] = char(tolower(str[4])); // The promotion piece character must be lowercased
for (const auto& m : MoveList<LEGAL>(pos))
if (str == move(m, pos.is_chess960()))
return m;
return Move::none();
}
} // namespace Stockfish
+46 -54
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -19,67 +19,59 @@
#ifndef UCI_H_INCLUDED
#define UCI_H_INCLUDED
#include <map>
#include <iostream>
#include <string>
#include <unordered_map>
#include "types.h"
#include "evaluate.h"
#include "misc.h"
#include "position.h"
#include "thread.h"
#include "tt.h"
#include "ucioption.h"
namespace Stockfish {
class Position;
namespace Eval::NNUE {
enum NetSize : int;
}
namespace UCI {
class Move;
enum Square : int;
using Value = int;
class Option;
class UCI {
public:
UCI(int argc, char** argv);
/// Custom comparator because UCI options should be case insensitive
struct CaseInsensitiveLess {
bool operator() (const std::string&, const std::string&) const;
void loop();
static int to_cp(Value v);
static std::string value(Value v);
static std::string square(Square s);
static std::string move(Move m, bool chess960);
static std::string wdl(Value v, int ply);
static Move to_move(const Position& pos, std::string& str);
const std::string& workingDirectory() const { return cli.workingDirectory; }
OptionsMap options;
std::unordered_map<Eval::NNUE::NetSize, Eval::EvalFile> evalFiles;
private:
TranspositionTable tt;
ThreadPool threads;
CommandLine cli;
void go(Position& pos, std::istringstream& is, StateListPtr& states);
void bench(Position& pos, std::istream& args, StateListPtr& states);
void position(Position& pos, std::istringstream& is, StateListPtr& states);
void trace_eval(Position& pos);
void search_clear();
void setoption(std::istringstream& is);
};
/// Our options container is actually a std::map
typedef std::map<std::string, Option, CaseInsensitiveLess> OptionsMap;
} // namespace Stockfish
/// Option class implements an option as defined by UCI protocol
class Option {
typedef void (*OnChange)(const Option&);
public:
Option(OnChange = nullptr);
Option(bool v, OnChange = nullptr);
Option(const char* v, OnChange = nullptr);
Option(double v, int minv, int maxv, OnChange = nullptr);
Option(const char* v, const char* cur, OnChange = nullptr);
Option& operator=(const std::string&);
void operator<<(const Option&);
operator double() const;
operator std::string() const;
bool operator==(const char*) const;
private:
friend std::ostream& operator<<(std::ostream&, const OptionsMap&);
std::string defaultValue, currentValue, type;
int min, max;
size_t idx;
OnChange on_change;
};
void init(OptionsMap&);
void loop(int argc, char* argv[]);
std::string value(Value v);
std::string square(Square s);
std::string move(Move m, bool chess960);
std::string pv(const Position& pos, Depth depth, Value alpha, Value beta);
std::string wdl(Value v, int ply);
Move to_move(const Position& pos, std::string& str);
} // namespace UCI
extern UCI::OptionsMap Options;
} // namespace Stockfish
#endif // #ifndef UCI_H_INCLUDED
#endif // #ifndef UCI_H_INCLUDED
+117 -126
View File
@@ -1,6 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Copyright (C) 2004-2024 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
@@ -16,179 +16,170 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ucioption.h"
#include <algorithm>
#include <cassert>
#include <ostream>
#include <cctype>
#include <iostream>
#include <sstream>
#include <utility>
#include "evaluate.h"
#include "misc.h"
#include "search.h"
#include "thread.h"
#include "tt.h"
#include "uci.h"
#include "syzygy/tbprobe.h"
using std::string;
namespace Stockfish {
UCI::OptionsMap Options; // Global object
bool CaseInsensitiveLess::operator()(const std::string& s1, const std::string& s2) const {
namespace UCI {
/// 'On change' actions, triggered by an option's value change
void on_clear_hash(const Option&) { Search::clear(); }
void on_hash_size(const Option& o) { TT.resize(size_t(o)); }
void on_logger(const Option& o) { start_logger(o); }
void on_threads(const Option& o) { Threads.set(size_t(o)); }
void on_tb_path(const Option& o) { Tablebases::init(o); }
void on_use_NNUE(const Option& ) { Eval::NNUE::init(); }
void on_eval_file(const Option& ) { Eval::NNUE::init(); }
/// Our case insensitive less() function as required by UCI protocol
bool CaseInsensitiveLess::operator() (const string& s1, const string& s2) const {
return std::lexicographical_compare(s1.begin(), s1.end(), s2.begin(), s2.end(),
[](char c1, char c2) { return tolower(c1) < tolower(c2); });
return std::lexicographical_compare(
s1.begin(), s1.end(), s2.begin(), s2.end(),
[](char c1, char c2) { return std::tolower(c1) < std::tolower(c2); });
}
void OptionsMap::setoption(std::istringstream& is) {
std::string token, name, value;
/// UCI::init() initializes the UCI options to their hard-coded default values
is >> token; // Consume the "name" token
void init(OptionsMap& o) {
// Read the option name (can contain spaces)
while (is >> token && token != "value")
name += (name.empty() ? "" : " ") + token;
constexpr int MaxHashMB = Is64Bit ? 33554432 : 2048;
// Read the option value (can contain spaces)
while (is >> token)
value += (value.empty() ? "" : " ") + token;
o["Debug Log File"] << Option("", on_logger);
o["Threads"] << Option(1, 1, 512, on_threads);
o["Hash"] << Option(16, 1, MaxHashMB, on_hash_size);
o["Clear Hash"] << Option(on_clear_hash);
o["Ponder"] << Option(false);
o["MultiPV"] << Option(1, 1, 500);
o["Skill Level"] << Option(20, 0, 20);
o["Move Overhead"] << Option(10, 0, 5000);
o["Slow Mover"] << Option(100, 10, 1000);
o["nodestime"] << Option(0, 0, 10000);
o["UCI_Chess960"] << Option(false);
o["UCI_AnalyseMode"] << Option(false);
o["UCI_LimitStrength"] << Option(false);
o["UCI_Elo"] << Option(1350, 1350, 2850);
o["UCI_ShowWDL"] << Option(false);
o["SyzygyPath"] << Option("<empty>", on_tb_path);
o["SyzygyProbeDepth"] << Option(1, 1, 100);
o["Syzygy50MoveRule"] << Option(true);
o["SyzygyProbeLimit"] << Option(7, 0, 7);
o["Use NNUE"] << Option(true, on_use_NNUE);
o["EvalFile"] << Option(EvalFileDefaultName, on_eval_file);
if (options_map.count(name))
options_map[name] = value;
else
sync_cout << "No such option: " << name << sync_endl;
}
/// operator<<() is used to print all the options default values in chronological
/// insertion order (the idx field) and in the format defined by the UCI protocol.
std::ostream& operator<<(std::ostream& os, const OptionsMap& om) {
for (size_t idx = 0; idx < om.size(); ++idx)
for (const auto& it : om)
if (it.second.idx == idx)
{
const Option& o = it.second;
os << "\noption name " << it.first << " type " << o.type;
if (o.type == "string" || o.type == "check" || o.type == "combo")
os << " default " << o.defaultValue;
if (o.type == "spin")
os << " default " << int(stof(o.defaultValue))
<< " min " << o.min
<< " max " << o.max;
break;
}
return os;
Option OptionsMap::operator[](const std::string& name) const {
auto it = options_map.find(name);
return it != options_map.end() ? it->second : Option();
}
Option& OptionsMap::operator[](const std::string& name) { return options_map[name]; }
/// Option class constructors and conversion operators
std::size_t OptionsMap::count(const std::string& name) const { return options_map.count(name); }
Option::Option(const char* v, OnChange f) : type("string"), min(0), max(0), on_change(f)
{ defaultValue = currentValue = v; }
Option::Option(const char* v, OnChange f) :
type("string"),
min(0),
max(0),
on_change(std::move(f)) {
defaultValue = currentValue = v;
}
Option::Option(bool v, OnChange f) : type("check"), min(0), max(0), on_change(f)
{ defaultValue = currentValue = (v ? "true" : "false"); }
Option::Option(bool v, OnChange f) :
type("check"),
min(0),
max(0),
on_change(std::move(f)) {
defaultValue = currentValue = (v ? "true" : "false");
}
Option::Option(OnChange f) : type("button"), min(0), max(0), on_change(f)
{}
Option::Option(OnChange f) :
type("button"),
min(0),
max(0),
on_change(std::move(f)) {}
Option::Option(double v, int minv, int maxv, OnChange f) : type("spin"), min(minv), max(maxv), on_change(f)
{ defaultValue = currentValue = std::to_string(v); }
Option::Option(double v, int minv, int maxv, OnChange f) :
type("spin"),
min(minv),
max(maxv),
on_change(std::move(f)) {
defaultValue = currentValue = std::to_string(v);
}
Option::Option(const char* v, const char* cur, OnChange f) : type("combo"), min(0), max(0), on_change(f)
{ defaultValue = v; currentValue = cur; }
Option::Option(const char* v, const char* cur, OnChange f) :
type("combo"),
min(0),
max(0),
on_change(std::move(f)) {
defaultValue = v;
currentValue = cur;
}
Option::operator double() const {
assert(type == "check" || type == "spin");
return (type == "spin" ? stof(currentValue) : currentValue == "true");
Option::operator int() const {
assert(type == "check" || type == "spin");
return (type == "spin" ? std::stoi(currentValue) : currentValue == "true");
}
Option::operator std::string() const {
assert(type == "string");
return currentValue;
assert(type == "string");
return currentValue;
}
bool Option::operator==(const char* s) const {
assert(type == "combo");
return !CaseInsensitiveLess()(currentValue, s)
&& !CaseInsensitiveLess()(s, currentValue);
assert(type == "combo");
return !CaseInsensitiveLess()(currentValue, s) && !CaseInsensitiveLess()(s, currentValue);
}
/// operator<<() inits options and assigns idx in the correct printing order
// Inits options and assigns idx in the correct printing order
void Option::operator<<(const Option& o) {
static size_t insert_order = 0;
static size_t insert_order = 0;
*this = o;
idx = insert_order++;
*this = o;
idx = insert_order++;
}
/// operator=() updates currentValue and triggers on_change() action. It's up to
/// the GUI to check for option's limits, but we could receive the new value
/// from the user by console window, so let's check the bounds anyway.
// Updates currentValue and triggers on_change() action. It's up to
// the GUI to check for option's limits, but we could receive the new value
// from the user by console window, so let's check the bounds anyway.
Option& Option::operator=(const std::string& v) {
Option& Option::operator=(const string& v) {
assert(!type.empty());
assert(!type.empty());
if ((type != "button" && type != "string" && v.empty())
|| (type == "check" && v != "true" && v != "false")
|| (type == "spin" && (std::stof(v) < min || std::stof(v) > max)))
return *this;
if ( (type != "button" && type != "string" && v.empty())
|| (type == "check" && v != "true" && v != "false")
|| (type == "spin" && (stof(v) < min || stof(v) > max)))
return *this;
if (type == "combo")
{
OptionsMap comboMap; // To have case insensitive compare
std::string token;
std::istringstream ss(defaultValue);
while (ss >> token)
comboMap[token] << Option();
if (!comboMap.count(v) || v == "var")
return *this;
}
if (type == "combo")
{
OptionsMap comboMap; // To have case insensitive compare
string token;
std::istringstream ss(defaultValue);
while (ss >> token)
comboMap[token] << Option();
if (!comboMap.count(v) || v == "var")
return *this;
}
if (type != "button")
currentValue = v;
if (type != "button")
currentValue = v;
if (on_change)
on_change(*this);
if (on_change)
on_change(*this);
return *this;
return *this;
}
} // namespace UCI
std::ostream& operator<<(std::ostream& os, const OptionsMap& om) {
for (size_t idx = 0; idx < om.options_map.size(); ++idx)
for (const auto& it : om.options_map)
if (it.second.idx == idx)
{
const Option& o = it.second;
os << "\noption name " << it.first << " type " << o.type;
} // namespace Stockfish
if (o.type == "string" || o.type == "check" || o.type == "combo")
os << " default " << o.defaultValue;
if (o.type == "spin")
os << " default " << int(stof(o.defaultValue)) << " min " << o.min << " max "
<< o.max;
break;
}
return os;
}
}
+81
View File
@@ -0,0 +1,81 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2024 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 <http://www.gnu.org/licenses/>.
*/
#ifndef UCIOPTION_H_INCLUDED
#define UCIOPTION_H_INCLUDED
#include <cstddef>
#include <functional>
#include <iosfwd>
#include <map>
#include <string>
namespace Stockfish {
// Define a custom comparator, because the UCI options should be case-insensitive
struct CaseInsensitiveLess {
bool operator()(const std::string&, const std::string&) const;
};
class Option;
class OptionsMap {
public:
void setoption(std::istringstream&);
friend std::ostream& operator<<(std::ostream&, const OptionsMap&);
Option operator[](const std::string&) const;
Option& operator[](const std::string&);
std::size_t count(const std::string&) const;
private:
// The options container is defined as a std::map
using OptionsStore = std::map<std::string, Option, CaseInsensitiveLess>;
OptionsStore options_map;
};
// The Option class implements each option as specified by the UCI protocol
class Option {
public:
using OnChange = std::function<void(const Option&)>;
Option(OnChange = nullptr);
Option(bool v, OnChange = nullptr);
Option(const char* v, OnChange = nullptr);
Option(double v, int minv, int maxv, OnChange = nullptr);
Option(const char* v, const char* cur, OnChange = nullptr);
Option& operator=(const std::string&);
void operator<<(const Option&);
operator int() const;
operator std::string() const;
bool operator==(const char*) const;
friend std::ostream& operator<<(std::ostream&, const OptionsMap&);
private:
std::string defaultValue, currentValue, type;
int min, max;
size_t idx;
OnChange on_change;
};
}
#endif // #ifndef UCIOPTION_H_INCLUDED
+59 -5
View File
@@ -1,5 +1,5 @@
#!/bin/bash
# check for errors under valgrind or sanitizers.
# check for errors under Valgrind or sanitizers.
error()
{
@@ -64,13 +64,32 @@ EOF
;;
esac
cat << EOF > bench_tmp.epd
Rn6/1rbq1bk1/2p2n1p/2Bp1p2/3Pp1pP/1N2P1P1/2Q1NPB1/6K1 w - - 2 26
rnbqkb1r/ppp1pp2/5n1p/3p2p1/P2PP3/5P2/1PP3PP/RNBQKBNR w KQkq - 0 3
3qnrk1/4bp1p/1p2p1pP/p2bN3/1P1P1B2/P2BQ3/5PP1/4R1K1 w - - 9 28
r4rk1/1b2ppbp/pq4pn/2pp1PB1/1p2P3/1P1P1NN1/1PP3PP/R2Q1RK1 w - - 0 13
EOF
# simple command line testing
for args in "eval" \
"go nodes 1000" \
"go depth 10" \
"go perft 4" \
"go movetime 1000" \
"go wtime 8000 btime 8000 winc 500 binc 500" \
"bench 128 $threads 8 default depth"
"go wtime 1000 btime 1000 winc 0 binc 0" \
"go wtime 1000 btime 1000 winc 0 binc 0" \
"go wtime 1000 btime 1000 winc 0 binc 0 movestogo 5" \
"go movetime 200" \
"go nodes 20000 searchmoves e2e4 d2d4" \
"bench 128 $threads 8 default depth" \
"bench 128 $threads 3 bench_tmp.epd depth" \
"export_net verify.nnue" \
"d" \
"compiler" \
"license" \
"uci"
do
echo "$prefix $exeprefix ./stockfish $args $postfix"
@@ -78,6 +97,11 @@ do
done
# verify the generated net equals the base net
network=`./stockfish uci | grep 'option name EvalFile type string default' | awk '{print $NF}'`
echo "Comparing $network to the written verify.nnue"
diff $network verify.nnue
# more general testing, following an uci protocol exchange
cat << EOF > game.exp
set timeout 240
@@ -86,6 +110,7 @@ cat << EOF > game.exp
send "uci\n"
expect "uciok"
# send "setoption name Debug Log File value debug.log\n"
send "setoption name Threads value $threads\n"
send "ucinewgame\n"
@@ -101,10 +126,32 @@ cat << EOF > game.exp
send "go depth 10\n"
expect "bestmove"
send "setoption name UCI_ShowWDL value true\n"
send "position startpos\n"
send "flip\n"
send "go depth 5\n"
expect "bestmove"
send "setoption name Skill Level value 10\n"
send "position startpos\n"
send "go depth 5\n"
expect "bestmove"
send "setoption name Clear Hash\n"
send "setoption name EvalFile value verify.nnue\n"
send "position startpos\n"
send "go depth 5\n"
expect "bestmove"
send "setoption name MultiPV value 4\n"
send "position startpos\n"
send "go depth 5\n"
send "quit\n"
expect eof
# return error code of the spawned program, useful for valgrind
# return error code of the spawned program, useful for Valgrind
lassign [wait] pid spawnid os_error_flag value
exit \$value
EOF
@@ -122,10 +169,17 @@ cat << EOF > syzygy.exp
send "setoption name SyzygyPath value ../tests/syzygy/\n"
expect "info string Found 35 tablebases" {} timeout {exit 1}
send "bench 128 1 8 default depth\n"
send "ucinewgame\n"
send "position fen 4k3/PP6/8/8/8/8/8/4K3 w - - 0 1\n"
send "go depth 5\n"
expect "bestmove"
send "position fen 8/1P6/2B5/8/4K3/8/6k1/8 w - - 0 1\n"
send "go depth 5\n"
expect "bestmove"
send "quit\n"
expect eof
# return error code of the spawned program, useful for valgrind
# return error code of the spawned program, useful for Valgrind
lassign [wait] pid spawnid os_error_flag value
exit \$value
EOF
@@ -140,6 +194,6 @@ do
done
rm -f tsan.supp
rm -f tsan.supp bench_tmp.epd
echo "instrumented testing OK"
+1 -1
View File
@@ -43,7 +43,7 @@ cat << EOF > repeat.exp
expect eof
EOF
# to increase the likelyhood of finding a non-reproducible case,
# to increase the likelihood of finding a non-reproducible case,
# the allowed number of nodes are varied systematically
for i in `seq 1 20`
do
+1 -1
View File
@@ -11,7 +11,7 @@ trap 'error ${LINENO}' ERR
# obtain
signature=`./stockfish bench 2>&1 | grep "Nodes searched : " | awk '{print $4}'`
signature=`eval "$WINE_PATH ./stockfish bench 2>&1" | grep "Nodes searched : " | awk '{print $4}'`
if [ $# -gt 0 ]; then
# compare to given reference