Compare commits

...

385 Commits

Author SHA1 Message Date
Joost VandeVondele 3597f1942e Stockfish 13
Official release version of Stockfish 13

Bench: 3766422

-----

It is our pleasure to release Stockfish 13 to chess fans worldwide.
As usual, downloads are freely available at

https://stockfishchess.org

The Stockfish project builds on a thriving community of enthusiasts
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 thank them all!

The good news first: from now on, our users can expect more frequent
high-quality releases of Stockfish! Sadly, this decision has been
triggered by the start of sales of the Fat Fritz 2 engine by ChessBase,
which is a copy of a very recent development version of Stockfish
with minor modifications. We refer to our statement on Fat Fritz 2[1]
and a community blog[2] for further information.

This version of Stockfish is significantly stronger than any of its
predecessors. Stockfish 13 outperforms Stockfish 12 by at least
35 Elo[3]. When playing against a one-year-old Stockfish, it wins 60
times more game pairs than it loses[4]. This release features an NNUE
network retrained on billions of positions, much faster network
evaluation code, and significantly improved search heuristics, as
well as additional evaluation tweaks. In the course of its development,
this version has won the superfinals of the TCEC Season 19 and
TCEC Season 20.

Going forward, the Leela Chess Zero and Stockfish teams will join
forces to demonstrate our commitment to open source chess engines and
training tools, and open data. We are convinced that our free and
open-source chess engines serve the chess community very well.

Stay safe and enjoy chess!

The Stockfish team
[1] https://blog.stockfishchess.org/post/643239805544792064/statement-on-fat-fritz-2
[2] https://lichess.org/blog/YCvy7xMAACIA8007/fat-fritz-2-is-a-rip-off
[3] https://tests.stockfishchess.org/tests/view/602bcccf7f517a561bc49b11
[4] https://tests.stockfishchess.org/tests/view/600fbb9c735dd7f0f0352d59
2021-02-18 22:14:55 +01:00
Stéphane Nicolet 9f6d69c544 Update README.md
• reorder some sections of the README file
• add reference to the AUTHORS file
• rename Syzygybases to Syzygy tablebases
• add pointer to the Discord channel
• more precise info about the GPLv3 licence

No functional change
2021-02-16 16:40:54 +01:00
Lolligerhans 40cb0f076a Small trivial clean-ups, February 2021
Closes https://github.com/official-stockfish/Stockfish/pull/3329

No functional change
2021-02-16 01:31:42 +01:00
Stéphane Nicolet b46813f9b7 Update Top CPU Contributors
No functional change
2021-02-15 23:58:03 +01:00
Vizvezdenec 76daa88cf8 PV-Nodes likely to fail low
Do not decrease reduction at pv-nodes which are likely to fail low.

The idea of this patch can be described as following: during the search, if a node
on the principal variation was re-searched in non-pv search and this re-search got
a value which was much lower than alpha, then we can assume that this pv-node is
likely to fail low again, and we can reduce more aggressively at this node.

Passed STC
https://tests.stockfishchess.org/tests/view/6023a5fa7f517a561bc49638
LLR: 2.95 (-2.94,2.94) {-0.25,1.25}
Total: 70288 W: 6443 L: 6223 D: 57622
Ptnml(0-2): 239, 5022, 24436, 5174, 273

Passed LTC
https://tests.stockfishchess.org/tests/view/6023f2617f517a561bc49661
LLR: 2.94 (-2.94,2.94) {0.25,1.25}
Total: 105656 W: 4048 L: 3748 D: 97860
Ptnml(0-2): 67, 3312, 45761, 3630, 58

Closes https://github.com/official-stockfish/Stockfish/pull/3349

Bench: 3766422
2021-02-11 23:39:06 +01:00
mattginsberg 573f0e364f Better code for hash table generation
This patch removes some magic numbers in TT bit management and introduce proper
constants in the code, to improve documentation and ease further modifications.

No function change
2021-02-11 22:29:35 +01:00
Gian-Carlo Pascutto 550fed3343 Enable New Pass Manager for Clang.
It's about 1% speedup for Stockfish.

Result of 100 runs
==================
base (...fish_clang12) =    1946851  +/- 3717
test (./stockfish    ) =    1967276  +/- 3408
diff                   =     +20425  +/- 2438

speedup        = +0.0105
P(speedup > 0) =  1.0000

Thanks to David Major for making me aware of this part
of LLVM development.

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

No functional change
2021-02-10 19:54:26 +01:00
Gian-Carlo Pascutto b15e3b3fa9 Disable ThinLTO when using Clang.
Benchmarking with current Clang 12 shows that
and ThinLTO is a pessimization, see issue #3341.

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

No functional change.
2021-02-10 19:52:20 +01:00
Andy Pilate 1f87a9eb6c Fixes FreeBSD compilation when using Clang
closes https://github.com/official-stockfish/Stockfish/pull/3342

No functional change
2021-02-10 19:50:44 +01:00
bmc4 29ed22de8c Search Parameters Tuning
A simple tuning on search.cpp.

based SPSA test:
https://tests.stockfishchess.org/tests/view/601f2a787f517a561bc493cd

passed STC:
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 117840 W: 10796 L: 10508 D: 96536
Ptnml(0-2): 422, 8381, 41041, 8639, 437
https://tests.stockfishchess.org/tests/view/602144c37f517a561bc494ae

passed LTC:
LLR: 2.96 (-2.94,2.94) {0.25,1.25}
Total: 25024 W: 972 L: 847 D: 23205
Ptnml(0-2): 7, 767, 10847, 876, 15
https://tests.stockfishchess.org/tests/view/602156877f517a561bc494be

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

Bench: 3974098
2021-02-08 21:42:03 +01:00
FauziAkram 5ebdc40f83 Pawns Tuning
A simple tuning of Pawns parameters, and some PSQT changes.

Passed STC:
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 219424 W: 43681 L: 43103 D: 132640
Ptnml(0-2): 4014, 25760, 49669, 26172, 4097
https://tests.stockfishchess.org/tests/view/601bce167f517a561bc491eb

Passed LTC:
LLR: 2.94 (-2.94,2.94) {0.25,1.25}
Total: 317312 W: 42525 L: 41579 D: 233208
Ptnml(0-2): 2447, 30157, 92636, 30835, 2581
https://tests.stockfishchess.org/tests/view/601c21557f517a561bc49227

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

Bench: 4154473
2021-02-08 21:39:30 +01:00
bmc4 9f8058bd26 Simplify En Passant
simplifies the handling of en passant during search, needs a little more care in initialization.

Passed STC:
LLR: 2.95 (-2.94,2.94) {-1.25,0.25}
Total: 72608 W: 6569 L: 6559 D: 59480
Ptnml(0-2): 233, 5117, 25629, 5057, 268
https://tests.stockfishchess.org/tests/view/600f1363735dd7f0f0352ce7

Passed LTC:
LLR: 2.92 (-2.94,2.94) {-0.75,0.25}
Total: 24328 W: 913 L: 864 D: 22551
Ptnml(0-2): 10, 731, 10633, 780, 10
https://tests.stockfishchess.org/tests/view/600f2e93735dd7f0f0352cf6

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

No functional change.
2021-02-08 21:35:59 +01:00
bmc4 6617ad6e03 Tune ordering of moves at internal nodes
We change the relative weights of the function used to order
quiet moves in our MovePicker class.

Passed STC:
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 32184 W: 2936 L: 2773 D: 26475
Ptnml(0-2): 115, 2196, 11328, 2317, 136
https://tests.stockfishchess.org/tests/view/60161ee1735dd7f0f03530f8

Passed LTC:
LLR: 2.93 (-2.94,2.94) {0.25,1.25}
Total: 33088 W: 1292 L: 1149 D: 30647
Ptnml(0-2): 14, 1030, 14318, 1163, 19
https://tests.stockfishchess.org/tests/view/60163146735dd7f0f03530ff

The new weight were chosen after the following SPSA session:
https://tests.stockfishchess.org/tests/view/60136857735dd7f0f0352f6c

Closes https://github.com/official-stockfish/Stockfish/pull/3331

Bench: 4398803
2021-01-31 16:00:06 +01:00
bmc4 dd96095214 Simplify Chess 960 castling
a little cleanup, and small speedup (about 0.3%) for Chess 960.

Verified with perft on a large set of chess960 positions.

Closes https://github.com/official-stockfish/Stockfish/pull/3317

No functional change
2021-01-31 10:07:02 +01:00
bmc4 0db374777e Speed Up Perft Search
It speeds up generate<LEGAL>, and thus perft, roughly by 2-3%.

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

No functional change
2021-01-31 10:04:41 +01:00
bmc4 befbcffb4e Clean Up Castling in gives_check
There is no need to add rto or kto on the Bitboard which represents the pieces.

STC:
LLR: 2.93 (-2.94,2.94) {-1.25,0.25}
Total: 57064 W: 5096 L: 5067 D: 46901
Ptnml(0-2): 202, 3862, 20355, 3931, 182
https://tests.stockfishchess.org/tests/view/6005ea2c6019e097de3efa55

LTC:
LLR: 2.92 (-2.94,2.94) {-0.75,0.25}
Total: 30088 W: 1094 L: 1052 D: 27942
Ptnml(0-2): 10, 882, 13217, 926, 9
https://tests.stockfishchess.org/tests/view/6006115a6019e097de3efa6e

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

No functional change.
2021-01-31 10:02:10 +01:00
bmc4 7d0a16e06d Avoid more expensive legality check
speedup of the code, enough to pass STC, failed LTC.

Passed STC:
LLR: 2.93 (-2.94,2.94) {-0.25,1.25}
Total: 68928 W: 6334 L: 6122 D: 56472
Ptnml(0-2): 233, 4701, 24369, 4943, 218
https://tests.stockfishchess.org/tests/view/6002747f6019e097de3ef8dc

Failed LTC:
LLR: -2.96 (-2.94,2.94) {0.25,1.25}
Total: 44560 W: 1702 L: 1675 D: 41183
Ptnml(0-2): 25, 1383, 19438, 1408, 26
https://tests.stockfishchess.org/tests/view/6002a4836019e097de3ef8e3

About 1% speedup:

Result of  50 runs
==================
base (...kfish.master) =    2237500  +/- 7428
test (...ckfish.patch) =    2267003  +/- 7017
diff                   =     +29503  +/- 4774

speedup        = +0.0132
P(speedup > 0) =  1.0000

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

No functional change.
2021-01-31 10:00:17 +01:00
Lolligerhans 70a818cbd6 Small cleanups
closes https://github.com/official-stockfish/Stockfish/pull/3301

No functional change
2021-01-30 13:27:31 +01:00
Stéphane Nicolet 1188141aa7 Improve play for closed positions
This patch give a small bonus to incite the attacking side to keep more
pawns on the board.

A consequence of this bonus is that Stockfish will tend to play positions
slightly more closed on average than master, especially when it believes
that it has an advantage.

To lower the risk of blockades where Stockfish start shuffling without
progress, we also implement a progressive decrease of the evaluation
value with the 50 moves counter (along with the necessary aging of the
transposition table to reduce the impact of the Graph History Interaction
problem): since the evaluation decreases during shuffling phases, the
engine will tend to examine the consequences of pawn breaks faster during
the search.

Passed STC:
LLR: 2.96 (-2.94,2.94) {-0.25,1.25}
Total: 26184 W: 2406 L: 2252 D: 21526
Ptnml(0-2): 85, 1784, 9223, 1892, 108
https://tests.stockfishchess.org/tests/view/600cc08b735dd7f0f0352c06

Passed LCT:
LLR: 2.95 (-2.94,2.94) {0.25,1.25}
Total: 199768 W: 7695 L: 7191 D: 184882
Ptnml(0-2): 85, 6478, 86269, 6952, 100
https://tests.stockfishchess.org/tests/view/600ccd28735dd7f0f0352c10

Closes https://github.com/official-stockfish/Stockfish/pull/3321

Bench: 3988915
2021-01-30 13:20:56 +01:00
Rod Johnson b7f643fe39 Add .gitignore
add files produced during the build to a newly added .gitignore

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

No functional change
2021-01-30 13:19:20 +01:00
Krystian Kuzniarek 329ef2a6aa Change lock type
No additional features of std::unique_lock has been previously used
so it's better to use a lighter lock.

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

No functional change.
2021-01-30 12:57:27 +01:00
Lolligerhans 77eeea407c Add penalty for doubled pawns in agile structure
Give an additional penalty of S(20, 10) for any doubled pawn if none of
the opponent's pawns is facing any of our
 - pawns or
 - pawn attacks;
that means, each of their pawns can push at least one square without
being captured.
This ignores their non-pawns pieces and attacks.

One possible justification: Their pawns' ability to push freely provides
options to react to our threats by changing their pawn structure. Our
doubled pawns however will likely lead to an exploitable weakness, even
if the pawn structure is not yet fixed.

Note that the notion of "their pawns not being fixed" is symmetric for
both players: If all of their pawns can push freely so can ours. All
pawns being freely pushable might just be an early-game-indicator.
However, it can trigger during endgame pawns races, where doubled pawns
are especially hindering, too.

LTC
LLR: 2.94 (-2.94,2.94) {0.25,1.25}
Total: 134976 W: 17964 L: 17415 D: 99597
Ptnml(0-2): 998, 12702, 39619, 13091, 1078
https://tests.stockfishchess.org/tests/view/5ffdd5316019e097de3ef281

STC
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 35640 W: 7219 L: 6904 D: 21517
Ptnml(0-2): 645, 4096, 8084, 4289, 706
https://tests.stockfishchess.org/tests/view/5ffda4a16019e097de3ef265

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

Bench: 4363873
2021-01-17 09:35:59 +01:00
Tomasz Sobczyk 6dddcecb09 Optimize generate_moves
This change simplifies control flow in the generate_moves function which ensures the compiler doesn't duplicate work due to possibly not resolving pureness of the function calls. Also the biggest change is the removal of the unnecessary condition checking for empty b in a convoluted way. The rationale for removal of this condition is that computing attacks_bb with occupancy is not much more costly than computing pseudo attacks and overall the condition (also being likely unpredictable) is a pessimisation.

This is inspired by previous changes by @BM123499.

Passed STC:
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 88040 W: 8172 L: 7931 D: 71937
Ptnml(0-2): 285, 6128, 30957, 6361, 289
https://tests.stockfishchess.org/tests/view/5ffc28386019e097de3ef1c7

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

No functional change.
2021-01-13 22:59:54 +01:00
FauziAkram ee3f7b6b6e Bad Outpost Pawn Scale
Changed name from Bad Outpost to Uncontested Outpost
Scale Uncontested Outpost with number of pawns + Decrease Bishop PSQT values and general tuning

Credits for the decrease of the Bishop PSQT values: Fauzi
Credits for scaling Uncontested Outpost with number of pawns: Lolligerhans
Credits for the tunings: Fauzi

Passed STC:
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 32040 W: 6593 L: 6281 D: 19166
Ptnml(0-2): 596, 3713, 7095, 4015, 601
https://tests.stockfishchess.org/tests/view/5ffa43026019e097de3ef0f2

Passed LTC:
LLR: 2.95 (-2.94,2.94) {0.25,1.25}
Total: 84376 W: 11395 L: 10950 D: 62031
Ptnml(0-2): 652, 7930, 24623, 8287, 696
https://tests.stockfishchess.org/tests/view/5ffa6e7b6019e097de3ef0fd

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

Bench: 4287509
2021-01-11 19:42:31 +01:00
Vizvezdenec 37c2b5685e Refine stat based reductions
This patch separates stat based reductions for quiet moves in case of being in check and in case of not being in check.
We will be using sum of first continuation history and main history (similar to movepicker) instead of statScore for the first case.

passed STC
https://tests.stockfishchess.org/tests/view/5ff87b2f6019e097de3ef09b
LLR: 2.93 (-2.94,2.94) {-0.25,1.25}
Total: 63992 W: 5887 L: 5678 D: 52427
Ptnml(0-2): 201, 4561, 22305, 4686, 243

passed LTC
https://tests.stockfishchess.org/tests/view/5ff8b6206019e097de3ef0b2
LLR: 2.94 (-2.94,2.94) {0.25,1.25}
Total: 81216 W: 3127 L: 2880 D: 75209
Ptnml(0-2): 46, 2544, 35176, 2801, 41

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

bench 4395984
2021-01-11 19:36:07 +01:00
BM123499 5f222f1d98 Rethink En Passant Evasion Capture
It now checks if it were a discovery attack instead of the attacking piece is the double-moved pawn.

As a side effect, certain illegal fens have different, and slightly more logical move generation.
There is no intend to maintain particular behavior for such non-reachable fens.

Passed STC:
LLR: 2.93 (-2.94,2.94) {-1.25,0.25}
Total: 47912 W: 4327 L: 4285 D: 39300
Ptnml(0-2): 144, 3312, 17012, 3334, 154
https://tests.stockfishchess.org/tests/view/5ff890946019e097de3ef0a5

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

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

No functional change
2021-01-11 19:31:22 +01:00
Dieter Dobbelaere 0266e70297 Fix static_assert.
With a hard-coded true, this declaration has no effect.

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

No functional change.
2021-01-11 19:23:05 +01:00
Dieter Dobbelaere 87586b3d0c Use correct chess terms + fix spelling.
- "discovered check" (instead of "discovery check")
  - "en passant" (instead of "en-passant")
  - "pseudo-legal" before a noun (instead of "pseudo legal")
  - "3-fold" (instead of "3fold")

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

No functional change.
2021-01-11 19:19:39 +01:00
Vizvezdenec b1bb376c3c Small code cleanup in LMR
In a recent patch we added comparing capture history to a number for LMR of captures.
Calling it via thisThread-> is not needed since capture history was already declared by this time -
so removing makes code slightly shorter and easier to follow.

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

No functional change.
2021-01-11 19:17:03 +01:00
MaximMolchanov 303713b560 Affine transform robust implementation
Size of the weights in the last layer is less than 512 bits. It leads to wrong data access for AVX512. There is no error because in current implementation it is guaranteed that there is an array of zeros after weights so zero multiplied by something is returned and sum is correct. It is a mistake that can lead to unexpected bugs in the future. Used AVX2 instructions for smaller input size.

No measurable slowdown on avx512.

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

No functional change.
2021-01-11 18:54:18 +01:00
bmc4 4d30438400 Remove Condition from Generate_Move Loop
it seems it's faster to handle blockers_for_king(~Us) outside loops

Passed STC:
LLR: 2.96 (-2.94,2.94) {-0.25,1.25}
Total: 22184 W: 2063 L: 1919 D: 18202
Ptnml(0-2): 63, 1485, 7855, 1623, 66
https://tests.stockfishchess.org/tests/view/5ffbee2f6019e097de3ef18d

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

No functional change
2021-01-11 18:41:47 +01:00
Joost VandeVondele c4d67d77c9 Update copyright years
No functional change
2021-01-08 17:04:23 +01:00
Vizvezdenec 2c1be0be8e Reorder conditions in LMR and pruning
Make code logic somewhat easier to follow.

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

No functional change.
2021-01-08 16:57:26 +01:00
MaximMolchanov 23c385ec36 Affine transform refactoring.
Reordered weights in such a way that accumulated sum fits to output.
Weights are grouped in blocks of four elements because four
int8 (weight type) corresponds to one int32 (output type).
No horizontal additions.
Grouped AVX512, AVX2 and SSSE3 implementations.
Repeated code was removed.

An earlier version passed STC:

LLR: 2.97 (-2.94,2.94) {-0.25,1.25}
Total: 15336 W: 1495 L: 1355 D: 12486
Ptnml(0-2): 44, 1054, 5350, 1158, 62
https://tests.stockfishchess.org/tests/view/5ff60e106019e097de3eefd5

Speedup depends on the architecture, up to 4% measured on a NNUE only bench.

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

No functional change
2021-01-08 16:35:44 +01:00
FauziAkram d21e421ad7 WeakUnopposed penalty for backwards on file A or H
Do not give the WeakUnopposed penalty for backwards on file A or H

The original idea comes from Lolligerhans, and a series of tunings and tests done by Fauzi.

Passed STC:
LLR: 2.96 (-2.94,2.94) {-0.25,1.25}
Total: 140864 W: 28127 L: 27660 D: 85077
Ptnml(0-2): 2529, 16660, 31735, 16831, 2677
https://tests.stockfishchess.org/tests/view/5fe39dec3932f79192d39673

Passed LTC:
LLR: 2.95 (-2.94,2.94) {0.25,1.25}
Total: 67568 W: 8993 L: 8590 D: 49985
Ptnml(0-2): 523, 6176, 19983, 6579, 523
https://tests.stockfishchess.org/tests/view/5fe3dd1b3932f79192d39693

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

Bench: 4109336
2020-12-31 18:03:33 +01:00
Unai Corzo 8ec97d161e Remove razoring
has become ineffective now.

STC https://tests.stockfishchess.org/tests/view/5fe653403932f79192d3981a
LLR: 2.95 (-2.94,2.94) {-1.25,0.25}
Total: 63448 W: 5965 L: 5934 D: 51549
Ptnml(0-2): 230, 4738, 21769, 4745, 242

LTC https://tests.stockfishchess.org/tests/view/5fe6f0f03932f79192d39856
LLR: 2.93 (-2.94,2.94) {-0.75,0.25}
Total: 65368 W: 2485 L: 2459 D: 60424
Ptnml(0-2): 33, 2186, 28230, 2192, 43

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

bench: 4493379
2020-12-31 17:51:14 +01:00
Unai Corzo 8985c210a1 Simplify away late irreversible move extension
Late irreversible move extension seems to be useless now.

STC https://tests.stockfishchess.org/tests/view/5fe75c5c3932f79192d398ca
LLR: 2.93 (-2.94,2.94) {-1.25,0.25}
Total: 196192 W: 18111 L: 18278 D: 159803
Ptnml(0-2): 681, 14097, 68652, 14040, 626

LTC https://tests.stockfishchess.org/tests/view/5fe875e23932f79192d39952
LLR: 2.96 (-2.94,2.94) {-0.75,0.25}
Total: 28080 W: 1105 L: 1053 D: 25922
Ptnml(0-2): 13, 904, 12158, 948, 17

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

bench: 4144640
2020-12-31 17:48:47 +01:00
Unai Corzo c57c71bf5c Assorted parameter tweak
Parameter tweak from various tunes and patches.

STC https://tests.stockfishchess.org/tests/view/5fec2ae36019e097de3ee94a
LLR: 2.97 (-2.94,2.94) {-0.25,1.25}
Total: 41976 W: 4032 L: 3848 D: 34096
Ptnml(0-2): 147, 3086, 14341, 3264, 150

LTC https://tests.stockfishchess.org/tests/view/5fec5c3c6019e097de3ee973
LLR: 2.94 (-2.94,2.94) {0.25,1.25}
Total: 23936 W: 970 L: 844 D: 22122
Ptnml(0-2): 14, 749, 10319, 869, 17

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

bench: 4354546
2020-12-31 17:44:15 +01:00
Stefan Geschwentner 4262461457 Tweak capture LMR.
Apply the recently added LMR condition for captures at nodes which are not PV or former PV nodes only if capture history is not too good.

STC:
LLR: 2.96 (-2.94,2.94) {-0.25,1.25}
Total: 95296 W: 8917 L: 8660 D: 77719
Ptnml(0-2): 323, 6871, 33045, 7044, 365
https://tests.stockfishchess.org/tests/view/5feca7f46019e097de3ee9ae

LTC:
LLR: 2.95 (-2.94,2.94) {0.25,1.25}
Total: 29216 W: 1172 L: 1034 D: 27010
Ptnml(0-2): 11, 946, 12568, 1060, 23
https://tests.stockfishchess.org/tests/view/5fecf1786019e097de3ee9d5

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

Bench: 4006138
2020-12-31 17:41:34 +01:00
Vizvezdenec 51deae8998 Do more LMR for captures
This patch enables LMR for all captures at allNodes that were not in PV.
Currently we do LMR for all captures at cutNodes so this is an expansion of this logic:
now we do LMR for all captures almost at all non-pv nodes,
excluding only allNodes that were in PV.

passed STC
https://tests.stockfishchess.org/tests/view/5fe50b9d3932f79192d3973c
LLR: 2.95 (-2.94,2.94) {-0.25,1.25}
Total: 83128 W: 7606 L: 7368 D: 68154
Ptnml(0-2): 292, 5905, 28939, 6129, 299

passed LTC
https://tests.stockfishchess.org/tests/view/5fe552e43932f79192d39744
LLR: 2.92 (-2.94,2.94) {0.25,1.25}
Total: 13968 W: 568 L: 466 D: 12934
Ptnml(0-2): 5, 418, 6043, 506, 12

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

Bench: 4194835
2020-12-25 10:21:00 +01:00
Moez Jellouli b06ef36ae5 Correct Outflanking calculations in classical eval
Take signed value of rank difference between kings squares instead absolute value in outflanking calculation. This change correct evaluation of endgames with one king invading opponent last ranks.

Passed STC:
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 122240 W: 24326 L: 23896 D: 74018
Ptnml(0-2): 2101, 14139, 28236, 14517, 2127
https://tests.stockfishchess.org/tests/view/5fdfc33a3932f79192d394b8

Passed LTC:
LLR: 2.97 (-2.94,2.94) {0.25,1.25}
Total: 157416 W: 20870 L: 20292 D: 116254
Ptnml(0-2): 973, 13954, 48333, 14418, 1030
https://tests.stockfishchess.org/tests/view/5fe07a453932f79192d39502

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

Bench: 4162769
2020-12-23 20:20:24 +01:00
FauziAkram 45b05328b6 Tweak the formulas for unsafeSquares
We give more bonus for a special case: If there are some enemy squares occupied
or attacked by the enemy on the passed pawn span,
but if they are all attacked by our pawn, use new intermediate factor 30.

The main credit goes to Rocky for the idea, with additional tuning and tests.

Passed STC:
LLR: 2.95 (-2.94,2.94) {-0.25,1.25}
Total: 96464 W: 19233 L: 18834 D: 58397
Ptnml(0-2): 1683, 11327, 21950, 11452, 1820
https://tests.stockfishchess.org/tests/view/5fdd21ab3932f79192d39357

Passed LTC:
LLR: 2.94 (-2.94,2.94) {0.25,1.25}
Total: 81320 W: 10784 L: 10352 D: 60184
Ptnml(0-2): 602, 7524, 24044, 7820, 670
https://tests.stockfishchess.org/tests/view/5fddec983932f79192d393a4

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

Bench: 4338972
2020-12-23 20:17:57 +01:00
pb00067 1f3b5b8b54 Simplify condition for assigning static-eval based bonus
for quiet move ordering and simplify bonus formula.

Due to clamping the bonus to relative low values the impact on high
depths is minimal, thus the restriction to low depths seems not
necessary.
Also the condition of movecount in previous node seems to be not
determinant.

Passed STC:
LLR: 2.95 (-2.94,2.94) {-1.25,0.25}
Total: 14600 W: 1424 L: 1323 D: 11853
Ptnml(0-2): 55, 1033, 5020, 1140, 52
https://tests.stockfishchess.org/tests/view/5fd67b381ac16912018885ec

Passed LTC:
LLR: 2.95 (-2.94,2.94) {-0.75,0.25}
Total: 85008 W: 3218 L: 3206 D: 78584
Ptnml(0-2): 49, 2840, 36700, 2880, 35
https://tests.stockfishchess.org/tests/view/5fd6af041ac16912018885f8

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

bench: 4524994
2020-12-18 21:19:46 +01:00
FauziAkram 66a7a8a0cc Adjust definition of unsafeSquares
and adjust related bonus values. The bonus is now not given whenever
there is an enemy piece in front of the pawn.

Passed STC:
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 109472 W: 22097 L: 21673 D: 65702
Ptnml(0-2): 2111, 12800, 24482, 13240, 2103
https://tests.stockfishchess.org/tests/view/5fd8d3740c5870924361ffad

Passed LTC:
LLR: 2.95 (-2.94,2.94) {0.25,1.25}
Total: 39384 W: 5334 L: 4990 D: 29060
Ptnml(0-2): 279, 3648, 11535, 3910, 320
https://tests.stockfishchess.org/tests/view/5fd971ab0c5870924361fff0

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

Bench: 4488955
2020-12-18 21:17:34 +01:00
Vizvezdenec a88a38c3a9 Increase reduction in case of stable best move
The idea of this patch is pretty simple - we already do more reductions
for non-PV and root nodes in case of stable best move for depth > 10.
This patch makes us do so if root depth if > 10 instead, which
is logical since best move changes (thus instability of it) is
counted at root, so it makes a lot of sense to use depth of the root.

passed STC
https://tests.stockfishchess.org/tests/view/5fd643271ac16912018885c5
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 13232 W: 1308 L: 1169 D: 10755
Ptnml(0-2): 39, 935, 4535, 1062, 45

passed LTC
https://tests.stockfishchess.org/tests/view/5fd68db11ac16912018885f0
LLR: 2.96 (-2.94,2.94) {0.25,1.25}
Total: 14024 W: 565 L: 463 D: 12996
Ptnml(0-2): 3, 423, 6062, 517, 7

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

Bench: 4050630
2020-12-14 07:52:02 +01:00
pb00067 16adcb5374 Merge static history into main history,
thus simplifying and reducing the memory footprint.
I believe using static diff for better move ordering is more suited for
low depths, so restrict writing to low depths.

Todo: probably the condition for writing can be simplified

LTC:
LLR: 2.95 (-2.94,2.94) {-0.75,0.25}
Total: 18752 W: 768 L: 705 D: 17279
Ptnml(0-2): 7, 635, 8034, 688, 12
https://tests.stockfishchess.org/tests/view/5fd631791ac169120188859e

STC:
LLR: 2.95 (-2.94,2.94) {-1.25,0.25}
Total: 36504 W: 3380 L: 3313 D: 29811
Ptnml(0-2): 116, 2667, 12645, 2682, 142
https://tests.stockfishchess.org/tests/view/5fd5ed861ac1691201888569

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

bench: 4018036
2020-12-14 07:48:48 +01:00
mstembera d862ba4069 AVX512, AVX2 and SSSE3 speedups
Improves throughput by summing 2 intermediate dot products using 16 bit addition before upconverting to 32 bit.

Potential saturation is detected and the code-path is avoided in this case.
The saturation can't happen with the current nets,
but nets can be constructed that trigger this check.

STC https://tests.stockfishchess.org/tests/view/5fd40a861ac1691201888479
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 25544 W: 2451 L: 2296 D: 20797
Ptnml(0-2): 92, 1761, 8925, 1888, 106

about 5% speedup

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

No functional change
2020-12-14 07:46:15 +01:00
FauziAkram d706ae62d7 New Imbalance Tables Tweak
Imbalance tables tweaked to contain MiddleGame and Endgame values, instead of a single value.

The idea started from Fisherman, which requested my help to tune the values back in June/July,
so I tuned the values back then, and we were able to accomplish good results,
but not enough to pass both STC and LTC tests.

So after the recent changes, I decided to give it another shot, and I am glad that it was a successful attempt.

A special thanks goes also to mstembera, which notified me a simple way to let the patch perform a little better.

Passed STC:
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 115976 W: 23124 L: 22695 D: 70157
Ptnml(0-2): 2074, 13652, 26285, 13725, 2252
https://tests.stockfishchess.org/tests/view/5fc92d2d42a050a89f02ccc8

Passed LTC:
LLR: 2.94 (-2.94,2.94) {0.25,1.25}
Total: 156304 W: 20617 L: 20024 D: 115663
Ptnml(0-2): 1138, 14647, 46084, 15050, 1233
https://tests.stockfishchess.org/tests/view/5fc9fee142a050a89f02cd3e

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

Bench: 4278746
2020-12-12 09:31:28 +01:00
Fanael Linithien c7f0a768cb Use arithmetic right shift for sign extension in MMX and SSE2 paths
This appears to be slightly faster than using a comparison against zero
to compute the high bits, on both old (like Pentium III) and new (like
Zen 2) hardware.

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

No functional change.
2020-12-12 09:20:15 +01:00
Vizvezdenec 8630d03dd4 Add comments to uncommented parts of code
https://github.com/official-stockfish/Stockfish/pull/3250

No functional change
2020-12-05 16:58:42 +01:00
Vizvezdenec be7a03a957 Introduce static history
The idea of this patch can be described as following: we update static
history stats based on comparison of the static evaluations of the
position before and after the move. If the move increases static evaluation
it's assigned positive bonus, if it decreases static evaluation
it's assigned negative bonus. These stats are used in movepicker
to sort quiet moves.

passed STC
https://tests.stockfishchess.org/tests/view/5fca4c0842a050a89f02cd66
LLR: 3.00 (-2.94,2.94) {-0.25,1.25}
Total: 78152 W: 7409 L: 7171 D: 63572
Ptnml(0-2): 303, 5695, 26873, 5871, 334

passed LTC
https://tests.stockfishchess.org/tests/view/5fca6be442a050a89f02cd75
LLR: 2.94 (-2.94,2.94) {0.25,1.25}
Total: 40240 W: 1602 L: 1441 D: 37197
Ptnml(0-2): 19, 1306, 17305, 1475, 15

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

bench 3845156
2020-12-05 16:48:33 +01:00
SFisGOD 7364006757 Update default net to nn-62ef826d1a6d.nnue
Include scaling change as suggested by Dietrich Kappe,
the one who trained net for Komodo.  According to him,
some nets may require different scaling in order to utilize its full strength.

STC:
LLR: 2.93 (-2.94,2.94) {-0.25,1.25}
Total: 99856 W: 9669 L: 9401 D: 80786
Ptnml(0-2): 374, 7468, 34037, 7614, 435
https://tests.stockfishchess.org/tests/view/5fc2697642a050a89f02c8ec

LTC:
LLR: 2.96 (-2.94,2.94) {0.25,1.25}
Total: 29840 W: 1220 L: 1081 D: 27539
Ptnml(0-2): 10, 969, 12827, 1100, 14
https://tests.stockfishchess.org/tests/view/5fc2ea5142a050a89f02c957

Bench: 3561701
2020-11-29 16:54:06 +01:00
Unai Corzo 2442ba2b0e Reductions simplification
Simplify increase reduction for captures/promotions if late move and at low depth.

STC https://tests.stockfishchess.org/tests/view/5fbff65067cbf42301d6b3ae
LLR: 2.97 (-2.94,2.94) {-1.25,0.25}
Total: 49088 W: 4607 L: 4555 D: 39926
Ptnml(0-2): 177, 3615, 16932, 3619, 201

LTC https://tests.stockfishchess.org/tests/view/5fc0902967cbf42301d6b3fc
LLR: 2.99 (-2.94,2.94) {-0.75,0.25}
Total: 160944 W: 6153 L: 6193 D: 148598
Ptnml(0-2): 90, 5525, 69294, 5461, 102

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

bench: 3834568
2020-11-29 16:52:51 +01:00
syzygy1 045728a7da Remove piece lists
This patch removes the incrementally updated piece lists from the Position object.

This has been tried before but always failed. My reasons for trying again are:

* 32-bit systems (including phones) are now much less important than they were some years ago (and are absent from fishtest);
* NNUE may have made SF less finely tuned to the order in which moves were generated.

STC:
LLR: 2.94 (-2.94,2.94) {-1.25,0.25}
Total: 55272 W: 5260 L: 5216 D: 44796
Ptnml(0-2): 208, 4147, 18898, 4159, 224
https://tests.stockfishchess.org/tests/view/5fc2986a42a050a89f02c926

LTC:
LLR: 2.96 (-2.94,2.94) {-0.75,0.25}
Total: 16600 W: 673 L: 608 D: 15319
Ptnml(0-2): 14, 533, 7138, 604, 11
https://tests.stockfishchess.org/tests/view/5fc2f98342a050a89f02c95c

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

Bench: 3940967
2020-11-29 16:51:01 +01:00
Unai Corzo 2bc4ae172a Update README.md
fix a few typos

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

No functional change
2020-11-29 16:47:00 +01:00
Unai Corzo 6c429c4d65 Search simplification
STC https://tests.stockfishchess.org/tests/view/5fc2083942a050a89f02c8bb
LLR: 2.93 (-2.94,2.94) {-1.25,0.25}
Total: 23200 W: 2251 L: 2160 D: 18789
Ptnml(0-2): 86, 1726, 7895, 1797, 96

LTC https://tests.stockfishchess.org/tests/view/5fc22d7b42a050a89f02c8d0
LLR: 2.92 (-2.94,2.94) {-0.75,0.25}
Total: 15832 W: 653 L: 590 D: 14589
Ptnml(0-2): 7, 521, 6795, 588, 5

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

bench: 3827317

Simplify search.
2020-11-29 16:42:40 +01:00
lonfom169 66da1e802c Remove bonus for killers.
Passed non-regression STC:
LLR: 2.94 (-2.94,2.94) {-1.25,0.25}
Total: 14712 W: 1416 L: 1315 D: 11981
Ptnml(0-2): 59, 1029, 5082, 1124, 62
https://tests.stockfishchess.org/tests/view/5fbfa31f67cbf42301d6b36e

Passed non-regression LTC:
LLR: 2.95 (-2.94,2.94) {-0.75,0.25}
Total: 27536 W: 1099 L: 1044 D: 25393
Ptnml(0-2): 11, 929, 11838, 974, 16
https://tests.stockfishchess.org/tests/view/5fbfac9167cbf42301d6b371

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

Bench: 3887644
2020-11-29 16:40:06 +01:00
Lolligerhans d6d6972a66 Refine rook penalty on closed files
+-----------------+
| . . . . . . . . | All files are closed. Some files are
| . . . . . o o . | more valuable for rooks, because
| . . . . o . . o | they might open in the future.
| . . . o x . . x |
| o . o x . x x . |
| x o x . . . . . | x  our pawns
| . x . . . . . . | o  their pawns
| . . . . . . . . | ^  rooks are scored higher on these files
+-----------------+
            ^ ^

Files containing none of our own pawns are open or half-open (otherwise
they are closed). Rooks on (half-)open files recieve a bonus for the
future potential to act along all ranks.

This commit refines the (relative) penalty of rooks on closed files.
Files that contain one of our blocked pawns are considered less likely
to open in the future; rooks on these files are now penalized stronger.

This bonus does not generally correlate with mobility. If the condition
is sufficiently refined in the future, it may be beneficial to adjust or
override mobility scores in some cases.

LTC
LLR: 2.94 (-2.94,2.94) {0.25,1.25}
Total: 494384 W: 71565 L: 70231 D: 352588
Ptnml(0-2): 3907, 48050, 142118, 49036, 4081
https://tests.stockfishchess.org/tests/view/5fb9312e67cbf42301d6afb9

LTC (non-regression w/ book noob_3moves.epd)
LLR: 2.95 (-2.94,2.94) {-0.75,0.25}
Total: 208520 W: 27044 L: 26937 D: 154539
Ptnml(0-2): 1557, 19850, 61391, 19853, 1609
https://tests.stockfishchess.org/tests/view/5fc01ced67cbf42301d6b3df

STC
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 98392 W: 20269 L: 19868 D: 58255
Ptnml(0-2): 1804, 11297, 22589, 11706, 1800
https://tests.stockfishchess.org/tests/view/5fb7f88a67cbf42301d6af10

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

Bench: 3682630
2020-11-29 16:38:03 +01:00
mstembera 9b7983a452 Cleaned up MakeIndex()
The index order in kpp_board_index[][] is reversed to be more optimal for the access pattern

STC https://tests.stockfishchess.org/tests/view/5fbd74f967cbf42301d6b24f
LLR: 2.93 (-2.94,2.94) {-1.25,0.25}
Total: 27504 W: 2686 L: 2607 D: 22211
Ptnml(0-2): 84, 2001, 9526, 2034, 107

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

No functional change
2020-11-29 16:36:49 +01:00
Vizvezdenec 190dd26b9f use classical for certain endgames.
STC https://tests.stockfishchess.org/tests/view/5fbc64c067cbf42301d6b1d6
LLR: 2.97 (-2.94,2.94) {-0.25,1.25}
Total: 53360 W: 5223 L: 5024 D: 43113
Ptnml(0-2): 184, 3877, 18390, 4014, 215

LTC https://tests.stockfishchess.org/tests/view/5fbc97f267cbf42301d6b1ee
LLR: 2.96 (-2.94,2.94) {0.25,1.25}
Total: 126472 W: 5111 L: 4766 D: 116595
Ptnml(0-2): 50, 4032, 54749, 4333, 72

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

bench: 3820648
2020-11-26 08:20:06 +01:00
MaximMolchanov 7615e3485e Calculate sum from first elements
in affine transform for AVX512/AVX2/SSSE3

The idea is to initialize sum with the first element instead of zero.
Reduce one add_epi32 and one set_zero SIMD instructions for each output dimension.

sum = 0; for i = 1 to n sum += a[i] ->
sum = a[1]; for i = 2 to n sum += a[i]

STC:
LLR: 2.95 (-2.94,2.94) {-0.25,1.25}
Total: 69048 W: 7024 L: 6799 D: 55225
Ptnml(0-2): 260, 5175, 23458, 5342, 289
https://tests.stockfishchess.org/tests/view/5faf2cf467cbf42301d6aa06

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

No functional change.
2020-11-25 21:10:13 +01:00
Unai Corzo 9fb6383ed8 Assorted search and eval parameter tune
Search and eval parameter tune.

STC https://tests.stockfishchess.org/tests/view/5fba850a67cbf42301d6b07d
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 24312 W: 2388 L: 2228 D: 19696
Ptnml(0-2): 85, 1800, 8241, 1930, 100

LTC https://tests.stockfishchess.org/tests/view/5fbad5ea67cbf42301d6b0fa
LLR: 2.95 (-2.94,2.94) {0.25,1.25}
Total: 88376 W: 3619 L: 3351 D: 81406
Ptnml(0-2): 56, 2977, 37849, 3255, 51

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

bench: 3600361
2020-11-25 21:05:08 +01:00
Stéphane Nicolet 027626db1e Small cleanups 13
No functional change
2020-11-23 22:20:32 +01:00
FauziAkram f9595828eb Rook Mobility Tweak
Passed STC:
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 171152 W: 34715 L: 34202 D: 102235
Ptnml(0-2): 3278, 20155, 38228, 20606, 3309
https://tests.stockfishchess.org/tests/view/5fa861f467cbf42301d6a68e

Passed LTC:
LLR: 2.94 (-2.94,2.94) {0.25,1.25}
Total: 149616 W: 20471 L: 19882 D: 109263
Ptnml(0-2): 1172, 14434, 43102, 14833, 1267
https://tests.stockfishchess.org/tests/view/5fa9c8ff67cbf42301d6a74f

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

Bench: 3597730
2020-11-15 13:23:19 +01:00
SFisGOD 285bf7041a Increase reduction at root
when the best move does not change frequently

STC:
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 51320 W: 5159 L: 4956 D: 41205
Ptnml(0-2): 215, 3897, 17242, 4082, 224
https://tests.stockfishchess.org/tests/view/5faa072367cbf42301d6a767

LTC:
LLR: 2.98 (-2.94,2.94) {0.25,1.25}
Total: 15952 W: 762 L: 642 D: 14548
Ptnml(0-2): 8, 561, 6725, 667, 15
https://tests.stockfishchess.org/tests/view/5faa4c3567cbf42301d6a794

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

Bench: 3954692
2020-11-12 12:49:03 +01:00
lonfom169 b5781150ea Increase reduction based on the number of best move changes.
Thanks to Vizvezdenec for the PvNode idea and also to vondele the !PvNode idea.

Passed STC:
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 19120 W: 1998 L: 1839 D: 15283
Ptnml(0-2): 76, 1445, 6375, 1572, 92
https://tests.stockfishchess.org/tests/view/5fa8af3e67cbf42301d6a6c9

Passed LTC:
LLR: 2.94 (-2.94,2.94) {0.25,1.25}
Total: 75584 W: 3454 L: 3205 D: 68925
Ptnml(0-2): 54, 2832, 31771, 3081, 54

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

Bench: 3595418
2020-11-10 18:21:05 +01:00
Stéphane Nicolet 392b529c3f Qsearch pruning: follow-up
This is a follow-up of the recent qsearch pruning patch in
https://github.com/official-stockfish/Stockfish/commit/a260c9a8a24a2630a900efc3821000c3481b0c5d

We now use the same guard condition (testing that we already have a defense with
a score better  score than a TB loss) for all pruning heuristics in qsearch().
This allows some pruning when in check, but  in a controlled way to ensure that
no wrong mate scores appear.

Tested with Elo-gaining bounds:

STC:
LLR: 2.97 (-2.94,2.94) {-0.25,1.25}
Total: 22632 W: 2433 L: 2264 D: 17935
Ptnml(0-2): 98, 1744, 7487, 1865, 122
https://tests.stockfishchess.org/tests/view/5fa59405936c54e11ec99515

LTC:
LLR: 2.94 (-2.94,2.94) {0.25,1.25}
Total: 105432 W: 4965 L: 4648 D: 95819
Ptnml(0-2): 85, 4110, 44011, 4423, 87
https://tests.stockfishchess.org/tests/view/5fa5b609936c54e11ec9952a

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

Bench: 3578092
2020-11-08 09:15:34 +01:00
SFisGOD 32edb1d009 Update default net to nn-c3ca321c51c9.nnue
Optimization of the net biases of the 32 x 32 layer and the output layer.

Tuning of 32 x 32 layer (200k games, 5 seconds TC)
https://tests.stockfishchess.org/tests/view/5f9aaf266a2c112b60691c68

STC:
LLR: 2.95 (-2.94,2.94) {-0.25,1.25}
Total: 41848 W: 4665 L: 4461 D: 32722
Ptnml(0-2): 239, 3308, 13659, 3446, 272
https://tests.stockfishchess.org/tests/view/5fa5ef5a936c54e11ec9954f

LTC:
LLR: 2.94 (-2.94,2.94) {0.25,1.25}
Total: 88008 W: 4045 L: 3768 D: 80195
Ptnml(0-2): 69, 3339, 36908, 3622, 66
https://tests.stockfishchess.org/tests/view/5fa62a78936c54e11ec99577

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

Bench: 3649288
2020-11-08 08:36:16 +01:00
Tomasz Sobczyk ba35c88ab8 AVX-512 for smaller affine and feature transforms.
For the feature transformer the code is analogical to AVX2 since there was room for easy adaptation of wider simd registers.

For the smaller affine transforms that have 32 byte stride we keep 2 columns in one zmm register. We also unroll more aggressively so that in the end we have to do 16 parallel horizontal additions on ymm slices each consisting of 4 32-bit integers. The slices are embedded in 8 zmm registers.

These changes provide about 1.5% speedup for AVX-512 builds.

Closes https://github.com/official-stockfish/Stockfish/pull/3218

No functional change.
2020-11-07 16:49:49 +01:00
FauziAkram 7fc47eeb6f Introducing King On File
this new concept calculates bonuses/penalties for the king when the king is in a semiopen or open file.

Passed STC:
LLR: 2.95 (-2.94,2.94) {-0.25,1.25}
Total: 44904 W: 9365 L: 9028 D: 26511
Ptnml(0-2): 857, 5309, 9841, 5530, 915
https://tests.stockfishchess.org/tests/view/5fa343625d72639a7acef72b

Passed LTC:
LLR: 2.94 (-2.94,2.94) {0.25,1.25}
Total: 60552 W: 8449 L: 8051 D: 44052
Ptnml(0-2): 466, 5772, 17481, 6012, 545
https://tests.stockfishchess.org/tests/view/5fa40e365d72639a7acef79e

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

Bench: 3689484
2020-11-07 16:49:49 +01:00
Joost VandeVondele 04a320666e Change handling the special case of a single legal move.
Using no searching time in case of a single legal move is not beneficial from
a strength point of view, and this special case can be easily removed:

STC:
LLR: 2.93 (-2.94,2.94) {-1.25,0.25}
Total: 22472 W: 2458 L: 2357 D: 17657
Ptnml(0-2): 106, 1733, 7453, 1842, 102
https://tests.stockfishchess.org/tests/view/5f926cbc81eda81bd78cb6df

LTC:
LLR: 2.94 (-2.94,2.94) {-0.75,0.25}
Total: 37880 W: 1736 L: 1682 D: 34462
Ptnml(0-2): 22, 1392, 16057, 1448, 21
https://tests.stockfishchess.org/tests/view/5f92a26081eda81bd78cb6fe

The advantage of using the normal time management for a single legal move is that scores
reported for that move are reasonable, not searching leads to artifacts during games
(see e.g. https://tcec-chess.com/#div=sf&game=96&season=19)

The disadvantage of using normal time management of a single legal move is that thinking
times can be unnaturally long, making it 'painful to watch' in online tournaments.

This patch uses normal time management, but caps the used time to 500ms.
This should lead to reasonable scores, and be hardly perceptible.

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

variant of a patch suggested by SFisGOD

No functional change.
2020-11-07 16:48:02 +01:00
Tomasz Sobczyk 3f6451eff7 Manually align arrays on the stack
as a workaround to issues with overaligned alignas() on stack variables in gcc < 9.3 on windows.

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

fixes #3216

No functional change
2020-11-04 19:52:42 +01:00
J. Oster a260c9a8a2 Fix incorrect pruning in qsearch
Only do countermove based pruning in qsearch if we already have a move with a better score than a TB loss.

This patch fixes a bug (started as 843a961) that incorrectly prunes moves if in check,
and adds an assert to make sure no wrong mate scores are given in the future.
It replaces a no-op moveCount check with a check for bestValue.

Initially discussed in #3171 and later in #3199, #3198 and #3210.
This PR effectively closes #3171
It also likely fixes #3196 where this causes user visible incorrect TB scores,
which probably result from these incorrect mate scores.

Passed STC and LTC non-regression tests.
https://tests.stockfishchess.org/tests/view/5f9ef8dabca9bf35bae7f648
LLR: 2.93 (-2.94,2.94) {-1.25,0.25}
Total: 21672 W: 2339 L: 2230 D: 17103
Ptnml(0-2): 126, 1689, 7083, 1826, 112

https://tests.stockfishchess.org/tests/view/5f9f0caebca9bf35bae7f666
LLR: 2.97 (-2.94,2.94) {-0.75,0.25}
Total: 33152 W: 1551 L: 1485 D: 30116
Ptnml(0-2): 27, 1308, 13832, 1390, 19

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

Bench: 3625915
2020-11-02 19:41:17 +01:00
FauziAkram 931070b65a Elo Worth in King Danger
Adding the EloWorth for each term in King Danger.
Should be useful for simplifications, tuning patches, and new ideas.

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

non-functional change
2020-11-02 19:41:17 +01:00
Tomasz Sobczyk 75e06a1c89 Optimize affine transform for SSSE3 and higher targets.
A non-functional speedup. Unroll the loops going over
the output dimensions in the affine transform layers by
a factor of 4 and perform 4 horizontal additions at a time.
Instead of doing naive horizontal additions on each vector
separately use hadd and shuffling between vectors to reduce
the number of instructions by using all lanes for all stages
of the horizontal adds.

passed STC of the initial version:
LLR: 2.95 (-2.94,2.94) {-0.25,1.25}
Total: 17808 W: 1914 L: 1756 D: 14138
Ptnml(0-2): 76, 1330, 5948, 1460, 90
https://tests.stockfishchess.org/tests/view/5f9d516f6a2c112b60691da3

passed STC of the final version after cleanup:
LLR: 2.95 (-2.94,2.94) {-0.25,1.25}
Total: 16296 W: 1750 L: 1595 D: 12951
Ptnml(0-2): 72, 1192, 5479, 1319, 86
https://tests.stockfishchess.org/tests/view/5f9df5776a2c112b60691de3

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

No functional change
2020-11-02 19:41:17 +01:00
mstembera dfc7f88650 Update default net to nn-cb26f10b1fd9.nnue
Result of https://tests.stockfishchess.org/tests/view/5f9a06796a2c112b60691c0f tuning.

STC
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 53712 W: 5776 L: 5561 D: 42375
Ptnml(0-2): 253, 4282, 17604, 4431, 286
https://tests.stockfishchess.org/tests/view/5f9c7bbc6a2c112b60691d4d

LTC
LLR: 2.97 (-2.94,2.94) {0.25,1.25}
Total: 80184 W: 4007 L: 3739 D: 72438
Ptnml(0-2): 58, 3302, 33130, 3518, 84
https://tests.stockfishchess.org/tests/view/5f9d01f06a2c112b60691d87

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

bench: 3517795
2020-11-01 08:02:40 +01:00
syzygy1 0f6c08c73f Do not skip non-recapture ttMove when in check
The qsearch() MovePicker incorrectly skips a non-recapture ttMove
when in check (if depth <= DEPTH_QS_RECAPTURES). This is clearly not
intended and can cause qsearch() to return a mate score when there
is no mate. Introduced in cad300c and 6596f0e, as observed by
joergoster in #3171 and #3198.

This PR fixes the bug by not skipping the non-recapture ttMove when in check.

Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/5f9867ea6a2c112b60691b10
LLR: 2.98 (-2.94,2.94) {-1.25,0.25}
Total: 27112 W: 2943 L: 2842 D: 21327
Ptnml(0-2): 127, 2170, 8878, 2237, 144

Passed non-regression LTC:
https://tests.stockfishchess.org/tests/view/5f9967326a2c112b60691bb0
LLR: 2.99 (-2.94,2.94) {-0.75,0.25}
Total: 18392 W: 807 L: 738 D: 16847
Ptnml(0-2): 9, 655, 7802, 718, 12

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

Bench: 3870606
2020-10-28 23:40:37 +01:00
SFisGOD 6328135264 Update default net to nn-2eb2e0707c2b.nnue
Optimization of the net weights of the 32 x 32 layer (1024 parameters) and net biases of the 512 x 32 layer (32 parameters) using SPSA.

Tuning of 32 x 32 Layer (800,000 games, 5 seconds time control):
https://tests.stockfishchess.org/tests/view/5f942040d3978d7e86f1aa05

Tuning of 512 x 32 Layer (80,000 games, 20 seconds time control):
https://tests.stockfishchess.org/tests/view/5f8f926d2c92c7fe3a8c608b

STC:
LLR: 2.96 (-2.94,2.94) {-0.25,1.25}
Total: 17336 W: 1918 L: 1754 D: 13664
Ptnml(0-2): 79, 1344, 5672, 1480, 93
https://tests.stockfishchess.org/tests/view/5f9882346a2c112b60691b34

LTC:
LLR: 2.94 (-2.94,2.94) {0.25,1.25}
Total: 37304 W: 1822 L: 1651 D: 33831
Ptnml(0-2): 27, 1461, 15501, 1640, 23
https://tests.stockfishchess.org/tests/view/5f98a4b36a2c112b60691b40

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

Bench: 3403528
2020-10-28 08:13:34 +01:00
FauziAkram bde3505758 Bishop Pawns based on Files
Passed STC:
https://tests.stockfishchess.org/tests/view/5f8cc8145a4eacb45305da3c
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 132544 W: 27795 L: 27328 D: 77421
Ptnml(0-2): 2756, 15558, 29272, 15835, 2851

Passed LTC:
https://tests.stockfishchess.org/tests/view/5f8df614bacb75a4f9a4721e
LLR: 2.94 (-2.94,2.94) {0.25,1.25}
Total: 169608 W: 23257 L: 22622 D: 123729
Ptnml(0-2): 1408, 16316, 48758, 16877, 1445

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

Bench: 4067106
2020-10-28 08:11:29 +01:00
syzygy1 2046d5da30 More incremental accumulator updates
This patch was inspired by c065abd which updates the accumulator,
if possible, based on the accumulator of two plies back if
the accumulator of the preceding ply is not available.

With this patch we look back even further in the position history
in an attempt to reduce the number of complete recomputations.
When we find a usable accumulator for the position N plies back,
we also update the accumulator of the position N-1 plies back
because that accumulator is most likely to be helpful later
when evaluating positions in sibling branches.
By not updating all intermediate accumulators immediately,
we avoid doing too much work that is not certain to be useful.
Overall, roughly 2-3% speedup.

This patch makes the code more specific to the net architecture,
changing input features of the net will require additional changes
to the incremental update code as discussed in the PR #3193 and #3191.

Passed STC:
https://tests.stockfishchess.org/tests/view/5f9056712c92c7fe3a8c60d0
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 10040 W: 1116 L: 968 D: 7956
Ptnml(0-2): 42, 722, 3365, 828, 63

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

No functional change.
2020-10-22 20:50:16 +02:00
Joost VandeVondele 258af8ae44 Add net as dependency of config
cleaner output and error message if the server is down and the net is not available.

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

No functional change
2020-10-22 20:18:12 +02:00
xoto10 f5dfad5d72 Reduce big time spikes by reducing PV re-searches.
Save time by reducing PV re-searches above original depth. Instead use 5% extra time on every move.

STC 10+0.1 th 1 :
LLR: 2.93 (-2.94,2.94) {-0.25,1.25}
Total: 90688 W: 9702 L: 9436 D: 71550
Ptnml(0-2): 408, 7252, 29792, 7450, 442
https://tests.stockfishchess.org/tests/view/5f8df807bacb75a4f9a47223

LTC 60+0.6 th 1 :
LLR: 2.97 (-2.94,2.94) {0.25,1.25}
Total: 97856 W: 4602 L: 4303 D: 88951
Ptnml(0-2): 53, 3757, 41057, 3960, 101
https://tests.stockfishchess.org/tests/view/5f8ec4872c92c7fe3a8c602d

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

Bench 3943959
2020-10-22 20:08:15 +02:00
Vizvezdenec 560c776397 Do more reductions for late quiet moves in case of consecutive fail highs.
Idea of this patch can be described as following - in case we have consecutive fail highs and we reach late enough moves at root node probability of remaining quiet moves being able to produce even bigger value than moves that produced previous cutoff (so ones that should be high in move ordering but now they fail to produce beta cutoff because we actually reached high move count) should be quiet small so we can reduce them more.

passed STC
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 53392 W: 5681 L: 5474 D: 42237
Ptnml(0-2): 214, 4104, 17894, 4229, 255
https://tests.stockfishchess.org/tests/view/5f88501adcdad978fe8c527e

passed LTC
LLR: 2.94 (-2.94,2.94) {0.25,1.25}
Total: 59136 W: 2773 L: 2564 D: 53799
Ptnml(0-2): 30, 2117, 25078, 2300, 43
https://tests.stockfishchess.org/tests/view/5f884dbfdcdad978fe8c527a

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

Bench: 4066972
2020-10-18 13:54:28 +02:00
mstembera 281d520cc2 Update default net to nn-eba324f53044.nnue
The new net is based on the previous net 04cf2b4ed1da but with the biases
for the 1st hidden layer tuned SPSA, see the SPSA session on fishtest there:
https://tests.stockfishchess.org/tests/view/5f875213dcdad978fe8c5211

Thanks to @vondele for writing out the net, see discussion in this thread:
https://github.com/mstembera/Stockfish/commit/432da86721647dff1d9426a7cdcfd2dbada8155e

Passed STC:
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 15000 W: 1640 L: 1483 D: 11877
Ptnml(0-2): 50, 1183, 4908, 1278, 81
https://tests.stockfishchess.org/tests/view/5f8955e20fea1a44ec4f0a5d

Passed LTC:
LLR: 2.96 (-2.94,2.94) {0.25,1.25}
Total: 81272 W: 3948 L: 3682 D: 73642
Ptnml(0-2): 64, 3194, 33856, 3456, 66
https://tests.stockfishchess.org/tests/view/5f89e8efeae8a6e60644d6e7

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

Bench: 3762411
2020-10-18 13:43:26 +02:00
Unai Corzo 288a604411 Scale factor tweak
Add !pawnsOnBothFlanks heuristic to scale factor.

STC https://tests.stockfishchess.org/tests/view/5f8080575b3847b5d41f9134
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 250960 W: 49779 L: 49168 D: 152013
Ptnml(0-2): 4224, 28822, 58802, 29383, 4249

LTC https://tests.stockfishchess.org/tests/view/5f832f498ea73fb8ddf83ddb
LLR: 2.95 (-2.94,2.94) {0.25,1.25}
Total: 88584 W: 11827 L: 11388 D: 65369
Ptnml(0-2): 585, 8079, 26578, 8412, 638

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

bench: 3834252
2020-10-14 19:32:12 +02:00
FauziAkram 4a5cc1365f RookOnQueenFile Removal
Removing Rook On Queen File looks beneficial, and it might even bring some ELO.
I will try to reintroduce it with a different method later on.

Passed STC:
https://tests.stockfishchess.org/tests/view/5f7cea204389873867eb10cb
LLR: 2.94 (-2.94,2.94) {-1.25,0.25}
Total: 18624 W: 3800 L: 3568 D: 11256
Ptnml(0-2): 308, 2131, 4257, 2253, 363

Passed LTC:
https://tests.stockfishchess.org/tests/view/5f7d76a4e936c6892bf50598
LLR: 2.95 (-2.94,2.94) {-0.75,0.25}
Total: 117864 W: 15515 L: 15340 D: 87009
Ptnml(0-2): 926, 11127, 34671, 11262, 946

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

Bench: 3756191
2020-10-14 19:29:22 +02:00
Joost VandeVondele ba73f8ce0d Update default net to nn-04cf2b4ed1da.nnue
Further tune the net parameters, now the last but one layer (32x32).
To limit the number of parameters optimized, the network layer was
decomposed using SVD, and the singular values were treated
as parameters and tuned.

Tuning branch: https://github.com/vondele/Stockfish/tree/svdTune
Tuner: https://github.com/vondele/nevergrad4sf

passed STC:
https://tests.stockfishchess.org/tests/view/5f83e82f8ea73fb8ddf83e4e
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 8488 W: 944 L: 795 D: 6749
Ptnml(0-2): 39, 609, 2811, 734, 51

passed LTC:
https://tests.stockfishchess.org/tests/view/5f83f4118ea73fb8ddf83e66
LLR: 2.94 (-2.94,2.94) {0.25,1.25}
Total: 169016 W: 8043 L: 7589 D: 153384
Ptnml(0-2): 133, 6623, 70538, 7085, 129

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

Bench: 3945198
2020-10-14 13:28:21 +02:00
FauziAkram 767b4f4fbe Pawn Tuning
Tuning of pawns, for classical evaluation:

Passed STC:
https://tests.stockfishchess.org/tests/view/5f771f0e52560f5fc78559ec
LLR: 2.96 (-2.94,2.94) {-0.25,1.25}
Total: 252696 W: 50321 L: 49692 D: 152683
Ptnml(0-2): 4614, 29845, 57049, 29978, 4862

Passed LTC:
https://tests.stockfishchess.org/tests/view/5f77cfef090dcf9aaa16d38b
LLR: 2.94 (-2.94,2.94) {0.25,1.25}
Total: 48184 W: 6556 L: 6193 D: 35435
Ptnml(0-2): 335, 4516, 14100, 4733, 408

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

bench: 4016121
2020-10-05 19:01:46 +02:00
Unai Corzo 17fb3a8ce0 Simplify away futility pruning for captures
Remove futility pruning for captures.

STC https://tests.stockfishchess.org/tests/view/5f749bfed930428c36d34c56
LLR: 2.94 (-2.94,2.94) {-1.25,0.25}
Total: 38064 W: 4011 L: 3929 D: 30124
Ptnml(0-2): 192, 3004, 12567, 3068, 201

LTC https://tests.stockfishchess.org/tests/view/5f74d99bf18675b1ce2f7412
LLR: 2.94 (-2.94,2.94) {-0.75,0.25}
Total: 184984 W: 8567 L: 8610 D: 167807
Ptnml(0-2): 146, 7593, 77058, 7548, 147

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

bench: 3890648
2020-10-05 18:59:02 +02:00
Joost VandeVondele 9382f854b3 Schedule threads fairly under valgrind
fixes a rare case that can cause CI to fail when running multithreaded under valgrind.

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

No functional change.
2020-10-05 18:56:49 +02:00
Stéphane Nicolet 5af09cfda5 Include pawns in NNUE scaling
We now include the total pawn count in the scaling factor for the output
of the NNUE evaluation network. This should have the effect of trying to
keep more pawns when SF has the advantage, but exchange them when she
is defending.

Thanks to Alexander Pagel (Lolligerhans) for the idea of using the
value of pawns to ease the comparison with the rest of the material
estimation.

Passed STC:
LLR: 2.93 (-2.94,2.94) {-0.25,1.25}
Total: 15072 W: 1700 L: 1539 D: 11833
Ptnml(0-2): 65, 1202, 4845, 1355, 69
https://tests.stockfishchess.org/tests/view/5f7235a63b22d6afa50699b3

Passed LTC:
LLR: 2.93 (-2.94,2.94) {0.25,1.25}
Total: 25880 W: 1270 L: 1124 D: 23486
Ptnml(0-2): 23, 980, 10788, 1126, 23
https://tests.stockfishchess.org/tests/view/5f723b483b22d6afa5069a99

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

Bench: 3776081
2020-09-28 22:42:26 +02:00
Stefan Geschwentner 6f0aa186d8 Tweak reduction formula.
Replace log(i) with log(i + 0.25 * log(i)). This increases especially for low values the reductions. But for bigger values there are nearly no changes.

STC:
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 49640 W: 5505 L: 5289 D: 38846
Ptnml(0-2): 270, 4074, 15924, 4274, 278
https://tests.stockfishchess.org/tests/view/5f71f04d3b22d6afa5069478

LTC:
LLR: 2.94 (-2.94,2.94) {0.25,1.25}
Total: 43856 W: 2209 L: 2021 D: 39626
Ptnml(0-2): 32, 1776, 18128, 1956, 36
https://tests.stockfishchess.org/tests/view/5f7232ee3b22d6afa50699a2

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

Bench: 3555769
2020-09-28 22:34:25 +02:00
SFisGOD 5efbaaba77 Update default net to nn-baeb9ef2d183.nnue
Further optimization of Sergio's nn-03744f8d56d8.nnue
This patch is the result of collaboration with Joost VandeVondele.

STC:
LLR: 2.96 (-2.94,2.94) {-0.25,1.25}
Total: 37000 W: 4145 L: 3947 D: 28908
Ptnml(0-2): 191, 3016, 11912, 3166, 215
https://tests.stockfishchess.org/tests/view/5f71e7983b22d6afa5069475

LTC:
LLR: 2.96 (-2.94,2.94) {0.25,1.25}
Total: 60224 W: 2992 L: 2769 D: 54463
Ptnml(0-2): 48, 2420, 24956, 2637, 51
https://tests.stockfishchess.org/tests/view/5f722bb83b22d6afa506998f

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

Bench: 3720073
2020-09-28 22:29:31 +02:00
FauziAkram ba46599aa2 Tweaking Mobility and Safe Check
Passed STC:
https://tests.stockfishchess.org/tests/view/5f70d86d3b22d6afa50693b9
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 100368 W: 20323 L: 19914 D: 60131
Ptnml(0-2): 1927, 11641, 22605, 12118, 1893

Passed LTC:
https://tests.stockfishchess.org/tests/view/5f71bb553b22d6afa5069457
LLR: 2.94 (-2.94,2.94) {0.25,1.25}
Total: 77648 W: 10613 L: 10181 D: 56854
Ptnml(0-2): 634, 7280, 22594, 7652, 664

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

Bench: 3861984
2020-09-28 22:26:37 +02:00
Vizvezdenec a5e68d9b25 Adjust null move pruning constants
Idea is that division by fraction of 2 is slightly faster than by other numbers so parameters are adjusted in a way that division in null move pruning depth reduction features dividing by 256 instead of dividing by 213.
Other than this patch is almost non-functional - difference starts to exist by depth 133.

passed STC
https://tests.stockfishchess.org/tests/view/5f70dd943b22d6afa50693c5
LLR: 2.95 (-2.94,2.94) {-0.25,1.25}
Total: 57048 W: 6616 L: 6392 D: 44040
Ptnml(0-2): 304, 4583, 18531, 4797, 309

passed LTC
https://tests.stockfishchess.org/tests/view/5f7180db3b22d6afa506941f
LLR: 2.95 (-2.94,2.94) {0.25,1.25}
Total: 45960 W: 2419 L: 2229 D: 41312
Ptnml(0-2): 43, 1779, 19137, 1987, 34

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

bench 3789924
2020-09-28 22:22:54 +02:00
Joost VandeVondele 36c2886302 Update default net to nn-04a843f8932e.nnue
an optimization of Sergio's nn-03744f8d56d8.nnue tuning the output layer (33 parameters) on game play.

WIP code to make layer parameters tunable is https://github.com/vondele/Stockfish/tree/optionOutput
Optimization itself is using https://github.com/vondele/nevergrad4sf
Writing of the modified net using WIP code based on the learner code https://github.com/vondele/Stockfish/tree/evalWrite

Most parameters in the output layer are changed only little (~5 for int8_t).

passed STC:
https://tests.stockfishchess.org/tests/view/5f716f6b3b22d6afa506941a
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 15488 W: 1859 L: 1689 D: 11940
Ptnml(0-2): 79, 1260, 4917, 1388, 100

passed LTC:
https://tests.stockfishchess.org/tests/view/5f71908e3b22d6afa506942e
LLR: 2.93 (-2.94,2.94) {0.25,1.25}
Total: 8728 W: 518 L: 400 D: 7810
Ptnml(0-2): 7, 338, 3556, 456, 7

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

Bench: 3789924
2020-09-28 16:55:40 +02:00
noobpwnftw c065abdcaf Use incremental updates more often
Use incremental updates for accumulators for up to 2 plies.
Do not copy accumulator. About 2% speedup.

Passed STC:
LLR: 2.95 (-2.94,2.94) {-0.25,1.25}
Total: 21752 W: 2583 L: 2403 D: 16766
Ptnml(0-2): 128, 1761, 6923, 1931, 133
https://tests.stockfishchess.org/tests/view/5f7150cf3b22d6afa5069412

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

No functional change
2020-09-28 16:54:35 +02:00
Stéphane Nicolet 1dbd2a1ad5 Tweak nnue scaling to keep more material
Current master uses a constant scale factor of 5/4 = 1.25 for the output
of the NNUE network, for compatibility with search and classical evaluation.
We modify this scale factor to make it dependent on the phase of the game,
going from about 1.5 in the opening to 1.0 for pure pawn endgames.

This helps Stockfish to avoid exchanges of pieces (heavy pieces in particular)
when she has the advantage, keeping more material on the board when attacking.

Passed STC:
LLR: 2.95 (-2.94,2.94) {-0.25,1.25}
Total: 14744 W: 1771 L: 1599 D: 11374
Ptnml(0-2): 87, 1184, 4664, 1344, 93
https://tests.stockfishchess.org/tests/view/5f6fb0a63b22d6afa506904f

Passed LTC:
LLR: 2.95 (-2.94,2.94) {0.25,1.25}
Total: 8912 W: 512 L: 393 D: 8007
Ptnml(0-2): 7, 344, 3637, 459, 9
https://tests.stockfishchess.org/tests/view/5f6fcf533b22d6afa5069066

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

Bench: 3943952
2020-09-27 08:24:50 +02:00
SFisGOD f66c381f11 Switch to NNUE eval probabilistically for OCB
Introduce a small chance of switching to NNUE if PSQ imbalance is large but we have opposite colored bishops and the classical eval is struggling to win.

STC:
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 25304 W: 3179 L: 2983 D: 19142
Ptnml(0-2): 172, 2171, 7781, 2345, 183
https://tests.stockfishchess.org/tests/view/5f6b14dec7759d4ee307cfe3

LTC:
LLR: 2.94 (-2.94,2.94) {0.25,1.25}
Total: 84680 W: 4846 L: 4556 D: 75278
Ptnml(0-2): 89, 3933, 34011, 4213, 94
https://tests.stockfishchess.org/tests/view/5f6b3fb6c7759d4ee307cff9

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

Bench: 3865413
2020-09-25 17:44:19 +02:00
Stéphane Nicolet 5e6a5e48e6 Suppress info strings before 'uci'
On Windows, Stockfish wouldn't launch in some GUI because we output some
info strings (about the use of large pages) before sending the 'uci'
command. It seems more robust to suppress these info strings, and instead
to add a proper section section in the Readme about large pages use.

fixes https://github.com/official-stockfish/Stockfish/issues/3052
closes https://github.com/official-stockfish/Stockfish/pull/3147

No functional change
2020-09-25 17:44:14 +02:00
Stéphane Nicolet 3d5b2c8a51 Increase reductions with the number of threads
Passed STC with 8 threads:
LLR: 2.92 (-2.94,2.94) {-0.25,1.25}
Total: 13520 W: 1135 L: 1012 D: 11373
Ptnml(0-2): 39, 815, 4929, 938, 39
https://tests.stockfishchess.org/tests/view/5f68e274ded68c240be73f41

Passed LTC with 8 threads:
LLR: 2.96 (-2.94,2.94) {0.25,1.25}
Total: 48384 W: 2183 L: 1994 D: 44207
Ptnml(0-2): 28, 1777, 20402, 1948, 37
https://tests.stockfishchess.org/tests/view/5f68f068ded68c240be747e9

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

No functional change (for one thread)
2020-09-22 22:45:02 +02:00
Stéphane Nicolet 9a64e737cf Small cleanups 12
- Clean signature of functions in namespace NNUE
- Add comment for countermove based pruning
- Remove bestMoveCount variable
- Add const qualifier to kpp_board_index array
- Fix spaces in get_best_thread()
- Fix indention in capture LMR code in search.cpp
- Rename TtmemDeleter to LargePageDeleter

Closes https://github.com/official-stockfish/Stockfish/pull/3063

No functional change
2020-09-21 10:41:10 +02:00
Sami Kiminki 485d517c68 Add large page support for NNUE weights and simplify TT mem management
Use TT memory functions to allocate memory for the NNUE weights. This
should provide a small speed-up on systems where large pages are not
automatically used, including Windows and some Linux distributions.

Further, since we now have a wrapper for std::aligned_alloc(), we can
simplify the TT memory management a bit:

- We no longer need to store separate pointers to the hash table and
  its underlying memory allocation.
- We also get to merge the Linux-specific and default implementations
  of aligned_ttmem_alloc().

Finally, we'll enable the VirtualAlloc code path with large page
support also for Win32.

STC: https://tests.stockfishchess.org/tests/view/5f66595823a84a47b9036fba
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 14896 W: 1854 L: 1686 D: 11356
Ptnml(0-2): 65, 1224, 4742, 1312, 105

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

No functional change.
2020-09-21 08:43:48 +02:00
Stefan Geschwentner 16b4578cc1 Tweak hybrid treshold.
Increase the first hybrid threshold with more material.
Rewrite the hybrid rules for clarity.

STC:
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 24416 W: 3039 L: 2848 D: 18529
Ptnml(0-2): 135, 2136, 7503, 2271, 163
https://tests.stockfishchess.org/tests/view/5f6451efbb0cae038ca8f4dc

LTC;
LLR: 2.95 (-2.94,2.94) {0.25,1.25}
Total: 65016 W: 3702 L: 3455 D: 57859
Ptnml(0-2): 66, 2991, 26157, 3218, 76
https://tests.stockfishchess.org/tests/view/5f64b143bb0cae038ca8f51f

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

Bench: 3973739
2020-09-21 08:19:10 +02:00
Unai Corzo 8559c43914 Simplify reduced depth search
Simplification in reduced depth search.

STC https://tests.stockfishchess.org/tests/view/5f64c72fbb0cae038ca8f531
LLR: 2.94 (-2.94,2.94) {-1.25,0.25}
Total: 28320 W: 3475 L: 3359 D: 21486
Ptnml(0-2): 170, 2485, 8773, 2523, 209

LTC https://tests.stockfishchess.org/tests/view/5f650cfabb0cae038ca8f585
LLR: 2.95 (-2.94,2.94) {-0.75,0.25}
Total: 58392 W: 3354 L: 3285 D: 51753
Ptnml(0-2): 74, 2826, 23336, 2877, 83

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

bench: 4201295
2020-09-21 07:47:41 +02:00
syzygy1 8b8a510fd6 Use tiling to speed up accumulator refreshes and updates
Perform the update and refresh operations tile by tile in a local
array of vectors. By selecting the array size carefully, we
achieve that the compiler keeps the whole array in vector registers.

Idea and original implementation by @sf-x.

STC: https://tests.stockfishchess.org/tests/view/5f623eec912c15f19854b855
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 4872 W: 623 L: 477 D: 3772
Ptnml(0-2): 14, 350, 1585, 450, 37

LTC: https://tests.stockfishchess.org/tests/view/5f62434e912c15f19854b860
LLR: 2.94 (-2.94,2.94) {0.25,1.25}
Total: 25808 W: 1565 L: 1401 D: 22842
Ptnml(0-2): 23, 1186, 10332, 1330, 33

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

No functional change
2020-09-17 17:24:52 +02:00
Unai Corzo 64a63464d7 Simplify futility pruning for captures
STC https://tests.stockfishchess.org/tests/view/5f61f0e4b91f2ec371e429c2
LLR: 2.94 (-2.94,2.94) {-1.25,0.25}
Total: 75512 W: 8747 L: 8704 D: 58061
Ptnml(0-2): 440, 6589, 23683, 6576, 468

LTC https://tests.stockfishchess.org/tests/view/5f6215d3912c15f19854b801
LLR: 2.95 (-2.94,2.94) {-0.75,0.25}
Total: 92912 W: 5030 L: 4992 D: 82890
Ptnml(0-2): 88, 4363, 37532, 4369, 104

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

bench: 3856086
2020-09-17 07:06:21 +02:00
Unai Corzo 0ca93c5b94 Remove castling extension
STC https://tests.stockfishchess.org/tests/view/5f5fa5348fbc1c8a3f476eca
LLR: 2.94 (-2.94,2.94) {-1.25,0.25}
Total: 38520 W: 4713 L: 4610 D: 29197
Ptnml(0-2): 233, 3486, 11734, 3559, 248

LTC https://tests.stockfishchess.org/tests/view/5f62166a912c15f19854b806
LLR: 2.93 (-2.94,2.94) {-0.75,0.25}
Total: 48024 W: 2673 L: 2600 D: 42751
Ptnml(0-2): 64, 2247, 19316, 2322, 63

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

bench: 3818400
2020-09-17 07:06:21 +02:00
GoldenRare df43805953 Added FEN string to bench output
fixes https://github.com/official-stockfish/Stockfish/pull/3117

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

No functional change
2020-09-17 07:06:21 +02:00
syzygy1 d86663af14 Improve NDK section in Makefile
This PR sets the "comp" variable simply to "clang",
which seems to be more consistent and allows a small simplification.

The PR also moves the section that sets "profile_make" and "profile_use" to after the NDK section,
which ensures that these variables are now set correctly for NDK/clang.

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

No functional change
2020-09-16 21:00:14 +02:00
xoto10 5f426d8667 Use 2 * bestMoveChanges.
NNUE appears to provide a more stable eval than the classic eval,
so the time use dependencies on bestMoveChanges, fallingEval,
etc may need to change to make the best use of available time.
This change doubles the effect of totBestMoveChanges when giving
more time because the choice of best move is unstable.

STC:
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 101928 W: 11995 L: 11698 D: 78235 Elo +0.78
Ptnml(0-2): 592, 8707, 32103, 8936, 626
https://tests.stockfishchess.org/tests/view/5f538a462d02727c56b36cec

LTC:
LLR: 2.94 (-2.94,2.94) {0.25,1.25}
Total: 186392 W: 10383 L: 9877 D: 166132 Elo +0.81
Ptnml(0-2): 207, 8370, 75539, 8870, 210
https://tests.stockfishchess.org/tests/view/5f54a9712d02727c56b36d5a

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

Bench 4222126
2020-09-16 20:56:40 +02:00
Sergio Vieri 7135678f71 Update default net to nn-03744f8d56d8.nnue
Equivalent to 20200914-1520

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

Bench: 4222126
2020-09-15 07:21:04 +02:00
mckx00 35ab8254b7 Simplify StatSCore Initialization
No need to initialize StatScore at rootNode. Current Logic is redundant because at subsequent levels the grandchildren statScore is initialized to zero.

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

Non functional change.
2020-09-15 07:19:02 +02:00
SFisGOD 0405f35403 Double probability of using classical eval
This patch doubles the moderate imbalance threshold and probability of using classical eval.
So now if imbalance is greater than PawnValueMg / 4 then there is a 1/8 chance of using classical eval.

STC:
LLR: 2.93 (-2.94,2.94) {-0.25,1.25}
Total: 10984 W: 1303 L: 1140 D: 8541
Ptnml(0-2): 58, 867, 3489, 1010, 68
https://tests.stockfishchess.org/tests/view/5f554c9f97da2d5437d3813e

LTC:
LLR: 2.95 (-2.94,2.94) {0.25,1.25}
Total: 43064 W: 2476 L: 2276 D: 38312
Ptnml(0-2): 37, 1985, 17308, 2145, 57
https://tests.stockfishchess.org/tests/view/5f55690a00a0aa2ca79f0a43

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

Bench: 4161067
2020-09-08 22:56:08 +02:00
Gian-Carlo Pascutto d2562cde12 Always re-enable NNUE after "bench".
Restore the default NNUE setting (enabled) after a bench command.
This also makes the resulting program settings independent of the
number of FENs that are being benched.

Fixes issue #3112.

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

No functional change.
2020-09-08 22:53:50 +02:00
syzygy1 fc27d158c0 Bug fix in do_null_move() and NNUE simplification.
This fixes #3108 and removes some NNUE code that is currently not used.

At the moment, do_null_move() copies the accumulator from the previous
state into the new state, which is correct. It then clears the "computed_score"
flag because the side to move has changed, and with the other side to move
NNUE will return a completely different evaluation (normally with changed
sign but also with different NNUE-internal tempo bonus).

The problem is that do_null_move() clears the wrong flag. It clears the
computed_score flag of the old state, not of the new state. It turns out
that this almost never affects the search. For example, fixing it does not
change the current bench (but it does change the previous bench). This is
because the search code usually avoids calling evaluate() after a null move.

This PR corrects do_null_move() by removing the computed_score flag altogether.
The flag is not needed because nnue_evaluate() is never called twice on a position.

This PR also removes some unnecessary {}s and inserts a few blank lines
in the modified NNUE files in line with SF coding style.

Resulf ot STC non-regression test:
LLR: 2.95 (-2.94,2.94) {-1.25,0.25}
Total: 26328 W: 3118 L: 3012 D: 20198
Ptnml(0-2): 126, 2208, 8397, 2300, 133
https://tests.stockfishchess.org/tests/view/5f553ccc2d02727c56b36db1

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

bench: 4109324
2020-09-08 22:53:17 +02:00
SFisGOD d539da19d2 Use classical eval more often
If there is a moderate imbalance, use classical eval with small probability (1/16),
as derived from the node counter.

STC:
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 32320 W: 3562 L: 3377 D: 25381
Ptnml(0-2): 144, 2609, 10478, 2776, 153
https://tests.stockfishchess.org/tests/view/5f520615ba100690c5cc5f80

LTC:
LLR: 2.95 (-2.94,2.94) {0.25,1.25}
Total: 21032 W: 1116 L: 974 D: 18942
Ptnml(0-2): 20, 837, 8664, 971, 24
https://tests.stockfishchess.org/tests/view/5f522eaaba100690c5cc5f8c

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

Bench: 4109324
2020-09-04 18:58:34 +02:00
Vizvezdenec 9a063fc3cb Adjust penalty on refuted early quiet moves
This patch changes how previous early moves are penalized in case
search finds a best move. Here, the first quiet move that was not
a transposition table move is penalized.

passed STC
https://tests.stockfishchess.org/tests/view/5f51d839ba100690c5cc5f69
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 10088 W: 1150 L: 997 D: 7941
Ptnml(0-2): 41, 772, 3278, 899, 54

passed LTC
https://tests.stockfishchess.org/tests/view/5f51e435ba100690c5cc5f76
LLR: 2.93 (-2.94,2.94) {0.25,1.25}
Total: 30808 W: 1564 L: 1405 D: 27839
Ptnml(0-2): 19, 1245, 12717, 1404, 19

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

bench 3983758
2020-09-04 18:52:46 +02:00
Sergio Vieri 9cc482c788 Update default net to nn-308d71810dff.nnue
equivalent to 20200903-1739

Net trained from scratch, so it has quite different features extracted compared to the previous net (82215d0fd0df).

STC:
LLR: 2.98 (-2.94,2.94) {-0.25,1.25}
Total: 108328 W: 14048 L: 13719 D: 80561
Ptnml(0-2): 842, 10039, 32062, 10390, 831
https://tests.stockfishchess.org/tests/view/5f50e053ba100690c5cc5f00

LTC:
LLR: 2.96 (-2.94,2.94) {0.25,1.25}
Total: 13872 W: 1059 L: 890 D: 11923
Ptnml(0-2): 30, 724, 5270, 871, 41
https://tests.stockfishchess.org/tests/view/5f51821fba100690c5cc5f36

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

Bench: 3832716
2020-09-04 08:03:43 +02:00
VoyagerOne 2a69611509 LMR Simplification
remove reduction at non-check cut nodes for second move at low depths

STC:
LLR: 2.95 (-2.94,2.94) {-1.25,0.25}
Total: 61712 W: 6594 L: 6543 D: 48575
Ptnml(0-2): 293, 5085, 20082, 5070, 326
https://tests.stockfishchess.org/tests/view/5f5007d6ba100690c5cc5ea9

LTC:
LLR: 2.94 (-2.94,2.94) {-0.75,0.25}
Total: 57544 W: 2983 L: 2925 D: 51636
Ptnml(0-2): 47, 2568, 23495, 2604, 58
https://tests.stockfishchess.org/tests/view/5f50c597ba100690c5cc5ef7

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

Bench: 3952302
2020-09-04 08:00:45 +02:00
Unai Corzo d6530f7d49 Simplify singularQuietLMR
remove formerPV dependence

STC https://tests.stockfishchess.org/tests/view/5f4cb922ba100690c5cc5d35
LLR: 2.96 (-2.94,2.94) {-1.25,0.25}
Total: 113672 W: 12347 L: 12368 D: 88957
Ptnml(0-2): 566, 9537, 36699, 9420, 614

LTC https://tests.stockfishchess.org/tests/view/5f4e8474ba100690c5cc5e12
LLR: 2.93 (-2.94,2.94) {-0.75,0.25}
Total: 43032 W: 2298 L: 2227 D: 38507
Ptnml(0-2): 45, 1940, 17475, 2011, 45

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

bench: 3290084
2020-09-04 07:58:13 +02:00
Unai Corzo 0e1f734b05 Less pruning in qsearch
do not prune moves that give discovery checks, even if with negative SSE.

STC https://tests.stockfishchess.org/tests/view/5f4cb5e8ba100690c5cc5d25
LLR: 2.96 (-2.94,2.94) {-0.25,1.25}
Total: 91328 W: 9940 L: 9667 D: 71721
Ptnml(0-2): 491, 7345, 29693, 7670, 465

LTC https://tests.stockfishchess.org/tests/view/5f4dbc2eba100690c5cc5dac
LLR: 2.97 (-2.94,2.94) {0.25,1.25}
Total: 52448 W: 2799 L: 2586 D: 47063
Ptnml(0-2): 53, 2220, 21459, 2445, 47

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

bench: 4031192
2020-09-04 07:55:41 +02:00
Joost VandeVondele 571c2d6d8d Restore development version
have fun!

No functional change
2020-09-04 07:46:06 +02:00
Joost VandeVondele c306d83869 Stockfish 12
Official release version of Stockfish 12

Bench: 3624569

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

It is our pleasure to release Stockfish 12 to users world-wide

Downloads will be freely available at

https://stockfishchess.org/download/

This version 12 of Stockfish plays significantly stronger than
any of its predecessors. In a match against Stockfish 11,
Stockfish 12 will typically win at least ten times more game pairs
than it loses.

This jump in strength, visible in regular progression tests during
development[1], results from the introduction of an efficiently
updatable neural network (NNUE) for the evaluation in Stockfish[2],
and associated tuning of the engine as a whole. The concept of the
NNUE evaluation was first introduced in shogi, and ported to
Stockfish afterward. Stockfish remains a CPU-only engine, since the
NNUE networks can be very efficiently evaluated on CPUs. The
recommended parameters of the NNUE network are embedded in
distributed binaries, and Stockfish will use NNUE by default.

Both the NNUE and the classical evaluations are available, and
can be used to assign values to positions that are later 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. The network is optimized and trained on the
evaluations of millions of positions.

The Stockfish project builds on a thriving community of enthusiasts
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 chess fans to join the fishtest testing
framework and programmers to contribute on github[3].

Stay safe and enjoy chess!

The Stockfish team

[1] https://github.com/glinscott/fishtest/wiki/Regression-Tests
[2] https://github.com/official-stockfish/Stockfish/commit/84f3e867903f62480c33243dd0ecbffd342796fc
[3] https://stockfishchess.org/get-involved/
2020-09-02 16:19:30 +02:00
Joost VandeVondele aa2de71230 Update CPU contributors list
with fishtest data of Sept. 2 2020

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

No functional change
2020-09-02 16:18:58 +02:00
Joost VandeVondele be87517734 Only use MADV_RANDOM if defined
needed to compile on Haiku.

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

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

No functional change
2020-09-02 07:32:10 +02:00
VoyagerOne a8bbaa1795 LMR Root Node Simplification
Simplify LMR at Root node

STC:
LLR: 2.94 (-2.94,2.94) {-1.25,0.25}
Total: 71520 W: 7649 L: 7614 D: 56257
Ptnml(0-2): 346, 5845, 23349, 5868, 352
https://tests.stockfishchess.org/tests/view/5f4be8c0ba100690c5cc5cbb

LTC:
LLR: 2.95 (-2.94,2.94) {-0.75,0.25}
Total: 74832 W: 3997 L: 3948 D: 66887
Ptnml(0-2): 77, 3422, 30362, 3485, 70
https://tests.stockfishchess.org/tests/view/5f4c603eba100690c5cc5d0e

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

Bench: 3624569
2020-09-01 09:31:40 +02:00
Joost VandeVondele 61381372ec Always print an info line before a bestmove
if very few nodes are being searched before a bestmove is reported,
an info line might be missing.

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

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

no functional change
2020-09-01 09:26:56 +02:00
mstembera a057f170c6 Use llvm linker with clang on windows for LTO.
other linkers might fail to link during the LTO phase.

The linker might have to be installed using
`pacman -Syu mingw-w64-x86_64-lld`

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

No functional change.
2020-09-01 09:26:08 +02:00
mstembera a0afe32d16 Use stable sort to make sure bench with TB yields same results everywhere.
std::sort() is not stable so different implementations can produce different results:
use the stable version instead.

Observed for '8/6k1/5r2/8/8/8/1K6/Q7 w - - 0 1' yielding different bench results for gcc and MSVC
and 3-4-5 syzygy TB prior to this patch.

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

No functional change.
2020-09-01 09:25:44 +02:00
FauziAkram e0bafa1911 Update parametes in classical evaluation.
Passed STC (NNUE=False):
https://tests.stockfishchess.org/tests/view/5f42edfe5089a564a10d84a0
LLR: 2.96 (-2.94,2.94) {-0.25,1.25}
Total: 13840 W: 2591 L: 2336 D: 8913
Ptnml(0-2): 194, 1453, 3387, 1676, 210

Passed LTC (NNUE=False):
https://tests.stockfishchess.org/tests/view/5f4369795089a564a10d84d8
LLR: 2.95 (-2.94,2.94) {0.25,1.25}
Total: 159744 W: 19430 L: 18850 D: 121464
Ptnml(0-2): 960, 14185, 49030, 14709, 988

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

bench: 3736029
2020-08-30 14:22:07 +02:00
VoyagerOne 9b5b9ec9a6 QS Pruning Simplification
Remove depth dependence in QS pruning

STC:
LLR: 2.95 (-2.94,2.94) {-1.25,0.25}
Total: 40536 W: 4442 L: 4358 D: 31736
Ptnml(0-2): 209, 3330, 13118, 3390, 221
https://tests.stockfishchess.org/tests/view/5f49035b3def6407861152f9

LTC:
LLR: 2.95 (-2.94,2.94) {-0.75,0.25}
Total: 97104 W: 5164 L: 5130 D: 86810
Ptnml(0-2): 103, 4478, 39377, 4470, 124
https://tests.stockfishchess.org/tests/view/5f4939d53def640786115322

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

Bench: 3865238
2020-08-30 14:17:23 +02:00
MJZ1977 c02b3a4c7a Add / remove leaves from search tree ttPv
add if previous leaf is in search tree and we didn't find a counter move
else remove the position if the leaf is the last one in search tree.

STC : https://tests.stockfishchess.org/tests/view/5f49203c3def640786115314
LLR: 2.95 (-2.94,2.94) {-0.25,1.25}
Total: 29968 W: 3381 L: 3195 D: 23392
Ptnml(0-2): 146, 2432, 9671, 2560, 175

LTC : https://tests.stockfishchess.org/tests/view/5f494bea3def640786115336
LLR: 2.96 (-2.94,2.94) {0.25,1.25}
Total: 84952 W: 4619 L: 4333 D: 76000
Ptnml(0-2): 86, 3765, 34481, 4065, 79

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

Bench 3527337
2020-08-30 14:13:16 +02:00
Unai Corzo d90d893b5e Reintroduce depth reduction
Reintroduce depth reduction if the position is not in TT.

STC https://tests.stockfishchess.org/tests/view/5f4652e85089a564a10d868c
LLR: 2.97 (-2.94,2.94) {-0.25,1.25}
Total: 40240 W: 4535 L: 4331 D: 31374
Ptnml(0-2): 215, 3276, 12969, 3410, 250

LTC https://tests.stockfishchess.org/tests/view/5f46ca5e5089a564a10d86f3
LLR: 2.93 (-2.94,2.94) {0.25,1.25}
Total: 63096 W: 3426 L: 3188 D: 56482
Ptnml(0-2): 51, 2798, 25645, 2970, 84

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

bench: 3611906
2020-08-30 14:04:29 +02:00
Joost VandeVondele e4ed7d3dd7 Cleaner make help
do not print details if ARCH is an empty string. Follow up for b0b4ca17db

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

No functional change
2020-08-30 14:03:02 +02:00
Stéphane Nicolet 406979ea12 Embed default net, and simplify using non-default nets
covers the most important cases from the user perspective:

It embeds the default net in the binary, so a download of that binary will result
in a working engine with the default net. The engine will be functional in the default mode
without any additional user action.

It allows non-default nets to be used, which will be looked for in up to
three directories (working directory, location of the binary, and optionally a specific default directory).
This mechanism is also kept for those developers that use MSVC,
the one compiler that doesn't have an easy mechanism for embedding data.

It is possible to disable embedding, and instead specify a specific directory, e.g. linux distros might want to use
CXXFLAGS="-DNNUE_EMBEDDING_OFF -DDEFAULT_NNUE_DIRECTORY=/usr/share/games/stockfish/" make -j ARCH=x86-64 profile-build

passed STC non-regression:
https://tests.stockfishchess.org/tests/view/5f4a581c150f0aef5f8ae03a
LLR: 2.95 (-2.94,2.94) {-1.25,-0.25}
Total: 66928 W: 7202 L: 7147 D: 52579
Ptnml(0-2): 291, 5309, 22211, 5360, 293

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

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

No functional change.
2020-08-29 21:56:00 +02:00
VoyagerOne 242a7d9fea Simplify MCP in QS
Simplify moveCount pruning in QS by removing depth dependency.

STC
LLR: 2.94 (-2.94,2.94) {-1.25,0.25}
Total: 42960 W: 4741 L: 4661 D: 33558
Ptnml(0-2): 218, 3574, 13804, 3678, 206
https://tests.stockfishchess.org/tests/view/5f42e3f75089a564a10d8493

LTC
LLR: 2.94 (-2.94,2.94) {-0.75,0.25}
Total: 66672 W: 3563 L: 3508 D: 59601
Ptnml(0-2): 71, 3064, 26996, 3149, 56
https://tests.stockfishchess.org/tests/view/5f4353285089a564a10d84d0

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

Bench: 4074430
2020-08-26 07:19:35 +02:00
VoyagerOne 95b8f3f800 Remove Reduce Depth
Remove Reduce Depth at PV nodes.

STC:
LLR: 2.94 (-2.94,2.94) {-1.25,0.25}
Total: 56760 W: 6299 L: 6236 D: 44225
Ptnml(0-2): 286, 4843, 18076, 4872, 303
https://tests.stockfishchess.org/tests/view/5f41356087a5c3c63d8f53c9

LTC:
LLR: 2.95 (-2.94,2.94) {-0.75,0.25}
Total: 17496 W: 954 L: 865 D: 15677
Ptnml(0-2): 13, 768, 7098, 855, 14
https://tests.stockfishchess.org/tests/view/5f41bb7687a5c3c63d8f53f9

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

Bench: 3555051
2020-08-26 07:16:50 +02:00
syzygy1 9b4967071e Remove EvalList
This patch removes the EvalList structure from the Position object and generally simplifies the interface between do_move() and the NNUE code.

The NNUE evaluation function first calculates the "accumulator". The accumulator consists of two halves: one for white's perspective, one for black's perspective.

If the "friendly king" has moved or the accumulator for the parent position is not available, the accumulator for this half has to be calculated from scratch. To do this, the NNUE node needs to know the positions and types of all non-king pieces and the position of the friendly king. This information can easily be obtained from the Position object.

If the "friendly king" has not moved, its half of the accumulator can be calculated by incrementally updating the accumulator for the previous position. For this, the NNUE code needs to know which pieces have been added to which squares and which pieces have been removed from which squares. In principle this information can be derived from the Position object and StateInfo struct (in the same way as undo_move() does this). However, it is probably a bit faster to prepare this information in do_move(), so I have kept the DirtyPiece struct. Since the DirtyPiece struct now stores the squares rather than "PieceSquare" indices, there are now at most three "dirty pieces" (previously two). A promotion move that captures a piece removes the capturing pawn and the captured piece from the board (to SQ_NONE) and moves the promoted piece to the promotion square (from SQ_NONE).

An STC test has confirmed a small speedup:

https://tests.stockfishchess.org/tests/view/5f43f06b5089a564a10d850a
LLR: 2.94 (-2.94,2.94) {-0.25,1.25}
Total: 87704 W: 9763 L: 9500 D: 68441
Ptnml(0-2): 426, 6950, 28845, 7197, 434

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

No functional change
2020-08-26 07:11:26 +02:00
Joost VandeVondele b0b4ca17db Check ARCH=.... variable
to prevent user errors or generating untested code,
check explicitly that the ARCH variable is equivalent to a supported architecture
as listed in `make help`.

To nevertheless compile for an untested target the user can override the internal
variable, passing the undocumented `SUPPORTED_ARCH=true` to make.

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

No functional change.
2020-08-26 07:07:06 +02:00
mstembera 530fccbf27 Allow for VNNI256 compilation with g++-8
explicitly pass needed -mavx512f -mavx512bw flags

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

No functional change
2020-08-24 12:43:39 +02:00
Vizvezdenec 843a961a8c Introduce countermove based pruning for qsearch
This patch continues work of previous patch in introducing pruning heuristics in qsearch by analogy to main search, now with countermove based pruning.
Idea is that if move is late enough and is quite check (we do generate them in qsearch) and has bad enough countermove history - prune it.

passed STC
https://tests.stockfishchess.org/tests/view/5f41220287a5c3c63d8f53c5
LLR: 2.93 (-2.94,2.94) {-0.25,1.25}
Total: 35944 W: 4127 L: 3929 D: 27888
Ptnml(0-2): 196, 2970, 11459, 3134, 213

passed LTC
https://tests.stockfishchess.org/tests/view/5f41862f87a5c3c63d8f53e8
LLR: 2.95 (-2.94,2.94) {0.25,1.25}
Total: 138448 W: 7655 L: 7252 D: 123541
Ptnml(0-2): 145, 6247, 56043, 6638, 151

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

Bench: 3610676
2020-08-24 12:09:04 +02:00
Sami Kiminki f7b3f0e842 Allow TT entries with key16==0 to be fetched
Fix the issue where a TT entry with key16==0 would always be reported
as a miss. Instead, we'll use depth8 to detect whether the TT entry is
occupied. In order to do that, we'll change DEPTH_OFFSET to -7
(depth8==0) to distinguish between an unoccupied entry and the
otherwise lowest possible depth, i.e., DEPTH_NONE (depth8==1).

To prevent a performance regression, we'll reorder the TT entry fields
by the access order of TranspositionTable::probe(). Memory in general
works fastest when accessed in sequential order. We'll also match the
store order in TTEntry::save() with the entry field order, and
re-order the 'if-or' expressions in TTEntry::save() from the cheapest
to the most expensive.

Finally, as we now have a proper TT entry occupancy test, we'll fix a
minor corner case with hashfull reporting. To reproduce:
- Use a big hash
- Either:
  a. Start 31 very quick searches (this wraparounds generation to 0); or
  b. Force generation of the first search to 0.
- go depth infinite

Before the fix, hashfull would incorrectly report nearly full hash
immediately after the search start, since
TranspositionTable::hashfull() used to consider only the entry
generation and not whether the entry was actually occupied.

STC:
LLR: 2.95 (-2.94,2.94) {-0.25,1.25}
Total: 36848 W: 4091 L: 3898 D: 28859
Ptnml(0-2): 158, 2996, 11972, 3091, 207
https://tests.stockfishchess.org/tests/view/5f3f98d5dc02a01a0c2881f7

LTC:
LLR: 2.95 (-2.94,2.94) {0.25,1.25}
Total: 32280 W: 1828 L: 1653 D: 28799
Ptnml(0-2): 34, 1428, 13051, 1583, 44
https://tests.stockfishchess.org/tests/view/5f3fe77a87a5c3c63d8f5332

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

Bench: 3760677
2020-08-24 12:03:28 +02:00
mstembera 701b2427bd Support VNNI on 256bit vectors
due to downclocking on current chips (tested up to cascade lake)
supporting avx512 and vnni512, it is better to use avx2 or vnni256
in multithreaded (in particular hyperthreaded) engine use.
In single threaded use, the picture is different.

gcc compilation for vnni256 requires a toolchain for gcc >= 9.

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

No functional change
2020-08-24 12:03:04 +02:00
George Sobala e453f09f06 armv8 AArch64 does not require -mfpu=neon
-mpfu is not required on AArch64 / armv8 architecture on Linux and throws an error if present.
This PR has been tested on gcc and clang on Gentoo-64 and Raspian-64 on a Raspberry Pi 4,
as well as with a cross from Ubuntu
(`make clean && make -j build ARCH=armv8         COMP=gcc COMPILER=aarch64-linux-gnu-g++`)

fixes https://github.com/official-stockfish/Stockfish/issues/3056
closes https://github.com/official-stockfish/Stockfish/pull/3059

No functional change
2020-08-24 11:30:55 +02:00
Vizvezdenec d5f86b6359 Introduce movecount pruning for qsearch()
If in quiescence search, we assume that me can prune late moves when:

a) the move ordering count of the move is : moveCount > abs(depth) + 2
b) we are not in check
c) the late move does not give check
d) the late move is not an advanced pawn push

Modification of an original idea by @VoyagerOne.

STC
https://tests.stockfishchess.org/tests/view/5f40581787a5c3c63d8f535f
LLR: 2.96 (-2.94,2.94) {-0.25,1.25}
Total: 132848 W: 14999 L: 14661 D: 103188
Ptnml(0-2): 684, 11242, 42309, 11430, 759

LTC
https://tests.stockfishchess.org/tests/view/5f4226da87a5c3c63d8f5412
LLR: 2.98 (-2.94,2.94) {0.25,1.25}
Total: 12008 W: 678 L: 551 D: 10779
Ptnml(0-2): 8, 485, 4899, 596, 16

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

Bench: 3749974
2020-08-23 23:27:03 +02:00
syzygy1 cc9d503dde Skip the alignment bug workaround for Clang
Clang-10.0.0 poses as gcc-4.2:

$ clang++ -E -dM - </dev/null | grep GNUC

This means that Clang is using the workaround for the alignment bug of gcc-8
even though it does not have the bug (as far as I know).

This patch should speed up AVX2 and AVX512 compiles on Windows (when using Clang),
because it disables (for Clang) the gcc workaround we had introduced in this commit:
https://github.com/official-stockfish/Stockfish/commit/875183b310a8249922c2155e82cb4cecfae2097e

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

No functional change.
2020-08-23 23:09:31 +02:00
Joost VandeVondele 5f1843c9cb Small trivial cleanups
closes https://github.com/official-stockfish/Stockfish/pull/2801

No functional change
2020-08-23 01:53:41 +02:00
Stéphane Nicolet 3542033342 Instructions to build on older Macintosh
In recent Macs, it is possible to use the Clang compiler provided by Apple
to compile Stockfish out of the box, and this is the method used by default
in our Makefile (the Makefile sets the macosx-version-min=10.14 flag to select
the right libc++ library for the Clang compiler with recent c++17 support).

But it is quite possible to compile and run Stockfish on older Macs! Below
we describe a method to install a recent GNU compiler on these Macs, to get
the c++17 support. We have tested the following procedure to install gcc10 on
machines running Mac OS 10.7, Mac OS 10.9 and Mac OS 10.13:

1) install XCode for your machine.

2) install Apple command-line developer tools for XCode, by typing the following
   command in a Terminal:

```
      sudo xcode-select --install
```

3) go to the Stockfish "src" directory, then try a default build and run Stockfish:

```
      make clean
      make build
      make net
      ./stockfish
```

4) if step 3 worked, congrats! You have a compiler recent enough on your Mac
to compile Stockfish. If not, continue with step 5 to install GNU gcc10 :-)

5) install the MacPorts package manager (https://www.macports.org/install.php),
for instance using the fast method in the "macOS Package (.pkg) Installer"
section of the page.

6) use the "port" command to install the gcc10 package of MacPorts by typing the
following command:

```
    sudo port install gcc10
```

With this step, MacPorts will install the gcc10 compiler under the name "g++-mp-10"
in the /opt/local/bin directory:

```
   which g++-mp-10

   /opt/local/bin/g++-mp-10       <--- answer
```

7) You can now go back to the "src" directory of Stockfish, and try to build
Stockfish by pointing at the right compiler:

```
   make clean
   make build COMP=gcc COMPCXX=/opt/local/bin/g++-mp-10
   make net
   ./stockfish
```

8) Enjoy Stockfish on Macintosh!

See this pull request for further discussion:
https://github.com/official-stockfish/Stockfish/pull/3049

No functional change
2020-08-22 22:37:50 +02:00
Joost VandeVondele 34f67c5722 Explicitly rely on pthreads if possible
allows us to set the needed stacksize on thread creation.

Useful for environments with too small a default stack size (e.g. Alpine Linux with musl).

Passed STC, no regression:

LLR: 2.96 (-2.94,2.94) {-1.25,0.25}
Total: 17816 W: 1344 L: 1275 D: 15197
Ptnml(0-2): 30, 1057, 6682, 1092, 47
https://tests.stockfishchess.org/tests/view/5f402b5587a5c3c63d8f534d

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

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

No functional change.
2020-08-22 11:00:45 +02:00
MJZ1977 cbcb05ca09 Display classic and NNUE evaluation in trace mode
show both the classical and NNUE evaluation,
as well as the Final evaluation.

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

No functional change.
2020-08-22 10:58:08 +02:00
Unai Corzo e64b957274 Simplify away internal iterative deepening
Remove the iterative deepening step.
Instead, employ a depth reduction if the position is not in TT and on the PV.

STC https://tests.stockfishchess.org/tests/view/5f3ce6eaa95672ddd56c637e
LLR: 2.97 (-2.94,2.94) {-0.50,1.50}
Total: 41096 W: 4421 L: 4257 D: 32418
Ptnml(0-2): 207, 3259, 13460, 3407, 215

LTC (old) https://tests.stockfishchess.org/tests/view/5f3d7d4fa95672ddd56c640b
LLR: 2.92 (-2.94,2.94) {-1.50,0.50}
Total: 26032 W: 1320 L: 1309 D: 23403
Ptnml(0-2): 22, 1152, 10654, 1169, 19

LTC (new) https://tests.stockfishchess.org/tests/view/5f3e31e0a95672ddd56c6464
LLR: 2.95 (-2.94,2.94) {-0.75,0.25}
Total: 34160 W: 1844 L: 1766 D: 30550
Ptnml(0-2): 33, 1533, 13876, 1599, 39

bench: 3849173
2020-08-21 18:04:14 +02:00
gsobala 15abcaedc1 Update Makefile for macOS
Changes to deal with compilation (particularly profile-build) on macOS.
(1) The default toolchain has gcc masquerading as clang,
    the previous Makefile was not picking up the required changes
    to the different profiling tools.
(2) The previous Makefile test for gccisclang occurred before
    a potential overwrite of CXX by COMPCXX
(3) llvm-profdata no longer runs as a command on macOS and
    instead is invoked by ``xcrun llvm-profdata``
(4) Needs to support use of true gcc using e.g.
    ``make build ... COMPCXX=g++-10``
(5) enable profile-build in travis for macOS

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

No functional change
2020-08-21 17:59:21 +02:00
Joost VandeVondele 8b45b1c490 Deal with very old linux kernels
MADV_HUGEPAGE might not be available, for kernels before 2.6.38 (released 2011). Just skip the madvise.

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

No functional change
2020-08-21 17:56:33 +02:00
Joost VandeVondele daac86691d Set Use NNUE by default to true
Since the initial stages of the merge, progress has been made so that
this seems the best option now:

* NNUE is clearly stronger on most relevant hardware and time controls
* All of our CI and testing infrastructure has been adjusted
* The default net is easy to get (further ideas #3030)

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

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

No functional change.
2020-08-20 21:14:32 +02:00
Joost VandeVondele a1ad8604a1 Send error message as an UCI info string
some GUIs do not show the error message when the engine terminates in the no-net case, as it is send to cerr.
Instead send it as an info string, which the GUI will more likely display.

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

No functional change.
2020-08-20 21:13:07 +02:00
SFisGOD 2deb08a529 Reintroduce last captures extension
STC:
LLR: 2.93 (-2.94,2.94) {-0.50,1.50}
Total: 34840 W: 3834 L: 3682 D: 27324
Ptnml(0-2): 153, 2767, 11455, 2865, 180
https://tests.stockfishchess.org/tests/view/5f3bb380b38d442594aabefc

LTC:
LLR: 2.95 (-2.94,2.94) {0.25,1.75}
Total: 15832 W: 890 L: 776 D: 14166
Ptnml(0-2): 17, 669, 6429, 785, 16
https://tests.stockfishchess.org/tests/view/5f3c46a0a95672ddd56c632a

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

see also https://github.com/official-stockfish/Stockfish/pull/3020

Bench: 4348811
2020-08-20 21:12:37 +02:00
syzygy1 42e8789f0b Expanded support for x86-32 architectures.
add new ARCH targets

x86-32-sse41-popcnt     > x86 32-bit with sse41 and popcnt support
x86-32-sse2             > x86 32-bit with sse2 support
x86-32                  > x86 32-bit generic (with mmx and sse support)

retire x86-32-old (use general-32)

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

No functional change.
2020-08-18 20:15:07 +02:00
Joost VandeVondele 384d684484 Better error message on missing curl/wget
provide clean error/warning message for missing curl/wget, sha256sum/shasum

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

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

No functional change
2020-08-18 19:57:30 +02:00
Joost VandeVondele fbae5614eb Fix Makefile typo
remove stray quote, shown with `make help`

No functional change
2020-08-18 08:49:06 +02:00
mstembera 1bcc981a5a Fallback to NNUE
If the classical eval ends up much smaller than estimated fall back to NNUE.
Also use multiply instead of divide for the threshold comparison for smoother transitions without rounding.

STC https://tests.stockfishchess.org/tests/view/5f3a5011b38d442594aabdfe
LLR: 2.96 (-2.94,2.94) {-0.50,1.50}
Total: 57352 W: 6325 L: 6135 D: 44892
Ptnml(0-2): 277, 4748, 18482, 4846, 323

LTC https://tests.stockfishchess.org/tests/view/5f3aee9db38d442594aabe82
LLR: 2.95 (-2.94,2.94) {0.25,1.75}
Total: 16232 W: 897 L: 781 D: 14554
Ptnml(0-2): 19, 679, 6616, 771, 31

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

bench: 4026216

-----

Recommended net: https://tests.stockfishchess.org/api/nn/nn-82215d0fd0df.nnue
2020-08-18 08:36:57 +02:00
Unai Corzo 581b92e4a7 Remove last captures extension
STC https://tests.stockfishchess.org/tests/view/5f395657e98b6c64b3df41dd
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 144664 W: 15426 L: 15537 D: 113701
Ptnml(0-2): 612, 11341, 48537, 11230, 612

LTC https://tests.stockfishchess.org/tests/view/5f3a2ec7b38d442594aabdd7
LLR: 2.96 (-2.94,2.94) {-1.50,0.50}
Total: 22728 W: 1161 L: 1146 D: 20421
Ptnml(0-2): 21, 960, 9388, 973, 22

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

bench: 3832662
2020-08-18 08:33:42 +02:00
VoyagerOne 1c0b7bdf4f Remove history bonus from Eval
STC:
LLR: 2.92 (-2.94,2.94) {-1.50,0.50}
Total: 26776 W: 2787 L: 2725 D: 21264
https://tests.stockfishchess.org/tests/view/5f39d6beb38d442594aabd9b

LTC:
LLR: 2.93 (-2.94,2.94) {-1.50,0.50}
Total: 12968 W: 635 L: 608 D: 11725
https://tests.stockfishchess.org/tests/view/5f39decfb38d442594aabda7

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

Bench:  4335100
2020-08-18 08:29:42 +02:00
notruck 65b976439f Support building for Android using NDK
The easiest way to use the NDK in conjunction with this Makefile (tested on linux-x86_64):

1. Download the latest NDK (r21d) from Google from https://developer.android.com/ndk/downloads
2. Place and unzip the NDK in $HOME/ndk folder
3. Export the path variable e.g., `export PATH=$PATH:$HOME/ndk/android-ndk-r21d/toolchains/llvm/prebuilt/linux-x86_64/bin`
4. cd to your Stockfish/src dir
5. Issue `make -j ARCH=armv8 COMP=ndk build`  (use `ARCH=armv7` or `ARCH=armv7-neon` for older CPUs)
6. Optionally `make -j ARCH=armv8 COMP=ndk strip`
7. That's all. Enjoy!

Improves support from Raspberry Pi (incomplete?) and compiling on arm in general

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

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

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

Support is still fragile as we're missing CI on these targets. Nevertheless tested with:

```bash
  # build crosses from ubuntu 20.04 on x86 to various arch/OS combos
  # tested with suitable packages installed
  # (build-essentials, mingw-w64, g++-arm-linux-gnueabihf, NDK (r21d) from google)

  # cross to Android
  export PATH=$HOME/ndk/android-ndk-r21d/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH
  make clean && make -j build ARCH=armv7         COMP=ndk  && make -j build ARCH=armv7 COMP=ndk strip
  make clean && make -j build ARCH=armv7-neon    COMP=ndk  && make -j build ARCH=armv7-neon COMP=ndk strip
  make clean && make -j build ARCH=armv8         COMP=ndk  && make -j build ARCH=armv8 COMP=ndk strip

  # cross to Raspberry Pi
  make clean && make -j build ARCH=armv7         COMP=gcc COMPILER=arm-linux-gnueabihf-g++
  make clean && make -j build ARCH=armv7-neon    COMP=gcc COMPILER=arm-linux-gnueabihf-g++

  # cross to Windows
  make clean && make -j build ARCH=x86-64-modern COMP=mingw
```

No functional change
2020-08-18 08:19:22 +02:00
Unai Corzo 0e17a89e4d Simplify away the passed pawn extension
STC https://tests.stockfishchess.org/tests/view/5f3955f0e98b6c64b3df41d7
LLR: 2.96 (-2.94,2.94) {-1.50,0.50}
Total: 31992 W: 3611 L: 3548 D: 24833
Ptnml(0-2): 174, 2658, 10273, 2713, 178

LTC https://tests.stockfishchess.org/tests/view/5f399e41e98b6c64b3df4210
LLR: 3.01 (-2.94,2.94) {-1.50,0.50}
Total: 29568 W: 1488 L: 1480 D: 26600
Ptnml(0-2): 40, 1272, 12142, 1300, 30

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

bench: 3844671

-----

Recommended net: https://tests.stockfishchess.org/api/nn/nn-82215d0fd0df.nnue
2020-08-17 12:27:35 +02:00
Stéphane Nicolet 81d716f5cc Reformat code in little-endian patch
Reformat code and rename the function to "read_little_endian()" in the recent
commit by Ronald de Man for support of big endian systems.

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

No functional change
-----

Recommended net: https://tests.stockfishchess.org/api/nn/nn-82215d0fd0df.nnue
2020-08-17 12:15:57 +02:00
Joost VandeVondele 65572de4a7 Add further targets to travis testing
general-32, general-64 and help

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

No functional change
2020-08-16 21:10:26 +02:00
syzygy1 72dc7a5c54 Assume network file is in little-endian byte order
This patch fixes the byte order when reading 16- and 32-bit values from the network file on a big-endian machine.

Bytes are ordered in read_le() using unsigned arithmetic, which doesn't need tricks to determine the endianness of the machine. Unfortunately the compiler doesn't seem to be able to optimise the ordering operation, but reading in the weights is not a time-critical operation and the extra time it takes should not be noticeable.

Big endian systems are still untested with NNUE.

fixes #3007

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

No functional change.
2020-08-16 21:10:26 +02:00
Daylen Yang 8cf43c6317 Display NEON in compiler string
if NEON intrinsics are being used and USE_NEON is defined.

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

No functional change
2020-08-16 21:10:26 +02:00
Joost VandeVondele cd0b8b4cf2 Use NNUE more for fortresses
Increases the use of NNUE evaluation in positions without captures/pawn moves,
by increasing the NNUEThreshold threshold with rule50_count.

This patch will force Stockfish to use NNUE eval more and more in materially
unbalanced positions, when it seems that the classical eval is struggling to
win and only manages to shuffle. This will ask the (slower) NNUE eval to
double-check the potential fortress branches of the search tree, but only
when necessary.

passed STC:
https://tests.stockfishchess.org/tests/view/5f36f1bf11a9b1a1dbf192d8
LLR: 2.93 (-2.94,2.94) {-0.50,1.50}
Total: 51824 W: 5836 L: 5653 D: 40335
Ptnml(0-2): 264, 4356, 16512, 4493, 287

passed LTC:
https://tests.stockfishchess.org/tests/view/5f37836111a9b1a1dbf1936d
LLR: 2.93 (-2.94,2.94) {0.25,1.75}
Total: 29768 W: 1747 L: 1590 D: 26431
Ptnml(0-2): 33, 1347, 11977, 1484, 43

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

Bench: 4173967
2020-08-16 08:20:32 +02:00
mstembera 6eb186c97e Try to match relative magnitude of NNUE eval to classical
The idea is that since we are mixing NNUE and classical evals matching their magnitudes closer allows for better comparisons.

STC https://tests.stockfishchess.org/tests/view/5f35a65411a9b1a1dbf18e2b
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 9840 W: 1150 L: 1027 D: 7663
Ptnml(0-2): 49, 772, 3175, 855, 69

LTC https://tests.stockfishchess.org/tests/view/5f35bcbe11a9b1a1dbf18e47
LLR: 2.93 (-2.94,2.94) {0.25,1.75}
Total: 44424 W: 2492 L: 2294 D: 39638
Ptnml(0-2): 42, 2015, 17915, 2183, 57

also corrects the location to clamp the evaluation (non-function on bench).

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

bench: 3905447
2020-08-14 16:39:52 +02:00
Miguel Lahoz e5f450cf0b Also dampen NNUE eval with 50 move rule
Move the existing dampening function last so that NNUE evaluations are
also handled as we approach the 50 move rule.

STC:
LLR: 2.95 (-2.94,2.94) {-0.50,1.50}
Total: 4792 W: 695 L: 561 D: 3536
Ptnml(0-2): 19, 420, 1422, 478, 57
https://tests.stockfishchess.org/tests/view/5f3164179081672066537534

LTC:
LLR: 8.62 (-2.94,2.94) {0.25,1.75}
Total: 286744 W: 18494 L: 17430 D: 250820
Ptnml(0-2): 418, 14886, 111745, 15860, 463
https://tests.stockfishchess.org/tests/view/5f316b039081672066537541

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

Bench: 4001800
2020-08-14 16:31:18 +02:00
Joost VandeVondele ce009ea1aa Verify SHA of downloaded net file
check SHA of the available and downloaded file.

Document the format requirement on the default net.

Also allow curl to make possibly insecure connections, as needed for old curl.

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

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

No functional change.
2020-08-14 16:20:42 +02:00
Stéphane Nicolet e8ea215a13 Clean-up Makefile help
Do not show the details of the default architecture for a simple "make help"
invocation, as the details are most likely to confuse beginners. Instead we
make it clear which architecture is the default and put an example at the end
of the Makefile as an incentative to use "make help ARCH=blah" to discover
the flags used by the different architectures.

```
    make help
    make help ARCH=x86-64-ssse3
```

Also clean-up and modernize a bit the Makefile examples while at it.

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

No functional change
2020-08-14 16:18:50 +02:00
Sergio Vieri 67e48418af Update default net to nn-82215d0fd0df.nnue
Net created at: 20200812-2257

passed STC: https://tests.stockfishchess.org/tests/view/5f340ca99e5f2effc089da17
LLR: 2.96 (-2.94,2.94) {-0.50,1.50}
Total: 5744 W: 756 L: 627 D: 4361
Ptnml(0-2): 28, 485, 1731, 586, 42

passed LTC: https://tests.stockfishchess.org/tests/view/5f341eba9e5f2effc089da23
LLR: 2.94 (-2.94,2.94) {0.25,1.75}
Total: 17136 W: 1041 L: 917 D: 15178
Ptnml(0-2): 13, 813, 6807, 907, 28

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

Bench: 3935117
2020-08-13 07:50:52 +02:00
Joost VandeVondele 69cfe28f31 Output the SSE2 flag in compiler_info
was missing in the list of outputs, slightly reorder flags.
explicitly add -msse2 if USE_SSE2 (is implicit already, -msse -m64).

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

No functional change.
2020-08-13 07:41:06 +02:00
mstembera dd63b98fb0 Add support for VNNI
Adds support for Vector Neural Network Instructions (avx512), as available on Intel Cascade Lake

The _mm512_dpbusd_epi32() intrinsic (vpdpbusd instruction) is taylor made for NNUE.

on a cascade lake CPU (AWS C5.24x.large, gcc 10) NNUE eval is at roughly 78% nps of classical
(single core test)

bench 1024 1 24 default depth:
target 	classical 	NNUE 	ratio
vnni 	2207232 	1725987 	78.20
avx512 	2216789 	1671734 	75.41
avx2 	2194006 	1611263 	73.44
modern 	2185001 	1352469 	61.90

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

No functional change
2020-08-13 07:39:52 +02:00
Daylen Yang 6bc0256292 Use posix_memalign for Apple Silicon instead of _mm_malloc
fails to build on that target, because of missing Intel Intrinsics.
macOS has posix_memalign() since ~2014 so we can simplify the code and just use that for all Apple platforms.

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

No functional change.
2020-08-12 07:49:36 +02:00
Joost VandeVondele 992f549ae7 Restrict avx2 hack to windows target
this workaround is possibly rather a windows & gcc specific problem. See e.g.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54412#c25

on Linux with gcc 8 this patch brings roughly a 8% speedup.
However, probably needs some testing in the wild.

includes a workaround for an old msys make (3.81) installation (fixes #2984)

No functional change
2020-08-11 23:35:02 +02:00
SFisGOD ee06046412 Tweak castling extension
Change condition from three friendly pieces to two. This now means that we only extend castling on the king side if there are no other friendly pieces aside from king and rook. For the queen side, we only extend if there is only a rook and another friendly piece or if there is only a single rook and no other friendly piece but this is very rare.

STC:
LLR: 3.20 (-2.94,2.94) {-0.50,1.50}
Total: 31144 W: 4086 L: 3903 D: 23155
Ptnml(0-2): 227, 2843, 9278, 2968, 256
https://tests.stockfishchess.org/tests/view/5f31487f9081672066537516

LTC:
LLR: 2.93 (-2.94,2.94) {0.25,1.75}
Total: 57816 W: 3786 L: 3538 D: 50492
Ptnml(0-2): 92, 2991, 22488, 3251, 86
https://tests.stockfishchess.org/tests/view/5f3167c3908167206653753d

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

Bench: 4244812
2020-08-11 13:46:02 +02:00
Guy Vreuls ea6220f381 This commit enables a mixed bench, to improve CI and allow for PGO (profile-build) of the NNUE part of the code.
Joint work gvreuls / vondele

* Download the default NNUE net in AppVeyor
* Download net in travis CI `make net`
* Adjust tests to cover more archs, speedup instrumented testing
* Introduce 'mixed' bench as default, with further options:

classical, NNUE, mixed.

mixed (default) and NNUE require the default net to be present,
which can be obtained with

```
make net
```

Further examples (first is equivalent to `./stockfish bench`):

```
./stockfish bench 16 1 13 default depth mixed
./stockfish bench 16 1 13 default depth classical
./stockfish bench 16 1 13 default depth NNUE
```

The net is now downloaded automatically if needed for `profile-build`
(usual `build` works fine without net present)

PGO gives a nice speedup on fishtest:

passed STC:
LLR: 2.93 (-2.94,2.94) {-0.50,1.50}
Total: 3360 W: 469 L: 343 D: 2548
Ptnml(0-2): 20, 246, 1030, 356, 28
https://tests.stockfishchess.org/tests/view/5f31b5499081672066537569

passed LTC:
LLR: 2.97 (-2.94,2.94) {0.25,1.75}
Total: 8824 W: 609 L: 502 D: 7713
Ptnml(0-2): 8, 430, 3438, 519, 17
https://tests.stockfishchess.org/tests/view/5f31c87b908167206653757c

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

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

requires fishtest updates before commit

Bench: 4290577
2020-08-11 08:17:03 +02:00
mstembera f46c73040c Fix AVX512 build with older compilers
avoids an intrinsic that is missing in gcc < 10.

For this target, might trigger another gcc bug on windows that
requires up-to-date gcc 8, 9, or 10, or usage of clang.

Fixes https://github.com/official-stockfish/Stockfish/issues/2975

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

No functional change
2020-08-11 08:17:03 +02:00
Joost VandeVondele 399cddf444 More aligned_alloc changes to support Android
Move to posix_memalign for those platforms, in particular android,
that do not fully support c++17 std::aligned_alloc() (and are not windows)

see https://github.com/official-stockfish/Stockfish/issues/2860

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

No functional change
2020-08-11 08:17:03 +02:00
Guy Vreuls 4ab8b0b738 Fix parallel LTO issues on Windows
This adds -save-temps to the linker flags when parallel LTO is used on
MinGW/MSYS.

fixes #2977

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

No functional change.
2020-08-11 08:17:03 +02:00
Vizvezdenec a72cec1ff8 Add comments to probCut code
and rename a variable

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

No functional change
2020-08-11 08:17:03 +02:00
Unai Corzo 220ef1d27d Assorted search parameter tune
STC https://tests.stockfishchess.org/tests/view/5f31219090816720665374ec
LLR: 2.96 (-2.94,2.94) {-0.50,1.50}
Total: 3376 W: 487 L: 359 D: 2530
Ptnml(0-2): 17, 253, 1042, 337, 39

LTC https://tests.stockfishchess.org/tests/view/5f3127f79081672066537502
LLR: 2.93 (-2.94,2.94) {0.25,1.75}
Total: 8360 W: 581 L: 475 D: 7304
Ptnml(0-2): 11, 407, 3238, 513, 11

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

bench: 4733874
2020-08-10 19:17:57 +02:00
Fanael Linithien 21df37d7fd Provide vectorized NNUE code for SSE2 and MMX targets
This patch allows old x86 CPUs, from AMD K8 (which the x86-64 baseline
targets) all the way down to the Pentium MMX, to benefit from NNUE with
comparable performance hit versus hand-written eval as on more modern
processors.

NPS of the bench with NNUE enabled on a Pentium III 1.13 GHz (using the
MMX code):
  master: 38951
  this patch: 80586

NPS of the bench with NNUE enabled using baseline x86-64 arch, which is
how linux distros are likely to package stockfish, on a modern CPU
(using the SSE2 code):
  master: 882584
  this patch: 1203945

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

No functional change.
2020-08-10 19:17:57 +02:00
mstembera f948cd008d Cleanup and optimize SSE/AVX code
AVX512 +4% faster
AVX2 +1% faster
SSSE3 +5% faster

passed non-regression STC:
STC https://tests.stockfishchess.org/tests/view/5f31249f90816720665374f6
LLR: 2.96 (-2.94,2.94) {-1.50,0.50}
Total: 17576 W: 2344 L: 2245 D: 12987
Ptnml(0-2): 127, 1570, 5292, 1675, 124

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

No functional change
2020-08-10 14:38:17 +02:00
sf-x cb0504028e Makefile rework/cleanup
Makefile targets x86-64-sse42, x86-sse3 are removed; x86-64-sse41
is renamed to x86-64-sse41-popcnt (it did enable popcnt).

Makefile variables sse3, sse42, their associated compilation flags
and code in misc.cpp are removed.

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

No functional change
2020-08-10 14:32:11 +02:00
SFisGOD ad2ad4c657 Modify castling extension
Extend castling only if there are few friendly pieces on the castling side.

Inspired by silversolver1's (Rahul Dsilva) test
https://tests.stockfishchess.org/tests/view/5f0fef560640035f9d2978cf

STC:
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 7096 W: 947 L: 818 D: 5331
Ptnml(0-2): 32, 604, 2181, 665, 66
https://tests.stockfishchess.org/tests/view/5f309f729081672066537426

LTC:
LLR: 2.96 (-2.94,2.94) {0.25,1.75}
Total: 4712 W: 300 L: 215 D: 4197
Ptnml(0-2): 2, 190, 1895, 259, 10
https://tests.stockfishchess.org/tests/view/5f30a2039081672066537430

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

Bench: 4094850
2020-08-10 11:14:46 +02:00
mstembera 875183b310 Workaround using unaligned loads for gcc < 9
despite usage of alignas, the generated (avx2/avx512) code with older compilers needs to use
unaligned loads with older gcc (e.g. confirmed crash with gcc 7.3/mingw on abrok).

Better performance thus requires gcc >= 9 on hardware supporting avx2/avx512

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

No functional change
2020-08-10 11:12:35 +02:00
jjoshua2 a54f9011c3 simplying hybrid condition
STC https://tests.stockfishchess.org/tests/view/5f3059d1908167206653736b:
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 12520 W: 766 L: 727 D: 11027
Ptnml(0-2): 13, 624, 4949, 659, 15

LTC: https://tests.stockfishchess.org/tests/view/5f30863a90816720665373d1
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 12520 W: 766 L: 727 D: 11027
Ptnml(0-2): 13, 624, 4949, 659, 15

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

Bench: 4084753
2020-08-10 07:34:45 +02:00
Sergio Vieri bcdf41dadc Update default net to nn-112bb1c8cdb5.nnue
First trained net using search eval instead of pv leaf static eval.

Net created at: 20200810-0744

passed STC: https://tests.stockfishchess.org/tests/view/5f30995d90816720665373f8
LLR: 2.93 (-2.94,2.94) {-0.50,1.50}
Total: 15416 W: 2071 L: 1920 D: 11425
Ptnml(0-2): 123, 1376, 4563, 1519, 127

passed LTC: https://tests.stockfishchess.org/tests/view/5f30a104908167206653742b
LLR: 2.93 (-2.94,2.94) {0.25,1.75}
Total: 29792 W: 2003 L: 1834 D: 25955
Ptnml(0-2): 50, 1541, 11550, 1700, 55

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

Bench: 4084753
2020-08-10 07:29:40 +02:00
Joost VandeVondele 651ec3b31e Revert "Avoid special casing for MinGW"
This reverts commit a6e89293df.

The offending setup has been found as gcc/mingw 7.3 (on Ubuntu 18.04).

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

closes https://github.com/official-stockfish/Stockfish/issues/2968

No functional change.
2020-08-10 07:28:19 +02:00
Joost VandeVondele 27b593a944 Fix a data race for NNUE
the stateInfo at the rootPos is no longer read-only, as the NNUE accumulator is part of it.
Threads can thus not share this object and need their own copy.

tested for no regression
https://tests.stockfishchess.org/tests/view/5f3022239081672066536bce
LLR: 2.96 (-2.94,2.94) {-1.50,0.50}
Total: 52800 W: 6843 L: 6802 D: 39155
Ptnml(0-2): 336, 4646, 16399, 4679, 340

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

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

No functional change
2020-08-09 23:51:07 +02:00
Dariusz Orzechowski a6e89293df Avoid special casing for MinGW
after some testing, no version of MinGW/gcc has been found where this code is still necessary.
Probably older code (pre-c++17?)

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

No functional change
2020-08-09 23:49:14 +02:00
Vizvezdenec 2bfde55429 Adjust NNUE usage based on number of pawns in position
The idea of this patch is that positions are usually more complex and hard to evaluate even if there are more pawns.
This patch adjusts NNUE threshold usage depending on number of pawns in position, if pawn count is <3 we use the
classical evaluation more often, for pawn count = 3 patch the is non-functional,
with pawn count > 3 NNUE evaluation is used more often.

passed STC
https://tests.stockfishchess.org/tests/view/5f2f02d09081672066536b1f
LLR: 2.96 (-2.94,2.94) {-0.50,1.50}
Total: 36520 W: 5011 L: 4823 D: 26686
Ptnml(0-2): 299, 3482, 10548, 3594, 337

passed LTC
https://tests.stockfishchess.org/tests/view/5f2f4c329081672066536b5c
LLR: 2.98 (-2.94,2.94) {0.25,1.75}
Total: 39272 W: 2630 L: 2433 D: 34209
Ptnml(0-2): 53, 2066, 15218, 2229, 70

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

bench 4084753
2020-08-09 21:26:17 +02:00
Joost VandeVondele cd1bb27dd4 Fix aligned_alloc on MinGW
introduced with d7a26899a9

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

No functional change.
2020-08-09 21:25:22 +02:00
Joost VandeVondele 320fa1b2f0 Improve error message on missing net.
small rewording, but also print the download url for the default net.

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

No functional change
2020-08-09 17:09:18 +02:00
Daniel Dugovic d7a26899a9 Use fallback implementation for C++ aligned_alloc
fixes https://github.com/official-stockfish/Stockfish/issues/2921

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

No functional change
2020-08-09 17:07:45 +02:00
Unai Corzo add890a10b LMR search tweak
All credit to Vizvezdenec, the original author of the idea.

STC https://tests.stockfishchess.org/tests/view/5f2d606a61e3b6af64881f88
LLR: 2.95 (-2.94,2.94) {-0.50,1.50}
Total: 8440 W: 1191 L: 1048 D: 6201
Ptnml(0-2): 59, 754, 2467, 865, 75

LTC https://tests.stockfishchess.org/tests/view/5f2d84ad61e3b6af64881fbd
LLR: 2.95 (-2.94,2.94) {0.25,1.75}
Total: 21896 W: 1557 L: 1406 D: 18933
Ptnml(0-2): 33, 1185, 8378, 1302, 50

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

bench: 4084753
2020-08-08 22:42:00 +02:00
Unai Corzo 1949eb8604 Singular extension search tweak
Tweak depth.

STC https://tests.stockfishchess.org/tests/view/5f2d22ec61e3b6af64881f40
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 17984 W: 2603 L: 2441 D: 12940
Ptnml(0-2): 133, 1751, 5094, 1849, 165

LTC https://tests.stockfishchess.org/tests/view/5f2d5a6a61e3b6af64881f7f
LLR: 2.95 (-2.94,2.94) {0.25,1.75}
Total: 85808 W: 5956 L: 5621 D: 74231
Ptnml(0-2): 149, 4748, 32785, 5063, 159

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

fixes two README.md typos:
fixes https://github.com/official-stockfish/Stockfish/issues/2932

bench: 4022669
2020-08-08 22:39:26 +02:00
Guy Vreuls 6d6267c378 Parallelize Link Time Optimization for GCC, CLANG and MINGW
This patch tries to run multiple LTO threads in parallel, speeding up
the build process of optimized builds if the -j make parameter is used.
This mitigates the longer linking times of optimized builds since the
integration of the NNUE code. Roughly 2x build speedup.

I've tried a similar patch some two years ago but it ran into trouble
with old compiler versions then. Since we're on the C++17 standard now
these old compilers should be obsolete.

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

No functional change.
2020-08-08 22:35:18 +02:00
Vizvezdenec e663bc5330 Do more aggressive futility pruning for captures
This patch lines up with other patches which use better eval to produce more aggressive cutoffs based on static evaluation of position, it allows more aggressive futility pruning for captures - so now we will be producing them with bigger evaluation of position, so more often.

passed STC
https://tests.stockfishchess.org/tests/view/5f2da79e61e3b6af64881fd2
LLR: 3.87 (-2.94,2.94) {-0.50,1.50}
Total: 27256 W: 3809 L: 3593 D: 19854
Ptnml(0-2): 221, 2578, 7830, 2762, 237

passed LTC
https://tests.stockfishchess.org/tests/view/5f2df92061e3b6af64882012
LLR: 4.97 (-2.94,2.94) {0.25,1.75}
Total: 43624 W: 3095 L: 2820 D: 37709
Ptnml(0-2): 66, 2410, 16608, 2639, 89

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

Bench: 4272280
2020-08-08 22:08:55 +02:00
Moez Jellouli 3368d03285 update Null Move Pruning parameters
STC: https://tests.stockfishchess.org/tests/view/5f2dc38561e3b6af64881fec
LLR: 2.99 (-2.94,2.94) {-0.50,1.50}
Total: 6120 W: 903 L: 758 D: 4459
Ptnml(0-2): 44, 535, 1775, 644, 62

LTC: https://tests.stockfishchess.org/tests/view/5f2dd55f61e3b6af64882003
LLR: 2.95 (-2.94,2.94) {0.25,1.75}
Total: 7424 W: 577 L: 463 D: 6384
Ptnml(0-2): 16, 375, 2824, 473, 24

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

bench 4107833
2020-08-08 22:07:51 +02:00
mckx00 450b60a303 Remove unnecessay legality check
Possible after the recent reording pos.legal(move) check

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

No functional change.
2020-08-08 21:42:59 +02:00
U-DESKTOP-3900\Mark 23ecf3d5c6 simplified and increased threshold to switch between NNUE and classical
STC https://tests.stockfishchess.org/tests/view/5f2deb1661e3b6af6488200f
LLR: 2.96 (-2.94,2.94) {-1.50,0.50}
Total: 10376 W: 1481 L: 1359 D: 7536
Ptnml(0-2): 91, 953, 2981, 1069, 94

LTC: https://tests.stockfishchess.org/html/live_elo.html?5f2e0a0461e3b6af64882019
LLR: 2.99 (-2.94,2.94) {-1.50,0.50}
Total: 5040 W: 375 L: 315 D: 4350
Ptnml(0-2): 7, 263, 1926, 311, 13

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

Bench: 4067325
2020-08-08 08:40:51 +02:00
Vizvezdenec 910f779eb1 Do more futility pruning for parent nodes.
This patch increases LMRdepth threshold for futility pruning at parent nodes so it can apply more often.
With radical change to evaluation approach it seems that search is really far from optimal state, especially it parts that use static evaluation of position.

passed STC
https://tests.stockfishchess.org/tests/view/5f2da75661e3b6af64881fd0
LLR: 2.93 (-2.94,2.94) {-0.50,1.50}
Total: 8744 W: 1305 L: 1156 D: 6283
Ptnml(0-2): 75, 789, 2500, 928, 80

passed LTC
https://tests.stockfishchess.org/tests/view/5f2dcb2a61e3b6af64881ff3
LLR: 2.98 (-2.94,2.94) {0.25,1.75}
Total: 17728 W: 1256 L: 1117 D: 15355
Ptnml(0-2): 22, 961, 6774, 1070, 37

Bench: 4067325
2020-08-08 08:35:47 +02:00
SFisGOD f4c27cda1a Reintroduce late irreversible move extension
Reintroduce vondele's late irreversible move extension for fortress keeping.
This was removed when we only had classical eval.
Now that we have the NNUE net, it seems that this is useful again.

STC:
LLR: 2.93 (-2.94,2.94) {-0.50,1.50}
Total: 5352 W: 787 L: 653 D: 3912
Ptnml(0-2): 34, 451, 1579, 571, 41
https://tests.stockfishchess.org/tests/view/5f2dc8ad61e3b6af64881ff0

LTC:
LLR: 2.94 (-2.94,2.94) {0.25,1.75}
Total: 14416 W: 1013 L: 891 D: 12512
Ptnml(0-2): 15, 722, 5623, 822, 26
https://tests.stockfishchess.org/tests/view/5f2e0e3661e3b6af6488201e

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

Bench: 4154696
2020-08-08 08:33:24 +02:00
Lolligerhans 5ccff25df2 Expand outposts to minors shielded by pawns
Allow any pawn in front of a minor piece to replace the pawn protection
requirement for outposts.

  +-------+  +-------+
  | . . o |  | o . . |    o  Their pawns
  | . o x |  | o . . |    x  Our pawns
  | o N . |  | x o B |  N,B  New (reachable) outpost
  | . . . |  | . _ . |    _  Reachable square behind a pawn
  +-------+  +-------+
  N outpost  B reaches
               outpost

  We want outposts to be secured by pawns against major pieces. If
a minor is shielded by any pawn from above, it is rarely at the same
time protected by our pawn attacks from below. However, the pawn shield
in itself offers some degree of protection.
  A pawn shield will now suffice to replace the pawn protection for the
outpost (and reachable outpost) bonus.

This effect stacks with the existing "minor behind pawn" bonus.

STC
https://tests.stockfishchess.org/tests/view/5f2bcd14b3ebe5cbfee85b2c
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 27248 W: 5353 L: 5119 D: 16776
Ptnml(0-2): 462, 3174, 6185, 3274, 529

LTC
https://tests.stockfishchess.org/tests/view/5f2bfef5b3ebe5cbfee85b5a
LLR: 2.96 (-2.94,2.94) {0.25,1.75}
Total: 99432 W: 12580 L: 12130 D: 74722
Ptnml(0-2): 696, 8903, 30049, 9391, 677

Closes #2935

Bench: 4143673
2020-08-08 08:31:06 +02:00
Unai Corzo dc5af66ead Tweak futility pruning depth.
STC https://tests.stockfishchess.org/tests/view/5f2d237161e3b6af64881f43
LLR: 2.96 (-2.94,2.94) {-0.50,1.50}
Total: 12712 W: 1823 L: 1664 D: 9225
Ptnml(0-2): 122, 1166, 3627, 1313, 128

LTC https://tests.stockfishchess.org/tests/view/5f2d473061e3b6af64881f6f
LLR: 2.96 (-2.94,2.94) {0.25,1.75}
Total: 12104 W: 912 L: 788 D: 10404
Ptnml(0-2): 13, 665, 4582, 769, 23

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

bench: 4271421
2020-08-08 08:25:06 +02:00
Sergio Vieri 857e045ced Update default net to nn-9931db908a9b.nnue
Net created at 20200806-1802

passed STC:
https://tests.stockfishchess.org/tests/view/5f2d00b461e3b6af64881f21
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 6672 W: 1052 L: 898 D: 4722
Ptnml(0-2): 63, 600, 1868, 730, 75

passed LTC:
https://tests.stockfishchess.org/tests/view/5f2d052a61e3b6af64881f29
LLR: 2.96 (-2.94,2.94) {0.25,1.75}
Total: 7576 W: 573 L: 463 D: 6540
Ptnml(0-2): 8, 392, 2889, 480, 19

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

Bench: 4390086
2020-08-07 13:07:28 +02:00
Stefan Geschwentner 615d98da24 Do move legality check before pruning.
This alllows to simplify the code because the move counter haven't to be
decremented later if a move isn't legal. As a side effect now illegal
pruned moves doesn't included anymore in move counter. So slightly less
pruning and reductions are done.

STC:
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 111016 W: 21106 L: 21077 D: 68833
Ptnml(0-2): 1830, 13083, 25736, 12946, 1913
https://tests.stockfishchess.org/tests/view/5f28816fa5abc164f05e4c26

LTC:
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 39264 W: 4909 L: 4843 D: 29512
Ptnml(0-2): 263, 3601, 11854, 3635, 279
https://tests.stockfishchess.org/tests/view/5f297902a5abc164f05e4c8e

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

Bench: 4390086
2020-08-07 09:05:20 +02:00
UnaiCorzo 7f336dd59b Remove QueenInfiltration
STC https://tests.stockfishchess.org/tests/view/5f2955b1a5abc164f05e4c85
LLR: 2.96 (-2.94,2.94) {-1.50,0.50}
Total: 29216 W: 5560 L: 5416 D: 18240
Ptnml(0-2): 466, 3329, 6902, 3417, 494

LTC https://tests.stockfishchess.org/tests/view/5f299154a5abc164f05e4ca1
LLR: 2.92 (-2.94,2.94) {-1.50,0.50}
Total: 54144 W: 6635 L: 6594 D: 40915
Ptnml(0-2): 372, 4859, 16536, 4966, 339

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

Bench: 4609008
2020-08-07 09:00:45 +02:00
FauziAkram af935365e3 Tuned pawn values
Passed STC:
https://tests.stockfishchess.org/tests/view/5f2aa49fa5abc164f05e4d1b
LLR: 2.95 (-2.94,2.94) {-0.50,1.50}
Total: 40888 W: 7977 L: 7726 D: 25185
Ptnml(0-2): 665, 4806, 9333, 4893, 747

Passed LTC:
https://tests.stockfishchess.org/tests/view/5f2b1059b3ebe5cbfee85ae7
LLR: 2.98 (-2.94,2.94) {0.25,1.75}
Total: 51264 W: 6445 L: 6134 D: 38685
Ptnml(0-2): 328, 4564, 15580, 4789, 371

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

bench: 4314943
2020-08-07 08:57:37 +02:00
Stefan Geschwentner 8b8412ef87 Add tempo also to NNUE eval.
STC:
LLR: 2.93 (-2.94,2.94) {-0.50,1.50}
Total: 10608 W: 1507 L: 1358 D: 7743
Ptnml(0-2): 94, 945, 3074, 1100, 91
https://tests.stockfishchess.org/tests/view/5f2c5921b3ebe5cbfee85b8b

LTC:
LLR: 2.94 (-2.94,2.94) {0.25,1.75}
Total: 7536 W: 556 L: 448 D: 6532
Ptnml(0-2): 9, 383, 2881, 481, 14
https://tests.stockfishchess.org/tests/view/5f2c6f4461e3b6af64881e95

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

Bench: 4746616
2020-08-07 08:54:38 +02:00
MJZ1977 3dca13a958 NNUE evaluation threshold
The idea is to use NNUE only on quite balanced material positions. This bring a big speedup on research since NNUE eval is slower than classical eval for most of the hardwares and specially on unbalanced positions with LazyEval.

STC: https://tests.stockfishchess.org/tests/view/5f2c2680b3ebe5cbfee85b61
LLR: 2.95 (-2.94,2.94) {-0.50,1.50}
Total: 3168 W: 560 L: 400 D: 2208
Ptnml(0-2): 21, 294, 819, 404, 46

LTC: https://tests.stockfishchess.org/tests/view/5f2c2ca6b3ebe5cbfee85b69
LLR: 2.98 (-2.94,2.94) {0.25,1.75}
Total: 3200 W: 287 L: 183 D: 2730
Ptnml(0-2): 4, 149, 1191, 251, 5

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

Bench 4746616
2020-08-06 21:46:31 +02:00
nodchip 84f3e86790 Add NNUE evaluation
This patch ports the efficiently updatable neural network (NNUE) evaluation to Stockfish.

Both the NNUE and the classical evaluations are available, and can be used to
assign a value to a position that is later 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. The network is optimized
and trained on the evalutions 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.

This patch is the result of contributions of various authors, from various communities,
including: nodchip, ynasu87, yaneurao (initial port and NNUE authors), domschl, FireFather,
rqs, xXH4CKST3RXx, tttak, zz4032, joergoster, mstembera, nguyenpham, erbsenzaehler,
dorzechowski, and vondele.

This new evaluation needed various changes to fishtest and the corresponding infrastructure,
for which tomtor, ppigazzini, noobpwnftw, daylen, and vondele are gratefully acknowledged.

The first networks have been provided by gekkehenker and sergiovieri, with the latter
net (nn-97f742aaefcd.nnue) being the current default.

The evaluation function can be selected at run time with the `Use NNUE` (true/false) UCI option,
provided the `EvalFile` option points the the network file (depending on the GUI, with full path).

The performance of the NNUE evaluation relative to the classical evaluation depends somewhat on
the hardware, and is expected to improve quickly, but is currently on > 80 Elo on fishtest:

60000 @ 10+0.1 th 1
https://tests.stockfishchess.org/tests/view/5f28fe6ea5abc164f05e4c4c
ELO: 92.77 +-2.1 (95%) LOS: 100.0%
Total: 60000 W: 24193 L: 8543 D: 27264
Ptnml(0-2): 609, 3850, 9708, 10948, 4885

40000 @ 20+0.2 th 8
https://tests.stockfishchess.org/tests/view/5f290229a5abc164f05e4c58
ELO: 89.47 +-2.0 (95%) LOS: 100.0%
Total: 40000 W: 12756 L: 2677 D: 24567
Ptnml(0-2): 74, 1583, 8550, 7776, 2017

At the same time, the impact on the classical evaluation remains minimal, causing no significant
regression:

sprt @ 10+0.1 th 1
https://tests.stockfishchess.org/tests/view/5f2906a2a5abc164f05e4c5b
LLR: 2.94 (-2.94,2.94) {-6.00,-4.00}
Total: 34936 W: 6502 L: 6825 D: 21609
Ptnml(0-2): 571, 4082, 8434, 3861, 520

sprt @ 60+0.6 th 1
https://tests.stockfishchess.org/tests/view/5f2906cfa5abc164f05e4c5d
LLR: 2.93 (-2.94,2.94) {-6.00,-4.00}
Total: 10088 W: 1232 L: 1265 D: 7591
Ptnml(0-2): 49, 914, 3170, 843, 68

The needed networks can be found at https://tests.stockfishchess.org/nns
It is recommended to use the default one as indicated by the `EvalFile` UCI option.

Guidelines for testing new nets can be found at
https://github.com/glinscott/fishtest/wiki/Creating-my-first-test#nnue-net-tests

Integration has been discussed in various issues:
https://github.com/official-stockfish/Stockfish/issues/2823
https://github.com/official-stockfish/Stockfish/issues/2728

The integration branch will be closed after the merge:
https://github.com/official-stockfish/Stockfish/pull/2825
https://github.com/official-stockfish/Stockfish/tree/nnue-player-wip

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

This will be an exciting time for computer chess, looking forward to seeing the evolution of
this approach.

Bench: 4746616
2020-08-06 16:37:45 +02:00
Stefan Geschwentner 9587eeeb5e Tweak cutnode reduction
Less reduction for second move at non-check CUT node with depth <= 10.

STC:
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 38680 W: 7490 L: 7245 D: 23945
Ptnml(0-2): 643, 4441, 8967, 4606, 683
https://tests.stockfishchess.org/tests/view/5f21e1782f7e63962b99f451

LTC:
LLR: 2.95 (-2.94,2.94) {0.25,1.75}
Total: 71976 W: 9003 L: 8636 D: 54337
Ptnml(0-2): 440, 6414, 21972, 6663, 499
https://tests.stockfishchess.org/tests/view/5f2245762f7e63962b99f4bd

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

Bench: 4746616
2020-07-31 10:12:54 +02:00
Stéphane Nicolet 33f3cfae00 Improve handling of queen imbalance
We double the bonus for potential threats by minors and rooks against
our queen, in case of "queen vs pieces imbalance". Hopefully this will
improve a little bit the evaluation for this well-known Stockfish weakness.

passed STC:
LLR: 2.93 (-2.94,2.94) {-0.50,1.50}
Total: 72976 W: 14003 L: 13710 D: 45263
Ptnml(0-2): 1218, 8370, 17094, 8513, 1293
https://tests.stockfishchess.org/tests/view/5efa50eb020eec13834a977d

passed LTC:
LLR: 2.93 (-2.94,2.94) {0.25,1.75}
Total: 22232 W: 2779 L: 2560 D: 16893
Ptnml(0-2): 129, 1885, 6896, 2050, 156
https://tests.stockfishchess.org/tests/view/5f1fdd2dc09435d870cb9f13

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

Bench: 4367349
2020-07-31 10:01:39 +02:00
UnaiCorzo 62d3106caa Remove late irreversible move extension
We simplify away the late irreversible move extension, which
does not seem to be necessary in the current master.

STC
LLR: 2.93 (-2.94,2.94) {-1.50,0.50}
Total: 38584 W: 7464 L: 7342 D: 23778
Ptnml(0-2): 581, 4328, 9365, 4424, 594
https://tests.stockfishchess.org/tests/view/5f1c9669c09435d870cb9de9

LTC
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 27840 W: 3417 L: 3353 D: 21070
Ptnml(0-2): 120, 2315, 8994, 2363, 128
https://tests.stockfishchess.org/tests/view/5f1d2e22c09435d870cb9e21

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

bench: 4829420
2020-07-31 09:55:56 +02:00
protonspring f0abde241d Remove conditional_more_than_two().
This is a functional simplification that removes the conditional_more_than_two()
function, which was quite strange and kooky. Note the very minor change to the bench
value.

See this thread for relevant comments on the passing branch:
protonspring/Stockfish@d89730d...ff35b50

STC
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 59760 W: 11411 L: 11311 D: 37038
Ptnml(0-2): 992, 6863, 14044, 7015, 966
https://tests.stockfishchess.org/tests/view/5f179988c09435d870cb9b9a

LTC
LLR: 2.93 (-2.94,2.94) {-1.50,0.50}
Total: 45208 W: 5553 L: 5497 D: 34158
Ptnml(0-2): 315, 4081, 13761, 4127, 320
https://tests.stockfishchess.org/tests/view/5f184847c09435d870cb9bee

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

Bench: 4578290
2020-07-31 09:47:24 +02:00
Vizvezdenec d89730d5c8 Do not overwrite valuable TT data after probcut.
This patch allows an engine to write probcut data only in case
the probcut search depth is greater than transposition table depth.

passed STC
https://tests.stockfishchess.org/tests/view/5f0b52e959f6f035328949a6
LLR: 2.97 (-2.94,2.94) {-0.50,1.50}
Total: 52544 W: 10145 L: 9880 D: 32519
Ptnml(0-2): 853, 6097, 12121, 6334, 867

passed LTC
https://tests.stockfishchess.org/tests/view/5f0bd94c59f6f035328949f3
LLR: 2.93 (-2.94,2.94) {0.25,1.75}
Total: 49576 W: 6164 L: 5863 D: 37549
Ptnml(0-2): 297, 4371, 15218, 4538, 364

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

bench 4578298
2020-07-17 20:28:44 +02:00
mstembera c3092c54bc Multiple lazy stages.
An extension of the lazy eval idea: when the score is sufficiently large
we now skip more granular parts of the eval.

Inspired by an original patch by Moez Jellouli
https://tests.stockfishchess.org/tests/view/5f03b2a159f6f03532894529
Credit to him!

STC https://tests.stockfishchess.org/tests/view/5f0a862c59f6f03532894924
LLR: 2.95 (-2.94,2.94) {-0.50,1.50}
Total: 13504 W: 2684 L: 2472 D: 8348
Ptnml(0-2): 229, 1496, 3111, 1666, 250

LTC https://tests.stockfishchess.org/tests/view/5f0ac0e159f6f0353289495b
LLR: 2.94 (-2.94,2.94) {0.25,1.75}
Total: 31312 W: 3926 L: 3677 D: 23709
Ptnml(0-2): 185, 2773, 9509, 2986, 203

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

bench: 4541608
2020-07-17 20:24:02 +02:00
syzygy1 6c197c3964 Corrects a functional change in a cleanup patch.
This corrects a functional change in
https://github.com/official-stockfish/Stockfish/commit/ddcbacd04d1c860e808202ce8c1206c8acdca627
changing evaluation of KPPvK. Bench remains unchanged at low depth

With this patch, 8/8/5k1p/8/7p/7K/8/8 b - - 1 11 is again correctly evaluated as a draw.

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

Bench: 4366686
2020-07-11 22:32:34 +02:00
SFisGOD 1f3bd968bb Introduce bad outpost penalty
In some French games, Stockfish likes to bring the Knight to a bad outpost spot. This is evident in TCEC S18 Superfinal Game 63, where there is a Knight outpost on the queenside but is actually useless. Stockfish is effectively playing a piece down while holding ground against Leela's break on the kingside.

This patch turns the +56 mg bonus for a Knight outpost into a -7 mg penalty if it satisfies the following conditions:

* The outpost square is not on the CenterFiles (i.e. not on files C,D,E and F)
* The knight is not attacking non pawn enemies.
* The side where the outpost is located contains only few enemies, with a particular conditional_more_than_two() implementation

Thank you to apospa...@gmail.com for bringing this to our attention and for providing insights.
See https://groups.google.com/forum/?fromgroups=#!topic/fishcooking/dEXNzSIBgZU
Reference game: https://tcec-chess.com/#div=sf&game=63&season=18

Passed STC:
LLR: 2.93 (-2.94,2.94) {-0.50,1.50}
Total: 6960 W: 1454 L: 1247 D: 4259
Ptnml(0-2): 115, 739, 1610, 856, 160
https://tests.stockfishchess.org/tests/view/5f08221059f6f0353289477e

Passed LTC:
LLR: 2.98 (-2.94,2.94) {0.25,1.75}
Total: 21440 W: 2767 L: 2543 D: 16130
Ptnml(0-2): 122, 1904, 6462, 2092, 140
https://tests.stockfishchess.org/tests/view/5f0838ed59f6f035328947a2

various related tests show strong test results, but so far no generalizations or simplifications of conditional_more_than_two() are found. See PR for details.

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

Bench: 4366686
2020-07-11 11:23:55 +02:00
Vizvezdenec 5e91c5dcc8 Maximize usage of transposition table in probcut
Probcut is a heuristic that wasn't changed a lot in past years,
all attempts to change it using information / writing info to transposition table failed.

This patch has a number of differences that can be summarized as follows:

* For TT write/read we use depth - 3. Because probcut search is depth - 4 but we actually do the move prior to it so effectively we do depth - 3 search;
* In any case of depth of eval from transposition table being >= depth - 3 we either produce cutoff or refuse to even do probcut search, this is allowing us to write info of probcut to transposition table because we know that we wouldn't be overwriting some deeper data with our depth - 3 search - this is an important aspect of this patch;
* For some not really known reason this patch completely ignores tte->bound() - which was the case for previous patch that made probcut interact with TT, maybe 2) is the reason, although it's unproven.

A first version of this patch passed STC and LTC

passed STC
https://tests.stockfishchess.org/tests/view/5f05908a59f6f03532894613
LLR: 2.95 (-2.94,2.94) {-0.50,1.50}
Total: 95776 W: 18300 L: 17973 D: 59503
Ptnml(0-2): 1646, 10944, 22377, 11279, 1642

passed LTC
https://tests.stockfishchess.org/tests/view/5f06b54059f6f035328946bb
LLR: 2.94 (-2.94,2.94) {0.25,1.75}
Total: 57128 W: 7266 L: 6938 D: 42924
Ptnml(0-2): 372, 5163, 17217, 5389, 423

However, an additional bugfix was needed to avoid checking a condition on ttMove if was not available. This passed non-regression bounds on top of the first version:

at STC
https://tests.stockfishchess.org/tests/view/5f080e5059f6f03532894766
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 14096 W: 2800 L: 2628 D: 8668
Ptnml(0-2): 225, 1620, 3238, 1688, 277

at LTC
https://tests.stockfishchess.org/tests/view/5f0836a559f6f0353289479c
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 25352 W: 3228 L: 3139 D: 18985
Ptnml(0-2): 175, 2350, 7549, 2415, 187

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

Bench 4540940
2020-07-11 11:10:06 +02:00
Joost VandeVondele 4006f2c913 Small cleanups
closes https://github.com/official-stockfish/Stockfish/pull/2772

No functional change
2020-07-09 22:01:06 +02:00
mstembera bf5ce1c214 Simplify make_promotions()
Remove special case handling of QUIET_CHECKS in make_promotions()

STC https://tests.stockfishchess.org/tests/view/5f055dbb59f6f035328945fb
LLR: 2.98 (-2.94,2.94) {-1.50,0.50}
Total: 42808 W: 8177 L: 8054 D: 26577
Ptnml(0-2): 665, 4890, 10201, 4953, 695

LTC https://tests.stockfishchess.org/tests/view/5f06231a59f6f03532894661
LLR: 2.96 (-2.94,2.94) {-1.50,0.50}
Total: 9616 W: 1214 L: 1111 D: 7291
Ptnml(0-2): 53, 821, 2965, 908, 61

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

Bench: 4576410
2020-07-09 21:59:32 +02:00
FauziAkram 804a29c738 Connected / blocked pawns simplification
There is no need to score blocked pawns at many places.
The idea originated from: Rocky
Tuning and testing by: Fauzi

Passed STC:
https://tests.stockfishchess.org/tests/view/5f04f8fd59f6f035328945d4
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 6352 W: 1299 L: 1118 D: 3935
Ptnml(0-2): 89, 695, 1469, 792, 131

Passed LTC:
https://tests.stockfishchess.org/tests/view/5f0527bd59f6f035328945e3
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 27648 W: 3517 L: 3433 D: 20698
Ptnml(0-2): 177, 2561, 8301, 2571, 214

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

Bench: 4734746
2020-07-09 21:57:13 +02:00
Alain SAVARD 76a039027d Clean-up en passant processing
the goal of this PR is to better document how we process
the ep square (if any) given position fen command, and to
output more meaningful (and consistent) debug fen on the "d"
command. The implementation follows
https://en.wikipedia.org/wiki/X-FEN#Encoding_en-passant
following x-fen, it is "valid" to record ep even if ep would put king en prise.

fixes #2784

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

No functional change
2020-07-09 21:46:26 +02:00
Stefan Geschwentner 7225d254f9 Add a rank based bonus for blocked pawns.
Fix for overevaluated blocked pawns on the 5th and 6th rank.
This is a rewrite of the original idea that uses only two parameters.
Thanks to rocky640 for pointing this out.

STC:
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 50800 W: 9707 L: 9446 D: 31647
Ptnml(0-2): 831, 5851, 11822, 6018, 878
https://tests.stockfishchess.org/tests/view/5f00b4f359f6f03532894304

LTC:
LLR: 2.93 (-2.94,2.94) {0.25,1.75}
Total: 52064 W: 6477 L: 6167 D: 39420
Ptnml(0-2): 331, 4628, 15834, 4878, 361
https://tests.stockfishchess.org/tests/view/5f0115fe59f6f03532894345

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

Bench: 4882833
2020-07-06 17:56:18 +02:00
protonspring c5b2a92cd1 denormalize KRKP.
a non-functional code style change that denormalizes the KRKP endgame,
making it somewhat easier to read.

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

No functional change
2020-07-06 17:50:35 +02:00
SFisGOD 67818ee948 Remove passed pawn condition.
This will help scale down relatively high eval in drawish rook endgames with passed pawn like in TCEC S18 Superfinal Game 90.

Passed STC
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 50456 W: 9644 L: 9540 D: 31272
Ptnml(0-2): 760, 5637, 12332, 5737, 762
https://tests.stockfishchess.org/tests/view/5efcb76e59f6f035328940ed

Passed LTC
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 77264 W: 9518 L: 9518 D: 58228
Ptnml(0-2): 402, 6766, 24321, 6716, 427
https://tests.stockfishchess.org/tests/view/5efd2ad759f6f03532894143

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

Bench: 4431626
2020-07-03 21:09:22 +02:00
Joost VandeVondele fb83da0892 Set UCI_ShowWDL by default to false
UCI_ShowWDL might not be shown by GUIs that don't know the option,
but crash on the WDL output, effectively making it hard for users to
turn it off and run the engine. This sets it by default to false.

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

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

No functional change.
2020-07-03 21:07:17 +02:00
Alain SAVARD 268c00b648 Use arrays
for safe checks, outposts and king protectors in evaluate.cpp

Tested for non regression on the safe checks
https://tests.stockfishchess.org/tests/view/5ef8b75c020eec13834a9596
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 22256 W: 4283 L: 4143 D: 13830
Ptnml(0-2): 291, 2439, 5588, 2459, 351

Tested for non regression on the safe checks, outposts and king protectors
https://tests.stockfishchess.org/tests/view/5ef8e543020eec13834a95e7
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 28400 W: 5382 L: 5253 D: 17765
Ptnml(0-2): 394, 3078, 7119, 3223, 386

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

No functional change
2020-07-03 21:06:36 +02:00
Joost VandeVondele 110068808b Provide WDL statistics
A number of engines, GUIs and tournaments start to report WDL estimates
along or instead of scores. This patch enables reporting of those stats
in a more or less standard way (http://www.talkchess.com/forum3/viewtopic.php?t=72140)

The model this reporting uses is based on data derived from a few million fishtest LTC games,
given a score and a game ply, a win rate is provided that matches rather closely,
especially in the intermediate range [0.05, 0.95] that data. Some data is shown at
https://github.com/glinscott/fishtest/wiki/UsefulData#win-loss-draw-statistics-of-ltc-games-on-fishtest
Making the conversion game ply dependent is important for a good fit, and is in line
with experience that a +1 score in the early midgame is more likely a win than in the late endgame.

Even when enabled, the printing of the info causes no significant overhead.

Passed STC:
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 197112 W: 37226 L: 37347 D: 122539
Ptnml(0-2): 2591, 21025, 51464, 20866, 2610
https://tests.stockfishchess.org/tests/view/5ef79ef4f993893290cc146b

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

No functional change
2020-07-01 07:33:05 +02:00
Stefan Geschwentner 69d3be42a1 Tweak single queen endgame scaling.
Increase scaling factor for each minor of the opponent side of the queen.

STC:
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 14528 W: 2860 L: 2653 D: 9015
Ptnml(0-2): 217, 1632, 3408, 1741, 266
https://tests.stockfishchess.org/tests/view/5ef98384020eec13834a96a0

LTC:
LLR: 2.95 (-2.94,2.94) {0.25,1.75}
Total: 34584 W: 4371 L: 4111 D: 26102
Ptnml(0-2): 205, 3080, 10501, 3262, 244
https://tests.stockfishchess.org/tests/view/5ef99972020eec13834a96c9

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

Bench: 4523573
2020-06-29 20:02:58 +02:00
Stéphane Nicolet c7194bd924 Scale down eval for queen imbalance
We lower the endgame value of the evaluation when we detect that there
is only one queen left on the board (more precisely, we use a scale
factor of 37/64, or about 0.58, for the endgame part of the evaluation).
Hopefully this helps a little bit for the assessment of positions with
queen imbalance, which are one of the well-known Stockfish weaknesses.

STC:
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 21600 W: 4176 L: 3955 D: 13469
Ptnml(0-2): 351, 2457, 5003, 2598, 391
https://tests.stockfishchess.org/tests/view/5ef871b6020eec13834a94e8

LTC:
LLR: 2.97 (-2.94,2.94) {0.25,1.75}
Total: 248328 W: 30596 L: 29720 D: 188012
Ptnml(0-2): 1544, 22345, 75665, 22911, 1699
https://tests.stockfishchess.org/tests/view/5ef87aec020eec13834a94fe

Closes https://github.com/official-stockfish/Stockfish/pull/2781

Bench: 4441323
2020-06-28 22:42:43 +02:00
Stefan Geschwentner 16836f39b2 Scale down eval for drawish rook endgames.
STC:
LLR: 2.96 (-2.94,2.94) {-0.50,1.50}
Total: 82136 W: 15694 L: 15407 D: 51035
Ptnml(0-2): 1076, 8960, 20767, 9131, 1134
https://tests.stockfishchess.org/tests/view/5ef86cf8020eec13834a94dd

LTC:
LLR: 2.93 (-2.94,2.94) {0.25,1.75}
Total: 70200 W: 8787 L: 8440 D: 52973
Ptnml(0-2): 325, 5983, 22170, 6264, 358
https://tests.stockfishchess.org/tests/view/5ef88225020eec13834a950a

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

Bench: 4478869
2020-06-28 22:05:09 +02:00
Stéphane Nicolet 2810a1ea85 Increase value of pawns on fifth rank
This patch increases the endgame value of pawns on the fifth rank.
The increase is very small (+1 evaluation point, about 0.005 pawn)
for the pawns on external columns (a-b-c-f-g-h) and a bit bigger
(+7 evaluation points, about 0.033 pawn) for the pawns on d5/e5.

STC:
LLR: 2.93 (-2.94,2.94) {-0.50,1.50}
Total: 79864 W: 15331 L: 15027 D: 49506
Ptnml(0-2): 1336, 9284, 18433, 9498, 1381
https://tests.stockfishchess.org/tests/view/5ef73e2ef993893290cc0c47

LTC:
LLR: 2.94 (-2.94,2.94) {0.25,1.75}
Total: 47240 W: 5927 L: 5630 D: 35683
Ptnml(0-2): 320, 4133, 14440, 4384, 343
https://tests.stockfishchess.org/tests/view/5ef7c0c4f993893290cc14b7

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

Bench: 4794633
2020-06-28 22:03:10 +02:00
mstembera 547c4a216a Remove old zobrist trick for castling rights
Removes an 8 year old micro optimization aimed at 32-bit architectures
because back then doing an xor of a Key could not be done in one instruction.
See original commit here 821e1c7

STC https://tests.stockfishchess.org/tests/view/5ef5833dde213bf647527d0c
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 162648 W: 31053 L: 31097 D: 100498
Ptnml(0-2): 2841, 18966, 37715, 19000, 2802

LTC https://tests.stockfishchess.org/tests/view/5ef7b1bbf993893290cc1489
LLR: 2.93 (-2.94,2.94) {-1.50,0.50}
Total: 62360 W: 7617 L: 7586 D: 47157
Ptnml(0-2): 423, 5662, 18994, 5663, 438

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

bench: 4591425
2020-06-28 22:00:19 +02:00
mstembera de24fcebc8 Fix fragile code to use proper random 64 bit keys.
This fixes an old issue where we want to make a position unique but only
change a small number of bits in the key instead of all 64 of them randomly.
This is fragile and can lead to non uniqueness issues in the TT.

Key make_key(uint64_t seed) takes any integer and produces a unique random 64 bit key.
It is computationally efficient and is based on a congruential pseudo random number
generator using well tested constants by Donald Knuth
(see https://en.wikipedia.org/wiki/Linear_congruential_generator)

STC https://tests.stockfishchess.org/tests/view/5ef6c78f761b685b4c724bb6
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 154320 W: 29343 L: 29376 D: 95601
Ptnml(0-2): 2543, 18170, 35891, 17889, 2667

LTC https://tests.stockfishchess.org/tests/view/5ef7d1a9020eec13834a940e
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 53488 W: 6629 L: 6584 D: 40275
Ptnml(0-2): 372, 4878, 16183, 4955, 356

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

bench: 4626776
2020-06-28 21:57:37 +02:00
Joost VandeVondele ca41ee6632 Revert LTO for mingw on windows.
LTO with static linking is still only working with the latest versions of gcc,
causing problems for some devs.

on a modern mingw toolchain LTO optimizations can still be enabled as:

```
CXXFLAGS='-flto' make -j ARCH=x86-64-modern COMP=mingw profile-build
```

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

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

No functional change.
2020-06-27 10:22:27 +02:00
Niklas Fiekas aecfca2dc2 support popcnt on armv8
* Supports popcnt (thanks @daylen)
* bits = 64 is now the default

Tested with g++ (Ubuntu/Linaro 7.5.0-3ubuntu1~18.04) 7.5.0 on ThunderX CN8890,
yields about 9% speedup.

Also tested with clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final).

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

No functional change.
2020-06-27 10:19:29 +02:00
Niklas Fiekas a84e3ac287 Simplify use_time_management() and allow composing
like other `go` commands wtime/btime can now be composed.

`go depth 10 wtime 100`

will let the engine use standard time management but stop if depth 10 is reached.

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

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

No functional change
2020-06-27 10:06:05 +02:00
Joost VandeVondele ab5cd8340f Small cleanups
closes https://github.com/official-stockfish/Stockfish/pull/2756

No functional change
2020-06-24 22:20:04 +02:00
UnaiCorzo 11483fe6d9 Makefile: support lto on mingw, default to 64bits
Clean and organize uppercase and spaces

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

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

No functional change
2020-06-24 22:14:25 +02:00
Joost VandeVondele 208c53df0f Remove 'Minimum Thinking Time' UCI option.
the option was, since at least 2014, not correctly implemented,
ignoring all dynamic adjustments to optimum time in search.
Instead of fixing it, remove it, no need to expose an option that
will influence time management negatively.

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

No functional change.
2020-06-24 22:02:17 +02:00
Niklas Fiekas 527d832a6d Support ARCH=armv8 in Makefile (#2355)
Tested with bench run after compiling with

- g++ (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
- clang version 3.8.1-24

on ThunderX CN8890.

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

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

No functional change.
2020-06-24 21:59:57 +02:00
Vizvezdenec bbe9857684 Do less futility pruning for captures.
The idea of this patch is that if capture can be described as
"less valuable piece takes more valuable piece" it's not really correct
to add only piece value of captured piece to static evaluation
since there can be more threats in other places and opponent can't really
do much but recapture our capturing piece which leaves us space for
more captures thus winning more material and increasing static eval.

passed STC
https://tests.stockfishchess.org/tests/view/5ef0167b122d6514328d760f
LLR: 2.96 (-2.94,2.94) {-0.50,1.50}
Total: 24736 W: 4838 L: 4607 D: 15291
Ptnml(0-2): 438, 2812, 5648, 3021, 449

passed LTC
https://tests.stockfishchess.org/tests/view/5ef073bc122d6514328d7693
LLR: 2.93 (-2.94,2.94) {0.25,1.75}
Total: 46152 W: 5865 L: 5567 D: 34720
Ptnml(0-2): 312, 4160, 13886, 4354, 364

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

bench 4789930
2020-06-24 21:56:11 +02:00
FauziAkram e9966d9a8e Introduce bonus for queen infiltration
Idea is that queen feels much better when it can't be kicked away now
or later by pawn moves, especially in endgame. Special thanks to
Linmiao Xu for the original idea of this patch.

passed STC:
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 84008 W: 16271 L: 15958 D: 51779
Ptnml(0-2): 1476, 9688, 19420, 9887, 1533
https://tests.stockfishchess.org/tests/view/5eee7ca0447c5b640047a439

passed LTC:
LLR: 2.95 (-2.94,2.94) {0.25,1.75}
Total: 11720 W: 1522 L: 1328 D: 8870
Ptnml(0-2): 52, 1021, 3574, 1107, 106
https://tests.stockfishchess.org/tests/view/5eefc588122d6514328d75f9

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

Bench: 4471740
2020-06-22 12:47:14 +02:00
protonspring 8a3f155b1c Make endgames consistent
Changes variable names and occasionally consolidated variable declarations.
Piece squares are consistently prefixed with "weak" or "strong."

passed STC
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 29008 W: 5532 L: 5416 D: 18060
Ptnml(0-2): 355, 2983, 7723, 3077, 366
https://tests.stockfishchess.org/tests/view/5eea88d3563bc7aa75600689

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

No functional change
2020-06-21 15:39:00 +02:00
Joost VandeVondele 6f15e7fab2 small cleanups
closes https://github.com/official-stockfish/Stockfish/pull/2695

No functional change
2020-06-21 15:22:20 +02:00
Vizvezdenec bc3c215490 More reduction for evading pawn moves.
pawn moves are irreversable unlike other evading moves; pawn is the least valuable piece in the game.
So it makes a lot of sence to assume that evading pawn moves are on average not as good as other evading moves thus can be reduced more.

Passed STC
https://tests.stockfishchess.org/tests/view/5ee9602e563bc7aa756002dc
LLR: 2.95 (-2.94,2.94) {-0.50,1.50}
Total: 94176 W: 17993 L: 17668 D: 58515
Ptnml(0-2): 1634, 10742, 21989, 11111, 1612

Passed LTC
https://tests.stockfishchess.org/tests/view/5ee97342563bc7aa75600301
LLR: 2.94 (-2.94,2.94) {0.25,1.75}
Total: 20432 W: 2572 L: 2354 D: 15506
Ptnml(0-2): 146, 1707, 6280, 1949, 134

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

Bench: 5073064
2020-06-17 07:41:59 +02:00
Stéphane Nicolet 4c72c95359 Small bonus to favor thorn pawns
We increase a little bit the midgame value of pawns on a4, h4, a6 and h6.

Original idea by Malcolm Campbell, who tried the version restricted to the
pawns on the H column a couple of weeks ago and got a patch which almost
passed LTC. The current pull request just adds the same idea for pawns on
the A column.

Possible follow-ups: maybe tweak the a5/h5 pawn values, and/or add a malus
for very low king mobility in midgame?

STC:
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 33416 W: 6516 L: 6275 D: 20625
Ptnml(0-2): 575, 3847, 7659, 4016, 611
https://tests.stockfishchess.org/tests/view/5ee6c4e687586124bc2c10d4

LTC:
LLR: 2.95 (-2.94,2.94) {0.25,1.75}
Total: 134368 W: 16869 L: 16319 D: 101180
Ptnml(0-2): 908, 12083, 40708, 12521, 964
https://tests.stockfishchess.org/tests/view/5ee74e60aae8aec816ab756a

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

Bench: 5299456
2020-06-17 07:35:58 +02:00
mstembera 1ea488d34c Use 128 bit multiply for TT index
Remove super cluster stuff from TT and just use a 128 bit multiply.

STC https://tests.stockfishchess.org/tests/view/5ee719b3aae8aec816ab7548
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 12736 W: 2502 L: 2333 D: 7901
Ptnml(0-2): 191, 1452, 2944, 1559, 222

LTC https://tests.stockfishchess.org/tests/view/5ee732d1aae8aec816ab7556
LLR: 2.93 (-2.94,2.94) {-1.50,0.50}
Total: 27584 W: 3431 L: 3350 D: 20803
Ptnml(0-2): 173, 2500, 8400, 2511, 208

Scheme back to being derived from https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/

Also the default optimized version of the index calculation now uses fewer instructions.
https://godbolt.org/z/Tktxbv
Might benefit from mulx (requires -mbmi2)

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

bench: 4320954
2020-06-17 07:32:16 +02:00
xoto10 995ee4b311 Retuned values after eval quantize patch.
The last search tune patch was tested before the implementation of #2733 which
presumably changed the search characteristics noticeably. Another tuning run was
done, see https://tests.stockfishchess.org/tests/view/5ee5b434ca6c451633a9a08c
and the updated values passed these tests:

STC:
LLR: 2.93 (-2.94,2.94) {-0.50,1.50}
Total: 34352 W: 6600 L: 6360 D: 21392
Ptnml(0-2): 581, 3947, 7914, 4119, 615
https://tests.stockfishchess.org/tests/view/5ee62f05ca6c451633a9a15f

LTC 60+0.6 th 1 :
LLR: 2.97 (-2.94,2.94) {0.25,1.75}
Total: 11176 W: 1499 L: 1304 D: 8373
Ptnml(0-2): 69, 933, 3403, 1100, 83
https://tests.stockfishchess.org/tests/view/5ee6205bca6c451633a9a147

SMP LTC 20+0.2 th 8 :
LLR: 2.93 (-2.94,2.94) {0.25,1.75}
Total: 54032 W: 6126 L: 5826 D: 42080
Ptnml(0-2): 278, 4454, 17280, 4698, 306
https://tests.stockfishchess.org/tests/view/5ee62f25ca6c451633a9a162

Closes https://github.com/official-stockfish/Stockfish/pull/2742

Bench 4957812
2020-06-15 08:05:16 +02:00
xoto10 42b7dbcb5e Tuned values for search constants
Tuned search constants after many search patches since the last
successful tune.

1st LTC @ 60+0.6 th 1 :
LLR: 2.97 (-2.94,2.94) {0.25,1.75}
Total: 57656 W: 7369 L: 7036 D: 43251
Ptnml(0-2): 393, 5214, 17336, 5437, 448
https://tests.stockfishchess.org/tests/view/5ee1e074f29b40b0fc95af19

SMP LTC @ 20+0.2 th 8 :
LLR: 2.95 (-2.94,2.94) {0.25,1.75}
Total: 83576 W: 9731 L: 9341 D: 64504
Ptnml(0-2): 464, 7062, 26369, 7406, 487
https://tests.stockfishchess.org/tests/view/5ee35a21f29b40b0fc95b008

The changes were rebased on top of a successful patch by Viz (see #2734)
and two different ways of doing this were tested. The successful test
modified the constants in the patch by Viz in a similar manner to the
tuning run:

LTC (rebased) @ 60+0.6 th 1 :
LLR: 2.94 (-2.94,2.94) {0.25,1.75}
Total: 193384 W: 24241 L: 23521 D: 145622
Ptnml(0-2): 1309, 17497, 58472, 17993, 1421
https://tests.stockfishchess.org/tests/view/5ee43319ca6c451633a995f9

Further work: the recent patch to quantize eval #2733 affects search quit
quite a bit, so doing another tune in, say, three months time might be a
good idea.

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

Bench 4246971
2020-06-13 13:33:18 +02:00
Joost VandeVondele 4d657618e9 Quantize eval to multiples of 16
Removes some excess precision, helps searchs.

Effectively reintroduces evaluation grain, with a slightly different context.
https://github.com/official-stockfish/Stockfish/commit/45dbd9cd0303d0db469670af8ec3598731a4eace

passed STC
LLR: 2.97 (-2.94,2.94) {-0.50,1.50}
Total: 197032 W: 37938 L: 37462 D: 121632
Ptnml(0-2): 3359, 22994, 45446, 23246, 3471
https://tests.stockfishchess.org/tests/view/5ee0c228f29b40b0fc95ae53

passed LTC
LLR: 2.94 (-2.94,2.94) {0.25,1.75}
Total: 77696 W: 9970 L: 9581 D: 58145
Ptnml(0-2): 530, 7075, 23311, 7340, 592
https://tests.stockfishchess.org/tests/view/5ee21426f29b40b0fc95af43

passed LTC SMP
LLR: 2.96 (-2.94,2.94) {0.25,1.75}
Total: 64136 W: 7425 L: 7091 D: 49620
Ptnml(0-2): 345, 5416, 20228, 5718, 361
https://tests.stockfishchess.org/tests/view/5ee387bbf29b40b0fc95b04c

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

Bench: 4939103
2020-06-13 07:10:34 +02:00
Vizvezdenec c44c62efc2 Adjust history threshold for quiet moves futility pruning
This patch adjusts the threshold for futility pruning of quiet moves
using the continuation history array contHist[5], in the same way as
it is used in movepicker.

passed STC:
https://tests.stockfishchess.org/tests/view/5ee3f88bca6c451633a9959f
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 55984 W: 10822 L: 10552 D: 34610
Ptnml(0-2): 952, 6435, 12941, 6719, 945

passed LTC:
https://tests.stockfishchess.org/tests/view/5ee4186dca6c451633a995cf
LLR: 2.96 (-2.94,2.94) {0.25,1.75}
Total: 41712 W: 5402 L: 5114 D: 31196
Ptnml(0-2): 293, 3766, 12469, 4016, 312

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

Bench: 4715960
2020-06-13 06:48:58 +02:00
Stéphane Nicolet 3af083a7cd Improve the anti-shuffling policy
We replace the current decrease of the complexity term in initiative
when shuffling by a direct damping of the evaluation. This scheme may
have two benefits over the initiative approach:

a) the damping effect is more brutal for fortresses with heavy pieces
   on the board, because the initiative term is almost an endgame term;

b) the initiative implementation had a funny side effect, almost a bug,
   in the rare positions where mg > 0, eg < 0 and the tampered eval
   returned a positive value (ie with heavy pieces still on the board):
   sending eg to zero via shuffling would **increase** the tampered
   eval instead of decreasing it, which is somewhat illogical. This
   patch avoids this phenomenon.

STC:
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 43072 W: 8373 L: 8121 D: 26578
Ptnml(0-2): 729, 4954, 9940, 5162, 751
https://tests.stockfishchess.org/tests/view/5ee008ebf29b40b0fc95ade2

LTC:
LLR: 2.94 (-2.94,2.94) {0.25,1.75}
Total: 37376 W: 4816 L: 4543 D: 28017
Ptnml(0-2): 259, 3329, 11286, 3508, 306
https://tests.stockfishchess.org/tests/view/5ee03b06f29b40b0fc95ae0c

Closes https://github.com/official-stockfish/Stockfish/pull/2727

Bench: 4757174
2020-06-10 13:07:12 +02:00
Sami Kiminki 4b10578acb Increase the maximum hash size by a factor of 256
Conceptually group hash clusters into super clusters of 256 clusters.
This scheme allows us to use hash sizes up to 32 TB
(= 2^32 super clusters = 2^40 clusters).

Use 48 bits of the Zobrist key to choose the cluster index. We use 8
extra bits to mitigate the quantization error for very large hashes when
scaling the hash key to cluster index.

The hash index computation is organized to be compatible with the existing
scheme for power-of-two hash sizes up to 128 GB.

Fixes https://github.com/official-stockfish/Stockfish/issues/1349

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

Passed non-regression STC:
LLR: 2.93 (-2.94,2.94) {-1.50,0.50}
Total: 37976 W: 7336 L: 7211 D: 23429
Ptnml(0-2): 578, 4295, 9149, 4356, 610
https://tests.stockfishchess.org/tests/view/5edcbaaef29b40b0fc95abc5

No functional change.
2020-06-09 18:44:07 +02:00
nguyenpham b081e52239 Improve Readme.md about compiling
Reparagraph, add an example how to compile on Unix-like systems

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

No functional change
2020-06-09 18:31:56 +02:00
NguyenPham d0cb9b286f show coordinates when displaying board
closes https://github.com/official-stockfish/Stockfish/pull/2723

No functional change
2020-06-09 18:28:20 +02:00
protonspring 1c65310c0e Refactor some threads related code.
This is a code style change that moves some pure thread code into the threads class.

It is a bit more code, but it makes search.cpp cleaner and easier to read by hiding some thread specific functionality.

STC (SMP)
LLR: 2.93 (-2.94,2.94) {-1.50,0.50}
Total: 75896 W: 12073 L: 12026 D: 51797
Ptnml(0-2): 828, 8224, 19872, 8121, 903
https://tests.stockfishchess.org/tests/view/5ed492e8f29b40b0fc95a74c

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

No functional change.
2020-06-09 18:22:27 +02:00
protonspring b0eb5a1ba3 Wrap all access to LineBB and add assert
This is a non-functional code style change which provides a safe access handler for LineBB.
Also includes an assert in debug mode to verify square correctness.

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

No functional change
2020-06-09 18:13:24 +02:00
xoto10 902309020a join scale_factor, initiative and mg+eg reduction
Merging this code into one function `winnable()`.
Should allow common concepts used to adjust the eg value,
either by addition or scaling, to be combined more effectively.

Improve trace function.

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

No functional change.
2020-06-09 18:11:44 +02:00
pb00067 15e190e942 Use lowply-history also on low depths
STC:
https://tests.stockfishchess.org/tests/view/5ed75078f29b40b0fc95a8b9
LLR: 2.93 (-2.94,2.94) {-0.50,1.50}
Total: 73928 W: 14301 L: 14005 D: 45622
Ptnml(0-2): 1243, 8572, 17096, 8752, 1301

LTC:
https://tests.stockfishchess.org/tests/view/5ed895e0f29b40b0fc95a976
LLR: 2.93 (-2.94,2.94) {0.25,1.75}
Total: 154848 W: 19684 L: 19074 D: 116090
Ptnml(0-2): 1048, 14108, 46627, 14468, 1173

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

bench: 4582693
2020-06-06 16:18:42 +02:00
protonspring fd8e88427b small speed-up in movegen
pass color as a template parameter.

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

No functional change.
2020-06-06 16:03:19 +02:00
Moez Jellouli 784263596f Minimal thinking time, even if only one rootMove.
without search, the eval returned can be misleading (e.g. mate instead of draw),
leading to wrong adjudication. With a minimal search, this is avoided.
This patch leads to 1ms long searches if there is only 1 move,
similar patches all indicate a small Elo gain.

Fixes https://github.com/official-stockfish/Stockfish/issues/2707

Passed non-regression STC:
LLR: 2.93 (-2.94,2.94) {-1.50,0.50}
Total: 22312 W: 4350 L: 4204 D: 13758
Ptnml(0-2): 323, 2488, 5437, 2536, 372
https://tests.stockfishchess.org/tests/view/5ed562b0f29b40b0fc95a7d0

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

Bench: 4733799
2020-06-06 15:58:50 +02:00
Moez Jellouli 16566a8fcf Singular quiet LMR
If ttMove is a capture and had a singular extension, it is probably the best move.
No need to make a decrease of LMR on other moves.

STC
LLR: 2.96 (-2.94,2.94) {-0.50,1.50}
Total: 41968 W: 8170 L: 7918 D: 25880
Ptnml(0-2): 733, 4770, 9726, 5022, 733
https://tests.stockfishchess.org/tests/view/5ed6b666f29b40b0fc95a884

LTC
LLR: 2.95 (-2.94,2.94) {0.25,1.75}
Total: 71376 W: 9200 L: 8827 D: 53349
Ptnml(0-2): 486, 6544, 21342, 6743, 573
https://tests.stockfishchess.org/tests/view/5ed7578bf29b40b0fc95a8c9

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

Bench: 4733799
2020-06-04 19:03:54 +02:00
Stefan Geschwentner d1ec10cd4f Give bonus for bishops that are alligned with enemy kingring.
Inspired by the succesful patch "Give bonus for rooks that are alligned with enemy kingring" from Vizvezdenec,
this idea has been reused for bishops. Here, we only consider attacks that are not blocked by any pawn.
Also we have a 50% higher bonus than for the rooks.

STC:
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 68960 W: 13495 L: 13202 D: 42263
Ptnml(0-2): 1213, 8018, 15802, 8157, 1290
https://tests.stockfishchess.org/tests/view/5ed27495042fa6d77c3553aa

LTC:
LLR: 2.96 (-2.94,2.94) {0.25,1.75}
Total: 54560 W: 7105 L: 6780 D: 40675
Ptnml(0-2): 379, 4986, 16254, 5253, 408
https://tests.stockfishchess.org/tests/view/5ed30375596e6dc1e1f97425

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

Bench: 4860021
2020-06-01 17:35:02 +02:00
ElbertoOne 8c3d9d996a Isolated pawns tweak
Give opposed doubled isolated pawns only the Doubled penalty.
The other isolated pawns get the Isolated penalty and the WeakUnopposed penalty.
The popcount condition has been replaced with an opposed check,
which is non-functional, but probably gives a speed-up.

Passed STC (https://tests.stockfishchess.org/tests/view/5ed0f0f0042fa6d77c3552f5):
LLR: 2.96 (-2.94,2.94) {-0.50,1.50}
Total: 121832 W: 23562 L: 23195 D: 75075
Ptnml(0-2): 2092, 14064, 28313, 14279, 2168

LTC: (https://tests.stockfishchess.org/tests/view/5ed22e40042fa6d77c355387)
LLR: 2.96 (-2.94,2.94) {0.25,1.75}
Total: 103368 W: 13232 L: 12768 D: 77368
Ptnml(0-2): 693, 9484, 30919, 9842, 746

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

Bench: 4085694
2020-06-01 17:27:29 +02:00
Joost VandeVondele 616eb60008 Less pruning in draw PV lines.
no futility pruning for certain captures if the PvNode has a draw eval.

passed STC:
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 59392 W: 11576 L: 11302 D: 36514
Ptnml(0-2): 977, 6816, 13920, 6922, 1061
https://tests.stockfishchess.org/tests/view/5ed0b1bb042fa6d77c355295

passed LTC:
LLR: 2.94 (-2.94,2.94) {0.25,1.75}
Total: 64040 W: 8273 L: 7923 D: 47844
Ptnml(0-2): 424, 5842, 19220, 6028, 506
https://tests.stockfishchess.org/tests/view/5ed145e0042fa6d77c35531c

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

Bench: 4704615
2020-05-30 20:32:52 +02:00
protonspring a5e3b4edde Consolidate all attacks bitboards
This is a non-functional simplification that simplifies getting attacks bitboards.

* consolidates all attacks to attacks_bb (remove Position::attacks_from(..)).
* attacks_bb<PieceType>(square) gets pseudo attacks
* attacks_bb<PieceType>(square, bitboard) gets attacks considering occupied squares in the bitboard).
* pawn_attacks_bb(Color, Square) gets pawn attacks like other pawn attack bitboards.
* Wraps all access to PawnAttacks arrays and PseudoAttacks arrays and adds asserts as appropriate.

Passed STC
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 90208 W: 17533 L: 17482 D: 55193
Ptnml(0-2): 1412, 10232, 21798, 10217, 1445
https://tests.stockfishchess.org/tests/view/5ece996275787cc0c05d9790

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

No functional change
2020-05-30 20:30:31 +02:00
xoto10 fb8095718b In BlockedStorm, theirPawns includes ones attacked by us.
Pawns heading towards our king tend to be dangerous whether or not we are attacking them so remove this test.

STC:
LLR: 2.93 (-2.94,2.94) {-1.50,0.50}
Total: 91184 W: 18196 L: 18137 D: 54851
Ptnml(0-2): 1580, 10656, 21092, 10653, 1611
https://tests.stockfishchess.org/tests/view/5ecc3f7080f2c838b9655841

LTC:
LLR: 2.93 (-2.94,2.94) {-1.50,0.50}
Total: 14152 W: 2045 L: 1937 D: 10170
Ptnml(0-2): 99, 1325, 4130, 1413, 109
https://tests.stockfishchess.org/tests/view/5ecc4f3180f2c838b9655861

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

Bench 4828973
2020-05-26 07:11:59 +02:00
Vizvezdenec d40d04c17c Give bonus for rooks that are alligned with enemy kingring
The idea of this patch is that if rooks are not directly attacking the opponent king,
they can support king attacks staying behind pawns or minor pieces and be really
deadly if position slightly opens up at enemy king ring ranks. Loosely based on
some stockfish games where it underestimated attacks on it king when enemy has one
or two rooks supporting pawn pushes towards it king.

passed STC
https://tests.stockfishchess.org/tests/view/5ecb093680f2c838b96550f9
LLR: 2.93 (-2.94,2.94) {-0.50,1.50}
Total: 53672 W: 10535 L: 10265 D: 32872
Ptnml(0-2): 952, 6210, 12258, 6448, 968

passed LTC
https://tests.stockfishchess.org/tests/view/5ecb639f80f2c838b9655117
LLR: 2.94 (-2.94,2.94) {0.25,1.75}
Total: 62424 W: 8094 L: 7748 D: 46582
Ptnml(0-2): 426, 5734, 18565, 6042, 445

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

Bench: 4663220
2020-05-25 22:18:56 +02:00
Moez Jellouli 7f2c8a2b81 Remove attacked pawns from storm evaluation
STC:
LLR: 2.96 (-2.94,2.94) {-0.50,1.50}
Total: 54456 W: 11009 L: 10737 D: 32710
Ptnml(0-2): 929, 6326, 12523, 6444, 1006
https://tests.stockfishchess.org/tests/view/5ec962e4404591b2793008a5

LTC:
LLR: 2.94 (-2.94,2.94) {0.25,1.75}
Total: 62448 W: 9018 L: 8664 D: 44766
Ptnml(0-2): 462, 5928, 18121, 6220, 493
https://tests.stockfishchess.org/tests/view/5ec976a8a586eee45aa2ab40

Non regression STC with "noob_3moves.epd" opening book
LLR: 3.81 (-2.94,2.94) {-1.50,0.50}
Total: 91896 W: 17770 L: 17653 D: 56473
Ptnml(0-2): 1598, 10782, 21124, 10793, 1651
https://tests.stockfishchess.org/tests/view/5ec9b83ea586eee45aa2ab96

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

Bench 4488597
2020-05-25 22:15:13 +02:00
ElbertoOne 81c58855e4 Remove and replace DoubledIsolated penalty by Doubled
The values for both penalties were very close, so DoubledIsolated can be removed and replaced by Doubled.

Passed STC (simplification): https://tests.stockfishchess.org/tests/view/5ec7c18e2a585b485af54407
LLR: 2.97 (-2.94,2.94) {-1.50,0.50}
Total: 105360 W: 20175 L: 20136 D: 65049
Ptnml(0-2): 1803, 12230, 24572, 12275, 1800

Passed LTC:
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 15440 W: 1978 L: 1877 D: 11585
Ptnml(0-2): 92, 1405, 4667, 1422, 134

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

Bench: 4668875
2020-05-23 22:10:14 +02:00
FauziAkram 86575bcdd8 Queen Mobility Tweak
It's ok to have low mobility values for the Queen in the middlegame, but it's absolutely not ok to have low mobility values for the Queen in the endgame.
Decrease penalty for bad mobility in MG and increase it in EG.

STC:
LLR: 2.93 (-2.94,2.94) {-0.50,1.50}
Total: 17264 W: 3424 L: 3206 D: 10634
Ptnml(0-2): 279, 2004, 3893, 2132, 324
https://tests.stockfishchess.org/tests/view/5ec8f9c1526edcbe9091eba1

LTC:
LLR: 2.94 (-2.94,2.94) {0.25,1.75}
Total: 175016 W: 22071 L: 21404 D: 131541
Ptnml(0-2): 1195, 15796, 52914, 16353, 1250
https://tests.stockfishchess.org/tests/view/5ec9057c404591b2793007df

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

Bench: 4487054
2020-05-23 22:06:26 +02:00
Joost VandeVondele 383b12e1a5 small cleanups
closes https://github.com/official-stockfish/Stockfish/pull/2653

No functional change
2020-05-23 13:27:16 +02:00
xoto10 d940e59dad Keep low ply history from previous move
This patch keeps the low-ply history from the previous move, shifting the data down by 2 ply.

Tested with closedpos book:

STC:
LLR: 2.93 (-2.94,2.94) {-0.50,1.50}
Total: 71584 W: 14175 L: 13891 D: 43518
Ptnml(0-2): 1069, 8228, 16993, 8354, 1148
https://tests.stockfishchess.org/tests/view/5ec0eaafe9d85f94dc429974

LTC:
LLR: 2.94 (-2.94,2.94) {0.25,1.75}
Total: 96552 W: 13946 L: 13498 D: 69108
Ptnml(0-2): 676, 9082, 28375, 9404, 739
https://tests.stockfishchess.org/tests/view/5ec145efe9d85f94dc4299b0

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

Bench 5148950
2020-05-23 13:19:26 +02:00
Joost VandeVondele 669b5d83ef Improve CI testing
also enable CXXFLAGS="-D_GLIBCXX_DEBUG" in CI.

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

No functional change.
2020-05-23 13:14:09 +02:00
Stefan Geschwentner cdf5cfdb92 Add doubled isolated pawn penalty.
This patch gives an additional penalty if a doubled isolated pawn is stopped
only by a single opponent pawn on the same file. Thanks to NKONSTANTAKIS,
who shared this idea on the forum!

https://groups.google.com/forum/?fromgroups=#!topic/fishcooking/vC4Qn-PMlS4.

STC:
LLR: 2.96 (-2.94,2.94) {-0.50,1.50}
Total: 84872 W: 16688 L: 16370 D: 51814
Ptnml(0-2): 1507, 9940, 19274, 10158, 1557
https://tests.stockfishchess.org/tests/view/5ec65bd955202b947dc5d4ac

LTC:
LLR: 2.93 (-2.94,2.94) {0.25,1.75}
Total: 58104 W: 7614 L: 7278 D: 43212
Ptnml(0-2): 411, 5369, 17196, 5625, 451
https://tests.stockfishchess.org/tests/view/5ec6e9f2c23f5b0710632b19

Closes https://github.com/official-stockfish/Stockfish/pull/2694

Bench: 5148950
2020-05-22 20:40:24 +02:00
Stefan Geschwentner 09c6917d05 Tweak knight mobility
New tuned values for knight mobility in endgames.

STC:
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 112576 W: 21999 L: 21644 D: 68933
Ptnml(0-2): 2009, 13084, 25735, 13463, 1997
https://tests.stockfishchess.org/tests/view/5ec58379377121ac09e10272

LTC:
LLR: 2.95 (-2.94,2.94) {0.25,1.75}
Total: 125192 W: 16200 L: 15671 D: 93321
Ptnml(0-2): 891, 11584, 37182, 11983, 956
https://tests.stockfishchess.org/tests/view/5ec5c0b8377121ac09e1028b

Closes https://github.com/official-stockfish/Stockfish/pull/2693

Bench: 4778956
2020-05-21 14:11:14 +02:00
Stéphane Nicolet 6c1af710d1 A combo of parameters tweaks
This patch is a combinaison of two recent parameters tweaks which had
failed narrowly (yellow) at long time control:

• improvement in move ordering during search by softening the distinction
  between bad captures and good captures during move generation, leading
  to improved awareness of Stockfish of potential piece sacrifices (idea
  by Rahul Dsilva)
• increase in the weight of pawns in the "initiative" part of the evaluation
  function. With this change Stockfish should have more incentive to exchange
  pawns when losing, and to keep pawns when winning.

STC:
LLR: 2.93 (-2.94,2.94) {-0.50,1.50}
Total: 10704 W: 2178 L: 1974 D: 6552
Ptnml(0-2): 168, 1185, 2464, 1345, 190
https://tests.stockfishchess.org/tests/view/5ec5553b377121ac09e1023d

LTC:
LLR: 2.94 (-2.94,2.94) {0.25,1.75}
Total: 60592 W: 7835 L: 7494 D: 45263
Ptnml(0-2): 430, 5514, 18086, 5817, 449
https://tests.stockfishchess.org/tests/view/5ec55ca2377121ac09e10249

Closes https://github.com/official-stockfish/Stockfish/pull/2691

Bench: 4519117
2020-05-21 14:05:07 +02:00
protonspring 20ceeac8b3 Simplify evaluation for blocked passers.
This is a functional simplification of the evaluation code for blocked passers.
I've also changed a few variable names for clarity.

STC
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 141984 W: 27450 L: 27466 D: 87068
Ptnml(0-2): 2414, 16511, 33175, 16461, 2431
https://tests.stockfishchess.org/tests/view/5ec4001b05aa4bc72d9759e7

LTC
LLR: 2.93 (-2.94,2.94) {-1.50,0.50}
Total: 30536 W: 3966 L: 3885 D: 22685
Ptnml(0-2): 216, 2841, 9073, 2922, 216
https://tests.stockfishchess.org/tests/view/5ec4bd0d377121ac09e101b7

Closes https://github.com/official-stockfish/Stockfish/pull/2690

Bench: 4704681
2020-05-21 13:57:50 +02:00
Sami Kiminki b36a1fa1b4 Avoid sending info strings before 'uci' has been received
Do not send the following info string on the first call to
aligned_ttmem_alloc() on Windows:

  info string Hash table allocation: Windows large pages [not] used.

The first call occurs before the 'uci' command has been received. This
confuses some GUIs, which expect the first engine-sent command to be
'id' as the response to the 'uci' command. (see https://github.com/official-stockfish/Stockfish/issues/2681)

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

No functional change.
2020-05-19 17:02:21 +02:00
xoto10 dd1adce748 Increase base time use and limit max used.
This change increases the base part of optimumTime at all depths. It also reduces the size of max_scale and thus maximumTime by using a linear scale instead of pow(x, 0.3) and by limiting max_scale to no more than 7 (previously as high as 8 or 9 at very high depths).

Tested using the closedpos book:

STC 10+0.1:
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 83696 W: 16813 L: 16508 D: 50375
Ptnml(0-2): 1315, 9649, 19686, 9812, 1386
https://tests.stockfishchess.org/tests/view/5ebfa92de9d85f94dc42989b

LTC 60+0.6:
LLR: 2.95 (-2.94,2.94) {0.25,1.75}
Total: 39384 W: 5868 L: 5582 D: 27934
Ptnml(0-2): 276, 3697, 11489, 3925, 305
https://tests.stockfishchess.org/tests/view/5ec0a6dce9d85f94dc42995a

Test for non-regression:

STC Sudden Death 10+0 :
LLR: 2.94 (-2.94,2.94) {-2.00,0.00}
Total: 111976 W: 25661 L: 25768 D: 60547
Ptnml(0-2): 2567, 13420, 24118, 13319, 2564
https://tests.stockfishchess.org/tests/view/5ec23b3be9d85f94dc429a58

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

Bench 4395562
2020-05-19 16:53:47 +02:00
protonspring 83c9e5911e Don't adjust MoveOverhead by increment
This is a change to address a potential timing issue for slow networks.

Move Overhead was limited by TC increment,
which might be problematic if small increments (or sudden death)
on slow networks (needing high Move Overhead) are used.

STC, sudden death.
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 169368 W: 38023 L: 38054 D: 93291
Ptnml(0-2): 3767, 20250, 36595, 20391, 3681
https://tests.stockfishchess.org/tests/view/5ebf25efe9d85f94dc42986f

STC, 10+0.1
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 83896 W: 16092 L: 16026 D: 51778
Ptnml(0-2): 1401, 9697, 19670, 9795, 1385
https://tests.stockfishchess.org/tests/view/5ec0239de9d85f94dc42991e

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

No functional change.
2020-05-17 10:10:28 +02:00
Joost VandeVondele d116e27f0f Workaround for older compiler
gcc < 5 doesn't fully support the c++11 `std::is_trivially_copyable<Entry>::value`
Remove it, as it is not essential.

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

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

No functional change.
2020-05-15 19:40:25 +02:00
protonspring c6ce612f0a Simplify Time Management
This is a functional simplification of the time management system.

With this patch, there is a simple equation for each of two distinct
time controls: basetime + increment, and x moves in y seconds (+increment).
These equations are easy to plot and understand making future modifications
or adding additional time controls much easier.

SlowMover is reset to 100 so that is has no effect unless a user changes it.

There are two scaling variables:
* Opt_scale is a scale factor (or percentage) of time to use for this current move.
* Max_scale is a scale factor to apply to the resulting optimumTime.

There seems to be some elo gain in most scenarios.
Better performance is attributable to one of two things:
* minThinkingTime was not allowing reasonable time calculations for very short games like 10+0 or 10+0.01. This is because adding almost no increment and substracting move overhead for 50 moves quickly results in almost 0 time very early in the game. Master depended on minThinkingTime to handle these short games instead of good time management. This patch addresses this issue by lowering minThinkingTime to 0 and adjusting moverOverhead if there are very low increments.
* Notice that the time distribution curves tail downward for the first 10 moves or so. This causes less time to attribute for very early moves leaving more time available for middle moves where more important decisions happen.

Here is a summary of tests for this version at different time controls:

SMP 5+0.05
LLR: 2.97 (-2.94,2.94) {-1.50,0.50}
Total: 46544 W: 7175 L: 7089 D: 32280
Ptnml(0-2): 508, 4826, 12517, 4914, 507
https://tests.stockfishchess.org/tests/user/protonspring

STC
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 20480 W: 3872 L: 3718 D: 12890
Ptnml(0-2): 295, 2364, 4824, 2406, 351
https://tests.stockfishchess.org/tests/view/5ebc343e7dd5693aad4e6873

STC, sudden death
LLR: 2.93 (-2.94,2.94) {-1.50,0.50}
Total: 7024 W: 1706 L: 1489 D: 3829
Ptnml(0-2): 149, 813, 1417, 938, 195
https://tests.stockfishchess.org/tests/view/5ebc346f7dd5693aad4e6875

STC, TCEC style
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 4192 W: 1014 L: 811 D: 2367
Ptnml(0-2): 66, 446, 912, 563, 109
https://tests.stockfishchess.org/tests/view/5ebc34857dd5693aad4e6877

40/10
LLR: 2.93 (-2.94,2.94) {-1.50,0.50}
Total: 54032 W: 10592 L: 10480 D: 32960
Ptnml(0-2): 967, 6148, 12677, 6254, 970
https://tests.stockfishchess.org/tests/view/5ebc50597dd5693aad4e688d

LTC, sudden death
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 9152 W: 1391 L: 1263 D: 6498
Ptnml(0-2): 75, 888, 2526, 1008, 79
https://tests.stockfishchess.org/tests/view/5ebc6f5c7dd5693aad4e689b

LTC
LLR: 2.98 (-2.94,2.94) {-1.50,0.50}
Total: 12344 W: 1563 L: 1459 D: 9322
Ptnml(0-2): 70, 1103, 3740, 1171, 88
https://tests.stockfishchess.org/tests/view/5ebc6f4c7dd5693aad4e6899

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

Bench: 4395562
2020-05-14 20:47:59 +02:00
Sami Kiminki beb327f910 Fix a Windows-only crash on exit without 'quit'
There was a bug in commit d4763424d2
(Add support for Windows large pages) that could result in trying to
free memory allocated with VirtualAlloc incorrectly with free().

Fix this by reverting the TT.resize(0) logic in the previous commit,
and instead, just call aligned_ttmem_free() in
TranspositionTable::~TranspositionTable().

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

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

No functional change
2020-05-14 20:35:40 +02:00
Stéphane Nicolet cca643669d Move 50 moves counter to initiative.
simplify the usage of the 50 moves counter,
moving it frome the scale factor to initiative.

This patch was inspired by recent games where a blocked or semi-blocked position
was 'blundered', by moving a pawn, into a lost endgame. This patch improves this situation,
finding a more robust move more often.

for example (1s searches with many threads):
```
FEN 8/p3kp2/Pp2p3/1n2PpP1/5P2/1Kp5/8/R7 b - - 68 143

master:
      6 bestmove b5c7
      6 bestmove e7e8
     12 bestmove e7d8
    176 bestmove e7d7
patch:
      3 bestmove b5c7
      5 bestmove e7d8
    192 bestmove e7d7
```

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

the patch also tests well

passed STC
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 50168 W: 9508 L: 9392 D: 31268
Ptnml(0-2): 818, 5873, 11616, 5929, 848
https://tests.stockfishchess.org/tests/view/5ebb07287dd5693aad4e680b

passed LTC
LLR: 2.93 (-2.94,2.94) {-1.50,0.50}
Total: 7520 W: 981 L: 870 D: 5669
Ptnml(0-2): 49, 647, 2256, 760, 48
https://tests.stockfishchess.org/tests/view/5ebbff747dd5693aad4e6858

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

Bench: 4395562
2020-05-14 20:34:15 +02:00
Sami Kiminki d4763424d2 Add support for Windows large pages
for users that set the needed privilige "Lock Pages in Memory"
large pages will be automatically enabled (see Readme.md).

This expert setting might improve speed, 5% - 30%, depending
on the hardware, the number of threads and hash size. More for
large hashes, large number of threads and NUMA. If the operating
system can not allocate large pages (easier after a reboot), default
allocation is used automatically. The engine log provides details.

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

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

No functional change
2020-05-13 20:57:47 +02:00
Tomasz Sobczyk 86ee4eb84d Use a trivially copyable struct for TBTables::Entry instead of a tuple.
fixes https://github.com/official-stockfish/Stockfish/issues/2673
which is a warning issued by recent gcc (10.1)

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

No functional change
2020-05-13 19:50:30 +02:00
Moez Jellouli 66ed8b6c47 Tune pawn value
Small tune of PawnValue parameters -4 / -7 with "closedpos.epd" opening book.

STC:
LLR: 2.96 (-2.94,2.94) {-0.50,1.50}
Total: 58776 W: 11787 L: 11511 D: 35478
Ptnml(0-2): 975, 6876, 13443, 7086, 1008
https://tests.stockfishchess.org/tests/view/5eb5aa712326444a3b6d3e33

LTC:
LLR: 2.98 (-2.94,2.94) {0.25,1.75}
Total: 137544 W: 19687 L: 19115 D: 98742
Ptnml(0-2): 988, 13219, 39901, 13561, 1103
https://tests.stockfishchess.org/tests/view/5eb67a392326444a3b6d3e9a

Non regression STC with "noob_3moves.epd" opening book
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 98168 W: 18545 L: 18499 D: 61124
Ptnml(0-2): 1647, 11396, 22951, 11444, 1646
https://tests.stockfishchess.org/tests/view/5eb7e489e0300e8e8c896203

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

Bench 4696646
2020-05-11 20:46:39 +02:00
Joost VandeVondele 8a1de2655c Use posix_memalign instead of aligned_alloc
should be a little more portable to older linux systems (before glibc-2.16).

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

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

No functional change.
2020-05-11 20:41:49 +02:00
xoto10 fcaf0736fe Fix syzygy dependencies issue
fixes https://github.com/official-stockfish/Stockfish/issues/2660

The problem was caused by .depend being created with a rule for tbprobe.o not for syzygy/tbprobe.o.
This patch keeps an explicit list of sources (SRCS), generates OBJS,
and compiles all object files to the src/ directory, consistent with .depend.
VPATH is used to search the syzygy directory as needed.

joint work with @gvreuls

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

No functional change
2020-05-09 09:39:52 +02:00
xoto10 a91cb9fc1b Penalty for all enemy pawns xrayed by our bishop.
STC:
LLR: 2.93 (-2.94,2.94) {-0.50,1.50}
Total: 159760 W: 30229 L: 29813 D: 99718
Ptnml(0-2): 2659, 18309, 37534, 18713, 2665
https://tests.stockfishchess.org/tests/view/5eb1d5032326444a3b6d33ce

LTC:
LLR: 2.93 (-2.94,2.94) {0.25,1.75}
Total: 26496 W: 3908 L: 3656 D: 18932
Ptnml(0-2): 192, 2512, 7610, 2720, 214
https://tests.stockfishchess.org/tests/view/5eb1e2dd2326444a3b6d33f9

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

Bench 5185517
2020-05-06 16:20:01 +02:00
Marco Costalba c527c3ad44 Fishtest Tuning Framework
The purpose of the code is to allow developers to easily and flexibly
setup SF for a tuning session. Mainly you have just to remove 'const'
qualifiers from the variables you want to tune and flag them for
tuning, so if you have:

int myKing = 10;
Score myBonus = S(5, 15);
Value myValue[][2] = { { V(100), V(20) }, { V(7), V(78) } };

and at the end of the update you may want to call
a post update function:

void my_post_update();

If instead of default Option's min-max values,
you prefer your custom ones, returned by:

std::pair<int, int> my_range(int value)

Or you jus want to set the range directly, you can
simply add below:

TUNE(SetRange(my_range), myKing, SetRange(-200, 200), myBonus, myValue, my_post_update);

And all the magic happens :-)

At startup all the parameters are printed in a
format suitable to be copy-pasted in fishtest.

In case the post update function is slow and you have many
parameters to tune, 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.
The last option is the one defined and created as the last one, so
this assumes that the GUI sends the options in the same order in
which have been defined.

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

No functional change.
2020-05-02 17:32:11 +02:00
Vizvezdenec eb4a124b88 Refine scale factor of opposite colored bishops endgames.
This patch makes it dependant on the count of passed pawns of
the strong side instead of 22/64 in every case.

passed STC
https://tests.stockfishchess.org/tests/view/5ead60966ffeed51f6e32591
LLR: 2.96 (-2.94,2.94) {-0.50,1.50}
Total: 50336 W: 9473 L: 9241 D: 31622
Ptnml(0-2): 570, 5371, 13098, 5515, 614

passed LTC
https://tests.stockfishchess.org/tests/view/5ead6d3b6ffeed51f6e325b0
LLR: 2.94 (-2.94,2.94) {0.25,1.75}
Total: 21952 W: 2810 L: 2603 D: 16539
Ptnml(0-2): 101, 1791, 7005, 1958, 121

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

bench 4247490
2020-05-02 17:30:22 +02:00
Linmiao Xu 7f8166db89 Tuned safe checks and minor piece king protectors
A combination of terms related to king safety one tuned safe check weights,
the other tuned knight and bishop king protector weights separately with
some compensation in the high outpost bonuses given to the minor pieces.

passed STC
LLR: 2.95 (-2.94,2.94) {-0.50,1.50}
Total: 39892 W: 7594 L: 7350 D: 24948
Ptnml(0-2): 643, 4559, 9314, 4771, 659
https://tests.stockfishchess.org/tests/view/5ea49635b908f6dd28f34b82

passed LTC
LLR: 2.94 (-2.94,2.94) {0.25,1.75}
Total: 104934 W: 13300 L: 12834 D: 78800
Ptnml(0-2): 697, 9571, 31514, 9939, 746
https://tests.stockfishchess.org/tests/view/5ea4abf6b908f6dd28f34bcb

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

Bench 4800754
2020-05-02 17:26:51 +02:00
Joost VandeVondele 353e20674b Small cleanups
closes https://github.com/official-stockfish/Stockfish/pull/2628

No functional change
2020-04-29 17:44:24 +02:00
Vizvezdenec 4776dc0e12 Introduce futility pruning for captures
The idea is somewhat similar to futility pruning for quiet moves -
if a late enough capture doesn't give check and the static eval is
much lower than alpha we can almost safely assume that this capture
wouldn't be a good move.

passed STC
https://tests.stockfishchess.org/tests/view/5ea8544b53a4548a0348ee5b
LLR: 2.95 (-2.94,2.94) {-0.50,1.50}
Total: 236040 W: 44420 L: 43894 D: 147726
Ptnml(0-2): 3830, 27202, 55496, 27596, 3896

passed LTC
https://tests.stockfishchess.org/tests/view/5ea87c842141237a731f0c7d
LLR: 2.95 (-2.94,2.94) {0.25,1.75}
Total: 81336 W: 10429 L: 10028 D: 60879
Ptnml(0-2): 589, 7356, 24404, 7703, 616

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

bench 4405247
2020-04-29 17:35:48 +02:00
pb00067 bb5589b829 continuation histories when in check
If in check, don't write to continuation histories ss-4, ss-6.
Adding inCheck to the stack was needed, and might be useful for
future patches.

Passed STC:
https://tests.stockfishchess.org/tests/view/5e9ee24acaaff5d60a50b812
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 61774 W: 11725 L: 11449 D: 38600
Ptnml(0-2): 971, 7211, 14322, 7337, 1046

Passed LTC:
https://tests.stockfishchess.org/tests/view/5e9eecb7caaff5d60a50b831
LLR: 2.94 (-2.94,2.94) {0.25,1.75}
Total: 250822 W: 32067 L: 31179 D: 187576
Ptnml(0-2): 1745, 23126, 74824, 23928, 1788

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

bench: 4808463
2020-04-22 08:48:01 +02:00
Vizvezdenec 221893bf67 Apply multicut pruning more often
This patch increases number of nodes where we produce multicut cutoffs.

The idea is that if our ttMove failed to produce a singular extension
but ttValue is greater than beta we can afford to do one more reduced search
near beta excluding ttMove to see if it will produce a fail high -
and if it does so produce muticut by analogy to existing logic.

passed STC
https://tests.stockfishchess.org/tests/view/5e9a162b5b664cdba0ce6e28
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 58238 W: 11192 L: 10917 D: 36129
Ptnml(0-2): 1007, 6704, 13442, 6939, 1027

passed LTC
https://tests.stockfishchess.org/tests/view/5e9a1e845b664cdba0ce7411
LLR: 2.94 (-2.94,2.94) {0.25,1.75}
Total: 137852 W: 17460 L: 16899 D: 103493
Ptnml(0-2): 916, 12610, 41383, 13031, 986

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

bench 4881443
2020-04-18 15:36:41 +02:00
protonspring bde1506ba5 Simplify minPawnDistance
This is a functional simplification which fixes an awkward numerical cliff.

With master king_safety, no pawns is scored higher than pawn(s) that is/are far from the king. This may motivate SF to throw away pawns to increase king safety. With this patch, there is a consistent value for minPawnDistance where losing a pawn never increases king safety.

STC
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 45548 W: 8624 L: 8525 D: 28399
Ptnml(0-2): 592, 4937, 11587, 5096, 562
https://tests.stockfishchess.org/tests/view/5e98ced630be947a14e9ddc5

LTC
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 42084 W: 5292 L: 5242 D: 31550
Ptnml(0-2): 193, 3703, 13252, 3649, 245
https://tests.stockfishchess.org/tests/view/5e98e22e30be947a14e9de07

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

bench 4600292
2020-04-18 15:29:24 +02:00
Joost VandeVondele 345b2d153a Remove one condition in probcut TTmove skipping
the removed condition appears illogical and is not needed.

passed STC:
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 80418 W: 15217 L: 15144 D: 50057
Ptnml(0-2): 1341, 9399, 18679, 9426, 1364
https://tests.stockfishchess.org/tests/view/5e977eb5c9ada107a0370d6b

passed LTC:
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 49878 W: 6299 L: 6247 D: 37332
Ptnml(0-2): 327, 4677, 14897, 4693, 345
https://tests.stockfishchess.org/tests/view/5e97e07dc9ada107a0370e53

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

Bench: 4958027
2020-04-16 21:44:52 +02:00
xoto10 ecac132bca Scale factor in opposite-color bishop endings
This change varies the scale factor with the total number of pieces and pawns on the strongSide.

STC :
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 150920 W: 28828 L: 28422 D: 93670 +0.65 Elo
Ptnml(0-2): 2507, 17548, 35030, 17782, 2593
https://tests.stockfishchess.org/tests/view/5e983eb2c00499c5410f4951

LTC :
LLR: 2.95 (-2.94,2.94) {0.25,1.75}
Total: 69238 W: 8810 L: 8446 D: 51982 +1.58 Elo
Ptnml(0-2): 451, 6276, 20879, 6484, 529
https://tests.stockfishchess.org/tests/view/5e985b27c00499c5410f4987

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

Bench 4821332
2020-04-16 21:40:06 +02:00
Lolligerhans 6f35af7ad3 Increase safe check bonus if multiple safe checks
Add 50% "safe checks" bonus when there are multiple safe checks from the
same piece type.

LTC
LLR: 2.97 (-2.94,2.94) {0.25,1.75}
Total: 128184 W: 16491 L: 15954 D: 95739
Ptnml(0-2): 884, 11793, 38267, 12198, 950
https://tests.stockfishchess.org/tests/view/5e97d1b6c9ada107a0370e03

STC
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 19022 W: 3733 L: 3514 D: 11775
Ptnml(0-2): 338, 2103, 4414, 2314, 342
https://tests.stockfishchess.org/tests/view/5e97c377c9ada107a0370ddf

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

Bench: 5057329
2020-04-16 21:36:19 +02:00
FauziAkram d87adcc006 Queen and Rook Tuning
Tuning for multiple parameters for Queen and Rook.

passed STC
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 62790 W: 12033 L: 11754 D: 39003
Ptnml(0-2): 1058, 7186, 14666, 7389, 1096
https://tests.stockfishchess.org/tests/view/5e978c66c9ada107a0370d87

passed LTC
LLR: 2.95 (-2.94,2.94) {0.25,1.75}
Total: 89780 W: 11460 L: 11036 D: 67284
Ptnml(0-2): 624, 8151, 26951, 8505, 659
https://tests.stockfishchess.org/tests/view/5e979aaec9ada107a0370d93

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

Bench: 5111578
2020-04-16 21:32:26 +02:00
Vizvezdenec 0e51ff1074 Don't attempt probcut if ttMove is not good enough.
This idea is loosely based on xoroshiro idea about raisedBeta and ttmoves.
If our ttmove have low enough ttvalue and is deep enough (deeper than our probcut depth) it makes little sense to try probcut moves, since the ttMove already more or less failed to produce one according to transposition table.

passed STC
https://tests.stockfishchess.org/tests/view/5e9673ddc2718dee3c822920
LLR: 2.95 (-2.94,2.94) {-0.50,1.50}
Total: 72148 W: 14038 L: 13741 D: 44369
Ptnml(0-2): 1274, 8326, 16615, 8547, 1312

passed LTC
https://tests.stockfishchess.org/tests/view/5e96b378c2718dee3c8229bf
LLR: 2.94 (-2.94,2.94) {0.25,1.75}
Total: 89054 W: 11418 L: 10996 D: 66640
Ptnml(0-2): 623, 8113, 26643, 8515, 633

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

bench 4952731
2020-04-15 20:33:03 +02:00
Vizvezdenec ca4e399ea6 Space bonus and number of blocked pawns
This patch refines the recently introduced interaction between
the space bonus and the number of blocked pawns in a position.

* pawns count as blocked also if their push square is attacked by 2 enemy pawns;
* overall dependence is stronger as well as offset;
* bonus increase is capped at 9 blocked pawns in position;

passed STC
https://tests.stockfishchess.org/tests/view/5e94560663d105aebbab243d
LLR: 2.96 (-2.94,2.94) {-0.50,1.50}
Total: 29500 W: 5842 L: 5603 D: 18055
Ptnml(0-2): 504, 3443, 6677, 3562, 564

passed LTC
https://tests.stockfishchess.org/tests/view/5e95b383c2aaa99f75d1a14d
LLR: 2.95 (-2.94,2.94) {0.25,1.75}
Total: 63504 W: 8329 L: 7974 D: 47201
Ptnml(0-2): 492, 5848, 18720, 6197, 495

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

bench 4956028
2020-04-15 08:29:20 +02:00
Stefan Geschwentner 5c58f67126 less bonus for blocked connected pawn
Use less bonus for blocked connected pawns so closed positions are less worth.

STC:
LLR: 2.96 (-2.94,2.94) {-0.50,1.50}
Total: 60004 W: 11904 L: 11619 D: 36481
Ptnml(0-2): 1066, 7083, 13535, 7136, 1182
https://tests.stockfishchess.org/tests/view/5e941a8063d105aebbab23e3

LTC:
LLR: 2.95 (-2.94,2.94) {0.25,1.75}
Total: 36606 W: 4831 L: 4556 D: 27219
Ptnml(0-2): 252, 3353, 10872, 3520, 306
https://tests.stockfishchess.org/tests/view/5e9444b963d105aebbab2427

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

Bench: 4961260
2020-04-14 08:01:53 +02:00
silversolver1 de9fc53af5 Removes evasionPrunable
STC:
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 25656 W: 4979 L: 4826 D: 15851
Ptnml(0-2): 414, 2971, 5964, 3006, 473
https://tests.stockfishchess.org/tests/view/5e93dbd72cb65b3059c33819

LTC:
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 43732 W: 5656 L: 5593 D: 32483
Ptnml(0-2): 324, 4072, 13009, 4139, 322
https://tests.stockfishchess.org/tests/view/5e93e37c2cb65b3059c33825

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

Bench: 4702195
2020-04-13 09:20:53 +02:00
Vizvezdenec db59696aaf Scale up space weight with number of blocked pawns
This idea is loosely based on stockfish losses in closed positions in different tournaments. Space weight symmetrically increases for both sides the more blocked position is.

passed STC
https://tests.stockfishchess.org/tests/view/5e919eefaf0a0143109dc8ce
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 16994 W: 3389 L: 3172 D: 10433
Ptnml(0-2): 277, 1931, 3918, 2040, 331

passed LTC
https://tests.stockfishchess.org/tests/view/5e91d04faf0a0143109dc8ea
LLR: 2.94 (-2.94,2.94) {0.25,1.75}
Total: 133386 W: 17316 L: 16763 D: 99307
Ptnml(0-2): 945, 12407, 39524, 12784, 1033

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

Bench: 4966867
2020-04-13 09:16:54 +02:00
Lolligerhans d7a2d5a445 Remove candidate passers w/o feasible lever
+-------+
| o . . | o  their pawns
| x . . | x  our pawns
| . x . | <- Can sacrifice to create passer?
+-------+
   yes

    1         2         3         4         5
+-------+ +-------+ +-------+ +-------+ +-------+
| o . . | | o r . | | o r . | | o . b | | o . b |  lowercase: theirs
| x b . | | x . . | | x . R | | x . R | | x . . |  uppercase: ours
| . x . | | . x . | | . x . | | . x . | | . x B |
+-------+ +-------+ +-------+ +-------+ +-------+
   no        no        yes       no        yes

The value of our top pawn depends on our ability to advance our bottom
pawn, levering their blocker. Previously, this pawn configuration was
always scored as passer (although a blocked one).

Add requirements for the square s above our (possibly) sacrificed pawn:
- s must not be occupied by them (1).
- If they attack s (2), we must attack s (3).
- If they attack s with a minor (4), we must attack s with a minor (5).
The attack from their blocker is ignored because it is inherent in the
structure; we are ok with sacrificing our bottom pawn.

LTC
LLR: 2.95 (-2.94,2.94) {0.25,1.75}
Total: 37030 W: 4962 L: 4682 D: 27386
Ptnml(0-2): 266, 3445, 10863, 3625, 316
https://tests.stockfishchess.org/tests/view/5e92a2b4be6ede5b954bf239

STC
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 40874 W: 8066 L: 7813 D: 24995
Ptnml(0-2): 706, 4753, 9324, 4890, 764
https://tests.stockfishchess.org/tests/view/5e922199af0a0143109dc90e

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

Bench: 4828294
2020-04-13 08:50:25 +02:00
Joost VandeVondele 2c5f0efa13 Extend irreversible moves
if these are ttMoves and played in positions with a high value of the rule50 counter. The unusual extension of 2 is safe in this context as awarding it will reset the rule50 counter, making sure it is awarded very rarely in a search path.

This patch partially addresses https://github.com/official-stockfish/Stockfish/issues/2620 as it should make it less likely to play a move that resets the counter, but that is worse than alternative moves after a slightly deeper search.

passed STC:
LLR: 2.96 (-2.94,2.94) {-0.50,1.50}
Total: 71658 W: 13840 L: 13560 D: 44258
Ptnml(0-2): 1058, 7921, 17643, 8097, 1110
https://tests.stockfishchess.org/tests/view/5e90d0f6754c3424c4cf9f41

passed LTC:
LLR: 2.94 (-2.94,2.94) {0.25,1.75}
Total: 85082 W: 11069 L: 10680 D: 63333
Ptnml(0-2): 459, 6982, 27259, 7393, 448
https://tests.stockfishchess.org/tests/view/5e917470af0a0143109dc341

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

Bench: 4432822
2020-04-12 20:38:47 +02:00
protonspring 6596f0eac0 Always remember the ttMove
In master, if the received ttMove meets the prescribed conditions in the various MovePicker constructors, it is returned as the first move, otherwise we set it to MOVE_NONE. If set to MOVE_NONE, we no longer track what the ttMove was, and it will might be returned later in a list of generated moves. This may be a waste. With this patch, if the ttMove fails to meet the prescribed conditions, we simply skip the TT stages, but still store the move and make sure it's never returned.

STC
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 66424 W: 12903 L: 12806 D: 40715
Ptnml(0-2): 1195, 7730, 15230, 7897, 1160

LTC
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 45682 W: 5989 L: 5926 D: 33767
Ptnml(0-2): 329, 4361, 13443, 4334, 374

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

Bench 4928928
2020-04-12 20:34:50 +02:00
Joost VandeVondele f83cb95740 Small cleanups
closes https://github.com/official-stockfish/Stockfish/pull/2606

No functional change
2020-04-12 20:30:08 +02:00
Vizvezdenec 195a4fec6d Introduce capture history pruning
This patch introduces a heuristic that is similar to countermove based pruning but for captures - capture history pruning. The idea is that we can (almost) safely prune really late captures with negative history if they don't give check so will most likely not produce some king-attacking tactic.

passed STC
https://tests.stockfishchess.org/tests/view/5e8c60d40ffd2be7f15e5470
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 23748 W: 4758 L: 4529 D: 14461
Ptnml(0-2): 421, 2712, 5400, 2899, 442

passed LTC
https://tests.stockfishchess.org/tests/view/5e8c72bf0ffd2be7f15e547f
LLR: 2.96 (-2.94,2.94) {0.25,1.75}
Total: 17330 W: 2415 L: 2190 D: 12725
Ptnml(0-2): 126, 1561, 5107, 1704, 167

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

bench 4417023
2020-04-07 17:47:01 +02:00
Vizvezdenec 85bcf4741e Further increase reductions with increasing number of threads
This patch doubles the reduction increase with thread count.

passed STC
https://tests.stockfishchess.org/tests/view/5e874f5a4411759d9d098696
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 9162 W: 1558 L: 1385 D: 6219
Ptnml(0-2): 90, 958, 2343, 1069, 121

passed LTC
https://tests.stockfishchess.org/tests/view/5e8762804411759d9d09869f
LLR: 2.94 (-2.94,2.94) {0.25,1.75}
Total: 79364 W: 9541 L: 9159 D: 60664
Ptnml(0-2): 462, 6880, 24661, 7172, 507

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

bench 4831963
2020-04-05 08:44:25 +02:00
31m059 fbc7a328c6 Retire candidate passed pawns
Before this commit, some pawns were considered "candidate" passed pawns and given half bonus. After this commit, all of these pawns are scored as passed pawns, and they do not receive less bonus.

STC:
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 21806 W: 4320 L: 4158 D: 13328
Ptnml(0-2): 367, 2526, 5001, 2596, 413
https://tests.stockfishchess.org/tests/view/5e86b4724411759d9d098639

LTC:
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 12590 W: 1734 L: 1617 D: 9239
Ptnml(0-2): 96, 1187, 3645, 1238, 129
https://tests.stockfishchess.org/tests/view/5e86d2874411759d9d098640

This PR and commit are dedicated to our colleague Stefan Geschwentner (@locutus2), one of the most respected and accomplished members of the Stockfish developer community. Stockfish is a volunteer project and has always thrived because of Stefan's talent, insight, generosity, and dedication. Welcome back, Stefan!

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

Bench: 4831963
2020-04-05 08:39:00 +02:00
protonspring 3cb1c6c3c6 remove KNPK endgame code
In more than 100k local KNPK games, there is no discernible difference between master and master with this endgame removed: master:42971, patch:42973, draws: 3969. Removal does not seem to regress in normal games.

STC
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 46390 W: 8998 L: 8884 D: 28508
Ptnml(0-2): 707, 5274, 11163, 5300, 751
https://tests.stockfishchess.org/tests/view/5e83b18ee42a5c3b3ca2ef02

LTC
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 44768 W: 5863 L: 5814 D: 33091
Ptnml(0-2): 251, 3918, 14028, 3905, 282
https://tests.stockfishchess.org/tests/view/5e84a82a4411759d9d0984f4

In tests with a book of endgames that can convert into KNPK, no significant difference can be seen either

```
TC 1.0+0.01
Score of patch vs master: 6131 - 6188 - 27681  [0.499] 40000
Elo difference: -0.5 +/- 1.9, LOS: 30.4 %, DrawRatio: 69.2 %

TC 2.0+0.02
Score of patch vs master: 5740 - 5741 - 28519 [0.500] 40000
Elo difference: -0.0 +/- 1.8, LOS: 49.6 %, DrawRatio: 71.3 %
``

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

Bench 4512059
2020-04-05 08:35:31 +02:00
Vizvezdenec c14f4877cf Increase reduction for captures.
The idea behind this patch is that if static eval is really bad so capturing of current piece on spot will still produce a position with an eval much lower than alpha then our best chance is to create some kind of king attack. So captures without check are mostly worse than captures with check and can be reduced more.

passed STC
https://tests.stockfishchess.org/tests/view/5e8514b44411759d9d098543
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 46196 W: 9039 L: 8781 D: 28376
Ptnml(0-2): 750, 5412, 10628, 5446, 862

passed LTC
https://tests.stockfishchess.org/tests/view/5e8530134411759d9d09854c
LLR: 2.94 (-2.94,2.94) {0.25,1.75}
Total: 23462 W: 3228 L: 2988 D: 17246
Ptnml(0-2): 186, 2125, 6849, 2405, 166

close https://github.com/official-stockfish/Stockfish/pull/2612

bench 4742598
2020-04-02 15:11:16 +02:00
31m059 375e4eeaf5 Simplify a candidate passer condition.
STC:
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 31528 W: 6208 L: 6061 D: 19259
Ptnml(0-2): 541, 3673, 7205, 3788, 557
https://tests.stockfishchess.org/tests/view/5e825db0e42a5c3b3ca2ee21

LTC:
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 38546 W: 5083 L: 5009 D: 28454
Ptnml(0-2): 299, 3628, 11362, 3668, 316
https://tests.stockfishchess.org/tests/view/5e826ec7e42a5c3b3ca2ee2a

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

Bench: 5139561
2020-04-02 14:56:30 +02:00
mstembera 84f3bf594d No voting for TB loss / mate.
Just as we pick the shortest mate also make sure we stave off mate as long as possible.

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

bench: 5138771
2020-04-02 14:54:47 +02:00
protonspring 0b8ce4b303 Limit array access in Position
This is a non-functional code style change that routes all position array accesses to single methods, and adds an assert to check correctness.

Passed STC
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 37312 W: 7378 L: 7246 D: 22688
Ptnml(0-2): 606, 4280, 8762, 4392, 616
https://tests.stockfishchess.org/tests/view/5e7c0c69e42a5c3b3ca2eb3d

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

No functional change.
2020-04-02 14:40:03 +02:00
Joost VandeVondele 209e94203f Small cleanups
https://github.com/official-stockfish/Stockfish/pull/2584

No functional change.
2020-03-30 22:46:07 +02:00
Praveen tummala b7ecdaada7 Movecount pruning reduction logic
This patch refines search reduction logic in case the position is not a former PV node and is pruned based on move count.

passed STC
https://tests.stockfishchess.org/tests/view/5e8092bde42a5c3b3ca2ed35
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 78848 W: 15480 L: 15170 D: 48198
Ptnml(0-2): 1406, 9310, 17773, 9438, 1497

passed LTC
https://tests.stockfishchess.org/tests/view/5e80bb13e42a5c3b3ca2ed4b
LLR: 2.94 (-2.94,2.94) {0.25,1.75}
Total: 86596 W: 11451 L: 11033 D: 64112
Ptnml(0-2): 624, 7993, 25687, 8329, 665

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

Bench: 5138771
2020-03-30 22:41:22 +02:00
Vizvezdenec f2430bf034 Count only the most advanced passed pawn for each file.
This patch adjusts definition of passed pawns - if there is a pawn of our color in the same file in front of a current pawn it's no longer counts as passed.

passed STC
https://tests.stockfishchess.org/tests/view/5e802037e42a5c3b3ca2ed07
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 215296 W: 41843 L: 41341 D: 132112
Ptnml(0-2): 3688, 25313, 49304, 25495, 3848

passed LTC
https://tests.stockfishchess.org/tests/view/5e806441e42a5c3b3ca2ed2b
LLR: 2.95 (-2.94,2.94) {0.25,1.75}
Total: 74050 W: 9761 L: 9379 D: 54910
Ptnml(0-2): 510, 6838, 22025, 7064, 588

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

bench: 4902237
2020-03-29 19:48:01 +02:00
xoto10 8c73339a36 Remove previousScore adjustment of delta.
STC:
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 14580 W: 2904 L: 2731 D: 8945
Ptnml(0-2): 243, 1665, 3339, 1762, 281
https://tests.stockfishchess.org/tests/view/5e7d080ae42a5c3b3ca2ebc6

LTC:
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 60338 W: 7870 L: 7831 D: 44637
Ptnml(0-2): 451, 5596, 18018, 5671, 433
https://tests.stockfishchess.org/tests/view/5e7d11b3e42a5c3b3ca2ebd3

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

Bench 5247262
2020-03-29 19:44:07 +02:00
Lyudmil Antonov 58746d9fb8 Tuned history reduction
Value after a long Bayesian tuning, using a home-made classification approach.

STC
https://tests.stockfishchess.org/tests/view/5e7c7b16e42a5c3b3ca2eb66
LLR: 2.96 (-2.94,2.94) {-0.50,1.50}
Total: 45472 W: 8992 L: 8732 D: 27748
Ptnml(0-2): 795, 5276, 10352, 5500, 813

LTC
https://tests.stockfishchess.org/tests/view/5e7c8be7e42a5c3b3ca2eb75
LLR: 2.94 (-2.94,2.94) {0.25,1.75}
Total: 22744 W: 3085 L: 2849 D: 16810
Ptnml(0-2): 156, 2090, 6658, 2298, 170

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

Bench 5030855
2020-03-26 17:49:28 +01:00
xoto10 c8e8e48b14 Remove passed_count from almostUnwinnable.
This simplification allows the almostUnwinnable flag to match endgames where the pawns are all on the same flank but are not symmetrical.

STC:
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 23356 W: 4543 L: 4395 D: 14418
Ptnml(0-2): 346, 2651, 5582, 2707, 392
https://tests.stockfishchess.org/tests/view/5e7b8f57e42a5c3b3ca2eb09

LTC:
LLR: 2.96 (-2.94,2.94) {-1.50,0.50}
Total: 31778 W: 4097 L: 4023 D: 23658
Ptnml(0-2): 199, 2853, 9729, 2891, 217
https://tests.stockfishchess.org/tests/view/5e7ba5ade42a5c3b3ca2eb16

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

Bench 4777139
2020-03-26 17:46:51 +01:00
protonspring 8b229381da Remove KNPKB endgame.
This is a functional simplification that removes the KNPKB endgame.

Testing on only KNPKB positions suggests that this removal actually gains Elo:

Score of patch vs master: 3380 - 3035 - 33585  [0.504] 40000
Elo difference: 3.0 +/- 1.4, LOS: 100.0 %, DrawRatio: 84.0 %

Score of patch vs master: 290 - 36 - 39674  [0.503] 40000
Elo difference: 2.2 +/- 0.3, LOS: 100.0 %, DrawRatio: 99.2 %

removal also doesn't cause a regression with the standard book:

STC
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 71376 W: 13794 L: 13719 D: 43863
Ptnml(0-2): 1066, 8092, 17290, 8181, 1059
https://tests.stockfishchess.org/tests/view/5e76c3d5e42a5c3b3ca2e8be

LTC
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 28394 W: 3731 L: 3662 D: 21001
Ptnml(0-2): 167, 2339, 9116, 2408, 167
https://tests.stockfishchess.org/tests/view/5e76e5eae42a5c3b3ca2e8d3

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

Bench 5480811
2020-03-25 21:42:33 +01:00
Vizvezdenec 6ecab03dee Adjust singular extension search depth
This patch applies a different singular extension search logic in case the position is ttPv && !PvNode.
It changes the depth of this search, higher for this types of nodes, and lower for other nodes.

passed STC
http://tests.stockfishchess.org/tests/view/5e72bbaae42a5c3b3ca2e75e
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 12692 W: 2608 L: 2389 D: 7695
Ptnml(0-2): 238, 1414, 2839, 1601, 254

passed LTC
http://tests.stockfishchess.org/tests/view/5e731c07e42a5c3b3ca2e770
LLR: 2.96 (-2.94,2.94) {0.25,1.75}
Total: 145716 W: 19218 L: 18626 D: 107872
Ptnml(0-2): 1100, 13605, 42899, 14111, 1143

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

Bench: 5398277
2020-03-20 21:07:37 +01:00
Vizvezdenec ff27109313 Adjust singular LMR for positions seen in PV
This patch continues work on altering search for ttPv nodes, using recent idea to alter it more in not PvNodes. Previous tweak based on this idea adjusted singularBeta - this one adjusts value of singularLMR, so they are both related to singular extension search.

passed STC
http://tests.stockfishchess.org/tests/view/5e700737e42a5c3b3ca2e659
LLR: 2.95 (-2.94,2.94) {-0.50,1.50}
Total: 140608 W: 27053 L: 26659 D: 86896
Ptnml(0-2): 2425, 16337, 32439, 16625, 2478

passed LTC
http://tests.stockfishchess.org/tests/view/5e7068eae42a5c3b3ca2e687
LLR: 2.94 (-2.94,2.94) {0.25,1.75}
Total: 79318 W: 10463 L: 10064 D: 58791
Ptnml(0-2): 567, 7416, 23359, 7685, 632

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

Bench: 4952322
2020-03-17 19:34:47 +01:00
Stéphane Nicolet 07caca2587 Anchored bishops
Reduce the "bad bishop" penalty when the bishop is protected by
one of our pawns, as it may indicate that the bishop has found
a safe spot outside the pawn chain.

STC:
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 176942 W: 34142 L: 33696 D: 109104
Ptnml(0-2): 3129, 20422, 40919, 20876, 3125
http://tests.stockfishchess.org/tests/view/5e6f61aae42a5c3b3ca2e62d

LTC:
LLR: 2.95 (-2.94,2.94) {0.25,1.75}
Total: 42252 W: 5615 L: 5322 D: 31315
Ptnml(0-2): 308, 3881, 12500, 4084, 353
http://tests.stockfishchess.org/tests/view/5e701382e42a5c3b3ca2e661

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

Bench: 4963440
2020-03-17 19:20:37 +01:00
Joost VandeVondele ddcbacd04d Small cleanups
closes https://github.com/official-stockfish/Stockfish/pull/2567

No functional change.
2020-03-14 17:04:50 +01:00
pb00067 ec2002c594 Simplify futility pruning parent node
only continuation histories seem needed for this purpose.

STC:
http://tests.stockfishchess.org/tests/view/5e6b88dfe42a5c3b3ca2e4ab
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 113356 W: 21725 L: 21696 D: 69935
Ptnml(0-2): 1999, 13255, 26163, 13240, 2021

LTC:
http://tests.stockfishchess.org/tests/view/5e6babbfe42a5c3b3ca2e4c2
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 22164 W: 2917 L: 2821 D: 16426
Ptnml(0-2): 173, 2040, 6548, 2160, 161

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

bench: 4839496
2020-03-14 16:30:17 +01:00
protonspring 442e1e0f93 simplify castling part of generate_all.
somewhat more compact, generates same code.

close https://github.com/official-stockfish/Stockfish/pull/2580

No functional change.
2020-03-14 16:27:54 +01:00
silversolver1 c077bfb413 Remove set statScore to zero
Simplification. Removes setting statScore to zero if negative.

STC:
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 84820 W: 16100 L: 16033 D: 52687
Ptnml(0-2): 1442, 9865, 19723, 9944, 1436
https://tests.stockfishchess.org/tests/view/5e654fdae42a5c3b3ca2e2f8

LTC:
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 57658 W: 7435 L: 7391 D: 42832
Ptnml(0-2): 441, 5397, 17104, 5451, 436
https://tests.stockfishchess.org/tests/view/5e657ce9e42a5c3b3ca2e307

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

Bench: 5168890
2020-03-09 22:46:13 +01:00
protonspring 47be966d30 Equations for edges and corners.
This is a functional simplification that removes the large arrays in endgames.cpp.
It also fixes a recently introduced bug (960d59d541) in KNBvK,
now using flip_file() instead of ~.

One fen added to bench to increase endgame coverage.

STC
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 174724 W: 33325 L: 33404 D: 107995
Ptnml(0-2): 2503, 19607, 43181, 19608, 2463
http://tests.stockfishchess.org/tests/view/5e6448ffe42a5c3b3ca2e287

LTC
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 35640 W: 4679 L: 4621 D: 26340
Ptnml(0-2): 189, 2991, 11424, 3005, 211
http://tests.stockfishchess.org/tests/view/5e650b24e42a5c3b3ca2e2d8

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

Bench: 5527957
2020-03-09 22:16:26 +01:00
Gary Heckman 37e3863927 Fix ambiguity between clamp implementations
There is an ambiguity between global and std clamp implementations when compiling in c++17,
and on certain toolchains that are not strictly conforming to c++11.
This is solved by putting our clamp implementation in a namespace.

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

No functional change.
2020-03-07 11:14:27 +01:00
protonspring 9690cd6295 Remove KRPPKRPScaleFactors array
Fucntional simplification that removes the KRPPKRPScaleFactors array.

STC
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 47374 W: 9159 L: 9049 D: 29166
Ptnml(0-2): 707, 5325, 11560, 5341, 754
http://tests.stockfishchess.org/tests/view/5e5ff464e42a5c3b3ca2e156

LTC
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 31268 W: 4064 L: 3995 D: 23209
Ptnml(0-2): 173, 2734, 9764, 2777, 186
http://tests.stockfishchess.org/tests/view/5e61be6ce42a5c3b3ca2e1c1

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

Bench 5123316
2020-03-07 11:09:38 +01:00
protonspring e7c1c8c1ab Cleanup KBPsK endgame
* Clarify distinction between strong side pawns and all pawns.
* Simplify and speed-up determination of pawns on the same file.
* Clarify comments.
* more_than_one() is probably faster than pos.count.

Passed STC:
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 40696 W: 7856 L: 7740 D: 25100
Ptnml(0-2): 584, 4519, 10054, 4579, 612
http://tests.stockfishchess.org/tests/view/5e6153b1e42a5c3b3ca2e1a9

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

No functional change.
2020-03-07 10:55:15 +01:00
protonspring 0424273d0b Small speed-up in BetweenBB
A speed-up removing some comparisons.

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

No functional change.
2020-03-07 10:48:16 +01:00
protonspring 5a7b45eac9 Use equations for PushAway and PushClose
A functional simplification replacing the corresponding arrays. Tested in two variants,
also the simpler one performs well, even though differences to master should be minimal.

STC
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 57864 W: 11092 L: 11001 D: 35771
Ptnml(0-2): 826, 6458, 14320, 6455, 873
http://tests.stockfishchess.org/tests/view/5e5da5b6e42a5c3b3ca2e05c

LTC
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 7198 W: 982 L: 883 D: 5333
Ptnml(0-2): 33, 575, 2296, 650, 45
http://tests.stockfishchess.org/tests/view/5e5df13ae42a5c3b3ca2e077

LTC (This exact version. . . more simplified)
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 5392 W: 729 L: 631 D: 4032
Ptnml(0-2): 23, 405, 1751, 485, 32
http://tests.stockfishchess.org/tests/view/5e5ead99e42a5c3b3ca2e0e4

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

Bench 5123316
2020-03-04 07:17:04 +01:00
protonspring 960d59d541 Consolidate Square Flipping
Add a flip_rank() and flip_file() so that all of the square flipping can be consolidated.

STC
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 57234 W: 11064 L: 10969 D: 35201
Ptnml(0-2): 822, 6562, 13801, 6563, 869
http://tests.stockfishchess.org/tests/view/5e5d2f2aafe6254521f2ffaa

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

No functional change.
2020-03-04 07:11:48 +01:00
Joost VandeVondele c6839a2615 Small cleanups
closes https://github.com/official-stockfish/Stockfish/pull/2546

No functional change.
2020-03-01 09:31:58 +01:00
Guenther Demetz f27339d35b Simplify lowply-history logic
Don't restrict usage to ttPv nodes exclusively

STC:
http://tests.stockfishchess.org/tests/view/5e5634f284a82b4acd41499a
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 152796 W: 29146 L: 29178 D: 94472
Ptnml(0-2): 2590, 17792, 35628, 17836, 2552

LTC:
http://tests.stockfishchess.org/tests/view/5e575d4984a82b4acd4149e8
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 20078 W: 2688 L: 2587 D: 14803
Ptnml(0-2): 139, 1914, 5853, 1973, 160

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

bench: 4923286
2020-03-01 09:20:31 +01:00
Moez Jellouli 09f53dbfa5 Weak queen protection
Extra penalty if weak piece is only protected by a queen.

STC:
http://tests.stockfishchess.org/tests/view/5e53c6ab84a82b4acd4148fa
LLR: 2.96 (-2.94,2.94) {-0.50,1.50}
Total: 44630 W: 8615 L: 8359 D: 27656
Ptnml(0-2): 746, 5156, 10323, 5276, 814

LTC:
http://tests.stockfishchess.org/tests/view/5e54e05d84a82b4acd414947
LLR: 2.94 (-2.94,2.94) {0.25,1.75}
Total: 175480 W: 23085 L: 22409 D: 129986
Ptnml(0-2): 1264, 16494, 51678, 16910, 1394

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

Bench: 4923286
2020-02-27 13:14:51 +01:00
AndyGrant 2e1369d030 Fix TT write in MultiPV case.
fixes an error reported earlier as https://github.com/official-stockfish/Stockfish/issues/2404 by @AndyGrant.

MultiPV at root shouldn't write to the TT for later lines, as that is neither the eval nor the bestmove for that position.
Fixing this error doesn't matter for playing games (http://tests.stockfishchess.org/tests/view/5dcdbd810ebc590256324a11).

However, it can lead to wrong mate announcements as reported by @uriblass. In particular the following testcase gives
wrong results for the second search, prior to this patch:

```
setoption name MultiPV value 2
position fen 5R2/2kB2p1/p2bR3/8/3p1B2/8/PPP5/2K5 b - - 0 49
go depth 40
position fen 2B2R2/3r2p1/p1kbR3/8/3p1B2/8/PPP5/2K5 b - - 8 48
go depth 40
```

fixes https://github.com/official-stockfish/Stockfish/issues/2561
closes https://github.com/official-stockfish/Stockfish/pull/2562

Only affects MultiPV search.

Bench: 4697493
2020-02-25 21:10:10 +01:00
31m059 8352977b91 Use single param for Outpost and ReachableOutpost.
In November 2019, as a result of the simplification of rank-based outposts by 37698b0,
separate bonuses were introduced for outposts that are currently occupied and outposts
that are reachable on the next move. However, the values of these two bonuses are
quite similar, and they have remained that way for three months of development.

It appears that we can safely retire the separate ReachableOutpost parameter and
use the same Outpost bonus in both cases, restoring the basic principles of Stockfish
outpost evaluation to their pre-November state, while also reducing
the size of the parameter space.

STC:
LLR: 2.96 (-2.94,2.94) {-1.50,0.50}
Total: 47680 W: 9213 L: 9092 D: 29375
Ptnml(0-2): 776, 5573, 11071, 5594, 826
https://tests.stockfishchess.org/tests/view/5e51e33190a0a02810d09802

LTC:
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 14690 W: 1960 L: 1854 D: 10876
Ptnml(0-2): 93, 1381, 4317, 1435, 119
https://tests.stockfishchess.org/tests/view/5e52197990a0a02810d0980f

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

Bench: 4697493
2020-02-25 21:03:42 +01:00
Günther Demetz b8c00efa27 Improve move order near the root
Current move histories are known to work well near the leaves, whilst at
higher depths they aren't very helpful. To address this problem this
patch introduces a table dedicated for what's happening at plies 0-3.
It's structured like mainHistory with ply index instead of color.
It get cleared with each new search and is filled during iterative
deepening at higher depths when recording successful quiet moves near
the root or traversing nodes which were in the principal variation
(ttPv).

Medium TC (20+0.2):
https://tests.stockfishchess.org/tests/view/5e4d358790a0a02810d096dc
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 100910 W: 16682 L: 16376 D: 67852
Ptnml(0-2): 1177, 10983, 25883, 11181, 1231

LTC:
https://tests.stockfishchess.org/tests/view/5e4e2cb790a0a02810d09714
LLR: 2.95 (-2.94,2.94) {0.25,1.75}
Total: 80444 W: 10495 L: 10095 D: 59854
Ptnml(0-2): 551, 7479, 23803, 7797, 592

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

Bench: 4705960
2020-02-22 21:32:32 +01:00
protonspring ab930f8d3f Updated KNNKP endgame.
This is a patch that significantly improves playing KNNKP endgames:

```
Score of 2553 vs master: 132 - 38 - 830 [0.547] 1000
Elo difference: 32.8 +/- 8.7, LOS: 100.0 %, DrawRatio: 83.0 %
```

At the same time it reduces the evaluation of this mostly draw engame
from ~7.5 to ~1.5

This patch does not regress against master in normal games:

STC
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 96616 W: 18459 L: 18424 D: 59733
Ptnml(0-2): 1409, 10812, 23802, 10905, 1380
http://tests.stockfishchess.org/tests/view/5e49dfe6f8d1d52b40cd31bc

LTC
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 49726 W: 6340 L: 6304 D: 37082
Ptnml(0-2): 239, 4227, 15906, 4241, 250
http://tests.stockfishchess.org/tests/view/5e4ab9ee16fb3df8c4cc01d0

Theory: KNNK is a dead draw, however the presence of the additional weakSide pawn opens up some mate opportunities. The idea is to block the pawn (preferably behind the Troitsky line) with one of the knights and press the weakSide king into a corner. If we can stalemate the king, we release the pawn with the knight (to avoid actual stalemate), and use the knight to complete the mate before the pawn promotes. This is also why there is an additional penalty for advancement of the pawn.

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

Bench: 4981770
2020-02-20 08:32:17 +01:00
protonspring 10ead8a724 Simplify Futility Move Count
remove two constants

STC
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 62050 W: 11903 L: 11802 D: 38345
Ptnml(0-2): 1002, 7346, 14283, 7320, 1065
http://tests.stockfishchess.org/tests/view/5e41d73be70d848499f63c6d

LTC
LLR: 2.93 (-2.94,2.94) {-1.50,0.50}
Total: 12850 W: 1679 L: 1572 D: 9599
Ptnml(0-2): 82, 1171, 3818, 1249, 96
http://tests.stockfishchess.org/tests/view/5e42bf07e70d848499f63cc0

Bench: 4762351
2020-02-15 15:13:14 +01:00
Joost VandeVondele be5a2f015e Fix for incorrect VALUE_MATE_IN_MAX_PLY usage.
Fixes #2533, fixes #2543, fixes #2423.

the code that prevents false mate announcements depending on the TT
state (GHI), incorrectly used VALUE_MATE_IN_MAX_PLY. The latter
constant, however, also includes, counterintuitively, the TB win range.

This patch fixes that, by restoring the behavior for TB win scores,
while retaining the false mate correctness, and improving the mate
finding ability. In particular

no alse mates are announced with the poisened hash testcase
```
position fen 8/8/8/3k4/8/8/6K1/7R w - - 0 1
go depth 40
position fen 8/8/8/3k4/8/8/6K1/7R w - - 76 1
go depth 20
ucinewgame
```

mates are found with the testcases reported in #2543
```
position fen 4k3/3pp3/8/8/8/8/2PPP3/4K3 w - - 0 1
setoption name Hash value 1024
go depth 55
ucinewgame
```
and
```
position fen 4k3/4p3/8/8/8/8/3PP3/4K3 w - - 0 1
setoption name Hash value 1024
go depth 45
ucinewgame
```

furthermore, on the mate finding benchmark (ChestUCI_23102018.epd),
performance improves over master, roughly reaching performance with the
false mate protection reverted
```
Analyzing 6566 mate positions for best and found mates:

                 ----------------best ---------------found
           nodes master revert  fixed master revert  fixed
        16000000   4233   4236   4235   5200   5201   5199
        32000000   4583   4585   4585   5417   5424   5418
        64000000   4852   4853   4855   5575   5584   5579
       128000000   5071   5068   5066   5710   5720   5716
       256000000   5280   5282   5279   5819   5827   5826
       512000000   5471   5468   5468   5919   5935   5932
```

On a testcase with TB enabled, progress is made consistently, contrary
to master
```
setoption name SyzygyPath value ../../../syzygy/3-4-5/
setoption name Hash value 2048
position fen 1R6/3k4/8/K2p4/4n3/2P5/8/8 w - - 0 1
go depth 58
ucinewgame
```

The PR (prior to a rewrite for clarity)

passed STC:
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 65405 W: 12454 L: 12384 D: 40567
Ptnml(0-2): 920, 7256, 16285, 7286, 944
http://tests.stockfishchess.org/tests/view/5e441a3be70d848499f63d15

passed LTC:
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 27096 W: 3477 L: 3413 D: 20206
Ptnml(0-2): 128, 2215, 8776, 2292, 122
http://tests.stockfishchess.org/tests/view/5e44e277e70d848499f63d63

The incorrectly named VALUE_MATE_IN_MAX_PLY and VALUE_MATED_IN_MAX_PLY
were renamed into VALUE_TB_WIN_IN_MAX_PLY and VALUE_TB_LOSS_IN_MAX_PLY,
and correclty defined VALUE_MATE_IN_MAX_PLY and VALUE_MATED_IN_MAX_PLY
were introduced.

One further (corner case) mistake using these constants was fixed (go
mate X), which could lead to a premature return if X > MAX_PLY / 2,
but TB were present.

Thanks to @svivanov72 for one of the reports and help fixing the issue.

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

Bench: 4932981
2020-02-15 15:10:07 +01:00
Vizvezdenec 4e8986483a Modify singular beta for ttPv positions.
This patch lowers singular beta for positions that have been in pv and are not pv nodes.
The idea of using ttpv && !PvNode improved scaling with TC and could be
useful for other search heuristics.

passed STC
http://tests.stockfishchess.org/tests/view/5e3f6d7ce70d848499f63bbc
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 154953 W: 29688 L: 29272 D: 95993
Ptnml(0-2): 2616, 17912, 36037, 18210, 2673

passed LTC
http://tests.stockfishchess.org/tests/view/5e405561e70d848499f63bfa
LLR: 2.95 (-2.94,2.94) {0.25,1.75}
Total: 70974 W: 9305 L: 8932 D: 52737
Ptnml(0-2): 466, 6658, 20920, 6826, 569

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

Bench: 4932981
2020-02-10 09:19:02 +01:00
Joost VandeVondele 0aee1ec4ab Fix wrong assert.
can trigger an abort when compiling with debug=yes, and using 7men TB.
The assert should check that less than 8 pieces are in the key for each
side, matching the assumption that underlies the FEN string construction.
Also take explicitly care of a 'v' character in material strings.

Fixes an issue reported in the forum:
https://groups.google.com/d/msg/fishcooking/yoVC7etIpz0/7mS7ntZMBAAJ

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

No functional change.
2020-02-10 09:12:07 +01:00
Joost VandeVondele 0c878adb36 Small cleanups.
closes https://github.com/official-stockfish/Stockfish/pull/2532

Bench: 4869669
2020-02-05 15:32:29 +01:00
Vizvezdenec ddd4224640 Reintroduce king infiltration
This patch reintroduces the recently simplified king infiltration bonus
in initiative calculation, doubling its effect, and compensating more.

passed STC
http://tests.stockfishchess.org/tests/view/5e3476f630ae32da08941d5c
LLR: 2.94 (-2.94,2.94) {-0.50,1.50}
Total: 75323 W: 14434 L: 14140 D: 46749
Ptnml(0-2): 1231, 8729, 17528, 8826, 1331

passed LTC
http://tests.stockfishchess.org/tests/view/5e377353e70d848499f638c1
LLR: 2.94 (-2.94,2.94) {0.25,1.75}
Total: 171466 W: 22223 L: 21561 D: 127682
Ptnml(0-2): 1204, 15951, 50831, 16397, 1312

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

Brench: 4869669
2020-02-05 13:42:24 +01:00
xoto10 0f37da0e34 Simplify away king infiltration.
STC :
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 91438 W: 17496 L: 17438 D: 56504
Ptnml(0-2): 1573, 10711, 21067, 10790, 1563
https://tests.stockfishchess.org/tests/view/5e34812630ae32da08941d65

LTC :
LLR: 2.96 (-2.94,2.94) {-1.50,0.50}
Total: 40485 W: 5246 L: 5177 D: 30062
Ptnml(0-2): 289, 3818, 11976, 3812, 327
https://tests.stockfishchess.org/tests/view/5e354daee70d848499f6380c

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

Bench: 5047825
2020-02-02 07:11:49 +01:00
xoto10 c390b734c4 Simplify Tweak late move reductions at root.
Revert change from Jan 15.

STC 10+0.1 :
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 65135 W: 12543 L: 12436 D: 40156
Ptnml(0-2): 1090, 7618, 14947, 7623, 1136
https://tests.stockfishchess.org/tests/view/5e334016708b13464ceea32e

LTC 60+0.6 :
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 17768 W: 2286 L: 2191 D: 13291
Ptnml(0-2): 128, 1602, 5273, 1679, 140
https://tests.stockfishchess.org/tests/view/5e34011e57e1ecae66ec2aab

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

Bench: 4914050
2020-02-01 09:05:13 +01:00
Joost VandeVondele 6ccb1cac5a Revert 5 recent patches
Revert 5 patches which were merged, but lead to a regression test that showed negative Elo gain:

http://tests.stockfishchess.org/tests/view/5e307251ab2d69d58394fdb9

This was discussed in depth in:

https://github.com/official-stockfish/Stockfish/issues/2531

Each patch was removed and tested as a simplification, full list below, and the whole combo as well.

After the revert the regression test showed a neutral result:

http://tests.stockfishchess.org/tests/view/5e334851708b13464ceea33c

As a result of this experience, the SPRT testing bounds will be made more strict.

Reverted patches:

1 Dynamic Complexity 6d0eabd5fe :

STC 10+0.1 https://tests.stockfishchess.org/tests/view/5e31fcacec661e2e6a340d08 :
LLR: 2.97 (-2.94,2.94) {-1.50,0.50}
Total: 38130 W: 7326 L: 7189 D: 23615
Ptnml(0-2): 677, 4346, 8843, 4545, 646

LTC 60+0.6 https://tests.stockfishchess.org/tests/view/5e32c18fec661e2e6a340d73 :
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 38675 W: 4941 L: 4866 D: 28868
Ptnml(0-2): 270, 3556, 11429, 3584, 291

3 More bonus for bestMoves on past PV nodes 71e0b5385e :

STC 10+0.1 https://tests.stockfishchess.org/tests/view/5e31fe93ec661e2e6a340d10 :
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 46100 W: 8853 L: 8727 D: 28520
Ptnml(0-2): 796, 5297, 10749, 5387, 813

LTC 60+0.6 https://tests.stockfishchess.org/tests/view/5e32c187ec661e2e6a340d71 :
LLR: 2.96 (-2.94,2.94) {-1.50,0.50}
Total: 16920 W: 2161 L: 2055 D: 12704
Ptnml(0-2): 115, 1498, 5006, 1569, 130

4 Tweak Restricted Piece Bonus 0ae00454ba :

STC 10+0.1 https://tests.stockfishchess.org/tests/view/5e31fefaec661e2e6a340d15 :
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 88328 W: 17060 L: 16997 D: 54271
Ptnml(0-2): 1536, 10446, 20169, 10422, 1581

LTC 60+0.6 https://tests.stockfishchess.org/tests/view/5e32c17aec661e2e6a340d6f :
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 34784 W: 4551 L: 4466 D: 25767
Ptnml(0-2): 255, 3279, 10061, 3345, 262

5 History update for pruned captures 01b6088af3 :

STC 10+0.1 https://tests.stockfishchess.org/tests/view/5e31ff5eec661e2e6a340d1a :
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 29541 W: 5735 L: 5588 D: 18218
Ptnml(0-2): 483, 3445, 6820, 3469, 545

LTC 60+0.6 https://tests.stockfishchess.org/tests/view/5e32c196ec661e2e6a340d75 :
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 22177 W: 2854 L: 2757 D: 16566
Ptnml(0-2): 143, 2005, 6555, 2055, 164

6 Tweak trapped rook penalty 18fc21eba0 :

STC 10+0.1 https://tests.stockfishchess.org/tests/view/5e31ffb1ec661e2e6a340d1c :
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 24476 W: 4727 L: 4569 D: 15180
Ptnml(0-2): 390, 2834, 5659, 2933, 417

LTC 60+0.6 https://tests.stockfishchess.org/tests/view/5e32c19eec661e2e6a340d77 :
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 97332 W: 12492 L: 12466 D: 72374
Ptnml(0-2): 690, 9107, 28738, 9034, 720

All 5 as one simplification :
LTC 60+0.6 https://tests.stockfishchess.org/tests/view/5e334098708b13464ceea330 :
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 7829 W: 1079 L: 964 D: 5786
Ptnml(0-2): 52, 690, 2281, 781, 65

Bench: 5153165
2020-01-31 19:48:44 +01:00
Joost VandeVondele 3b70932b0d Fix compilation on android
Fall back to the default implementation of aligned_ttmem_alloc, which
was introduced as part of 39437f4e55

Fixes  #2524

No functional change.
2020-01-29 07:25:18 +01:00
joergoster a910ba71ee Simplify hashfull calculation.
We can simplify the calculation of the hashfull info by looping over exact 1,000 entries,
and then divide the result by ClusterSize. Somewhat memory accesses, somewhat more accurate.

Passed non-regression LTC
https://tests.stockfishchess.org/tests/view/5e30079dab2d69d58394fd5d
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 30125 W: 3987 L: 3926 D: 22212
Ptnml(0-2): 177, 2504, 9558, 2642, 141

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

No functional change.
2020-01-28 19:25:39 +01:00
Guenther Demetz 71e0b5385e More bonus for bestMoves on past PV nodes
It looks like it is important to keep past PV (ttPv) nodes as close as possible to current PV nodes.
Credits to Mark Tenzer (31m059) & Stefan Geschwentner who first tried ideas on ttPv nodes.

STC:
https://tests.stockfishchess.org/tests/view/5e2ff5efab2d69d58394fd52
LLR: 2.95 (-2.94,2.94) {-1.00,3.00}
Total: 13302 W: 2647 L: 2507 D: 8148
Ptnml(0-2): 237, 1540, 2956, 1632, 260

LTC:
https://tests.stockfishchess.org/tests/view/5e2fff38ab2d69d58394fd55
LLR: 2.95 (-2.94,2.94) {0.00,2.00}
Total: 15797 W: 2137 L: 1960 D: 11700
Ptnml(0-2): 96, 1443, 4628, 1547, 130

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

bench: 5545845
2020-01-28 16:28:56 +01:00
31m059 d878bc8cda Less NMP if the position was previously in PV.
The intention of the patch is to avoid aggressive null move pruning (NMP)
in positions that have previously been found to be important (PV nodes).
If we already do not apply NMP for current PV nodes, it makes sense to apply
it less often for positions that have previously been PV nodes too.

STC:
LLR: 2.96 (-2.94,2.94) {-1.00,3.00}
Total: 14959 W: 2921 L: 2782 D: 9256
Ptnml(0-2): 254, 1679, 3493, 1762, 282
http://tests.stockfishchess.org/tests/view/5e2f6637ab2d69d58394fcfd

LTC:
LLR: 2.95 (-2.94,2.94) {0.00,2.00}
Total: 6442 W: 899 L: 753 D: 4790
Ptnml(0-2): 42, 549, 1885, 659, 61
http://tests.stockfishchess.org/tests/view/5e2f767bab2d69d58394fd04

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

Bench: 4725546
2020-01-28 10:31:25 +01:00
Alain SAVARD 1d3efff472 Dynamic Complexity based on psqt
Adjust initiative score by psqt/2 instead of materialScore/2 which simplifies #2516

Passed STC
http://tests.stockfishchess.org/tests/view/5e2e667dab2d69d58394fc73
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 23198 W: 4506 L: 4353 D: 14339
Ptnml(0-2): 396, 2615, 5380, 2728, 418

Passed LTC
http://tests.stockfishchess.org/tests/view/5e2ed75cab2d69d58394fcbf
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 8519 W: 1179 L: 1062 D: 6278
Ptnml(0-2): 50, 775, 2472, 843, 74

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

Bench:  4684459
2020-01-27 18:14:10 +01:00
Sami Kiminki 39437f4e55 Advise the kernel to use huge pages (Linux)
Align the TT allocation by 2M to make it huge page friendly and advise the
kernel to use huge pages.

Benchmarks on my i7-8700K (6C/12T) box: (3 runs per bench per config)

                    vanilla (nps)               hugepages (nps)              avg
==================================================================================
bench             | 3012490  3024364  3036331   3071052  3067544  3071052    +1.5%
bench 16 12 20    | 19237932 19050166 19085315  19266346 19207025 19548758   +1.1%
bench 16384 12 20 | 18182313 18371581 18336838  19381275 19738012 19620225   +7.0%

On my box, huge pages have a significant perf impact when using a big
hash size. They also speed up TT initialization big time:

                                  vanilla (s)  huge pages (s)  speed-up
=======================================================================
time stockfish bench 16384 1 1  | 5.37         1.48            3.6x

In practice, huge pages with auto-defrag may always be enabled in the
system, in which case this patch has no effect. This
depends on the values in /sys/kernel/mm/transparent_hugepage/enabled
and /sys/kernel/mm/transparent_hugepage/defrag.

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

No functional change
2020-01-27 11:16:10 +01:00
Alain SAVARD 6d0eabd5fe Dynamic complexity
Instead of computing the initiative bonus on the material score + dynamic score
compute it on (material score/2) + dynamic score,

Passed STC
http://tests.stockfishchess.org/tests/view/5e2c4945ab2d69d58394fa8f
LLR: 2.94 (-2.94,2.94) {-1.00,3.00}
Total: 39387 W: 7594 L: 7386 D: 24407
Ptnml(0-2): 658, 4519, 9165, 4649, 697

Passed LTC
http://tests.stockfishchess.org/tests/view/5e2c85ccab2d69d58394faa7
LLR: 2.95 (-2.94,2.94) {0.00,2.00}
Total: 32588 W: 4206 L: 3986 D: 24396
Ptnml(0-2): 244, 2909, 9738, 3111, 253

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

Bench: 4765486
2020-01-27 09:05:55 +01:00
Lolligerhans 0ae00454ba Tweak RestrictedPiece bonus
Double the "RestrictedPiece" bonus for restricted moves targeting
occupied squares.

STC LLR: 3.58 (-2.94,2.94) {-1.00,3.00}
    Total: 25504 W: 4887 L: 4697 D: 15920
    Ptnml(0-2): 387, 2935, 5947, 3051, 422
    https://tests.stockfishchess.org/tests/view/5e2aa15dab2d69d58394f94d

LTC LLR: 2.94 (-2.94,2.94) {0.00,2.00}
    Total: 28572 W: 3826 L: 3621 D: 21125
    Ptnml(0-2): 224, 2609, 8403, 2791, 239
    https://tests.stockfishchess.org/tests/view/5e2ae7f4ab2d69d58394f9a6

Bench: 4719086
2020-01-25 09:44:09 +01:00
Stefan Geschwentner 01b6088af3 History update for pruned captures
Use a SEE pruned capture move for history updates: this patch collects
pruned capture moves also in the failed captures list, so that they get
an update in capture history.

STC:
LLR: 2.95 (-2.94,2.94) {-1.00,3.00}
Total: 11124 W: 2222 L: 2089 D: 6813
Ptnml(0-2): 186, 1280, 2506, 1381, 200
http://tests.stockfishchess.org/tests/view/5e28995fc3b97aa0d75bc294

LTC:
LLR: 2.94 (-2.94,2.94) {0.00,2.00}
Total: 25552 W: 3418 L: 3211 D: 18923
Ptnml(0-2): 168, 2354, 7538, 2490, 200
http://tests.stockfishchess.org/tests/view/5e2943734744cfa4d6af415b

Closes https://github.com/official-stockfish/Stockfish/pull/2511

Bench: 4810202
2020-01-23 19:12:48 +01:00
Vizvezdenec 18fc21eba0 Tweak trapped rook penalty
This patch greatly increases the endgame penalty for having a trapped rook.
Idea was a result of witnessing Stockfish losing some games at CCCC exchanging
pieces in the position with a trapped rook which directly lead to a lost endgame.
This patch should partially fix such behavior making this penalty high even in
deep endgames.

Passed STC
http://tests.stockfishchess.org/tests/view/5e279d7cc3b97aa0d75bc1c4
LLR: 2.94 (-2.94,2.94) {-1.00,3.00}
Total: 8528 W: 1706 L: 1588 D: 5234
Ptnml(0-2): 133, 957, 1985, 1024, 159

Passed LTC
http://tests.stockfishchess.org/tests/view/5e27aee4c3b97aa0d75bc1e1
LLR: 2.95 (-2.94,2.94) {0.00,2.00}
Total: 88713 W: 11520 L: 11130 D: 66063
Ptnml(0-2): 646, 8170, 26342, 8492, 676

Closes https://github.com/official-stockfish/Stockfish/pull/2510

Bench: 4964462

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

Comment by Malcolm Campbell:

Congrats! I think this might be a common pattern - scores that seem to mainly apply
to the midgame are often better with a similar (or at least fairly big) endgame value
as well. Maybe there are others eval parameters we can tweak like this...
2020-01-23 19:03:25 +01:00
Stefan Geschwentner 56e698ef83 Less reduction for escape moves at ttPv nodes
At expected PV nodes or nodes which marked as PV node in the hash table,
reduce escape moves even one ply less.

STC:
LLR: 2.94 (-2.94,2.94) {-1.00,3.00}
Total: 31795 W: 6140 L: 5953 D: 19702
Ptnml(0-2): 525, 3625, 7455, 3695, 583
http://tests.stockfishchess.org/tests/view/5e25d77fc3b97aa0d75bc013

LTC:
LLR: 2.94 (-2.94,2.94) {0.00,2.00}
Total: 43975 W: 5708 L: 5454 D: 32813
Ptnml(0-2): 314, 4012, 13070, 4242, 325
http://tests.stockfishchess.org/tests/view/5e2618c1c3b97aa0d75bc03c

Closes https://github.com/official-stockfish/Stockfish/pull/2505

Bench: 4475583
2020-01-23 18:53:50 +01:00
Guenther Demetz f63d112c71 Use (strict) greater-than-operator for 'improving'
Currently on a normal bench run in ~0,7% of cases 'improving' is set to
true although the static eval isn't improving at all, just keeping
equal. It looks like the strict gt-operator is more appropriate here,
since it returns to 'improving' its literal meaning without sideffects.

STC {-1.00,3.00} failed yellow:
https://tests.stockfishchess.org/tests/view/5e1ec38c8fd5f550e4ae1c28
LLR: -2.93 (-2.94,2.94) {-1.00,3.00}
Total: 53155 W: 10170 L: 10109 D: 32876
Ptnml(0-2): 863, 6282, 12251, 6283, 892

non-regression LTC passed:
https://tests.stockfishchess.org/tests/view/5e1f1c0d8fd5f550e4ae1c41
LLR: 2.98 (-2.94,2.94) {-1.50,0.50}
Total: 23961 W: 3114 L: 3018 D: 17829
Ptnml(0-2): 163, 2220, 7114, 2298, 170

CLoses https://github.com/official-stockfish/Stockfish/pull/2496

bench: 4561386
2020-01-23 18:43:47 +01:00
Chess13234 7ed817d7e4 Minor fixes for misc.cpp
Fixes conflict with tune.h STRINGIFY macro.

No functional change
2020-01-23 18:33:01 +01:00
protonspring 6f1013794c Use a std::bitset for KPKBitbase
This is a non-functional simplification. Looks like std::bitset works good
for the KPKBitbase. Thanks for Jorg Oster for helping get the speed up
(the [] accessor is faster than test()).

Speed testing: 10k calls to probe:
  master 9.8 sec
  patch 9.8 sec.

STC
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 100154 W: 19025 L: 18992 D: 62137
Ptnml(0-2): 1397, 11376, 24572, 11254, 1473
http://tests.stockfishchess.org/tests/view/5e21e601346e35ac603b7d2b

Closes https://github.com/official-stockfish/Stockfish/pull/2502

No functional change
2020-01-23 18:20:11 +01:00
protonspring f3c83ed46c Determine opposite colors mathematically
This is a non-functional speed-up: master has to access SquareBB twice while this patch
determines opposite_colors just using the values of the squares. It doesn't seem to change
the overall speed of bench, but calling opposite_colors(...) 10 Million times:

master: 39.4 seconds
patch: 11.4 seconds.

The only data point I have (other than my own tests), is a quite old failed STC test:
LLR: -2.93 (-2.94,2.94) [-1.50,4.50]
Total: 24308 W: 5331 L: 5330 D: 13647
Ptnml(0-2): 315, 2577, 6326, 2623, 289
http://tests.stockfishchess.org/tests/view/5e010256c13ac2425c4a9a67

Closes https://github.com/official-stockfish/Stockfish/pull/2498

No functional change
2020-01-23 17:59:03 +01:00
protonspring 75dfdeac11 Simplify KPK classify
This is a non-functional simplification. If we use the "side to move" of the entry
instead of the template, one of the classify methods goes away. Furthermore, I've
resolved  the colors in some of the statements (we're already assuming direction
using NORTH), and used stm (side to move) instead of "us," since this is much clearer
to me.

This is not tested because it is non-functional, only applies building the bitbase
and there are no changes to the binary (on my machine).

Closes https://github.com/official-stockfish/Stockfish/pull/2485

No functional change
2020-01-23 17:49:10 +01:00
protonspring 7a7bcd6359 Simplify signature of remove_piece()
This is a non-functional simplification. Instead of passing the piece type
for remove_piece, we can rely on the board. The only exception is en-passant
which must be explicitly set because the destination square for the capture
is not the same as the piece to remove.

Verified also in the Chess960 castling case by running a couple of perft, see
the pull request discussion: https://github.com/official-stockfish/Stockfish/pull/2460

STC
LLR: 2.94 (-2.94,2.94) [-3.00,1.00]
Total: 18624 W: 4147 L: 4070 D: 10407
Ptnml(0-2): 223, 1933, 4945, 1938, 260
http://tests.stockfishchess.org/tests/view/5dfeaa93e70446e17e451163

No functional change
2020-01-23 17:31:45 +01:00
Stéphane Nicolet bcf9282844 Restore development version
No functional change
2020-01-23 17:17:26 +01:00
66 changed files with 6242 additions and 2242 deletions
+12
View File
@@ -0,0 +1,12 @@
# Files from build
**/*.o
**/*.s
src/.depend
# Built binary
src/stockfish*
src/-lstdc++.res
# Neural network for the NNUE evaluation
**/*.nnue
+44 -16
View File
@@ -1,5 +1,5 @@
language: cpp
dist: xenial
dist: bionic
matrix:
include:
@@ -7,7 +7,6 @@ matrix:
compiler: gcc
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-8', 'g++-8-multilib', 'g++-multilib', 'valgrind', 'expect', 'curl']
env:
- COMPILER=g++-8
@@ -17,23 +16,23 @@ matrix:
compiler: clang
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-xenial-6.0']
packages: ['clang-6.0', 'llvm-6.0-dev', 'g++-multilib', 'valgrind', 'expect', 'curl']
packages: ['clang-10', 'llvm-10-dev', 'g++-multilib', 'valgrind', 'expect', 'curl']
env:
- COMPILER=clang++-6.0
- COMPILER=clang++-10
- COMP=clang
- LDFLAGS=-fuse-ld=lld
- os: osx
osx_image: xcode12
compiler: gcc
env:
- COMPILER=g++
- COMP=gcc
- os: osx
osx_image: xcode12
compiler: clang
env:
- COMPILER=clang++ V='Apple LLVM 9.4.1' # Apple LLVM version 9.1.0 (clang-902.0.39.2)
- COMPILER=clang++
- COMP=clang
branches:
@@ -44,30 +43,59 @@ before_script:
- cd src
script:
# Download net
- make net
# Obtain bench reference from git log
- git log HEAD | grep "\b[Bb]ench[ :]\+[0-9]\{7\}" | head -n 1 | sed "s/[^0-9]*\([0-9]*\).*/\1/g" > git_sig
- export benchref=$(cat git_sig)
- echo "Reference bench:" $benchref
#
# Compiler version string
- $COMPILER -v
# test help target
- make help
# Verify bench number against various builds
- export CXXFLAGS=-Werror
- make clean && make -j2 ARCH=x86-64 optimize=no debug=yes build && ../tests/signature.sh $benchref
- make clean && make -j2 ARCH=x86-32 optimize=no debug=yes build && ../tests/signature.sh $benchref
- make clean && make -j2 ARCH=x86-32 build && ../tests/signature.sh $benchref
- export CXXFLAGS="-Werror -D_GLIBCXX_DEBUG"
- make clean && make -j2 ARCH=x86-64-modern optimize=no debug=yes build && ../tests/signature.sh $benchref
- export CXXFLAGS="-Werror"
- make clean && make -j2 ARCH=x86-64-modern build && ../tests/signature.sh $benchref
- make clean && make -j2 ARCH=x86-64-ssse3 build && ../tests/signature.sh $benchref
- make clean && make -j2 ARCH=x86-64-sse3-popcnt build && ../tests/signature.sh $benchref
- make clean && make -j2 ARCH=x86-64 build && ../tests/signature.sh $benchref
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then make clean && make -j2 ARCH=general-64 build && ../tests/signature.sh $benchref; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then make clean && make -j2 ARCH=x86-32 optimize=no debug=yes build && ../tests/signature.sh $benchref; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then make clean && make -j2 ARCH=x86-32-sse41-popcnt build && ../tests/signature.sh $benchref; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then make clean && make -j2 ARCH=x86-32-sse2 build && ../tests/signature.sh $benchref; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then make clean && make -j2 ARCH=x86-32 build && ../tests/signature.sh $benchref; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then make clean && make -j2 ARCH=general-32 build && ../tests/signature.sh $benchref; fi
# workaround: exclude a custom version of llvm+clang, which doesn't find llvm-profdata on ubuntu
- if [[ "$TRAVIS_OS_NAME" != "linux" || "$COMP" == "gcc" ]]; then make clean && make -j2 ARCH=x86-64-modern profile-build && ../tests/signature.sh $benchref; fi
# compile only for some more advanced architectures (might not run in travis)
- make clean && make -j2 ARCH=x86-64-avx2 build
- make clean && make -j2 ARCH=x86-64-bmi2 build
- make clean && make -j2 ARCH=x86-64-avx512 build
- make clean && make -j2 ARCH=x86-64-vnni512 build
- make clean && make -j2 ARCH=x86-64-vnni256 build
#
# Check perft and reproducible search
- make clean && make -j2 ARCH=x86-64-modern build
- ../tests/perft.sh
- ../tests/reprosearch.sh
#
# Valgrind
#
- export CXXFLAGS="-O1 -fno-inline"
- if [ -x "$(command -v valgrind )" ]; then make clean && make -j2 ARCH=x86-64 debug=yes optimize=no build > /dev/null && ../tests/instrumented.sh --valgrind; fi
- if [ -x "$(command -v valgrind )" ]; then make clean && make -j2 ARCH=x86-64-modern debug=yes optimize=no build > /dev/null && ../tests/instrumented.sh --valgrind; fi
- if [ -x "$(command -v valgrind )" ]; then ../tests/instrumented.sh --valgrind-thread; fi
#
# Sanitizer
#
# Use g++-8 as a proxy for having sanitizers, might need revision as they become available for more recent versions of clang/gcc
- if [[ "$COMPILER" == "g++-8" ]]; then make clean && make -j2 ARCH=x86-64 sanitize=undefined optimize=no debug=yes build > /dev/null && ../tests/instrumented.sh --sanitizer-undefined; fi
- if [[ "$COMPILER" == "g++-8" ]]; then make clean && make -j2 ARCH=x86-64 sanitize=thread optimize=no debug=yes build > /dev/null && ../tests/instrumented.sh --sanitizer-thread; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then make clean && make -j2 ARCH=x86-64-modern sanitize=undefined optimize=no debug=yes build > /dev/null && ../tests/instrumented.sh --sanitizer-undefined; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then make clean && make -j2 ARCH=x86-64-modern sanitize=thread optimize=no debug=yes build > /dev/null && ../tests/instrumented.sh --sanitizer-thread; fi
+36 -7
View File
@@ -1,10 +1,17 @@
# List of authors for Stockfish, as of January 7, 2020
# List of authors for Stockfish, as of August 4, 2020
# Founders of the Stockfish project and fishtest infrastructure
Tord Romstad (romstad)
Marco Costalba (mcostalba)
Joona Kiiski (zamar)
Gary Linscott (glinscott)
# Authors and inventors of NNUE, training, NNUE port
Yu Nasu (ynasu87)
Motohiro Isozaki (yaneurao)
Hisayori Noda (nodchip)
# all other authors of the code in alphabetical order
Aditya (absimaldata)
Adrian Petrescu (apetresc)
Ajith Chandy Jose (ajithcj)
@@ -12,6 +19,7 @@ Alain Savard (Rocky640)
Alayan Feh (Alayan-stk-2)
Alexander Kure
Alexander Pagel (Lolligerhans)
Alfredo Menezes (lonfom169)
Ali AlZhrani (Cooffe)
Andrew Grant (AndyGrant)
Andrey Neporada (nepal)
@@ -25,29 +33,38 @@ Bill Henry (VoyagerOne)
Bojun Guo (noobpwnftw, Nooby)
braich
Brian Sheppard (SapphireBrand, briansheppard-toast)
Bruno de Melo Costa (BM123499)
Bryan Cross (crossbr)
candirufish
Chess13234
Chris Cain (ceebo)
Dale Weiler (graphitemaster)
Dan Schmidt (dfannius)
Daniel Axtens (daxtens)
Daniel Dugovic (ddugovic)
Dariusz Orzechowski
Dariusz Orzechowski (dorzechowski)
David Zar
Daylen Yang (daylen)
Deshawn Mohan-Smith (GoldenRare)
Dieter Dobbelaere (ddobbelaere)
DiscanX
Dominik Schlösser (domschl)
double-beep
Eduardo Cáceres (eduherminio)
Eelco de Groot (KingDefender)
Elvin Liu (solarlight2)
erbsenzaehler
Ernesto Gatti
Linmiao Xu (linrock)
Fabian Beuke (madnight)
Fabian Fichter (ianfab)
Fanael Linithien (Fanael)
fanon
Fauzi Akram Dabat (FauziAkram)
Felix Wittmann
gamander
Gary Heckman (gheckman)
George Sobala (gsobala)
gguliash
Gian-Carlo Pascutto (gcp)
Gontran Lemaire (gonlem)
@@ -69,8 +86,9 @@ Jean Gauthier (OuaisBla)
Jean-Francois Romang (jromang)
Jekaa
Jerry Donald Watson (jerrydonaldwatson)
jjoshua2
Jonathan Calovski (Mysseno)
Jonathan Dumale (SFisGOD)
Jonathan Buladas Dumale (SFisGOD)
Joost VandeVondele (vondele)
Jörg Oster (joergoster)
Joseph Ellis (jhellis3)
@@ -82,6 +100,7 @@ Ken Takusagawa
kinderchocolate
Kiran Panditrao (Krgp)
Kojirion
Krystian Kuzniarek (kuzkry)
Leonardo Ljubičić (ICCF World Champion)
Leonid Pechenik (lp--)
Linus Arver (listx)
@@ -94,8 +113,10 @@ Maciej Żenczykowski (zenczykowski)
Malcolm Campbell (xoto10)
Mark Tenzer (31m059)
marotear
Matt Ginsberg (mattginsberg)
Matthew Lai (matthewlai)
Matthew Sullivan (Matt14916)
Maxim Molchanov (Maxim)
Michael An (man)
Michael Byrne (MichaelB7)
Michael Chaly (Vizvezdenec)
@@ -113,6 +134,9 @@ Nick Pelling (nickpelling)
Nicklas Persson (NicklasPersson)
Niklas Fiekas (niklasf)
Nikolay Kostov (NikolayIT)
Nguyen Pham (nguyenpham)
Norman Schmidt (FireFather)
notruck
Ondrej Mosnáček (WOnder93)
Oskar Werkelin Ahlin
Pablo Vazquez
@@ -122,6 +146,8 @@ Pasquale Pigazzini (ppigazzini)
Patrick Jansen (mibere)
pellanda
Peter Zsifkovits (CoffeeOne)
Praveen Kumar Tummala (praveentml)
Rahul Dsilva (silversolver1)
Ralph Stößer (Ralph Stoesser)
Raminder Singh
renouve
@@ -130,14 +156,17 @@ Richard Lloyd
Rodrigo Exterckötter Tjäder
Ron Britvich (Britvich)
Ronald de Man (syzygy1, syzygy)
rqs
Ryan Schmitt
Ryan Takker
Sami Kiminki (skiminki)
Sebastian Buchwald (UniQP)
Sergei Antonov (saproj)
Sergei Ivanov (svivanov72)
Sergio Vieri (sergiovieri)
sf-x
Shane Booth (shane31)
Shawn Varghese (xXH4CKST3RXx)
Stefan Geschwentner (locutus2)
Stefano Cardanobile (Stefano80)
Steinar Gunderson (sesse)
@@ -147,17 +176,17 @@ thaspel
theo77186
Tom Truscott
Tom Vijlbrief (tomtor)
Tomasz Sobczyk (Sopel97)
Torsten Franz (torfranz, tfranzer)
Tracey Emery (basepr1me)
tttak
Unai Corzo (unaiic)
Uri Blass (uriblass)
Vince Negri (cuddlestmonkey)
zz4032
# Additionally, we acknowledge the authors and maintainers of fishtest,
# an amazing and essential framework for the development of Stockfish!
#
# https://github.com/glinscott/fishtest/blob/master/AUTHORS
+300
View File
@@ -0,0 +1,300 @@
## Overview
[![Build Status](https://travis-ci.org/official-stockfish/Stockfish.svg?branch=master)](https://travis-ci.org/official-stockfish/Stockfish)
[![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](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).
## Files
This distribution of Stockfish consists of the following files:
* Readme.md, the file you are currently reading.
* Copying.txt, a text file containing the GNU General Public License version 3.
* AUTHORS, a text file with the list of authors for the project
* src, 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.
## UCI options
Currently, Stockfish has the following UCI options:
* #### 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).
* #### Contempt
A positive value for contempt favors middle game positions and avoids draws,
effective for the classical evaluation only.
* #### Analysis Contempt
By default, contempt is set to prefer the side to move. Set this option to "White"
or "Black" to analyse with contempt for that side, or "Off" to disable contempt.
* #### 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.
## 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 version and
compiler you used to create your executable. These informations can
be found by typing the following commands in a console:
```
./stockfish compiler
```
## Understanding the code base and participating in the project
Stockfish's improvement over the last couple of years has been a great
community effort. There are a few ways to help contribute to its growth.
### 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 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
Stockfish are explained with a lot of background information.
* [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)
first, where the basics of Stockfish development are explained.
## 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.
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.
For full details, read the copy of the GPL v3 found in the file named
*Copying.txt*.
-210
View File
@@ -1,210 +0,0 @@
## Overview
[![Build Status](https://travis-ci.org/official-stockfish/Stockfish.svg?branch=master)](https://travis-ci.org/official-stockfish/Stockfish)
[![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](https://stockfishchess.org) is a free, powerful UCI chess engine
derived from Glaurung 2.1. It is not a complete chess program and requires a
UCI-compatible 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.
## Files
This distribution of Stockfish consists of the following files:
* Readme.md, the file you are currently reading.
* Copying.txt, a text file containing the GNU General Public License version 3.
* src, a subdirectory containing the full source code, including a Makefile
that can be used to compile Stockfish on Unix-like systems.
## UCI parameters
Currently, Stockfish has the following UCI options:
* #### Debug Log File
Write all communication to and from the engine into a text file.
* #### Contempt
A positive value for contempt favors middle game positions and avoids draws.
* #### Analysis Contempt
By default, contempt is set to prefer the side to move. Set this option to "White"
or "Black" to analyse with contempt for that side, or "Off" to disable contempt.
* #### 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.
* #### 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.
* #### 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.
* #### 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.
* #### 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.
* #### Minimum Thinking Time
Search for at least x ms per move.
* #### 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.
* #### UCI_Chess960
An option handled by your GUI. If true, Stockfish will play Chess960.
* #### UCI_AnalyseMode
An option handled by your GUI.
* #### 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 agressively if you experience too much slowdown
(in terms of nps) due to TB 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).
## What to expect from Syzygybases?
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
that 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 Syzygybases 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 Syzygybases 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.
## Compiling Stockfish yourself from the sources
On Unix-like systems, it should be possible to compile Stockfish
directly from the source code with the included Makefile.
Stockfish has support for 32 or 64-bit CPUs, the hardware POPCNT
instruction, big-endian machines such as Power PC, and other platforms.
In general it is recommended to run `make help` to see a list of make
targets with corresponding descriptions. 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 version and
compiler you used to create your executable. These informations can
be found by typing the following commands in a console:
```
./stockfish
compiler
```
## Understanding the code base and participating in the project
Stockfish's improvement over the last couple of years has been a great
community effort. There are a few ways to help contribute to its growth.
### 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 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
Stockfish are explained with a lot of background information.
* [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 in the [FishCooking](https://groups.google.com/forum/#!forum/fishcooking)
group and 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)
first, where the basics of Stockfish development are explained.
## Terms of use
Stockfish is free, and distributed under the **GNU General Public License version 3**
(GPL v3). Essentially, this means that 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 web site, 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. If you make any changes to the
source code, these changes must also be made available under the GPL.
For full details, read the copy of the GPL v3 found in the file named
*Copying.txt*.
+187 -152
View File
@@ -1,154 +1,189 @@
Contributors with >10,000 CPU hours as of January 7, 2020
Contributors to Fishtest with >10,000 CPU hours, as of Feb 15, 2021.
Thank you!
Username CPU Hours Games played
--------------------------------------------------
noobpwnftw 9305707 695548021
mlang 780050 61648867
dew 621626 43921547
mibere 524702 42238645
crunchy 354587 27344275
cw 354495 27274181
fastgm 332801 22804359
JojoM 295750 20437451
CSU_Dynasty 262015 21828122
Fisherman 232181 18939229
ctoks 218866 17622052
glinscott 201989 13780820
tvijlbrief 201204 15337115
velislav 188630 14348485
gvreuls 187164 15149976
bking_US 180289 11876016
nordlandia 172076 13467830
leszek 157152 11443978
Thanar 148021 12365359
spams 141975 10319326
drabel 138073 11121749
vdv 137850 9394330
mgrabiak 133578 10454324
TueRens 132485 10878471
bcross 129683 11557084
marrco 126078 9356740
sqrt2 125830 9724586
robal 122873 9593418
vdbergh 120766 8926915
malala 115926 8002293
CoffeeOne 114241 5004100
dsmith 113189 7570238
BrunoBanani 104644 7436849
Data 92328 8220352
mhoram 89333 6695109
davar 87924 7009424
xoto 81094 6869316
ElbertoOne 80899 7023771
grandphish2 78067 6160199
brabos 77212 6186135
psk 75733 5984901
BRAVONE 73875 5054681
sunu 70771 5597972
sterni1971 70605 5590573
MaZePallas 66886 5188978
Vizvezdenec 63708 4967313
nssy 63462 5259388
jromang 61634 4940891
teddybaer 61231 5407666
Pking_cda 60099 5293873
solarlight 57469 5028306
dv8silencer 56913 3883992
tinker 54936 4086118
renouve 49732 3501516
Freja 49543 3733019
robnjr 46972 4053117
rap 46563 3219146
Bobo1239 46036 3817196
ttruscott 45304 3649765
racerschmacer 44881 3975413
finfish 44764 3370515
eva42 41783 3599691
biffhero 40263 3111352
bigpen0r 39817 3291647
mhunt 38871 2691355
ronaldjerum 38820 3240695
Antihistamine 38785 2761312
pb00067 38038 3086320
speedycpu 37591 3003273
rkl 37207 3289580
VoyagerOne 37050 3441673
jbwiebe 35320 2805433
cuistot 34191 2146279
homyur 33927 2850481
manap 32873 2327384
gri 32538 2515779
oryx 31267 2899051
EthanOConnor 30959 2090311
SC 30832 2730764
csnodgrass 29505 2688994
jmdana 29458 2205261
strelock 28219 2067805
jkiiski 27832 1904470
Pyafue 27533 1902349
Garf 27515 2747562
eastorwest 27421 2317535
slakovv 26903 2021889
Prcuvu 24835 2170122
anst 24714 2190091
hyperbolic.tom 24319 2017394
Patrick_G 23687 1801617
Sharaf_DG 22896 1786697
nabildanial 22195 1519409
chriswk 21931 1868317
achambord 21665 1767323
Zirie 20887 1472937
team-oh 20217 1636708
Isidor 20096 1680691
ncfish1 19931 1520927
nesoneg 19875 1463031
Spprtr 19853 1548165
JanErik 19849 1703875
agg177 19478 1395014
SFTUser 19231 1567999
xor12 19017 1680165
sg4032 18431 1641865
rstoesser 18118 1293588
MazeOfGalious 17917 1629593
j3corre 17743 941444
cisco2015 17725 1690126
ianh2105 17706 1632562
dex 17678 1467203
jundery 17194 1115855
iisiraider 17019 1101015
horst.prack 17012 1465656
Adrian.Schmidt123 16563 1281436
purplefishies 16342 1092533
wei 16274 1745989
ville 16144 1384026
eudhan 15712 1283717
OuaisBla 15581 972000
DragonLord 15559 1162790
dju 14716 875569
chris 14479 1487385
0xB00B1ES 14079 1001120
OssumOpossum 13776 1007129
enedene 13460 905279
bpfliegel 13346 884523
Ente 13198 1156722
IgorLeMasson 13087 1147232
jpulman 13000 870599
ako027ako 12775 1173203
Nikolay.IT 12352 1068349
Andrew Grant 12327 895539
joster 12008 950160
AdrianSA 11996 804972
Nesa92 11455 1111993
fatmurphy 11345 853210
Dark_wizzie 11108 1007152
modolief 10869 896470
mschmidt 10757 803401
infinity 10594 727027
mabichito 10524 749391
Thomas A. Anderson 10474 732094
thijsk 10431 719357
Flopzee 10339 894821
crocogoat 10104 1013854
SapphireBrand 10104 969604
stocky 10017 699440
Username CPU Hours Games played
----------------------------------------------------
noobpwnftw 23930906 1560559941
dew 1169948 70333008
mlang 957168 61657446
mibere 703840 46867607
tvijlbrief 517888 33379462
JojoM 515404 30334272
cw 443276 29385549
crunchy 427035 27344275
grandphish2 425794 26347253
fastgm 414133 24519696
gvreuls 377843 24708884
CSU_Dynasty 338718 23030006
Fisherman 326795 21820747
TueRens 313730 19490246
ctoks 298442 20052551
velislav 270519 17355456
bcross 241064 17196165
glinscott 217799 13780820
nordlandia 211692 13484886
bking_US 198894 11876016
drabel 191096 13129722
leszek 189170 11446821
mgrabiak 187153 12013300
robal 181389 11539242
Thanar 179852 12365359
vdv 175274 9889046
spams 157128 10319326
marrco 150292 9401741
sqrt2 147963 9724586
CoffeeOne 137086 5022516
vdbergh 137041 8926915
malala 136182 8002293
mhoram 132780 8398229
xoto 124729 8652088
davar 122092 7960001
dsmith 122059 7570238
Data 113305 8220352
BrunoBanani 112960 7436849
pemo 109598 5036441
Dantist 106768 6431396
MaZePallas 102741 6630419
ElbertoOne 99028 7023771
brabos 92118 6186135
linrock 90903 6708639
psk 89957 5984901
sunu 88614 6020673
sterni1971 86948 5613788
Vizvezdenec 83761 5344740
BRAVONE 81239 5054681
nssy 76497 5259388
cuistot 76366 4370584
racerschmacer 75753 5442626
teddybaer 75125 5407666
Pking_cda 73776 5293873
0x3C33 73133 4670293
jromang 72117 5054915
solarlight 70517 5028306
dv8silencer 70287 3883992
Bobo1239 68515 4652287
manap 66273 4121774
tinker 64321 4268390
robnjr 57262 4053117
Freja 56938 3733019
ttruscott 56010 3680085
rkl 54986 4150767
renouve 53811 3501516
finfish 51360 3370515
eva42 51272 3599691
rap 49985 3219146
pb00067 49727 3298270
amicic 49691 3042481
ronaldjerum 47654 3240695
bigpen0r 47278 3291647
biffhero 46564 3111352
VoyagerOne 45476 3452465
eastorwest 45033 3071805
speedycpu 43842 3003273
jbwiebe 43305 2805433
Antihistamine 41788 2761312
mhunt 41735 2691355
homyur 39893 2850481
gri 39871 2515779
oryx 38282 2944400
Spprtr 38157 2470529
SC 37290 2731014
csnodgrass 36207 2688994
jmdana 36157 2210661
strelock 34716 2074055
Garf 33800 2747562
skiminki 33515 2055584
EthanOConnor 33370 2090311
slakovv 32915 2021889
yurikvelo 32600 2255966
Prcuvu 30377 2170122
manapbk 30326 1770143
anst 30301 2190091
jkiiski 30136 1904470
hyperbolic.tom 29840 2017394
Pyafue 29650 1902349
qurashee 27758 1509620
OuaisBla 27636 1578800
chriswk 26902 1868317
achambord 26582 1767323
Fifis 26376 1776853
Patrick_G 26276 1801617
yorkman 26193 1992080
SFTUser 25182 1675689
nabildanial 24942 1519409
Sharaf_DG 24765 1786697
ncfish1 24411 1520927
agg177 23890 1395014
JanErik 23408 1703875
Isidor 23388 1680691
Norabor 23164 1591830
cisco2015 22895 1762069
Zirie 22542 1472937
team-oh 22272 1636708
MazeOfGalious 21978 1629593
sg4032 21945 1643065
ianh2105 21725 1632562
xor12 21628 1680365
dex 21612 1467203
nesoneg 21494 1463031
jjoshua2 20997 1422689
horst.prack 20878 1465656
0xB00B1ES 20590 1208666
sphinx 20515 1352368
j3corre 20405 941444
Adrian.Schmidt123 20316 1281436
Ente 20017 1432602
wei 19973 1745989
rstoesser 19569 1293588
eudhan 19274 1283717
jundery 18445 1115855
iisiraider 18247 1101015
ville 17883 1384026
chris 17698 1487385
purplefishies 17595 1092533
DMBK 17357 1279152
DragonLord 17014 1162790
dju 16515 929427
IgorLeMasson 16064 1147232
ako027ako 15671 1173203
Nikolay.IT 15154 1068349
Andrew Grant 15114 895539
OssumOpossum 14857 1007129
enedene 14476 905279
bpfliegel 14298 884523
jpulman 13982 870599
joster 13794 950160
Nesa92 13786 1114691
crocogoat 13753 1114622
Hjax 13535 915487
Dark_wizzie 13422 1007152
mpx86 12941 693640
mabichito 12903 749391
thijsk 12886 722107
AdrianSA 12860 804972
Flopzee 12698 894821
fatmurphy 12547 853210
scuzzi 12511 845761
Karby 12429 735880
SapphireBrand 12416 969604
modolief 12386 896470
pgontarz 12151 848794
stocky 11954 699440
mschmidt 11941 803401
infinity 11470 727027
torbjo 11395 729145
Thomas A. Anderson 11372 732094
d64 11263 789184
Maxim 11129 804704
snicolet 11106 869170
MooTheCow 11008 694942
savage84 10965 641068
Rudolphous 10915 741268
Wolfgang 10809 580032
rpngn 10712 688203
basepi 10637 744851
michaelrpg 10409 735127
dzjp 10343 732529
ali-al-zhrani 10324 726502
ols 10259 570669
lbraesch 10252 647825
+24 -7
View File
@@ -4,10 +4,9 @@ clone_depth: 50
branches:
only:
- master
- appveyor
# Operating system (build VM template)
os: Visual Studio 2017
os: Visual Studio 2019
# Build platform, i.e. x86, x64, AnyCPU. This setting is optional.
platform:
@@ -36,8 +35,11 @@ before_build:
$src = $src.Replace("\", "/")
# Build CMakeLists.txt
$t = 'cmake_minimum_required(VERSION 3.8)',
$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})'
@@ -51,13 +53,28 @@ before_build:
$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 15 2017"
If (${env:PLATFORM} -eq 'x64') { $g = $g + ' Win64' }
cmake -G "${g}" .
Write-Host "Generated files for: " $g
$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%
+448 -102
View File
@@ -1,7 +1,5 @@
# Stockfish, a UCI chess playing engine derived from Glaurung 2.1
# Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
# Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
# Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
# 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
@@ -35,10 +33,15 @@ BINDIR = $(PREFIX)/bin
### Built-in benchmark for pgo-builds
PGOBENCH = ./$(EXE) bench
### Object files
OBJS = benchmark.o bitbase.o bitboard.o endgame.o evaluate.o main.o \
material.o misc.o movegen.o movepick.o pawns.o position.o psqt.o \
search.o thread.o timeman.o tt.o uci.o ucioption.o syzygy/tbprobe.o
### Source and object files
SRCS = benchmark.cpp bitbase.cpp bitboard.cpp endgame.cpp evaluate.cpp main.cpp \
material.cpp misc.cpp movegen.cpp movepick.cpp pawns.cpp position.cpp psqt.cpp \
search.cpp thread.cpp timeman.cpp tt.cpp uci.cpp ucioption.cpp tune.cpp syzygy/tbprobe.cpp \
nnue/evaluate_nnue.cpp nnue/features/half_kp.cpp
OBJS = $(notdir $(SRCS:.cpp=.o))
VPATH = syzygy:nnue:nnue/features
### Establish the operating system name
KERNEL = $(shell uname -s)
@@ -50,7 +53,7 @@ endif
### Section 2. High-level Configuration
### ==========================================================================
#
# flag --- Comp switch --- Description
# flag --- Comp switch --- Description
# ----------------------------------------------------------------------------
#
# debug = yes/no --- -DNDEBUG --- Enable/Disable debug mode
@@ -62,93 +65,237 @@ endif
# 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
# sse = yes/no --- -msse --- Use Intel Streaming SIMD Extensions
# pext = yes/no --- -DUSE_PEXT --- Use pext x86_64 asm-instruction
# sse = yes/no --- -msse --- Use Intel Streaming SIMD Extensions
# mmx = yes/no --- -mmmx --- Use Intel MMX instructions
# sse2 = yes/no --- -msse2 --- Use Intel Streaming SIMD Extensions 2
# ssse3 = yes/no --- -mssse3 --- Use Intel Supplemental Streaming SIMD Extensions 3
# sse41 = yes/no --- -msse4.1 --- Use Intel Streaming SIMD Extensions 4.1
# avx2 = yes/no --- -mavx2 --- Use Intel Advanced Vector Extensions 2
# avx512 = yes/no --- -mavx512bw --- Use Intel Advanced Vector Extensions 512
# vnni256 = yes/no --- -mavx512vnni --- Use Intel Vector Neural Network Instructions 256
# vnni512 = yes/no --- -mavx512vnni --- Use Intel Vector Neural Network Instructions 512
# neon = yes/no --- -DUSE_NEON --- Use ARM SIMD architecture
#
# Note that Makefile is space sensitive, so when adding new architectures
# or modifying existing flags, you have to make sure there are no extra spaces
# at the end of the line for flag values.
### 2.1. General and architecture defaults
ifeq ($(ARCH),)
ARCH = x86-64-modern
help_skip_sanity = yes
endif
# explicitly check for the list of supported architectures (as listed with make help),
# the user can override with `make ARCH=x86-32-vnni256 SUPPORTED_ARCH=true`
ifeq ($(ARCH), $(filter $(ARCH), \
x86-64-vnni512 x86-64-vnni256 x86-64-avx512 x86-64-bmi2 x86-64-avx2 \
x86-64-sse41-popcnt x86-64-modern x86-64-ssse3 x86-64-sse3-popcnt \
x86-64 x86-32-sse41-popcnt x86-32-sse2 x86-32 ppc-64 ppc-32 \
armv7 armv7-neon armv8 apple-silicon general-64 general-32))
SUPPORTED_ARCH=true
else
SUPPORTED_ARCH=false
endif
optimize = yes
debug = no
sanitize = no
bits = 32
bits = 64
prefetch = no
popcnt = no
sse = no
pext = no
sse = no
mmx = no
sse2 = no
ssse3 = no
sse41 = no
avx2 = no
avx512 = no
vnni256 = no
vnni512 = no
neon = no
STRIP = strip
### 2.2 Architecture specific
ifeq ($(findstring x86,$(ARCH)),x86)
# x86-32/64
ifeq ($(findstring x86-32,$(ARCH)),x86-32)
arch = i386
bits = 32
sse = yes
mmx = yes
else
arch = x86_64
sse = yes
sse2 = yes
endif
ifeq ($(findstring -sse,$(ARCH)),-sse)
sse = yes
endif
ifeq ($(findstring -popcnt,$(ARCH)),-popcnt)
popcnt = yes
endif
ifeq ($(findstring -mmx,$(ARCH)),-mmx)
mmx = yes
endif
ifeq ($(findstring -sse2,$(ARCH)),-sse2)
sse = yes
sse2 = yes
endif
ifeq ($(findstring -ssse3,$(ARCH)),-ssse3)
sse = yes
sse2 = yes
ssse3 = yes
endif
ifeq ($(findstring -sse41,$(ARCH)),-sse41)
sse = yes
sse2 = yes
ssse3 = yes
sse41 = yes
endif
ifeq ($(findstring -modern,$(ARCH)),-modern)
popcnt = yes
sse = yes
sse2 = yes
ssse3 = yes
sse41 = yes
endif
ifeq ($(findstring -avx2,$(ARCH)),-avx2)
popcnt = yes
sse = yes
sse2 = yes
ssse3 = yes
sse41 = yes
avx2 = yes
endif
ifeq ($(findstring -bmi2,$(ARCH)),-bmi2)
popcnt = yes
sse = yes
sse2 = yes
ssse3 = yes
sse41 = yes
avx2 = yes
pext = yes
endif
ifeq ($(findstring -avx512,$(ARCH)),-avx512)
popcnt = yes
sse = yes
sse2 = yes
ssse3 = yes
sse41 = yes
avx2 = yes
pext = yes
avx512 = yes
endif
ifeq ($(findstring -vnni256,$(ARCH)),-vnni256)
popcnt = yes
sse = yes
sse2 = yes
ssse3 = yes
sse41 = yes
avx2 = yes
pext = yes
vnni256 = yes
endif
ifeq ($(findstring -vnni512,$(ARCH)),-vnni512)
popcnt = yes
sse = yes
sse2 = yes
ssse3 = yes
sse41 = yes
avx2 = yes
pext = yes
avx512 = yes
vnni512 = yes
endif
ifeq ($(sse),yes)
prefetch = yes
endif
# 64-bit pext is not available on x86-32
ifeq ($(bits),32)
pext = no
endif
else
# all other architectures
ifeq ($(ARCH),general-32)
arch = any
endif
ifeq ($(ARCH),x86-32-old)
arch = i386
endif
ifeq ($(ARCH),x86-32)
arch = i386
prefetch = yes
sse = yes
bits = 32
endif
ifeq ($(ARCH),general-64)
arch = any
bits = 64
endif
ifeq ($(ARCH),x86-64)
arch = x86_64
bits = 64
prefetch = yes
sse = yes
endif
ifeq ($(ARCH),x86-64-modern)
arch = x86_64
bits = 64
prefetch = yes
popcnt = yes
sse = yes
endif
ifeq ($(ARCH),x86-64-bmi2)
arch = x86_64
bits = 64
prefetch = yes
popcnt = yes
sse = yes
pext = yes
endif
ifeq ($(ARCH),armv7)
arch = armv7
prefetch = yes
bits = 32
endif
ifeq ($(ARCH),armv7-neon)
arch = armv7
prefetch = yes
popcnt = yes
neon = yes
bits = 32
endif
ifeq ($(ARCH),armv8)
arch = armv8
prefetch = yes
popcnt = yes
neon = yes
endif
ifeq ($(ARCH),apple-silicon)
arch = arm64
prefetch = yes
popcnt = yes
neon = yes
endif
ifeq ($(ARCH),ppc-32)
arch = ppc
bits = 32
endif
ifeq ($(ARCH),ppc-64)
arch = ppc64
bits = 64
popcnt = yes
prefetch = yes
endif
endif
### ==========================================================================
### Section 3. Low-level configuration
### Section 3. Low-level Configuration
### ==========================================================================
### 3.1 Selecting compiler (default = gcc)
CXXFLAGS += -Wall -Wcast-qual -fno-exceptions -std=c++11 $(EXTRACXXFLAGS)
DEPENDFLAGS += -std=c++11
CXXFLAGS += -Wall -Wcast-qual -fno-exceptions -std=c++17 $(EXTRACXXFLAGS)
DEPENDFLAGS += -std=c++17
LDFLAGS += $(EXTRALDFLAGS)
ifeq ($(COMP),)
@@ -160,7 +307,7 @@ ifeq ($(COMP),gcc)
CXX=g++
CXXFLAGS += -pedantic -Wextra -Wshadow
ifeq ($(ARCH),armv7)
ifeq ($(arch),$(filter $(arch),armv7 armv8))
ifeq ($(OS),Android)
CXXFLAGS += -m$(bits)
LDFLAGS += -m$(bits)
@@ -170,6 +317,10 @@ ifeq ($(COMP),gcc)
LDFLAGS += -m$(bits)
endif
ifeq ($(arch),$(filter $(arch),armv7))
LDFLAGS += -latomic
endif
ifneq ($(KERNEL),Darwin)
LDFLAGS += -Wl,--no-as-needed
endif
@@ -213,11 +364,13 @@ ifeq ($(COMP),clang)
ifneq ($(KERNEL),Darwin)
ifneq ($(KERNEL),OpenBSD)
ifneq ($(KERNEL),FreeBSD)
LDFLAGS += -latomic
endif
endif
endif
ifeq ($(ARCH),armv7)
ifeq ($(arch),$(filter $(arch),armv7 armv8))
ifeq ($(OS),Android)
CXXFLAGS += -m$(bits)
LDFLAGS += -m$(bits)
@@ -228,23 +381,40 @@ ifeq ($(COMP),clang)
endif
endif
ifeq ($(KERNEL),Darwin)
CXXFLAGS += -arch $(arch) -mmacosx-version-min=10.14
LDFLAGS += -arch $(arch) -mmacosx-version-min=10.14
XCRUN = xcrun
endif
# To cross-compile for Android, NDK version r21 or later is recommended.
# In earlier NDK versions, you'll need to pass -fno-addrsig if using GNU binutils.
# Currently we don't know how to make PGO builds with the NDK yet.
ifeq ($(COMP),ndk)
CXXFLAGS += -stdlib=libc++ -fPIE
comp=clang
ifeq ($(arch),armv7)
CXX=armv7a-linux-androideabi16-clang++
CXXFLAGS += -mthumb -march=armv7-a -mfloat-abi=softfp -mfpu=neon
STRIP=arm-linux-androideabi-strip
endif
ifeq ($(arch),armv8)
CXX=aarch64-linux-android21-clang++
STRIP=aarch64-linux-android-strip
endif
LDFLAGS += -static-libstdc++ -pie -lm -latomic
endif
ifeq ($(comp),icc)
profile_make = icc-profile-make
profile_use = icc-profile-use
else
ifeq ($(comp),clang)
else ifeq ($(comp),clang)
profile_make = clang-profile-make
profile_use = clang-profile-use
else
profile_make = gcc-profile-make
profile_use = gcc-profile-use
endif
endif
ifeq ($(KERNEL),Darwin)
CXXFLAGS += -arch $(arch) -mmacosx-version-min=10.9
LDFLAGS += -arch $(arch) -mmacosx-version-min=10.9
endif
### Travis CI script uses COMPILER to overwrite CXX
ifdef COMPILER
@@ -256,13 +426,26 @@ ifdef COMPCXX
CXX=$(COMPCXX)
endif
### Sometimes gcc is really clang
ifeq ($(COMP),gcc)
gccversion = $(shell $(CXX) --version)
gccisclang = $(findstring clang,$(gccversion))
ifneq ($(gccisclang),)
profile_make = clang-profile-make
profile_use = clang-profile-use
endif
endif
### On mingw use Windows threads, otherwise POSIX
ifneq ($(comp),mingw)
CXXFLAGS += -DUSE_PTHREADS
# On Android Bionic's C library comes with its own pthread implementation bundled in
ifneq ($(OS),Android)
# Haiku has pthreads in its libroot, so only link it in on other platforms
ifneq ($(KERNEL),Haiku)
LDFLAGS += -lpthread
ifneq ($(COMP),ndk)
LDFLAGS += -lpthread
endif
endif
endif
endif
@@ -276,8 +459,8 @@ endif
### 3.2.2 Debugging with undefined behavior sanitizers
ifneq ($(sanitize),no)
CXXFLAGS += -g3 -fsanitize=$(sanitize) -fuse-ld=gold
LDFLAGS += -fsanitize=$(sanitize) -fuse-ld=gold
CXXFLAGS += -g3 -fsanitize=$(sanitize)
LDFLAGS += -fsanitize=$(sanitize)
endif
### 3.3 Optimization
@@ -296,6 +479,10 @@ ifeq ($(optimize),yes)
CXXFLAGS += -mdynamic-no-pic
endif
endif
ifeq ($(comp),clang)
CXXFLAGS += -fexperimental-new-pass-manager
endif
endif
### 3.4 Bits
@@ -307,7 +494,6 @@ endif
ifeq ($(prefetch),yes)
ifeq ($(sse),yes)
CXXFLAGS += -msse
DEPENDFLAGS += -msse
endif
else
CXXFLAGS += -DNO_PREFETCH
@@ -315,7 +501,7 @@ endif
### 3.6 popcnt
ifeq ($(popcnt),yes)
ifeq ($(arch),ppc64)
ifeq ($(arch),$(filter $(arch),ppc64 armv7 armv8 arm64))
CXXFLAGS += -DUSE_POPCNT
else ifeq ($(comp),icc)
CXXFLAGS += -msse3 -DUSE_POPCNT
@@ -324,28 +510,121 @@ ifeq ($(popcnt),yes)
endif
endif
ifeq ($(avx2),yes)
CXXFLAGS += -DUSE_AVX2
ifeq ($(comp),$(filter $(comp),gcc clang mingw))
CXXFLAGS += -mavx2
endif
endif
ifeq ($(avx512),yes)
CXXFLAGS += -DUSE_AVX512
ifeq ($(comp),$(filter $(comp),gcc clang mingw))
CXXFLAGS += -mavx512f -mavx512bw
endif
endif
ifeq ($(vnni256),yes)
CXXFLAGS += -DUSE_VNNI
ifeq ($(comp),$(filter $(comp),gcc clang mingw))
CXXFLAGS += -mavx512f -mavx512bw -mavx512vnni -mavx512dq -mavx512vl -mprefer-vector-width=256
endif
endif
ifeq ($(vnni512),yes)
CXXFLAGS += -DUSE_VNNI
ifeq ($(comp),$(filter $(comp),gcc clang mingw))
CXXFLAGS += -mavx512vnni -mavx512dq -mavx512vl
endif
endif
ifeq ($(sse41),yes)
CXXFLAGS += -DUSE_SSE41
ifeq ($(comp),$(filter $(comp),gcc clang mingw))
CXXFLAGS += -msse4.1
endif
endif
ifeq ($(ssse3),yes)
CXXFLAGS += -DUSE_SSSE3
ifeq ($(comp),$(filter $(comp),gcc clang mingw))
CXXFLAGS += -mssse3
endif
endif
ifeq ($(sse2),yes)
CXXFLAGS += -DUSE_SSE2
ifeq ($(comp),$(filter $(comp),gcc clang mingw))
CXXFLAGS += -msse2
endif
endif
ifeq ($(mmx),yes)
CXXFLAGS += -DUSE_MMX
ifeq ($(comp),$(filter $(comp),gcc clang mingw))
CXXFLAGS += -mmmx
endif
endif
ifeq ($(neon),yes)
CXXFLAGS += -DUSE_NEON
ifeq ($(KERNEL),Linux)
ifneq ($(COMP),ndk)
ifneq ($(arch),armv8)
CXXFLAGS += -mfpu=neon
endif
endif
endif
endif
### 3.7 pext
ifeq ($(pext),yes)
CXXFLAGS += -DUSE_PEXT
ifeq ($(comp),$(filter $(comp),gcc clang mingw))
CXXFLAGS += -msse4 -mbmi2
CXXFLAGS += -mbmi2
endif
endif
### 3.8 Link Time Optimization, it works since gcc 4.5 but not on mingw under Windows.
### 3.8 Link Time Optimization
### This is a mix of compile and link time options because the lto link phase
### needs access to the optimization flags.
ifeq ($(optimize),yes)
ifeq ($(debug), no)
ifeq ($(comp),$(filter $(comp),gcc clang))
ifeq ($(comp),clang)
CXXFLAGS += -flto
ifneq ($(findstring MINGW,$(KERNEL)),)
CXXFLAGS += -fuse-ld=lld
else ifneq ($(findstring MSYS,$(KERNEL)),)
CXXFLAGS += -fuse-ld=lld
endif
LDFLAGS += $(CXXFLAGS)
# GCC and CLANG use different methods for parallelizing LTO and CLANG pretends to be
# GCC on some systems.
else ifeq ($(comp),gcc)
ifeq ($(gccisclang),)
CXXFLAGS += -flto
LDFLAGS += $(CXXFLAGS) -flto=jobserver
ifneq ($(findstring MINGW,$(KERNEL)),)
LDFLAGS += -save-temps
else ifneq ($(findstring MSYS,$(KERNEL)),)
LDFLAGS += -save-temps
endif
else
CXXFLAGS += -flto
LDFLAGS += $(CXXFLAGS)
endif
ifeq ($(comp),mingw)
# To use LTO and static linking on windows, the tool chain requires a recent gcc:
# gcc version 10.1 in msys2 or TDM-GCC version 9.2 are known to work, older might not.
# So, only enable it for a cross from Linux by default.
else ifeq ($(comp),mingw)
ifeq ($(KERNEL),Linux)
ifneq ($(arch),i386)
CXXFLAGS += -flto
LDFLAGS += $(CXXFLAGS)
LDFLAGS += $(CXXFLAGS) -flto=jobserver
endif
endif
endif
endif
@@ -358,10 +637,10 @@ ifeq ($(OS), Android)
LDFLAGS += -fPIE -pie
endif
### ==========================================================================
### Section 4. Public Targets
### ==========================================================================
### ==========================================================================
### Section 4. Public targets
### ==========================================================================
help:
@echo ""
@@ -371,22 +650,35 @@ help:
@echo ""
@echo "Supported targets:"
@echo ""
@echo "help > Display architecture details"
@echo "build > Standard build"
@echo "profile-build > PGO build"
@echo "net > Download the default nnue net"
@echo "profile-build > Faster build (with profile-guided optimization)"
@echo "strip > Strip executable"
@echo "install > Install executable"
@echo "clean > Clean up"
@echo ""
@echo "Supported archs:"
@echo ""
@echo "x86-64-bmi2 > x86 64-bit with pext support (also enables SSE4)"
@echo "x86-64-modern > x86 64-bit with popcnt support (also enables SSE3)"
@echo "x86-64 > x86 64-bit generic"
@echo "x86-32 > x86 32-bit (also enables SSE)"
@echo "x86-32-old > x86 32-bit fall back for old hardware"
@echo "x86-64-vnni512 > x86 64-bit with vnni support 512bit wide"
@echo "x86-64-vnni256 > x86 64-bit with vnni support 256bit wide"
@echo "x86-64-avx512 > x86 64-bit with avx512 support"
@echo "x86-64-bmi2 > x86 64-bit with bmi2 support"
@echo "x86-64-avx2 > x86 64-bit with avx2 support"
@echo "x86-64-sse41-popcnt > x86 64-bit with sse41 and popcnt support"
@echo "x86-64-modern > common modern CPU, currently x86-64-sse41-popcnt"
@echo "x86-64-ssse3 > x86 64-bit with ssse3 support"
@echo "x86-64-sse3-popcnt > x86 64-bit with sse3 and popcnt support"
@echo "x86-64 > x86 64-bit generic (with sse2 support)"
@echo "x86-32-sse41-popcnt > x86 32-bit with sse41 and popcnt support"
@echo "x86-32-sse2 > x86 32-bit with sse2 support"
@echo "x86-32 > x86 32-bit generic (with mmx and sse support)"
@echo "ppc-64 > PPC 64-bit"
@echo "ppc-32 > PPC 32-bit"
@echo "armv7 > ARMv7 32-bit"
@echo "armv7-neon > ARMv7 32-bit with popcnt and neon"
@echo "armv8 > ARMv8 64-bit with popcnt and neon"
@echo "apple-silicon > Apple silicon ARM64"
@echo "general-64 > unspecified 64-bit"
@echo "general-32 > unspecified 32-bit"
@echo ""
@@ -396,27 +688,37 @@ help:
@echo "mingw > Gnu compiler with MinGW under Windows"
@echo "clang > LLVM Clang compiler"
@echo "icc > Intel compiler"
@echo "ndk > Google NDK to cross-compile for Android"
@echo ""
@echo "Simple examples. If you don't know what to do, you likely want to run: "
@echo ""
@echo "make build ARCH=x86-64 (This is for 64-bit systems)"
@echo "make build ARCH=x86-32 (This is for 32-bit systems)"
@echo "make -j build ARCH=x86-64 (A portable, slow compile for 64-bit systems)"
@echo "make -j build ARCH=x86-32 (A portable, slow compile for 32-bit systems)"
@echo ""
@echo "Advanced examples, for experienced users: "
@echo "Advanced examples, for experienced users looking for performance: "
@echo ""
@echo "make build ARCH=x86-64 COMP=clang"
@echo "make profile-build ARCH=x86-64-bmi2 COMP=gcc COMPCXX=g++-4.8"
@echo "make help ARCH=x86-64-bmi2"
@echo "make -j profile-build ARCH=x86-64-bmi2 COMP=gcc COMPCXX=g++-9.0"
@echo "make -j build ARCH=x86-64-ssse3 COMP=clang"
@echo ""
@echo "-------------------------------"
ifeq ($(SUPPORTED_ARCH)$(help_skip_sanity), true)
@echo "The selected architecture $(ARCH) will enable the following configuration: "
@$(MAKE) ARCH=$(ARCH) COMP=$(COMP) config-sanity
else
@echo "Specify a supported architecture with the ARCH option for more details"
@echo ""
endif
.PHONY: help build profile-build strip install clean objclean profileclean help \
.PHONY: help build profile-build strip install clean net objclean profileclean \
config-sanity icc-profile-use icc-profile-make gcc-profile-use gcc-profile-make \
clang-profile-use clang-profile-make
build: config-sanity
build: net config-sanity
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) all
profile-build: config-sanity objclean profileclean
profile-build: net config-sanity objclean profileclean
@echo ""
@echo "Step 1/4. Building instrumented executable ..."
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) $(profile_make)
@@ -432,37 +734,61 @@ profile-build: config-sanity objclean profileclean
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) profileclean
strip:
strip $(EXE)
$(STRIP) $(EXE)
install:
-mkdir -p -m 755 $(BINDIR)
-cp $(EXE) $(BINDIR)
-strip $(BINDIR)/$(EXE)
#clean all
# 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
@rm -f $(EXE) *.o ./syzygy/*.o ./nnue/*.o ./nnue/features/*.o
# clean auxiliary profiling files
profileclean:
@rm -rf profdir
@rm -f bench.txt *.gcda ./syzygy/*.gcda *.gcno ./syzygy/*.gcno
@rm -f bench.txt *.gcda *.gcno ./syzygy/*.gcda ./nnue/*.gcda ./nnue/features/*.gcda *.s
@rm -f stockfish.profdata *.profraw
default:
help
### ==========================================================================
### Section 5. Private targets
### Section 5. Private Targets
### ==========================================================================
all: $(EXE) .depend
config-sanity:
config-sanity: net
@echo ""
@echo "Config:"
@echo "debug: '$(debug)'"
@@ -474,8 +800,17 @@ config-sanity:
@echo "os: '$(OS)'"
@echo "prefetch: '$(prefetch)'"
@echo "popcnt: '$(popcnt)'"
@echo "sse: '$(sse)'"
@echo "pext: '$(pext)'"
@echo "sse: '$(sse)'"
@echo "mmx: '$(mmx)'"
@echo "sse2: '$(sse2)'"
@echo "ssse3: '$(ssse3)'"
@echo "sse41: '$(sse41)'"
@echo "avx2: '$(avx2)'"
@echo "avx512: '$(avx512)'"
@echo "vnni256: '$(vnni256)'"
@echo "vnni512: '$(vnni512)'"
@echo "neon: '$(neon)'"
@echo ""
@echo "Flags:"
@echo "CXX: $(CXX)"
@@ -487,17 +822,29 @@ config-sanity:
@test "$(debug)" = "yes" || test "$(debug)" = "no"
@test "$(sanitize)" = "undefined" || test "$(sanitize)" = "thread" || test "$(sanitize)" = "address" || test "$(sanitize)" = "no"
@test "$(optimize)" = "yes" || test "$(optimize)" = "no"
@test "$(SUPPORTED_ARCH)" = "true"
@test "$(arch)" = "any" || test "$(arch)" = "x86_64" || test "$(arch)" = "i386" || \
test "$(arch)" = "ppc64" || test "$(arch)" = "ppc" || test "$(arch)" = "armv7"
test "$(arch)" = "ppc64" || test "$(arch)" = "ppc" || \
test "$(arch)" = "armv7" || test "$(arch)" = "armv8" || test "$(arch)" = "arm64"
@test "$(bits)" = "32" || test "$(bits)" = "64"
@test "$(prefetch)" = "yes" || test "$(prefetch)" = "no"
@test "$(popcnt)" = "yes" || test "$(popcnt)" = "no"
@test "$(sse)" = "yes" || test "$(sse)" = "no"
@test "$(pext)" = "yes" || test "$(pext)" = "no"
@test "$(comp)" = "gcc" || test "$(comp)" = "icc" || test "$(comp)" = "mingw" || test "$(comp)" = "clang"
@test "$(sse)" = "yes" || test "$(sse)" = "no"
@test "$(mmx)" = "yes" || test "$(mmx)" = "no"
@test "$(sse2)" = "yes" || test "$(sse2)" = "no"
@test "$(ssse3)" = "yes" || test "$(ssse3)" = "no"
@test "$(sse41)" = "yes" || test "$(sse41)" = "no"
@test "$(avx2)" = "yes" || test "$(avx2)" = "no"
@test "$(avx512)" = "yes" || test "$(avx512)" = "no"
@test "$(vnni256)" = "yes" || test "$(vnni256)" = "no"
@test "$(vnni512)" = "yes" || test "$(vnni512)" = "no"
@test "$(neon)" = "yes" || test "$(neon)" = "no"
@test "$(comp)" = "gcc" || test "$(comp)" = "icc" || test "$(comp)" = "mingw" || test "$(comp)" = "clang" \
|| test "$(comp)" = "armv7a-linux-androideabi16-clang" || test "$(comp)" = "aarch64-linux-android21-clang"
$(EXE): $(OBJS)
$(CXX) -o $@ $(OBJS) $(LDFLAGS)
+$(CXX) -o $@ $(OBJS) $(LDFLAGS)
clang-profile-make:
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
@@ -506,7 +853,7 @@ clang-profile-make:
all
clang-profile-use:
llvm-profdata merge -output=stockfish.profdata *.profraw
$(XCRUN) llvm-profdata merge -output=stockfish.profdata *.profraw
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
EXTRACXXFLAGS='-fprofile-instr-use=stockfish.profdata' \
EXTRALDFLAGS='-fprofile-use ' \
@@ -536,7 +883,6 @@ icc-profile-use:
all
.depend:
-@$(CXX) $(DEPENDFLAGS) -MM $(OBJS:.o=.cpp) > $@ 2> /dev/null
-@$(CXX) $(DEPENDFLAGS) -MM $(SRCS) > $@ 2> /dev/null
-include .depend
+16 -6
View File
@@ -1,8 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
@@ -65,6 +63,7 @@ const vector<string> Defaults = {
"4rrk1/1p1nq3/p7/2p1P1pp/3P2bp/3Q1Bn1/PPPB4/1K2R1NR w - - 40 21",
"r3k2r/3nnpbp/q2pp1p1/p7/Pp1PPPP1/4BNN1/1P5P/R2Q1RK1 w kq - 0 16",
"3Qb1k1/1r2ppb1/pN1n2q1/Pp1Pp1Pr/4P2p/4BP2/4B1R1/1R5K b - - 11 40",
"4k3/3q1r2/1N2r1b1/3ppN2/2nPP3/1B1R2n1/2R1Q3/3K4 w - - 5 1",
// 5-man positions
"8/8/8/8/5kp1/P7/8/1K1N4 w - - 0 1", // Kc2 - mate
@@ -87,7 +86,7 @@ const vector<string> Defaults = {
// Chess 960
"setoption name UCI_Chess960 value true",
"bbqnnrkr/pppppppp/8/8/8/8/PPPPPPPP/BBQNNRKR w KQkq - 0 1 moves g2g3 d7d5 d2d4 c8h3 c1g5 e8d6 g5e7 f7f6",
"bbqnnrkr/pppppppp/8/8/8/8/PPPPPPPP/BBQNNRKR w HFhf - 0 1 moves g2g3 d7d5 d2d4 c8h3 c1g5 e8d6 g5e7 f7f6",
"setoption name UCI_Chess960 value false"
};
@@ -96,8 +95,9 @@ const vector<string> Defaults = {
/// 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 and the type of the limit:
/// depth, perft, nodes and movetime (in millisecs).
/// 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)
@@ -116,6 +116,7 @@ vector<string> setup_bench(const Position& current, istream& is) {
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;
@@ -147,14 +148,23 @@ vector<string> setup_bench(const Position& current, istream& is) {
list.emplace_back("setoption name Hash value " + ttSize);
list.emplace_back("ucinewgame");
size_t posCounter = 0;
for (const string& fen : fens)
if (fen.find("setoption") != string::npos)
list.emplace_back(fen);
else
{
if (evalType == "classical" || (evalType == "mixed" && posCounter % 2 == 0))
list.emplace_back("setoption name Use NNUE value false");
else if (evalType == "NNUE" || (evalType == "mixed" && posCounter % 2 != 0))
list.emplace_back("setoption name Use NNUE value true");
list.emplace_back("position fen " + fen);
list.emplace_back(go);
++posCounter;
}
list.emplace_back("setoption name Use NNUE value true");
return list;
}
+33 -43
View File
@@ -1,8 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
@@ -19,8 +17,8 @@
*/
#include <cassert>
#include <numeric>
#include <vector>
#include <bitset>
#include "bitboard.h"
#include "types.h"
@@ -31,8 +29,7 @@ namespace {
// 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
// Each uint32_t stores results of 32 positions, one per bit
uint32_t KPKBitbase[MAX_INDEX / 32];
std::bitset<MAX_INDEX> KPKBitbase;
// A KPK bitbase index is an integer in [0, IndexMax] range
//
@@ -43,8 +40,8 @@ namespace {
// 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 us, Square bksq, Square wksq, Square psq) {
return int(wksq) | (bksq << 6) | (us << 12) | (file_of(psq) << 13) | ((RANK_7 - rank_of(psq)) << 15);
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 {
@@ -60,12 +57,9 @@ namespace {
KPKPosition() = default;
explicit KPKPosition(unsigned idx);
operator Result() const { return result; }
Result classify(const std::vector<KPKPosition>& db)
{ return us == WHITE ? classify<WHITE>(db) : classify<BLACK>(db); }
Result classify(const std::vector<KPKPosition>& db);
template<Color Us> Result classify(const std::vector<KPKPosition>& db);
Color us;
Color stm;
Square ksq[COLOR_NB], psq;
Result result;
};
@@ -73,12 +67,11 @@ namespace {
} // namespace
bool Bitbases::probe(Square wksq, Square wpsq, Square bksq, Color us) {
bool Bitbases::probe(Square wksq, Square wpsq, Square bksq, Color stm) {
assert(file_of(wpsq) <= FILE_D);
unsigned idx = index(us, bksq, wksq, wpsq);
return KPKBitbase[idx / 32] & (1 << (idx & 0x1F));
return KPKBitbase[index(stm, bksq, wksq, wpsq)];
}
@@ -97,10 +90,10 @@ void Bitbases::init() {
for (repeat = idx = 0; idx < MAX_INDEX; ++idx)
repeat |= (db[idx] == UNKNOWN && db[idx].classify(db) != UNKNOWN);
// Map 32 results into one KPKBitbase[] entry
// Fill the bitbase with the decisive results
for (idx = 0; idx < MAX_INDEX; ++idx)
if (db[idx] == WIN)
KPKBitbase[idx / 32] |= 1 << (idx & 0x1F);
KPKBitbase.set(idx);
}
@@ -110,28 +103,28 @@ namespace {
ksq[WHITE] = Square((idx >> 0) & 0x3F);
ksq[BLACK] = Square((idx >> 6) & 0x3F);
us = Color ((idx >> 12) & 0x01);
stm = Color ((idx >> 12) & 0x01);
psq = make_square(File((idx >> 13) & 0x3), Rank(RANK_7 - ((idx >> 15) & 0x7)));
// Check if two pieces are on the same square or if a king can be captured
// 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
|| (us == WHITE && (PawnAttacks[WHITE][psq] & ksq[BLACK])))
|| (stm == WHITE && (pawn_attacks_bb(WHITE, psq) & ksq[BLACK])))
result = INVALID;
// Immediate win if a pawn can be promoted without getting captured
else if ( us == WHITE
// Win if the pawn can be promoted without getting captured
else if ( stm == WHITE
&& rank_of(psq) == RANK_7
&& ksq[us] != psq + NORTH
&& ( distance(ksq[~us], psq + NORTH) > 1
|| (PseudoAttacks[KING][ksq[us]] & (psq + NORTH))))
&& ksq[WHITE] != psq + NORTH
&& ( distance(ksq[BLACK], psq + NORTH) > 1
|| (distance(ksq[WHITE], psq + NORTH) == 1)))
result = WIN;
// Immediate draw if it is a stalemate or a king captures undefended pawn
else if ( us == BLACK
&& ( !(PseudoAttacks[KING][ksq[us]] & ~(PseudoAttacks[KING][ksq[~us]] | PawnAttacks[~us][psq]))
|| (PseudoAttacks[KING][ksq[us]] & psq & ~PseudoAttacks[KING][ksq[~us]])))
// 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
@@ -139,7 +132,6 @@ namespace {
result = UNKNOWN;
}
template<Color Us>
Result KPKPosition::classify(const std::vector<KPKPosition>& db) {
// White to move: If one move leads to a position classified as WIN, the result
@@ -151,27 +143,25 @@ namespace {
// 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.
constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
constexpr Result Good = (Us == WHITE ? WIN : DRAW);
constexpr Result Bad = (Us == WHITE ? DRAW : WIN);
const Result Good = (stm == WHITE ? WIN : DRAW);
const Result Bad = (stm == WHITE ? DRAW : WIN);
Result r = INVALID;
Bitboard b = PseudoAttacks[KING][ksq[Us]];
Bitboard b = attacks_bb<KING>(ksq[stm]);
while (b)
r |= Us == WHITE ? db[index(Them, ksq[Them] , pop_lsb(&b), psq)]
: db[index(Them, pop_lsb(&b), ksq[Them] , psq)];
r |= stm == WHITE ? db[index(BLACK, ksq[BLACK] , pop_lsb(&b), psq)]
: db[index(WHITE, pop_lsb(&b), ksq[WHITE], psq)];
if (Us == WHITE)
if (stm == WHITE)
{
if (rank_of(psq) < RANK_7) // Single push
r |= db[index(Them, ksq[Them], ksq[Us], psq + NORTH)];
r |= db[index(BLACK, ksq[BLACK], ksq[WHITE], psq + NORTH)];
if ( rank_of(psq) == RANK_2 // Double push
&& psq + NORTH != ksq[Us]
&& psq + NORTH != ksq[Them])
r |= db[index(Them, ksq[Them], ksq[Us], psq + NORTH + NORTH)];
&& 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;
+40 -49
View File
@@ -1,8 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
@@ -40,7 +38,17 @@ namespace {
Bitboard RookTable[0x19000]; // To store rook attacks
Bitboard BishopTable[0x1480]; // To store bishop attacks
void init_magics(Bitboard table[], Magic magics[], Direction directions[]);
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) {
Square to = Square(s + step);
return is_ok(to) && distance(s, to) <= 2 ? square_bb(to) : Bitboard(0);
}
@@ -56,8 +64,9 @@ const std::string Bitboards::pretty(Bitboard b) {
for (File f = FILE_A; f <= FILE_H; ++f)
s += b & make_square(f, r) ? "| X " : "| ";
s += "|\n+---+---+---+---+---+---+---+---+\n";
s += "| " + std::to_string(1 + r) + "\n+---+---+---+---+---+---+---+---+\n";
}
s += " a b c d e f g h\n";
return s;
}
@@ -69,7 +78,7 @@ const std::string Bitboards::pretty(Bitboard b) {
void Bitboards::init() {
for (unsigned i = 0; i < (1 << 16); ++i)
PopCnt16[i] = std::bitset<16>(i).count();
PopCnt16[i] = uint8_t(std::bitset<16>(i).count());
for (Square s = SQ_A1; s <= SQ_H8; ++s)
SquareBB[s] = (1ULL << s);
@@ -78,36 +87,20 @@ void Bitboards::init() {
for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2)
SquareDistance[s1][s2] = std::max(distance<File>(s1, s2), distance<Rank>(s1, s2));
for (Square s = SQ_A1; s <= SQ_H8; ++s)
{
PawnAttacks[WHITE][s] = pawn_attacks_bb<WHITE>(square_bb(s));
PawnAttacks[BLACK][s] = pawn_attacks_bb<BLACK>(square_bb(s));
}
// Helper returning the target bitboard of a step from a square
auto landing_square_bb = [&](Square s, int step)
{
Square to = Square(s + step);
return is_ok(to) && distance(s, to) <= 2 ? square_bb(to) : Bitboard(0);
};
for (Square s = SQ_A1; s <= SQ_H8; ++s)
{
for (int step : {-9, -8, -7, -1, 1, 7, 8, 9} )
PseudoAttacks[KING][s] |= landing_square_bb(s, step);
for (int step : {-17, -15, -10, -6, 6, 10, 15, 17} )
PseudoAttacks[KNIGHT][s] |= landing_square_bb(s, step);
}
Direction RookDirections[] = { NORTH, EAST, SOUTH, WEST };
Direction BishopDirections[] = { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST };
init_magics(RookTable, RookMagics, RookDirections);
init_magics(BishopTable, BishopMagics, BishopDirections);
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 (int step : {-9, -8, -7, -1, 1, 7, 8, 9} )
PseudoAttacks[KING][s1] |= safe_destination(s1, step);
for (int step : {-17, -15, -10, -6, 6, 10, 15, 17} )
PseudoAttacks[KNIGHT][s1] |= safe_destination(s1, step);
PseudoAttacks[QUEEN][s1] = PseudoAttacks[BISHOP][s1] = attacks_bb<BISHOP>(s1, 0);
PseudoAttacks[QUEEN][s1] |= PseudoAttacks[ ROOK][s1] = attacks_bb< ROOK>(s1, 0);
@@ -121,22 +114,20 @@ void Bitboards::init() {
namespace {
Bitboard sliding_attack(Direction directions[], Square sq, Bitboard occupied) {
Bitboard sliding_attack(PieceType pt, Square sq, Bitboard occupied) {
Bitboard attack = 0;
Bitboard attacks = 0;
Direction RookDirections[4] = {NORTH, SOUTH, EAST, WEST};
Direction BishopDirections[4] = {NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST};
for (int i = 0; i < 4; ++i)
for (Square s = sq + directions[i];
is_ok(s) && distance(s, s - directions[i]) == 1;
s += directions[i])
{
attack |= s;
for (Direction d : (pt == ROOK ? RookDirections : BishopDirections))
{
Square s = sq;
while(safe_destination(s, d) && !(occupied & s))
attacks |= (s += d);
}
if (occupied & s)
break;
}
return attack;
return attacks;
}
@@ -145,7 +136,7 @@ namespace {
// www.chessprogramming.org/Magic_Bitboards. In particular, here we use the so
// called "fancy" approach.
void init_magics(Bitboard table[], Magic magics[], Direction directions[]) {
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 },
@@ -165,7 +156,7 @@ 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(directions, s, 0) & ~edges;
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
@@ -177,7 +168,7 @@ namespace {
b = size = 0;
do {
occupancy[size] = b;
reference[size] = sliding_attack(directions, s, b);
reference[size] = sliding_attack(pt, s, b);
if (HasPext)
m.attacks[pext(b, m.mask)] = reference[size];
+79 -36
View File
@@ -1,8 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
@@ -106,10 +104,11 @@ extern Magic RookMagics[SQUARE_NB];
extern Magic BishopMagics[SQUARE_NB];
inline Bitboard square_bb(Square s) {
assert(s >= SQ_A1 && s <= SQ_H8);
assert(is_ok(s));
return SquareBB[s];
}
/// Overloads of bitwise operators between a Bitboard and a Square for testing
/// whether a given bit is set in a bitboard, and for setting and clearing bits.
@@ -123,38 +122,39 @@ 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, Square s2) { return square_bb(s) | square_bb(s2); }
inline Bitboard operator|(Square s1, Square s2) { return square_bb(s1) | s2; }
constexpr bool more_than_one(Bitboard b) {
return b & (b - 1);
}
inline bool opposite_colors(Square s1, Square s2) {
return bool(DarkSquares & s1) != bool(DarkSquares & s2);
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.
inline Bitboard rank_bb(Rank r) {
constexpr Bitboard rank_bb(Rank r) {
return Rank1BB << (8 * r);
}
inline Bitboard rank_bb(Square s) {
constexpr Bitboard rank_bb(Square s) {
return rank_bb(rank_of(s));
}
inline Bitboard file_bb(File f) {
constexpr Bitboard file_bb(File f) {
return FileABB << f;
}
inline Bitboard file_bb(Square s) {
constexpr Bitboard file_bb(Square s) {
return file_bb(file_of(s));
}
/// shift() moves a bitboard one step along direction D
/// shift() moves a bitboard one or two steps as specified by the direction D
template<Direction D>
constexpr Bitboard shift(Bitboard b) {
@@ -176,6 +176,12 @@ constexpr Bitboard pawn_attacks_bb(Bitboard 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];
}
/// pawn_double_attacks_bb() returns the squares doubly attacked by pawns of the
/// given color from the squares in the given bitboard.
@@ -188,19 +194,33 @@ constexpr Bitboard pawn_double_attacks_bb(Bitboard b) {
/// adjacent_files_bb() returns a bitboard representing all the squares on the
/// adjacent files of the given one.
/// adjacent files of a given square.
inline Bitboard adjacent_files_bb(Square s) {
constexpr Bitboard adjacent_files_bb(Square s) {
return shift<EAST>(file_bb(s)) | shift<WEST>(file_bb(s));
}
/// between_bb() returns squares that are linearly between the given squares
/// If the given squares are not on a same file/rank/diagonal, return 0.
/// line_bb() returns a bitboard representing an entire line (from board edge
/// to board edge) that intersects the two given squares. If the given squares
/// are not on a same file/rank/diagonal, the function returns 0. For instance,
/// line_bb(SQ_C4, SQ_F7) will return a bitboard with the A2-G8 diagonal.
inline Bitboard line_bb(Square s1, Square s2) {
assert(is_ok(s1) && is_ok(s2));
return LineBB[s1][s2];
}
/// between_bb() returns a bitboard representing squares that are linearly
/// between the two given squares (excluding the given squares). If the given
/// squares are not on a same file/rank/diagonal, we return 0. For instance,
/// between_bb(SQ_C4, SQ_F7) will return a bitboard with squares D5 and E6.
inline Bitboard between_bb(Square s1, Square s2) {
return LineBB[s1][s2] & ( (AllSquares << (s1 + (s1 < s2)))
^(AllSquares << (s2 + !(s1 < s2))));
Bitboard b = line_bb(s1, s2) & ((AllSquares << s1) ^ (AllSquares << s2));
return b & (b - 1); //exclude lsb
}
@@ -208,25 +228,25 @@ inline Bitboard between_bb(Square s1, Square s2) {
/// 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.
inline Bitboard forward_ranks_bb(Color c, Square s) {
return c == WHITE ? ~Rank1BB << 8 * (rank_of(s) - RANK_1)
: ~Rank8BB >> 8 * (RANK_8 - rank_of(s));
constexpr Bitboard forward_ranks_bb(Color c, Square s) {
return c == WHITE ? ~Rank1BB << 8 * relative_rank(WHITE, s)
: ~Rank8BB >> 8 * relative_rank(BLACK, s);
}
/// 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.
inline Bitboard forward_file_bb(Color c, Square s) {
constexpr Bitboard forward_file_bb(Color c, Square s) {
return forward_ranks_bb(c, s) & file_bb(s);
}
/// pawn_attack_span() returns a bitboard representing all the squares that can
/// be attacked by a pawn of the given color when it moves along its file,
/// starting from the given square.
/// be attacked by a pawn of the given color when it moves along its file, starting
/// from the given square.
inline Bitboard pawn_attack_span(Color c, Square s) {
constexpr Bitboard pawn_attack_span(Color c, Square s) {
return forward_ranks_bb(c, s) & adjacent_files_bb(s);
}
@@ -234,8 +254,8 @@ inline Bitboard pawn_attack_span(Color c, Square s) {
/// passed_pawn_span() returns a bitboard which can be used to test if a pawn of
/// the given color and on the given square is a passed pawn.
inline Bitboard passed_pawn_span(Color c, Square s) {
return forward_ranks_bb(c, s) & (adjacent_files_bb(s) | file_bb(s));
constexpr Bitboard passed_pawn_span(Color c, Square s) {
return pawn_attack_span(c, s) | forward_file_bb(c, s);
}
@@ -243,7 +263,7 @@ inline Bitboard passed_pawn_span(Color c, Square s) {
/// straight or on a diagonal line.
inline bool aligned(Square s1, Square s2, Square s3) {
return LineBB[s1][s2] & s3;
return line_bb(s1, s2) & s3;
}
@@ -255,23 +275,43 @@ template<> inline int distance<File>(Square x, Square y) { return std::abs(file_
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]; }
template<class T> constexpr const T& clamp(const T& v, const T& lo, const T& hi) {
return v < lo ? lo : v > hi ? hi : v;
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.
template<PieceType Pt>
inline Bitboard attacks_bb(Square s) {
assert((Pt != PAWN) && (is_ok(s)));
return PseudoAttacks[Pt][s];
}
/// attacks_bb() returns a bitboard representing all the squares attacked by a
/// piece of type Pt (bishop or rook) placed on 's'.
/// attacks_bb(Square, Bitboard) returns the attacks by the given piece
/// assuming the board is occupied according to the passed Bitboard.
/// Sliding piece attacks do not continue passed an occupied square.
template<PieceType Pt>
inline Bitboard attacks_bb(Square s, Bitboard occupied) {
const Magic& m = Pt == ROOK ? RookMagics[s] : BishopMagics[s];
return m.attacks[m.index(occupied)];
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];
}
}
inline Bitboard attacks_bb(PieceType pt, Square s, Bitboard occupied) {
assert(pt != PAWN);
assert((pt != PAWN) && (is_ok(s)));
switch (pt)
{
@@ -376,14 +416,17 @@ inline Square msb(Bitboard b) {
/// pop_lsb() finds and clears the least significant bit in a non-zero bitboard
inline Square pop_lsb(Bitboard* b) {
assert(*b);
const Square s = lsb(*b);
*b &= *b - 1;
return s;
}
/// frontmost_sq() returns the most advanced square for the given color
/// 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);
}
+231 -294
View File
@@ -1,8 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
@@ -24,42 +22,25 @@
#include "endgame.h"
#include "movegen.h"
using std::string;
namespace {
// Table used to drive the king towards the edge of the board
// Used to drive the king towards the edge of the board
// in KX vs K and KQ vs KR endgames.
constexpr int PushToEdges[SQUARE_NB] = {
100, 90, 80, 70, 70, 80, 90, 100,
90, 70, 60, 50, 50, 60, 70, 90,
80, 60, 40, 30, 30, 40, 60, 80,
70, 50, 30, 20, 20, 30, 50, 70,
70, 50, 30, 20, 20, 30, 50, 70,
80, 60, 40, 30, 30, 40, 60, 80,
90, 70, 60, 50, 50, 60, 70, 90,
100, 90, 80, 70, 70, 80, 90, 100
};
// 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);
}
// Table used to drive the king towards a corner square of the
// right color in KBN vs K endgames.
constexpr int PushToCorners[SQUARE_NB] = {
6400, 6080, 5760, 5440, 5120, 4800, 4480, 4160,
6080, 5760, 5440, 5120, 4800, 4480, 4160, 4480,
5760, 5440, 4960, 4480, 4480, 4000, 4480, 4800,
5440, 5120, 4480, 3840, 3520, 4480, 4800, 5120,
5120, 4800, 4480, 3520, 3840, 4480, 5120, 5440,
4800, 4480, 4000, 4480, 4480, 4960, 5440, 5760,
4480, 4160, 4480, 4800, 5120, 5440, 5760, 6080,
4160, 4480, 4800, 5120, 5440, 5760, 6080, 6400
};
// 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));
}
// Tables used to drive a piece towards or away from another piece
constexpr int PushClose[8] = { 0, 0, 100, 80, 60, 40, 20, 10 };
constexpr int PushAway [8] = { 0, 5, 20, 40, 60, 80, 90, 100 };
// Pawn Rank based scaling factors used in KRPPKRP endgame
constexpr int KRPPKRPScaleFactors[RANK_NB] = { 0, 9, 10, 14, 21, 44, 0, 0 };
// 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) {
@@ -74,9 +55,9 @@ namespace {
assert(pos.count<PAWN>(strongSide) == 1);
if (file_of(pos.square<PAWN>(strongSide)) >= FILE_E)
sq = Square(int(sq) ^ 7); // Mirror SQ_H1 -> SQ_A1
sq = flip_file(sq);
return strongSide == WHITE ? sq : ~sq;
return strongSide == WHITE ? sq : flip_rank(sq);
}
} // namespace
@@ -98,8 +79,6 @@ namespace Endgames {
add<KQKR>("KQKR");
add<KNNKP>("KNNKP");
add<KNPK>("KNPK");
add<KNPKB>("KNPKB");
add<KRPKR>("KRPKR");
add<KRPKB>("KRPKB");
add<KBPKB>("KBPKB");
@@ -124,20 +103,20 @@ Value Endgame<KXK>::operator()(const Position& pos) const {
if (pos.side_to_move() == weakSide && !MoveList<LEGAL>(pos).size())
return VALUE_DRAW;
Square winnerKSq = pos.square<KING>(strongSide);
Square loserKSq = pos.square<KING>(weakSide);
Square strongKing = pos.square<KING>(strongSide);
Square weakKing = pos.square<KING>(weakSide);
Value result = pos.non_pawn_material(strongSide)
+ pos.count<PAWN>(strongSide) * PawnValueEg
+ PushToEdges[loserKSq]
+ PushClose[distance(winnerKSq, loserKSq)];
+ 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_MATE_IN_MAX_PLY - 1);
result = std::min(result + VALUE_KNOWN_WIN, VALUE_TB_WIN_IN_MAX_PLY - 1);
return strongSide == pos.side_to_move() ? result : -result;
}
@@ -151,18 +130,18 @@ 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 winnerKSq = pos.square<KING>(strongSide);
Square loserKSq = pos.square<KING>(weakSide);
Square bishopSq = pos.square<BISHOP>(strongSide);
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
+ PushClose[distance(winnerKSq, loserKSq)]
+ PushToCorners[opposite_colors(bishopSq, SQ_A1) ? ~loserKSq : loserKSq];
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_MATE_IN_MAX_PLY);
assert(abs(result) < VALUE_TB_WIN_IN_MAX_PLY);
return strongSide == pos.side_to_move() ? result : -result;
}
@@ -175,16 +154,16 @@ Value Endgame<KPK>::operator()(const Position& pos) const {
assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
// Assume strongSide is white and the pawn is on files A-D
Square wksq = normalize(pos, strongSide, pos.square<KING>(strongSide));
Square bksq = normalize(pos, strongSide, pos.square<KING>(weakSide));
Square psq = normalize(pos, strongSide, pos.square<PAWN>(strongSide));
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(wksq, psq, bksq, us))
if (!Bitbases::probe(strongKing, strongPawn, weakKing, us))
return VALUE_DRAW;
Value result = VALUE_KNOWN_WIN + PawnValueEg + Value(rank_of(psq));
Value result = VALUE_KNOWN_WIN + PawnValueEg + Value(rank_of(strongPawn));
return strongSide == pos.side_to_move() ? result : -result;
}
@@ -200,36 +179,35 @@ Value Endgame<KRKP>::operator()(const Position& pos) const {
assert(verify_material(pos, strongSide, RookValueMg, 0));
assert(verify_material(pos, weakSide, VALUE_ZERO, 1));
Square wksq = relative_square(strongSide, pos.square<KING>(strongSide));
Square bksq = relative_square(strongSide, pos.square<KING>(weakSide));
Square rsq = relative_square(strongSide, pos.square<ROOK>(strongSide));
Square psq = relative_square(strongSide, pos.square<PAWN>(weakSide));
Square queeningSq = make_square(file_of(psq), RANK_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(WHITE, wksq) & psq)
result = RookValueEg - distance(wksq, psq);
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(bksq, psq) >= 3 + (pos.side_to_move() == weakSide)
&& distance(bksq, rsq) >= 3)
result = RookValueEg - distance(wksq, psq);
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 ( rank_of(bksq) <= RANK_3
&& distance(bksq, psq) == 1
&& rank_of(wksq) >= RANK_4
&& distance(wksq, psq) > 2 + (pos.side_to_move() == strongSide))
result = Value(80) - 8 * distance(wksq, psq);
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(wksq, psq + SOUTH)
- distance(bksq, psq + SOUTH)
- distance(psq, queeningSq));
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;
}
@@ -243,7 +221,7 @@ 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(PushToEdges[pos.square<KING>(weakSide)]);
Value result = Value(push_to_edge(pos.square<KING>(weakSide)));
return strongSide == pos.side_to_move() ? result : -result;
}
@@ -256,9 +234,9 @@ Value Endgame<KRKN>::operator()(const Position& pos) const {
assert(verify_material(pos, strongSide, RookValueMg, 0));
assert(verify_material(pos, weakSide, KnightValueMg, 0));
Square bksq = pos.square<KING>(weakSide);
Square bnsq = pos.square<KNIGHT>(weakSide);
Value result = Value(PushToEdges[bksq] + PushAway[distance(bksq, bnsq)]);
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;
}
@@ -273,22 +251,22 @@ Value Endgame<KQKP>::operator()(const Position& pos) const {
assert(verify_material(pos, strongSide, QueenValueMg, 0));
assert(verify_material(pos, weakSide, VALUE_ZERO, 1));
Square winnerKSq = pos.square<KING>(strongSide);
Square loserKSq = pos.square<KING>(weakSide);
Square pawnSq = pos.square<PAWN>(weakSide);
Square strongKing = pos.square<KING>(strongSide);
Square weakKing = pos.square<KING>(weakSide);
Square weakPawn = pos.square<PAWN>(weakSide);
Value result = Value(PushClose[distance(winnerKSq, loserKSq)]);
Value result = Value(push_close(strongKing, weakKing));
if ( relative_rank(weakSide, pawnSq) != RANK_7
|| distance(loserKSq, pawnSq) != 1
|| !((FileABB | FileCBB | FileFBB | FileHBB) & pawnSq))
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
/// 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.
@@ -298,28 +276,32 @@ Value Endgame<KQKR>::operator()(const Position& pos) const {
assert(verify_material(pos, strongSide, QueenValueMg, 0));
assert(verify_material(pos, weakSide, RookValueMg, 0));
Square winnerKSq = pos.square<KING>(strongSide);
Square loserKSq = pos.square<KING>(weakSide);
Square strongKing = pos.square<KING>(strongSide);
Square weakKing = pos.square<KING>(weakSide);
Value result = QueenValueEg
- RookValueEg
+ PushToEdges[loserKSq]
+ PushClose[distance(winnerKSq, loserKSq)];
+ push_to_edge(weakKing)
+ push_close(strongKing, weakKing);
return strongSide == pos.side_to_move() ? result : -result;
}
/// KNN vs KP. Simply push the opposing king to the corner
/// 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));
Value result = 2 * KnightValueEg
- PawnValueEg
+ PushToEdges[pos.square<KING>(weakSide)];
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;
}
@@ -342,51 +324,47 @@ ScaleFactor Endgame<KBPsK>::operator()(const Position& pos) const {
// No assertions about the material of weakSide, because we want draws to
// be detected even when the weaker side has some pawns.
Bitboard pawns = pos.pieces(strongSide, PAWN);
File pawnsFile = file_of(lsb(pawns));
Bitboard strongPawns = pos.pieces(strongSide, PAWN);
Bitboard allPawns = pos.pieces(PAWN);
// All pawns are on a single rook file?
if ( (pawnsFile == FILE_A || pawnsFile == FILE_H)
&& !(pawns & ~file_bb(pawnsFile)))
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 bishopSq = pos.square<BISHOP>(strongSide);
Square queeningSq = relative_square(strongSide, make_square(pawnsFile, RANK_8));
Square kingSq = pos.square<KING>(weakSide);
Square queeningSquare = relative_square(strongSide, make_square(file_of(lsb(strongPawns)), RANK_8));
if ( opposite_colors(queeningSq, bishopSq)
&& distance(queeningSq, kingSq) <= 1)
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 ( (pawnsFile == FILE_B || pawnsFile == FILE_G)
&& !(pos.pieces(PAWN) & ~file_bb(pawnsFile))
if ((!(allPawns & ~FileBBB) || !(allPawns & ~FileGBB))
&& pos.non_pawn_material(weakSide) == 0
&& pos.count<PAWN>(weakSide) >= 1)
{
// Get weakSide pawn that is closest to the home rank
Square weakPawnSq = frontmost_sq(strongSide, pos.pieces(weakSide, PAWN));
Square strongKingSq = pos.square<KING>(strongSide);
Square weakKingSq = pos.square<KING>(weakSide);
Square bishopSq = pos.square<BISHOP>(strongSide);
// 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, weakPawnSq) == RANK_7
&& (pos.pieces(strongSide, PAWN) & (weakPawnSq + pawn_push(weakSide)))
&& (opposite_colors(bishopSq, weakPawnSq) || pos.count<PAWN>(strongSide) == 1))
// 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(weakPawnSq, strongKingSq);
int weakKingDist = distance(weakPawnSq, weakKingSq);
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, weakKingSq) >= RANK_7
// 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;
@@ -406,15 +384,16 @@ ScaleFactor Endgame<KQKRPs>::operator()(const Position& pos) const {
assert(pos.count<ROOK>(weakSide) == 1);
assert(pos.count<PAWN>(weakSide) >= 1);
Square kingSq = pos.square<KING>(weakSide);
Square rsq = pos.square<ROOK>(weakSide);
Square strongKing = pos.square<KING>(strongSide);
Square weakKing = pos.square<KING>(weakSide);
Square weakRook = pos.square<ROOK>(weakSide);
if ( relative_rank(weakSide, kingSq) <= RANK_2
&& relative_rank(weakSide, pos.square<KING>(strongSide)) >= RANK_4
&& relative_rank(weakSide, rsq) == RANK_3
if ( relative_rank(weakSide, weakKing) <= RANK_2
&& relative_rank(weakSide, strongKing) >= RANK_4
&& relative_rank(weakSide, weakRook) == RANK_3
&& ( pos.pieces(weakSide, PAWN)
& pos.attacks_from<KING>(kingSq)
& pos.attacks_from<PAWN>(rsq, strongSide)))
& attacks_bb<KING>(weakKing)
& pawn_attacks_bb(strongSide, weakRook)))
return SCALE_FACTOR_DRAW;
return SCALE_FACTOR_NONE;
@@ -434,89 +413,89 @@ ScaleFactor Endgame<KRPKR>::operator()(const Position& pos) const {
assert(verify_material(pos, weakSide, RookValueMg, 0));
// Assume strongSide is white and the pawn is on files A-D
Square wksq = normalize(pos, strongSide, pos.square<KING>(strongSide));
Square bksq = normalize(pos, strongSide, pos.square<KING>(weakSide));
Square wrsq = normalize(pos, strongSide, pos.square<ROOK>(strongSide));
Square wpsq = normalize(pos, strongSide, pos.square<PAWN>(strongSide));
Square brsq = normalize(pos, strongSide, pos.square<ROOK>(weakSide));
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 f = file_of(wpsq);
Rank r = rank_of(wpsq);
Square queeningSq = make_square(f, RANK_8);
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 ( r <= RANK_5
&& distance(bksq, queeningSq) <= 1
&& wksq <= SQ_H5
&& (rank_of(brsq) == RANK_6 || (r <= RANK_3 && rank_of(wrsq) != RANK_6)))
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 ( r == RANK_6
&& distance(bksq, queeningSq) <= 1
&& rank_of(wksq) + tempo <= RANK_6
&& (rank_of(brsq) == RANK_1 || (!tempo && distance<File>(brsq, wpsq) >= 3)))
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 ( r >= RANK_6
&& bksq == queeningSq
&& rank_of(brsq) == RANK_1
&& (!tempo || distance(wksq, wpsq) >= 2))
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 ( wpsq == SQ_A7
&& wrsq == SQ_A8
&& (bksq == SQ_H7 || bksq == SQ_G7)
&& file_of(brsq) == FILE_A
&& (rank_of(brsq) <= RANK_3 || file_of(wksq) >= FILE_D || rank_of(wksq) <= RANK_5))
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 ( r <= RANK_5
&& bksq == wpsq + NORTH
&& distance(wksq, wpsq) - tempo >= 2
&& distance(wksq, brsq) - tempo >= 2)
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 ( r == RANK_7
&& f != FILE_A
&& file_of(wrsq) == f
&& wrsq != queeningSq
&& (distance(wksq, queeningSq) < distance(bksq, queeningSq) - 2 + tempo)
&& (distance(wksq, queeningSq) < distance(bksq, wrsq) + tempo))
return ScaleFactor(SCALE_FACTOR_MAX - 2 * distance(wksq, queeningSq));
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 ( f != FILE_A
&& file_of(wrsq) == f
&& wrsq < wpsq
&& (distance(wksq, queeningSq) < distance(bksq, queeningSq) - 2 + tempo)
&& (distance(wksq, wpsq + NORTH) < distance(bksq, wpsq + NORTH) - 2 + tempo)
&& ( distance(bksq, wrsq) + tempo >= 3
|| ( distance(wksq, queeningSq) < distance(bksq, wrsq) + tempo
&& (distance(wksq, wpsq + NORTH) < distance(bksq, wrsq) + tempo))))
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(wpsq, queeningSq)
- 2 * distance(wksq, queeningSq));
- 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 (r <= RANK_4 && bksq > wpsq)
if (pawnRank <= RANK_4 && weakKing > strongPawn)
{
if (file_of(bksq) == file_of(wpsq))
if (file_of(weakKing) == file_of(strongPawn))
return ScaleFactor(10);
if ( distance<File>(bksq, wpsq) == 1
&& distance(wksq, bksq) > 2)
return ScaleFactor(24 - 2 * distance(wksq, bksq));
if ( distance<File>(weakKing, strongPawn) == 1
&& distance(strongKing, weakKing) > 2)
return ScaleFactor(24 - 2 * distance(strongKing, weakKing));
}
return SCALE_FACTOR_NONE;
}
@@ -530,10 +509,11 @@ ScaleFactor Endgame<KRPKB>::operator()(const Position& pos) const {
// Test for a rook pawn
if (pos.pieces(PAWN) & (FileABB | FileHBB))
{
Square ksq = pos.square<KING>(weakSide);
Square bsq = pos.square<BISHOP>(weakSide);
Square psq = pos.square<PAWN>(strongSide);
Rank rk = relative_rank(strongSide, psq);
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
@@ -541,11 +521,11 @@ ScaleFactor Endgame<KRPKB>::operator()(const Position& pos) const {
// 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 (rk == RANK_5 && !opposite_colors(bsq, psq))
if (pawnRank == RANK_5 && !opposite_colors(weakBishop, strongPawn))
{
int d = distance(psq + 3 * push, ksq);
int d = distance(strongPawn + 3 * push, weakKing);
if (d <= 2 && !(d == 0 && ksq == pos.square<KING>(strongSide) + 2 * push))
if (d <= 2 && !(d == 0 && weakKing == strongKing + 2 * push))
return ScaleFactor(24);
else
return ScaleFactor(48);
@@ -555,10 +535,10 @@ ScaleFactor Endgame<KRPKB>::operator()(const Position& pos) const {
// 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 ( rk == RANK_6
&& distance(psq + 2 * push, ksq) <= 1
&& (PseudoAttacks[BISHOP][bsq] & (psq + push))
&& distance<File>(bsq, psq) >= 2)
if ( pawnRank == RANK_6
&& distance(strongPawn + 2 * push, weakKing) <= 1
&& (attacks_bb<BISHOP>(weakBishop) & (strongPawn + push))
&& distance<File>(weakBishop, strongPawn) >= 2)
return ScaleFactor(8);
}
@@ -573,28 +553,28 @@ ScaleFactor Endgame<KRPPKRP>::operator()(const Position& pos) const {
assert(verify_material(pos, strongSide, RookValueMg, 2));
assert(verify_material(pos, weakSide, RookValueMg, 1));
Square wpsq1 = pos.squares<PAWN>(strongSide)[0];
Square wpsq2 = pos.squares<PAWN>(strongSide)[1];
Square bksq = pos.square<KING>(weakSide);
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, wpsq1) || pos.pawn_passed(strongSide, wpsq2))
if (pos.pawn_passed(strongSide, strongPawn1) || pos.pawn_passed(strongSide, strongPawn2))
return SCALE_FACTOR_NONE;
Rank r = std::max(relative_rank(strongSide, wpsq1), relative_rank(strongSide, wpsq2));
Rank pawnRank = std::max(relative_rank(strongSide, strongPawn1), relative_rank(strongSide, strongPawn2));
if ( distance<File>(bksq, wpsq1) <= 1
&& distance<File>(bksq, wpsq2) <= 1
&& relative_rank(strongSide, bksq) > r)
if ( distance<File>(weakKing, strongPawn1) <= 1
&& distance<File>(weakKing, strongPawn2) <= 1
&& relative_rank(strongSide, weakKing) > pawnRank)
{
assert(r > RANK_1 && r < RANK_7);
return ScaleFactor(KRPPKRPScaleFactors[r]);
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
/// 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 {
@@ -603,14 +583,12 @@ ScaleFactor Endgame<KPsK>::operator()(const Position& pos) const {
assert(pos.count<PAWN>(strongSide) >= 2);
assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
Square ksq = pos.square<KING>(weakSide);
Bitboard pawns = pos.pieces(strongSide, PAWN);
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 and
// the king is within one file of the pawns, it's a draw.
if ( !(pawns & ~forward_ranks_bb(weakSide, ksq))
&& !((pawns & ~FileABB) && (pawns & ~FileHBB))
&& distance<File>(ksq, lsb(pawns)) <= 1)
// 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;
@@ -627,20 +605,19 @@ ScaleFactor Endgame<KBPKB>::operator()(const Position& pos) const {
assert(verify_material(pos, strongSide, BishopValueMg, 1));
assert(verify_material(pos, weakSide, BishopValueMg, 0));
Square pawnSq = pos.square<PAWN>(strongSide);
Square strongBishopSq = pos.square<BISHOP>(strongSide);
Square weakBishopSq = pos.square<BISHOP>(weakSide);
Square weakKingSq = pos.square<KING>(weakSide);
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 ( file_of(weakKingSq) == file_of(pawnSq)
&& relative_rank(strongSide, pawnSq) < relative_rank(strongSide, weakKingSq)
&& ( opposite_colors(weakKingSq, strongBishopSq)
|| relative_rank(strongSide, weakKingSq) <= RANK_6))
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(strongBishopSq, weakBishopSq))
if (opposite_colors(strongBishop, weakBishop))
return SCALE_FACTOR_DRAW;
return SCALE_FACTOR_NONE;
@@ -654,36 +631,36 @@ ScaleFactor Endgame<KBPPKB>::operator()(const Position& pos) const {
assert(verify_material(pos, strongSide, BishopValueMg, 2));
assert(verify_material(pos, weakSide, BishopValueMg, 0));
Square wbsq = pos.square<BISHOP>(strongSide);
Square bbsq = pos.square<BISHOP>(weakSide);
Square strongBishop = pos.square<BISHOP>(strongSide);
Square weakBishop = pos.square<BISHOP>(weakSide);
if (!opposite_colors(wbsq, bbsq))
if (!opposite_colors(strongBishop, weakBishop))
return SCALE_FACTOR_NONE;
Square ksq = pos.square<KING>(weakSide);
Square psq1 = pos.squares<PAWN>(strongSide)[0];
Square psq2 = pos.squares<PAWN>(strongSide)[1];
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, psq1) > relative_rank(strongSide, psq2))
if (relative_rank(strongSide, strongPawn1) > relative_rank(strongSide, strongPawn2))
{
blockSq1 = psq1 + pawn_push(strongSide);
blockSq2 = make_square(file_of(psq2), rank_of(psq1));
blockSq1 = strongPawn1 + pawn_push(strongSide);
blockSq2 = make_square(file_of(strongPawn2), rank_of(strongPawn1));
}
else
{
blockSq1 = psq2 + pawn_push(strongSide);
blockSq2 = make_square(file_of(psq1), rank_of(psq2));
blockSq1 = strongPawn2 + pawn_push(strongSide);
blockSq2 = make_square(file_of(strongPawn1), rank_of(strongPawn2));
}
switch (distance<File>(psq1, psq2))
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(ksq) == file_of(blockSq1)
&& relative_rank(strongSide, ksq) >= relative_rank(strongSide, blockSq1)
&& opposite_colors(ksq, wbsq))
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;
@@ -692,17 +669,17 @@ ScaleFactor Endgame<KBPPKB>::operator()(const Position& pos) const {
// 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 ( ksq == blockSq1
&& opposite_colors(ksq, wbsq)
&& ( bbsq == blockSq2
|| (pos.attacks_from<BISHOP>(blockSq2) & pos.pieces(weakSide, BISHOP))
|| distance<Rank>(psq1, psq2) >= 2))
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 ( ksq == blockSq2
&& opposite_colors(ksq, wbsq)
&& ( bbsq == blockSq1
|| (pos.attacks_from<BISHOP>(blockSq1) & pos.pieces(weakSide, BISHOP))))
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;
@@ -714,7 +691,7 @@ ScaleFactor Endgame<KBPPKB>::operator()(const Position& pos) const {
}
/// KBP vs KN. There is a single rule: If the defending king is somewhere along
/// 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<>
@@ -723,62 +700,22 @@ ScaleFactor Endgame<KBPKN>::operator()(const Position& pos) const {
assert(verify_material(pos, strongSide, BishopValueMg, 1));
assert(verify_material(pos, weakSide, KnightValueMg, 0));
Square pawnSq = pos.square<PAWN>(strongSide);
Square strongBishopSq = pos.square<BISHOP>(strongSide);
Square weakKingSq = pos.square<KING>(weakSide);
Square strongPawn = pos.square<PAWN>(strongSide);
Square strongBishop = pos.square<BISHOP>(strongSide);
Square weakKing = pos.square<KING>(weakSide);
if ( file_of(weakKingSq) == file_of(pawnSq)
&& relative_rank(strongSide, pawnSq) < relative_rank(strongSide, weakKingSq)
&& ( opposite_colors(weakKingSq, strongBishopSq)
|| relative_rank(strongSide, weakKingSq) <= RANK_6))
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;
}
/// KNP vs K. There is a single rule: if the pawn is a rook pawn on the 7th rank
/// and the defending king prevents the pawn from advancing, the position is drawn.
template<>
ScaleFactor Endgame<KNPK>::operator()(const Position& pos) const {
assert(verify_material(pos, strongSide, KnightValueMg, 1));
assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
// Assume strongSide is white and the pawn is on files A-D
Square pawnSq = normalize(pos, strongSide, pos.square<PAWN>(strongSide));
Square weakKingSq = normalize(pos, strongSide, pos.square<KING>(weakSide));
if (pawnSq == SQ_A7 && distance(SQ_A8, weakKingSq) <= 1)
return SCALE_FACTOR_DRAW;
return SCALE_FACTOR_NONE;
}
/// KNP vs KB. If knight can block bishop from taking pawn, it's a win.
/// Otherwise the position is drawn.
template<>
ScaleFactor Endgame<KNPKB>::operator()(const Position& pos) const {
assert(verify_material(pos, strongSide, KnightValueMg, 1));
assert(verify_material(pos, weakSide, BishopValueMg, 0));
Square pawnSq = pos.square<PAWN>(strongSide);
Square bishopSq = pos.square<BISHOP>(weakSide);
Square weakKingSq = pos.square<KING>(weakSide);
// King needs to get close to promoting pawn to prevent knight from blocking.
// Rules for this are very tricky, so just approximate.
if (forward_file_bb(strongSide, pawnSq) & pos.attacks_from<BISHOP>(bishopSq))
return ScaleFactor(distance(weakKingSq, pawnSq));
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
/// 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).
@@ -789,18 +726,18 @@ ScaleFactor Endgame<KPKP>::operator()(const Position& pos) const {
assert(verify_material(pos, weakSide, VALUE_ZERO, 1));
// Assume strongSide is white and the pawn is on files A-D
Square wksq = normalize(pos, strongSide, pos.square<KING>(strongSide));
Square bksq = normalize(pos, strongSide, pos.square<KING>(weakSide));
Square psq = normalize(pos, strongSide, pos.square<PAWN>(strongSide));
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(psq) >= RANK_5 && file_of(psq) != FILE_A)
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(wksq, psq, bksq, us) ? SCALE_FACTOR_NONE : SCALE_FACTOR_DRAW;
return Bitbases::probe(strongKing, strongPawn, weakKing, us) ? SCALE_FACTOR_NONE : SCALE_FACTOR_DRAW;
}
+2 -6
View File
@@ -1,8 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
@@ -21,10 +19,10 @@
#ifndef ENDGAME_H_INCLUDED
#define ENDGAME_H_INCLUDED
#include <unordered_map>
#include <memory>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <utility>
#include "position.h"
@@ -57,8 +55,6 @@ enum EndgameCode {
KBPKB, // KBP vs KB
KBPPKB, // KBPP vs KB
KBPKN, // KBP vs KN
KNPK, // KNP vs K
KNPKB, // KNP vs KB
KPKP // KP vs KP
};
+491 -231
View File
File diff suppressed because it is too large Load Diff
+20 -7
View File
@@ -1,8 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
@@ -29,11 +27,26 @@ class Position;
namespace Eval {
constexpr Value Tempo = Value(28); // Must be visible to search
std::string trace(const Position& pos);
Value evaluate(const Position& pos);
std::string trace(const Position& pos);
extern bool useNNUE;
extern std::string eval_file_loaded;
Value evaluate(const Position& pos);
}
// 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-62ef826d1a6d.nnue"
namespace NNUE {
Value evaluate(const Position& pos);
bool load_eval(std::string name, std::istream& stream);
void init();
void verify();
} // namespace NNUE
} // namespace Eval
#endif // #ifndef EVALUATE_H_INCLUDED
+26
View File
@@ -0,0 +1,26 @@
The file "incbin.h" is free and unencumbered software released into
the public domain by Dale Weiler, see:
<https://github.com/graphitemaster/incbin>
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
+368
View File
@@ -0,0 +1,368 @@
/**
* @file incbin.h
* @author Dale Weiler
* @brief Utility for including binary files
*
* Facilities for including binary files into the current translation unit and
* making use from them externally in other translation units.
*/
#ifndef INCBIN_HDR
#define INCBIN_HDR
#include <limits.h>
#if defined(__AVX512BW__) || \
defined(__AVX512CD__) || \
defined(__AVX512DQ__) || \
defined(__AVX512ER__) || \
defined(__AVX512PF__) || \
defined(__AVX512VL__) || \
defined(__AVX512F__)
# define INCBIN_ALIGNMENT_INDEX 6
#elif defined(__AVX__) || \
defined(__AVX2__)
# define INCBIN_ALIGNMENT_INDEX 5
#elif defined(__SSE__) || \
defined(__SSE2__) || \
defined(__SSE3__) || \
defined(__SSSE3__) || \
defined(__SSE4_1__) || \
defined(__SSE4_2__) || \
defined(__neon__)
# define INCBIN_ALIGNMENT_INDEX 4
#elif ULONG_MAX != 0xffffffffu
# define INCBIN_ALIGNMENT_INDEX 3
# else
# define INCBIN_ALIGNMENT_INDEX 2
#endif
/* Lookup table of (1 << n) where `n' is `INCBIN_ALIGNMENT_INDEX' */
#define INCBIN_ALIGN_SHIFT_0 1
#define INCBIN_ALIGN_SHIFT_1 2
#define INCBIN_ALIGN_SHIFT_2 4
#define INCBIN_ALIGN_SHIFT_3 8
#define INCBIN_ALIGN_SHIFT_4 16
#define INCBIN_ALIGN_SHIFT_5 32
#define INCBIN_ALIGN_SHIFT_6 64
/* Actual alignment value */
#define INCBIN_ALIGNMENT \
INCBIN_CONCATENATE( \
INCBIN_CONCATENATE(INCBIN_ALIGN_SHIFT, _), \
INCBIN_ALIGNMENT_INDEX)
/* Stringize */
#define INCBIN_STR(X) \
#X
#define INCBIN_STRINGIZE(X) \
INCBIN_STR(X)
/* Concatenate */
#define INCBIN_CAT(X, Y) \
X ## Y
#define INCBIN_CONCATENATE(X, Y) \
INCBIN_CAT(X, Y)
/* Deferred macro expansion */
#define INCBIN_EVAL(X) \
X
#define INCBIN_INVOKE(N, ...) \
INCBIN_EVAL(N(__VA_ARGS__))
/* Green Hills uses a different directive for including binary data */
#if defined(__ghs__)
# if (__ghs_asm == 2)
# define INCBIN_MACRO ".file"
/* Or consider the ".myrawdata" entry in the ld file */
# else
# define INCBIN_MACRO "\tINCBIN"
# endif
#else
# define INCBIN_MACRO ".incbin"
#endif
#ifndef _MSC_VER
# define INCBIN_ALIGN \
__attribute__((aligned(INCBIN_ALIGNMENT)))
#else
# define INCBIN_ALIGN __declspec(align(INCBIN_ALIGNMENT))
#endif
#if defined(__arm__) || /* GNU C and RealView */ \
defined(__arm) || /* Diab */ \
defined(_ARM) /* ImageCraft */
# define INCBIN_ARM
#endif
#ifdef __GNUC__
/* Utilize .balign where supported */
# define INCBIN_ALIGN_HOST ".balign " INCBIN_STRINGIZE(INCBIN_ALIGNMENT) "\n"
# define INCBIN_ALIGN_BYTE ".balign 1\n"
#elif defined(INCBIN_ARM)
/*
* On arm assemblers, the alignment value is calculated as (1 << n) where `n' is
* the shift count. This is the value passed to `.align'
*/
# define INCBIN_ALIGN_HOST ".align " INCBIN_STRINGIZE(INCBIN_ALIGNMENT_INDEX) "\n"
# define INCBIN_ALIGN_BYTE ".align 0\n"
#else
/* We assume other inline assembler's treat `.align' as `.balign' */
# define INCBIN_ALIGN_HOST ".align " INCBIN_STRINGIZE(INCBIN_ALIGNMENT) "\n"
# define INCBIN_ALIGN_BYTE ".align 1\n"
#endif
/* INCBIN_CONST is used by incbin.c generated files */
#if defined(__cplusplus)
# define INCBIN_EXTERNAL extern "C"
# define INCBIN_CONST extern const
#else
# define INCBIN_EXTERNAL extern
# define INCBIN_CONST const
#endif
/**
* @brief Optionally override the linker section into which data is emitted.
*
* @warning If you use this facility, you'll have to deal with platform-specific linker output
* section naming on your own
*
* Overriding the default linker output section, e.g for esp8266/Arduino:
* @code
* #define INCBIN_OUTPUT_SECTION ".irom.text"
* #include "incbin.h"
* INCBIN(Foo, "foo.txt");
* // Data is emitted into program memory that never gets copied to RAM
* @endcode
*/
#if !defined(INCBIN_OUTPUT_SECTION)
# if defined(__APPLE__)
# define INCBIN_OUTPUT_SECTION ".const_data"
# else
# define INCBIN_OUTPUT_SECTION ".rodata"
# endif
#endif
#if defined(__APPLE__)
/* The directives are different for Apple branded compilers */
# define INCBIN_SECTION INCBIN_OUTPUT_SECTION "\n"
# define INCBIN_GLOBAL(NAME) ".globl " INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME "\n"
# define INCBIN_INT ".long "
# define INCBIN_MANGLE "_"
# define INCBIN_BYTE ".byte "
# define INCBIN_TYPE(...)
#else
# define INCBIN_SECTION ".section " INCBIN_OUTPUT_SECTION "\n"
# define INCBIN_GLOBAL(NAME) ".global " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME "\n"
# if defined(__ghs__)
# define INCBIN_INT ".word "
# else
# define INCBIN_INT ".int "
# endif
# if defined(__USER_LABEL_PREFIX__)
# define INCBIN_MANGLE INCBIN_STRINGIZE(__USER_LABEL_PREFIX__)
# else
# define INCBIN_MANGLE ""
# endif
# if defined(INCBIN_ARM)
/* On arm assemblers, `@' is used as a line comment token */
# define INCBIN_TYPE(NAME) ".type " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME ", %object\n"
# elif defined(__MINGW32__) || defined(__MINGW64__)
/* Mingw doesn't support this directive either */
# define INCBIN_TYPE(NAME)
# else
/* It's safe to use `@' on other architectures */
# define INCBIN_TYPE(NAME) ".type " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME ", @object\n"
# endif
# define INCBIN_BYTE ".byte "
#endif
/* List of style types used for symbol names */
#define INCBIN_STYLE_CAMEL 0
#define INCBIN_STYLE_SNAKE 1
/**
* @brief Specify the prefix to use for symbol names.
*
* By default this is `g', producing symbols of the form:
* @code
* #include "incbin.h"
* INCBIN(Foo, "foo.txt");
*
* // Now you have the following symbols:
* // const unsigned char gFooData[];
* // const unsigned char *const gFooEnd;
* // const unsigned int gFooSize;
* @endcode
*
* If however you specify a prefix before including: e.g:
* @code
* #define INCBIN_PREFIX incbin
* #include "incbin.h"
* INCBIN(Foo, "foo.txt");
*
* // Now you have the following symbols instead:
* // const unsigned char incbinFooData[];
* // const unsigned char *const incbinFooEnd;
* // const unsigned int incbinFooSize;
* @endcode
*/
#if !defined(INCBIN_PREFIX)
# define INCBIN_PREFIX g
#endif
/**
* @brief Specify the style used for symbol names.
*
* Possible options are
* - INCBIN_STYLE_CAMEL "CamelCase"
* - INCBIN_STYLE_SNAKE "snake_case"
*
* Default option is *INCBIN_STYLE_CAMEL* producing symbols of the form:
* @code
* #include "incbin.h"
* INCBIN(Foo, "foo.txt");
*
* // Now you have the following symbols:
* // const unsigned char <prefix>FooData[];
* // const unsigned char *const <prefix>FooEnd;
* // const unsigned int <prefix>FooSize;
* @endcode
*
* If however you specify a style before including: e.g:
* @code
* #define INCBIN_STYLE INCBIN_STYLE_SNAKE
* #include "incbin.h"
* INCBIN(foo, "foo.txt");
*
* // Now you have the following symbols:
* // const unsigned char <prefix>foo_data[];
* // const unsigned char *const <prefix>foo_end;
* // const unsigned int <prefix>foo_size;
* @endcode
*/
#if !defined(INCBIN_STYLE)
# define INCBIN_STYLE INCBIN_STYLE_CAMEL
#endif
/* Style lookup tables */
#define INCBIN_STYLE_0_DATA Data
#define INCBIN_STYLE_0_END End
#define INCBIN_STYLE_0_SIZE Size
#define INCBIN_STYLE_1_DATA _data
#define INCBIN_STYLE_1_END _end
#define INCBIN_STYLE_1_SIZE _size
/* Style lookup: returning identifier */
#define INCBIN_STYLE_IDENT(TYPE) \
INCBIN_CONCATENATE( \
INCBIN_STYLE_, \
INCBIN_CONCATENATE( \
INCBIN_EVAL(INCBIN_STYLE), \
INCBIN_CONCATENATE(_, TYPE)))
/* Style lookup: returning string literal */
#define INCBIN_STYLE_STRING(TYPE) \
INCBIN_STRINGIZE( \
INCBIN_STYLE_IDENT(TYPE)) \
/* Generate the global labels by indirectly invoking the macro with our style
* type and concatenating the name against them. */
#define INCBIN_GLOBAL_LABELS(NAME, TYPE) \
INCBIN_INVOKE( \
INCBIN_GLOBAL, \
INCBIN_CONCATENATE( \
NAME, \
INCBIN_INVOKE( \
INCBIN_STYLE_IDENT, \
TYPE))) \
INCBIN_INVOKE( \
INCBIN_TYPE, \
INCBIN_CONCATENATE( \
NAME, \
INCBIN_INVOKE( \
INCBIN_STYLE_IDENT, \
TYPE)))
/**
* @brief Externally reference binary data included in another translation unit.
*
* Produces three external symbols that reference the binary data included in
* another translation unit.
*
* The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
* "Data", as well as "End" and "Size" after. An example is provided below.
*
* @param NAME The name given for the binary data
*
* @code
* INCBIN_EXTERN(Foo);
*
* // Now you have the following symbols:
* // extern const unsigned char <prefix>FooData[];
* // extern const unsigned char *const <prefix>FooEnd;
* // extern const unsigned int <prefix>FooSize;
* @endcode
*/
#define INCBIN_EXTERN(NAME) \
INCBIN_EXTERNAL const INCBIN_ALIGN unsigned char \
INCBIN_CONCATENATE( \
INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
INCBIN_STYLE_IDENT(DATA))[]; \
INCBIN_EXTERNAL const INCBIN_ALIGN unsigned char *const \
INCBIN_CONCATENATE( \
INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
INCBIN_STYLE_IDENT(END)); \
INCBIN_EXTERNAL const unsigned int \
INCBIN_CONCATENATE( \
INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
INCBIN_STYLE_IDENT(SIZE))
/**
* @brief Include a binary file into the current translation unit.
*
* Includes a binary file into the current translation unit, producing three symbols
* for objects that encode the data and size respectively.
*
* The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
* "Data", as well as "End" and "Size" after. An example is provided below.
*
* @param NAME The name to associate with this binary data (as an identifier.)
* @param FILENAME The file to include (as a string literal.)
*
* @code
* INCBIN(Icon, "icon.png");
*
* // Now you have the following symbols:
* // const unsigned char <prefix>IconData[];
* // const unsigned char *const <prefix>IconEnd;
* // const unsigned int <prefix>IconSize;
* @endcode
*
* @warning This must be used in global scope
* @warning The identifiers may be different if INCBIN_STYLE is not default
*
* To externally reference the data included by this in another translation unit
* please @see INCBIN_EXTERN.
*/
#ifdef _MSC_VER
#define INCBIN(NAME, FILENAME) \
INCBIN_EXTERN(NAME)
#else
#define INCBIN(NAME, FILENAME) \
__asm__(INCBIN_SECTION \
INCBIN_GLOBAL_LABELS(NAME, DATA) \
INCBIN_ALIGN_HOST \
INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(DATA) ":\n" \
INCBIN_MACRO " \"" FILENAME "\"\n" \
INCBIN_GLOBAL_LABELS(NAME, END) \
INCBIN_ALIGN_BYTE \
INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(END) ":\n" \
INCBIN_BYTE "1\n" \
INCBIN_GLOBAL_LABELS(NAME, SIZE) \
INCBIN_ALIGN_HOST \
INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(SIZE) ":\n" \
INCBIN_INT INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(END) " - " \
INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(DATA) "\n" \
INCBIN_ALIGN_HOST \
".text\n" \
); \
INCBIN_EXTERN(NAME)
#endif
#endif
+8 -10
View File
@@ -1,8 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
@@ -21,30 +19,30 @@
#include <iostream>
#include "bitboard.h"
#include "endgame.h"
#include "position.h"
#include "psqt.h"
#include "search.h"
#include "syzygy/tbprobe.h"
#include "thread.h"
#include "tt.h"
#include "uci.h"
#include "endgame.h"
#include "syzygy/tbprobe.h"
namespace PSQT {
void init();
}
int main(int argc, char* argv[]) {
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(Options["Threads"]);
Threads.set(size_t(Options["Threads"]));
Search::clear(); // After threads are up
Eval::NNUE::init();
UCI::loop(argc, argv);
+34 -28
View File
@@ -1,8 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
@@ -27,31 +25,36 @@
using namespace std;
namespace {
#define S(mg, eg) make_score(mg, eg)
// Polynomial material imbalance parameters
constexpr int QuadraticOurs[][PIECE_TYPE_NB] = {
// OUR PIECES
// pair pawn knight bishop rook queen
{1438 }, // Bishop pair
{ 40, 38 }, // Pawn
{ 32, 255, -62 }, // Knight OUR PIECES
{ 0, 104, 4, 0 }, // Bishop
{ -26, -2, 47, 105, -208 }, // Rook
{-189, 24, 117, 133, -134, -6 } // Queen
// 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
};
constexpr int QuadraticTheirs[][PIECE_TYPE_NB] = {
// THEIR PIECES
// pair pawn knight bishop rook queen
{ 0 }, // Bishop pair
{ 36, 0 }, // Pawn
{ 9, 63, 0 }, // Knight OUR PIECES
{ 59, 65, 42, 0 }, // Bishop
{ 46, 39, 24, -24, 0 }, // Rook
{ 97, 100, -42, 137, 268, 0 } // 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) };
@@ -79,14 +82,16 @@ namespace {
&& pos.count<PAWN>(~us) >= 1;
}
/// imbalance() calculates the imbalance by comparing the piece count of each
/// piece type for both colors.
template<Color Us>
int imbalance(const int pieceCount[][PIECE_TYPE_NB]) {
Score imbalance(const int pieceCount[][PIECE_TYPE_NB]) {
constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
constexpr Color Them = ~Us;
int bonus = 0;
Score bonus = SCORE_ZERO;
// Second-degree polynomial material imbalance, by Tord Romstad
for (int pt1 = NO_PIECE_TYPE; pt1 <= QUEEN; ++pt1)
@@ -94,9 +99,9 @@ namespace {
if (!pieceCount[Us][pt1])
continue;
int v = 0;
int v = QuadraticOurs[pt1][pt1] * pieceCount[Us][pt1];
for (int pt2 = NO_PIECE_TYPE; pt2 <= pt1; ++pt2)
for (int pt2 = NO_PIECE_TYPE; pt2 < pt1; ++pt2)
v += QuadraticOurs[pt1][pt2] * pieceCount[Us][pt2]
+ QuadraticTheirs[pt1][pt2] * pieceCount[Them][pt2];
@@ -110,6 +115,7 @@ 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
@@ -129,7 +135,7 @@ Entry* probe(const Position& pos) {
Value npm_w = pos.non_pawn_material(WHITE);
Value npm_b = pos.non_pawn_material(BLACK);
Value npm = clamp(npm_w + npm_b, EndgameLimit, MidgameLimit);
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));
@@ -212,7 +218,7 @@ Entry* probe(const Position& pos) {
{ 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->value = int16_t((imbalance<WHITE>(pieceCount) - imbalance<BLACK>(pieceCount)) / 16);
e->score = (imbalance<WHITE>(pieceCount) - imbalance<BLACK>(pieceCount)) / 16;
return e;
}
+6 -8
View File
@@ -1,8 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
@@ -39,12 +37,12 @@ namespace Material {
struct Entry {
Score imbalance() const { return make_score(value, value); }
Phase game_phase() const { return gamePhase; }
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
// 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
@@ -59,9 +57,9 @@ struct Entry {
const EndgameBase<Value>* evaluationFunction;
const EndgameBase<ScaleFactor>* scalingFunction[COLOR_NB]; // Could be one for each
// side (e.g. KPKP, KBPsK)
int16_t value;
Score score;
int16_t gamePhase;
uint8_t factor[COLOR_NB];
Phase gamePhase;
};
typedef HashTable<Entry, 8192> Table;
+250 -17
View File
@@ -1,8 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
@@ -46,6 +44,17 @@ typedef bool(*fun3_t)(HANDLE, CONST GROUP_AFFINITY*, PGROUP_AFFINITY);
#include <iostream>
#include <sstream>
#include <vector>
#include <cstdlib>
#if defined(__linux__) && !defined(__ANDROID__)
#include <stdlib.h>
#include <sys/mman.h>
#endif
#if defined(__APPLE__) || defined(__ANDROID__) || defined(__OpenBSD__) || (defined(__GLIBCXX__) && !defined(_GLIBCXX_HAVE_ALIGNED_ALLOC) && !defined(_WIN32))
#define POSIXALIGNEDALLOC
#include <stdlib.h>
#endif
#include "misc.h"
#include "thread.h"
@@ -56,7 +65,7 @@ namespace {
/// Version number. If Version is left empty, then compile date in the format
/// DD-MM-YY and show in engine_info.
const string Version = "11";
const string Version = "13";
/// Our fancy logging facility. The trick here is to replace cin.rdbuf() and
/// cout.rdbuf() with two Tie objects that tie cin and cout to a file stream. We
@@ -123,6 +132,7 @@ public:
} // namespace
/// engine_info() returns the full name of the current Stockfish version. This
/// will be either "Stockfish <Tag> DD-MM-YY" (where DD-MM-YY is the date when
/// the program was compiled) or "Stockfish <Version>", depending on whether
@@ -142,10 +152,8 @@ const string engine_info(bool to_uci) {
ss << setw(2) << day << setw(2) << (1 + months.find(month) / 4) << year.substr(2);
}
ss << (Is64Bit ? " 64" : "")
<< (HasPext ? " BMI2" : (HasPopCnt ? " POPCNT" : ""))
<< (to_uci ? "\nid author ": " by ")
<< "T. Romstad, M. Costalba, J. Kiiski, G. Linscott";
ss << (to_uci ? "\nid author ": " by ")
<< "the Stockfish developers (see AUTHORS file)";
return ss.str();
}
@@ -155,9 +163,9 @@ const string engine_info(bool to_uci) {
const std::string compiler_info() {
#define STRINGIFY2(x) #x
#define STRINGIFY(x) STRINGIFY2(x)
#define VER_STRING(major, minor, patch) STRINGIFY(major) "." STRINGIFY(minor) "." STRINGIFY(patch)
#define stringify2(x) #x
#define stringify(x) stringify2(x)
#define make_version_string(major, minor, patch) stringify(major) "." stringify(minor) "." stringify(patch)
/// Predefined macros hell:
///
@@ -171,26 +179,26 @@ const std::string compiler_info() {
#ifdef __clang__
compiler += "clang++ ";
compiler += VER_STRING(__clang_major__, __clang_minor__, __clang_patchlevel__);
compiler += make_version_string(__clang_major__, __clang_minor__, __clang_patchlevel__);
#elif __INTEL_COMPILER
compiler += "Intel compiler ";
compiler += "(version ";
compiler += STRINGIFY(__INTEL_COMPILER) " update " STRINGIFY(__INTEL_COMPILER_UPDATE);
compiler += stringify(__INTEL_COMPILER) " update " stringify(__INTEL_COMPILER_UPDATE);
compiler += ")";
#elif _MSC_VER
compiler += "MSVC ";
compiler += "(version ";
compiler += STRINGIFY(_MSC_FULL_VER) "." STRINGIFY(_MSC_BUILD);
compiler += stringify(_MSC_FULL_VER) "." stringify(_MSC_BUILD);
compiler += ")";
#elif __GNUC__
compiler += "g++ (GNUC) ";
compiler += VER_STRING(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
compiler += make_version_string(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
#else
compiler += "Unknown compiler ";
compiler += "(unknown version)";
#endif
#if defined(__APPLE__)
#if defined(__APPLE__)
compiler += " on Apple";
#elif defined(__CYGWIN__)
compiler += " on Cygwin";
@@ -210,7 +218,40 @@ const std::string compiler_info() {
compiler += " on unknown system";
#endif
compiler += "\n __VERSION__ macro expands to: ";
compiler += "\nCompilation settings include: ";
compiler += (Is64Bit ? " 64bit" : " 32bit");
#if defined(USE_VNNI)
compiler += " VNNI";
#endif
#if defined(USE_AVX512)
compiler += " AVX512";
#endif
compiler += (HasPext ? " BMI2" : "");
#if defined(USE_AVX2)
compiler += " AVX2";
#endif
#if defined(USE_SSE41)
compiler += " SSE41";
#endif
#if defined(USE_SSSE3)
compiler += " SSSE3";
#endif
#if defined(USE_SSE2)
compiler += " SSE2";
#endif
compiler += (HasPopCnt ? " POPCNT" : "");
#if defined(USE_MMX)
compiler += " MMX";
#endif
#if defined(USE_NEON)
compiler += " NEON";
#endif
#if !defined(NDEBUG)
compiler += " DEBUG";
#endif
compiler += "\n__VERSION__ macro expands to: ";
#ifdef __VERSION__
compiler += __VERSION__;
#else
@@ -288,6 +329,141 @@ void prefetch(void* addr) {
#endif
/// std_aligned_alloc() is our wrapper for systems where the c++17 implementation
/// does not guarantee the availability of aligned_alloc(). Memory allocated with
/// std_aligned_alloc() must be freed with std_aligned_free().
void* std_aligned_alloc(size_t alignment, size_t size) {
#if defined(POSIXALIGNEDALLOC)
void *mem;
return posix_memalign(&mem, alignment, size) ? nullptr : mem;
#elif defined(_WIN32)
return _mm_malloc(size, alignment);
#else
return std::aligned_alloc(alignment, size);
#endif
}
void std_aligned_free(void* ptr) {
#if defined(POSIXALIGNEDALLOC)
free(ptr);
#elif defined(_WIN32)
_mm_free(ptr);
#else
free(ptr);
#endif
}
/// aligned_large_pages_alloc() will return suitably aligned memory, if possible using large pages.
#if defined(_WIN32)
static void* aligned_large_pages_alloc_win(size_t allocSize) {
HANDLE hProcessToken { };
LUID luid { };
void* mem = nullptr;
const size_t largePageSize = GetLargePageMinimum();
if (!largePageSize)
return nullptr;
// We need SeLockMemoryPrivilege, so try to enable it for the process
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hProcessToken))
return nullptr;
if (LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME, &luid))
{
TOKEN_PRIVILEGES tp { };
TOKEN_PRIVILEGES prevTp { };
DWORD prevTpLen = 0;
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// Try to enable SeLockMemoryPrivilege. Note that even if AdjustTokenPrivileges() succeeds,
// we still need to query GetLastError() to ensure that the privileges were actually obtained.
if (AdjustTokenPrivileges(
hProcessToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &prevTp, &prevTpLen) &&
GetLastError() == ERROR_SUCCESS)
{
// Round up size to full pages and allocate
allocSize = (allocSize + largePageSize - 1) & ~size_t(largePageSize - 1);
mem = VirtualAlloc(
NULL, allocSize, MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE);
// Privilege no longer needed, restore previous state
AdjustTokenPrivileges(hProcessToken, FALSE, &prevTp, 0, NULL, NULL);
}
}
CloseHandle(hProcessToken);
return mem;
}
void* aligned_large_pages_alloc(size_t allocSize) {
// Try to allocate large pages
void* mem = aligned_large_pages_alloc_win(allocSize);
// Fall back to regular, page aligned, allocation if necessary
if (!mem)
mem = VirtualAlloc(NULL, allocSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
return mem;
}
#else
void* aligned_large_pages_alloc(size_t allocSize) {
#if defined(__linux__)
constexpr size_t alignment = 2 * 1024 * 1024; // assumed 2MB page size
#else
constexpr size_t alignment = 4096; // assumed small page size
#endif
// round up to multiples of alignment
size_t size = ((allocSize + alignment - 1) / alignment) * alignment;
void *mem = std_aligned_alloc(alignment, size);
#if defined(MADV_HUGEPAGE)
madvise(mem, size, MADV_HUGEPAGE);
#endif
return mem;
}
#endif
/// aligned_large_pages_free() will free the previously allocated ttmem
#if defined(_WIN32)
void aligned_large_pages_free(void* mem) {
if (mem && !VirtualFree(mem, 0, MEM_RELEASE))
{
DWORD err = GetLastError();
std::cerr << "Failed to free transposition table. Error code: 0x" <<
std::hex << err << std::dec << std::endl;
exit(EXIT_FAILURE);
}
}
#else
void aligned_large_pages_free(void *mem) {
std_aligned_free(mem);
}
#endif
namespace WinProcGroup {
#ifndef _WIN32
@@ -393,3 +569,60 @@ void bindThisThread(size_t idx) {
#endif
} // namespace WinProcGroup
#ifdef _WIN32
#include <direct.h>
#define GETCWD _getcwd
#else
#include <unistd.h>
#define GETCWD getcwd
#endif
namespace CommandLine {
string argv0; // path+name of the executable binary, as given by argv[0]
string binaryDirectory; // path of the executable directory
string workingDirectory; // path of the working directory
void init(int argc, char* argv[]) {
(void)argc;
string pathSeparator;
// extract the path+name of the executable binary
argv0 = argv[0];
#ifdef _WIN32
pathSeparator = "\\";
#ifdef _MSC_VER
// Under windows argv[0] may not have the extension. Also _get_pgmptr() had
// issues in some windows 10 versions, so check returned values carefully.
char* pgmptr = nullptr;
if (!_get_pgmptr(&pgmptr) && pgmptr != nullptr && *pgmptr)
argv0 = pgmptr;
#endif
#else
pathSeparator = "/";
#endif
// extract the working directory
workingDirectory = "";
char buff[40000];
char* cwd = GETCWD(buff, 40000);
if (cwd)
workingDirectory = cwd;
// extract the binary directory path from argv0
binaryDirectory = argv0;
size_t pos = binaryDirectory.find_last_of("\\/");
if (pos == std::string::npos)
binaryDirectory = "." + pathSeparator;
else
binaryDirectory.resize(pos + 1);
// pattern replacement: "./" at the start of path is replaced by the working directory
if (binaryDirectory.find("." + pathSeparator) == 0)
binaryDirectory.replace(0, 1, workingDirectory);
}
} // namespace CommandLine
+37 -5
View File
@@ -1,8 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
@@ -26,6 +24,7 @@
#include <ostream>
#include <string>
#include <vector>
#include <cstdint>
#include "types.h"
@@ -33,6 +32,10 @@ const std::string engine_info(bool to_uci = false);
const 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);
@@ -40,9 +43,7 @@ void dbg_mean_of(int v);
void dbg_print();
typedef std::chrono::milliseconds::rep TimePoint; // 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();
@@ -63,6 +64,17 @@ std::ostream& operator<<(std::ostream&, SyncCout);
#define sync_cout std::cout << IO_LOCK
#define sync_endl std::endl << IO_UNLOCK
// `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);
const uintptr_t ptrint = reinterpret_cast<uintptr_t>(reinterpret_cast<char*>(ptr));
return reinterpret_cast<T*>(reinterpret_cast<char*>((ptrint + (Alignment - 1)) / Alignment * Alignment));
}
/// xorshift64star Pseudo-Random Number Generator
/// This class is based on original code written and dedicated
@@ -100,6 +112,19 @@ public:
{ 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;
#else
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;
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
@@ -111,4 +136,11 @@ namespace WinProcGroup {
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
}
#endif // #ifndef MISC_H_INCLUDED
+79 -85
View File
@@ -1,8 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
@@ -29,22 +27,20 @@ namespace {
ExtMove* make_promotions(ExtMove* moveList, Square to, Square ksq) {
if (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS)
{
*moveList++ = make<PROMOTION>(to - D, to, QUEEN);
if (attacks_bb<KNIGHT>(to) & ksq)
*moveList++ = make<PROMOTION>(to - D, to, KNIGHT);
}
if (Type == QUIETS || Type == EVASIONS || Type == NON_EVASIONS)
{
*moveList++ = make<PROMOTION>(to - D, to, ROOK);
*moveList++ = make<PROMOTION>(to - D, to, BISHOP);
*moveList++ = make<PROMOTION>(to - D, to, KNIGHT);
if (!(attacks_bb<KNIGHT>(to) & ksq))
*moveList++ = make<PROMOTION>(to - D, to, KNIGHT);
}
// Knight promotion is the only promotion that can give a direct check
// that's not already included in the queen promotion.
if (Type == QUIET_CHECKS && (PseudoAttacks[KNIGHT][to] & ksq))
*moveList++ = make<PROMOTION>(to - D, to, KNIGHT);
else
(void)ksq; // Silence a warning under MSVC
return moveList;
}
@@ -52,8 +48,7 @@ namespace {
template<Color Us, GenType Type>
ExtMove* generate_pawn_moves(const Position& pos, ExtMove* moveList, Bitboard target) {
// Compute some compile time parameters relative to the white side
constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
constexpr Color Them = ~Us;
constexpr Bitboard TRank7BB = (Us == WHITE ? Rank7BB : Rank2BB);
constexpr Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB);
constexpr Direction Up = pawn_push(Us);
@@ -85,12 +80,12 @@ namespace {
if (Type == QUIET_CHECKS)
{
b1 &= pos.attacks_from<PAWN>(ksq, Them);
b2 &= pos.attacks_from<PAWN>(ksq, Them);
b1 &= pawn_attacks_bb(Them, ksq);
b2 &= pawn_attacks_bb(Them, ksq);
// Add pawn pushes which give discovered check. This is possible only
// if the pawn is not on the same file as the enemy king, because we
// don't generate captures. Note that a possible discovery check
// don't generate captures. Note that a possible discovered check
// promotion has been already generated amongst the captures.
Bitboard dcCandidateQuiets = pos.blockers_for_king(Them) & pawnsNotOn7;
if (dcCandidateQuiets)
@@ -139,7 +134,7 @@ namespace {
moveList = make_promotions<Type, Up >(moveList, pop_lsb(&b3), ksq);
}
// Standard and en-passant captures
// Standard and en passant captures
if (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS)
{
Bitboard b1 = shift<UpRight>(pawnsNotOn7) & enemies;
@@ -161,18 +156,16 @@ namespace {
{
assert(rank_of(pos.ep_square()) == relative_rank(Us, RANK_6));
// An en passant capture can be an evasion only if the checking piece
// is the double pushed pawn and so is in the target. Otherwise this
// is a discovery check and we are forced to do otherwise.
if (Type == EVASIONS && !(target & (pos.ep_square() - Up)))
// An en passant capture cannot resolve a discovered check.
if (Type == EVASIONS && (target & (pos.ep_square() + Up)))
return moveList;
b1 = pawnsNotOn7 & pos.attacks_from<PAWN>(pos.ep_square(), Them);
b1 = pawnsNotOn7 & pawn_attacks_bb(Them, pos.ep_square());
assert(b1);
while (b1)
*moveList++ = make<ENPASSANT>(pop_lsb(&b1), pos.ep_square());
*moveList++ = make<EN_PASSANT>(pop_lsb(&b1), pos.ep_square());
}
}
@@ -181,29 +174,23 @@ namespace {
template<PieceType Pt, bool Checks>
ExtMove* generate_moves(const Position& pos, ExtMove* moveList, Color us,
Bitboard target) {
ExtMove* generate_moves(const Position& pos, ExtMove* moveList, Bitboard piecesToMove, Bitboard target) {
static_assert(Pt != KING && Pt != PAWN, "Unsupported piece type in generate_moves()");
const Square* pl = pos.squares<Pt>(us);
Bitboard bb = piecesToMove & pos.pieces(Pt);
for (Square from = *pl; from != SQ_NONE; from = *++pl)
{
if (Checks)
{
if ( (Pt == BISHOP || Pt == ROOK || Pt == QUEEN)
&& !(PseudoAttacks[Pt][from] & target & pos.check_squares(Pt)))
continue;
if (!bb)
return moveList;
if (pos.blockers_for_king(~us) & from)
continue;
}
[[maybe_unused]] const Bitboard checkSquares = pos.check_squares(Pt);
Bitboard b = pos.attacks_from<Pt>(from) & target;
while (bb) {
Square from = pop_lsb(&bb);
if (Checks)
b &= pos.check_squares(Pt);
Bitboard b = attacks_bb<Pt>(from, pos.pieces()) & target;
if constexpr (Checks)
b &= checkSquares;
while (b)
*moveList++ = make_move(from, pop_lsb(&b));
@@ -214,33 +201,53 @@ namespace {
template<Color Us, GenType Type>
ExtMove* generate_all(const Position& pos, ExtMove* moveList, Bitboard target) {
ExtMove* generate_all(const Position& pos, ExtMove* moveList) {
constexpr CastlingRights OO = Us & KING_SIDE;
constexpr CastlingRights OOO = Us & QUEEN_SIDE;
constexpr bool Checks = Type == QUIET_CHECKS; // Reduce template instantations
static_assert(Type != LEGAL, "Unsupported type in generate_all()");
constexpr bool Checks = Type == QUIET_CHECKS; // Reduce template instantiations
Bitboard target, piecesToMove = pos.pieces(Us);
if(Type == QUIET_CHECKS)
piecesToMove &= ~pos.blockers_for_king(~Us);
switch (Type)
{
case CAPTURES:
target = pos.pieces(~Us);
break;
case QUIETS:
case QUIET_CHECKS:
target = ~pos.pieces();
break;
case EVASIONS:
{
Square checksq = lsb(pos.checkers());
target = between_bb(pos.square<KING>(Us), checksq) | checksq;
break;
}
case NON_EVASIONS:
target = ~pos.pieces(Us);
break;
}
moveList = generate_pawn_moves<Us, Type>(pos, moveList, target);
moveList = generate_moves<KNIGHT, Checks>(pos, moveList, Us, target);
moveList = generate_moves<BISHOP, Checks>(pos, moveList, Us, target);
moveList = generate_moves< ROOK, Checks>(pos, moveList, Us, target);
moveList = generate_moves< QUEEN, Checks>(pos, moveList, Us, target);
moveList = generate_moves<KNIGHT, Checks>(pos, moveList, piecesToMove, target);
moveList = generate_moves<BISHOP, Checks>(pos, moveList, piecesToMove, target);
moveList = generate_moves< ROOK, Checks>(pos, moveList, piecesToMove, target);
moveList = generate_moves< QUEEN, Checks>(pos, moveList, piecesToMove, target);
if (Type != QUIET_CHECKS && Type != EVASIONS)
{
Square ksq = pos.square<KING>(Us);
Bitboard b = pos.attacks_from<KING>(ksq) & target;
Bitboard b = attacks_bb<KING>(ksq) & target;
while (b)
*moveList++ = make_move(ksq, pop_lsb(&b));
if (Type != CAPTURES && pos.can_castle(CastlingRights(OO | OOO)))
{
if (!pos.castling_impeded(OO) && pos.can_castle(OO))
*moveList++ = make<CASTLING>(ksq, pos.castling_rook_square(OO));
if (!pos.castling_impeded(OOO) && pos.can_castle(OOO))
*moveList++ = make<CASTLING>(ksq, pos.castling_rook_square(OOO));
}
if ((Type != CAPTURES) && pos.can_castle(Us & ANY_CASTLING))
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));
}
return moveList;
@@ -249,8 +256,8 @@ namespace {
} // namespace
/// <CAPTURES> Generates all pseudo-legal captures and queen promotions
/// <QUIETS> Generates all pseudo-legal non-captures and underpromotions
/// <CAPTURES> Generates all pseudo-legal captures plus queen and checking knight promotions
/// <QUIETS> Generates all pseudo-legal non-captures and underpromotions (except checking knight)
/// <NON_EVASIONS> Generates all pseudo-legal captures and non-captures
///
/// Returns a pointer to the end of the move list.
@@ -263,12 +270,8 @@ ExtMove* generate(const Position& pos, ExtMove* moveList) {
Color us = pos.side_to_move();
Bitboard target = Type == CAPTURES ? pos.pieces(~us)
: Type == QUIETS ? ~pos.pieces()
: Type == NON_EVASIONS ? ~pos.pieces(us) : 0;
return us == WHITE ? generate_all<WHITE, Type>(pos, moveList, target)
: generate_all<BLACK, Type>(pos, moveList, target);
return us == WHITE ? generate_all<WHITE, Type>(pos, moveList)
: generate_all<BLACK, Type>(pos, moveList);
}
// Explicit template instantiations
@@ -277,35 +280,32 @@ template ExtMove* generate<QUIETS>(const Position&, ExtMove*);
template ExtMove* generate<NON_EVASIONS>(const Position&, ExtMove*);
/// generate<QUIET_CHECKS> generates all pseudo-legal non-captures and knight
/// underpromotions that give check. Returns a pointer to the end of the move list.
/// generate<QUIET_CHECKS> generates all pseudo-legal non-captures giving check,
/// except castling. Returns a pointer to the end of the move list.
template<>
ExtMove* generate<QUIET_CHECKS>(const Position& pos, ExtMove* moveList) {
assert(!pos.checkers());
Color us = pos.side_to_move();
Bitboard dc = pos.blockers_for_king(~us) & pos.pieces(us);
Bitboard dc = pos.blockers_for_king(~us) & pos.pieces(us) & ~pos.pieces(PAWN);
while (dc)
{
Square from = pop_lsb(&dc);
PieceType pt = type_of(pos.piece_on(from));
if (pt == PAWN)
continue; // Will be generated together with direct checks
Bitboard b = pos.attacks_from(pt, from) & ~pos.pieces();
Bitboard b = attacks_bb(pt, from, pos.pieces()) & ~pos.pieces();
if (pt == KING)
b &= ~PseudoAttacks[QUEEN][pos.square<KING>(~us)];
b &= ~attacks_bb<QUEEN>(pos.square<KING>(~us));
while (b)
*moveList++ = make_move(from, pop_lsb(&b));
}
return us == WHITE ? generate_all<WHITE, QUIET_CHECKS>(pos, moveList, ~pos.pieces())
: generate_all<BLACK, QUIET_CHECKS>(pos, moveList, ~pos.pieces());
return us == WHITE ? generate_all<WHITE, QUIET_CHECKS>(pos, moveList)
: generate_all<BLACK, QUIET_CHECKS>(pos, moveList);
}
@@ -325,13 +325,10 @@ ExtMove* generate<EVASIONS>(const Position& pos, ExtMove* moveList) {
// the king evasions in order to skip known illegal moves, which avoids any
// useless legality checks later on.
while (sliders)
{
Square checksq = pop_lsb(&sliders);
sliderAttacks |= LineBB[checksq][ksq] ^ checksq;
}
sliderAttacks |= line_bb(ksq, pop_lsb(&sliders)) & ~pos.checkers();
// Generate evasions for king, capture and non capture moves
Bitboard b = pos.attacks_from<KING>(ksq) & ~pos.pieces(us) & ~sliderAttacks;
Bitboard b = attacks_bb<KING>(ksq) & ~pos.pieces(us) & ~sliderAttacks;
while (b)
*moveList++ = make_move(ksq, pop_lsb(&b));
@@ -339,11 +336,8 @@ ExtMove* generate<EVASIONS>(const Position& pos, ExtMove* moveList) {
return moveList; // Double check, only a king move can save the day
// Generate blocking evasions or captures of the checking piece
Square checksq = lsb(pos.checkers());
Bitboard target = between_bb(checksq, ksq) | checksq;
return us == WHITE ? generate_all<WHITE, EVASIONS>(pos, moveList, target)
: generate_all<BLACK, EVASIONS>(pos, moveList, target);
return us == WHITE ? generate_all<WHITE, EVASIONS>(pos, moveList)
: generate_all<BLACK, EVASIONS>(pos, moveList);
}
@@ -360,7 +354,7 @@ ExtMove* generate<LEGAL>(const Position& pos, ExtMove* moveList) {
moveList = pos.checkers() ? generate<EVASIONS >(pos, moveList)
: generate<NON_EVASIONS>(pos, moveList);
while (cur != moveList)
if ( (pinned || from_sq(*cur) == ksq || type_of(*cur) == ENPASSANT)
if ( ((pinned && pinned & from_sq(*cur)) || from_sq(*cur) == ksq || type_of(*cur) == EN_PASSANT)
&& !pos.legal(*cur))
*cur = (--moveList)->move;
else
+1 -3
View File
@@ -1,8 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
+33 -39
View File
@@ -1,8 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
@@ -56,45 +54,40 @@ namespace {
/// 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, Move cm, Move* killers)
: pos(p), mainHistory(mh), captureHistory(cph), continuationHistory(ch),
refutations{{killers[0], 0}, {killers[1], 0}, {cm, 0}}, depth(d) {
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;
ttMove = ttm && pos.pseudo_legal(ttm) ? ttm : MOVE_NONE;
stage += (ttMove == MOVE_NONE);
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), recaptureSquare(rs), depth(d) {
: pos(p), mainHistory(mh), captureHistory(cph), continuationHistory(ch), ttMove(ttm), recaptureSquare(rs), depth(d) {
assert(d <= 0);
stage = pos.checkers() ? EVASION_TT : QSEARCH_TT;
ttMove = ttm
&& (depth > DEPTH_QS_RECAPTURES || to_sq(ttm) == recaptureSquare)
&& pos.pseudo_legal(ttm) ? ttm : MOVE_NONE;
stage += (ttMove == MOVE_NONE);
stage = (pos.checkers() ? EVASION_TT : QSEARCH_TT) +
!( ttm
&& (pos.checkers() || depth > DEPTH_QS_RECAPTURES || to_sq(ttm) == recaptureSquare)
&& 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), threshold(th) {
: pos(p), captureHistory(cph), ttMove(ttm), threshold(th) {
assert(!pos.checkers());
stage = PROBCUT_TT;
ttMove = ttm
&& pos.capture(ttm)
&& pos.pseudo_legal(ttm)
&& pos.see_ge(ttm, threshold) ? ttm : MOVE_NONE;
stage += (ttMove == MOVE_NONE);
stage = PROBCUT_TT + !(ttm && pos.capture(ttm)
&& pos.pseudo_legal(ttm)
&& pos.see_ge(ttm, threshold));
}
/// MovePicker::score() assigns a numerical value to each move in a list, used
@@ -106,16 +99,17 @@ void MovePicker::score() {
static_assert(Type == CAPTURES || Type == QUIETS || Type == EVASIONS, "Wrong type");
for (auto& m : *this)
if (Type == CAPTURES)
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)))];
else if (Type == QUIETS)
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)]
+ 2 * (*continuationHistory[1])[pos.moved_piece(m)][to_sq(m)]
+ 2 * (*continuationHistory[3])[pos.moved_piece(m)][to_sq(m)]
+ (*continuationHistory[5])[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 ? std::min(4, depth / 3) * (*lowPlyHistory)[ply][from_to(m)] : 0);
else // Type == EVASIONS
{
@@ -123,8 +117,8 @@ void MovePicker::score() {
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)]
+ (*continuationHistory[0])[pos.moved_piece(m)][to_sq(m)]
m.value = (*mainHistory)[pos.side_to_move()][from_to(m)]
+ 2 * (*continuationHistory[0])[pos.moved_piece(m)][to_sq(m)]
- (1 << 28);
}
}
@@ -148,7 +142,7 @@ Move MovePicker::select(Pred filter) {
}
/// 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
/// 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) {
@@ -174,7 +168,7 @@ top:
case GOOD_CAPTURE:
if (select<Best>([&](){
return pos.see_ge(*cur, Value(-55 * cur->value / 1024)) ?
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);
@@ -189,7 +183,7 @@ top:
--endMoves;
++stage;
/* fallthrough */
[[fallthrough]];
case REFUTATION:
if (select<Next>([&](){ return *cur != MOVE_NONE
@@ -197,7 +191,7 @@ top:
&& pos.pseudo_legal(*cur); }))
return *(cur - 1);
++stage;
/* fallthrough */
[[fallthrough]];
case QUIET_INIT:
if (!skipQuiets)
@@ -210,7 +204,7 @@ top:
}
++stage;
/* fallthrough */
[[fallthrough]];
case QUIET:
if ( !skipQuiets
@@ -224,7 +218,7 @@ top:
endMoves = endBadCaptures;
++stage;
/* fallthrough */
[[fallthrough]];
case BAD_CAPTURE:
return select<Next>([](){ return true; });
@@ -235,7 +229,7 @@ top:
score<EVASIONS>();
++stage;
/* fallthrough */
[[fallthrough]];
case EVASION:
return select<Best>([](){ return true; });
@@ -253,14 +247,14 @@ top:
return MOVE_NONE;
++stage;
/* fallthrough */
[[fallthrough]];
case QCHECK_INIT:
cur = moves;
endMoves = generate<QUIET_CHECKS>(pos, cur);
++stage;
/* fallthrough */
[[fallthrough]];
case QCHECK:
return select<Next>([](){ return true; });
+18 -10
View File
@@ -1,8 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
@@ -86,7 +84,13 @@ enum StatsType { NoCaptures, Captures };
/// 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, 10692, COLOR_NB, int(SQUARE_NB) * int(SQUARE_NB)> ButterflyHistory;
typedef Stats<int16_t, 13365, COLOR_NB, int(SQUARE_NB) * int(SQUARE_NB)> ButterflyHistory;
/// At higher depths LowPlyHistory records successful quiet moves near the root
/// and quiet moves which are/were in the PV (ttPv). It is cleared with each new
/// search and filled during iterative deepening.
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
@@ -104,12 +108,12 @@ typedef Stats<int16_t, 29952, PIECE_NB, SQUARE_NB> PieceToHistory;
typedef Stats<PieceToHistory, NOT_USED, PIECE_NB, SQUARE_NB> ContinuationHistory;
/// MovePicker class is used to pick one pseudo legal move at a time from the
/// 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.
/// 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 };
@@ -123,10 +127,12 @@ public:
const PieceToHistory**,
Square);
MovePicker(const Position&, Move, Depth, const ButterflyHistory*,
const LowPlyHistory*,
const CapturePieceToHistory*,
const PieceToHistory**,
Move,
Move*);
const Move*,
int);
Move next_move(bool skipQuiets = false);
private:
@@ -137,6 +143,7 @@ private:
const Position& pos;
const ButterflyHistory* mainHistory;
const LowPlyHistory* lowPlyHistory;
const CapturePieceToHistory* captureHistory;
const PieceToHistory** continuationHistory;
Move ttMove;
@@ -145,6 +152,7 @@ private:
Square recaptureSquare;
Value threshold;
Depth depth;
int ply;
ExtMove moves[MAX_MOVES];
};
@@ -0,0 +1,54 @@
/*
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/>.
*/
// Definition of input features and network structure used in NNUE evaluation function
#ifndef NNUE_HALFKP_256X2_32_32_H_INCLUDED
#define NNUE_HALFKP_256X2_32_32_H_INCLUDED
#include "../features/feature_set.h"
#include "../features/half_kp.h"
#include "../layers/input_slice.h"
#include "../layers/affine_transform.h"
#include "../layers/clipped_relu.h"
namespace Eval::NNUE {
// Input features used in evaluation function
using RawFeatures = Features::FeatureSet<
Features::HalfKP<Features::Side::kFriend>>;
// Number of input feature dimensions after conversion
constexpr IndexType kTransformedFeatureDimensions = 256;
namespace Layers {
// Define network structure
using InputLayer = InputSlice<kTransformedFeatureDimensions * 2>;
using HiddenLayer1 = ClippedReLU<AffineTransform<InputLayer, 32>>;
using HiddenLayer2 = ClippedReLU<AffineTransform<HiddenLayer1, 32>>;
using OutputLayer = AffineTransform<HiddenLayer2, 1>;
} // namespace Layers
using Network = Layers::OutputLayer;
} // namespace Eval::NNUE
#endif // #ifndef NNUE_HALFKP_256X2_32_32_H_INCLUDED
+144
View File
@@ -0,0 +1,144 @@
/*
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/>.
*/
// Code for calculating NNUE evaluation function
#include <iostream>
#include <set>
#include "../evaluate.h"
#include "../position.h"
#include "../misc.h"
#include "../uci.h"
#include "../types.h"
#include "evaluate_nnue.h"
namespace Eval::NNUE {
// Input feature converter
LargePagePtr<FeatureTransformer> feature_transformer;
// Evaluation function
AlignedPtr<Network> network;
// Evaluation function file name
std::string fileName;
namespace Detail {
// 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) {
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 ReadParameters(std::istream& stream, T& reference) {
std::uint32_t header;
header = read_little_endian<std::uint32_t>(stream);
if (!stream || header != T::GetHashValue()) return false;
return reference.ReadParameters(stream);
}
} // namespace Detail
// Initialize the evaluation function parameters
void Initialize() {
Detail::Initialize(feature_transformer);
Detail::Initialize(network);
}
// Read network header
bool ReadHeader(std::istream& stream, std::uint32_t* hash_value, std::string* architecture)
{
std::uint32_t version, size;
version = read_little_endian<std::uint32_t>(stream);
*hash_value = read_little_endian<std::uint32_t>(stream);
size = read_little_endian<std::uint32_t>(stream);
if (!stream || version != kVersion) return false;
architecture->resize(size);
stream.read(&(*architecture)[0], size);
return !stream.fail();
}
// Read network parameters
bool ReadParameters(std::istream& stream) {
std::uint32_t hash_value;
std::string architecture;
if (!ReadHeader(stream, &hash_value, &architecture)) return false;
if (hash_value != kHashValue) return false;
if (!Detail::ReadParameters(stream, *feature_transformer)) return false;
if (!Detail::ReadParameters(stream, *network)) return false;
return stream && stream.peek() == std::ios::traits_type::eof();
}
// Evaluation function. Perform differential calculation.
Value 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 = kCacheLineSize;
#if defined(ALIGNAS_ON_STACK_VARIABLES_BROKEN)
TransformedFeatureType transformed_features_unaligned[
FeatureTransformer::kBufferSize + alignment / sizeof(TransformedFeatureType)];
char buffer_unaligned[Network::kBufferSize + alignment];
auto* transformed_features = align_ptr_up<alignment>(&transformed_features_unaligned[0]);
auto* buffer = align_ptr_up<alignment>(&buffer_unaligned[0]);
#else
alignas(alignment)
TransformedFeatureType transformed_features[FeatureTransformer::kBufferSize];
alignas(alignment) char buffer[Network::kBufferSize];
#endif
ASSERT_ALIGNED(transformed_features, alignment);
ASSERT_ALIGNED(buffer, alignment);
feature_transformer->Transform(pos, transformed_features);
const auto output = network->Propagate(transformed_features, buffer);
return static_cast<Value>(output[0] / FV_SCALE);
}
// Load eval, from a file stream or a memory stream
bool load_eval(std::string name, std::istream& stream) {
Initialize();
fileName = name;
return ReadParameters(stream);
}
} // namespace Eval::NNUE
+59
View File
@@ -0,0 +1,59 @@
/*
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/>.
*/
// header used in NNUE evaluation function
#ifndef NNUE_EVALUATE_NNUE_H_INCLUDED
#define NNUE_EVALUATE_NNUE_H_INCLUDED
#include "nnue_feature_transformer.h"
#include <memory>
namespace Eval::NNUE {
// Hash value of evaluation function structure
constexpr std::uint32_t kHashValue =
FeatureTransformer::GetHashValue() ^ Network::GetHashValue();
// Deleter for automating release of memory area
template <typename T>
struct AlignedDeleter {
void operator()(T* ptr) const {
ptr->~T();
std_aligned_free(ptr);
}
};
template <typename T>
struct LargePageDeleter {
void operator()(T* ptr) const {
ptr->~T();
aligned_large_pages_free(ptr);
}
};
template <typename T>
using AlignedPtr = std::unique_ptr<T, AlignedDeleter<T>>;
template <typename T>
using LargePagePtr = std::unique_ptr<T, LargePageDeleter<T>>;
} // namespace Eval::NNUE
#endif // #ifndef NNUE_EVALUATE_NNUE_H_INCLUDED
+69
View File
@@ -0,0 +1,69 @@
/*
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/>.
*/
// A class template that represents the input feature set of the NNUE evaluation function
#ifndef NNUE_FEATURE_SET_H_INCLUDED
#define NNUE_FEATURE_SET_H_INCLUDED
#include "features_common.h"
#include <array>
namespace Eval::NNUE::Features {
// Class template that represents a list of values
template <typename T, T... Values>
struct CompileTimeList;
template <typename T, T First, T... Remaining>
struct CompileTimeList<T, First, Remaining...> {
static constexpr bool Contains(T value) {
return value == First || CompileTimeList<T, Remaining...>::Contains(value);
}
static constexpr std::array<T, sizeof...(Remaining) + 1>
kValues = {{First, Remaining...}};
};
// Base class of feature set
template <typename Derived>
class FeatureSetBase {
};
// Class template that represents the feature set
template <typename FeatureType>
class FeatureSet<FeatureType> : public FeatureSetBase<FeatureSet<FeatureType>> {
public:
// Hash value embedded in the evaluation file
static constexpr std::uint32_t kHashValue = FeatureType::kHashValue;
// Number of feature dimensions
static constexpr IndexType kDimensions = FeatureType::kDimensions;
// Maximum number of simultaneously active features
static constexpr IndexType kMaxActiveDimensions =
FeatureType::kMaxActiveDimensions;
// Trigger for full calculation instead of difference calculation
using SortedTriggerSet =
CompileTimeList<TriggerEvent, FeatureType::kRefreshTrigger>;
static constexpr auto kRefreshTriggers = SortedTriggerSet::kValues;
};
} // namespace Eval::NNUE::Features
#endif // #ifndef NNUE_FEATURE_SET_H_INCLUDED
+45
View File
@@ -0,0 +1,45 @@
/*
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/>.
*/
//Common header of input features of NNUE evaluation function
#ifndef NNUE_FEATURES_COMMON_H_INCLUDED
#define NNUE_FEATURES_COMMON_H_INCLUDED
#include "../../evaluate.h"
#include "../nnue_common.h"
namespace Eval::NNUE::Features {
class IndexList;
template <typename... FeatureTypes>
class FeatureSet;
// Trigger to perform full calculations instead of difference only
enum class TriggerEvent {
kFriendKingMoved // calculate full evaluation when own king moves
};
enum class Side {
kFriend // side to move
};
} // namespace Eval::NNUE::Features
#endif // #ifndef NNUE_FEATURES_COMMON_H_INCLUDED
+68
View File
@@ -0,0 +1,68 @@
/*
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/>.
*/
//Definition of input features HalfKP of NNUE evaluation function
#include "half_kp.h"
#include "index_list.h"
namespace Eval::NNUE::Features {
// Orient a square according to perspective (rotates by 180 for black)
inline Square orient(Color perspective, Square s) {
return Square(int(s) ^ (bool(perspective) * 63));
}
// Index of a feature for a given king position and another piece on some square
inline IndexType make_index(Color perspective, Square s, Piece pc, Square ksq) {
return IndexType(orient(perspective, s) + kpp_board_index[perspective][pc] + PS_END * ksq);
}
// Get a list of indices for active features
template <Side AssociatedKing>
void HalfKP<AssociatedKing>::AppendActiveIndices(
const Position& pos, Color perspective, IndexList* active) {
Square ksq = orient(perspective, pos.square<KING>(perspective));
Bitboard bb = pos.pieces() & ~pos.pieces(KING);
while (bb) {
Square s = pop_lsb(&bb);
active->push_back(make_index(perspective, s, pos.piece_on(s), ksq));
}
}
// Get a list of indices for recently changed features
template <Side AssociatedKing>
void HalfKP<AssociatedKing>::AppendChangedIndices(
const Position& pos, const DirtyPiece& dp, Color perspective,
IndexList* removed, IndexList* added) {
Square ksq = orient(perspective, pos.square<KING>(perspective));
for (int i = 0; i < dp.dirty_num; ++i) {
Piece pc = dp.piece[i];
if (type_of(pc) == KING) continue;
if (dp.from[i] != SQ_NONE)
removed->push_back(make_index(perspective, dp.from[i], pc, ksq));
if (dp.to[i] != SQ_NONE)
added->push_back(make_index(perspective, dp.to[i], pc, ksq));
}
}
template class HalfKP<Side::kFriend>;
} // namespace Eval::NNUE::Features
+59
View File
@@ -0,0 +1,59 @@
/*
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/>.
*/
//Definition of input features HalfKP of NNUE evaluation function
#ifndef NNUE_FEATURES_HALF_KP_H_INCLUDED
#define NNUE_FEATURES_HALF_KP_H_INCLUDED
#include "../../evaluate.h"
#include "features_common.h"
namespace Eval::NNUE::Features {
// Feature HalfKP: Combination of the position of own king
// and the position of pieces other than kings
template <Side AssociatedKing>
class HalfKP {
public:
// Feature name
static constexpr const char* kName = "HalfKP(Friend)";
// Hash value embedded in the evaluation file
static constexpr std::uint32_t kHashValue =
0x5D69D5B9u ^ (AssociatedKing == Side::kFriend);
// Number of feature dimensions
static constexpr IndexType kDimensions =
static_cast<IndexType>(SQUARE_NB) * static_cast<IndexType>(PS_END);
// Maximum number of simultaneously active features
static constexpr IndexType kMaxActiveDimensions = 30; // Kings don't count
// Trigger for full calculation instead of difference calculation
static constexpr TriggerEvent kRefreshTrigger = TriggerEvent::kFriendKingMoved;
// Get a list of indices for active features
static void AppendActiveIndices(const Position& pos, Color perspective,
IndexList* active);
// Get a list of indices for recently changed features
static void AppendChangedIndices(const Position& pos, const DirtyPiece& dp, Color perspective,
IndexList* removed, IndexList* added);
};
} // namespace Eval::NNUE::Features
#endif // #ifndef NNUE_FEATURES_HALF_KP_H_INCLUDED
+64
View File
@@ -0,0 +1,64 @@
/*
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/>.
*/
// Definition of index list of input features
#ifndef NNUE_FEATURES_INDEX_LIST_H_INCLUDED
#define NNUE_FEATURES_INDEX_LIST_H_INCLUDED
#include "../../position.h"
#include "../nnue_architecture.h"
namespace Eval::NNUE::Features {
// Class template used for feature index list
template <typename T, std::size_t MaxSize>
class ValueList {
public:
std::size_t size() const { return size_; }
void resize(std::size_t size) { size_ = size; }
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_; }
void swap(ValueList& other) {
const std::size_t max_size = std::max(size_, other.size_);
for (std::size_t i = 0; i < max_size; ++i) {
std::swap(values_[i], other.values_[i]);
}
std::swap(size_, other.size_);
}
private:
T values_[MaxSize];
std::size_t size_ = 0;
};
//Type of feature index list
class IndexList
: public ValueList<IndexType, RawFeatures::kMaxActiveDimensions> {
};
} // namespace Eval::NNUE::Features
#endif // NNUE_FEATURES_INDEX_LIST_H_INCLUDED
+464
View File
@@ -0,0 +1,464 @@
/*
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/>.
*/
// Definition of layer AffineTransform of NNUE evaluation function
#ifndef NNUE_LAYERS_AFFINE_TRANSFORM_H_INCLUDED
#define NNUE_LAYERS_AFFINE_TRANSFORM_H_INCLUDED
#include <iostream>
#include "../nnue_common.h"
namespace Eval::NNUE::Layers {
// Affine transformation layer
template <typename PreviousLayer, IndexType OutputDimensions>
class AffineTransform {
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 kInputDimensions =
PreviousLayer::kOutputDimensions;
static constexpr IndexType kOutputDimensions = OutputDimensions;
static constexpr IndexType kPaddedInputDimensions =
CeilToMultiple<IndexType>(kInputDimensions, kMaxSimdWidth);
#if defined (USE_AVX512)
static constexpr const IndexType kOutputSimdWidth = kSimdWidth / 2;
#elif defined (USE_SSSE3)
static constexpr const IndexType kOutputSimdWidth = kSimdWidth / 4;
#endif
// Size of forward propagation buffer used in this layer
static constexpr std::size_t kSelfBufferSize =
CeilToMultiple(kOutputDimensions * sizeof(OutputType), kCacheLineSize);
// Size of the forward propagation buffer used from the input layer to this layer
static constexpr std::size_t kBufferSize =
PreviousLayer::kBufferSize + kSelfBufferSize;
// Hash value embedded in the evaluation file
static constexpr std::uint32_t GetHashValue() {
std::uint32_t hash_value = 0xCC03DAE4u;
hash_value += kOutputDimensions;
hash_value ^= PreviousLayer::GetHashValue() >> 1;
hash_value ^= PreviousLayer::GetHashValue() << 31;
return hash_value;
}
// Read network parameters
bool ReadParameters(std::istream& stream) {
if (!previous_layer_.ReadParameters(stream)) return false;
for (std::size_t i = 0; i < kOutputDimensions; ++i)
biases_[i] = read_little_endian<BiasType>(stream);
for (std::size_t i = 0; i < kOutputDimensions * kPaddedInputDimensions; ++i)
#if !defined (USE_SSSE3)
weights_[i] = read_little_endian<WeightType>(stream);
#else
weights_[
(i / 4) % (kPaddedInputDimensions / 4) * kOutputDimensions * 4 +
i / kPaddedInputDimensions * 4 +
i % 4
] = read_little_endian<WeightType>(stream);
// Determine if eights of weight and input products can be summed using 16bits
// without saturation. We assume worst case combinations of 0 and 127 for all inputs.
if (kOutputDimensions > 1 && !stream.fail())
{
canSaturate16.count = 0;
#if !defined(USE_VNNI)
for (IndexType i = 0; i < kPaddedInputDimensions; i += 16)
for (IndexType j = 0; j < kOutputDimensions; ++j)
for (int x = 0; x < 2; ++x)
{
WeightType* w = &weights_[i * kOutputDimensions + j * 4 + x * 2];
int sum[2] = {0, 0};
for (int k = 0; k < 8; ++k)
{
IndexType idx = k / 2 * kOutputDimensions * 4 + k % 2;
sum[w[idx] < 0] += w[idx];
}
for (int sign : {-1, 1})
while (sign * sum[sign == -1] > 258)
{
int maxK = 0, maxW = 0;
for (int k = 0; k < 8; ++k)
{
IndexType idx = k / 2 * kOutputDimensions * 4 + k % 2;
if (maxW < sign * w[idx])
maxK = k, maxW = sign * w[idx];
}
IndexType idx = maxK / 2 * kOutputDimensions * 4 + maxK % 2;
sum[sign == -1] -= w[idx];
canSaturate16.add(j, i + maxK / 2 * 4 + maxK % 2 + x * 2, w[idx]);
w[idx] = 0;
}
}
// Non functional optimization for faster more linear access
std::sort(canSaturate16.ids, canSaturate16.ids + canSaturate16.count,
[](const typename CanSaturate::Entry& e1, const typename CanSaturate::Entry& e2)
{ return e1.in == e2.in ? e1.out < e2.out : e1.in < e2.in; });
#endif
}
#endif
return !stream.fail();
}
// Forward propagation
const OutputType* Propagate(
const TransformedFeatureType* transformed_features, char* buffer) const {
const auto input = previous_layer_.Propagate(
transformed_features, buffer + kSelfBufferSize);
#if defined (USE_AVX512)
[[maybe_unused]] const __m512i kOnes512 = _mm512_set1_epi16(1);
[[maybe_unused]] auto m512_hadd = [](__m512i sum, int bias) -> int {
return _mm512_reduce_add_epi32(sum) + bias;
};
[[maybe_unused]] auto 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, kOnes512);
acc = _mm512_add_epi32(acc, product0);
#endif
};
[[maybe_unused]] auto m512_add_dpbusd_epi32x4 = [=](__m512i& acc, __m512i a0, __m512i b0, __m512i a1, __m512i b1,
__m512i a2, __m512i b2, __m512i a3, __m512i b3) {
#if defined (USE_VNNI)
acc = _mm512_dpbusd_epi32(acc, a0, b0);
acc = _mm512_dpbusd_epi32(acc, a1, b1);
acc = _mm512_dpbusd_epi32(acc, a2, b2);
acc = _mm512_dpbusd_epi32(acc, a3, b3);
#else
__m512i product0 = _mm512_maddubs_epi16(a0, b0);
__m512i product1 = _mm512_maddubs_epi16(a1, b1);
__m512i product2 = _mm512_maddubs_epi16(a2, b2);
__m512i product3 = _mm512_maddubs_epi16(a3, b3);
product0 = _mm512_add_epi16(product0, product1);
product2 = _mm512_add_epi16(product2, product3);
product0 = _mm512_add_epi16(product0, product2);
product0 = _mm512_madd_epi16(product0, kOnes512);
acc = _mm512_add_epi32(acc, product0);
#endif
};
#endif
#if defined (USE_AVX2)
[[maybe_unused]] const __m256i kOnes256 = _mm256_set1_epi16(1);
[[maybe_unused]] auto m256_hadd = [](__m256i sum, int bias) -> int {
__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]] auto 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, kOnes256);
acc = _mm256_add_epi32(acc, product0);
#endif
};
[[maybe_unused]] auto m256_add_dpbusd_epi32x4 = [=](__m256i& acc, __m256i a0, __m256i b0, __m256i a1, __m256i b1,
__m256i a2, __m256i b2, __m256i a3, __m256i b3) {
#if defined (USE_VNNI)
acc = _mm256_dpbusd_epi32(acc, a0, b0);
acc = _mm256_dpbusd_epi32(acc, a1, b1);
acc = _mm256_dpbusd_epi32(acc, a2, b2);
acc = _mm256_dpbusd_epi32(acc, a3, b3);
#else
__m256i product0 = _mm256_maddubs_epi16(a0, b0);
__m256i product1 = _mm256_maddubs_epi16(a1, b1);
__m256i product2 = _mm256_maddubs_epi16(a2, b2);
__m256i product3 = _mm256_maddubs_epi16(a3, b3);
product0 = _mm256_add_epi16(product0, product1);
product2 = _mm256_add_epi16(product2, product3);
product0 = _mm256_add_epi16(product0, product2);
product0 = _mm256_madd_epi16(product0, kOnes256);
acc = _mm256_add_epi32(acc, product0);
#endif
};
#endif
#if defined (USE_SSSE3)
[[maybe_unused]] const __m128i kOnes128 = _mm_set1_epi16(1);
[[maybe_unused]] auto m128_hadd = [](__m128i sum, int bias) -> int {
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]] auto m128_add_dpbusd_epi32 = [=](__m128i& acc, __m128i a, __m128i b) {
__m128i product0 = _mm_maddubs_epi16(a, b);
product0 = _mm_madd_epi16(product0, kOnes128);
acc = _mm_add_epi32(acc, product0);
};
[[maybe_unused]] auto m128_add_dpbusd_epi32x4 = [=](__m128i& acc, __m128i a0, __m128i b0, __m128i a1, __m128i b1,
__m128i a2, __m128i b2, __m128i a3, __m128i b3) {
__m128i product0 = _mm_maddubs_epi16(a0, b0);
__m128i product1 = _mm_maddubs_epi16(a1, b1);
__m128i product2 = _mm_maddubs_epi16(a2, b2);
__m128i product3 = _mm_maddubs_epi16(a3, b3);
product0 = _mm_adds_epi16(product0, product1);
product2 = _mm_adds_epi16(product2, product3);
product0 = _mm_adds_epi16(product0, product2);
product0 = _mm_madd_epi16(product0, kOnes128);
acc = _mm_add_epi32(acc, product0);
};
#endif
#if defined (USE_AVX512)
using vec_t = __m512i;
#define vec_setzero _mm512_setzero_si512
#define vec_set_32 _mm512_set1_epi32
auto& vec_add_dpbusd_32 = m512_add_dpbusd_epi32;
auto& vec_add_dpbusd_32x4 = m512_add_dpbusd_epi32x4;
auto& vec_hadd = m512_hadd;
#elif defined (USE_AVX2)
using vec_t = __m256i;
#define vec_setzero _mm256_setzero_si256
#define vec_set_32 _mm256_set1_epi32
auto& vec_add_dpbusd_32 = m256_add_dpbusd_epi32;
auto& vec_add_dpbusd_32x4 = m256_add_dpbusd_epi32x4;
auto& vec_hadd = m256_hadd;
#elif defined (USE_SSSE3)
using vec_t = __m128i;
#define vec_setzero _mm_setzero_si128
#define vec_set_32 _mm_set1_epi32
auto& vec_add_dpbusd_32 = m128_add_dpbusd_epi32;
auto& vec_add_dpbusd_32x4 = m128_add_dpbusd_epi32x4;
auto& vec_hadd = m128_hadd;
#endif
#if defined (USE_SSSE3)
const auto output = reinterpret_cast<OutputType*>(buffer);
const auto input_vector = reinterpret_cast<const vec_t*>(input);
static_assert(kOutputDimensions % kOutputSimdWidth == 0 || kOutputDimensions == 1);
// kOutputDimensions is either 1 or a multiple of kSimdWidth
// because then it is also an input dimension.
if constexpr (kOutputDimensions % kOutputSimdWidth == 0)
{
constexpr IndexType kNumChunks = kPaddedInputDimensions / 4;
const auto input32 = reinterpret_cast<const std::int32_t*>(input);
vec_t* outptr = reinterpret_cast<vec_t*>(output);
std::memcpy(output, biases_, kOutputDimensions * sizeof(OutputType));
for (int i = 0; i < (int)kNumChunks - 3; i += 4)
{
const vec_t in0 = vec_set_32(input32[i + 0]);
const vec_t in1 = vec_set_32(input32[i + 1]);
const vec_t in2 = vec_set_32(input32[i + 2]);
const vec_t in3 = vec_set_32(input32[i + 3]);
const auto col0 = reinterpret_cast<const vec_t*>(&weights_[(i + 0) * kOutputDimensions * 4]);
const auto col1 = reinterpret_cast<const vec_t*>(&weights_[(i + 1) * kOutputDimensions * 4]);
const auto col2 = reinterpret_cast<const vec_t*>(&weights_[(i + 2) * kOutputDimensions * 4]);
const auto col3 = reinterpret_cast<const vec_t*>(&weights_[(i + 3) * kOutputDimensions * 4]);
for (int j = 0; j * kOutputSimdWidth < kOutputDimensions; ++j)
vec_add_dpbusd_32x4(outptr[j], in0, col0[j], in1, col1[j], in2, col2[j], in3, col3[j]);
}
for (int i = 0; i < canSaturate16.count; ++i)
output[canSaturate16.ids[i].out] += input[canSaturate16.ids[i].in] * canSaturate16.ids[i].w;
}
else if constexpr (kOutputDimensions == 1)
{
#if defined (USE_AVX512)
if constexpr (kPaddedInputDimensions % (kSimdWidth * 2) != 0)
{
constexpr IndexType kNumChunks = kPaddedInputDimensions / kSimdWidth;
const auto input_vector256 = reinterpret_cast<const __m256i*>(input);
__m256i sum0 = _mm256_setzero_si256();
const auto row0 = reinterpret_cast<const __m256i*>(&weights_[0]);
for (int j = 0; j < (int)kNumChunks; ++j)
{
const __m256i in = input_vector256[j];
m256_add_dpbusd_epi32(sum0, in, row0[j]);
}
output[0] = m256_hadd(sum0, biases_[0]);
}
else
#endif
{
#if defined (USE_AVX512)
constexpr IndexType kNumChunks = kPaddedInputDimensions / (kSimdWidth * 2);
#else
constexpr IndexType kNumChunks = kPaddedInputDimensions / kSimdWidth;
#endif
vec_t sum0 = vec_setzero();
const auto row0 = reinterpret_cast<const vec_t*>(&weights_[0]);
for (int j = 0; j < (int)kNumChunks; ++j)
{
const vec_t in = input_vector[j];
vec_add_dpbusd_32(sum0, in, row0[j]);
}
output[0] = vec_hadd(sum0, biases_[0]);
}
}
#else
// Use old implementation for the other architectures.
auto output = reinterpret_cast<OutputType*>(buffer);
#if defined(USE_SSE2)
constexpr IndexType kNumChunks = kPaddedInputDimensions / kSimdWidth;
const __m128i kZeros = _mm_setzero_si128();
const auto input_vector = reinterpret_cast<const __m128i*>(input);
#elif defined(USE_MMX)
constexpr IndexType kNumChunks = kPaddedInputDimensions / kSimdWidth;
const __m64 kZeros = _mm_setzero_si64();
const auto input_vector = reinterpret_cast<const __m64*>(input);
#elif defined(USE_NEON)
constexpr IndexType kNumChunks = kPaddedInputDimensions / kSimdWidth;
const auto input_vector = reinterpret_cast<const int8x8_t*>(input);
#endif
for (IndexType i = 0; i < kOutputDimensions; ++i) {
const IndexType offset = i * kPaddedInputDimensions;
#if defined(USE_SSE2)
__m128i sum_lo = _mm_cvtsi32_si128(biases_[i]);
__m128i sum_hi = kZeros;
const auto row = reinterpret_cast<const __m128i*>(&weights_[offset]);
for (IndexType j = 0; j < kNumChunks; ++j) {
__m128i row_j = _mm_load_si128(&row[j]);
__m128i input_j = _mm_load_si128(&input_vector[j]);
__m128i extended_row_lo = _mm_srai_epi16(_mm_unpacklo_epi8(row_j, row_j), 8);
__m128i extended_row_hi = _mm_srai_epi16(_mm_unpackhi_epi8(row_j, row_j), 8);
__m128i extended_input_lo = _mm_unpacklo_epi8(input_j, kZeros);
__m128i extended_input_hi = _mm_unpackhi_epi8(input_j, kZeros);
__m128i product_lo = _mm_madd_epi16(extended_row_lo, extended_input_lo);
__m128i product_hi = _mm_madd_epi16(extended_row_hi, extended_input_hi);
sum_lo = _mm_add_epi32(sum_lo, product_lo);
sum_hi = _mm_add_epi32(sum_hi, product_hi);
}
__m128i sum = _mm_add_epi32(sum_lo, sum_hi);
__m128i sum_high_64 = _mm_shuffle_epi32(sum, _MM_SHUFFLE(1, 0, 3, 2));
sum = _mm_add_epi32(sum, sum_high_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 sum_lo = _mm_cvtsi32_si64(biases_[i]);
__m64 sum_hi = kZeros;
const auto row = reinterpret_cast<const __m64*>(&weights_[offset]);
for (IndexType j = 0; j < kNumChunks; ++j) {
__m64 row_j = row[j];
__m64 input_j = input_vector[j];
__m64 extended_row_lo = _mm_srai_pi16(_mm_unpacklo_pi8(row_j, row_j), 8);
__m64 extended_row_hi = _mm_srai_pi16(_mm_unpackhi_pi8(row_j, row_j), 8);
__m64 extended_input_lo = _mm_unpacklo_pi8(input_j, kZeros);
__m64 extended_input_hi = _mm_unpackhi_pi8(input_j, kZeros);
__m64 product_lo = _mm_madd_pi16(extended_row_lo, extended_input_lo);
__m64 product_hi = _mm_madd_pi16(extended_row_hi, extended_input_hi);
sum_lo = _mm_add_pi32(sum_lo, product_lo);
sum_hi = _mm_add_pi32(sum_hi, product_hi);
}
__m64 sum = _mm_add_pi32(sum_lo, sum_hi);
sum = _mm_add_pi32(sum, _mm_unpackhi_pi32(sum, sum));
output[i] = _mm_cvtsi64_si32(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 < kNumChunks; ++j) {
int16x8_t product = vmull_s8(input_vector[j * 2], row[j * 2]);
product = vmlal_s8(product, input_vector[j * 2 + 1], row[j * 2 + 1]);
sum = vpadalq_s16(sum, product);
}
output[i] = sum[0] + sum[1] + sum[2] + sum[3];
#else
OutputType sum = biases_[i];
for (IndexType j = 0; j < kInputDimensions; ++j) {
sum += weights_[offset + j] * input[j];
}
output[i] = sum;
#endif
}
#if defined(USE_MMX)
_mm_empty();
#endif
#endif
return output;
}
private:
using BiasType = OutputType;
using WeightType = std::int8_t;
PreviousLayer previous_layer_;
alignas(kCacheLineSize) BiasType biases_[kOutputDimensions];
alignas(kCacheLineSize) WeightType weights_[kOutputDimensions * kPaddedInputDimensions];
#if defined (USE_SSSE3)
struct CanSaturate {
int count;
struct Entry {
uint16_t out;
uint16_t in;
int8_t w;
} ids[kPaddedInputDimensions * kOutputDimensions * 3 / 4];
void add(int i, int j, int8_t w) {
ids[count].out = i;
ids[count].in = j;
ids[count].w = w;
++count;
}
} canSaturate16;
#endif
};
} // namespace Eval::NNUE::Layers
#endif // #ifndef NNUE_LAYERS_AFFINE_TRANSFORM_H_INCLUDED
+166
View File
@@ -0,0 +1,166 @@
/*
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/>.
*/
// Definition of layer ClippedReLU of NNUE evaluation function
#ifndef NNUE_LAYERS_CLIPPED_RELU_H_INCLUDED
#define NNUE_LAYERS_CLIPPED_RELU_H_INCLUDED
#include "../nnue_common.h"
namespace Eval::NNUE::Layers {
// Clipped ReLU
template <typename PreviousLayer>
class ClippedReLU {
public:
// Input/output type
using InputType = typename PreviousLayer::OutputType;
using OutputType = std::uint8_t;
static_assert(std::is_same<InputType, std::int32_t>::value, "");
// Number of input/output dimensions
static constexpr IndexType kInputDimensions =
PreviousLayer::kOutputDimensions;
static constexpr IndexType kOutputDimensions = kInputDimensions;
// Size of forward propagation buffer used in this layer
static constexpr std::size_t kSelfBufferSize =
CeilToMultiple(kOutputDimensions * sizeof(OutputType), kCacheLineSize);
// Size of the forward propagation buffer used from the input layer to this layer
static constexpr std::size_t kBufferSize =
PreviousLayer::kBufferSize + kSelfBufferSize;
// Hash value embedded in the evaluation file
static constexpr std::uint32_t GetHashValue() {
std::uint32_t hash_value = 0x538D24C7u;
hash_value += PreviousLayer::GetHashValue();
return hash_value;
}
// Read network parameters
bool ReadParameters(std::istream& stream) {
return previous_layer_.ReadParameters(stream);
}
// Forward propagation
const OutputType* Propagate(
const TransformedFeatureType* transformed_features, char* buffer) const {
const auto input = previous_layer_.Propagate(
transformed_features, buffer + kSelfBufferSize);
const auto output = reinterpret_cast<OutputType*>(buffer);
#if defined(USE_AVX2)
constexpr IndexType kNumChunks = kInputDimensions / kSimdWidth;
const __m256i kZero = _mm256_setzero_si256();
const __m256i kOffsets = _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 < kNumChunks; ++i) {
const __m256i words0 = _mm256_srai_epi16(_mm256_packs_epi32(
_mm256_load_si256(&in[i * 4 + 0]),
_mm256_load_si256(&in[i * 4 + 1])), kWeightScaleBits);
const __m256i words1 = _mm256_srai_epi16(_mm256_packs_epi32(
_mm256_load_si256(&in[i * 4 + 2]),
_mm256_load_si256(&in[i * 4 + 3])), kWeightScaleBits);
_mm256_store_si256(&out[i], _mm256_permutevar8x32_epi32(_mm256_max_epi8(
_mm256_packs_epi16(words0, words1), kZero), kOffsets));
}
constexpr IndexType kStart = kNumChunks * kSimdWidth;
#elif defined(USE_SSE2)
constexpr IndexType kNumChunks = kInputDimensions / kSimdWidth;
#ifdef USE_SSE41
const __m128i kZero = _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 < kNumChunks; ++i) {
const __m128i words0 = _mm_srai_epi16(_mm_packs_epi32(
_mm_load_si128(&in[i * 4 + 0]),
_mm_load_si128(&in[i * 4 + 1])), kWeightScaleBits);
const __m128i words1 = _mm_srai_epi16(_mm_packs_epi32(
_mm_load_si128(&in[i * 4 + 2]),
_mm_load_si128(&in[i * 4 + 3])), kWeightScaleBits);
const __m128i packedbytes = _mm_packs_epi16(words0, words1);
_mm_store_si128(&out[i],
#ifdef USE_SSE41
_mm_max_epi8(packedbytes, kZero)
#else
_mm_subs_epi8(_mm_adds_epi8(packedbytes, k0x80s), k0x80s)
#endif
);
}
constexpr IndexType kStart = kNumChunks * kSimdWidth;
#elif defined(USE_MMX)
constexpr IndexType kNumChunks = kInputDimensions / kSimdWidth;
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 < kNumChunks; ++i) {
const __m64 words0 = _mm_srai_pi16(
_mm_packs_pi32(in[i * 4 + 0], in[i * 4 + 1]),
kWeightScaleBits);
const __m64 words1 = _mm_srai_pi16(
_mm_packs_pi32(in[i * 4 + 2], in[i * 4 + 3]),
kWeightScaleBits);
const __m64 packedbytes = _mm_packs_pi16(words0, words1);
out[i] = _mm_subs_pi8(_mm_adds_pi8(packedbytes, k0x80s), k0x80s);
}
_mm_empty();
constexpr IndexType kStart = kNumChunks * kSimdWidth;
#elif defined(USE_NEON)
constexpr IndexType kNumChunks = kInputDimensions / (kSimdWidth / 2);
const int8x8_t kZero = {0};
const auto in = reinterpret_cast<const int32x4_t*>(input);
const auto out = reinterpret_cast<int8x8_t*>(output);
for (IndexType i = 0; i < kNumChunks; ++i) {
int16x8_t shifted;
const auto pack = reinterpret_cast<int16x4_t*>(&shifted);
pack[0] = vqshrn_n_s32(in[i * 2 + 0], kWeightScaleBits);
pack[1] = vqshrn_n_s32(in[i * 2 + 1], kWeightScaleBits);
out[i] = vmax_s8(vqmovn_s16(shifted), kZero);
}
constexpr IndexType kStart = kNumChunks * (kSimdWidth / 2);
#else
constexpr IndexType kStart = 0;
#endif
for (IndexType i = kStart; i < kInputDimensions; ++i) {
output[i] = static_cast<OutputType>(
std::max(0, std::min(127, input[i] >> kWeightScaleBits)));
}
return output;
}
private:
PreviousLayer previous_layer_;
};
} // namespace Eval::NNUE::Layers
#endif // NNUE_LAYERS_CLIPPED_RELU_H_INCLUDED
+68
View File
@@ -0,0 +1,68 @@
/*
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 Eval::NNUE::Layers {
// Input layer
template <IndexType OutputDimensions, IndexType Offset = 0>
class InputSlice {
public:
// Need to maintain alignment
static_assert(Offset % kMaxSimdWidth == 0, "");
// Output type
using OutputType = TransformedFeatureType;
// Output dimensionality
static constexpr IndexType kOutputDimensions = OutputDimensions;
// Size of forward propagation buffer used from the input layer to this layer
static constexpr std::size_t kBufferSize = 0;
// Hash value embedded in the evaluation file
static constexpr std::uint32_t GetHashValue() {
std::uint32_t hash_value = 0xEC42E90Du;
hash_value ^= kOutputDimensions ^ (Offset << 10);
return hash_value;
}
// Read network parameters
bool ReadParameters(std::istream& /*stream*/) {
return true;
}
// Forward propagation
const OutputType* Propagate(
const TransformedFeatureType* transformed_features,
char* /*buffer*/) const {
return transformed_features + Offset;
}
private:
};
} // namespace Layers
#endif // #ifndef NNUE_LAYERS_INPUT_SLICE_H_INCLUDED
+40
View File
@@ -0,0 +1,40 @@
/*
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/>.
*/
// Class for difference calculation of NNUE evaluation function
#ifndef NNUE_ACCUMULATOR_H_INCLUDED
#define NNUE_ACCUMULATOR_H_INCLUDED
#include "nnue_architecture.h"
namespace Eval::NNUE {
// The accumulator of a StateInfo without parent is set to the INIT state
enum AccumulatorState { EMPTY, COMPUTED, INIT };
// Class that holds the result of affine transformation of input features
struct alignas(kCacheLineSize) Accumulator {
std::int16_t
accumulation[2][kRefreshTriggers.size()][kTransformedFeatureDimensions];
AccumulatorState state[2];
};
} // namespace Eval::NNUE
#endif // NNUE_ACCUMULATOR_H_INCLUDED
+38
View File
@@ -0,0 +1,38 @@
/*
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/>.
*/
// Input features and network structure used in NNUE evaluation function
#ifndef NNUE_ARCHITECTURE_H_INCLUDED
#define NNUE_ARCHITECTURE_H_INCLUDED
// Defines the network structure
#include "architectures/halfkp_256x2-32-32.h"
namespace Eval::NNUE {
static_assert(kTransformedFeatureDimensions % kMaxSimdWidth == 0, "");
static_assert(Network::kOutputDimensions == 1, "");
static_assert(std::is_same<Network::OutputType, std::int32_t>::value, "");
// Trigger for full calculation instead of difference calculation
constexpr auto kRefreshTriggers = RawFeatures::kRefreshTriggers;
} // namespace Eval::NNUE
#endif // #ifndef NNUE_ARCHITECTURE_H_INCLUDED
+132
View File
@@ -0,0 +1,132 @@
/*
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/>.
*/
// Constants used in NNUE evaluation function
#ifndef NNUE_COMMON_H_INCLUDED
#define NNUE_COMMON_H_INCLUDED
#include <cstring>
#include <iostream>
#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
namespace Eval::NNUE {
// Version of the evaluation file
constexpr std::uint32_t kVersion = 0x7AF32F16u;
// Constant used in evaluation value calculation
constexpr int FV_SCALE = 16;
constexpr int kWeightScaleBits = 6;
// Size of cache line (in bytes)
constexpr std::size_t kCacheLineSize = 64;
// SIMD width (in bytes)
#if defined(USE_AVX2)
constexpr std::size_t kSimdWidth = 32;
#elif defined(USE_SSE2)
constexpr std::size_t kSimdWidth = 16;
#elif defined(USE_MMX)
constexpr std::size_t kSimdWidth = 8;
#elif defined(USE_NEON)
constexpr std::size_t kSimdWidth = 16;
#endif
constexpr std::size_t kMaxSimdWidth = 32;
// unique number for each piece type on each square
enum {
PS_NONE = 0,
PS_W_PAWN = 1,
PS_B_PAWN = 1 * SQUARE_NB + 1,
PS_W_KNIGHT = 2 * SQUARE_NB + 1,
PS_B_KNIGHT = 3 * SQUARE_NB + 1,
PS_W_BISHOP = 4 * SQUARE_NB + 1,
PS_B_BISHOP = 5 * SQUARE_NB + 1,
PS_W_ROOK = 6 * SQUARE_NB + 1,
PS_B_ROOK = 7 * SQUARE_NB + 1,
PS_W_QUEEN = 8 * SQUARE_NB + 1,
PS_B_QUEEN = 9 * SQUARE_NB + 1,
PS_W_KING = 10 * SQUARE_NB + 1,
PS_END = PS_W_KING, // pieces without kings (pawns included)
PS_B_KING = 11 * SQUARE_NB + 1,
PS_END2 = 12 * SQUARE_NB + 1
};
constexpr uint32_t kpp_board_index[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_W_KING, PS_NONE,
PS_NONE, PS_B_PAWN, PS_B_KNIGHT, PS_B_BISHOP, PS_B_ROOK, PS_B_QUEEN, PS_B_KING, PS_NONE },
{ PS_NONE, PS_B_PAWN, PS_B_KNIGHT, PS_B_BISHOP, PS_B_ROOK, PS_B_QUEEN, PS_B_KING, PS_NONE,
PS_NONE, PS_W_PAWN, PS_W_KNIGHT, PS_W_BISHOP, PS_W_ROOK, PS_W_QUEEN, PS_W_KING, PS_NONE }
};
// 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 CeilToMultiple(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;
std::uint8_t u[sizeof(IntType)];
typename std::make_unsigned<IntType>::type v = 0;
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];
std::memcpy(&result, &v, sizeof(IntType));
return result;
}
} // namespace Eval::NNUE
#endif // #ifndef NNUE_COMMON_H_INCLUDED
+417
View File
@@ -0,0 +1,417 @@
/*
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/>.
*/
// A class that converts the input features of the NNUE evaluation function
#ifndef NNUE_FEATURE_TRANSFORMER_H_INCLUDED
#define NNUE_FEATURE_TRANSFORMER_H_INCLUDED
#include "nnue_common.h"
#include "nnue_architecture.h"
#include "features/index_list.h"
#include <cstring> // std::memset()
namespace Eval::NNUE {
// If vector instructions are enabled, we update and refresh the
// accumulator tile by tile such that each tile fits in the CPU's
// vector registers.
#define VECTOR
#ifdef USE_AVX512
typedef __m512i vec_t;
#define vec_load(a) _mm512_load_si512(a)
#define vec_store(a,b) _mm512_store_si512(a,b)
#define vec_add_16(a,b) _mm512_add_epi16(a,b)
#define vec_sub_16(a,b) _mm512_sub_epi16(a,b)
static constexpr IndexType kNumRegs = 8; // only 8 are needed
#elif USE_AVX2
typedef __m256i vec_t;
#define vec_load(a) _mm256_load_si256(a)
#define vec_store(a,b) _mm256_store_si256(a,b)
#define vec_add_16(a,b) _mm256_add_epi16(a,b)
#define vec_sub_16(a,b) _mm256_sub_epi16(a,b)
static constexpr IndexType kNumRegs = 16;
#elif USE_SSE2
typedef __m128i vec_t;
#define vec_load(a) (*(a))
#define vec_store(a,b) *(a)=(b)
#define vec_add_16(a,b) _mm_add_epi16(a,b)
#define vec_sub_16(a,b) _mm_sub_epi16(a,b)
static constexpr IndexType kNumRegs = Is64Bit ? 16 : 8;
#elif USE_MMX
typedef __m64 vec_t;
#define vec_load(a) (*(a))
#define vec_store(a,b) *(a)=(b)
#define vec_add_16(a,b) _mm_add_pi16(a,b)
#define vec_sub_16(a,b) _mm_sub_pi16(a,b)
static constexpr IndexType kNumRegs = 8;
#elif USE_NEON
typedef int16x8_t vec_t;
#define vec_load(a) (*(a))
#define vec_store(a,b) *(a)=(b)
#define vec_add_16(a,b) vaddq_s16(a,b)
#define vec_sub_16(a,b) vsubq_s16(a,b)
static constexpr IndexType kNumRegs = 16;
#else
#undef VECTOR
#endif
// Input feature converter
class FeatureTransformer {
private:
// Number of output dimensions for one side
static constexpr IndexType kHalfDimensions = kTransformedFeatureDimensions;
#ifdef VECTOR
static constexpr IndexType kTileHeight = kNumRegs * sizeof(vec_t) / 2;
static_assert(kHalfDimensions % kTileHeight == 0, "kTileHeight must divide kHalfDimensions");
#endif
public:
// Output type
using OutputType = TransformedFeatureType;
// Number of input/output dimensions
static constexpr IndexType kInputDimensions = RawFeatures::kDimensions;
static constexpr IndexType kOutputDimensions = kHalfDimensions * 2;
// Size of forward propagation buffer
static constexpr std::size_t kBufferSize =
kOutputDimensions * sizeof(OutputType);
// Hash value embedded in the evaluation file
static constexpr std::uint32_t GetHashValue() {
return RawFeatures::kHashValue ^ kOutputDimensions;
}
// Read network parameters
bool ReadParameters(std::istream& stream) {
for (std::size_t i = 0; i < kHalfDimensions; ++i)
biases_[i] = read_little_endian<BiasType>(stream);
for (std::size_t i = 0; i < kHalfDimensions * kInputDimensions; ++i)
weights_[i] = read_little_endian<WeightType>(stream);
return !stream.fail();
}
// Convert input features
void Transform(const Position& pos, OutputType* output) const {
UpdateAccumulator(pos, WHITE);
UpdateAccumulator(pos, BLACK);
const auto& accumulation = pos.state()->accumulator.accumulation;
#if defined(USE_AVX512)
constexpr IndexType kNumChunks = kHalfDimensions / (kSimdWidth * 2);
static_assert(kHalfDimensions % (kSimdWidth * 2) == 0);
const __m512i kControl = _mm512_setr_epi64(0, 2, 4, 6, 1, 3, 5, 7);
const __m512i kZero = _mm512_setzero_si512();
#elif defined(USE_AVX2)
constexpr IndexType kNumChunks = kHalfDimensions / kSimdWidth;
constexpr int kControl = 0b11011000;
const __m256i kZero = _mm256_setzero_si256();
#elif defined(USE_SSE2)
constexpr IndexType kNumChunks = kHalfDimensions / kSimdWidth;
#ifdef USE_SSE41
const __m128i kZero = _mm_setzero_si128();
#else
const __m128i k0x80s = _mm_set1_epi8(-128);
#endif
#elif defined(USE_MMX)
constexpr IndexType kNumChunks = kHalfDimensions / kSimdWidth;
const __m64 k0x80s = _mm_set1_pi8(-128);
#elif defined(USE_NEON)
constexpr IndexType kNumChunks = kHalfDimensions / (kSimdWidth / 2);
const int8x8_t kZero = {0};
#endif
const Color perspectives[2] = {pos.side_to_move(), ~pos.side_to_move()};
for (IndexType p = 0; p < 2; ++p) {
const IndexType offset = kHalfDimensions * p;
#if defined(USE_AVX512)
auto out = reinterpret_cast<__m512i*>(&output[offset]);
for (IndexType j = 0; j < kNumChunks; ++j) {
__m512i sum0 = _mm512_load_si512(
&reinterpret_cast<const __m512i*>(accumulation[perspectives[p]][0])[j * 2 + 0]);
__m512i sum1 = _mm512_load_si512(
&reinterpret_cast<const __m512i*>(accumulation[perspectives[p]][0])[j * 2 + 1]);
_mm512_store_si512(&out[j], _mm512_permutexvar_epi64(kControl,
_mm512_max_epi8(_mm512_packs_epi16(sum0, sum1), kZero)));
}
#elif defined(USE_AVX2)
auto out = reinterpret_cast<__m256i*>(&output[offset]);
for (IndexType j = 0; j < kNumChunks; ++j) {
__m256i sum0 = _mm256_load_si256(
&reinterpret_cast<const __m256i*>(accumulation[perspectives[p]][0])[j * 2 + 0]);
__m256i sum1 = _mm256_load_si256(
&reinterpret_cast<const __m256i*>(accumulation[perspectives[p]][0])[j * 2 + 1]);
_mm256_store_si256(&out[j], _mm256_permute4x64_epi64(_mm256_max_epi8(
_mm256_packs_epi16(sum0, sum1), kZero), kControl));
}
#elif defined(USE_SSE2)
auto out = reinterpret_cast<__m128i*>(&output[offset]);
for (IndexType j = 0; j < kNumChunks; ++j) {
__m128i sum0 = _mm_load_si128(&reinterpret_cast<const __m128i*>(
accumulation[perspectives[p]][0])[j * 2 + 0]);
__m128i sum1 = _mm_load_si128(&reinterpret_cast<const __m128i*>(
accumulation[perspectives[p]][0])[j * 2 + 1]);
const __m128i packedbytes = _mm_packs_epi16(sum0, sum1);
_mm_store_si128(&out[j],
#ifdef USE_SSE41
_mm_max_epi8(packedbytes, kZero)
#else
_mm_subs_epi8(_mm_adds_epi8(packedbytes, k0x80s), k0x80s)
#endif
);
}
#elif defined(USE_MMX)
auto out = reinterpret_cast<__m64*>(&output[offset]);
for (IndexType j = 0; j < kNumChunks; ++j) {
__m64 sum0 = *(&reinterpret_cast<const __m64*>(
accumulation[perspectives[p]][0])[j * 2 + 0]);
__m64 sum1 = *(&reinterpret_cast<const __m64*>(
accumulation[perspectives[p]][0])[j * 2 + 1]);
const __m64 packedbytes = _mm_packs_pi16(sum0, sum1);
out[j] = _mm_subs_pi8(_mm_adds_pi8(packedbytes, k0x80s), k0x80s);
}
#elif defined(USE_NEON)
const auto out = reinterpret_cast<int8x8_t*>(&output[offset]);
for (IndexType j = 0; j < kNumChunks; ++j) {
int16x8_t sum = reinterpret_cast<const int16x8_t*>(
accumulation[perspectives[p]][0])[j];
out[j] = vmax_s8(vqmovn_s16(sum), kZero);
}
#else
for (IndexType j = 0; j < kHalfDimensions; ++j) {
BiasType sum = accumulation[static_cast<int>(perspectives[p])][0][j];
output[offset + j] = static_cast<OutputType>(
std::max<int>(0, std::min<int>(127, sum)));
}
#endif
}
#if defined(USE_MMX)
_mm_empty();
#endif
}
private:
void UpdateAccumulator(const Position& pos, const Color c) const {
#ifdef VECTOR
// Gcc-10.2 unnecessarily spills AVX2 registers if this array
// is defined in the VECTOR code below, once in each branch
vec_t acc[kNumRegs];
#endif
// Look for a usable accumulator of an earlier position. We keep track
// of the estimated gain in terms of features to be added/subtracted.
StateInfo *st = pos.state(), *next = nullptr;
int gain = pos.count<ALL_PIECES>() - 2;
while (st->accumulator.state[c] == EMPTY)
{
auto& dp = st->dirtyPiece;
// The first condition tests whether an incremental update is
// possible at all: if this side's king has moved, it is not possible.
static_assert(std::is_same_v<RawFeatures::SortedTriggerSet,
Features::CompileTimeList<Features::TriggerEvent, Features::TriggerEvent::kFriendKingMoved>>,
"Current code assumes that only kFriendlyKingMoved refresh trigger is being used.");
if ( dp.piece[0] == make_piece(c, KING)
|| (gain -= dp.dirty_num + 1) < 0)
break;
next = st;
st = st->previous;
}
if (st->accumulator.state[c] == COMPUTED)
{
if (next == nullptr)
return;
// Update incrementally in two steps. First, we update the "next"
// accumulator. Then, we update the current accumulator (pos.state()).
// Gather all features to be updated. This code assumes HalfKP features
// only and doesn't support refresh triggers.
static_assert(std::is_same_v<Features::FeatureSet<Features::HalfKP<Features::Side::kFriend>>,
RawFeatures>);
Features::IndexList removed[2], added[2];
Features::HalfKP<Features::Side::kFriend>::AppendChangedIndices(pos,
next->dirtyPiece, c, &removed[0], &added[0]);
for (StateInfo *st2 = pos.state(); st2 != next; st2 = st2->previous)
Features::HalfKP<Features::Side::kFriend>::AppendChangedIndices(pos,
st2->dirtyPiece, c, &removed[1], &added[1]);
// Mark the accumulators as computed.
next->accumulator.state[c] = COMPUTED;
pos.state()->accumulator.state[c] = COMPUTED;
// Now update the accumulators listed in info[], where the last element is a sentinel.
StateInfo *info[3] =
{ next, next == pos.state() ? nullptr : pos.state(), nullptr };
#ifdef VECTOR
for (IndexType j = 0; j < kHalfDimensions / kTileHeight; ++j)
{
// Load accumulator
auto accTile = reinterpret_cast<vec_t*>(
&st->accumulator.accumulation[c][0][j * kTileHeight]);
for (IndexType k = 0; k < kNumRegs; ++k)
acc[k] = vec_load(&accTile[k]);
for (IndexType i = 0; info[i]; ++i)
{
// Difference calculation for the deactivated features
for (const auto index : removed[i])
{
const IndexType offset = kHalfDimensions * index + j * kTileHeight;
auto column = reinterpret_cast<const vec_t*>(&weights_[offset]);
for (IndexType k = 0; k < kNumRegs; ++k)
acc[k] = vec_sub_16(acc[k], column[k]);
}
// Difference calculation for the activated features
for (const auto index : added[i])
{
const IndexType offset = kHalfDimensions * index + j * kTileHeight;
auto column = reinterpret_cast<const vec_t*>(&weights_[offset]);
for (IndexType k = 0; k < kNumRegs; ++k)
acc[k] = vec_add_16(acc[k], column[k]);
}
// Store accumulator
accTile = reinterpret_cast<vec_t*>(
&info[i]->accumulator.accumulation[c][0][j * kTileHeight]);
for (IndexType k = 0; k < kNumRegs; ++k)
vec_store(&accTile[k], acc[k]);
}
}
#else
for (IndexType i = 0; info[i]; ++i)
{
std::memcpy(info[i]->accumulator.accumulation[c][0],
st->accumulator.accumulation[c][0],
kHalfDimensions * sizeof(BiasType));
st = info[i];
// Difference calculation for the deactivated features
for (const auto index : removed[i])
{
const IndexType offset = kHalfDimensions * index;
for (IndexType j = 0; j < kHalfDimensions; ++j)
st->accumulator.accumulation[c][0][j] -= weights_[offset + j];
}
// Difference calculation for the activated features
for (const auto index : added[i])
{
const IndexType offset = kHalfDimensions * index;
for (IndexType j = 0; j < kHalfDimensions; ++j)
st->accumulator.accumulation[c][0][j] += weights_[offset + j];
}
}
#endif
}
else
{
// Refresh the accumulator
auto& accumulator = pos.state()->accumulator;
accumulator.state[c] = COMPUTED;
Features::IndexList active;
Features::HalfKP<Features::Side::kFriend>::AppendActiveIndices(pos, c, &active);
#ifdef VECTOR
for (IndexType j = 0; j < kHalfDimensions / kTileHeight; ++j)
{
auto biasesTile = reinterpret_cast<const vec_t*>(
&biases_[j * kTileHeight]);
for (IndexType k = 0; k < kNumRegs; ++k)
acc[k] = biasesTile[k];
for (const auto index : active)
{
const IndexType offset = kHalfDimensions * index + j * kTileHeight;
auto column = reinterpret_cast<const vec_t*>(&weights_[offset]);
for (unsigned k = 0; k < kNumRegs; ++k)
acc[k] = vec_add_16(acc[k], column[k]);
}
auto accTile = reinterpret_cast<vec_t*>(
&accumulator.accumulation[c][0][j * kTileHeight]);
for (unsigned k = 0; k < kNumRegs; k++)
vec_store(&accTile[k], acc[k]);
}
#else
std::memcpy(accumulator.accumulation[c][0], biases_,
kHalfDimensions * sizeof(BiasType));
for (const auto index : active)
{
const IndexType offset = kHalfDimensions * index;
for (IndexType j = 0; j < kHalfDimensions; ++j)
accumulator.accumulation[c][0][j] += weights_[offset + j];
}
#endif
}
#if defined(USE_MMX)
_mm_empty();
#endif
}
using BiasType = std::int16_t;
using WeightType = std::int16_t;
alignas(kCacheLineSize) BiasType biases_[kHalfDimensions];
alignas(kCacheLineSize)
WeightType weights_[kHalfDimensions * kInputDimensions];
};
} // namespace Eval::NNUE
#endif // #ifndef NNUE_FEATURE_TRANSFORMER_H_INCLUDED
+84 -39
View File
@@ -1,8 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
@@ -32,23 +30,30 @@ namespace {
#define S(mg, eg) make_score(mg, eg)
// Pawn penalties
constexpr Score Backward = S( 9, 24);
constexpr Score BlockedStorm = S(82, 82);
constexpr Score Doubled = S(11, 56);
constexpr Score Isolated = S( 5, 15);
constexpr Score WeakLever = S( 0, 56);
constexpr Score WeakUnopposed = S(13, 27);
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, 7, 8, 12, 29, 48, 86 };
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( -6), V( 81), V( 93), V( 58), V( 39), V( 18), V( 25) },
{ V(-43), V( 61), V( 35), V(-49), V(-29), V(-11), V( -63) },
{ V(-10), V( 75), V( 23), V( -2), V( 32), V( 3), V( -45) },
{ V(-39), V(-13), V(-29), V(-52), V(-48), V(-67), V(-166) }
{ 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].
@@ -56,27 +61,40 @@ namespace {
// 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( 85), V(-289), V(-166), V(97), V(50), V( 45), V( 50) },
{ V( 46), V( -25), V( 122), V(45), V(37), V(-10), V( 20) },
{ V( -6), V( 51), V( 168), V(34), V(-2), V(-22), V(-14) },
{ V(-15), V( -11), V( 101), V( 4), V(11), V(-15), V(-29) }
{ 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 == WHITE ? BLACK : WHITE);
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;
const Square* pl = pos.squares<PAWN>(Us);
Bitboard b = pos.pieces(Us, PAWN);
Bitboard ourPawns = pos.pieces( Us, PAWN);
Bitboard theirPawns = pos.pieces(Them, PAWN);
@@ -86,10 +104,12 @@ namespace {
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 ((s = *pl++) != SQ_NONE)
{
while (b) {
s = pop_lsb(&b);
assert(pos.piece_on(s) == make_piece(Us, PAWN));
Rank r = relative_rank(Us, s);
@@ -98,13 +118,20 @@ namespace {
opposed = theirPawns & forward_file_bb(Us, s);
blocked = theirPawns & (s + Up);
stoppers = theirPawns & passed_pawn_span(Us, s);
lever = theirPawns & PawnAttacks[Us][s];
leverPush = theirPawns & PawnAttacks[Us][s + Up];
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))
@@ -118,12 +145,15 @@ namespace {
// (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)
@@ -133,22 +163,32 @@ namespace {
if (support | phalanx)
{
int v = Connected[r] * (2 + bool(phalanx) - bool(opposed))
+ 21 * popcount(support);
+ 22 * popcount(support);
score += make_score(v, v * (r - 2) / 4);
}
else if (!neighbours)
score -= Isolated
+ WeakUnopposed * !opposed;
{
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;
score -= Backward
+ WeakUnopposed * !opposed * bool(~(FileABB | FileHBB) & s);
if (!support)
score -= Doubled * doubled
+ WeakLever * more_than_one(lever);
score -= Doubled * doubled
+ WeakLever * more_than_one(lever);
if (blocked && r >= RANK_5)
score += BlockedPawn[r - RANK_5];
}
return score;
@@ -158,6 +198,7 @@ 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
@@ -172,6 +213,7 @@ Entry* probe(const Position& pos) {
return e;
e->key = key;
e->blockedCount = 0;
e->scores[WHITE] = evaluate<WHITE>(pos, e);
e->scores[BLACK] = evaluate<BLACK>(pos, e);
@@ -183,17 +225,17 @@ Entry* probe(const Position& pos) {
/// 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) {
Score Entry::evaluate_shelter(const Position& pos, Square ksq) const {
constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
constexpr Color Them = ~Us;
Bitboard b = pos.pieces(PAWN) & ~forward_ranks_bb(Them, ksq);
Bitboard ourPawns = b & pos.pieces(Us);
Bitboard ourPawns = b & pos.pieces(Us) & ~pawnAttacks[Them];
Bitboard theirPawns = b & pos.pieces(Them);
Score bonus = make_score(5, 5);
File center = clamp(file_of(ksq), FILE_B, FILE_G);
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);
@@ -202,15 +244,18 @@ Score Entry::evaluate_shelter(const Position& pos, Square ksq) {
b = theirPawns & file_bb(f);
int theirRank = b ? relative_rank(Us, frontmost_sq(Them, b)) : 0;
File d = map_to_queenside(f);
int d = edge_distance(f);
bonus += make_score(ShelterStrength[d][ourRank], 0);
if (ourRank && (ourRank == theirRank - 1))
bonus -= BlockedStorm * int(theirRank == RANK_3);
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;
}
@@ -238,9 +283,9 @@ Score Entry::do_king_safety(const Position& pos) {
// In endgame we like to bring our king near our closest pawn
Bitboard pawns = pos.pieces(Us, PAWN);
int minPawnDist = pawns ? 8 : 0;
int minPawnDist = 6;
if (pawns & PseudoAttacks[KING][ksq])
if (pawns & attacks_bb<KING>(ksq))
minPawnDist = 1;
else while (pawns)
minPawnDist = std::min(minPawnDist, distance(ksq, pop_lsb(&pawns)));
+4 -4
View File
@@ -1,8 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
@@ -38,6 +36,7 @@ struct Entry {
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) {
@@ -49,7 +48,7 @@ struct Entry {
Score do_king_safety(const Position& pos);
template<Color Us>
Score evaluate_shelter(const Position& pos, Square ksq);
Score evaluate_shelter(const Position& pos, Square ksq) const;
Key key;
Score scores[COLOR_NB];
@@ -59,6 +58,7 @@ struct Entry {
Square kingSquares[COLOR_NB];
Score kingSafety[COLOR_NB];
int castlingRights[COLOR_NB];
int blockedCount;
};
typedef HashTable<Entry, 131072> Table;
+168 -126
View File
@@ -1,8 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
@@ -64,10 +62,11 @@ std::ostream& operator<<(std::ostream& os, const Position& pos) {
for (File f = FILE_A; f <= FILE_H; ++f)
os << " | " << PieceToChar[pos.piece_on(make_square(f, r))];
os << " |\n +---+---+---+---+---+---+---+---+\n";
os << " | " << (1 + r) << "\n +---+---+---+---+---+---+---+---+\n";
}
os << "\nFen: " << pos.fen() << "\nKey: " << std::hex << std::uppercase
os << " a b c d e f g h\n"
<< "\nFen: " << pos.fen() << "\nKey: " << std::hex << std::uppercase
<< std::setfill('0') << std::setw(16) << pos.key()
<< std::setfill(' ') << std::dec << "\nCheckers: ";
@@ -78,6 +77,8 @@ std::ostream& operator<<(std::ostream& os, const Position& pos) {
&& !pos.can_castle(ANY_CASTLING))
{
StateInfo st;
ASSERT_ALIGNED(&st, Eval::NNUE::kCacheLineSize);
Position p;
p.set(pos.fen(), pos.is_chess960(), &st, pos.this_thread());
Tablebases::ProbeState s1, s2;
@@ -104,8 +105,7 @@ Key cuckoo[8192];
Move cuckooMove[8192];
/// Position::init() initializes at startup the various arrays used to compute
/// hash keys.
/// Position::init() initializes at startup the various arrays used to compute hash keys
void Position::init() {
@@ -119,15 +119,7 @@ void Position::init() {
Zobrist::enpassant[f] = rng.rand<Key>();
for (int cr = NO_CASTLING; cr <= ANY_CASTLING; ++cr)
{
Zobrist::castling[cr] = 0;
Bitboard b = cr;
while (b)
{
Key k = Zobrist::castling[1ULL << pop_lsb(&b)];
Zobrist::castling[cr] ^= k ? k : rng.rand<Key>();
}
}
Zobrist::castling[cr] = rng.rand<Key>();
Zobrist::side = rng.rand<Key>();
Zobrist::noPawns = rng.rand<Key>();
@@ -139,7 +131,7 @@ void Position::init() {
for (Piece pc : Pieces)
for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
for (Square s2 = Square(s1 + 1); s2 <= SQ_H8; ++s2)
if (PseudoAttacks[type_of(pc)][s1] & s2)
if ((type_of(pc) != PAWN) && (attacks_bb(type_of(pc), s1, 0) & s2))
{
Move move = make_move(s1, s2);
Key key = Zobrist::psq[pc][s1] ^ Zobrist::psq[pc][s2] ^ Zobrist::side;
@@ -186,9 +178,9 @@ Position& Position::set(const string& fenStr, bool isChess960, StateInfo* si, Th
4) En passant target square (in algebraic notation). If there's no en passant
target square, this is "-". If a pawn has just made a 2-square move, this
is the position "behind" the pawn. This is recorded only if there is a pawn
in position to make an en passant capture, and if there really is a pawn
that might have advanced two squares.
is the position "behind" the pawn. Following X-FEN standard, this is recorded only
if there is a pawn in position to make an en passant capture, and if there really
is a pawn that might have advanced two squares.
5) Halfmove clock. This is the number of halfmoves since the last pawn advance
or capture. This is used to determine if a draw can be claimed under the
@@ -205,7 +197,6 @@ Position& Position::set(const string& fenStr, bool isChess960, StateInfo* si, Th
std::memset(this, 0, sizeof(Position));
std::memset(si, 0, sizeof(StateInfo));
std::fill_n(&pieceList[0][0], sizeof(pieceList) / sizeof(Square), SQ_NONE);
st = si;
ss >> std::noskipws;
@@ -219,8 +210,7 @@ Position& Position::set(const string& fenStr, bool isChess960, StateInfo* si, Th
else if (token == '/')
sq += 2 * SOUTH;
else if ((idx = PieceToChar.find(token)) != string::npos)
{
else if ((idx = PieceToChar.find(token)) != string::npos) {
put_piece(Piece(idx), sq);
++sq;
}
@@ -259,15 +249,37 @@ Position& Position::set(const string& fenStr, bool isChess960, StateInfo* si, Th
set_castling_right(c, rsq);
}
// 4. En passant square. Ignore if no pawn capture is possible
set_state(st);
// 4. En passant square.
// Ignore if square is invalid or not on side to move relative rank 6.
bool enpassant = false;
if ( ((ss >> col) && (col >= 'a' && col <= 'h'))
&& ((ss >> row) && (row == '3' || row == '6')))
&& ((ss >> row) && (row == (sideToMove == WHITE ? '6' : '3'))))
{
st->epSquare = make_square(File(col - 'a'), Rank(row - '1'));
if ( !(attackers_to(st->epSquare) & pieces(sideToMove, PAWN))
|| !(pieces(~sideToMove, PAWN) & (st->epSquare + pawn_push(~sideToMove))))
st->epSquare = SQ_NONE;
// En passant square will be considered only if
// a) side to move have a pawn threatening epSquare
// b) there is an enemy pawn in front of epSquare
// c) there is no piece on epSquare or behind epSquare
// d) enemy pawn didn't block a check of its own color by moving forward
enpassant = pawn_attacks_bb(~sideToMove, st->epSquare) & pieces(sideToMove, PAWN)
&& (pieces(~sideToMove, PAWN) & (st->epSquare + pawn_push(~sideToMove)))
&& !(pieces() & (st->epSquare | (st->epSquare + pawn_push(sideToMove))))
&& ( file_of(square<KING>(sideToMove)) == file_of(st->epSquare)
|| !(blockers_for_king(sideToMove) & (st->epSquare + pawn_push(~sideToMove))));
}
// It's necessary for st->previous to be intialized in this way because legality check relies on its existence
if (enpassant) {
st->previous = new StateInfo();
remove_piece(st->epSquare - pawn_push(sideToMove));
st->previous->checkersBB = attackers_to(square<KING>(~sideToMove)) & pieces(sideToMove);
st->previous->blockersForKing[WHITE] = slider_blockers(pieces(BLACK), square<KING>(WHITE), st->previous->pinners[BLACK]);
st->previous->blockersForKing[BLACK] = slider_blockers(pieces(WHITE), square<KING>(BLACK), st->previous->pinners[WHITE]);
put_piece(make_piece(~sideToMove, PAWN), st->epSquare - pawn_push(sideToMove));
}
else
st->epSquare = SQ_NONE;
@@ -281,7 +293,8 @@ Position& Position::set(const string& fenStr, bool isChess960, StateInfo* si, Th
chess960 = isChess960;
thisThread = th;
set_state(st);
st->accumulator.state[WHITE] = Eval::NNUE::INIT;
st->accumulator.state[BLACK] = Eval::NNUE::INIT;
assert(pos_is_ok());
@@ -306,7 +319,7 @@ void Position::set_castling_right(Color c, Square rfrom) {
Square rto = relative_square(c, cr & KING_SIDE ? SQ_F1 : SQ_D1);
castlingPath[cr] = (between_bb(rfrom, rto) | between_bb(kfrom, kto) | rto | kto)
& ~(square_bb(kfrom) | rfrom);
& ~(kfrom | rfrom);
}
@@ -319,10 +332,10 @@ void Position::set_check_info(StateInfo* si) const {
Square ksq = square<KING>(~sideToMove);
si->checkSquares[PAWN] = attacks_from<PAWN>(ksq, ~sideToMove);
si->checkSquares[KNIGHT] = attacks_from<KNIGHT>(ksq);
si->checkSquares[BISHOP] = attacks_from<BISHOP>(ksq);
si->checkSquares[ROOK] = attacks_from<ROOK>(ksq);
si->checkSquares[PAWN] = pawn_attacks_bb(~sideToMove, ksq);
si->checkSquares[KNIGHT] = attacks_bb<KNIGHT>(ksq);
si->checkSquares[BISHOP] = attacks_bb<BISHOP>(ksq, pieces());
si->checkSquares[ROOK] = attacks_bb<ROOK>(ksq, pieces());
si->checkSquares[QUEEN] = si->checkSquares[BISHOP] | si->checkSquares[ROOK];
si->checkSquares[KING] = 0;
}
@@ -375,11 +388,13 @@ void Position::set_state(StateInfo* si) const {
Position& Position::set(const string& code, Color c, StateInfo* si) {
assert(code.length() > 0 && code.length() < 8);
assert(code[0] == 'K');
string sides[] = { code.substr(code.find('K', 1)), // Weak
code.substr(0, code.find('K', 1)) }; // Strong
code.substr(0, std::min(code.find('v'), code.find('K', 1))) }; // Strong
assert(sides[0].length() > 0 && sides[0].length() < 8);
assert(sides[1].length() > 0 && sides[1].length() < 8);
std::transform(sides[c].begin(), sides[c].end(), sides[c].begin(), tolower);
@@ -453,8 +468,8 @@ Bitboard Position::slider_blockers(Bitboard sliders, Square s, Bitboard& pinners
pinners = 0;
// Snipers are sliders that attack 's' when a piece and other snipers are removed
Bitboard snipers = ( (PseudoAttacks[ ROOK][s] & pieces(QUEEN, ROOK))
| (PseudoAttacks[BISHOP][s] & pieces(QUEEN, BISHOP))) & sliders;
Bitboard snipers = ( (attacks_bb< ROOK>(s) & pieces(QUEEN, ROOK))
| (attacks_bb<BISHOP>(s) & pieces(QUEEN, BISHOP))) & sliders;
Bitboard occupancy = pieces() ^ snipers;
while (snipers)
@@ -478,12 +493,12 @@ Bitboard Position::slider_blockers(Bitboard sliders, Square s, Bitboard& pinners
Bitboard Position::attackers_to(Square s, Bitboard occupied) const {
return (attacks_from<PAWN>(s, BLACK) & pieces(WHITE, PAWN))
| (attacks_from<PAWN>(s, WHITE) & pieces(BLACK, PAWN))
| (attacks_from<KNIGHT>(s) & pieces(KNIGHT))
return (pawn_attacks_bb(BLACK, s) & pieces(WHITE, PAWN))
| (pawn_attacks_bb(WHITE, s) & pieces(BLACK, PAWN))
| (attacks_bb<KNIGHT>(s) & pieces(KNIGHT))
| (attacks_bb< ROOK>(s, occupied) & pieces( ROOK, QUEEN))
| (attacks_bb<BISHOP>(s, occupied) & pieces(BISHOP, QUEEN))
| (attacks_from<KING>(s) & pieces(KING));
| (attacks_bb<KING>(s) & pieces(KING));
}
@@ -500,23 +515,11 @@ bool Position::legal(Move m) const {
assert(color_of(moved_piece(m)) == us);
assert(piece_on(square<KING>(us)) == make_piece(us, KING));
// En passant captures are a tricky special case. Because they are rather
// uncommon, we do it simply by testing whether the king is attacked after
// the move is made.
if (type_of(m) == ENPASSANT)
{
Square ksq = square<KING>(us);
Square capsq = to - pawn_push(us);
Bitboard occupied = (pieces() ^ from ^ capsq) | to;
assert(to == ep_square());
assert(moved_piece(m) == make_piece(us, PAWN));
assert(piece_on(capsq) == make_piece(~us, PAWN));
assert(piece_on(to) == NO_PIECE);
return !(attacks_bb< ROOK>(ksq, occupied) & pieces(~us, QUEEN, ROOK))
&& !(attacks_bb<BISHOP>(ksq, occupied) & pieces(~us, QUEEN, BISHOP));
}
// st->previous->blockersForKing consider capsq as empty.
// If pinned, it has to move along the king ray.
if (type_of(m) == EN_PASSANT)
return !(st->previous->blockersForKing[sideToMove] & from)
|| aligned(from, to, square<KING>(us));
// Castling moves generation does not check if the castling path is clear of
// enemy attacks, it is delayed at a later time: now!
@@ -531,11 +534,9 @@ bool Position::legal(Move m) const {
if (attackers_to(s) & pieces(~us))
return false;
// In case of Chess960, verify that when moving the castling rook we do
// not discover some hidden checker.
// In case of Chess960, verify if the Rook blocks some checks
// For instance an enemy queen in SQ_A1 when castling rook is in SQ_B1.
return !chess960
|| !(attacks_bb<ROOK>(to, pieces() ^ to_sq(m)) & pieces(~us, ROOK, QUEEN));
return !chess960 || !(blockers_for_king(us) & to_sq(m));
}
// If the moving piece is a king, check whether the destination square is
@@ -545,8 +546,8 @@ bool Position::legal(Move m) const {
// A non-king move is legal if and only if it is not pinned or it
// is moving along the ray towards or away from the king.
return !(blockers_for_king(us) & from)
|| aligned(from, to, square<KING>(us));
return !(blockers_for_king(us) & from)
|| aligned(from, to, square<KING>(us));
}
@@ -562,8 +563,10 @@ bool Position::pseudo_legal(const Move m) const {
Piece pc = moved_piece(m);
// Use a slower but simpler function for uncommon cases
// yet we skip the legality check of MoveList<LEGAL>().
if (type_of(m) != NORMAL)
return MoveList<LEGAL>(*this).contains(m);
return checkers() ? MoveList< EVASIONS>(*this).contains(m)
: MoveList<NON_EVASIONS>(*this).contains(m);
// Is not a promotion, so promotion piece must be empty
if (promotion_type(m) - KNIGHT != NO_PIECE_TYPE)
@@ -586,15 +589,15 @@ bool Position::pseudo_legal(const Move m) const {
if ((Rank8BB | Rank1BB) & to)
return false;
if ( !(attacks_from<PAWN>(from, us) & pieces(~us) & to) // Not a capture
if ( !(pawn_attacks_bb(us, from) & pieces(~us) & to) // Not a capture
&& !((from + pawn_push(us) == to) && empty(to)) // Not a single push
&& !( (from + 2 * pawn_push(us) == to) // Not a double push
&& (rank_of(from) == relative_rank(us, RANK_2))
&& (relative_rank(us, from) == RANK_2)
&& empty(to)
&& empty(to - pawn_push(us))))
return false;
}
else if (!(attacks_from(type_of(pc), from) & to))
else if (!(attacks_bb(type_of(pc), from, pieces()) & to))
return false;
// Evasions generator already takes care to avoid some kind of illegal moves
@@ -633,11 +636,11 @@ bool Position::gives_check(Move m) const {
Square to = to_sq(m);
// Is there a direct check?
if (st->checkSquares[type_of(piece_on(from))] & to)
if (check_squares(type_of(piece_on(from))) & to)
return true;
// Is there a discovered check?
if ( (st->blockersForKing[~sideToMove] & from)
if ( (blockers_for_king(~sideToMove) & from)
&& !aligned(from, to, square<KING>(~sideToMove)))
return true;
@@ -649,31 +652,24 @@ bool Position::gives_check(Move m) const {
case PROMOTION:
return attacks_bb(promotion_type(m), to, pieces() ^ from) & square<KING>(~sideToMove);
// En passant capture with check? We have already handled the case
// of direct checks and ordinary discovered check, so the only case we
// need to handle is the unusual case of a discovered check through
// the captured pawn.
case ENPASSANT:
{
Square capsq = make_square(file_of(to), rank_of(from));
Bitboard b = (pieces() ^ from ^ capsq) | to;
// The double-pushed pawn blocked a check? En Passant will remove the blocker.
// The only discovery check that wasn't handle is through capsq and fromsq
// So the King must be in the same rank as fromsq to consider this possibility.
// st->previous->blockersForKing consider capsq as empty.
case EN_PASSANT:
return st->previous->checkersBB
|| ( rank_of(square<KING>(~sideToMove)) == rank_of(from)
&& st->previous->blockersForKing[~sideToMove] & from);
return (attacks_bb< ROOK>(square<KING>(~sideToMove), b) & pieces(sideToMove, QUEEN, ROOK))
| (attacks_bb<BISHOP>(square<KING>(~sideToMove), b) & pieces(sideToMove, QUEEN, BISHOP));
}
case CASTLING:
default: //CASTLING
{
Square kfrom = from;
Square rfrom = to; // Castling is encoded as 'King captures the rook'
Square kto = relative_square(sideToMove, rfrom > kfrom ? SQ_G1 : SQ_C1);
Square rto = relative_square(sideToMove, rfrom > kfrom ? SQ_F1 : SQ_D1);
// Castling is encoded as 'king captures the rook'
Square ksq = square<KING>(~sideToMove);
Square rto = relative_square(sideToMove, to > from ? SQ_F1 : SQ_D1);
return (PseudoAttacks[ROOK][rto] & square<KING>(~sideToMove))
&& (attacks_bb<ROOK>(rto, (pieces() ^ kfrom ^ rfrom) | rto | kto) & square<KING>(~sideToMove));
return (attacks_bb<ROOK>(rto) & ksq)
&& (attacks_bb<ROOK>(rto, pieces() ^ from ^ to) & ksq);
}
default:
assert(false);
return false;
}
}
@@ -703,12 +699,18 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
++st->rule50;
++st->pliesFromNull;
// Used by NNUE
st->accumulator.state[WHITE] = Eval::NNUE::EMPTY;
st->accumulator.state[BLACK] = Eval::NNUE::EMPTY;
auto& dp = st->dirtyPiece;
dp.dirty_num = 1;
Color us = sideToMove;
Color them = ~us;
Square from = from_sq(m);
Square to = to_sq(m);
Piece pc = piece_on(from);
Piece captured = type_of(m) == ENPASSANT ? make_piece(them, PAWN) : piece_on(to);
Piece captured = type_of(m) == EN_PASSANT ? make_piece(them, PAWN) : piece_on(to);
assert(color_of(pc) == us);
assert(captured == NO_PIECE || color_of(captured) == (type_of(m) != CASTLING ? them : us));
@@ -734,7 +736,7 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
// update non-pawn material.
if (type_of(captured) == PAWN)
{
if (type_of(m) == ENPASSANT)
if (type_of(m) == EN_PASSANT)
{
capsq -= pawn_push(us);
@@ -743,8 +745,6 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
assert(relative_rank(us, to) == RANK_6);
assert(piece_on(to) == NO_PIECE);
assert(piece_on(capsq) == make_piece(them, PAWN));
board[capsq] = NO_PIECE; // Not done by remove_piece()
}
st->pawnKey ^= Zobrist::psq[captured][capsq];
@@ -752,8 +752,19 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
else
st->nonPawnMaterial[them] -= PieceValue[MG][captured];
if (Eval::useNNUE)
{
dp.dirty_num = 2; // 1 piece moved, 1 piece captured
dp.piece[1] = captured;
dp.from[1] = capsq;
dp.to[1] = SQ_NONE;
}
// Update board and piece lists
remove_piece(captured, capsq);
remove_piece(capsq);
if (type_of(m) == EN_PASSANT)
board[capsq] = NO_PIECE;
// Update material hash key and prefetch access to materialTable
k ^= Zobrist::psq[captured][capsq];
@@ -777,21 +788,30 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
// Update castling rights if needed
if (st->castlingRights && (castlingRightsMask[from] | castlingRightsMask[to]))
{
int cr = castlingRightsMask[from] | castlingRightsMask[to];
k ^= Zobrist::castling[st->castlingRights & cr];
st->castlingRights &= ~cr;
k ^= Zobrist::castling[st->castlingRights];
st->castlingRights &= ~(castlingRightsMask[from] | castlingRightsMask[to]);
k ^= Zobrist::castling[st->castlingRights];
}
// Move the piece. The tricky Chess960 castling is handled earlier
if (type_of(m) != CASTLING)
move_piece(pc, from, to);
{
if (Eval::useNNUE)
{
dp.piece[0] = pc;
dp.from[0] = from;
dp.to[0] = to;
}
move_piece(from, to);
}
// If the moving piece is a pawn do some special extra work
if (type_of(pc) == PAWN)
{
// Set en-passant square if the moved pawn can be captured
// Set en passant square if the moved pawn can be captured
if ( (int(to) ^ int(from)) == 16
&& (attacks_from<PAWN>(to - pawn_push(us), us) & pieces(them, PAWN)))
&& (pawn_attacks_bb(us, to - pawn_push(us)) & pieces(them, PAWN)))
{
st->epSquare = to - pawn_push(us);
k ^= Zobrist::enpassant[file_of(st->epSquare)];
@@ -804,9 +824,19 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
assert(relative_rank(us, to) == RANK_8);
assert(type_of(promotion) >= KNIGHT && type_of(promotion) <= QUEEN);
remove_piece(pc, to);
remove_piece(to);
put_piece(promotion, to);
if (Eval::useNNUE)
{
// Promoting pawn to SQ_NONE, promoted piece from SQ_NONE
dp.to[0] = SQ_NONE;
dp.piece[dp.dirty_num] = promotion;
dp.from[dp.dirty_num] = SQ_NONE;
dp.to[dp.dirty_num] = to;
dp.dirty_num++;
}
// Update hash keys
k ^= Zobrist::psq[pc][to] ^ Zobrist::psq[promotion][to];
st->pawnKey ^= Zobrist::psq[pc][to];
@@ -884,7 +914,7 @@ void Position::undo_move(Move m) {
assert(type_of(pc) == promotion_type(m));
assert(type_of(pc) >= KNIGHT && type_of(pc) <= QUEEN);
remove_piece(pc, to);
remove_piece(to);
pc = make_piece(us, PAWN);
put_piece(pc, to);
}
@@ -896,13 +926,13 @@ void Position::undo_move(Move m) {
}
else
{
move_piece(pc, to, from); // Put the piece back at the source square
move_piece(to, from); // Put the piece back at the source square
if (st->capturedPiece)
{
Square capsq = to;
if (type_of(m) == ENPASSANT)
if (type_of(m) == EN_PASSANT)
{
capsq -= pawn_push(us);
@@ -935,10 +965,22 @@ void Position::do_castling(Color us, Square from, Square& to, Square& rfrom, Squ
rto = relative_square(us, kingSide ? SQ_F1 : SQ_D1);
to = relative_square(us, kingSide ? SQ_G1 : SQ_C1);
if (Do && Eval::useNNUE)
{
auto& dp = st->dirtyPiece;
dp.piece[0] = make_piece(us, KING);
dp.from[0] = from;
dp.to[0] = to;
dp.piece[1] = make_piece(us, ROOK);
dp.from[1] = rfrom;
dp.to[1] = rto;
dp.dirty_num = 2;
}
// Remove both pieces first since squares could overlap in Chess960
remove_piece(make_piece(us, KING), Do ? from : to);
remove_piece(make_piece(us, ROOK), Do ? rfrom : rto);
board[Do ? from : to] = board[Do ? rfrom : rto] = NO_PIECE; // Since remove_piece doesn't do it for us
remove_piece(Do ? from : to);
remove_piece(Do ? rfrom : rto);
board[Do ? from : to] = board[Do ? rfrom : rto] = NO_PIECE; // Since remove_piece doesn't do this for us
put_piece(make_piece(us, KING), Do ? to : from);
put_piece(make_piece(us, ROOK), Do ? rto : rfrom);
}
@@ -952,10 +994,16 @@ void Position::do_null_move(StateInfo& newSt) {
assert(!checkers());
assert(&newSt != st);
std::memcpy(&newSt, st, sizeof(StateInfo));
std::memcpy(&newSt, st, offsetof(StateInfo, accumulator));
newSt.previous = st;
st = &newSt;
st->dirtyPiece.dirty_num = 0;
st->dirtyPiece.piece[0] = NO_PIECE; // Avoid checks in UpdateAccumulator()
st->accumulator.state[WHITE] = Eval::NNUE::EMPTY;
st->accumulator.state[BLACK] = Eval::NNUE::EMPTY;
if (st->epSquare != SQ_NONE)
{
st->key ^= Zobrist::enpassant[file_of(st->epSquare)];
@@ -963,7 +1011,7 @@ void Position::do_null_move(StateInfo& newSt) {
}
st->key ^= Zobrist::side;
prefetch(TT.first_entry(st->key));
prefetch(TT.first_entry(key()));
++st->rule50;
st->pliesFromNull = 0;
@@ -988,7 +1036,7 @@ void Position::undo_null_move() {
/// Position::key_after() computes the new hash key after the given move. Needed
/// for speculative prefetch. It doesn't recognize special moves like castling,
/// en-passant and promotions.
/// en passant and promotions.
Key Position::key_after(Move m) const {
@@ -1013,7 +1061,7 @@ bool Position::see_ge(Move m, Value threshold) const {
assert(is_ok(m));
// Only deal with normal moves, assume others pass a simple see
// Only deal with normal moves, assume others pass a simple SEE
if (type_of(m) != NORMAL)
return VALUE_ZERO >= threshold;
@@ -1044,8 +1092,8 @@ bool Position::see_ge(Move m, Value threshold) const {
// Don't allow pinned pieces to attack (except the king) as long as
// there are pinners on their original square.
if (st->pinners[~stm] & occupied)
stmAttackers &= ~st->blockersForKing[stm];
if (pinners(~stm) & occupied)
stmAttackers &= ~blockers_for_king(stm);
if (!stmAttackers)
break;
@@ -1108,6 +1156,7 @@ bool Position::see_ge(Move m, Value threshold) const {
return bool(res);
}
/// Position::is_draw() tests whether the position is drawn by 50-move rule
/// or by repetition. It does not detect stalemates.
@@ -1118,10 +1167,7 @@ bool Position::is_draw(int ply) const {
// Return a draw score if a position repeats once earlier but strictly
// after the root, or repeats twice before or at the root.
if (st->repetition && st->repetition < ply)
return true;
return false;
return st->repetition && st->repetition < ply;
}
@@ -1267,21 +1313,17 @@ bool Position::pos_is_ok() const {
assert(0 && "pos_is_ok: Bitboards");
StateInfo si = *st;
ASSERT_ALIGNED(&si, Eval::NNUE::kCacheLineSize);
set_state(&si);
if (std::memcmp(&si, st, sizeof(StateInfo)))
assert(0 && "pos_is_ok: State");
for (Piece pc : Pieces)
{
if ( pieceCount[pc] != popcount(pieces(color_of(pc), type_of(pc)))
|| pieceCount[pc] != std::count(board, board + SQUARE_NB, pc))
assert(0 && "pos_is_ok: Pieces");
for (int i = 0; i < pieceCount[pc]; ++i)
if (board[pieceList[pc][i]] != pc || index[pieceList[pc][i]] != i)
assert(0 && "pos_is_ok: Index");
}
for (Color c : { WHITE, BLACK })
for (CastlingRights cr : {c & KING_SIDE, c & QUEEN_SIDE})
{
+58 -84
View File
@@ -1,8 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
@@ -27,8 +25,12 @@
#include <string>
#include "bitboard.h"
#include "evaluate.h"
#include "psqt.h"
#include "types.h"
#include "nnue/nnue_accumulator.h"
/// 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
@@ -54,8 +56,13 @@ struct StateInfo {
Bitboard pinners[COLOR_NB];
Bitboard checkSquares[PIECE_TYPE_NB];
int repetition;
// Used by NNUE
Eval::NNUE::Accumulator accumulator;
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
@@ -83,7 +90,6 @@ public:
const std::string fen() const;
// Position representation
Bitboard pieces() const;
Bitboard pieces(PieceType pt) const;
Bitboard pieces(PieceType pt1, PieceType pt2) const;
Bitboard pieces(Color c) const;
@@ -94,12 +100,11 @@ public:
bool empty(Square s) const;
template<PieceType Pt> int count(Color c) const;
template<PieceType Pt> int count() const;
template<PieceType Pt> const Square* squares(Color c) const;
template<PieceType Pt> Square square(Color c) const;
bool is_on_semiopen_file(Color c, Square s) const;
// Castling
int castling_rights(Color c) const;
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;
@@ -108,14 +113,12 @@ public:
Bitboard checkers() const;
Bitboard blockers_for_king(Color c) const;
Bitboard check_squares(PieceType pt) const;
bool is_discovery_check_on_king(Color c, Move m) const;
Bitboard pinners(Color c) const;
bool is_discovered_check_on_king(Color c, Move m) const;
// Attacks to/from a given square
Bitboard attackers_to(Square s) const;
Bitboard attackers_to(Square s, Bitboard occupied) const;
Bitboard attacks_from(PieceType pt, Square s) const;
template<PieceType> Bitboard attacks_from(Square s) const;
template<PieceType> Bitboard attacks_from(Square s, Color c) const;
Bitboard slider_blockers(Bitboard sliders, Square s, Bitboard& pinners) const;
// Properties of moves
@@ -166,6 +169,9 @@ public:
bool pos_is_ok() const;
void flip();
// Used by NNUE
StateInfo* state() const;
private:
// Initialization helpers (used while setting up a position)
void set_castling_right(Color c, Square rfrom);
@@ -174,8 +180,8 @@ private:
// Other helpers
void put_piece(Piece pc, Square s);
void remove_piece(Piece pc, Square s);
void move_piece(Piece pc, Square from, Square to);
void remove_piece(Square s);
void move_piece(Square from, Square to);
template<bool Do>
void do_castling(Color us, Square from, Square& to, Square& rfrom, Square& rto);
@@ -184,8 +190,6 @@ private:
Bitboard byTypeBB[PIECE_TYPE_NB];
Bitboard byColorBB[COLOR_NB];
int pieceCount[PIECE_NB];
Square pieceList[PIECE_NB][16];
int index[SQUARE_NB];
int castlingRightsMask[SQUARE_NB];
Square castlingRookSquare[CASTLING_RIGHT_NB];
Bitboard castlingPath[CASTLING_RIGHT_NB];
@@ -197,38 +201,31 @@ private:
bool chess960;
};
namespace PSQT {
extern Score psq[PIECE_NB][SQUARE_NB];
}
extern std::ostream& operator<<(std::ostream& os, const Position& pos);
inline Color Position::side_to_move() const {
return sideToMove;
}
inline bool Position::empty(Square s) const {
return board[s] == NO_PIECE;
}
inline Piece Position::piece_on(Square s) const {
assert(is_ok(s));
return board[s];
}
inline bool Position::empty(Square s) const {
return piece_on(s) == NO_PIECE;
}
inline Piece Position::moved_piece(Move m) const {
return board[from_sq(m)];
return piece_on(from_sq(m));
}
inline Bitboard Position::pieces() const {
return byTypeBB[ALL_PIECES];
}
inline Bitboard Position::pieces(PieceType pt) const {
inline Bitboard Position::pieces(PieceType pt = ALL_PIECES) const {
return byTypeBB[pt];
}
inline Bitboard Position::pieces(PieceType pt1, PieceType pt2) const {
return byTypeBB[pt1] | byTypeBB[pt2];
return pieces(pt1) | pieces(pt2);
}
inline Bitboard Position::pieces(Color c) const {
@@ -236,11 +233,11 @@ inline Bitboard Position::pieces(Color c) const {
}
inline Bitboard Position::pieces(Color c, PieceType pt) const {
return byColorBB[c] & byTypeBB[pt];
return pieces(c) & pieces(pt);
}
inline Bitboard Position::pieces(Color c, PieceType pt1, PieceType pt2) const {
return byColorBB[c] & (byTypeBB[pt1] | byTypeBB[pt2]);
return pieces(c) & (pieces(pt1) | pieces(pt2));
}
template<PieceType Pt> inline int Position::count(Color c) const {
@@ -248,16 +245,12 @@ template<PieceType Pt> inline int Position::count(Color c) const {
}
template<PieceType Pt> inline int Position::count() const {
return pieceCount[make_piece(WHITE, Pt)] + pieceCount[make_piece(BLACK, Pt)];
}
template<PieceType Pt> inline const Square* Position::squares(Color c) const {
return pieceList[make_piece(c, Pt)];
return count<Pt>(WHITE) + count<Pt>(BLACK);
}
template<PieceType Pt> inline Square Position::square(Color c) const {
assert(pieceCount[make_piece(c, Pt)] == 1);
return pieceList[make_piece(c, Pt)][0];
assert(count<Pt>(c) == 1);
return lsb(pieces(c, Pt));
}
inline Square Position::ep_square() const {
@@ -272,14 +265,14 @@ inline bool Position::can_castle(CastlingRights cr) const {
return st->castlingRights & cr;
}
inline int Position::castling_rights(Color c) const {
return st->castlingRights & (c == WHITE ? WHITE_CASTLING : BLACK_CASTLING);
inline CastlingRights Position::castling_rights(Color c) const {
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 byTypeBB[ALL_PIECES] & castlingPath[cr];
return pieces() & castlingPath[cr];
}
inline Square Position::castling_rook_square(CastlingRights cr) const {
@@ -288,26 +281,8 @@ inline Square Position::castling_rook_square(CastlingRights cr) const {
return castlingRookSquare[cr];
}
template<PieceType Pt>
inline Bitboard Position::attacks_from(Square s) const {
static_assert(Pt != PAWN, "Pawn attacks need color");
return Pt == BISHOP || Pt == ROOK ? attacks_bb<Pt>(s, byTypeBB[ALL_PIECES])
: Pt == QUEEN ? attacks_from<ROOK>(s) | attacks_from<BISHOP>(s)
: PseudoAttacks[Pt][s];
}
template<>
inline Bitboard Position::attacks_from<PAWN>(Square s, Color c) const {
return PawnAttacks[c][s];
}
inline Bitboard Position::attacks_from(PieceType pt, Square s) const {
return attacks_bb(pt, s, byTypeBB[ALL_PIECES]);
}
inline Bitboard Position::attackers_to(Square s) const {
return attackers_to(s, byTypeBB[ALL_PIECES]);
return attackers_to(s, pieces());
}
inline Bitboard Position::checkers() const {
@@ -318,11 +293,15 @@ 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 bool Position::is_discovery_check_on_king(Color c, Move m) const {
inline bool Position::is_discovered_check_on_king(Color c, Move m) const {
return st->blockersForKing[c] & from_sq(m);
}
@@ -340,7 +319,8 @@ inline int Position::pawns_on_same_color_squares(Color c, Square s) const {
}
inline Key Position::key() const {
return st->key;
return st->rule50 < 14 ? st->key
: st->key ^ make_key((st->rule50 - 14) / 8);
}
inline Key Position::pawn_key() const {
@@ -360,7 +340,7 @@ inline Value Position::non_pawn_material(Color c) const {
}
inline Value Position::non_pawn_material() const {
return st->nonPawnMaterial[WHITE] + st->nonPawnMaterial[BLACK];
return non_pawn_material(WHITE) + non_pawn_material(BLACK);
}
inline int Position::game_ply() const {
@@ -372,8 +352,8 @@ inline int Position::rule50_count() const {
}
inline bool Position::opposite_bishops() const {
return pieceCount[W_BISHOP] == 1
&& pieceCount[B_BISHOP] == 1
return count<BISHOP>(WHITE) == 1
&& count<BISHOP>(BLACK) == 1
&& opposite_colors(square<BISHOP>(WHITE), square<BISHOP>(BLACK));
}
@@ -389,7 +369,7 @@ inline bool Position::capture_or_promotion(Move m) const {
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) == ENPASSANT;
return (!empty(to_sq(m)) && type_of(m) != CASTLING) || type_of(m) == EN_PASSANT;
}
inline Piece Position::captured_piece() const {
@@ -403,45 +383,34 @@ inline Thread* Position::this_thread() const {
inline void Position::put_piece(Piece pc, Square s) {
board[s] = pc;
byTypeBB[ALL_PIECES] |= s;
byTypeBB[type_of(pc)] |= s;
byTypeBB[ALL_PIECES] |= byTypeBB[type_of(pc)] |= s;
byColorBB[color_of(pc)] |= s;
index[s] = pieceCount[pc]++;
pieceList[pc][index[s]] = s;
pieceCount[pc]++;
pieceCount[make_piece(color_of(pc), ALL_PIECES)]++;
psq += PSQT::psq[pc][s];
}
inline void Position::remove_piece(Piece pc, Square s) {
inline void Position::remove_piece(Square s) {
// WARNING: This is not a reversible operation. If we remove a piece in
// do_move() and then replace it in undo_move() we will put it at the end of
// the list and not in its original place, it means index[] and pieceList[]
// are not invariant to a do_move() + undo_move() sequence.
Piece pc = board[s];
byTypeBB[ALL_PIECES] ^= s;
byTypeBB[type_of(pc)] ^= s;
byColorBB[color_of(pc)] ^= s;
/* board[s] = NO_PIECE; Not needed, overwritten by the capturing one */
Square lastSquare = pieceList[pc][--pieceCount[pc]];
index[lastSquare] = index[s];
pieceList[pc][index[lastSquare]] = lastSquare;
pieceList[pc][pieceCount[pc]] = SQ_NONE;
pieceCount[pc]--;
pieceCount[make_piece(color_of(pc), ALL_PIECES)]--;
psq -= PSQT::psq[pc][s];
}
inline void Position::move_piece(Piece pc, Square from, Square to) {
inline void Position::move_piece(Square from, Square to) {
// index[from] is not updated and becomes stale. This works as long as index[]
// is accessed just by known occupied squares.
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;
index[to] = index[from];
pieceList[pc][index[to]] = to;
psq += PSQT::psq[pc][to] - PSQT::psq[pc][from];
}
@@ -449,4 +418,9 @@ inline void Position::do_move(Move m, StateInfo& newSt) {
do_move(m, newSt, gives_check(m));
}
inline StateInfo* Position::state() const {
return st;
}
#endif // #ifndef POSITION_H_INCLUDED
+44 -46
View File
@@ -1,8 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
@@ -18,23 +16,22 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "psqt.h"
#include <algorithm>
#include "bitboard.h"
#include "types.h"
Value PieceValue[PHASE_NB][PIECE_NB] = {
{ VALUE_ZERO, PawnValueMg, KnightValueMg, BishopValueMg, RookValueMg, QueenValueMg },
{ VALUE_ZERO, PawnValueEg, KnightValueEg, BishopValueEg, RookValueEg, QueenValueEg }
};
namespace PSQT {
namespace
{
#define S(mg, eg) make_score(mg, eg)
auto constexpr S = make_score;
// Bonus[PieceType][Square / 2] contains Piece-Square scores. For each piece
// type on a given square a (middlegame, endgame) score pair is assigned. Table
// is defined for files A..D and white side: it is symmetric for black side and
// second half of the files.
// '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] = {
{ },
{ },
@@ -49,14 +46,14 @@ constexpr Score Bonus[][RANK_NB][int(FILE_NB) / 2] = {
{ S(-201,-100), S(-83,-88), S(-56,-56), S(-26,-17) }
},
{ // Bishop
{ S(-53,-57), S( -5,-30), S( -8,-37), S(-23,-12) },
{ S(-15,-37), S( 8,-13), S( 19,-17), S( 4, 1) },
{ S( -7,-16), S( 21, -1), S( -5, -2), S( 17, 10) },
{ S( -5,-20), S( 11, -6), S( 25, 0), S( 39, 17) },
{ S(-12,-17), S( 29, -1), S( 22,-14), S( 31, 15) },
{ S(-16,-30), S( 6, 6), S( 1, 4), S( 11, 6) },
{ S(-17,-31), S(-14,-20), S( 5, -1), S( 0, 1) },
{ S(-48,-46), S( 1,-42), S(-14,-37), S(-23,-24) }
{ 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) },
@@ -70,13 +67,13 @@ constexpr Score Bonus[][RANK_NB][int(FILE_NB) / 2] = {
},
{ // Queen
{ S( 3,-69), S(-5,-57), S(-5,-47), S( 4,-26) },
{ S(-3,-55), S( 5,-31), S( 8,-22), S(12, -4) },
{ 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,-12), S( 8, 1) },
{ 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,-75), S(-2,-52), S( 1,-43), S(-2,-36) }
{ 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) },
@@ -93,37 +90,38 @@ constexpr Score Bonus[][RANK_NB][int(FILE_NB) / 2] = {
constexpr Score PBonus[RANK_NB][FILE_NB] =
{ // Pawn (asymmetric distribution)
{ },
{ S( 3,-10), S( 3, -6), S( 10, 10), S( 19, 0), S( 16, 14), S( 19, 7), S( 7, -5), S( -5,-19) },
{ S( -9,-10), S(-15,-10), S( 11,-10), S( 15, 4), S( 32, 4), S( 22, 3), S( 5, -6), S(-22, -4) },
{ S( -8, 6), S(-23, -2), S( 6, -8), S( 20, -4), S( 40,-13), S( 17,-12), S( 4,-10), S(-12, -9) },
{ S( 13, 9), S( 0, 4), S(-13, 3), S( 1,-12), S( 11,-12), S( -2, -6), S(-13, 13), S( 5, 8) },
{ S( -5, 28), S(-12, 20), S( -7, 21), S( 22, 28), S( -8, 30), S( -5, 7), S(-15, 6), S(-18, 13) },
{ S( -7, 0), S( 7,-11), S( -3, 12), S(-13, 21), S( 5, 25), S(-16, 19), S( 10, 4), S( -8, 7) }
{ 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) }
};
#undef S
} // namespace
namespace PSQT
{
Score psq[PIECE_NB][SQUARE_NB];
// init() initializes piece-square tables: the white halves of the tables are
// copied from Bonus[] adding the piece value, then the black halves of the
// tables are initialized by flipping and changing the sign of the white scores.
// 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; pc <= W_KING; ++pc)
for (Piece pc : {W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING})
{
PieceValue[MG][~pc] = PieceValue[MG][pc];
PieceValue[EG][~pc] = PieceValue[EG][pc];
Score score = make_score(PieceValue[MG][pc], PieceValue[EG][pc]);
Score score = make_score(PieceValue[MG][pc], PieceValue[EG][pc]);
for (Square s = SQ_A1; s <= SQ_H8; ++s)
{
File f = map_to_queenside(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][~s] = -psq[pc][s];
}
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];
}
}
}
+38
View File
@@ -0,0 +1,38 @@
/*
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 PSQT_H_INCLUDED
#define PSQT_H_INCLUDED
#include "types.h"
namespace PSQT
{
extern Score psq[PIECE_NB][SQUARE_NB];
// Fill psqt array from a set of internally linked parameters
extern void init();
} // namespace PSQT
#endif // PSQT_H_INCLUDED
+434 -298
View File
File diff suppressed because it is too large Load Diff
+5 -5
View File
@@ -1,8 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
@@ -49,6 +47,9 @@ struct Stack {
Value staticEval;
int statScore;
int moveCount;
bool inCheck;
bool ttPv;
bool ttHit;
};
@@ -70,7 +71,6 @@ struct RootMove {
Value previousScore = -VALUE_INFINITE;
int selDepth = 0;
int tbRank = 0;
int bestMoveCount = 0;
Value tbScore;
std::vector<Move> pv;
};
@@ -90,7 +90,7 @@ struct LimitsType {
}
bool use_time_management() const {
return !(mate | movetime | depth | nodes | perft | infinite);
return time[WHITE] || time[BLACK];
}
std::vector<Move> searchmoves;
+37 -27
View File
@@ -1,7 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (c) 2013 Ronald de Man
Copyright (C) 2016-2020 Marco Costalba, Lucas Braesch
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
@@ -60,13 +59,12 @@ namespace {
constexpr int TBPIECES = 7; // Max number of supported pieces
enum { BigEndian, LittleEndian };
enum TBType { KEY, WDL, DTZ }; // Used as template parameter
enum TBType { WDL, DTZ }; // Used as template parameter
// Each table has a set of flags: all of them refer to DTZ tables, the last one to WDL tables
enum TBFlag { STM = 1, Mapped = 2, WinPlies = 4, LossPlies = 8, Wide = 16, SingleValue = 128 };
inline WDLScore operator-(WDLScore d) { return WDLScore(-int(d)); }
inline Square operator^=(Square& s, int i) { return s = Square(int(s) ^ i); }
inline Square operator^(Square s, int i) { return Square(int(s) ^ i); }
const std::string PieceToChar = " PNBRQK pnbrqk";
@@ -225,7 +223,9 @@ public:
*mapping = statbuf.st_size;
*baseAddress = mmap(nullptr, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
#if defined(MADV_RANDOM)
madvise(*baseAddress, statbuf.st_size, MADV_RANDOM);
#endif
::close(fd);
if (*baseAddress == MAP_FAILED)
@@ -404,7 +404,17 @@ TBTable<DTZ>::TBTable(const TBTable<WDL>& wdl) : TBTable() {
// at init time, accessed at probe time.
class TBTables {
typedef std::tuple<Key, TBTable<WDL>*, TBTable<DTZ>*> Entry;
struct Entry
{
Key key;
TBTable<WDL>* wdl;
TBTable<DTZ>* dtz;
template <TBType Type>
TBTable<Type>* get() const {
return (TBTable<Type>*)(Type == WDL ? (void*)wdl : (void*)dtz);
}
};
static constexpr int Size = 1 << 12; // 4K table, indexed by key's 12 lsb
static constexpr int Overflow = 1; // Number of elements allowed to map to the last bucket
@@ -416,12 +426,12 @@ class TBTables {
void insert(Key key, TBTable<WDL>* wdl, TBTable<DTZ>* dtz) {
uint32_t homeBucket = (uint32_t)key & (Size - 1);
Entry entry = std::make_tuple(key, wdl, dtz);
Entry entry{ key, wdl, dtz };
// Ensure last element is empty to avoid overflow when looking up
for (uint32_t bucket = homeBucket; bucket < Size + Overflow - 1; ++bucket) {
Key otherKey = std::get<KEY>(hashTable[bucket]);
if (otherKey == key || !std::get<WDL>(hashTable[bucket])) {
Key otherKey = hashTable[bucket].key;
if (otherKey == key || !hashTable[bucket].get<WDL>()) {
hashTable[bucket] = entry;
return;
}
@@ -430,7 +440,7 @@ class TBTables {
// insert here and search for a new spot for the other element instead.
uint32_t otherHomeBucket = (uint32_t)otherKey & (Size - 1);
if (otherHomeBucket > homeBucket) {
swap(entry, hashTable[bucket]);
std::swap(entry, hashTable[bucket]);
key = otherKey;
homeBucket = otherHomeBucket;
}
@@ -443,8 +453,8 @@ public:
template<TBType Type>
TBTable<Type>* get(Key key) {
for (const Entry* entry = &hashTable[(uint32_t)key & (Size - 1)]; ; ++entry) {
if (std::get<KEY>(*entry) == key || !std::get<Type>(*entry))
return std::get<Type>(*entry);
if (entry->key == key || !entry->get<Type>())
return entry->get<Type>();
}
}
@@ -521,7 +531,7 @@ int decompress_pairs(PairsData* d, uint64_t idx) {
// I(k) = k * d->span + d->span / 2 (1)
// First step is to get the 'k' of the I(k) nearest to our idx, using definition (1)
uint32_t k = idx / d->span;
uint32_t k = uint32_t(idx / d->span);
// Then we read the corresponding SparseIndex[] entry
uint32_t block = number<uint32_t, LittleEndian>(&d->sparseIndex[k].block);
@@ -567,7 +577,7 @@ int decompress_pairs(PairsData* d, uint64_t idx) {
// All the symbols of a given length are consecutive integers (numerical
// sequence property), so we can compute the offset of our symbol of
// length len, stored at the beginning of buf64.
sym = (buf64 - d->base64[len]) >> (64 - len - d->minSymLen);
sym = Sym((buf64 - d->base64[len]) >> (64 - len - d->minSymLen));
// Now add the value of the lowest symbol of length len to get our symbol
sym += number<Sym, LittleEndian>(&d->lowestSym[len]);
@@ -706,7 +716,7 @@ Ret do_probe_table(const Position& pos, T* entry, WDLScore wdl, ProbeState* resu
std::swap(squares[0], *std::max_element(squares, squares + leadPawnsCnt, pawns_comp));
tbFile = map_to_queenside(file_of(squares[0]));
tbFile = File(edge_distance(file_of(squares[0])));
}
// DTZ tables are one-sided, i.e. they store positions only for white to
@@ -743,14 +753,14 @@ Ret do_probe_table(const Position& pos, T* entry, WDLScore wdl, ProbeState* resu
// the triangle A1-D1-D4.
if (file_of(squares[0]) > FILE_D)
for (int i = 0; i < size; ++i)
squares[i] ^= 7; // Horizontal flip: SQ_H1 -> SQ_A1
squares[i] = flip_file(squares[i]);
// Encode leading pawns starting with the one with minimum MapPawns[] and
// proceeding in ascending order.
if (entry->hasPawns) {
idx = LeadPawnIdx[leadPawnsCnt][squares[0]];
std::sort(squares + 1, squares + leadPawnsCnt, pawns_comp);
std::stable_sort(squares + 1, squares + leadPawnsCnt, pawns_comp);
for (int i = 1; i < leadPawnsCnt; ++i)
idx += Binomial[i][MapPawns[squares[i]]];
@@ -762,7 +772,7 @@ Ret do_probe_table(const Position& pos, T* entry, WDLScore wdl, ProbeState* resu
// piece is below RANK_5.
if (rank_of(squares[0]) > RANK_4)
for (int i = 0; i < size; ++i)
squares[i] ^= SQ_A8; // Vertical flip: SQ_A8 -> SQ_A1
squares[i] = flip_rank(squares[i]);
// Look for the first piece of the leading group not on the A1-D4 diagonal
// and ensure it is mapped below the diagonal.
@@ -770,7 +780,7 @@ Ret do_probe_table(const Position& pos, T* entry, WDLScore wdl, ProbeState* resu
if (!off_A1H8(squares[i]))
continue;
if (off_A1H8(squares[i]) > 0) // A1-H8 diagonal flip: SQ_A3 -> SQ_C3
if (off_A1H8(squares[i]) > 0) // A1-H8 diagonal flip: SQ_A3 -> SQ_C1
for (int j = i; j < size; ++j)
squares[j] = Square(((squares[j] >> 3) | (squares[j] << 3)) & 63);
break;
@@ -851,7 +861,7 @@ encode_remaining:
while (d->groupLen[++next])
{
std::sort(groupSq, groupSq + d->groupLen[next]);
std::stable_sort(groupSq, groupSq + d->groupLen[next]);
uint64_t n = 0;
// Map down a square if "comes later" than a square in the previous
@@ -975,7 +985,7 @@ uint8_t* set_sizes(PairsData* d, uint8_t* data) {
d->sizeofBlock = 1ULL << *data++;
d->span = 1ULL << *data++;
d->sparseIndexSize = (tbSize + d->span - 1) / d->span; // Round up
d->sparseIndexSize = size_t((tbSize + d->span - 1) / d->span); // Round up
auto padding = number<uint8_t, LittleEndian>(data++);
d->blocksNum = number<uint32_t, LittleEndian>(data); data += sizeof(uint32_t);
d->blockLengthSize = d->blocksNum + padding; // Padded to ensure SparseIndex[]
@@ -990,7 +1000,7 @@ uint8_t* set_sizes(PairsData* d, uint8_t* data) {
// so that d->lowestSym[i] >= d->lowestSym[i+1] (when read as LittleEndian).
// Starting from this we compute a base64[] table indexed by symbol length
// and containing 64 bit values so that d->base64[i] >= d->base64[i+1].
// See http://www.eecs.harvard.edu/~michaelm/E210/huffman.pdf
// See https://en.wikipedia.org/wiki/Huffman_coding
for (int i = d->base64.size() - 2; i >= 0; --i) {
d->base64[i] = (d->base64[i + 1] + number<Sym, LittleEndian>(&d->lowestSym[i])
- number<Sym, LittleEndian>(&d->lowestSym[i + 1])) / 2;
@@ -1131,7 +1141,7 @@ void* mapped(TBTable<Type>& e, const Position& pos) {
if (e.ready.load(std::memory_order_acquire))
return e.baseAddress; // Could be nullptr if file does not exist
std::unique_lock<std::mutex> lk(mutex);
std::scoped_lock<std::mutex> lk(mutex);
if (e.ready.load(std::memory_order_relaxed)) // Recheck under lock
return e.baseAddress;
@@ -1191,7 +1201,7 @@ WDLScore search(Position& pos, ProbeState* result) {
auto moveList = MoveList<LEGAL>(pos);
size_t totalCount = moveList.size(), moveCount = 0;
for (const Move& move : moveList)
for (const Move move : moveList)
{
if ( !pos.capture(move)
&& (!CheckZeroingMoves || type_of(pos.moved_piece(move)) != PAWN))
@@ -1344,7 +1354,7 @@ void Tablebases::init(const std::string& paths) {
if (leadPawnsCnt == 1)
{
MapPawns[sq] = availableSquares--;
MapPawns[sq ^ 7] = availableSquares--; // Horizontal flip
MapPawns[flip_file(sq)] = availableSquares--;
}
LeadPawnIdx[leadPawnsCnt][sq] = idx;
idx += Binomial[leadPawnsCnt - 1][MapPawns[sq]];
@@ -1353,7 +1363,7 @@ void Tablebases::init(const std::string& paths) {
LeadPawnsSize[leadPawnsCnt][f] = idx;
}
// Add entries in TB tables if the corresponding ".rtbw" file exsists
// Add entries in TB tables if the corresponding ".rtbw" file exists
for (PieceType p1 = PAWN; p1 < KING; ++p1) {
TBTables.add({KING, p1, KING});
@@ -1430,7 +1440,7 @@ WDLScore Tablebases::probe_wdl(Position& pos, ProbeState* result) {
// If n = 100 immediately after a capture or pawn move, then the position
// is also certainly a win, and during the whole phase until the next
// capture or pawn move, the inequality to be preserved is
// dtz + 50-movecounter <= 100.
// dtz + 50-move-counter <= 100.
//
// In short, if a move is available resulting in dtz + 50-move-counter <= 99,
// then do not accept moves leading to dtz + 50-move-counter == 100.
@@ -1460,7 +1470,7 @@ int Tablebases::probe_dtz(Position& pos, ProbeState* result) {
StateInfo st;
int minDTZ = 0xFFFF;
for (const Move& move : MoveList<LEGAL>(pos))
for (const Move move : MoveList<LEGAL>(pos))
{
bool zeroing = pos.capture(move) || type_of(pos.moved_piece(move)) == PAWN;
+1 -2
View File
@@ -1,7 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (c) 2013 Ronald de Man
Copyright (C) 2016-2020 Marco Costalba, Lucas Braesch
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
+72 -32
View File
@@ -1,8 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
@@ -52,15 +50,6 @@ Thread::~Thread() {
stdThread.join();
}
/// Thread::bestMoveCount(Move move) return best move counter for the given root move
int Thread::best_move_count(Move move) {
auto rm = std::find(rootMoves.begin() + pvIdx,
rootMoves.begin() + pvLast, move);
return rm != rootMoves.begin() + pvLast ? rm->bestMoveCount : 0;
}
/// Thread::clear() reset histories, usually before a new game
@@ -68,19 +57,20 @@ 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);
for (bool inCheck : { false, true })
for (StatsType c : { NoCaptures, Captures })
continuationHistory[inCheck][c][NO_PIECE][0]->fill(Search::CounterMovePruneThreshold - 1);
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
void Thread::start_searching() {
@@ -151,14 +141,15 @@ void ThreadPool::set(size_t requested) {
clear();
// Reallocate the hash with the new threadpool size
TT.resize(Options["Hash"]);
TT.resize(size_t(Options["Hash"]));
// Init thread number dependent search params.
Search::init();
}
}
/// ThreadPool::clear() sets threadPool data to initial values.
/// ThreadPool::clear() sets threadPool data to initial values
void ThreadPool::clear() {
@@ -166,10 +157,11 @@ void ThreadPool::clear() {
th->clear();
main()->callsCnt = 0;
main()->previousScore = VALUE_INFINITE;
main()->bestPreviousScore = VALUE_INFINITE;
main()->previousTimeReduction = 1.0;
}
/// 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.
@@ -201,20 +193,68 @@ void ThreadPool::start_thinking(Position& pos, StateListPtr& states,
// 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 to not lose the info
// we need to backup and later restore setupStates->back(). Note that setupStates
// is shared by threads but is accessed in read-only mode.
StateInfo tmp = setupStates->back();
// 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 = 0;
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(), &setupStates->back(), th);
th->rootPos.set(pos.fen(), pos.is_chess960(), &th->rootState, th);
th->rootState = setupStates->back();
}
setupStates->back() = tmp;
main()->start_searching();
}
Thread* ThreadPool::get_best_thread() const {
Thread* bestThread = front();
std::map<Move, int64_t> votes;
Value minScore = VALUE_NONE;
// Find minimum score of all threads
for (Thread* th: *this)
minScore = std::min(minScore, th->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);
if (abs(bestThread->rootMoves[0].score) >= VALUE_TB_WIN_IN_MAX_PLY)
{
// Make sure we pick the shortest mate / TB conversion or stave off mate the longest
if (th->rootMoves[0].score > bestThread->rootMoves[0].score)
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]]))
bestThread = th;
}
return bestThread;
}
/// Start non-main threads
void ThreadPool::start_searching() {
for (Thread* th : *this)
if (th != front())
th->start_searching();
}
/// Wait for non-main threads
void ThreadPool::wait_for_search_finished() const {
for (Thread* th : *this)
if (th != front())
th->wait_for_search_finished();
}
+8 -5
View File
@@ -1,8 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
@@ -56,7 +54,6 @@ public:
void idle_loop();
void start_searching();
void wait_for_search_finished();
int best_move_count(Move move);
Pawns::Table pawnsTable;
Material::Table materialTable;
@@ -67,13 +64,16 @@ public:
std::atomic<uint64_t> nodes, tbHits, bestMoveChanges;
Position rootPos;
StateInfo rootState;
Search::RootMoves rootMoves;
Depth rootDepth, completedDepth;
CounterMoveHistory counterMoves;
ButterflyHistory mainHistory;
LowPlyHistory lowPlyHistory;
CapturePieceToHistory captureHistory;
ContinuationHistory continuationHistory[2][2];
Score contempt;
int failedHighCnt;
};
@@ -87,7 +87,7 @@ struct MainThread : public Thread {
void check_time();
double previousTimeReduction;
Value previousScore;
Value bestPreviousScore;
Value iterValue[4];
int callsCnt;
bool stopOnPonderhit;
@@ -108,6 +108,9 @@ struct ThreadPool : public std::vector<Thread*> {
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;
+2 -4
View File
@@ -1,8 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
@@ -29,7 +27,7 @@
/// 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__)
#if defined(__APPLE__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(USE_PTHREADS)
#include <pthread.h>
+41 -77
View File
@@ -1,8 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
@@ -28,66 +26,21 @@
TimeManagement Time; // Our global time management object
namespace {
enum TimeType { OptimumTime, MaxTime };
constexpr int MoveHorizon = 50; // Plan time management at most this many moves ahead
constexpr double MaxRatio = 7.3; // When in trouble, we can step over reserved time with this ratio
constexpr double StealRatio = 0.34; // However we must not steal time from remaining moves over this ratio
// move_importance() is a skew-logistic function based on naive statistical
// analysis of "how many games are still undecided after n half-moves". Game
// is considered "undecided" as long as neither side has >275cp advantage.
// Data was extracted from the CCRL game database with some simple filtering criteria.
double move_importance(int ply) {
constexpr double XScale = 6.85;
constexpr double XShift = 64.5;
constexpr double Skew = 0.171;
return pow((1 + exp((ply - XShift) / XScale)), -Skew) + DBL_MIN; // Ensure non-zero
}
template<TimeType T>
TimePoint remaining(TimePoint myTime, int movesToGo, int ply, TimePoint slowMover) {
constexpr double TMaxRatio = (T == OptimumTime ? 1.0 : MaxRatio);
constexpr double TStealRatio = (T == OptimumTime ? 0.0 : StealRatio);
double moveImportance = (move_importance(ply) * slowMover) / 100.0;
double otherMovesImportance = 0.0;
for (int i = 1; i < movesToGo; ++i)
otherMovesImportance += move_importance(ply + 2 * i);
double ratio1 = (TMaxRatio * moveImportance) / (TMaxRatio * moveImportance + otherMovesImportance);
double ratio2 = (moveImportance + TStealRatio * otherMovesImportance) / (moveImportance + otherMovesImportance);
return TimePoint(myTime * std::min(ratio1, ratio2)); // Intel C++ asks for an explicit cast
}
} // namespace
/// init() is called at the beginning of the search and calculates the allowed
/// thinking time out of the time control and current game ply. We support four
/// different kinds of time controls, passed in 'limits':
///
/// inc == 0 && movestogo == 0 means: x basetime [sudden death!]
/// inc == 0 && movestogo != 0 means: x moves in y minutes
/// inc > 0 && movestogo == 0 means: x basetime + z increment
/// inc > 0 && movestogo != 0 means: x moves in y minutes + z increment
/// 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 minThinkingTime = Options["Minimum Thinking Time"];
TimePoint moveOverhead = Options["Move Overhead"];
TimePoint slowMover = Options["Slow Mover"];
TimePoint npmsec = Options["nodestime"];
TimePoint hypMyTime;
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.
@@ -105,29 +58,40 @@ void TimeManagement::init(Search::LimitsType& limits, Color us, int ply) {
}
startTime = limits.startTime;
optimumTime = maximumTime = std::max(limits.time[us], minThinkingTime);
const int maxMTG = limits.movestogo ? std::min(limits.movestogo, MoveHorizon) : MoveHorizon;
// Maximum move horizon of 50 moves
int mtg = limits.movestogo ? std::min(limits.movestogo, 50) : 50;
// We calculate optimum time usage for different hypothetical "moves to go" values
// and choose the minimum of calculated search time values. Usually the greatest
// hypMTG gives the minimum values.
for (int hypMTG = 1; hypMTG <= maxMTG; ++hypMTG)
// 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));
// 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)
{
// Calculate thinking time for hypothetical "moves to go"-value
hypMyTime = limits.time[us]
+ limits.inc[us] * (hypMTG - 1)
- moveOverhead * (2 + std::min(hypMTG, 40));
hypMyTime = std::max(hypMyTime, TimePoint(0));
TimePoint t1 = minThinkingTime + remaining<OptimumTime>(hypMyTime, hypMTG, ply, slowMover);
TimePoint t2 = minThinkingTime + remaining<MaxTime >(hypMyTime, hypMTG, ply, slowMover);
optimumTime = std::min(t1, optimumTime);
maximumTime = std::min(t2, maximumTime);
optScale = std::min(0.0084 + std::pow(ply + 3.0, 0.5) * 0.0042,
0.2 * limits.time[us] / double(timeLeft));
maxScale = std::min(7.0, 4.0 + ply / 12.0);
}
// x moves in y seconds (+ z increment)
else
{
optScale = std::min((0.8 + ply / 128.0) / mtg,
0.8 * 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;
}
+1 -3
View File
@@ -1,8 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
+33 -33
View File
@@ -1,8 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
@@ -30,27 +28,28 @@
TranspositionTable TT; // Our global transposition table
/// TTEntry::save populates the TTEntry with a new node's data, possibly
/// TTEntry::save() populates the TTEntry with a new node's data, possibly
/// overwriting an old position. 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) {
// Preserve any existing move for the same position
if (m || (k >> 48) != key16)
if (m || (uint16_t)k != key16)
move16 = (uint16_t)m;
// Overwrite less valuable entries
if ( (k >> 48) != key16
|| d - DEPTH_OFFSET > depth8 - 4
|| b == BOUND_EXACT)
// 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 > DEPTH_OFFSET);
assert(d < 256 + DEPTH_OFFSET);
key16 = (uint16_t)(k >> 48);
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;
genBound8 = (uint8_t)(TT.generation8 | uint8_t(pv) << 2 | b);
depth8 = (uint8_t)(d - DEPTH_OFFSET);
}
}
@@ -63,19 +62,18 @@ void TranspositionTable::resize(size_t mbSize) {
Threads.main()->wait_for_search_finished();
aligned_large_pages_free(table);
clusterCount = mbSize * 1024 * 1024 / sizeof(Cluster);
free(mem);
mem = malloc(clusterCount * sizeof(Cluster) + CacheLineSize - 1);
if (!mem)
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);
}
table = (Cluster*)((uintptr_t(mem) + CacheLineSize - 1) & ~(CacheLineSize - 1));
clear();
}
@@ -96,8 +94,8 @@ void TranspositionTable::clear() {
WinProcGroup::bindThisThread(idx);
// Each thread will zero its part of the hash table
const size_t stride = clusterCount / Options["Threads"],
start = stride * idx,
const size_t stride = size_t(clusterCount / Options["Threads"]),
start = size_t(stride * idx),
len = idx != Options["Threads"] - 1 ?
stride : clusterCount - start;
@@ -105,10 +103,11 @@ void TranspositionTable::clear() {
});
}
for (std::thread& th: threads)
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
@@ -119,25 +118,26 @@ void TranspositionTable::clear() {
TTEntry* TranspositionTable::probe(const Key key, bool& found) const {
TTEntry* const tte = first_entry(key);
const uint16_t key16 = key >> 48; // Use the high 16 bits as key inside the cluster
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 || tte[i].key16 == key16)
if (tte[i].key16 == key16 || !tte[i].depth8)
{
tte[i].genBound8 = uint8_t(generation8 | (tte[i].genBound8 & 0x7)); // Refresh
tte[i].genBound8 = uint8_t(generation8 | (tte[i].genBound8 & (GENERATION_DELTA - 1))); // Refresh
return found = (bool)tte[i].key16, &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 263 (256 is the modulus plus 7 to keep the unrelated
// lowest three bits from affecting the result) to calculate the entry
// age correctly even after generation8 overflows into the next cycle.
if ( replace->depth8 - ((263 + generation8 - replace->genBound8) & 0xF8)
> tte[i].depth8 - ((263 + generation8 - tte[i].genBound8) & 0xF8))
// 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;
@@ -150,9 +150,9 @@ TTEntry* TranspositionTable::probe(const Key key, bool& found) const {
int TranspositionTable::hashfull() const {
int cnt = 0;
for (int i = 0; i < 1000 / ClusterSize; ++i)
for (int i = 0; i < 1000; ++i)
for (int j = 0; j < ClusterSize; ++j)
cnt += (table[i].entry[j].genBound8 & 0xF8) == generation8;
cnt += table[i].entry[j].depth8 && (table[i].entry[j].genBound8 & GENERATION_MASK) == generation8;
return cnt * 1000 / (ClusterSize * (1000 / ClusterSize));
return cnt / ClusterSize;
}
+24 -24
View File
@@ -1,8 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
@@ -27,13 +25,13 @@
/// TTEntry struct is the 10 bytes transposition table entry, defined as below:
///
/// key 16 bit
/// move 16 bit
/// value 16 bit
/// eval value 16 bit
/// depth 8 bit
/// generation 5 bit
/// pv node 1 bit
/// bound type 2 bit
/// depth 8 bit
/// move 16 bit
/// value 16 bit
/// eval value 16 bit
struct TTEntry {
@@ -41,7 +39,7 @@ struct TTEntry {
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); }
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);
@@ -49,44 +47,47 @@ private:
friend class TranspositionTable;
uint16_t key16;
uint8_t depth8;
uint8_t genBound8;
uint16_t move16;
int16_t value16;
int16_t eval16;
uint8_t genBound8;
uint8_t depth8;
};
/// A TranspositionTable consists of a power of 2 number of clusters and each
/// cluster consists of ClusterSize number of TTEntry. Each non-empty entry
/// contains information of exactly one position. The size of a cluster should
/// divide the size of a cache line size, to ensure that clusters never cross
/// cache lines. This ensures best cache performance, as the cacheline is
/// prefetched, as soon as 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 CacheLineSize = 64;
static constexpr int ClusterSize = 3;
struct Cluster {
TTEntry entry[ClusterSize];
char padding[2]; // Align to a divisor of the cache line size
char padding[2]; // Pad to 32 bytes
};
static_assert(CacheLineSize % sizeof(Cluster) == 0, "Cluster size incorrect");
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
public:
~TranspositionTable() { free(mem); }
void new_search() { generation8 += 8; } // Lower 3 bits are used by PV flag and Bound
~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();
// The 32 lowest order bits of the key are used to get the index of the cluster
TTEntry* first_entry(const Key key) const {
return &table[(uint32_t(key) * uint64_t(clusterCount)) >> 32].entry[0];
return &table[mul_hi64(key, clusterCount)].entry[0];
}
private:
@@ -94,7 +95,6 @@ private:
size_t clusterCount;
Cluster* table;
void* mem;
uint8_t generation8; // Size must be not bigger than TTEntry::genBound8
};
+144
View File
@@ -0,0 +1,144 @@
/*
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 <iostream>
#include <sstream>
#include "types.h"
#include "misc.h"
#include "uci.h"
using std::string;
bool Tune::update_on_last;
const UCI::Option* LastOption = nullptr;
BoolConditions Conditions;
static std::map<std::string, int> TuneResults;
string Tune::next(string& names, bool pop) {
string name;
do {
string token = names.substr(0, names.find(','));
if (pop)
names.erase(0, token.size() + 1);
std::stringstream ws(token);
name += (ws >> token, token); // Remove trailing whitespace
} while ( std::count(name.begin(), name.end(), '(')
- std::count(name.begin(), name.end(), ')'));
return name;
}
static void on_tune(const UCI::Option& o) {
if (!Tune::update_on_last || LastOption == &o)
Tune::read_options();
}
static void make_option(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;
if (TuneResults.count(n))
v = TuneResults[n];
Options[n] << UCI::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;
}
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<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]));
}
// 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(); }
// Set binary conditions according to a probability that depends
// on the corresponding parameter value.
void BoolConditions::set() {
static PRNG rng(now());
static bool startup = true; // To workaround fishtest bench
for (size_t i = 0; i < binary.size(); i++)
binary[i] = !startup && (values[i] + int(rng.rand<unsigned>() % variance) > threshold);
startup = false;
for (size_t i = 0; i < binary.size(); i++)
sync_cout << binary[i] << sync_endl;
}
// Init options with tuning session results instead of default values. Useful to
// get correct bench signature after a tuning session or to test tuned values.
// Just copy fishtest tuning results in a result.txt file and extract the
// values with:
//
// cat results.txt | sed 's/^param: \([^,]*\), best: \([^,]*\).*/ TuneResults["\1"] = int(round(\2));/'
//
// Then paste the output below, as the function body
#include <cmath>
void Tune::read_results() {
/* ...insert your values here... */
}
+193
View File
@@ -0,0 +1,193 @@
/*
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 TUNE_H_INCLUDED
#define TUNE_H_INCLUDED
#include <memory>
#include <string>
#include <type_traits>
#include <vector>
typedef std::pair<int, int> Range; // Option's min-max values
typedef Range (RangeFun) (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);
}
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; }
RangeFun* fun;
Range range;
};
#define SetDefaultRange SetRange(default_range)
/// BoolConditions struct is used to tune boolean conditions in the
/// code by toggling them on/off according to a probability that
/// depends on the value of a tuned integer parameter: for high
/// values of the parameter condition is always disabled, for low
/// values is always enabled, otherwise it is enabled with a given
/// probability that depnends on the parameter under tuning.
struct BoolConditions {
void init(size_t size) { values.resize(size, defaultValue), binary.resize(size, 0); }
void set();
std::vector<int> binary, values;
int defaultValue = 465, variance = 40, threshold = 500;
SetRange range = SetRange(0, 1000);
};
extern BoolConditions Conditions;
inline void set_conditions() { Conditions.set(); }
/// 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.
class Tune {
typedef void (PostUpdate) (); // Post-update function
Tune() { read_results(); }
Tune(const Tune&) = delete;
void operator=(const Tune&) = delete;
void read_results();
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;
};
template<typename T>
struct Entry : public EntryBase {
static_assert(!std::is_const<T>::value, "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!");
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;
};
// 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; }
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 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 BoolConditions
template<typename... Args>
int add(const SetRange& range, std::string&& names, BoolConditions& cond, Args&&... args) {
for (size_t size = cond.values.size(), i = 0; i < size; i++)
add(cond.range, next(names, i == size - 1) + "_" + std::to_string(i), cond.values[i]);
return add(range, std::move(names), args...);
}
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;
};
// Some macro magic :-) we define a dummy int variable that 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 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
// Some macro to tune toggling of boolean conditions
#define CONDITION(x) (Conditions.binary[__COUNTER__] || (x))
#define TUNE_CONDITIONS() int UNIQUE(c, __LINE__) = (Conditions.init(__COUNTER__), 0); \
TUNE(Conditions, set_conditions)
#endif // #ifndef TUNE_H_INCLUDED
+62 -34
View File
@@ -1,8 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
@@ -40,7 +38,6 @@
#include <cassert>
#include <cctype>
#include <climits>
#include <cstdint>
#include <cstdlib>
#include <algorithm>
@@ -60,6 +57,12 @@
/// _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
#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
@@ -110,7 +113,7 @@ constexpr int MAX_PLY = 246;
/// 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
/// 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
@@ -124,7 +127,7 @@ enum Move : int {
enum MoveType {
NORMAL,
PROMOTION = 1 << 14,
ENPASSANT = 2 << 14,
EN_PASSANT = 2 << 14,
CASTLING = 3 << 14
};
@@ -176,14 +179,17 @@ enum Value : int {
VALUE_INFINITE = 32001,
VALUE_NONE = 32002,
VALUE_MATE_IN_MAX_PLY = VALUE_MATE - 2 * MAX_PLY,
VALUE_MATED_IN_MAX_PLY = -VALUE_MATE + 2 * MAX_PLY,
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,
PawnValueMg = 128, PawnValueEg = 213,
PawnValueMg = 126, PawnValueEg = 208,
KnightValueMg = 781, KnightValueEg = 854,
BishopValueMg = 825, BishopValueEg = 915,
RookValueMg = 1276, RookValueEg = 1380,
QueenValueMg = 2538, QueenValueEg = 2682,
Tempo = 28,
MidgameLimit = 15258, EndgameLimit = 3915
};
@@ -196,23 +202,28 @@ enum PieceType {
enum Piece {
NO_PIECE,
W_PAWN = 1, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING,
B_PAWN = 9, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING,
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
};
extern Value PieceValue[PHASE_NB][PIECE_NB];
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 }
};
typedef int Depth;
enum : int {
DEPTH_QS_CHECKS = 0,
DEPTH_QS_NO_CHECKS = -1,
DEPTH_QS_RECAPTURES = -5,
DEPTH_NONE = -6,
DEPTH_OFFSET = DEPTH_NONE,
DEPTH_OFFSET = -7 // value used only for TT entry occupancy check
};
enum Square : int {
@@ -226,7 +237,8 @@ enum Square : int {
SQ_A8, SQ_B8, SQ_C8, SQ_D8, SQ_E8, SQ_F8, SQ_G8, SQ_H8,
SQ_NONE,
SQUARE_NB = 64
SQUARE_ZERO = 0,
SQUARE_NB = 64
};
enum Direction : int {
@@ -249,6 +261,21 @@ enum Rank : int {
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;
// 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];
};
/// 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
@@ -274,11 +301,11 @@ inline Value mg_value(Score s) {
}
#define ENABLE_BASE_OPERATORS_ON(T) \
constexpr T operator+(T d1, T d2) { return T(int(d1) + int(d2)); } \
constexpr T operator-(T d1, T d2) { return T(int(d1) - int(d2)); } \
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, T d2) { return d1 = d1 + d2; } \
inline T& operator-=(T& d1, T d2) { return d1 = d1 - d2; }
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); } \
@@ -296,8 +323,8 @@ 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(PieceType)
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)
@@ -308,12 +335,6 @@ ENABLE_BASE_OPERATORS_ON(Score)
#undef ENABLE_INCR_OPERATORS_ON
#undef ENABLE_BASE_OPERATORS_ON
/// Additional operators to add integers to a Value
constexpr Value operator+(Value v, int i) { return Value(int(v) + i); }
constexpr Value operator-(Value v, int i) { return Value(int(v) - i); }
inline Value& operator+=(Value& v, int i) { return v = v + i; }
inline Value& operator-=(Value& v, int i) { return v = v - i; }
/// 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)); }
@@ -343,23 +364,23 @@ inline Score operator*(Score s, int i) {
/// Multiplication of a Score by a boolean
inline Score operator*(Score s, bool b) {
return Score(int(s) * int(b));
return b ? s : SCORE_ZERO;
}
constexpr Color operator~(Color c) {
return Color(c ^ BLACK); // Toggle color
}
constexpr Square operator~(Square s) {
return Square(s ^ SQ_A8); // Vertical flip SQ_A1 -> SQ_A8
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
}
inline File map_to_queenside(File f) {
return std::min(f, File(FILE_H - f)); // Map files ABCDEFGH to files ABCDDCBA
return Piece(pc ^ 8); // Swap color of piece B_KNIGHT <-> W_KNIGHT
}
constexpr CastlingRights operator&(Color c, CastlingRights cr) {
@@ -456,4 +477,11 @@ 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
constexpr Key make_key(uint64_t seed) {
return seed * 6364136223846793005ULL + 1442695040888963407ULL;
}
#endif // #ifndef TYPES_H_INCLUDED
#include "tune.h" // Global visibility to tuning setup
+59 -8
View File
@@ -1,8 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
@@ -19,6 +17,7 @@
*/
#include <cassert>
#include <cmath>
#include <iostream>
#include <sstream>
#include <string>
@@ -77,6 +76,20 @@ namespace {
}
}
// trace_eval() prints the evaluation for the current position, consistent with the UCI
// options set so far.
void trace_eval(Position& pos) {
StateListPtr states(new std::deque<StateInfo>(1));
Position p;
p.set(pos.fen(), Options["UCI_Chess960"], &states->back(), Threads.main());
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").
@@ -115,7 +128,7 @@ namespace {
limits.startTime = now(); // As early as possible!
while (is >> token)
if (token == "searchmoves")
if (token == "searchmoves") // Needs to be the last command on the line
while (is >> token)
limits.searchmoves.push_back(UCI::to_move(pos, token));
@@ -157,7 +170,7 @@ namespace {
if (token == "go" || token == "eval")
{
cerr << "\nPosition: " << cnt++ << '/' << num << endl;
cerr << "\nPosition: " << cnt++ << '/' << num << " (" << pos.fen() << ")" << endl;
if (token == "go")
{
go(pos, is, states);
@@ -165,7 +178,7 @@ namespace {
nodes += Threads.nodes_searched();
}
else
sync_cout << "\n" << Eval::trace(pos) << sync_endl;
trace_eval(pos);
}
else if (token == "setoption") setoption(is);
else if (token == "position") position(pos, is, states);
@@ -182,6 +195,28 @@ namespace {
<< "\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[] = {-8.24404295, 64.23892342, -95.73056462, 153.86478679};
double bs[] = {-3.37154371, 28.44489198, -56.67657741, 72.05858751};
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, -1000.0, 1000.0);
// Return win rate in per mille (rounded to nearest)
return int(0.5 + 1000 / (1 + std::exp((a - x) / b)));
}
} // namespace
@@ -238,7 +273,7 @@ void UCI::loop(int argc, char* argv[]) {
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") sync_cout << Eval::trace(pos) << sync_endl;
else if (token == "eval") trace_eval(pos);
else if (token == "compiler") sync_cout << compiler_info() << sync_endl;
else
sync_cout << "Unknown command: " << cmd << sync_endl;
@@ -260,7 +295,7 @@ string UCI::value(Value v) {
stringstream ss;
if (abs(v) < VALUE_MATE - MAX_PLY)
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;
@@ -269,6 +304,22 @@ string UCI::value(Value v) {
}
/// 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) {
+2 -3
View File
@@ -1,8 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
@@ -73,6 +71,7 @@ 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
+13 -12
View File
@@ -1,8 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
@@ -23,6 +21,7 @@
#include <ostream>
#include <sstream>
#include "evaluate.h"
#include "misc.h"
#include "search.h"
#include "thread.h"
@@ -38,11 +37,12 @@ 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(o); }
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(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 {
@@ -52,12 +52,11 @@ bool CaseInsensitiveLess::operator() (const string& s1, const string& s2) const
}
/// init() initializes the UCI options to their hard-coded default values
/// UCI::init() initializes the UCI options to their hard-coded default values
void init(OptionsMap& o) {
// at most 2^32 clusters.
constexpr int MaxHashMB = Is64Bit ? 131072 : 2048;
constexpr int MaxHashMB = Is64Bit ? 33554432 : 2048;
o["Debug Log File"] << Option("", on_logger);
o["Contempt"] << Option(24, -100, 100);
@@ -68,18 +67,20 @@ void init(OptionsMap& o) {
o["Ponder"] << Option(false);
o["MultiPV"] << Option(1, 1, 500);
o["Skill Level"] << Option(20, 0, 20);
o["Move Overhead"] << Option(30, 0, 5000);
o["Minimum Thinking Time"] << Option(20, 0, 5000);
o["Slow Mover"] << Option(84, 10, 1000);
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);
}
+5 -5
View File
@@ -20,7 +20,7 @@ case $1 in
--valgrind-thread)
echo "valgrind-thread testing started"
prefix=''
exeprefix='valgrind --error-exitcode=42'
exeprefix='valgrind --fair-sched=try --error-exitcode=42'
postfix='1>/dev/null'
threads="2"
;;
@@ -70,7 +70,7 @@ for args in "eval" \
"go depth 10" \
"go movetime 1000" \
"go wtime 8000 btime 8000 winc 500 binc 500" \
"bench 128 $threads 10 default depth"
"bench 128 $threads 8 default depth"
do
echo "$prefix $exeprefix ./stockfish $args $postfix"
@@ -80,7 +80,7 @@ done
# more general testing, following an uci protocol exchange
cat << EOF > game.exp
set timeout 10
set timeout 240
spawn $exeprefix ./stockfish
send "uci\n"
@@ -98,7 +98,7 @@ cat << EOF > game.exp
expect "bestmove"
send "position fen 5rk1/1K4p1/8/8/3B4/8/8/8 b - - 0 1\n"
send "go depth 30\n"
send "go depth 20\n"
expect "bestmove"
send "quit\n"
@@ -121,7 +121,7 @@ cat << EOF > syzygy.exp
send "uci\n"
send "setoption name SyzygyPath value ../tests/syzygy/\n"
expect "info string Found 35 tablebases" {} timeout {exit 1}
send "bench 128 1 10 default depth\n"
send "bench 128 1 8 default depth\n"
send "quit\n"
expect eof