From 319af5cf0a77d1057a69cef0cf8885d06475dece Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Thu, 14 Apr 2022 23:00:14 +0200 Subject: [PATCH 01/84] Update CPU contributors closes https://github.com/official-stockfish/Stockfish/pull/3979 No functional change --- Top CPU Contributors.txt | 121 ++++++++++++++++++++------------------- 1 file changed, 63 insertions(+), 58 deletions(-) diff --git a/Top CPU Contributors.txt b/Top CPU Contributors.txt index 4bc96cde..76aa01e9 100644 --- a/Top CPU Contributors.txt +++ b/Top CPU Contributors.txt @@ -1,59 +1,59 @@ -Contributors to Fishtest with >10,000 CPU hours, as of 2022-02-05. +Contributors to Fishtest with >10,000 CPU hours, as of 2022-04-14. Thank you! Username CPU Hours Games played ------------------------------------------------------------------ -noobpwnftw 30730952 2158431735 -mlang 2729669 187335452 -technologov 1696847 74478658 -dew 1635640 97483012 -grandphish2 1062754 64955639 +noobpwnftw 31714850 2267266129 +mlang 2954099 198421098 +technologov 2324150 102449398 +dew 1670874 99276012 +grandphish2 1134273 68070459 +okrout 901194 77738874 +TueRens 821388 50207666 tvijlbrief 795993 51894442 -okrout 773704 63465204 -TueRens 766198 47770388 +pemo 744463 32486677 +JojoM 724378 43660674 mibere 703840 46867607 -JojoM 703005 42689868 -pemo 634102 29868807 linrock 626939 17408017 -gvreuls 517442 33605006 -cw 503905 33850487 -fastgm 482847 29004732 +gvreuls 534079 34352532 +cw 507221 34006775 +fastgm 489749 29344518 crunchy 427035 27344275 -CSU_Dynasty 415864 28116776 -ctoks 403102 26737127 -oz 357710 26490208 -bcross 331095 23165889 +CSU_Dynasty 424643 28525220 +ctoks 415771 27364603 +oz 369200 27017658 +bcross 342642 23671289 Fisherman 327231 21829379 -velislav 321708 20729264 -leszek 303654 19063973 -Dantist 251015 15843226 -mgrabiak 231973 15162494 +velislav 325670 20911076 +leszek 321295 19874113 +Dantist 274747 16910258 +mgrabiak 237604 15418700 +robal 217959 13840386 glinscott 217799 13780820 -robal 213960 13665726 nordlandia 211692 13484886 -drabel 200914 13755384 +drabel 201967 13798360 bking_US 198894 11876016 -mhoram 180229 11610075 +mhoram 194862 12261809 Thanar 179852 12365359 vdv 175544 9904472 spams 157128 10319326 +rpngn 154081 9652139 marrco 150300 9402229 sqrt2 147963 9724586 -vdbergh 137429 8955089 +vdbergh 137430 8955097 CoffeeOne 137100 5024116 malala 136182 8002293 xoto 133759 9159372 -rpngn 131285 8657757 -davar 122661 7996937 +davar 125240 8117121 dsmith 122059 7570238 amicic 119659 7937885 Data 113305 8220352 BrunoBanani 112960 7436849 CypressChess 108321 7759588 +DesolatedDodo 106811 6776980 MaZePallas 102823 6633619 sterni1971 100532 5880772 sunu 100167 7040199 -DesolatedDodo 99038 6414626 ElbertoOne 99028 7023771 skiminki 98123 6478402 brabos 92118 6186135 @@ -61,39 +61,39 @@ cuistot 90358 5351004 psk 89957 5984901 racerschmacer 85712 6119648 Vizvezdenec 83761 5344740 +zeryl 83680 5250995 sschnee 83003 4840890 0x3C33 82614 5271253 BRAVONE 81239 5054681 nssy 76497 5259388 teddybaer 75125 5407666 +jromang 74796 5175825 Pking_cda 73776 5293873 -zeryl 73335 4774257 -jromang 72192 5057715 +Calis007 72477 4088576 solarlight 70517 5028306 dv8silencer 70287 3883992 Bobo1239 68515 4652287 manap 66273 4121774 +yurikvelo 65716 4457300 tinker 64333 4268790 -yurikvelo 63371 4335060 +Wolfgang 62644 3817410 qurashee 61208 3429862 robnjr 57262 4053117 -Wolfgang 57014 3561352 Freja 56938 3733019 ttruscott 56010 3680085 rkl 55132 4164467 renouve 53811 3501516 +megaman7de 52434 3243016 +MaxKlaxxMiner 51977 3153032 finfish 51360 3370515 eva42 51272 3599691 -Calis007 51182 3131552 eastorwest 51058 3451555 rap 49985 3219146 pb00067 49727 3298270 -Spprtr 48260 3141959 +Spprtr 48920 3161711 bigpen0r 47667 3336927 ronaldjerum 47654 3240695 -MaxKlaxxMiner 47584 2972142 biffhero 46564 3111352 -megaman7de 45992 2952006 Fifis 45843 3088497 VoyagerOne 45476 3452465 speedycpu 43842 3003273 @@ -102,25 +102,27 @@ Antihistamine 41788 2761312 mhunt 41735 2691355 homyur 39893 2850481 gri 39871 2515779 +armo9494 39064 2832326 oryx 38867 2976992 SC 37299 2731694 Garf 37213 2986270 +tolkki963 37059 2154330 csnodgrass 36207 2688994 jmdana 36157 2210661 strelock 34716 2074055 +DMBK 34010 2482916 EthanOConnor 33370 2090311 slakovv 32915 2021889 -armo9494 32129 2551682 -tolkki963 32114 1932256 +gopeto 30993 2028106 manapbk 30987 1810399 -DMBK 30675 2383552 Prcuvu 30377 2170122 anst 30301 2190091 jkiiski 30136 1904470 -gopeto 29886 1979118 hyperbolic.tom 29840 2017394 chuckstablers 29659 2093438 Pyafue 29650 1902349 +ncfish1 29105 1704011 +belzedar94 27935 1789106 OuaisBla 27636 1578800 chriswk 26902 1868317 achambord 26582 1767323 @@ -129,15 +131,14 @@ yorkman 26193 1992080 SFTUser 25182 1675689 nabildanial 24942 1519409 Sharaf_DG 24765 1786697 -ncfish1 24411 1520927 rodneyc 24275 1410450 agg177 23890 1395014 -belzedar94 23707 1593860 JanErik 23408 1703875 Isidor 23388 1680691 Norabor 23339 1602636 -Ente 23093 1642458 +Ente 23270 1651432 cisco2015 22897 1762669 +MarcusTullius 22688 1274821 Zirie 22542 1472937 team-oh 22272 1636708 MazeOfGalious 21978 1629593 @@ -146,17 +147,22 @@ ianh2105 21725 1632562 xor12 21628 1680365 dex 21612 1467203 nesoneg 21494 1463031 +Roady 21323 1433822 sphinx 21211 1384728 +user213718 21196 1397710 +spcc 21065 1311338 jjoshua2 21001 1423089 horst.prack 20878 1465656 -user213718 20783 1379584 0xB00B1ES 20590 1208666 j3corre 20405 941444 +kdave 20364 1389254 Adrian.Schmidt123 20316 1281436 +Ulysses 20217 1351500 +markkulix 19976 1115258 wei 19973 1745989 -Roady 19848 1335928 rstoesser 19569 1293588 eudhan 19274 1283717 +fishtester 18995 1238686 vulcan 18871 1729392 jundery 18445 1115855 iisiraider 18247 1101015 @@ -164,21 +170,19 @@ ville 17883 1384026 chris 17698 1487385 purplefishies 17595 1092533 dju 17353 978595 -kdave 17183 1242754 +Wencey 17125 805964 DragonLord 17014 1162790 thirdlife 16996 447356 -spcc 16932 1130940 -fishtester 16644 1123000 -Ulysses 16490 1184400 IgorLeMasson 16064 1147232 ako027ako 15671 1173203 +AndreasKrug 15550 1194497 Nikolay.IT 15154 1068349 Andrew Grant 15114 895539 +scuzzi 14928 953313 OssumOpossum 14857 1007129 Karby 14808 867120 -AndreasKrug 14608 1152093 +jsys14 14652 855642 enedene 14476 905279 -jsys14 14340 844792 bpfliegel 14298 884523 mpx86 14019 759568 jpulman 13982 870599 @@ -188,8 +192,8 @@ Nesa92 13786 1114691 mbeier 13650 1044928 Hjax 13535 915487 Dark_wizzie 13422 1007152 +Jopo12321 13367 678852 Rudolphous 13244 883140 -MarcusTullius 13221 843169 Machariel 13010 863104 mabichito 12903 749391 thijsk 12886 722107 @@ -197,34 +201,35 @@ AdrianSA 12860 804972 infinigon 12807 937332 Flopzee 12698 894821 fatmurphy 12547 853210 -scuzzi 12511 845761 SapphireBrand 12416 969604 modolief 12386 896470 Farseer 12249 694108 pgontarz 12151 848794 +pirt 12008 923149 stocky 11954 699440 mschmidt 11941 803401 dbernier 11609 818636 Maxim 11543 836024 -pirt 11516 894513 infinity 11470 727027 aga 11409 695071 torbjo 11395 729145 Thomas A. Anderson 11372 732094 savage84 11358 670860 -markkulix 11331 739098 -FormazChar 11308 847735 +FormazChar 11349 850327 d64 11263 789184 MooTheCow 11237 720174 snicolet 11106 869170 ali-al-zhrani 11098 768494 whelanh 11067 235676 +Jackfish 10978 720078 +deflectooor 10886 520116 basepi 10637 744851 Cubox 10621 826448 michaelrpg 10509 739239 OIVAS7572 10420 995586 dzjp 10343 732529 -Garruk 10332 703905 +Garruk 10334 704065 ols 10259 570669 lbraesch 10252 647825 -Jackfish 10098 682338 +qoo_charly_cai 10212 620407 +Naven94 10069 503192 From c3b67faf983ac918f313d019a7427d99901fcdb0 Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Fri, 15 Apr 2022 17:23:51 +0200 Subject: [PATCH 02/84] Update WDL model for current SF This updates the WDL model based on the LTC statistics for the last month (8M games). for old results see: https://github.com/official-stockfish/Stockfish/pull/3582 https://github.com/official-stockfish/Stockfish/pull/2778 the model changed a bit from the past, some images to follow in the PR closes https://github.com/official-stockfish/Stockfish/pull/3981 No functional change. --- src/uci.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/uci.cpp b/src/uci.cpp index 741241b3..7b30cc04 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -207,8 +207,8 @@ namespace { // Coefficients of a 3rd order polynomial fit based on fishtest data // for two parameters needed to transform eval to the argument of a // logistic function. - double as[] = {-3.68389304, 30.07065921, -60.52878723, 149.53378557}; - double bs[] = {-2.0181857, 15.85685038, -29.83452023, 47.59078827}; + double as[] = {-1.17202460e-01, 5.94729104e-01, 1.12065546e+01, 1.22606222e+02}; + double bs[] = {-1.79066759, 11.30759193, -17.43677612, 36.47147479}; 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]; From c25d4c4887dbc23395afef59e24a520c5d12ab52 Mon Sep 17 00:00:00 2001 From: FauziAkram Date: Tue, 12 Apr 2022 20:45:25 +0300 Subject: [PATCH 03/84] Tuning classical and NNUE scaling terms changes to parameters in both classical and NNUE scaling, following up from an earlier successful #3958 passed STC: LLR: 2.95 (-2.94,2.94) <0.00,2.50> Total: 23936 W: 6490 L: 6234 D: 11212 Ptnml(0-2): 107, 2610, 6306, 2810, 135 https://tests.stockfishchess.org/tests/view/625820aa33c40bb9d964e6ae passed LTC: LLR: 2.94 (-2.94,2.94) <0.50,3.00> Total: 50376 W: 13629 L: 13327 D: 23420 Ptnml(0-2): 20, 4979, 14920, 5217, 52 https://tests.stockfishchess.org/tests/view/62584592c1d7f5008a33a4d1 closes https://github.com/official-stockfish/Stockfish/pull/3982 Bench: 6964954 --- src/evaluate.cpp | 10 +++++----- src/pawns.cpp | 38 +++++++++++++++++++------------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index d9180f2b..8bb42ce1 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -198,12 +198,12 @@ namespace { constexpr Value SpaceThreshold = Value(11551); // KingAttackWeights[PieceType] contains king attack weights by piece type - constexpr int KingAttackWeights[PIECE_TYPE_NB] = { 0, 0, 81, 52, 44, 10 }; + constexpr int KingAttackWeights[PIECE_TYPE_NB] = { 0, 0, 76, 46, 45, 14 }; // SafeCheck[PieceType][single/multiple] contains safe check bonus by piece type, // higher if multiple safe checks are possible for that piece type. constexpr int SafeCheck[][2] = { - {}, {}, {803, 1292}, {639, 974}, {1087, 1878}, {759, 1132} + {}, {}, {805, 1292}, {650, 984}, {1071, 1886}, {730, 1128} }; #define S(mg, eg) make_score(mg, eg) @@ -1089,7 +1089,7 @@ Value Eval::evaluate(const Position& pos) { // but we switch to NNUE during long shuffling or with high material on the board. if ( !useNNUE || ((pos.this_thread()->depth > 9 || pos.count() > 7) && - abs(eg_value(pos.psq_score())) * 5 > (856 + pos.non_pawn_material() / 64) * (5 + pos.rule50_count()))) + abs(eg_value(pos.psq_score())) * 5 > (856 + pos.non_pawn_material() / 64) * (10 + pos.rule50_count()))) { v = Evaluation(pos).value(); // classical useClassical = abs(v) >= 297; @@ -1099,7 +1099,7 @@ Value Eval::evaluate(const Position& pos) { if (useNNUE && !useClassical) { Value nnue = NNUE::evaluate(pos, true); // NNUE - int scale = 1036 + 20 * pos.non_pawn_material() / 1024; + int scale = 1036 + 22 * pos.non_pawn_material() / 1024; Color stm = pos.side_to_move(); Value optimism = pos.this_thread()->optimism[stm]; Value psq = (stm == WHITE ? 1 : -1) * eg_value(pos.psq_score()); @@ -1113,7 +1113,7 @@ Value Eval::evaluate(const Position& pos) { } // Damp down the evaluation linearly when shuffling - v = v * (207 - pos.rule50_count()) / 207; + v = v * (195 - pos.rule50_count()) / 211; // Guarantee evaluation does not hit the tablebase range v = std::clamp(v, VALUE_TB_LOSS_IN_MAX_PLY + 1, VALUE_TB_WIN_IN_MAX_PLY - 1); diff --git a/src/pawns.cpp b/src/pawns.cpp index 6e509133..fdcfa022 100644 --- a/src/pawns.cpp +++ b/src/pawns.cpp @@ -32,30 +32,30 @@ namespace { #define S(mg, eg) make_score(mg, eg) // Pawn penalties - constexpr Score Backward = S( 9, 22); - constexpr Score Doubled = S(13, 51); - constexpr Score DoubledEarly = S(20, 7); - constexpr Score Isolated = S( 3, 15); - constexpr Score WeakLever = S( 4, 58); - constexpr Score WeakUnopposed = S(13, 24); + constexpr Score Backward = S( 6, 19); + constexpr Score Doubled = S(11, 51); + constexpr Score DoubledEarly = S(17, 7); + constexpr Score Isolated = S( 1, 20); + constexpr Score WeakLever = S( 2, 57); + constexpr Score WeakUnopposed = S(15, 18); // Bonus for blocked pawns at 5th or 6th rank - constexpr Score BlockedPawn[2] = { S(-17, -6), S(-9, 2) }; + constexpr Score BlockedPawn[2] = { S(-19, -8), S(-7, 3) }; 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) + S(0, 0), S(0, 0), S(64, 75), S(-3, 14), S(-12, 19), S(-7, 4), S(-10, 5) }; // Connected pawn bonus - constexpr int Connected[RANK_NB] = { 0, 5, 7, 11, 23, 48, 87 }; + constexpr int Connected[RANK_NB] = { 0, 3, 7, 7, 15, 54, 86 }; // Strength of pawn shelter for our king by [distance from edge][rank]. // RANK_1 = 0 is used for files where we have no pawn, or pawn is behind our king. constexpr Value ShelterStrength[int(FILE_NB) / 2][RANK_NB] = { - { V( -5), V( 82), V( 92), V( 54), V( 36), V( 22), V( 28) }, - { V(-44), V( 63), V( 33), V(-50), V(-30), V(-12), V( -62) }, - { V(-11), V( 77), V( 22), V( -6), V( 31), V( 8), V( -45) }, - { V(-39), V(-12), V(-29), V(-50), V(-43), V(-68), V(-164) } + { V(-2), V(85), V(95), V(53), V(39), V(23), V(25) }, + { V(-55), V(64), V(32), V(-55), V(-30), V(-11), V(-61) }, + { V(-11), V(75), V(19), V(-6), V(26), V(9), V(-47) }, + { V(-41), V(-11), V(-27), V(-58), V(-42), V(-66), V(-163) } }; // Danger of enemy pawns moving toward our king by [distance from edge][rank]. @@ -63,17 +63,17 @@ 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( 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) } + { V(94), V(-280), V(-170), V(90), V(59), V(47), V(53) }, + { V(43), V(-17), V(128), V(39), V(26), V(-17), V(15) }, + { V(-9), V(62), V(170), V(34), V(-5), V(-20), V(-11) }, + { V(-27), V(-19), V(106), V(10), V(2), V(-13), V(-24) } }; // 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) }}; + constexpr Score KingOnFile[2][2] = {{ S(-18,11), S(-6,-3) }, + { S( 0, 0), S( 5,-4) }}; #undef S #undef V From df2f7e75276cc93a8cb8c70057903ab0edbd92bd Mon Sep 17 00:00:00 2001 From: KJE-98 <> Date: Thu, 14 Apr 2022 22:09:50 -0400 Subject: [PATCH 04/84] Decrease LMR at PV nodes with low depth. This patch lessens the Late Move Reduction at PV nodes with low depth. Previously the affect of depth on LMR was independant of nodeType. The idea behind this patch is that at PV nodes, LMR at low depth is will miss out on potential alpha-raising moves. Passed STC: https://tests.stockfishchess.org/tests/view/625aa867d3367522c4b8965c LLR: 2.93 (-2.94,2.94) <0.00,2.50> Total: 19360 W: 5252 L: 5006 D: 9102 Ptnml(0-2): 79, 2113, 5069, 2321, 98 Passed LTC: https://tests.stockfishchess.org/tests/view/625ae844d3367522c4b8a009 LLR: 2.94 (-2.94,2.94) <0.50,3.00> Total: 39264 W: 10636 L: 10357 D: 18271 Ptnml(0-2): 18, 3928, 11473, 4183, 30 closes https://github.com/official-stockfish/Stockfish/pull/3985 bench: 8129754 --- AUTHORS | 1 + src/search.cpp | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/AUTHORS b/AUTHORS index 34b95ba5..edf189d8 100644 --- a/AUTHORS +++ b/AUTHORS @@ -104,6 +104,7 @@ jundery Justin Blanchard (UncombedCoconut) Kelly Wilson Ken Takusagawa +Kian E (KJE-98) kinderchocolate Kiran Panditrao (Krgp) Kojirion diff --git a/src/search.cpp b/src/search.cpp index fa73dce5..49d7c5c9 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1173,6 +1173,10 @@ moves_loop: // When in check, search starts here if (PvNode && !ss->inCheck && abs(ss->staticEval - bestValue) > 250) r--; + // Increase depth based reduction if PvNode + if (PvNode) + r -= 15 / ( 3 + depth ); + ss->statScore = thisThread->mainHistory[us][from_to(move)] + (*contHist[0])[movedPiece][to_sq(move)] + (*contHist[1])[movedPiece][to_sq(move)] From e6e324eb28fd49c1fc44b3b65784f85a773ec61c Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Mon, 18 Apr 2022 10:17:57 +0200 Subject: [PATCH 05/84] Stockfish 15 Official release version of Stockfish 15 Bench: 8129754 --- A new major release of Stockfish is now available at https://stockfishchess.org Stockfish 15 continues to push the boundaries of chess, providing unrivalled analysis and playing strength. In our testing, Stockfish 15 is ahead of Stockfish 14 by 36 Elo points and wins nine times more game pairs than it loses[1]. Improvements to the engine have made it possible for Stockfish to end up victorious in tournaments at all sorts of time controls ranging from bullet to classical and even at Fischer random chess[2]. At CCC, Stockfish won all of the latest tournaments: CCC 16 Bullet, Blitz and Rapid, CCC 960 championship, and the CCC 17 Rapid. At TCEC, Stockfish won the Season 21, Cup 9, FRC 4 and in the current Season 22 superfinal, at the time of writing, has won 16 game pairs and not yet lost a single one. This progress is the result of a dedicated team of developers that comes up with new ideas and improvements. For Stockfish 15, we tested nearly 13000 different changes and retained the best 200. These include the fourth generation of our NNUE network architecture, as well as various search improvements. To perform these tests, contributors provide CPU time for testing, and in the last year, they have collectively played roughly a billion chess games. In the last few years, our distributed testing framework, Fishtest, has been operated superbly and has been developed and improved extensively. This work by Pasquale Pigazzini, Tom Vijlbrief, Michel Van den Bergh, and various other developers[3] is an essential part of the success of the Stockfish project. Indeed, the Stockfish project builds on a thriving community of enthusiasts to offer a free and open-source chess engine that is robust, widely available, and very strong. We invite our chess fans to join the Fishtest testing framework and programmers to contribute to the project[4]. The Stockfish team [1] https://tests.stockfishchess.org/tests/view/625d156dff677a888877d1be [2] https://en.wikipedia.org/wiki/Stockfish_(chess)#Competition_results [3] https://github.com/glinscott/fishtest/blob/master/AUTHORS [4] https://stockfishchess.org/get-involved/ --- src/misc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/misc.cpp b/src/misc.cpp index 41c59b3f..178465c1 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -69,7 +69,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 = ""; +const string Version = "15"; /// 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 From c4db7fd1f941dbd3875e9faaaeb964755d039633 Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Mon, 18 Apr 2022 23:05:24 +0200 Subject: [PATCH 06/84] Restore development version No functional change. --- src/misc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/misc.cpp b/src/misc.cpp index 178465c1..41c59b3f 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -69,7 +69,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 = "15"; +const string Version = ""; /// 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 From 6e0680efa0d0653686b8eb8753dc49718b95cb2b Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Mon, 18 Apr 2022 07:34:03 +0200 Subject: [PATCH 07/84] Update default net to nn-d0b74ce1e5eb.nnue train a net using training data with a heavier weight on positions having 16 pieces on the board. More specifically, with a relative weight of `i * (32-i)/(16 * 16)+1` (where i is the number of pieces on the board). This is done with the trainer branch https://github.com/glinscott/nnue-pytorch/pull/173 The command used is: ``` python train.py $datafile $datafile $restarttype $restartfile --gpus 1 --threads 4 --num-workers 12 --random-fen-skipping=3 --batch-size 16384 --progress_bar_refresh_rate 300 --smart-fen-skipping --features=HalfKAv2_hm^ --lambda=1.00 --max_epochs=$epochs --seed $RANDOM --default_root_dir exp/run_$i ``` The datafile is T60T70wIsRightFarseerT60T74T75T76.binpack, the restart is from the master net. passed STC: LLR: 2.94 (-2.94,2.94) <0.00,2.50> Total: 22728 W: 6197 L: 5945 D: 10586 Ptnml(0-2): 105, 2453, 6001, 2695, 110 https://tests.stockfishchess.org/tests/view/625cf944ff677a888877cd90 passed LTC: LLR: 2.94 (-2.94,2.94) <0.50,3.00> Total: 35664 W: 9535 L: 9264 D: 16865 Ptnml(0-2): 30, 3524, 10455, 3791, 32 https://tests.stockfishchess.org/tests/view/625d3c32ff677a888877d7ca closes https://github.com/official-stockfish/Stockfish/pull/3989 Bench: 7269563 --- src/evaluate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evaluate.h b/src/evaluate.h index 1934c9bd..e857b799 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -39,7 +39,7 @@ namespace Eval { // The default net name MUST follow the format nn-[SHA256 first 12 digits].nnue // for the build process (profile-build and fishtest) to work. Do not change the // name of the macro, as it is used in the Makefile. - #define EvalFileDefaultName "nn-6877cd24400e.nnue" + #define EvalFileDefaultName "nn-d0b74ce1e5eb.nnue" namespace NNUE { From e41f727f0f7041b43997f04c031353be5087856b Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Thu, 21 Apr 2022 15:28:23 +0300 Subject: [PATCH 08/84] Simplify away best move count logic the only place where it was used it was true with >99% probability so it seemed to not be doing much any more. Passed STC: https://tests.stockfishchess.org/tests/view/625f4778d00da81c22dd4c93 LLR: 2.95 (-2.94,2.94) <-2.25,0.25> Total: 85152 W: 22487 L: 22406 D: 40259 Ptnml(0-2): 313, 9035, 23818, 9078, 332 Passed LTC: https://tests.stockfishchess.org/tests/view/625ff1f1b03f22647441a215 LLR: 2.94 (-2.94,2.94) <-2.25,0.25> Total: 66776 W: 17768 L: 17673 D: 31335 Ptnml(0-2): 46, 6200, 20792, 6313, 37 close https://github.com/official-stockfish/Stockfish/pull/3993 bench 7280798 --- src/search.cpp | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 49d7c5c9..167209a3 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -556,7 +556,7 @@ namespace { bool givesCheck, improving, didLMR, priorCapture; bool capture, doFullDepthSearch, moveCountPruning, ttCapture; Piece movedPiece; - int moveCount, captureCount, quietCount, bestMoveCount, improvement, complexity; + int moveCount, captureCount, quietCount, improvement, complexity; // Step 1. Initialize node Thread* thisThread = pos.this_thread(); @@ -564,7 +564,7 @@ namespace { ss->inCheck = pos.checkers(); priorCapture = pos.captured_piece(); Color us = pos.side_to_move(); - moveCount = bestMoveCount = captureCount = quietCount = ss->moveCount = 0; + moveCount = captureCount = quietCount = ss->moveCount = 0; bestValue = -VALUE_INFINITE; maxValue = VALUE_INFINITE; @@ -1145,11 +1145,6 @@ moves_loop: // When in check, search starts here { Depth r = reduction(improving, depth, moveCount, delta, thisThread->rootDelta); - // Decrease reduction at some PvNodes (~2 Elo) - if ( PvNode - && bestMoveCount <= 3) - r--; - // Decrease reduction if position is or has been on the PV // and node is not likely to fail low. (~3 Elo) if ( ss->ttPv @@ -1173,9 +1168,9 @@ moves_loop: // When in check, search starts here if (PvNode && !ss->inCheck && abs(ss->staticEval - bestValue) > 250) r--; - // Increase depth based reduction if PvNode + // Decrease reduction for PvNodes based on depth if (PvNode) - r -= 15 / ( 3 + depth ); + r -= 1 + 15 / ( 3 + depth ); ss->statScore = thisThread->mainHistory[us][from_to(move)] + (*contHist[0])[movedPiece][to_sq(move)] @@ -1297,10 +1292,7 @@ moves_loop: // When in check, search starts here update_pv(ss->pv, move, (ss+1)->pv); if (PvNode && value < beta) // Update alpha! Always alpha < beta - { alpha = value; - bestMoveCount++; - } else { assert(value >= beta); // Fail high From e1f12aa4e61a8bbb772918c405137acdd85e3eec Mon Sep 17 00:00:00 2001 From: candirufish <38038147+candirufish@users.noreply.github.com> Date: Fri, 22 Apr 2022 08:03:50 +0200 Subject: [PATCH 09/84] Negative extension for ttMove that is less than alpha and value in the context of singular extensions Passed STC: https://tests.stockfishchess.org/tests/view/626047e8b03f22647441ade0 LLR: 2.97 (-2.94,2.94) <0.00,2.50> Total: 50296 W: 13410 L: 13108 D: 23778 Ptnml(0-2): 196, 5548, 13370, 5826, 208 Passed LTC: https://tests.stockfishchess.org/tests/view/6260a513b03f22647441b970 LLR: 2.96 (-2.94,2.94) <0.50,3.00> Total: 83896 W: 22433 L: 22054 D: 39409 Ptnml(0-2): 49, 8273, 24938, 8626, 62 closes https://github.com/official-stockfish/Stockfish/pull/3995 bench: 7729968 --- src/search.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/search.cpp b/src/search.cpp index 167209a3..ff6bf335 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1098,6 +1098,10 @@ moves_loop: // When in check, search starts here // If the eval of ttMove is greater than beta, we reduce it (negative extension) else if (ttValue >= beta) extension = -2; + + // If the eval of ttMove is less than alpha and value, we reduce it (negative extension) + else if (ttValue <= alpha && ttValue <= value) + extension = -1; } // Check extensions (~1 Elo) From 285a79eaa0b89b342b5e4f217682e083a6fd33f5 Mon Sep 17 00:00:00 2001 From: Stefan Geschwentner Date: Wed, 27 Apr 2022 13:09:53 +0200 Subject: [PATCH 10/84] Simplify time management. Replace the best move instability adjustment factor by a simpler version which doesn't have a dependency on the iteration depth. STC: LLR: 2.94 (-2.94,2.94) <-2.25,0.25> Total: 30800 W: 8232 L: 8073 D: 14495 Ptnml(0-2): 101, 3309, 8444, 3422, 124 https://tests.stockfishchess.org/tests/view/6266c77bc5b924ba22908d30 LTC: LLR: 2.95 (-2.94,2.94) <-2.25,0.25> Total: 61664 W: 16375 L: 16272 D: 29017 Ptnml(0-2): 40, 5869, 18897, 6000, 26 https://tests.stockfishchess.org/tests/view/6266fc39b3d1812808915f23 closes https://github.com/official-stockfish/Stockfish/pull/3999 Bench: 7729968 --- src/search.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index ff6bf335..cd38e629 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -466,8 +466,7 @@ void Thread::search() { // If the bestMove is stable over several iterations, reduce time accordingly timeReduction = lastBestMoveDepth + 10 < completedDepth ? 1.63 : 0.73; double reduction = (1.56 + mainThread->previousTimeReduction) / (2.20 * timeReduction); - double bestMoveInstability = 1.073 + std::max(1.0, 2.25 - 9.9 / rootDepth) - * totBestMoveChanges / Threads.size(); + double bestMoveInstability = 1 + 1.7 * totBestMoveChanges / Threads.size(); int complexity = mainThread->complexityAverage.value(); double complexPosition = std::clamp(1.0 + (complexity - 326) / 1618.1, 0.5, 1.5); From a32d2086bc227f1d76bd04808e10c8e7bd230fe9 Mon Sep 17 00:00:00 2001 From: candirufish <38038147+candirufish@users.noreply.github.com> Date: Tue, 3 May 2022 12:35:21 +0200 Subject: [PATCH 11/84] Use fail high count for LMR Increase reduction if next ply has a lot of fail high else reset count to 0 Passed STC: https://tests.stockfishchess.org/tests/view/626ea8299116b52aa83b71f6 LLR: 2.94 (-2.94,2.94) <0.00,2.50> Total: 144288 W: 38377 L: 37902 D: 68009 Ptnml(0-2): 565, 16298, 38054, 16551, 676 Passed LTC: https://tests.stockfishchess.org/tests/view/626fa0fb79f761bab2e382f0 LLR: 2.98 (-2.94,2.94) <0.50,3.00> Total: 74872 W: 20050 L: 19686 D: 35136 Ptnml(0-2): 51, 7541, 21893, 7895, 56 closes https://github.com/official-stockfish/Stockfish/pull/4006 bench: 7084802 --- src/search.cpp | 9 +++++++++ src/search.h | 1 + 2 files changed, 10 insertions(+) diff --git a/src/search.cpp b/src/search.cpp index cd38e629..70b852f3 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -603,6 +603,7 @@ namespace { (ss+1)->ttPv = false; (ss+1)->excludedMove = bestMove = MOVE_NONE; (ss+2)->killers[0] = (ss+2)->killers[1] = MOVE_NONE; + (ss+2)->cutoffCnt = 0; ss->doubleExtensions = (ss-1)->doubleExtensions; ss->depth = depth; Square prevSq = to_sq((ss-1)->currentMove); @@ -1175,6 +1176,10 @@ moves_loop: // When in check, search starts here if (PvNode) r -= 1 + 15 / ( 3 + depth ); + // Increase reduction if next ply has a lot of fail high else reset count to 0 + if ((ss+1)->cutoffCnt > 3 && !PvNode) + r++; + ss->statScore = thisThread->mainHistory[us][from_to(move)] + (*contHist[0])[movedPiece][to_sq(move)] + (*contHist[1])[movedPiece][to_sq(move)] @@ -1298,11 +1303,15 @@ moves_loop: // When in check, search starts here alpha = value; else { + ss->cutoffCnt++; assert(value >= beta); // Fail high break; } } } + else + ss->cutoffCnt = 0; + // If the move is worse than some previously searched move, remember it to update its stats later if (move != bestMove) diff --git a/src/search.h b/src/search.h index 806295a1..8bb51832 100644 --- a/src/search.h +++ b/src/search.h @@ -54,6 +54,7 @@ struct Stack { bool ttPv; bool ttHit; int doubleExtensions; + int cutoffCnt; }; From 9eb7b607cf69f6b613c89ae767b7f934f26e59e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ste=CC=81phane=20Nicolet?= Date: Wed, 4 May 2022 07:39:23 +0200 Subject: [PATCH 12/84] Reduce depth after score improvement at PV nodes STC: LLR: 2.95 (-2.94,2.94) <0.00,2.50> Total: 73760 W: 19590 L: 19244 D: 34926 Ptnml(0-2): 285, 8352, 19292, 8634, 317 https://tests.stockfishchess.org/tests/view/626eb2dc9116b52aa83b73da LTC: LLR: 2.93 (-2.94,2.94) <0.50,3.00> Total: 114400 W: 30561 L: 30111 D: 53728 Ptnml(0-2): 68, 11432, 33785, 11812, 103 https://tests.stockfishchess.org/tests/view/626f730859e9c431e0b10b21 closes https://github.com/official-stockfish/Stockfish/pull/4008 bench: 6174823 --- src/search.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/search.cpp b/src/search.cpp index 70b852f3..c12b60e6 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1300,7 +1300,18 @@ moves_loop: // When in check, search starts here update_pv(ss->pv, move, (ss+1)->pv); if (PvNode && value < beta) // Update alpha! Always alpha < beta + { alpha = value; + + // Reduce other moves if we have found at least one score improvement + if ( depth > 2 + && depth < 7 + && beta < VALUE_KNOWN_WIN + && alpha > -VALUE_KNOWN_WIN) + depth -= 1; + + assert(depth > 0); + } else { ss->cutoffCnt++; From c079acc26f93acc2eda08c7218c60559854f52f0 Mon Sep 17 00:00:00 2001 From: Tomasz Sobczyk Date: Fri, 13 May 2022 17:26:50 +0200 Subject: [PATCH 13/84] Update NNUE architecture to SFNNv5. Update network to nn-3c0aa92af1da.nnue. Architecture changes: Duplicated activation after the 1024->15 layer with squared crelu (so 15->15*2). As proposed by vondele. Trainer changes: Added bias to L1 factorization, which was previously missing (no measurable improvement but at least neutral in principle) For retraining linearly reduce lambda parameter from 1.0 at epoch 0 to 0.75 at epoch 800. reduce max_skipping_rate from 15 to 10 (compared to vondele's outstanding PR) Note: This network was trained with a ~0.8% error in quantization regarding the newly added activation function. This will be fixed in the released trainer version. Expect a trainer PR tomorrow. Note: The inference implementation cuts a corner to merge results from two activation functions. This could possibly be resolved nicer in the future. AVX2 implementation likely not necessary, but NEON is missing. First training session invocation: python3 train.py \ ../nnue-pytorch-training/data/nodes5000pv2_UHO.binpack \ ../nnue-pytorch-training/data/nodes5000pv2_UHO.binpack \ --gpus "$3," \ --threads 4 \ --num-workers 8 \ --batch-size 16384 \ --progress_bar_refresh_rate 20 \ --random-fen-skipping 3 \ --features=HalfKAv2_hm^ \ --lambda=1.0 \ --max_epochs=400 \ --default_root_dir ../nnue-pytorch-training/experiment_$1/run_$2 Second training session invocation: python3 train.py \ ../nnue-pytorch-training/data/T60T70wIsRightFarseerT60T74T75T76.binpack \ ../nnue-pytorch-training/data/T60T70wIsRightFarseerT60T74T75T76.binpack \ --gpus "$3," \ --threads 4 \ --num-workers 8 \ --batch-size 16384 \ --progress_bar_refresh_rate 20 \ --random-fen-skipping 3 \ --features=HalfKAv2_hm^ \ --start-lambda=1.0 \ --end-lambda=0.75 \ --gamma=0.995 \ --lr=4.375e-4 \ --max_epochs=800 \ --resume-from-model /data/sopel/nnue/nnue-pytorch-training/data/exp367/nn-exp367-run3-epoch399.pt \ --default_root_dir ../nnue-pytorch-training/experiment_$1/run_$2 Passed STC: LLR: 2.95 (-2.94,2.94) <0.00,2.50> Total: 27288 W: 7445 L: 7178 D: 12665 Ptnml(0-2): 159, 3002, 7054, 3271, 158 https://tests.stockfishchess.org/tests/view/627e8c001919125939623644 Passed LTC: LLR: 2.95 (-2.94,2.94) <0.50,3.00> Total: 21792 W: 5969 L: 5727 D: 10096 Ptnml(0-2): 25, 2152, 6294, 2406, 19 https://tests.stockfishchess.org/tests/view/627f2a855734b18b2e2ece47 closes https://github.com/official-stockfish/Stockfish/pull/4020 Bench: 6481017 --- src/evaluate.h | 2 +- src/nnue/layers/sqr_clipped_relu.h | 120 +++++++++++++++++++++++++++++ src/nnue/nnue_architecture.h | 9 ++- 3 files changed, 128 insertions(+), 3 deletions(-) create mode 100644 src/nnue/layers/sqr_clipped_relu.h diff --git a/src/evaluate.h b/src/evaluate.h index e857b799..f67961a9 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -39,7 +39,7 @@ namespace Eval { // The default net name MUST follow the format nn-[SHA256 first 12 digits].nnue // for the build process (profile-build and fishtest) to work. Do not change the // name of the macro, as it is used in the Makefile. - #define EvalFileDefaultName "nn-d0b74ce1e5eb.nnue" + #define EvalFileDefaultName "nn-3c0aa92af1da.nnue" namespace NNUE { diff --git a/src/nnue/layers/sqr_clipped_relu.h b/src/nnue/layers/sqr_clipped_relu.h new file mode 100644 index 00000000..b603a277 --- /dev/null +++ b/src/nnue/layers/sqr_clipped_relu.h @@ -0,0 +1,120 @@ +/* + Stockfish, a UCI chess playing engine derived from Glaurung 2.1 + Copyright (C) 2004-2022 The Stockfish developers (see AUTHORS file) + + Stockfish is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Stockfish is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// Definition of layer ClippedReLU of NNUE evaluation function + +#ifndef NNUE_LAYERS_SQR_CLIPPED_RELU_H_INCLUDED +#define NNUE_LAYERS_SQR_CLIPPED_RELU_H_INCLUDED + +#include "../nnue_common.h" + +namespace Stockfish::Eval::NNUE::Layers { + + // Clipped ReLU + template + class SqrClippedReLU { + public: + // Input/output type + using InputType = std::int32_t; + using OutputType = std::uint8_t; + + // Number of input/output dimensions + static constexpr IndexType InputDimensions = InDims; + static constexpr IndexType OutputDimensions = InputDimensions; + static constexpr IndexType PaddedOutputDimensions = + ceil_to_multiple(OutputDimensions, 32); + + using OutputBuffer = OutputType[PaddedOutputDimensions]; + + // Hash value embedded in the evaluation file + static constexpr std::uint32_t get_hash_value(std::uint32_t prevHash) { + std::uint32_t hashValue = 0x538D24C7u; + hashValue += prevHash; + return hashValue; + } + + // Read network parameters + bool read_parameters(std::istream&) { + return true; + } + + // Write network parameters + bool write_parameters(std::ostream&) const { + return true; + } + + // Forward propagation + const OutputType* propagate( + const InputType* input, OutputType* output) const { + + #if defined(USE_SSE2) + constexpr IndexType NumChunks = InputDimensions / 16; + + #ifdef USE_SSE41 + const __m128i Zero = _mm_setzero_si128(); + #else + const __m128i k0x80s = _mm_set1_epi8(-128); + #endif + + static_assert(WeightScaleBits == 6); + const auto in = reinterpret_cast(input); + const auto out = reinterpret_cast<__m128i*>(output); + for (IndexType i = 0; i < NumChunks; ++i) { + __m128i words0 = _mm_packs_epi32( + _mm_load_si128(&in[i * 4 + 0]), + _mm_load_si128(&in[i * 4 + 1])); + __m128i words1 = _mm_packs_epi32( + _mm_load_si128(&in[i * 4 + 2]), + _mm_load_si128(&in[i * 4 + 3])); + + // Not sure if + words0 = _mm_srli_epi16(_mm_mulhi_epi16(words0, words0), 3); + words1 = _mm_srli_epi16(_mm_mulhi_epi16(words1, words1), 3); + + const __m128i packedbytes = _mm_packs_epi16(words0, words1); + + _mm_store_si128(&out[i], + + #ifdef USE_SSE41 + _mm_max_epi8(packedbytes, Zero) + #else + _mm_subs_epi8(_mm_adds_epi8(packedbytes, k0x80s), k0x80s) + #endif + + ); + } + constexpr IndexType Start = NumChunks * 16; + + #else + constexpr IndexType Start = 0; + #endif + + for (IndexType i = Start; i < InputDimensions; ++i) { + output[i] = static_cast( + // realy should be /127 but we need to make it fast + // needs to be accounted for in the trainer + std::max(0ll, std::min(127ll, (((long long)input[i] * input[i]) >> (2 * WeightScaleBits)) / 128))); + } + + return output; + } + }; + +} // namespace Stockfish::Eval::NNUE::Layers + +#endif // NNUE_LAYERS_SQR_CLIPPED_RELU_H_INCLUDED diff --git a/src/nnue/nnue_architecture.h b/src/nnue/nnue_architecture.h index 4f9596ae..cac83730 100644 --- a/src/nnue/nnue_architecture.h +++ b/src/nnue/nnue_architecture.h @@ -29,6 +29,7 @@ #include "layers/affine_transform.h" #include "layers/clipped_relu.h" +#include "layers/sqr_clipped_relu.h" #include "../misc.h" @@ -48,8 +49,9 @@ struct Network static constexpr int FC_1_OUTPUTS = 32; Layers::AffineTransform fc_0; + Layers::SqrClippedReLU ac_sqr_0; Layers::ClippedReLU ac_0; - Layers::AffineTransform fc_1; + Layers::AffineTransform fc_1; Layers::ClippedReLU ac_1; Layers::AffineTransform fc_2; @@ -93,6 +95,7 @@ struct Network struct alignas(CacheLineSize) Buffer { alignas(CacheLineSize) decltype(fc_0)::OutputBuffer fc_0_out; + alignas(CacheLineSize) decltype(ac_sqr_0)::OutputType ac_sqr_0_out[ceil_to_multiple(FC_0_OUTPUTS * 2, 32)]; alignas(CacheLineSize) decltype(ac_0)::OutputBuffer ac_0_out; alignas(CacheLineSize) decltype(fc_1)::OutputBuffer fc_1_out; alignas(CacheLineSize) decltype(ac_1)::OutputBuffer ac_1_out; @@ -114,8 +117,10 @@ struct Network #endif fc_0.propagate(transformedFeatures, buffer.fc_0_out); + ac_sqr_0.propagate(buffer.fc_0_out, buffer.ac_sqr_0_out); ac_0.propagate(buffer.fc_0_out, buffer.ac_0_out); - fc_1.propagate(buffer.ac_0_out, buffer.fc_1_out); + std::memcpy(buffer.ac_sqr_0_out + FC_0_OUTPUTS, buffer.ac_0_out, FC_0_OUTPUTS * sizeof(decltype(ac_0)::OutputType)); + fc_1.propagate(buffer.ac_sqr_0_out, buffer.fc_1_out); ac_1.propagate(buffer.fc_1_out, buffer.ac_1_out); fc_2.propagate(buffer.ac_1_out, buffer.fc_2_out); From 5372f81cc81d5be3040db6f2dbfff108c460baf9 Mon Sep 17 00:00:00 2001 From: disservin <45608332+Disservin@users.noreply.github.com> Date: Sat, 14 May 2022 12:10:13 +0200 Subject: [PATCH 14/84] SE depth scaling using the previous depth This patch makes the SE depth condition more robust and allows it to scale with completed depth from a previous search. At long TC this patch is almost equivalent to https://github.com/official-stockfish/Stockfish/pull/4016 which had VLTC: https://tests.stockfishchess.org/tests/view/626abd7e8707aa698c0093a8 Elo: 2.35 +-1.5 (95%) LOS: 99.9% Total: 40000 W: 10991 L: 10720 D: 18289 Ptnml(0-2): 8, 3534, 12648, 3799, 11 nElo: 5.47 +-3.4 (95%) PairsRatio: 1.08 VLTC multicore: https://tests.stockfishchess.org/tests/view/6272a6afc8f14123163c1997 LLR: 2.94 (-2.94,2.94) <0.50,3.00> Total: 86808 W: 24165 L: 23814 D: 38829 Ptnml(0-2): 11, 7253, 28524, 7606, 10 however, it is now also gaining at LTC: LTC: https://tests.stockfishchess.org/tests/view/627e7cb523c0c72a05b651a9 LLR: 2.94 (-2.94,2.94) <0.50,3.00> Total: 27064 W: 7285 L: 7046 D: 12733 Ptnml(0-2): 8, 2446, 8390, 2675, 13 and should have nearly no influence at STC as depth 27 is rarely reached. It was noticed that initializing the threshold with MAX_PLY, had an adverse effect, possibly because the first move is sensitive to this. closes https://github.com/official-stockfish/Stockfish/pull/4021 closes https://github.com/official-stockfish/Stockfish/pull/4016 Bench: 6481017 --- AUTHORS | 1 + src/search.cpp | 5 ++++- src/thread.cpp | 3 ++- src/thread.h | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/AUTHORS b/AUTHORS index edf189d8..b435ff8f 100644 --- a/AUTHORS +++ b/AUTHORS @@ -125,6 +125,7 @@ marotear Matt Ginsberg (mattginsberg) Matthew Lai (matthewlai) Matthew Sullivan (Matt14916) +Max A. (Disservin) Maxim Molchanov (Maxim) Michael An (man) Michael Byrne (MichaelB7) diff --git a/src/search.cpp b/src/search.cpp index c12b60e6..4a41a8b0 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -238,6 +238,9 @@ void MainThread::search() { bestPreviousScore = bestThread->rootMoves[0].score; bestPreviousAverageScore = bestThread->rootMoves[0].averageScore; + for (Thread* th : Threads) + th->previousDepth = bestThread->completedDepth; + // Send again PV info if we have a new best thread if (bestThread != this) sync_cout << UCI::pv(bestThread->rootPos, bestThread->completedDepth, -VALUE_INFINITE, VALUE_INFINITE) << sync_endl; @@ -1061,7 +1064,7 @@ moves_loop: // When in check, search starts here // a reduced search on all the other moves but the ttMove and if the // result is lower than ttValue minus a margin, then we will extend the ttMove. if ( !rootNode - && depth >= 4 + 2 * (PvNode && tte->is_pv()) + && depth >= 4 - (thisThread->previousDepth > 27) + 2 * (PvNode && tte->is_pv()) && move == ttMove && !excludedMove // Avoid recursive singular search /* && ttValue != VALUE_NONE Already implicit in the next condition */ diff --git a/src/thread.cpp b/src/thread.cpp index 30177a39..08a78db5 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -60,7 +60,8 @@ void Thread::clear() { counterMoves.fill(MOVE_NONE); mainHistory.fill(0); captureHistory.fill(0); - + previousDepth = 0; + for (bool inCheck : { false, true }) for (StatsType c : { NoCaptures, Captures }) { diff --git a/src/thread.h b/src/thread.h index 8027855a..9e9cd488 100644 --- a/src/thread.h +++ b/src/thread.h @@ -69,7 +69,7 @@ public: Position rootPos; StateInfo rootState; Search::RootMoves rootMoves; - Depth rootDepth, completedDepth, depth; + Depth rootDepth, completedDepth, depth, previousDepth; Value rootDelta; CounterMoveHistory counterMoves; ButterflyHistory mainHistory; From 22b7909809c731aea691184dd7c1a2b02c5946af Mon Sep 17 00:00:00 2001 From: xoto10 Date: Sun, 15 May 2022 13:14:28 +0100 Subject: [PATCH 15/84] Tune scale and optimism. Tune scale and optimism in effort to make stockfish play more aggressively. STC @ 10+0.1 th 1: LLR: 2.94 (-2.94,2.94) <0.00,2.50> Total: 27896 W: 7506 L: 7248 D: 13142 Ptnml(0-2): 103, 3047, 7388, 3309, 101 https://tests.stockfishchess.org/tests/live_elo/627fd0cfab44257388ab1f13 LTC @ 60+0.6 th 1: LLR: 2.93 (-2.94,2.94) <0.50,3.00> Total: 65576 W: 17512 L: 17178 D: 30886 Ptnml(0-2): 37, 6397, 19587, 6729, 38 https://tests.stockfishchess.org/tests/live_elo/627ff666ab44257388ab256d closes https://github.com/official-stockfish/Stockfish/pull/4025 Bench 6407734 --- src/evaluate.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 8bb42ce1..718c7bc0 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -192,6 +192,7 @@ using namespace Trace; namespace { + // Threshold for lazy and space evaluation constexpr Value LazyThreshold1 = Value(3631); constexpr Value LazyThreshold2 = Value(2084); @@ -1099,14 +1100,14 @@ Value Eval::evaluate(const Position& pos) { if (useNNUE && !useClassical) { Value nnue = NNUE::evaluate(pos, true); // NNUE - int scale = 1036 + 22 * pos.non_pawn_material() / 1024; + int scale = 1014 + 21 * pos.non_pawn_material() / 1024; Color stm = pos.side_to_move(); Value optimism = pos.this_thread()->optimism[stm]; Value psq = (stm == WHITE ? 1 : -1) * eg_value(pos.psq_score()); int complexity = 35 * abs(nnue - psq) / 256; - optimism = optimism * (44 + complexity) / 31; - v = (nnue + optimism) * scale / 1024 - optimism; + optimism = optimism * (32 + complexity) / 32; + v = (nnue * scale + optimism * (scale - 846)) / 1024; if (pos.is_chess960()) v += fix_FRC(pos); From cc7bcd5303a645223a6cd853817d3172754243aa Mon Sep 17 00:00:00 2001 From: candirufish <38038147+candirufish@users.noreply.github.com> Date: Sat, 21 May 2022 04:20:09 +0200 Subject: [PATCH 16/84] Simplify a condition Principal variation depth late move reduction extension simplification. stc: https://tests.stockfishchess.org/tests/view/6285a1d19d18a78568e7fa24 LLR: 2.94 (-2.94,2.94) <-2.25,0.25> Total: 428536 W: 113433 L: 113851 D: 201252 Ptnml(0-2): 1671, 48606, 114090, 48272, 1629 ltc: https://tests.stockfishchess.org/tests/view/62871d20375cdc5de8cf5db3 LLR: 2.95 (-2.94,2.94) <-2.25,0.25> Total: 56792 W: 15123 L: 15011 D: 26658 Ptnml(0-2): 42, 5681, 16825, 5819, 29 closes https://github.com/official-stockfish/Stockfish/pull/4028 bench: 6501437 --- src/search.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index 4a41a8b0..d09ced9a 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1197,7 +1197,7 @@ moves_loop: // When in check, search starts here // deeper than the first move (this may lead to hidden double extensions). int deeper = r >= -1 ? 0 : moveCount <= 4 ? 2 - : PvNode && depth > 4 ? 1 + : PvNode ? 1 : cutNode && moveCount <= 8 ? 1 : 0; From f7d1491b3df28bf10faac81e340cb6a22fc5b57b Mon Sep 17 00:00:00 2001 From: Giacomo Lorenzetti Date: Fri, 1 Apr 2022 18:33:25 +0200 Subject: [PATCH 17/84] Assorted small cleanups closes https://github.com/official-stockfish/Stockfish/pull/3973 No functional change --- README.md | 3 +- src/Makefile | 48 ++++++++++++++--------------- src/evaluate.cpp | 10 +++--- src/nnue/nnue_feature_transformer.h | 18 +++++------ src/search.cpp | 6 +--- src/search.h | 1 - src/syzygy/tbprobe.cpp | 2 +- src/types.h | 2 +- 8 files changed, 42 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index 6e6e762e..f84b79d1 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ ## Overview [![Build Status](https://github.com/official-stockfish/Stockfish/actions/workflows/stockfish.yml/badge.svg)](https://github.com/official-stockfish/Stockfish/actions) -[![Build Status](https://ci.appveyor.com/api/projects/status/github/official-stockfish/Stockfish?branch=master&svg=true)](https://ci.appveyor.com/project/mcostalba/stockfish/branch/master) [Stockfish](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 @@ -21,7 +20,7 @@ avx2, neon, or similar). This distribution of Stockfish consists of the following files: - * [Readme.md](https://github.com/official-stockfish/Stockfish/blob/master/README.md), + * [README.md](https://github.com/official-stockfish/Stockfish/blob/master/README.md), the file you are currently reading. * [Copying.txt](https://github.com/official-stockfish/Stockfish/blob/master/Copying.txt), diff --git a/src/Makefile b/src/Makefile index eff8baca..cc9b4201 100644 --- a/src/Makefile +++ b/src/Makefile @@ -542,17 +542,17 @@ ifeq ($(optimize),yes) endif endif - ifeq ($(KERNEL),Darwin) - ifeq ($(comp),$(filter $(comp),clang icc)) - CXXFLAGS += -mdynamic-no-pic - endif + ifeq ($(KERNEL),Darwin) + ifeq ($(comp),$(filter $(comp),clang icc)) + CXXFLAGS += -mdynamic-no-pic + endif - ifeq ($(comp),gcc) - ifneq ($(arch),arm64) - CXXFLAGS += -mdynamic-no-pic - endif - endif - endif + ifeq ($(comp),gcc) + ifneq ($(arch),arm64) + CXXFLAGS += -mdynamic-no-pic + endif + endif + endif ifeq ($(comp),clang) CXXFLAGS += -fexperimental-new-pass-manager @@ -824,22 +824,22 @@ net: $(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; + 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 + 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: diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 718c7bc0..9061a384 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -192,7 +192,6 @@ using namespace Trace; namespace { - // Threshold for lazy and space evaluation constexpr Value LazyThreshold1 = Value(3631); constexpr Value LazyThreshold2 = Value(2084); @@ -1084,13 +1083,14 @@ make_v: Value Eval::evaluate(const Position& pos) { Value v; - bool useClassical = false; + // Deciding between classical and NNUE eval (~10 Elo): for high PSQ imbalance we use classical, + // but we switch to NNUE during long shuffling or with high material on the board. + bool useClassical = (pos.this_thread()->depth > 9 || pos.count() > 7) && + abs(eg_value(pos.psq_score())) * 5 > (856 + pos.non_pawn_material() / 64) * (10 + pos.rule50_count()); // Deciding between classical and NNUE eval (~10 Elo): for high PSQ imbalance we use classical, // but we switch to NNUE during long shuffling or with high material on the board. - if ( !useNNUE - || ((pos.this_thread()->depth > 9 || pos.count() > 7) && - abs(eg_value(pos.psq_score())) * 5 > (856 + pos.non_pawn_material() / 64) * (10 + pos.rule50_count()))) + if (!useNNUE || useClassical) { v = Evaluation(pos).value(); // classical useClassical = abs(v) >= 297; diff --git a/src/nnue/nnue_feature_transformer.h b/src/nnue/nnue_feature_transformer.h index c969ac6c..34d7292c 100644 --- a/src/nnue/nnue_feature_transformer.h +++ b/src/nnue/nnue_feature_transformer.h @@ -120,12 +120,12 @@ namespace Stockfish::Eval::NNUE { #define vec_zero() _mm_setzero_si64() #define vec_set_16(a) _mm_set1_pi16(a) inline vec_t vec_max_16(vec_t a,vec_t b){ - vec_t comparison = _mm_cmpgt_pi16(a,b); - return _mm_or_si64(_mm_and_si64(comparison, a), _mm_andnot_si64(comparison, b)); + vec_t comparison = _mm_cmpgt_pi16(a,b); + return _mm_or_si64(_mm_and_si64(comparison, a), _mm_andnot_si64(comparison, b)); } inline vec_t vec_min_16(vec_t a,vec_t b){ - vec_t comparison = _mm_cmpgt_pi16(a,b); - return _mm_or_si64(_mm_and_si64(comparison, b), _mm_andnot_si64(comparison, a)); + vec_t comparison = _mm_cmpgt_pi16(a,b); + return _mm_or_si64(_mm_and_si64(comparison, b), _mm_andnot_si64(comparison, a)); } #define vec_msb_pack_16(a,b) _mm_packs_pi16(_mm_srli_pi16(a,7),_mm_srli_pi16(b,7)) #define vec_load_psqt(a) (*(a)) @@ -150,10 +150,10 @@ namespace Stockfish::Eval::NNUE { #define vec_max_16(a,b) vmaxq_s16(a,b) #define vec_min_16(a,b) vminq_s16(a,b) inline vec_t vec_msb_pack_16(vec_t a, vec_t b){ - const int8x8_t shifta = vshrn_n_s16(a, 7); - const int8x8_t shiftb = vshrn_n_s16(b, 7); - const int8x16_t compacted = vcombine_s8(shifta,shiftb); - return *reinterpret_cast (&compacted); + const int8x8_t shifta = vshrn_n_s16(a, 7); + const int8x8_t shiftb = vshrn_n_s16(b, 7); + const int8x16_t compacted = vcombine_s8(shifta,shiftb); + return *reinterpret_cast (&compacted); } #define vec_load_psqt(a) (*(a)) #define vec_store_psqt(a,b) *(a)=(b) @@ -290,7 +290,7 @@ namespace Stockfish::Eval::NNUE { #if defined(VECTOR) - constexpr IndexType OutputChunkSize = MaxChunkSize; + constexpr IndexType OutputChunkSize = MaxChunkSize; static_assert((HalfDimensions / 2) % OutputChunkSize == 0); constexpr IndexType NumOutputChunks = HalfDimensions / 2 / OutputChunkSize; diff --git a/src/search.cpp b/src/search.cpp index d09ced9a..ff7b996b 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -608,7 +608,6 @@ namespace { (ss+2)->killers[0] = (ss+2)->killers[1] = MOVE_NONE; (ss+2)->cutoffCnt = 0; ss->doubleExtensions = (ss-1)->doubleExtensions; - ss->depth = depth; Square prevSq = to_sq((ss-1)->currentMove); // Initialize statScore to zero for the grandchildren of the current position. @@ -869,7 +868,6 @@ namespace { MovePicker mp(pos, ttMove, probCutBeta - ss->staticEval, depth - 3, &captureHistory); bool ttPv = ss->ttPv; - bool captureOrPromotion; ss->ttPv = false; while ((move = mp.next_move()) != MOVE_NONE) @@ -877,11 +875,9 @@ namespace { { assert(pos.capture(move) || promotion_type(move) == QUEEN); - captureOrPromotion = true; - ss->currentMove = move; ss->continuationHistory = &thisThread->continuationHistory[ss->inCheck] - [captureOrPromotion] + [true] [pos.moved_piece(move)] [to_sq(move)]; diff --git a/src/search.h b/src/search.h index 8bb51832..4ad5784f 100644 --- a/src/search.h +++ b/src/search.h @@ -47,7 +47,6 @@ struct Stack { Move excludedMove; Move killers[2]; Value staticEval; - Depth depth; int statScore; int moveCount; bool inCheck; diff --git a/src/syzygy/tbprobe.cpp b/src/syzygy/tbprobe.cpp index a1315244..43af89f0 100644 --- a/src/syzygy/tbprobe.cpp +++ b/src/syzygy/tbprobe.cpp @@ -1290,7 +1290,7 @@ void Tablebases::init(const std::string& paths) { for (auto s : diagonal) MapA1D1D4[s] = code++; - // MapKK[] encodes all the 461 possible legal positions of two kings where + // MapKK[] encodes all the 462 possible legal positions of two kings where // the first is in the a1-d1-d4 triangle. If the first king is on the a1-d4 // diagonal, the other one shall not to be above the a1-h8 diagonal. std::vector> bothOnDiagonal; diff --git a/src/types.h b/src/types.h index cf42bc9f..c2087c6c 100644 --- a/src/types.h +++ b/src/types.h @@ -450,7 +450,7 @@ constexpr Square to_sq(Move m) { } constexpr int from_to(Move m) { - return m & 0xFFF; + return m & 0xFFF; } constexpr MoveType type_of(Move m) { From 48df0754bc87f099c4b29ff1b2f2629ddacd1c95 Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Fri, 20 May 2022 07:42:33 +0200 Subject: [PATCH 18/84] Add command line flags to link to information This patch provides command line flags `--help` and `--license` as well as the corresponding `help` and `license` commands. ``` $ ./stockfish --help Stockfish 200522 by the Stockfish developers (see AUTHORS file) Stockfish is a powerful chess engine and free software licensed under the GNU GPLv3. Stockfish is normally used with a separate graphical user interface (GUI). Stockfish implements the universal chess interface (UCI) to exchange information. For further information see https://github.com/official-stockfish/Stockfish#readme or the corresponding README.md and Copying.txt files distributed with this program. ``` The idea is to provide a minimal help that links to the README.md file, not replicating information that is already available elsewhere. We use this opportunity to explicitly report the license as well. closes https://github.com/official-stockfish/Stockfish/pull/4027 No functional change. --- src/uci.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/uci.cpp b/src/uci.cpp index 7b30cc04..c28cf6d1 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -285,8 +285,14 @@ void UCI::loop(int argc, char* argv[]) { filename = f; Eval::NNUE::save_eval(filename); } + else if (token == "--help" || token == "help" || token == "--license" || token == "license") + sync_cout << "\nStockfish is a powerful chess engine and free software licensed under the GNU GPLv3." + "\nStockfish is normally used with a separate graphical user interface (GUI)." + "\nStockfish implements the universal chess interface (UCI) to exchange information." + "\nFor further information see https://github.com/official-stockfish/Stockfish#readme" + "\nor the corresponding README.md and Copying.txt files distributed with this program.\n" << sync_endl; else if (!token.empty() && token[0] != '#') - sync_cout << "Unknown command: " << cmd << sync_endl; + sync_cout << "Unknown command: '" << cmd << "'. Type help for more information." << sync_endl; } while (token != "quit" && argc == 1); // Command line args are one-shot } From 1a168201bd8424da4cea384ee4c03973b2ccf0ca Mon Sep 17 00:00:00 2001 From: Giacomo Lorenzetti Date: Sun, 22 May 2022 12:47:30 +0200 Subject: [PATCH 19/84] Small speedup in futility_move_count The speedup is around 0.25% using gcc 11.3.1 (bmi2, nnue bench, depth 16 and 23) while it is neutral using clang (same conditions). According to `perf` that integer division was one of the most time-consuming instructions in search (gcc disassembly). Passed STC: https://tests.stockfishchess.org/tests/view/628a17fe24a074e5cd59b3aa LLR: 2.94 (-2.94,2.94) <0.00,2.50> Total: 22232 W: 5992 L: 5751 D: 10489 Ptnml(0-2): 88, 2235, 6218, 2498, 77 yellow LTC: https://tests.stockfishchess.org/tests/view/628a35d7ccae0450e35106f7 LLR: -2.95 (-2.94,2.94) <0.50,3.00> Total: 320168 W: 85853 L: 85326 D: 148989 Ptnml(0-2): 185, 29698, 99821, 30165, 215 This patch also suggests that UHO STC is sensible to small speedups (< 0.50%). closes https://github.com/official-stockfish/Stockfish/pull/4032 No functional change --- src/search.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index ff7b996b..0a4b1a18 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -75,7 +75,8 @@ namespace { } constexpr int futility_move_count(bool improving, Depth depth) { - return (3 + depth * depth) / (2 - improving); + return improving ? (3 + depth * depth) + : (3 + depth * depth) / 2; } // History and stats update bonus, based on depth From 6ede1bed89fd9d1c25cc6349722898f084bf5e15 Mon Sep 17 00:00:00 2001 From: proukornew Date: Fri, 17 Dec 2021 00:41:29 +0300 Subject: [PATCH 20/84] Improve handling of variables set in the make environment removes duplication on the commandline for example in a profile-build closes https://github.com/official-stockfish/Stockfish/pull/3859 No functional change --- src/Makefile | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Makefile b/src/Makefile index cc9b4201..ff2452d6 100644 --- a/src/Makefile +++ b/src/Makefile @@ -345,9 +345,15 @@ endif ### ========================================================================== ### 3.1 Selecting compiler (default = gcc) -CXXFLAGS += -Wall -Wcast-qual -fno-exceptions -std=c++17 $(EXTRACXXFLAGS) -DEPENDFLAGS += -std=c++17 -LDFLAGS += $(EXTRALDFLAGS) +ifeq ($(MAKELEVEL),0) + export ENV_CXXFLAGS := $(CXXFLAGS) + export ENV_DEPENDFLAGS := $(DEPENDFLAGS) + export ENV_LDFLAGS := $(LDFLAGS) +endif + +CXXFLAGS = $(ENV_CXXFLAGS) -Wall -Wcast-qual -fno-exceptions -std=c++17 $(EXTRACXXFLAGS) +DEPENDFLAGS = $(ENV_DEPENDFLAGS) -std=c++17 +LDFLAGS = $(ENV_LDFLAGS) $(EXTRALDFLAGS) ifeq ($(COMP),) COMP=gcc From 4c7de9e8abd8d5dc71d0c85dddd75a7b244600d7 Mon Sep 17 00:00:00 2001 From: xoto10 Date: Thu, 19 May 2022 08:51:40 +0100 Subject: [PATCH 21/84] Adjust scale param higher xoto10's scaleopt tune resulted in a yellow LTC, but the main parameter shift looked almost exactly like the tune rate reduction schedule, so further increases of that param were tried. Joint work xoto10 and dubslow. passed LTC: https://tests.stockfishchess.org/tests/view/628c709372775f382300f03e LLR: 2.93 (-2.94,2.94) <0.50,3.00> Total: 70112 W: 18932 L: 18584 D: 32596 Ptnml(0-2): 66, 6904, 20757, 7274, 55 failed STC: https://tests.stockfishchess.org/tests/view/6290e4441e7cd5f29966bdc8 LLR: -2.96 (-2.94,2.94) <0.00,2.50> Total: 59976 W: 15919 L: 16018 D: 28039 Ptnml(0-2): 250, 6791, 15974, 6754, 219 similar LTC's were yellow first yellow LTC: https://tests.stockfishchess.org/tests/view/6288a33f817227d3e5c5b05d double exaggerate yellow: https://tests.stockfishchess.org/tests/live_elo/628e140372775f38230129a6 triple exaggerate yellow: https://tests.stockfishchess.org/tests/live_elo/628e2caf72775f3823012d45 closes https://github.com/official-stockfish/Stockfish/pull/4036 bench 6410652 --- AUTHORS | 1 + src/evaluate.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/AUTHORS b/AUTHORS index b435ff8f..715f83b1 100644 --- a/AUTHORS +++ b/AUTHORS @@ -55,6 +55,7 @@ DiscanX Dominik Schlösser (domschl) double-beep Douglas Matos Gomes (dsmsgms) +Dubslow Eduardo Cáceres (eduherminio) Eelco de Groot (KingDefender) Elvin Liu (solarlight2) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 9061a384..9ed9e8e3 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -1100,14 +1100,14 @@ Value Eval::evaluate(const Position& pos) { if (useNNUE && !useClassical) { Value nnue = NNUE::evaluate(pos, true); // NNUE - int scale = 1014 + 21 * pos.non_pawn_material() / 1024; + int scale = 1080 + 110 * pos.non_pawn_material() / 5120; Color stm = pos.side_to_move(); Value optimism = pos.this_thread()->optimism[stm]; Value psq = (stm == WHITE ? 1 : -1) * eg_value(pos.psq_score()); - int complexity = 35 * abs(nnue - psq) / 256; + int complexity = (278 * abs(nnue - psq)) / 256; - optimism = optimism * (32 + complexity) / 32; - v = (nnue * scale + optimism * (scale - 846)) / 1024; + optimism = optimism * (251 + complexity) / 256; + v = (nnue * scale + optimism * (scale - 852)) / 1024; if (pos.is_chess960()) v += fix_FRC(pos); From 8fadbcf1b2c3bc281b2d1efd7992fc9f4c3a38be Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Mon, 30 May 2022 13:30:59 +0300 Subject: [PATCH 22/84] Add info about elo gained from some heuristics Add info about qsearch and impact of main and continuation histories. Based on these tests: https://tests.stockfishchess.org/tests/view/62946ffcb0d5a7d1b780fc7e https://tests.stockfishchess.org/tests/view/628facb71e7cd5f299669534 https://tests.stockfishchess.org/tests/view/628eade11e7cd5f299666f2e closes https://github.com/official-stockfish/Stockfish/pull/4041 No functional change. --- src/movepick.h | 2 ++ src/search.cpp | 1 + 2 files changed, 3 insertions(+) diff --git a/src/movepick.h b/src/movepick.h index 9a3c279b..6b3c08c7 100644 --- a/src/movepick.h +++ b/src/movepick.h @@ -86,6 +86,7 @@ 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 +/// (~11 elo) typedef Stats ButterflyHistory; /// CounterMoveHistory stores counter moves indexed by [piece][to] of the previous @@ -101,6 +102,7 @@ typedef Stats PieceToHistory; /// ContinuationHistory is the combined history of a given pair of moves, usually /// the current one given a previous one. The nested history table is based on /// PieceToHistory instead of ButterflyBoards. +/// (~63 elo) typedef Stats ContinuationHistory; diff --git a/src/search.cpp b/src/search.cpp index 0a4b1a18..407cb701 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1396,6 +1396,7 @@ moves_loop: // When in check, search starts here // qsearch() is the quiescence search function, which is called by the main search // function with zero depth, or recursively with further decreasing depth per call. + // (~155 elo) template Value qsearch(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth) { From 653bd0817ceea2980474d76198fe527f8b84bf04 Mon Sep 17 00:00:00 2001 From: candirufish <38038147+candirufish@users.noreply.github.com> Date: Tue, 31 May 2022 21:52:04 +0200 Subject: [PATCH 23/84] cutnode and movecount lmr extension simplification Passed STC https://tests.stockfishchess.org/tests/view/6294133cb0d5a7d1b780ece3 LLR: 2.94 (-2.94,2.94) <-2.25,0.25> Total: 41072 W: 11052 L: 10908 D: 19112 Ptnml(0-2): 153, 4324, 11461, 4422, 176 Passed LTC ltc: https://tests.stockfishchess.org/tests/view/62947ae6b0d5a7d1b780fe86 LLR: 2.94 (-2.94,2.94) <-2.25,0.25> Total: 102736 W: 27509 L: 27459 D: 47768 Ptnml(0-2): 98, 9734, 31669, 9754, 113 closes https://github.com/official-stockfish/Stockfish/pull/4045 Bench: 6410652 --- src/search.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 407cb701..8ecdbc30 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1194,8 +1194,7 @@ moves_loop: // When in check, search starts here // deeper than the first move (this may lead to hidden double extensions). int deeper = r >= -1 ? 0 : moveCount <= 4 ? 2 - : PvNode ? 1 - : cutNode && moveCount <= 8 ? 1 + : PvNode || cutNode ? 1 : 0; Depth d = std::clamp(newDepth - r, 1, newDepth + deeper); From 7f1333ccf89c715933ead72e31233510c6f4d146 Mon Sep 17 00:00:00 2001 From: xoto10 Date: Wed, 1 Jun 2022 01:20:27 +0100 Subject: [PATCH 24/84] Blend nnue complexity with classical. Following mstembera's test of the complexity value derived from nnue values, this change blends that idea with the old complexity calculation. STC 10+0.1: LLR: 2.95 (-2.94,2.94) <0.00,2.50> Total: 42320 W: 11436 L: 11148 D: 19736 Ptnml(0-2): 209, 4585, 11263, 4915, 188 https://tests.stockfishchess.org/tests/live_elo/6295c9239c8c2fcb2bad7fd9 LTC 60+0.6: LLR: 2.98 (-2.94,2.94) <0.50,3.00> Total: 34600 W: 9393 L: 9125 D: 16082 Ptnml(0-2): 32, 3323, 10319, 3597, 29 https://tests.stockfishchess.org/tests/view/6295fd5d9c8c2fcb2bad88cf closes https://github.com/official-stockfish/Stockfish/pull/4046 Bench 6078140 --- src/evaluate.cpp | 11 ++++++----- src/evaluate.h | 2 +- src/nnue/evaluate_nnue.cpp | 7 +++++-- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 9ed9e8e3..415c18c5 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -1099,15 +1099,16 @@ Value Eval::evaluate(const Position& pos) { // If result of a classical evaluation is much lower than threshold fall back to NNUE if (useNNUE && !useClassical) { - Value nnue = NNUE::evaluate(pos, true); // NNUE - int scale = 1080 + 110 * pos.non_pawn_material() / 5120; + int complexity; + int scale = 1048 + 109 * pos.non_pawn_material() / 5120; Color stm = pos.side_to_move(); Value optimism = pos.this_thread()->optimism[stm]; Value psq = (stm == WHITE ? 1 : -1) * eg_value(pos.psq_score()); - int complexity = (278 * abs(nnue - psq)) / 256; + Value nnue = NNUE::evaluate(pos, true, &complexity); // NNUE - optimism = optimism * (251 + complexity) / 256; - v = (nnue * scale + optimism * (scale - 852)) / 1024; + complexity = (137 * complexity + 137 * abs(nnue - psq)) / 256; + optimism = optimism * (255 + complexity) / 256; + v = (nnue * scale + optimism * (scale - 848)) / 1024; if (pos.is_chess960()) v += fix_FRC(pos); diff --git a/src/evaluate.h b/src/evaluate.h index f67961a9..e79eaea3 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -44,7 +44,7 @@ namespace Eval { namespace NNUE { std::string trace(Position& pos); - Value evaluate(const Position& pos, bool adjusted = false); + Value evaluate(const Position& pos, bool adjusted = false, int* complexity = nullptr); void init(); void verify(); diff --git a/src/nnue/evaluate_nnue.cpp b/src/nnue/evaluate_nnue.cpp index 9ee599f4..eb6ad71f 100644 --- a/src/nnue/evaluate_nnue.cpp +++ b/src/nnue/evaluate_nnue.cpp @@ -137,7 +137,7 @@ namespace Stockfish::Eval::NNUE { } // Evaluation function. Perform differential calculation. - Value evaluate(const Position& pos, bool adjusted) { + Value evaluate(const Position& pos, bool adjusted, int* complexity) { // We manually align the arrays on the stack because with gcc < 9.3 // overaligning stack variables with alignas() doesn't work correctly. @@ -161,9 +161,12 @@ namespace Stockfish::Eval::NNUE { const auto psqt = featureTransformer->transform(pos, transformedFeatures, bucket); const auto positional = network[bucket]->propagate(transformedFeatures); + if (complexity) + *complexity = abs(psqt - positional) / OutputScale; + // Give more value to positional evaluation when adjusted flag is set if (adjusted) - return static_cast(((128 - delta) * psqt + (128 + delta) * positional) / 128 / OutputScale); + return static_cast(((128 - delta) * psqt + (128 + delta) * positional) / (128 * OutputScale)); else return static_cast((psqt + positional) / OutputScale); } From 90cf8e7d2bde9e480aac4b119ce130e09dd2be39 Mon Sep 17 00:00:00 2001 From: Dubslow Date: Sun, 29 May 2022 19:52:11 -0500 Subject: [PATCH 25/84] Remove LMR condition for complex pos Inspired by Kia's similar test: https://tests.stockfishchess.org/tests/view/6292898c1e7cd5f29966fbe0 Passed STC: https://tests.stockfishchess.org/tests/view/62941588b0d5a7d1b780ed4b LLR: 2.94 (-2.94,2.94) <-2.25,0.25> Total: 266872 W: 70850 L: 71033 D: 124989 Ptnml(0-2): 1180, 30114, 70941, 30111, 1090 Passed LTC: https://tests.stockfishchess.org/tests/view/62964a754628d33daa24f062 LLR: 2.95 (-2.94,2.94) <-2.25,0.25> Total: 70160 W: 18756 L: 18662 D: 32742 Ptnml(0-2): 42, 6976, 20950, 7070, 42 closes https://github.com/official-stockfish/Stockfish/pull/4047 Bench 6237567 --- src/search.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 8ecdbc30..ea1e63fe 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1167,11 +1167,6 @@ moves_loop: // When in check, search starts here if (ttCapture) r++; - // Decrease reduction at PvNodes if bestvalue - // is vastly different from static evaluation - if (PvNode && !ss->inCheck && abs(ss->staticEval - bestValue) > 250) - r--; - // Decrease reduction for PvNodes based on depth if (PvNode) r -= 1 + 15 / ( 3 + depth ); From 809849fa275512225d19e280809f227990d97eb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bo=C5=A1tjan=20Mejak?= Date: Tue, 31 May 2022 20:25:57 +0200 Subject: [PATCH 26/84] Wording of help output and comments. Improved the output text that is diplayed when executing the 'help' command. Also, some comments were fixed along the way. closes https://github.com/official-stockfish/Stockfish/pull/4048 closes https://github.com/official-stockfish/Stockfish/pull/4044 No functional change --- AUTHORS | 1 + src/uci.cpp | 126 ++++++++++++++++++++++++++-------------------------- src/uci.h | 6 +-- 3 files changed, 67 insertions(+), 66 deletions(-) diff --git a/AUTHORS b/AUTHORS index 715f83b1..fc885acb 100644 --- a/AUTHORS +++ b/AUTHORS @@ -35,6 +35,7 @@ Ben Chaney (Chaneybenjamini) Ben Koshy (BKSpurgeon) Bill Henry (VoyagerOne) Bojun Guo (noobpwnftw, Nooby) +Boštjan Mejak (PedanticHacker) braich Brian Sheppard (SapphireBrand, briansheppard-toast) Bruno de Melo Costa (BM123499) diff --git a/src/uci.cpp b/src/uci.cpp index c28cf6d1..c0bacfaf 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -40,14 +40,14 @@ extern vector setup_bench(const Position&, istream&); namespace { - // FEN string of the initial position, normal chess + // FEN string for the initial position in standard chess const char* StartFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"; - // position() is called when engine receives the "position" UCI command. - // The function sets up the position described in the given FEN string ("fen") - // or the starting position ("startpos") and then makes the moves given in the - // following move list ("moves"). + // position() is called when the engine receives the "position" UCI command. + // It sets up the position that is described in the given FEN string ("fen") or + // the initial position ("startpos") and then makes the moves given in the following + // move list ("moves"). void position(Position& pos, istringstream& is, StateListPtr& states) { @@ -59,7 +59,7 @@ namespace { if (token == "startpos") { fen = StartFEN; - is >> token; // Consume "moves" token if any + is >> token; // Consume the "moves" token, if any } else if (token == "fen") while (is >> token && token != "moves") @@ -67,10 +67,10 @@ namespace { else return; - states = StateListPtr(new std::deque(1)); // Drop old and create a new one + states = StateListPtr(new std::deque(1)); // Drop the old state and create a new one pos.set(fen, Options["UCI_Chess960"], &states->back(), Threads.main()); - // Parse move list (if any) + // Parse the move list, if any while (is >> token && (m = UCI::to_move(pos, token)) != MOVE_NONE) { states->emplace_back(); @@ -78,8 +78,8 @@ namespace { } } - // trace_eval() prints the evaluation for the current position, consistent with the UCI - // options set so far. + // trace_eval() prints the evaluation of the current position, consistent with + // the UCI options set so far. void trace_eval(Position& pos) { @@ -93,20 +93,20 @@ namespace { } - // setoption() is called when engine receives the "setoption" UCI command. The - // function updates the UCI option ("name") to the given value ("value"). + // setoption() is called when the engine receives the "setoption" UCI command. + // The function updates the UCI option ("name") to the given value ("value"). void setoption(istringstream& is) { string token, name, value; - is >> token; // Consume "name" token + is >> token; // Consume the "name" token - // Read option name (can contain spaces) + // Read the option name (can contain spaces) while (is >> token && token != "value") name += (name.empty() ? "" : " ") + token; - // Read option value (can contain spaces) + // Read the option value (can contain spaces) while (is >> token) value += (value.empty() ? "" : " ") + token; @@ -117,9 +117,9 @@ namespace { } - // go() is called when engine receives the "go" UCI command. The function sets - // the thinking time and other parameters from the input string, then starts - // the search. + // go() is called when the engine receives the "go" UCI command. The function + // sets the thinking time and other parameters from the input string, then starts + // with a search. void go(Position& pos, istringstream& is, StateListPtr& states) { @@ -127,7 +127,7 @@ namespace { string token; bool ponderMode = false; - limits.startTime = now(); // As early as possible! + limits.startTime = now(); // The search starts as early as possible while (is >> token) if (token == "searchmoves") // Needs to be the last command on the line @@ -151,9 +151,9 @@ namespace { } - // bench() is called when engine receives the "bench" command. Firstly - // a list of UCI commands is setup according to bench parameters, then - // it is run one by one printing a summary at the end. + // bench() is called when the engine receives the "bench" command. + // Firstly, a list of UCI commands is set up according to the bench + // parameters, then it is run one by one, printing a summary at the end. void bench(Position& pos, istream& args, StateListPtr& states) { @@ -184,12 +184,12 @@ namespace { } else if (token == "setoption") setoption(is); else if (token == "position") position(pos, is, states); - else if (token == "ucinewgame") { Search::clear(); elapsed = now(); } // Search::clear() may take some while + else if (token == "ucinewgame") { Search::clear(); elapsed = now(); } // Search::clear() may take a while } elapsed = now() - elapsed + 1; // Ensure positivity to avoid a 'divide by zero' - dbg_print(); // Just before exiting + dbg_print(); cerr << "\n===========================" << "\nTotal time (ms) : " << elapsed @@ -197,36 +197,36 @@ 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. + // The win rate model returns the probability of winning (in per mille units) given an + // eval and a game ply. It fits the LTC fishtest statistics rather accurately. int win_rate_model(Value v, int ply) { - // The model captures only up to 240 plies, so limit input (and rescale) + // The model only captures up to 240 plies, so limit the input and then 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. + // The coefficients of a third-order polynomial fit is based on the fishtest data + // for two parameters that need to transform eval to the argument of a logistic + // function. double as[] = {-1.17202460e-01, 5.94729104e-01, 1.12065546e+01, 1.22606222e+02}; double bs[] = {-1.79066759, 11.30759193, -17.43677612, 36.47147479}; 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 + // Transform the eval to centipawns with limited range double x = std::clamp(double(100 * v) / PawnValueEg, -2000.0, 2000.0); - // Return win rate in per mille (rounded to nearest) + // Return the win rate in per mille units rounded to the nearest value return int(0.5 + 1000 / (1 + std::exp((a - x) / b))); } } // namespace -/// UCI::loop() waits for a command from stdin, parses it and calls the appropriate -/// function. Also intercepts EOF from stdin to ensure gracefully exiting if the -/// GUI dies unexpectedly. When called with some command line arguments, e.g. to -/// run 'bench', once the command is executed the function returns immediately. -/// In addition to the UCI ones, also some additional debug commands are supported. +/// UCI::loop() waits for a command from the stdin, parses it and then calls the appropriate +/// function. It also intercepts an end-of-file (EOF) indication from the stdin to ensure a +/// graceful exit if the GUI dies unexpectedly. When called with some command-line arguments, +/// like running 'bench', the function returns immediately after the command is executed. +/// In addition to the UCI ones, some additional debug commands are also supported. void UCI::loop(int argc, char* argv[]) { @@ -240,24 +240,24 @@ void UCI::loop(int argc, char* argv[]) { cmd += std::string(argv[i]) + " "; do { - if (argc == 1 && !getline(cin, cmd)) // Block here waiting for input or EOF + if (argc == 1 && !getline(cin, cmd)) // Wait for an input or an end-of-file (EOF) indication cmd = "quit"; istringstream is(cmd); - token.clear(); // Avoid a stale if getline() returns empty or blank line + token.clear(); // Avoid a stale if getline() returns nothing or a blank line is >> skipws >> token; if ( token == "quit" || token == "stop") Threads.stop = true; - // The GUI sends 'ponderhit' to tell us the user has played the expected move. - // So 'ponderhit' will be sent if we were told to ponder on the same move the - // user has played. We should continue searching but switch from pondering to - // normal search. + // The GUI sends 'ponderhit' to tell that the user has played the expected move. + // So, 'ponderhit' is sent if pondering was done on the same move that the user + // has played. The search should continue, but should also switch from pondering + // to the normal search. else if (token == "ponderhit") - Threads.main()->ponder = false; // Switch to normal search + Threads.main()->ponder = false; // Switch to the normal search else if (token == "uci") sync_cout << "id name " << engine_info(true) @@ -270,8 +270,8 @@ void UCI::loop(int argc, char* argv[]) { else if (token == "ucinewgame") Search::clear(); else if (token == "isready") sync_cout << "readyok" << sync_endl; - // Additional custom non-UCI commands, mainly for debugging. - // Do not use these commands during a search! + // Add custom non-UCI commands, mainly for debugging purposes. + // These commands must not be used during a search! else if (token == "flip") pos.flip(); else if (token == "bench") bench(pos, is, states); else if (token == "d") sync_cout << pos << sync_endl; @@ -286,24 +286,24 @@ void UCI::loop(int argc, char* argv[]) { Eval::NNUE::save_eval(filename); } else if (token == "--help" || token == "help" || token == "--license" || token == "license") - sync_cout << "\nStockfish is a powerful chess engine and free software licensed under the GNU GPLv3." - "\nStockfish is normally used with a separate graphical user interface (GUI)." - "\nStockfish implements the universal chess interface (UCI) to exchange information." - "\nFor further information see https://github.com/official-stockfish/Stockfish#readme" - "\nor the corresponding README.md and Copying.txt files distributed with this program.\n" << sync_endl; + sync_cout << "\nStockfish is a powerful chess engine for playing and analyzing." + "\nIt is released as free software licensed under the GNU GPLv3 License." + "\nStockfish is normally used with a graphical user interface (GUI) and implements" + "\nthe Universal Chess Interface (UCI) protocol to communicate with a GUI, an API, etc." + "\nFor any further information, visit https://github.com/official-stockfish/Stockfish#readme" + "\nor read the corresponding README.md and Copying.txt files distributed along with this program.\n" << sync_endl; else if (!token.empty() && token[0] != '#') sync_cout << "Unknown command: '" << cmd << "'. Type help for more information." << sync_endl; - } while (token != "quit" && argc == 1); // Command line args are one-shot + } while (token != "quit" && argc == 1); // The command-line arguments are one-shot } -/// UCI::value() converts a Value to a string suitable for use with the UCI -/// protocol specification: +/// UCI::value() converts a Value to a string by adhering to the UCI protocol specification: /// /// cp The score from the engine's point of view in centipawns. -/// mate Mate in y moves, not plies. If the engine is getting mated -/// use negative values for y. +/// mate Mate in 'y' moves (not plies). If the engine is getting mated, +/// uses negative values for 'y'. string UCI::value(Value v) { @@ -320,8 +320,8 @@ 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. +/// UCI::wdl() reports the win-draw-loss (WDL) statistics given an evaluation +/// and a game ply based on the data gathered for fishtest LTC games. string UCI::wdl(Value v, int ply) { @@ -344,9 +344,9 @@ std::string UCI::square(Square s) { /// UCI::move() converts a Move to a string in coordinate notation (g1f3, a7a8q). -/// The only special case is castling, where we print in the e1g1 notation in -/// normal chess mode, and in e1h1 notation in chess960 mode. Internally all -/// castling moves are always encoded as 'king captures rook'. +/// The only special case is castling where the e1g1 notation is printed in +/// standard chess mode and in e1h1 notation it is printed in Chess960 mode. +/// Internally, all castling moves are always encoded as 'king captures rook'. string UCI::move(Move m, bool chess960) { @@ -376,8 +376,8 @@ string UCI::move(Move m, bool chess960) { Move UCI::to_move(const Position& pos, string& str) { - if (str.length() == 5) // Junior could send promotion piece in uppercase - str[4] = char(tolower(str[4])); + if (str.length() == 5) + str[4] = char(tolower(str[4])); // The promotion piece character must be lowercased for (const auto& m : MoveList(pos)) if (str == UCI::move(m, pos.is_chess960())) diff --git a/src/uci.h b/src/uci.h index 5bb24a4e..76a893f9 100644 --- a/src/uci.h +++ b/src/uci.h @@ -32,15 +32,15 @@ namespace UCI { class Option; -/// Custom comparator because UCI options should be case insensitive +/// Define a custom comparator, because the UCI options should be case-insensitive struct CaseInsensitiveLess { bool operator() (const std::string&, const std::string&) const; }; -/// Our options container is actually a std::map +/// The options container is defined as a std::map typedef std::map OptionsMap; -/// Option class implements an option as defined by UCI protocol +/// The Option class implements each option as specified by the UCI protocol class Option { typedef void (*OnChange)(const Option&); From 00297cfef0ad604a61aaff2747dea029fa6aa733 Mon Sep 17 00:00:00 2001 From: candirufish <38038147+candirufish@users.noreply.github.com> Date: Tue, 7 Jun 2022 07:21:43 +0200 Subject: [PATCH 27/84] Use qsearch on step 11 if depth is equal to or below 0 larger reduction of depth if no TT entry is found, and go in qsearch as needed. stc: https://tests.stockfishchess.org/tests/view/629dfacd593a4a9b6482db72 LLR: 2.93 (-2.94,2.94) <0.00,2.50> Total: 31920 W: 8591 L: 8322 D: 15007 Ptnml(0-2): 127, 3551, 8376, 3738, 168 ltc: https://tests.stockfishchess.org/tests/view/629e304e593a4a9b6482e451 LLR: 2.95 (-2.94,2.94) <0.50,3.00> Total: 17488 W: 4842 L: 4614 D: 8032 Ptnml(0-2): 13, 1670, 5151, 1896, 14 closes https://github.com/official-stockfish/Stockfish/pull/4056 Bench: 5870283 --- src/search.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index ea1e63fe..17ac05c4 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -908,14 +908,17 @@ namespace { ss->ttPv = ttPv; } - // Step 11. If the position is not in TT, decrease depth by 2 or 1 depending on node type (~3 Elo) - if ( PvNode - && depth >= 3 + // Step 11. If the position is not in TT, decrease depth by 3. + // Use qsearch if depth is equal or below zero (~4 Elo) + if ( PvNode && !ttMove) - depth -= 2; + depth -= 3; - if ( cutNode - && depth >= 8 + if (depth <= 0) + return qsearch(pos, ss, alpha, beta); + + if ( cutNode + && depth >= 8 && !ttMove) depth--; From d54b85b4bdcd2354903a31f4f35cca6b3742a7d9 Mon Sep 17 00:00:00 2001 From: ppigazzini Date: Mon, 13 Jun 2022 22:08:01 +0200 Subject: [PATCH 28/84] Restore NDKv21 for GitHub Actions GitHub updated the versions of NDK installed on the Actions runners breaking the ARM tests. Restore the NDKv21 using the GitHub suggested mitigation, see: https://github.com/actions/virtual-environments/issues/5595 closes https://github.com/official-stockfish/Stockfish/pull/4077 No functional change --- .github/workflows/stockfish.yml | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/.github/workflows/stockfish.yml b/.github/workflows/stockfish.yml index 33560d52..782e3f2b 100644 --- a/.github/workflows/stockfish.yml +++ b/.github/workflows/stockfish.yml @@ -5,7 +5,6 @@ on: - master - tools - github_ci - - github_ci_armv7 pull_request: branches: - master @@ -269,6 +268,12 @@ jobs: - name: Test armv8 build if: ${{ matrix.config.run_armv8_tests }} run: | + ANDROID_ROOT=/usr/local/lib/android + ANDROID_SDK_ROOT=${ANDROID_ROOT}/sdk + SDKMANAGER=${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager + echo "y" | $SDKMANAGER "ndk;21.4.7075529" + ANDROID_NDK_ROOT=${ANDROID_SDK_ROOT}/ndk-bundle + ln -sfn $ANDROID_SDK_ROOT/ndk/21.4.7075529 $ANDROID_NDK_ROOT export PATH=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH export LDFLAGS="-static -Wno-unused-command-line-argument" make clean @@ -280,6 +285,12 @@ jobs: - name: Test armv7 build if: ${{ matrix.config.run_armv7_tests }} run: | + ANDROID_ROOT=/usr/local/lib/android + ANDROID_SDK_ROOT=${ANDROID_ROOT}/sdk + SDKMANAGER=${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager + echo "y" | $SDKMANAGER "ndk;21.4.7075529" + ANDROID_NDK_ROOT=${ANDROID_SDK_ROOT}/ndk-bundle + ln -sfn $ANDROID_SDK_ROOT/ndk/21.4.7075529 $ANDROID_NDK_ROOT export PATH=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH export LDFLAGS="-static -Wno-unused-command-line-argument" make clean @@ -289,6 +300,12 @@ jobs: - name: Test armv7-neon build if: ${{ matrix.config.run_armv7_tests }} run: | + ANDROID_ROOT=/usr/local/lib/android + ANDROID_SDK_ROOT=${ANDROID_ROOT}/sdk + SDKMANAGER=${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager + echo "y" | $SDKMANAGER "ndk;21.4.7075529" + ANDROID_NDK_ROOT=${ANDROID_SDK_ROOT}/ndk-bundle + ln -sfn $ANDROID_SDK_ROOT/ndk/21.4.7075529 $ANDROID_NDK_ROOT export PATH=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH export LDFLAGS="-static -Wno-unused-command-line-argument" make clean From 2d5dcf3d18842dc2cfb17e3dd64e0812bf01ab65 Mon Sep 17 00:00:00 2001 From: mstembera Date: Sun, 5 Jun 2022 19:32:05 -0700 Subject: [PATCH 29/84] Minor simplifications and cleanup in search STC: https://tests.stockfishchess.org/tests/view/629d6775593a4a9b6482c1ec LLR: 2.93 (-2.94,2.94) <-2.25,0.25> Total: 77416 W: 20683 L: 20589 D: 36144 Ptnml(0-2): 317, 8690, 20620, 8744, 337 LTC: https://tests.stockfishchess.org/tests/view/629db4be593a4a9b6482ceef LLR: 2.95 (-2.94,2.94) <-2.25,0.25> Total: 106544 W: 28752 L: 28705 D: 49087 Ptnml(0-2): 97, 10692, 31641, 10751, 91 closes https://github.com/official-stockfish/Stockfish/pull/4059 Bench: 5913510 --- src/search.cpp | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 17ac05c4..1ab71a56 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -85,8 +85,8 @@ namespace { } // Add a small random component to draw evaluations to avoid 3-fold blindness - Value value_draw(Thread* thisThread) { - return VALUE_DRAW + Value(2 * (thisThread->nodes & 1) - 1); + Value value_draw(const Thread* thisThread) { + return VALUE_DRAW - 1 + Value(thisThread->nodes & 0x2); } // Skill structure is used to implement strength limit. If we have an uci_elo then @@ -116,7 +116,7 @@ namespace { Value value_to_tt(Value v, int ply); Value value_from_tt(Value v, int ply, int r50c); - void update_pv(Move* pv, Move move, Move* childPv); + void update_pv(Move* pv, Move move, const Move* childPv); void update_continuation_histories(Stack* ss, Piece pc, Square to, int bonus); void update_quiet_stats(const Position& pos, Stack* ss, Move move, int bonus); void update_all_stats(const Position& pos, Stack* ss, Move bestMove, Value bestValue, Value beta, Square prevSq, @@ -635,10 +635,9 @@ namespace { // At non-PV nodes we check for an early TT cutoff if ( !PvNode && ss->ttHit - && tte->depth() > depth - (thisThread->id() % 2 == 1) + && tte->depth() > depth - ((int)thisThread->id() & 0x1) && ttValue != VALUE_NONE // Possible in case of TT access race - && (ttValue >= beta ? (tte->bound() & BOUND_LOWER) - : (tte->bound() & BOUND_UPPER))) + && (tte->bound() & (ttValue >= beta ? BOUND_LOWER : BOUND_UPPER))) { // If ttMove is quiet, update move sorting heuristics on TT hit (~1 Elo) if (ttMove) @@ -896,12 +895,11 @@ namespace { if (value >= probCutBeta) { // if transposition table doesn't have equal or more deep info write probCut data into it - if ( !(ss->ttHit - && tte->depth() >= depth - 3 - && ttValue != VALUE_NONE)) + if (!( ss->ttHit + && tte->depth() >= depth - 3 + && ttValue != VALUE_NONE)) tte->save(posKey, value_to_tt(value, ss->ply), ttPv, - BOUND_LOWER, - depth - 3, move, ss->staticEval); + BOUND_LOWER, depth - 3, move, ss->staticEval); return value; } } @@ -1172,7 +1170,7 @@ moves_loop: // When in check, search starts here // Decrease reduction for PvNodes based on depth if (PvNode) - r -= 1 + 15 / ( 3 + depth ); + r -= 1 + 15 / (3 + depth); // Increase reduction if next ply has a lot of fail high else reset count to 0 if ((ss+1)->cutoffCnt > 3 && !PvNode) @@ -1450,8 +1448,7 @@ moves_loop: // When in check, search starts here && ss->ttHit && tte->depth() >= ttDepth && ttValue != VALUE_NONE // Only in case of TT access race - && (ttValue >= beta ? (tte->bound() & BOUND_LOWER) - : (tte->bound() & BOUND_UPPER))) + && (tte->bound() & (ttValue >= beta ? BOUND_LOWER : BOUND_UPPER))) return ttValue; // Evaluate the position statically @@ -1567,14 +1564,14 @@ moves_loop: // When in check, search starts here [to_sq(move)]; // Continuation history based pruning (~2 Elo) - if ( !capture + if ( !capture && bestValue > VALUE_TB_LOSS_IN_MAX_PLY && (*contHist[0])[pos.moved_piece(move)][to_sq(move)] < CounterMovePruneThreshold && (*contHist[1])[pos.moved_piece(move)][to_sq(move)] < CounterMovePruneThreshold) continue; // movecount pruning for quiet check evasions - if ( bestValue > VALUE_TB_LOSS_IN_MAX_PLY + if ( bestValue > VALUE_TB_LOSS_IN_MAX_PLY && quietCheckEvasions > 1 && !capture && ss->inCheck) @@ -1675,7 +1672,7 @@ moves_loop: // When in check, search starts here // update_pv() adds current move and appends child pv[] - void update_pv(Move* pv, Move move, Move* childPv) { + void update_pv(Move* pv, Move move, const Move* childPv) { for (*pv++ = move; childPv && *childPv != MOVE_NONE; ) *pv++ = *childPv++; @@ -1688,19 +1685,18 @@ moves_loop: // When in check, search starts here void update_all_stats(const Position& pos, Stack* ss, Move bestMove, Value bestValue, Value beta, Square prevSq, Move* quietsSearched, int quietCount, Move* capturesSearched, int captureCount, Depth depth) { - int bonus1, bonus2; Color us = pos.side_to_move(); Thread* thisThread = pos.this_thread(); CapturePieceToHistory& captureHistory = thisThread->captureHistory; Piece moved_piece = pos.moved_piece(bestMove); PieceType captured = type_of(pos.piece_on(to_sq(bestMove))); - - bonus1 = stat_bonus(depth + 1); - bonus2 = bestValue > beta + PawnValueMg ? bonus1 // larger bonus - : stat_bonus(depth); // smaller bonus + int bonus1 = stat_bonus(depth + 1); if (!pos.capture(bestMove)) { + int bonus2 = bestValue > beta + PawnValueMg ? bonus1 // larger bonus + : stat_bonus(depth); // smaller bonus + // Increase stats for the best move in case it was a quiet move update_quiet_stats(pos, ss, bestMove, bonus2); From 6edc29d720b43383a04bd2208e9666a6f3173a64 Mon Sep 17 00:00:00 2001 From: bmc4 Date: Thu, 9 Jun 2022 10:37:24 -0300 Subject: [PATCH 30/84] Simplify away condition in ttSave in probCut Remove condition for tte->save in probCut so it always saves on probCut cutoff. STC: LLR: 2.95 (-2.94,2.94) <-2.25,0.25> Total: 47848 W: 12921 L: 12782 D: 22145 Ptnml(0-2): 207, 5340, 12715, 5431, 231 https://tests.stockfishchess.org/tests/view/62a1f7c87bd8e641e44436f7 LTC: LLR: 2.97 (-2.94,2.94) <-2.25,0.25> Total: 132736 W: 35895 L: 35881 D: 60960 Ptnml(0-2): 109, 13384, 39360, 13414, 101 https://tests.stockfishchess.org/tests/view/62a2421a7bd8e641e444434f closes https://github.com/official-stockfish/Stockfish/pull/4069 bench: 5845802 --- src/search.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 1ab71a56..466c9ec1 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -894,12 +894,8 @@ namespace { if (value >= probCutBeta) { - // if transposition table doesn't have equal or more deep info write probCut data into it - if (!( ss->ttHit - && tte->depth() >= depth - 3 - && ttValue != VALUE_NONE)) - tte->save(posKey, value_to_tt(value, ss->ply), ttPv, - BOUND_LOWER, depth - 3, move, ss->staticEval); + // Save ProbCut data into transposition table + tte->save(posKey, value_to_tt(value, ss->ply), ttPv, BOUND_LOWER, depth - 3, move, ss->staticEval); return value; } } From 4d6a11a04cd8447b56447a9433c0cfb547a00643 Mon Sep 17 00:00:00 2001 From: bmc4 Date: Thu, 16 Jun 2022 07:19:39 -0300 Subject: [PATCH 31/84] Don't change ttPv at probCut STC: LLR: 2.96 (-2.94,2.94) <-2.25,0.25> Total: 35672 W: 9618 L: 9462 D: 16592 Ptnml(0-2): 151, 3890, 9601, 4040, 154 https://tests.stockfishchess.org/tests/view/62ab03f750949cfc241b1965 LTC: LLR: 2.93 (-2.94,2.94) <-2.25,0.25> Total: 54160 W: 14626 L: 14511 D: 25023 Ptnml(0-2): 42, 5414, 16056, 5523, 45 https://tests.stockfishchess.org/tests/view/62ab5e6fd89eb6cf1e071b87 closes https://github.com/official-stockfish/Stockfish/pull/4088 bench: 5798229 --- src/search.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 466c9ec1..6169e060 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -867,8 +867,6 @@ namespace { assert(probCutBeta < VALUE_INFINITE); MovePicker mp(pos, ttMove, probCutBeta - ss->staticEval, depth - 3, &captureHistory); - bool ttPv = ss->ttPv; - ss->ttPv = false; while ((move = mp.next_move()) != MOVE_NONE) if (move != excludedMove && pos.legal(move)) @@ -895,11 +893,10 @@ namespace { if (value >= probCutBeta) { // Save ProbCut data into transposition table - tte->save(posKey, value_to_tt(value, ss->ply), ttPv, BOUND_LOWER, depth - 3, move, ss->staticEval); + tte->save(posKey, value_to_tt(value, ss->ply), ss->ttPv, BOUND_LOWER, depth - 3, move, ss->staticEval); return value; } } - ss->ttPv = ttPv; } // Step 11. If the position is not in TT, decrease depth by 3. From 5304b561ab96ae1c025d98cf4a6d138daa11374d Mon Sep 17 00:00:00 2001 From: Dubslow Date: Wed, 15 Jun 2022 17:30:32 -0500 Subject: [PATCH 32/84] LMR: remove `deeper` ...apparently it wasn't doing much anymore. inspired by rufish's recent attempts to improve this. passed STC: https://tests.stockfishchess.org/tests/view/62abca2cd89eb6cf1e072c04 LLR: 2.95 (-2.94,2.94) <-2.25,0.25> Total: 85576 W: 22766 L: 22683 D: 40127 Ptnml(0-2): 362, 9607, 22741, 9742, 336 passed LTC: https://tests.stockfishchess.org/tests/view/62ac90ffd89eb6cf1e07488f LLR: 2.93 (-2.94,2.94) <-2.25,0.25> Total: 48248 W: 13018 L: 12896 D: 22334 Ptnml(0-2): 32, 4773, 14400, 4879, 40 closes https://github.com/official-stockfish/Stockfish/pull/4088 bench 5578988 --- src/search.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 6169e060..37277ec4 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1178,15 +1178,10 @@ moves_loop: // When in check, search starts here // Decrease/increase reduction for moves with a good/bad history (~30 Elo) r -= ss->statScore / 15914; - // In general we want to cap the LMR depth search at newDepth. But if reductions - // are really negative and movecount is low, we allow this move to be searched - // deeper than the first move (this may lead to hidden double extensions). - int deeper = r >= -1 ? 0 - : moveCount <= 4 ? 2 - : PvNode || cutNode ? 1 - : 0; - - Depth d = std::clamp(newDepth - r, 1, newDepth + deeper); + // In general we want to cap the LMR depth search at newDepth, but when + // reduction is negative, we allow this move a limited search extension + // beyond the first move depth. This may lead to hidden double extensions. + Depth d = std::clamp(newDepth - r, 1, newDepth + 1); value = -search(pos, ss+1, -(alpha+1), -alpha, d, true); From 442c40b43de8ede1e424efa674c8d45322e3b43c Mon Sep 17 00:00:00 2001 From: Dubslow Date: Fri, 10 Jun 2022 08:11:02 -0500 Subject: [PATCH 33/84] Use NNUE complexity in search, retune related parameters This builds on ideas of xoto10 and mstembera to use more output from NNUE in the search algorithm. passed STC: https://tests.stockfishchess.org/tests/view/62ae454fe7ee5525ef88a957 LLR: 2.95 (-2.94,2.94) <0.00,2.50> Total: 89208 W: 24127 L: 23753 D: 41328 Ptnml(0-2): 400, 9886, 23642, 10292, 384 passed LTC: https://tests.stockfishchess.org/tests/view/62acc6ddd89eb6cf1e0750a1 LLR: 2.93 (-2.94,2.94) <0.50,3.00> Total: 56352 W: 15430 L: 15115 D: 25807 Ptnml(0-2): 44, 5501, 16782, 5794, 55 closes https://github.com/official-stockfish/Stockfish/pull/4088 bench 5332964 --- src/evaluate.cpp | 32 ++++++++++++++++++++------------ src/evaluate.h | 2 +- src/nnue/evaluate_nnue.cpp | 4 ++-- src/position.h | 5 +++++ src/search.cpp | 20 ++++++++++---------- 5 files changed, 38 insertions(+), 25 deletions(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 415c18c5..6d2e8da8 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -1080,35 +1080,39 @@ make_v: /// evaluate() is the evaluator for the outer world. It returns a static /// evaluation of the position from the point of view of the side to move. -Value Eval::evaluate(const Position& pos) { +Value Eval::evaluate(const Position& pos, int* complexity) { Value v; + Color stm = pos.side_to_move(); + Value psq = pos.psq_eg_stm(); // Deciding between classical and NNUE eval (~10 Elo): for high PSQ imbalance we use classical, // but we switch to NNUE during long shuffling or with high material on the board. - bool useClassical = (pos.this_thread()->depth > 9 || pos.count() > 7) && - abs(eg_value(pos.psq_score())) * 5 > (856 + pos.non_pawn_material() / 64) * (10 + pos.rule50_count()); + bool useClassical = (pos.this_thread()->depth > 9 || pos.count() > 7) + && abs(psq) * 5 > (856 + pos.non_pawn_material() / 64) * (10 + pos.rule50_count()); // Deciding between classical and NNUE eval (~10 Elo): for high PSQ imbalance we use classical, // but we switch to NNUE during long shuffling or with high material on the board. if (!useNNUE || useClassical) { - v = Evaluation(pos).value(); // classical + v = Evaluation(pos).value(); useClassical = abs(v) >= 297; } // If result of a classical evaluation is much lower than threshold fall back to NNUE if (useNNUE && !useClassical) { - int complexity; - int scale = 1048 + 109 * pos.non_pawn_material() / 5120; - Color stm = pos.side_to_move(); + int nnueComplexity; + int scale = 1092 + 106 * pos.non_pawn_material() / 5120; Value optimism = pos.this_thread()->optimism[stm]; - Value psq = (stm == WHITE ? 1 : -1) * eg_value(pos.psq_score()); - Value nnue = NNUE::evaluate(pos, true, &complexity); // NNUE - complexity = (137 * complexity + 137 * abs(nnue - psq)) / 256; - optimism = optimism * (255 + complexity) / 256; - v = (nnue * scale + optimism * (scale - 848)) / 1024; + Value nnue = NNUE::evaluate(pos, true, &nnueComplexity); + // Blend nnue complexity with (semi)classical complexity + nnueComplexity = (104 * nnueComplexity + 131 * abs(nnue - psq)) / 256; + if (complexity) // Return hybrid NNUE complexity to caller + *complexity = nnueComplexity; + + optimism = optimism * (269 + nnueComplexity) / 256; + v = (nnue * scale + optimism * (scale - 754)) / 1024; if (pos.is_chess960()) v += fix_FRC(pos); @@ -1120,6 +1124,10 @@ Value Eval::evaluate(const Position& pos) { // Guarantee evaluation does not hit the tablebase range v = std::clamp(v, VALUE_TB_LOSS_IN_MAX_PLY + 1, VALUE_TB_WIN_IN_MAX_PLY - 1); + // When not using NNUE, return classical complexity to caller + if (complexity && (!useNNUE || useClassical)) + *complexity = abs(v - psq); + return v; } diff --git a/src/evaluate.h b/src/evaluate.h index e79eaea3..e25bd52e 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -31,7 +31,7 @@ class Position; namespace Eval { std::string trace(Position& pos); - Value evaluate(const Position& pos); + Value evaluate(const Position& pos, int* complexity = nullptr); extern bool useNNUE; extern std::string currentEvalFileName; diff --git a/src/nnue/evaluate_nnue.cpp b/src/nnue/evaluate_nnue.cpp index eb6ad71f..ba2ed367 100644 --- a/src/nnue/evaluate_nnue.cpp +++ b/src/nnue/evaluate_nnue.cpp @@ -143,7 +143,7 @@ namespace Stockfish::Eval::NNUE { // overaligning stack variables with alignas() doesn't work correctly. constexpr uint64_t alignment = CacheLineSize; - int delta = 10 - pos.non_pawn_material() / 1515; + int delta = 24 - pos.non_pawn_material() / 9560; #if defined(ALIGNAS_ON_STACK_VARIABLES_BROKEN) TransformedFeatureType transformedFeaturesUnaligned[ @@ -166,7 +166,7 @@ namespace Stockfish::Eval::NNUE { // Give more value to positional evaluation when adjusted flag is set if (adjusted) - return static_cast(((128 - delta) * psqt + (128 + delta) * positional) / (128 * OutputScale)); + return static_cast(((1024 - delta) * psqt + (1024 + delta) * positional) / (1024 * OutputScale)); else return static_cast((psqt + positional) / OutputScale); } diff --git a/src/position.h b/src/position.h index e5585818..510875d8 100644 --- a/src/position.h +++ b/src/position.h @@ -161,6 +161,7 @@ public: bool has_repeated() const; int rule50_count() const; Score psq_score() const; + Value psq_eg_stm() const; Value non_pawn_material(Color c) const; Value non_pawn_material() const; @@ -342,6 +343,10 @@ inline Score Position::psq_score() const { return psq; } +inline Value Position::psq_eg_stm() const { + return (sideToMove == WHITE ? 1 : -1) * eg_value(psq); +} + inline Value Position::non_pawn_material(Color c) const { return st->nonPawnMaterial[c]; } diff --git a/src/search.cpp b/src/search.cpp index 37277ec4..f11d76be 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -307,7 +307,7 @@ void Thread::search() { multiPV = std::min(multiPV, rootMoves.size()); - complexityAverage.set(202, 1); + complexityAverage.set(174, 1); trend = SCORE_ZERO; optimism[ us] = Value(39); @@ -472,7 +472,7 @@ void Thread::search() { double reduction = (1.56 + mainThread->previousTimeReduction) / (2.20 * timeReduction); double bestMoveInstability = 1 + 1.7 * totBestMoveChanges / Threads.size(); int complexity = mainThread->complexityAverage.value(); - double complexPosition = std::clamp(1.0 + (complexity - 326) / 1618.1, 0.5, 1.5); + double complexPosition = std::clamp(1.0 + (complexity - 277) / 1819, 0.5, 1.5); double totalTime = Time.optimum() * fallingEval * reduction * bestMoveInstability * complexPosition; @@ -736,7 +736,9 @@ namespace { // Never assume anything about values stored in TT ss->staticEval = eval = tte->eval(); if (eval == VALUE_NONE) - ss->staticEval = eval = evaluate(pos); + ss->staticEval = eval = evaluate(pos, &complexity); + else // Fall back to (semi)classical complexity for TT hits, the NNUE complexity is lost + complexity = abs(ss->staticEval - pos.psq_eg_stm()); // Randomize draw evaluation if (eval == VALUE_DRAW) @@ -749,13 +751,15 @@ namespace { } else { - ss->staticEval = eval = evaluate(pos); + ss->staticEval = eval = evaluate(pos, &complexity); // Save static evaluation into transposition table if (!excludedMove) tte->save(posKey, VALUE_NONE, ss->ttPv, BOUND_NONE, DEPTH_NONE, MOVE_NONE, eval); } + thisThread->complexityAverage.update(complexity); + // Use static evaluation difference to improve quiet move ordering (~3 Elo) if (is_ok((ss-1)->currentMove) && !(ss-1)->inCheck && !priorCapture) { @@ -770,11 +774,7 @@ namespace { improvement = (ss-2)->staticEval != VALUE_NONE ? ss->staticEval - (ss-2)->staticEval : (ss-4)->staticEval != VALUE_NONE ? ss->staticEval - (ss-4)->staticEval : 175; - improving = improvement > 0; - complexity = abs(ss->staticEval - (us == WHITE ? eg_value(pos.psq_score()) : -eg_value(pos.psq_score()))); - - thisThread->complexityAverage.update(complexity); // Step 7. Razoring. // If eval is really low check with qsearch if it can exceed alpha, if it can't, @@ -803,7 +803,7 @@ namespace { && (ss-1)->statScore < 14695 && eval >= beta && eval >= ss->staticEval - && ss->staticEval >= beta - 15 * depth - improvement / 15 + 198 + complexity / 28 + && ss->staticEval >= beta - 15 * depth - improvement / 15 + 201 + complexity / 24 && !excludedMove && pos.non_pawn_material(us) && (ss->ply >= thisThread->nmpMinPly || us != thisThread->nmpColor)) @@ -811,7 +811,7 @@ namespace { assert(eval - beta >= 0); // Null move dynamic reduction based on depth, eval and complexity of position - Depth R = std::min(int(eval - beta) / 147, 5) + depth / 3 + 4 - (complexity > 753); + Depth R = std::min(int(eval - beta) / 147, 5) + depth / 3 + 4 - (complexity > 650); ss->currentMove = MOVE_NULL; ss->continuationHistory = &thisThread->continuationHistory[0][0][NO_PIECE][0]; From 85f8ee6199f8578fbc082fc0f37e1985813e637a Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Fri, 1 Jul 2022 15:07:49 +0200 Subject: [PATCH 34/84] Update default net to nn-3c0054ea9860.nnu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit First things first... this PR is being made from court. Today, Tord and Stéphane, with broad support of the developer community are defending their complaint, filed in Munich, against ChessBase. With their products Houdini 6 and Fat Fritz 2, both Stockfish derivatives, ChessBase violated repeatedly the Stockfish GPLv3 license. Tord and Stéphane have terminated their license with ChessBase permanently. Today we have the opportunity to present our evidence to the judge and enforce that termination. To read up, have a look at our blog post https://stockfishchess.org/blog/2022/public-court-hearing-soon/ and https://stockfishchess.org/blog/2021/our-lawsuit-against-chessbase/ This PR introduces a net trained with an enhanced data set and a modified loss function in the trainer. A slight adjustment for the scaling was needed to get a pass on standard chess. passed STC: https://tests.stockfishchess.org/tests/view/62c0527a49b62510394bd610 LLR: 2.94 (-2.94,2.94) <0.00,2.50> Total: 135008 W: 36614 L: 36152 D: 62242 Ptnml(0-2): 640, 15184, 35407, 15620, 653 passed LTC: https://tests.stockfishchess.org/tests/view/62c17e459e7d9997a12d458e LLR: 2.94 (-2.94,2.94) <0.50,3.00> Total: 28864 W: 8007 L: 7749 D: 13108 Ptnml(0-2): 47, 2810, 8466, 3056, 53 Local testing at a fixed 25k nodes resulted in Test run1026/easy_train_data/experiments/experiment_2/training/run_0/nn-epoch799.nnue localElo: 4.2 +- 1.6 The real strength of the net is in FRC and DFRC chess where it gains significantly. Tested at STC with slightly different scaling: FRC: https://tests.stockfishchess.org/tests/view/62c13a4002ba5d0a774d20d4 Elo: 29.78 +-3.4 (95%) LOS: 100.0% Total: 10000 W: 2007 L: 1152 D: 6841 Ptnml(0-2): 31, 686, 2804, 1355, 124 nElo: 59.24 +-6.9 (95%) PairsRatio: 2.06 DFRC: https://tests.stockfishchess.org/tests/view/62c13a5702ba5d0a774d20d9 Elo: 55.25 +-3.9 (95%) LOS: 100.0% Total: 10000 W: 2984 L: 1407 D: 5609 Ptnml(0-2): 51, 636, 2266, 1779, 268 nElo: 96.95 +-7.2 (95%) PairsRatio: 2.98 Tested at LTC with identical scaling: FRC: https://tests.stockfishchess.org/tests/view/62c26a3c9e7d9997a12d6caf Elo: 16.20 +-2.5 (95%) LOS: 100.0% Total: 10000 W: 1192 L: 726 D: 8082 Ptnml(0-2): 10, 403, 3727, 831, 29 nElo: 44.12 +-6.7 (95%) PairsRatio: 2.08 DFRC: https://tests.stockfishchess.org/tests/view/62c26a539e7d9997a12d6cb2 Elo: 40.94 +-3.0 (95%) LOS: 100.0% Total: 10000 W: 2215 L: 1042 D: 6743 Ptnml(0-2): 10, 410, 3053, 1451, 76 nElo: 92.77 +-6.9 (95%) PairsRatio: 3.64 This is due to the mixing in a significant fraction of DFRC training data in the final training round. The net is trained using the easy_train.py script in the following way: ``` python easy_train.py \ --training-dataset=../Leela-dfrc_n5000.binpack \ --experiment-name=2 \ --nnue-pytorch-branch=vondele/nnue-pytorch/lossScan4 \ --additional-training-arg=--param-index=2 \ --start-lambda=1.0 \ --end-lambda=0.75 \ --gamma=0.995 \ --lr=4.375e-4 \ --start-from-engine-test-net True \ --tui=False \ --seed=$RANDOM \ --max_epoch=800 \ --auto-exit-timeout-on-training-finished=900 \ --network-testing-threads 8 \ --num-workers 12 ``` where the data set used (Leela-dfrc_n5000.binpack) is a combination of our previous best data set (mix of Leela and some SF data) and DFRC data, interleaved to form: The data is available in https://drive.google.com/drive/folders/1S9-ZiQa_3ApmjBtl2e8SyHxj4zG4V8gG?usp=sharing Leela mix: https://drive.google.com/file/d/1JUkMhHSfgIYCjfDNKZUMYZt6L5I7Ra6G/view?usp=sharing DFRC: https://drive.google.com/file/d/17vDaff9LAsVo_1OfsgWAIYqJtqR8aHlm/view?usp=sharing The training branch used is https://github.com/vondele/nnue-pytorch/commits/lossScan4 A PR to the main trainer repo will be made later. This contains a revised loss function, now computing the loss from the score based on the win rate model, which is a more accurate representation than what we had before. Scaling constants are tweaked there as well. closes https://github.com/official-stockfish/Stockfish/pull/4100 Bench: 5186781 --- src/evaluate.cpp | 2 +- src/evaluate.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 6d2e8da8..53613794 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -1102,7 +1102,7 @@ Value Eval::evaluate(const Position& pos, int* complexity) { if (useNNUE && !useClassical) { int nnueComplexity; - int scale = 1092 + 106 * pos.non_pawn_material() / 5120; + int scale = 1064 + 106 * pos.non_pawn_material() / 5120; Value optimism = pos.this_thread()->optimism[stm]; Value nnue = NNUE::evaluate(pos, true, &nnueComplexity); diff --git a/src/evaluate.h b/src/evaluate.h index e25bd52e..36d3b2b2 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -39,7 +39,7 @@ namespace Eval { // The default net name MUST follow the format nn-[SHA256 first 12 digits].nnue // for the build process (profile-build and fishtest) to work. Do not change the // name of the macro, as it is used in the Makefile. - #define EvalFileDefaultName "nn-3c0aa92af1da.nnue" + #define EvalFileDefaultName "nn-3c0054ea9860.nnue" namespace NNUE { From c2aaaa65f97d4cd5fc06f19ce8d158d85dcd7a7b Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Tue, 5 Jul 2022 14:15:34 +0300 Subject: [PATCH 35/84] Simplify away FRC correction term Since new net is trained partially using FRC data this part of adjustment that penalises bishops that are locked in the corner is no longer needed - net should "know" this things itself much better. STC on FRC book : https://tests.stockfishchess.org/tests/view/62c3031b9e7d9997a12d852f LLR: 2.96 (-2.94,2.94) <-2.25,0.25> Total: 22048 W: 3003 L: 2845 D: 16200 Ptnml(0-2): 96, 1778, 7149, 1874, 127 LTC on FRC book : https://tests.stockfishchess.org/tests/view/62c32e939e7d9997a12d8c5e LLR: 2.94 (-2.94,2.94) <-2.25,0.25> Total: 36784 W: 3138 L: 3037 D: 30609 Ptnml(0-2): 36, 1842, 14537, 1939, 38 STC on DFRC book : https://tests.stockfishchess.org/tests/view/62c32efb9e7d9997a12d8c6f LLR: 2.94 (-2.94,2.94) <-2.25,0.25> Total: 20424 W: 3903 L: 3721 D: 12800 Ptnml(0-2): 172, 1984, 5724, 2154, 178 LTC on DFRC book : https://tests.stockfishchess.org/tests/view/62c358c79e7d9997a12d9319 LLR: 2.93 (-2.94,2.94) <-2.25,0.25> Total: 53784 W: 7581 L: 7480 D: 38723 Ptnml(0-2): 87, 3887, 18856, 3962, 100 closes https://github.com/official-stockfish/Stockfish/pull/4101 bench 5182295 --- src/evaluate.cpp | 35 ----------------------------------- 1 file changed, 35 deletions(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 53613794..d340d3d5 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -1042,38 +1042,6 @@ make_v: return v; } - - /// Fisher Random Chess: correction for cornered bishops, to fix chess960 play with NNUE - - Value fix_FRC(const Position& pos) { - - constexpr Bitboard Corners = 1ULL << SQ_A1 | 1ULL << SQ_H1 | 1ULL << SQ_A8 | 1ULL << SQ_H8; - - if (!(pos.pieces(BISHOP) & Corners)) - return VALUE_ZERO; - - int correction = 0; - - if ( pos.piece_on(SQ_A1) == W_BISHOP - && pos.piece_on(SQ_B2) == W_PAWN) - correction -= CorneredBishop; - - if ( pos.piece_on(SQ_H1) == W_BISHOP - && pos.piece_on(SQ_G2) == W_PAWN) - correction -= CorneredBishop; - - if ( pos.piece_on(SQ_A8) == B_BISHOP - && pos.piece_on(SQ_B7) == B_PAWN) - correction += CorneredBishop; - - if ( pos.piece_on(SQ_H8) == B_BISHOP - && pos.piece_on(SQ_G7) == B_PAWN) - correction += CorneredBishop; - - return pos.side_to_move() == WHITE ? Value(3 * correction) - : -Value(3 * correction); - } - } // namespace Eval @@ -1113,9 +1081,6 @@ Value Eval::evaluate(const Position& pos, int* complexity) { optimism = optimism * (269 + nnueComplexity) / 256; v = (nnue * scale + optimism * (scale - 754)) / 1024; - - if (pos.is_chess960()) - v += fix_FRC(pos); } // Damp down the evaluation linearly when shuffling From aa18b68033403ee2d8d49df783cab32e6bccf59c Mon Sep 17 00:00:00 2001 From: Dubslow Date: Fri, 1 Jul 2022 11:53:16 -0500 Subject: [PATCH 36/84] Time mgmt fix division. oversight changed the corresponding float division to integer division in a previous tune https://github.com/official-stockfish/Stockfish/commit/442c40b43de8ede1e424efa674c8d45322e3b43c it is stronger to keep the original float division. green LTC: https://tests.stockfishchess.org/tests/view/62bf34bc0340fb1e0cc934e7 LLR: 2.94 (-2.94,2.94) <0.50,3.00> Total: 38952 W: 10738 L: 10467 D: 17747 Ptnml(0-2): 46, 3576, 11968, 3833, 53 yellow STC: https://tests.stockfishchess.org/tests/view/62bff6506178ffe6394ba1d1 LLR: -2.95 (-2.94,2.94) <0.00,2.50> Total: 226960 W: 61265 L: 61062 D: 104633 Ptnml(0-2): 938, 24398, 62582, 24647, 915 further slightly tweaked tests confirm this Elo gain. closes https://github.com/official-stockfish/Stockfish/pull/4097 No functional change --- src/search.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index f11d76be..07f18a34 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -472,7 +472,7 @@ void Thread::search() { double reduction = (1.56 + mainThread->previousTimeReduction) / (2.20 * timeReduction); double bestMoveInstability = 1 + 1.7 * totBestMoveChanges / Threads.size(); int complexity = mainThread->complexityAverage.value(); - double complexPosition = std::clamp(1.0 + (complexity - 277) / 1819, 0.5, 1.5); + double complexPosition = std::clamp(1.0 + (complexity - 277) / 1819.1, 0.5, 1.5); double totalTime = Time.optimum() * fallingEval * reduction * bestMoveInstability * complexPosition; From 2e02dd79366e6f17df5b0599048937289fd5819e Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Sat, 2 Jul 2022 08:55:05 +0200 Subject: [PATCH 37/84] Limit the researching at same depth. If the elapsed time is close to the available time, the time management thread can signal that the next iterations should be searched at the same depth (Threads.increaseDepth = false). While the rootDepth increases, the adjustedDepth is kept constant with the searchAgainCounter. In exceptional cases, when threading is used and the master thread, which controls the time management, signals to not increaseDepth, but by itself takes a long time to finish the iteration, the helper threads can search repeatedly at the same depth. This search finishes more and more quickly, leading to helper threads that report a rootDepth of MAX_DEPTH (245). The latter is not optimal as it is confusing for the user, stops search on these threads, and leads to an incorrect bias in the thread voting scheme. Probably with only a small impact on strength. This behavior was observed almost two years ago, see https://github.com/official-stockfish/Stockfish/issues/2717 This patch fixes #2717 by ensuring the effective depth increases at once every four iterations, even in increaseDepth is false. Depth 245 searches (for non-trivial positions) were indeed absent with this patch, but frequent with master in the tests below: https://discord.com/channels/435943710472011776/813919248455827515/994872720800088095 Total pgns: 2173 Base: 2867 Patch: 0 it passed non-regression testing in various setups: SMP STC: https://tests.stockfishchess.org/tests/view/62bfecc96178ffe6394ba036 LLR: 2.94 (-2.94,2.94) <-2.25,0.25> Total: 37288 W: 10171 L: 10029 D: 17088 Ptnml(0-2): 75, 3777, 10793, 3929, 70 SMP LTC: https://tests.stockfishchess.org/tests/view/62c08f6f49b62510394be066 LLR: 2.94 (-2.94,2.94) <-2.25,0.25> Total: 190568 W: 52125 L: 52186 D: 86257 Ptnml(0-2): 70, 17854, 59504, 17779, 77 LTC: https://tests.stockfishchess.org/tests/view/62c08b6049b62510394bdfb6 LLR: 2.96 (-2.94,2.94) <-2.25,0.25> Total: 48120 W: 13204 L: 13083 D: 21833 Ptnml(0-2): 54, 4458, 14919, 4571, 58 Special thanks to miguel-I, Disservin, ruicoelhopedro and others for analysing the problem, the data, and coming up with the key insight, needed to fix this longstanding issue. closes https://github.com/official-stockfish/Stockfish/pull/4104 Bench: 5182295 --- src/search.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index 07f18a34..ca1d2632 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -373,7 +373,9 @@ void Thread::search() { int failedHighCnt = 0; while (true) { - Depth adjustedDepth = std::max(1, rootDepth - failedHighCnt - searchAgainCounter); + // Adjust the effective depth searched, but ensuring at least one effective increment for every + // four searchAgain steps (see issue #2717). + Depth adjustedDepth = std::max(1, rootDepth - failedHighCnt - 3 * (searchAgainCounter + 1) / 4); bestValue = Stockfish::search(rootPos, ss, alpha, beta, adjustedDepth, false); // Bring the best move to the front. It is critical that sorting From 95d24b77dfe8a147100d9753c5580563c3e642d2 Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Wed, 13 Jul 2022 11:59:54 +0300 Subject: [PATCH 38/84] Simplify away some unneeded code in time management The lower bound of the clamp is never used since complexity can't be negative and thus is unneeded. closes https://github.com/official-stockfish/Stockfish/pull/4105 No functional change --- src/search.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index ca1d2632..c5c7f111 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -474,7 +474,7 @@ void Thread::search() { double reduction = (1.56 + mainThread->previousTimeReduction) / (2.20 * timeReduction); double bestMoveInstability = 1 + 1.7 * totBestMoveChanges / Threads.size(); int complexity = mainThread->complexityAverage.value(); - double complexPosition = std::clamp(1.0 + (complexity - 277) / 1819.1, 0.5, 1.5); + double complexPosition = std::min(1.0 + (complexity - 277) / 1819.1, 1.5); double totalTime = Time.optimum() * fallingEval * reduction * bestMoveInstability * complexPosition; From 4b4b7d1209259811537634c68555d2a8f4af197c Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Mon, 11 Jul 2022 17:32:39 +0200 Subject: [PATCH 39/84] Update default net to nn-ad9b42354671.nnue using trainer branch https://github.com/glinscott/nnue-pytorch/pull/208 with a slightly tweaked loss function (power 2.5 instead of 2.6), otherwise same training as in the previous net update https://github.com/official-stockfish/Stockfish/pull/4100 passed STC: LLR: 2.97 (-2.94,2.94) <0.00,2.50> Total: 367536 W: 99465 L: 98573 D: 169498 Ptnml(0-2): 1820, 40994, 97117, 42148, 1689 https://tests.stockfishchess.org/tests/view/62cc43fe50dcbecf5fc1c5b8 passed LTC: LLR: 2.94 (-2.94,2.94) <0.50,3.00> Total: 25032 W: 6802 L: 6553 D: 11677 Ptnml(0-2): 40, 2424, 7341, 2669, 42 https://tests.stockfishchess.org/tests/view/62ce5f421dacb46e4d5fd277 closes https://github.com/official-stockfish/Stockfish/pull/4107 Bench: 5905619 --- src/evaluate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evaluate.h b/src/evaluate.h index 36d3b2b2..f5ac3263 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -39,7 +39,7 @@ namespace Eval { // The default net name MUST follow the format nn-[SHA256 first 12 digits].nnue // for the build process (profile-build and fishtest) to work. Do not change the // name of the macro, as it is used in the Makefile. - #define EvalFileDefaultName "nn-3c0054ea9860.nnue" + #define EvalFileDefaultName "nn-ad9b42354671.nnue" namespace NNUE { From c4a644922dc219aade86ea07c85e95899850fac8 Mon Sep 17 00:00:00 2001 From: Dubslow Date: Tue, 19 Jul 2022 01:09:30 -0500 Subject: [PATCH 40/84] Simplify reduction condition for cutNodes LMR: for cutNodes, dont exclude killer moves. This was a prelude to reducing allNodes, altho that's failed so far. STC https://tests.stockfishchess.org/tests/view/62d64ad147ae1768b34a27c3 LLR: 2.95 (-2.94,2.94) <-2.25,0.25> Total: 37064 W: 10044 L: 9889 D: 17131 Ptnml(0-2): 162, 4115, 9828, 4260, 167 LTC https://tests.stockfishchess.org/tests/view/62d66cc047ae1768b34a2b14 LLR: 2.94 (-2.94,2.94) <-2.25,0.25> Total: 39832 W: 10796 L: 10659 D: 18377 Ptnml(0-2): 69, 3969, 11706, 4100, 72 closes https://github.com/official-stockfish/Stockfish/pull/4109 bench: 5697891 --- src/search.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index c5c7f111..96b1d0f1 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1156,7 +1156,7 @@ moves_loop: // When in check, search starts here r--; // Increase reduction for cut nodes (~3 Elo) - if (cutNode && move != ss->killers[0]) + if (cutNode) r += 2; // Increase reduction if ttMove is a capture (~3 Elo) From 18389e269d43af69c96521f3fe9d85e6b7ed073c Mon Sep 17 00:00:00 2001 From: Dubslow Date: Tue, 26 Jul 2022 23:45:19 -0500 Subject: [PATCH 41/84] remove useClassical depth condition passed STC: https://tests.stockfishchess.org/tests/view/62e0c3e98e4fa6ae472695ed LLR: 2.96 (-2.94,2.94) <-2.25,0.25> Total: 293568 W: 78934 L: 79151 D: 135483 Ptnml(0-2): 1344, 31488, 81366, 31213, 1373 passed LTC: https://tests.stockfishchess.org/tests/view/62e190aa8e4fa6ae4726b5b5 LLR: 2.98 (-2.94,2.94) <-2.25,0.25> Total: 187392 W: 50971 L: 51028 D: 85393 Ptnml(0-2): 384, 17801, 57369, 17772, 370 other attempts to otherwise tune this parameter failed, bounds 6,7,10,11 failed STC, 8 passed STC but failed LTC closes https://github.com/official-stockfish/Stockfish/pull/4112 bench 5796377 --- src/evaluate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index d340d3d5..9e3eaba5 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -1055,7 +1055,7 @@ Value Eval::evaluate(const Position& pos, int* complexity) { Value psq = pos.psq_eg_stm(); // Deciding between classical and NNUE eval (~10 Elo): for high PSQ imbalance we use classical, // but we switch to NNUE during long shuffling or with high material on the board. - bool useClassical = (pos.this_thread()->depth > 9 || pos.count() > 7) + bool useClassical = (pos.count() > 7) && abs(psq) * 5 > (856 + pos.non_pawn_material() / 64) * (10 + pos.rule50_count()); // Deciding between classical and NNUE eval (~10 Elo): for high PSQ imbalance we use classical, From 582c88ee94c24b4352477ffacf8de2afc521bcce Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Sun, 31 Jul 2022 02:04:23 +0300 Subject: [PATCH 42/84] Do more TT cutoffs in case of exact bound The idea is that these TT entries are considered move valuable in TT replacement scheme - they are always overwriting other entries. So it makes sence for them to produce more aggressive cutoffs. passed STC https://tests.stockfishchess.org/tests/view/62e4d407b383a712b1385410 LLR: 2.95 (-2.94,2.94) <0.00,2.50> Total: 96632 W: 26045 L: 25659 D: 44928 Ptnml(0-2): 434, 10635, 25770, 11065, 412 passed LTC https://tests.stockfishchess.org/tests/view/62e523e2b383a712b1386193 LLR: 2.94 (-2.94,2.94) <0.50,3.00> Total: 77960 W: 21363 L: 20989 D: 35608 Ptnml(0-2): 190, 7591, 23009, 8035, 155 closes https://github.com/official-stockfish/Stockfish/pull/4114 bench 5820568 --- src/search.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index 96b1d0f1..004d061b 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -637,7 +637,7 @@ namespace { // At non-PV nodes we check for an early TT cutoff if ( !PvNode && ss->ttHit - && tte->depth() > depth - ((int)thisThread->id() & 0x1) + && tte->depth() > depth - ((int)thisThread->id() & 0x1) - (tte->bound() == BOUND_EXACT) && ttValue != VALUE_NONE // Possible in case of TT access race && (tte->bound() & (ttValue >= beta ? BOUND_LOWER : BOUND_UPPER))) { From 675f6a038ba98b6b906a4767f009cf6fe91b0c52 Mon Sep 17 00:00:00 2001 From: Stefan Geschwentner Date: Tue, 2 Aug 2022 23:14:14 +0200 Subject: [PATCH 43/84] Tweak history updates In general the history update bonus is slightly decreased by 11% which gives a slower saturation speed. In addition only for main history the divisor is halfed (used history values are doubled to maintain same maximum) which have an effect in the opposite direction on saturation speed. STC: LLR: 2.95 (-2.94,2.94) <0.00,2.50> Total: 157088 W: 42673 L: 42168 D: 72247 Ptnml(0-2): 857, 17346, 41642, 17833, 866 https://tests.stockfishchess.org/tests/view/62e5517ab383a712b13867c5 LTC: LLR: 2.94 (-2.94,2.94) <0.50,3.00> Total: 325592 W: 88705 L: 87753 D: 149134 Ptnml(0-2): 594, 32288, 96076, 33248, 590 https://tests.stockfishchess.org/tests/view/62e5e4f4b383a712b1387d53 closes https://github.com/official-stockfish/Stockfish/pull/4119 Bench: 5518728 --- src/movepick.cpp | 4 ++-- src/movepick.h | 2 +- src/search.cpp | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/movepick.cpp b/src/movepick.cpp index b0166c6e..60d041ab 100644 --- a/src/movepick.cpp +++ b/src/movepick.cpp @@ -137,7 +137,7 @@ void MovePicker::score() { + (*captureHistory)[pos.moved_piece(m)][to_sq(m)][type_of(pos.piece_on(to_sq(m)))]; else if constexpr (Type == QUIETS) - m.value = (*mainHistory)[pos.side_to_move()][from_to(m)] + m.value = 2 * (*mainHistory)[pos.side_to_move()][from_to(m)] + 2 * (*continuationHistory[0])[pos.moved_piece(m)][to_sq(m)] + (*continuationHistory[1])[pos.moved_piece(m)][to_sq(m)] + (*continuationHistory[3])[pos.moved_piece(m)][to_sq(m)] @@ -155,7 +155,7 @@ 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)] + m.value = 2 * (*mainHistory)[pos.side_to_move()][from_to(m)] + 2 * (*continuationHistory[0])[pos.moved_piece(m)][to_sq(m)] - (1 << 28); } diff --git a/src/movepick.h b/src/movepick.h index 6b3c08c7..979709ae 100644 --- a/src/movepick.h +++ b/src/movepick.h @@ -87,7 +87,7 @@ enum StatsType { NoCaptures, Captures }; /// ordering decisions. It uses 2 tables (one for each color) indexed by /// the move's from and to squares, see www.chessprogramming.org/Butterfly_Boards /// (~11 elo) -typedef Stats ButterflyHistory; +typedef Stats ButterflyHistory; /// CounterMoveHistory stores counter moves indexed by [piece][to] of the previous /// move, see www.chessprogramming.org/Countermove_Heuristic diff --git a/src/search.cpp b/src/search.cpp index 004d061b..9b747e78 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -81,7 +81,7 @@ namespace { // History and stats update bonus, based on depth int stat_bonus(Depth d) { - return std::min((9 * d + 270) * d - 311 , 2145); + return std::min((8 * d + 240) * d - 276 , 1907); } // Add a small random component to draw evaluations to avoid 3-fold blindness @@ -1033,7 +1033,7 @@ moves_loop: // When in check, search starts here && history < -3875 * (depth - 1)) continue; - history += thisThread->mainHistory[us][from_to(move)]; + history += 2 * thisThread->mainHistory[us][from_to(move)]; // Futility pruning: parent node (~9 Elo) if ( !ss->inCheck @@ -1171,7 +1171,7 @@ moves_loop: // When in check, search starts here if ((ss+1)->cutoffCnt > 3 && !PvNode) r++; - ss->statScore = thisThread->mainHistory[us][from_to(move)] + ss->statScore = 2 * thisThread->mainHistory[us][from_to(move)] + (*contHist[0])[movedPiece][to_sq(move)] + (*contHist[1])[movedPiece][to_sq(move)] + (*contHist[3])[movedPiece][to_sq(move)] From b8f4903fbb8ac9be8d26cef30848b3a9527c8725 Mon Sep 17 00:00:00 2001 From: lonfom169 Date: Wed, 3 Aug 2022 12:43:21 -0300 Subject: [PATCH 44/84] Reintroduce singularQuietLMR STC: LLR: 2.96 (-2.94,2.94) <0.00,2.00> Total: 88912 W: 23972 L: 23580 D: 41360 Ptnml(0-2): 365, 9820, 23712, 10176, 383 https://tests.stockfishchess.org/tests/view/62e9537a400addce2c13399b LTC: LLR: 2.97 (-2.94,2.94) <0.50,2.50> Total: 85672 W: 23607 L: 23192 D: 38873 Ptnml(0-2): 219, 8316, 25365, 8703, 233 https://tests.stockfishchess.org/tests/view/62e9a174400addce2c1346e4 closes https://github.com/official-stockfish/Stockfish/pull/4122 Bench: 5921315 --- src/search.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 9b747e78..7c0601e6 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -558,7 +558,7 @@ namespace { Move ttMove, move, excludedMove, bestMove; Depth extension, newDepth; Value bestValue, value, ttValue, eval, maxValue, probCutBeta; - bool givesCheck, improving, didLMR, priorCapture; + bool givesCheck, improving, didLMR, priorCapture, singularQuietLMR; bool capture, doFullDepthSearch, moveCountPruning, ttCapture; Piece movedPiece; int moveCount, captureCount, quietCount, improvement, complexity; @@ -945,7 +945,7 @@ moves_loop: // When in check, search starts here ss->killers); value = bestValue; - moveCountPruning = false; + moveCountPruning = singularQuietLMR = false; // Indicate PvNodes that will probably fail low if the node was searched // at a depth equal or greater than the current depth, and the result of this search was a fail low. @@ -1075,6 +1075,7 @@ moves_loop: // When in check, search starts here if (value < singularBeta) { extension = 1; + singularQuietLMR = !ttCapture; // Avoid search explosion by limiting the number of double extensions if ( !PvNode @@ -1167,6 +1168,10 @@ moves_loop: // When in check, search starts here if (PvNode) r -= 1 + 15 / (3 + depth); + // Decrease reduction if ttMove has been singularly extended (~1 Elo) + if (singularQuietLMR) + r--; + // Increase reduction if next ply has a lot of fail high else reset count to 0 if ((ss+1)->cutoffCnt > 3 && !PvNode) r++; From 7cc929f437f56396ce151c4d8095e24f3d957bd9 Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Sun, 31 Jul 2022 15:04:23 +0200 Subject: [PATCH 45/84] Update CPU contributors list Thanks for your contributions! closes https://github.com/official-stockfish/Stockfish/pull/4116 No functional change --- Top CPU Contributors.txt | 148 +++++++++++++++++++++------------------ 1 file changed, 79 insertions(+), 69 deletions(-) diff --git a/Top CPU Contributors.txt b/Top CPU Contributors.txt index 76aa01e9..23a5d7f9 100644 --- a/Top CPU Contributors.txt +++ b/Top CPU Contributors.txt @@ -1,96 +1,102 @@ -Contributors to Fishtest with >10,000 CPU hours, as of 2022-04-14. +Contributors to Fishtest with >10,000 CPU hours, as of 2022-07-31. Thank you! Username CPU Hours Games played ------------------------------------------------------------------ -noobpwnftw 31714850 2267266129 -mlang 2954099 198421098 -technologov 2324150 102449398 -dew 1670874 99276012 -grandphish2 1134273 68070459 -okrout 901194 77738874 -TueRens 821388 50207666 +noobpwnftw 33202707 2423743815 +technologov 5064327 270208248 +mlang 2963357 198937430 +dew 1677196 99717674 +grandphish2 1231326 74551309 +okrout 1102747 98977462 +TueRens 925904 57404676 +pemo 911980 35581261 tvijlbrief 795993 51894442 -pemo 744463 32486677 -JojoM 724378 43660674 +JojoM 774270 47311084 mibere 703840 46867607 -linrock 626939 17408017 -gvreuls 534079 34352532 -cw 507221 34006775 -fastgm 489749 29344518 +linrock 697283 18804969 +gvreuls 564284 36392236 +cw 515739 34775505 +fastgm 500949 30101898 +oz 439015 31794460 +CSU_Dynasty 438017 29369136 crunchy 427035 27344275 -CSU_Dynasty 424643 28525220 -ctoks 415771 27364603 -oz 369200 27017658 -bcross 342642 23671289 +ctoks 422671 27812261 +bcross 363335 25108521 +leszek 360149 22674005 +velislav 333325 21444360 Fisherman 327231 21829379 -velislav 325670 20911076 -leszek 321295 19874113 -Dantist 274747 16910258 -mgrabiak 237604 15418700 -robal 217959 13840386 +Dantist 292327 17951982 +mgrabiak 247220 16137378 +nordlandia 226543 14601042 +robal 224740 14314972 glinscott 217799 13780820 -nordlandia 211692 13484886 -drabel 201967 13798360 +ncfish1 207751 13909639 +drabel 203884 13922680 +mhoram 200022 12533963 bking_US 198894 11876016 -mhoram 194862 12261809 +rpngn 191764 12236583 Thanar 179852 12365359 vdv 175544 9904472 spams 157128 10319326 -rpngn 154081 9652139 marrco 150300 9402229 sqrt2 147963 9724586 -vdbergh 137430 8955097 +vdbergh 137480 8958795 CoffeeOne 137100 5024116 malala 136182 8002293 xoto 133759 9159372 -davar 125240 8117121 +davar 128645 8367253 +DesolatedDodo 124877 8056482 dsmith 122059 7570238 -amicic 119659 7937885 +amicic 119661 7938029 Data 113305 8220352 BrunoBanani 112960 7436849 CypressChess 108321 7759588 -DesolatedDodo 106811 6776980 MaZePallas 102823 6633619 +skiminki 102168 6778440 sterni1971 100532 5880772 sunu 100167 7040199 ElbertoOne 99028 7023771 -skiminki 98123 6478402 +zeryl 96984 6162287 brabos 92118 6186135 -cuistot 90358 5351004 +cuistot 91738 5447070 psk 89957 5984901 racerschmacer 85712 6119648 Vizvezdenec 83761 5344740 -zeryl 83680 5250995 sschnee 83003 4840890 0x3C33 82614 5271253 +armo9494 82501 5806056 BRAVONE 81239 5054681 nssy 76497 5259388 +thirdlife 76478 1544524 +Calis007 76457 4281018 +jromang 75885 5230523 teddybaer 75125 5407666 -jromang 74796 5175825 Pking_cda 73776 5293873 -Calis007 72477 4088576 +Wolfgang 72750 4538670 +sebastronomy 70784 1329428 solarlight 70517 5028306 dv8silencer 70287 3883992 Bobo1239 68515 4652287 +yurikvelo 67651 4578970 manap 66273 4121774 -yurikvelo 65716 4457300 tinker 64333 4268790 -Wolfgang 62644 3817410 qurashee 61208 3429862 robnjr 57262 4053117 +megaman7de 57023 3525850 Freja 56938 3733019 +MaxKlaxxMiner 56279 3410158 ttruscott 56010 3680085 rkl 55132 4164467 renouve 53811 3501516 -megaman7de 52434 3243016 -MaxKlaxxMiner 51977 3153032 +tolkki963 53294 3354682 +DMBK 52963 3933332 finfish 51360 3370515 eva42 51272 3599691 +Spprtr 51139 3299983 eastorwest 51058 3451555 rap 49985 3219146 pb00067 49727 3298270 -Spprtr 48920 3161711 bigpen0r 47667 3336927 ronaldjerum 47654 3240695 biffhero 46564 3111352 @@ -102,18 +108,17 @@ Antihistamine 41788 2761312 mhunt 41735 2691355 homyur 39893 2850481 gri 39871 2515779 -armo9494 39064 2832326 -oryx 38867 2976992 +oryx 39602 3024830 SC 37299 2731694 Garf 37213 2986270 -tolkki963 37059 2154330 +Dubslow 36714 2409254 csnodgrass 36207 2688994 jmdana 36157 2210661 +markkulix 35994 2226860 strelock 34716 2074055 -DMBK 34010 2482916 EthanOConnor 33370 2090311 slakovv 32915 2021889 -gopeto 30993 2028106 +gopeto 31078 2033362 manapbk 30987 1810399 Prcuvu 30377 2170122 anst 30301 2190091 @@ -121,7 +126,8 @@ jkiiski 30136 1904470 hyperbolic.tom 29840 2017394 chuckstablers 29659 2093438 Pyafue 29650 1902349 -ncfish1 29105 1704011 +MarcusTullius 28611 1646671 +spcc 28241 1821198 belzedar94 27935 1789106 OuaisBla 27636 1578800 chriswk 26902 1868317 @@ -131,14 +137,16 @@ yorkman 26193 1992080 SFTUser 25182 1675689 nabildanial 24942 1519409 Sharaf_DG 24765 1786697 -rodneyc 24275 1410450 +rodneyc 24375 1416258 +Ulysses 24017 1626140 agg177 23890 1395014 JanErik 23408 1703875 +Ente 23403 1660988 +kdave 23392 1630462 Isidor 23388 1680691 Norabor 23339 1602636 -Ente 23270 1651432 cisco2015 22897 1762669 -MarcusTullius 22688 1274821 +Wencey 22573 1121406 Zirie 22542 1472937 team-oh 22272 1636708 MazeOfGalious 21978 1629593 @@ -150,19 +158,16 @@ nesoneg 21494 1463031 Roady 21323 1433822 sphinx 21211 1384728 user213718 21196 1397710 -spcc 21065 1311338 jjoshua2 21001 1423089 horst.prack 20878 1465656 0xB00B1ES 20590 1208666 j3corre 20405 941444 -kdave 20364 1389254 Adrian.Schmidt123 20316 1281436 -Ulysses 20217 1351500 -markkulix 19976 1115258 +jcAEie 20221 1504162 wei 19973 1745989 rstoesser 19569 1293588 eudhan 19274 1283717 -fishtester 18995 1238686 +fishtester 19145 1242668 vulcan 18871 1729392 jundery 18445 1115855 iisiraider 18247 1101015 @@ -170,29 +175,31 @@ ville 17883 1384026 chris 17698 1487385 purplefishies 17595 1092533 dju 17353 978595 -Wencey 17125 805964 +AndreasKrug 17191 1317997 DragonLord 17014 1162790 -thirdlife 16996 447356 +Jopo12321 16966 944924 +GPUex 16744 1077826 +xwziegtm 16608 1276372 IgorLeMasson 16064 1147232 ako027ako 15671 1173203 -AndreasKrug 15550 1194497 +jsys14 15474 917092 Nikolay.IT 15154 1068349 Andrew Grant 15114 895539 -scuzzi 14928 953313 +scuzzi 15112 960373 OssumOpossum 14857 1007129 Karby 14808 867120 -jsys14 14652 855642 enedene 14476 905279 bpfliegel 14298 884523 mpx86 14019 759568 jpulman 13982 870599 +Naven94 13879 811552 +Karpovbot 13808 734276 crocogoat 13803 1117422 joster 13794 950160 Nesa92 13786 1114691 mbeier 13650 1044928 Hjax 13535 915487 Dark_wizzie 13422 1007152 -Jopo12321 13367 678852 Rudolphous 13244 883140 Machariel 13010 863104 mabichito 12903 749391 @@ -200,36 +207,39 @@ thijsk 12886 722107 AdrianSA 12860 804972 infinigon 12807 937332 Flopzee 12698 894821 +pirt 12551 965597 fatmurphy 12547 853210 SapphireBrand 12416 969604 modolief 12386 896470 Farseer 12249 694108 pgontarz 12151 848794 -pirt 12008 923149 stocky 11954 699440 mschmidt 11941 803401 +Oakwen 11925 818865 +MooTheCow 11851 772628 +deflectooor 11642 565132 dbernier 11609 818636 +Skiff84 11604 602786 Maxim 11543 836024 infinity 11470 727027 +FormazChar 11430 856559 aga 11409 695071 +Jackfish 11403 750526 torbjo 11395 729145 Thomas A. Anderson 11372 732094 savage84 11358 670860 -FormazChar 11349 850327 d64 11263 789184 -MooTheCow 11237 720174 +qoo_charly_cai 11127 671959 snicolet 11106 869170 ali-al-zhrani 11098 768494 whelanh 11067 235676 -Jackfish 10978 720078 -deflectooor 10886 520116 basepi 10637 744851 Cubox 10621 826448 +Alb11747 10558 689794 michaelrpg 10509 739239 OIVAS7572 10420 995586 +Garruk 10343 704723 dzjp 10343 732529 -Garruk 10334 704065 ols 10259 570669 lbraesch 10252 647825 -qoo_charly_cai 10212 620407 -Naven94 10069 503192 +Karmatron 10195 661432 From e639c4557786513018f625ff96f04b63157a85c1 Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Sun, 31 Jul 2022 14:58:13 +0200 Subject: [PATCH 46/84] Update WDL model for current SF This updates the WDL model based on the LTC statistics for the two weeks (3M games). for old results see: https://github.com/official-stockfish/Stockfish/pull/3981 https://github.com/official-stockfish/Stockfish/pull/3582 https://github.com/official-stockfish/Stockfish/pull/2778 closes https://github.com/official-stockfish/Stockfish/pull/4115 No functional change. --- src/uci.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/uci.cpp b/src/uci.cpp index c0bacfaf..ec106ee9 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -207,8 +207,8 @@ namespace { // The coefficients of a third-order polynomial fit is based on the fishtest data // for two parameters that need to transform eval to the argument of a logistic // function. - double as[] = {-1.17202460e-01, 5.94729104e-01, 1.12065546e+01, 1.22606222e+02}; - double bs[] = {-1.79066759, 11.30759193, -17.43677612, 36.47147479}; + double as[] = { 0.50379905, -4.12755858, 18.95487051, 152.00733652}; + double bs[] = {-1.71790378, 10.71543602, -17.05515898, 41.15680404}; 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]; From 0a01dd044f8a8f291127ebf60462773bf12c90c7 Mon Sep 17 00:00:00 2001 From: Stefan Geschwentner Date: Tue, 9 Aug 2022 20:56:13 +0200 Subject: [PATCH 47/84] Cleanup code This PR includes following cleanups: - Remove the unused depth variable in the thread class. - cleanup ValueList (added from mstembera) closes https://github.com/official-stockfish/Stockfish/pull/4127 No functional change. --- src/evaluate.cpp | 1 - src/misc.h | 13 ------------- src/position.cpp | 6 ++++-- src/search.cpp | 1 - src/thread.h | 2 +- 5 files changed, 5 insertions(+), 18 deletions(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 9e3eaba5..7d587675 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -1114,7 +1114,6 @@ std::string Eval::trace(Position& pos) { std::memset(scores, 0, sizeof(scores)); // Reset any global variable used in eval - pos.this_thread()->depth = 0; pos.this_thread()->trend = SCORE_ZERO; pos.this_thread()->bestValue = VALUE_ZERO; pos.this_thread()->optimism[WHITE] = VALUE_ZERO; diff --git a/src/misc.h b/src/misc.h index 2fd2b408..fe1143de 100644 --- a/src/misc.h +++ b/src/misc.h @@ -116,23 +116,10 @@ class ValueList { public: std::size_t size() const { return size_; } - void resize(std::size_t newSize) { size_ = newSize; } void push_back(const T& value) { values_[size_++] = value; } - T& operator[](std::size_t index) { return values_[index]; } - T* begin() { return values_; } - T* end() { return values_ + size_; } - const T& operator[](std::size_t index) const { return values_[index]; } const T* begin() const { return values_; } const T* end() const { return values_ + size_; } - void swap(ValueList& other) { - const std::size_t maxSize = std::max(size_, other.size_); - for (std::size_t i = 0; i < maxSize; ++i) { - std::swap(values_[i], other.values_[i]); - } - std::swap(size_, other.size_); - } - private: T values_[MaxSize]; std::size_t size_ = 0; diff --git a/src/position.cpp b/src/position.cpp index ec9229ea..08ed1a89 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -1099,10 +1099,12 @@ bool Position::see_ge(Move m, Value threshold) const { // Don't allow pinned pieces to attack as long as there are // pinners on their original square. if (pinners(~stm) & occupied) + { stmAttackers &= ~blockers_for_king(stm); - if (!stmAttackers) - break; + if (!stmAttackers) + break; + } res ^= 1; diff --git a/src/search.cpp b/src/search.cpp index 7c0601e6..565fba0f 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -565,7 +565,6 @@ namespace { // Step 1. Initialize node Thread* thisThread = pos.this_thread(); - thisThread->depth = depth; ss->inCheck = pos.checkers(); priorCapture = pos.captured_piece(); Color us = pos.side_to_move(); diff --git a/src/thread.h b/src/thread.h index 9e9cd488..c430a818 100644 --- a/src/thread.h +++ b/src/thread.h @@ -69,7 +69,7 @@ public: Position rootPos; StateInfo rootState; Search::RootMoves rootMoves; - Depth rootDepth, completedDepth, depth, previousDepth; + Depth rootDepth, completedDepth, previousDepth; Value rootDelta; CounterMoveHistory counterMoves; ButterflyHistory mainHistory; From 1054a483ca0c560d30fb61617c0192cb4cd31528 Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Sun, 31 Jul 2022 16:55:07 +0200 Subject: [PATCH 48/84] Remove an unneeded randomization of evals. most of the effect comes from the randomization of 3-folds. passed STC: https://tests.stockfishchess.org/tests/view/62e697e97e84186e5d19af6f LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 572976 W: 153168 L: 153539 D: 266269 Ptnml(0-2): 2505, 64783, 152364, 64250, 2586 passed LTC: https://tests.stockfishchess.org/tests/view/62ee5977523c86dcd6957154 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 704808 W: 191212 L: 191680 D: 321916 Ptnml(0-2): 1340, 70579, 208972, 70235, 1278 closes https://github.com/official-stockfish/Stockfish/pull/4128 Bench: 5868987 --- src/search.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 565fba0f..4d56d14d 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -741,10 +741,6 @@ namespace { else // Fall back to (semi)classical complexity for TT hits, the NNUE complexity is lost complexity = abs(ss->staticEval - pos.psq_eg_stm()); - // Randomize draw evaluation - if (eval == VALUE_DRAW) - eval = value_draw(thisThread); - // ttValue can be used as a better position evaluation (~4 Elo) if ( ttValue != VALUE_NONE && (tte->bound() & (ttValue > eval ? BOUND_LOWER : BOUND_UPPER))) From 4568f6369bfb94d8a105a8074e43e8d79c57eaee Mon Sep 17 00:00:00 2001 From: mstembera Date: Mon, 8 Aug 2022 21:33:59 -0700 Subject: [PATCH 49/84] Report longest PV lines for multithreaded search In case several threads find the same bestmove, report the longest PV line found. closes https://github.com/official-stockfish/Stockfish/pull/4126 No functional change. --- src/thread.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/thread.cpp b/src/thread.cpp index 08a78db5..c834fa9f 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -237,7 +237,9 @@ Thread* ThreadPool::get_best_thread() const { } 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]])) + && ( votes[th->rootMoves[0].pv[0]] > votes[bestThread->rootMoves[0].pv[0]] + || ( votes[th->rootMoves[0].pv[0]] == votes[bestThread->rootMoves[0].pv[0]] + && th->rootMoves[0].pv.size() > bestThread->rootMoves[0].pv.size())))) bestThread = th; } From 3370f69881564025d933668ea5d407af0c5dcea2 Mon Sep 17 00:00:00 2001 From: mckx00 Date: Sat, 13 Aug 2022 05:32:30 -0700 Subject: [PATCH 50/84] Make LMR code easier to follow Remove flags doFullDepthSearch and didLMR, and reorder instruction. Small measured speedup. Closes https://github.com/official-stockfish/Stockfish/pull/4129 No functional change. --- src/search.cpp | 35 +++++++++++++---------------------- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 4d56d14d..7244b8d6 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -558,8 +558,8 @@ namespace { Move ttMove, move, excludedMove, bestMove; Depth extension, newDepth; Value bestValue, value, ttValue, eval, maxValue, probCutBeta; - bool givesCheck, improving, didLMR, priorCapture, singularQuietLMR; - bool capture, doFullDepthSearch, moveCountPruning, ttCapture; + bool givesCheck, improving, priorCapture, singularQuietLMR; + bool capture, moveCountPruning, ttCapture; Piece movedPiece; int moveCount, captureCount, quietCount, improvement, complexity; @@ -1127,8 +1127,6 @@ moves_loop: // When in check, search starts here // Step 16. Make the move pos.do_move(move, st, givesCheck); - bool doDeeperSearch = false; - // Step 17. Late moves reduction / extension (LMR, ~98 Elo) // We use various heuristics for the sons of a node after the first son has // been searched. In general we would like to reduce them, but there are many @@ -1187,25 +1185,12 @@ moves_loop: // When in check, search starts here value = -search(pos, ss+1, -(alpha+1), -alpha, d, true); - // If the son is reduced and fails high it will be re-searched at full depth - doFullDepthSearch = value > alpha && d < newDepth; - doDeeperSearch = value > (alpha + 78 + 11 * (newDepth - d)); - didLMR = true; - } - else - { - doFullDepthSearch = !PvNode || moveCount > 1; - didLMR = false; - } - - // Step 18. Full depth search when LMR is skipped or fails high - if (doFullDepthSearch) - { - value = -search(pos, ss+1, -(alpha+1), -alpha, newDepth + doDeeperSearch, !cutNode); - - // If the move passed LMR update its stats - if (didLMR) + // Do full depth search when reduced LMR search fails high + if (value > alpha && d < newDepth) { + const bool doDeeperSearch = value > (alpha + 78 + 11 * (newDepth - d)); + value = -search(pos, ss+1, -(alpha+1), -alpha, newDepth + doDeeperSearch, !cutNode); + int bonus = value > alpha ? stat_bonus(newDepth) : -stat_bonus(newDepth); @@ -1216,6 +1201,12 @@ moves_loop: // When in check, search starts here } } + // Step 18. Full depth search when LMR is skipped + else if (!PvNode || moveCount > 1) + { + value = -search(pos, ss+1, -(alpha+1), -alpha, newDepth, !cutNode); + } + // For PV nodes only, do a full PV search on the first move or after a fail // high (in the latter case search only if value < beta), otherwise let the // parent node fail low with value <= alpha and try another move. From 5f290352cd91beb9374671f6ae489165bd8ac2c0 Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Mon, 15 Aug 2022 08:52:55 +0300 Subject: [PATCH 51/84] Simplify away smp adjustment in TT use Passed STC https://tests.stockfishchess.org/tests/view/62f7d81f23d42b50a8dab568 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 98160 W: 26307 L: 26165 D: 45688 Ptnml(0-2): 201, 10282, 27960, 10448, 189 Passed LTC https://tests.stockfishchess.org/tests/view/62f8d1a623d42b50a8dad4fb LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 81544 W: 22346 L: 22200 D: 36998 Ptnml(0-2): 44, 7542, 25446, 7704, 36 closes https://github.com/official-stockfish/Stockfish/pull/4131 No functional change (single threaded). --- src/search.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index 7244b8d6..6d78403f 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -636,7 +636,7 @@ namespace { // At non-PV nodes we check for an early TT cutoff if ( !PvNode && ss->ttHit - && tte->depth() > depth - ((int)thisThread->id() & 0x1) - (tte->bound() == BOUND_EXACT) + && tte->depth() > depth - (tte->bound() == BOUND_EXACT) && ttValue != VALUE_NONE // Possible in case of TT access race && (tte->bound() & (ttValue >= beta ? BOUND_LOWER : BOUND_UPPER))) { From 15ac117ac492e3147b391aa0ee3665fe8876be63 Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Fri, 12 Aug 2022 12:31:49 +0200 Subject: [PATCH 52/84] Simplify the use of classical eval no benefit of the fallback term (exercised rarely). Cleanup the associated code. passed STC https://tests.stockfishchess.org/tests/view/62f62c2b6f0a08af9f776367 LLR: 2.96 (-2.94,2.94) <-1.75,0.25> Total: 67832 W: 18334 L: 18148 D: 31350 Ptnml(0-2): 369, 7171, 18609, 7439, 328 passed LTC https://tests.stockfishchess.org/tests/view/62f68beb6f0a08af9f77710e LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 104664 W: 28363 L: 28233 D: 48068 Ptnml(0-2): 169, 10162, 31511, 10350, 140 closes https://github.com/official-stockfish/Stockfish/pull/4132 Bench: 6079565 --- src/evaluate.cpp | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 7d587675..eaad4d55 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -1053,34 +1053,29 @@ Value Eval::evaluate(const Position& pos, int* complexity) { Value v; Color stm = pos.side_to_move(); Value psq = pos.psq_eg_stm(); - // Deciding between classical and NNUE eval (~10 Elo): for high PSQ imbalance we use classical, - // but we switch to NNUE during long shuffling or with high material on the board. - bool useClassical = (pos.count() > 7) - && abs(psq) * 5 > (856 + pos.non_pawn_material() / 64) * (10 + pos.rule50_count()); - // Deciding between classical and NNUE eval (~10 Elo): for high PSQ imbalance we use classical, + // Deciding between classical and NNUE eval: for high PSQ imbalance we use classical, // but we switch to NNUE during long shuffling or with high material on the board. - if (!useNNUE || useClassical) - { + bool useClassical = !useNNUE || + ((pos.count() > 7) + && abs(psq) * 5 > (856 + pos.non_pawn_material() / 64) * (10 + pos.rule50_count())); + + if (useClassical) v = Evaluation(pos).value(); - useClassical = abs(v) >= 297; - } - - // If result of a classical evaluation is much lower than threshold fall back to NNUE - if (useNNUE && !useClassical) + else { - int nnueComplexity; - int scale = 1064 + 106 * pos.non_pawn_material() / 5120; - Value optimism = pos.this_thread()->optimism[stm]; + int nnueComplexity; + int scale = 1064 + 106 * pos.non_pawn_material() / 5120; + Value optimism = pos.this_thread()->optimism[stm]; - Value nnue = NNUE::evaluate(pos, true, &nnueComplexity); - // Blend nnue complexity with (semi)classical complexity - nnueComplexity = (104 * nnueComplexity + 131 * abs(nnue - psq)) / 256; - if (complexity) // Return hybrid NNUE complexity to caller - *complexity = nnueComplexity; + Value nnue = NNUE::evaluate(pos, true, &nnueComplexity); + // Blend nnue complexity with (semi)classical complexity + nnueComplexity = (104 * nnueComplexity + 131 * abs(nnue - psq)) / 256; + if (complexity) // Return hybrid NNUE complexity to caller + *complexity = nnueComplexity; - optimism = optimism * (269 + nnueComplexity) / 256; - v = (nnue * scale + optimism * (scale - 754)) / 1024; + optimism = optimism * (269 + nnueComplexity) / 256; + v = (nnue * scale + optimism * (scale - 754)) / 1024; } // Damp down the evaluation linearly when shuffling @@ -1091,7 +1086,7 @@ Value Eval::evaluate(const Position& pos, int* complexity) { // When not using NNUE, return classical complexity to caller if (complexity && (!useNNUE || useClassical)) - *complexity = abs(v - psq); + *complexity = abs(v - psq); return v; } From 02ef1f4496965b5ad8c26ac6bc18245eaffae2ea Mon Sep 17 00:00:00 2001 From: mstembera Date: Sat, 13 Aug 2022 17:01:11 -0700 Subject: [PATCH 53/84] Make key_after() more consistent with key() STC: https://tests.stockfishchess.org/tests/view/62f8547123d42b50a8dac674 LLR: 2.95 (-2.94,2.94) <0.00,2.00> Total: 176640 W: 47699 L: 47189 D: 81752 Ptnml(0-2): 776, 18599, 49129, 18971, 845 A bug fix plus non functional speed optimization. Position::key_after(Move m) is now consistent with Position::key() thus prefetching correct TT entries which speeds things up. Related PR #3759 closes https://github.com/official-stockfish/Stockfish/pull/4130 No functional change --- src/position.cpp | 5 ++++- src/position.h | 12 ++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/position.cpp b/src/position.cpp index 08ed1a89..62e6e238 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -1054,7 +1054,10 @@ Key Position::key_after(Move m) const { if (captured) k ^= Zobrist::psq[captured][to]; - return k ^ Zobrist::psq[pc][to] ^ Zobrist::psq[pc][from]; + k ^= Zobrist::psq[pc][to] ^ Zobrist::psq[pc][from]; + + return (captured || type_of(pc) == PAWN) + ? k : adjust_key50(k); } diff --git a/src/position.h b/src/position.h index 510875d8..078ff5b7 100644 --- a/src/position.h +++ b/src/position.h @@ -185,6 +185,8 @@ private: void move_piece(Square from, Square to); template void do_castling(Color us, Square from, Square& to, Square& rfrom, Square& rto); + template + Key adjust_key50(Key k) const; // Data members Piece board[SQUARE_NB]; @@ -327,8 +329,14 @@ inline int Position::pawns_on_same_color_squares(Color c, Square s) const { } inline Key Position::key() const { - return st->rule50 < 14 ? st->key - : st->key ^ make_key((st->rule50 - 14) / 8); + return adjust_key50(st->key); +} + +template +inline Key Position::adjust_key50(Key k) const +{ + return st->rule50 < 14 - AfterMove + ? k : k ^ make_key((st->rule50 - (14 - AfterMove)) / 8); } inline Key Position::pawn_key() const { From 97860cb575e3e71791b9a99b94f9f7d7a0dbf25e Mon Sep 17 00:00:00 2001 From: dav1312 <63931154+dav1312@users.noreply.github.com> Date: Fri, 26 Aug 2022 11:26:31 +0200 Subject: [PATCH 54/84] Disable ARM CI tests Temporarily disable ARM CI tests until a mitigation is implemented closes https://github.com/official-stockfish/Stockfish/pull/4148 No functional change. --- .github/workflows/stockfish.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/stockfish.yml b/.github/workflows/stockfish.yml index 782e3f2b..b007ec78 100644 --- a/.github/workflows/stockfish.yml +++ b/.github/workflows/stockfish.yml @@ -50,7 +50,7 @@ jobs: os: ubuntu-20.04, compiler: aarch64-linux-android21-clang++, comp: ndk, - run_armv8_tests: true, + run_armv8_tests: false, shell: 'bash {0}' } - { @@ -58,7 +58,7 @@ jobs: os: ubuntu-20.04, compiler: armv7a-linux-androideabi21-clang++, comp: ndk, - run_armv7_tests: true, + run_armv7_tests: false, shell: 'bash {0}' } - { From dddf8fc2b4867bad8b01fe3a18266c3677f3f726 Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Sat, 3 Sep 2022 11:15:40 +0200 Subject: [PATCH 55/84] Increase the maximum number of threads to 1024 relatively soon servers with 512 threads will be available 'quite commonly', anticipate even more threads, and increase our current maximum from 512 to 1024. closes https://github.com/official-stockfish/Stockfish/pull/4152 No functional change. --- src/ucioption.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ucioption.cpp b/src/ucioption.cpp index 922fa34f..9fb48345 100644 --- a/src/ucioption.cpp +++ b/src/ucioption.cpp @@ -61,7 +61,7 @@ void init(OptionsMap& o) { constexpr int MaxHashMB = Is64Bit ? 33554432 : 2048; o["Debug Log File"] << Option("", on_logger); - o["Threads"] << Option(1, 1, 512, on_threads); + o["Threads"] << Option(1, 1, 1024, on_threads); o["Hash"] << Option(16, 1, MaxHashMB, on_hash_size); o["Clear Hash"] << Option(on_clear_hash); o["Ponder"] << Option(false); From a4d18d23a9f7626234fcfbb6b23b3d0b8d1a9441 Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Sat, 3 Sep 2022 11:03:09 +0200 Subject: [PATCH 56/84] Provide network download fallback in case the base infrastructure for providing the networks https://tests.stockfishchess.org/nns is down, use an alternate github repo for downloading networks during the build. fixes #4149 fixes #4140 closes https://github.com/official-stockfish/Stockfish/pull/4151 No functional change --- src/Makefile | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/src/Makefile b/src/Makefile index ff2452d6..8315f33d 100644 --- a/src/Makefile +++ b/src/Makefile @@ -827,24 +827,34 @@ clean: objclean profileclean 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 nnuedownloadurl1 := https://tests.stockfishchess.org/api/nn/$(nnuenet)) + $(eval nnuedownloadurl2 := https://github.com/official-stockfish/networks/raw/master/$(nnuenet)) $(eval curl_or_wget := $(shell if hash curl 2>/dev/null; then echo "curl -skL"; elif hash wget 2>/dev/null; then echo "wget -qO-"; fi)) - @if 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; + @if [ "x$(curl_or_wget)" = "x" ]; then \ + echo "Automatic download failed: neither curl nor wget is installed. Install one of these tools or download the net manually"; exit 1; \ + fi $(eval shasum_command := $(shell if hash shasum 2>/dev/null; then echo "shasum -a 256 "; elif hash sha256sum 2>/dev/null; then echo "sha256sum "; fi)) - @if [ "x$(shasum_command)" != "x" ]; then \ - 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"; \ + @if [ "x$(shasum_command)" = "x" ]; then \ + echo "shasum / sha256sum not found, skipping net validation"; \ + fi + @for nnuedownloadurl in "$(nnuedownloadurl1)" "$(nnuedownloadurl2)"; do \ + if test -f "$(nnuenet)"; then \ + echo "$(nnuenet) available."; \ + else \ + if [ "x$(curl_or_wget)" != "x" ]; then \ + echo "Downloading $${nnuedownloadurl}"; $(curl_or_wget) $${nnuedownloadurl} > $(nnuenet);\ + fi; \ + fi; \ + if [ "x$(shasum_command)" != "x" ]; then \ + if [ "$(nnuenet)" != "nn-"`$(shasum_command) $(nnuenet) | cut -c1-12`".nnue" ]; then \ + echo "Removing failed download"; rm -f $(nnuenet); \ + else \ + echo "Network validated"; break; \ + fi; \ + fi; \ + done + @if ! test -f "$(nnuenet)"; then \ + echo "Failed to download $(nnuenet)."; \ fi # clean binaries and objects From 5eeb96d0e7d54686376305029c477c42478aa1d5 Mon Sep 17 00:00:00 2001 From: FauziAkram Date: Wed, 31 Aug 2022 14:45:39 +0300 Subject: [PATCH 57/84] VLTC tuning Tuning some parameters that scale well with longer time control: Failed STC: https://tests.stockfishchess.org/tests/view/6313424d8202a039920e130a LLR: -2.94 (-2.94,2.94) <-1.75,0.25> Total: 42680 W: 11231 L: 11540 D: 19909 Ptnml(0-2): 191, 5008, 11232, 4737, 172 Passed LTC: https://tests.stockfishchess.org/tests/view/6311e2cd874169ca52ae7933 LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 53448 W: 14782 L: 14437 D: 24229 Ptnml(0-2): 101, 5214, 15740, 5577, 92 Passed VLTC: https://tests.stockfishchess.org/tests/view/6312530cfa99a92e3002c927 LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 123336 W: 33465 L: 33007 D: 56864 Ptnml(0-2): 38, 11466, 38204, 11920, 40 closes https://github.com/official-stockfish/Stockfish/pull/4154 Bench: 5609606 --- src/search.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 6d78403f..cd7369c8 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -63,7 +63,7 @@ namespace { // Futility margin Value futility_margin(Depth d, bool improving) { - return Value(168 * (d - improving)); + return Value(174 * (d - improving)); } // Reductions lookup table, initialized at startup @@ -362,7 +362,7 @@ void Thread::search() { trend = (us == WHITE ? make_score(tr, tr / 2) : -make_score(tr, tr / 2)); - int opt = sigmoid(prev, 8, 17, 144, 13966, 183); + int opt = sigmoid(prev, 8, 17, 144, 15012, 183); optimism[ us] = Value(opt); optimism[~us] = -optimism[us]; } @@ -778,7 +778,7 @@ namespace { // return a fail low. if ( !PvNode && depth <= 7 - && eval < alpha - 348 - 258 * depth * depth) + && eval < alpha - 341 - 267 * depth * depth) { value = qsearch(pos, ss, alpha - 1, alpha); if (value < alpha) @@ -797,7 +797,7 @@ namespace { // Step 9. Null move search with verification search (~22 Elo) if ( !PvNode && (ss-1)->currentMove != MOVE_NULL - && (ss-1)->statScore < 14695 + && (ss-1)->statScore < 15344 && eval >= beta && eval >= ss->staticEval && ss->staticEval >= beta - 15 * depth - improvement / 15 + 201 + complexity / 24 @@ -808,7 +808,7 @@ namespace { assert(eval - beta >= 0); // Null move dynamic reduction based on depth, eval and complexity of position - Depth R = std::min(int(eval - beta) / 147, 5) + depth / 3 + 4 - (complexity > 650); + Depth R = std::min(int(eval - beta) / 152, 5) + depth / 3 + 4 - (complexity > 650); ss->currentMove = MOVE_NULL; ss->continuationHistory = &thisThread->continuationHistory[0][0][NO_PIECE][0]; @@ -844,7 +844,7 @@ namespace { } } - probCutBeta = beta + 179 - 46 * improving; + probCutBeta = beta + 173 - 46 * improving; // Step 10. ProbCut (~4 Elo) // If we have a good enough capture and a reduced search returns a value @@ -906,9 +906,9 @@ namespace { return qsearch(pos, ss, alpha, beta); if ( cutNode - && depth >= 8 + && depth >= 9 && !ttMove) - depth--; + depth -= 2; moves_loop: // When in check, search starts here @@ -1009,7 +1009,7 @@ moves_loop: // When in check, search starts here && !PvNode && lmrDepth < 6 && !ss->inCheck - && ss->staticEval + 281 + 179 * lmrDepth + PieceValue[EG][pos.piece_on(to_sq(move))] + && ss->staticEval + 277 + 187 * lmrDepth + PieceValue[EG][pos.piece_on(to_sq(move))] + captureHistory[movedPiece][to_sq(move)][type_of(pos.piece_on(to_sq(move)))] / 6 < alpha) continue; @@ -1173,7 +1173,7 @@ moves_loop: // When in check, search starts here + (*contHist[0])[movedPiece][to_sq(move)] + (*contHist[1])[movedPiece][to_sq(move)] + (*contHist[3])[movedPiece][to_sq(move)] - - 4334; + - 4560; // Decrease/increase reduction for moves with a good/bad history (~30 Elo) r -= ss->statScore / 15914; @@ -1188,7 +1188,7 @@ moves_loop: // When in check, search starts here // Do full depth search when reduced LMR search fails high if (value > alpha && d < newDepth) { - const bool doDeeperSearch = value > (alpha + 78 + 11 * (newDepth - d)); + const bool doDeeperSearch = value > (alpha + 73 + 12 * (newDepth - d)); value = -search(pos, ss+1, -(alpha+1), -alpha, newDepth + doDeeperSearch, !cutNode); int bonus = value > alpha ? stat_bonus(newDepth) @@ -1337,14 +1337,14 @@ moves_loop: // When in check, search starts here quietsSearched, quietCount, capturesSearched, captureCount, depth); // Bonus for prior countermove that caused the fail low - else if ( (depth >= 4 || PvNode) + else if ( (depth >= 5 || PvNode) && !priorCapture) { //Assign extra bonus if current node is PvNode or cutNode //or fail low was really bad bool extraBonus = PvNode || cutNode - || bestValue < alpha - 70 * depth; + || bestValue < alpha - 66 * depth; update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, stat_bonus(depth) * (1 + extraBonus)); } From eaf2c8207fff9699201085fec123c114f454f798 Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Sun, 11 Sep 2022 01:45:37 +0300 Subject: [PATCH 58/84] Further LTC tuning of search parameters Tuning done by bigpenor with some hand adjustments on top by Viz. Had a good performance at fixed games 180+1.8: https://tests.stockfishchess.org/tests/view/631836b437f41b13973d7da1 Elo: 1.35 +-1.2 (95%) LOS: 98.6% Total: 60000 W: 16422 L: 16189 D: 27389 Ptnml(0-2): 39, 5335, 18992, 5622, 12 nElo: 3.13 +-2.8 (95%) PairsRatio: 1.05 Passed 60+0.6 8 threads SPRT: https://tests.stockfishchess.org/tests/view/631ba0ff74bc4fe483a99db3 LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 29712 W: 8301 L: 8039 D: 13372 Ptnml(0-2): 12, 2318, 9925, 2598, 3 closes https://github.com/official-stockfish/Stockfish/pull/4160 bench 3938073 --- src/search.cpp | 92 +++++++++++++++++++++++++------------------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index cd7369c8..162a0994 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -63,7 +63,7 @@ namespace { // Futility margin Value futility_margin(Depth d, bool improving) { - return Value(174 * (d - improving)); + return Value(165 * (d - improving)); } // Reductions lookup table, initialized at startup @@ -71,7 +71,7 @@ namespace { Depth reduction(bool i, Depth d, int mn, Value delta, Value rootDelta) { int r = Reductions[d] * Reductions[mn]; - return (r + 1463 - int(delta) * 1024 / int(rootDelta)) / 1024 + (!i && r > 1010); + return (r + 1642 - int(delta) * 1024 / int(rootDelta)) / 1024 + (!i && r > 916); } constexpr int futility_move_count(bool improving, Depth depth) { @@ -81,7 +81,7 @@ namespace { // History and stats update bonus, based on depth int stat_bonus(Depth d) { - return std::min((8 * d + 240) * d - 276 , 1907); + return std::min((12 * d + 282) * d - 349 , 1594); } // Add a small random component to draw evaluations to avoid 3-fold blindness @@ -158,7 +158,7 @@ namespace { void Search::init() { for (int i = 1; i < MAX_MOVES; ++i) - Reductions[i] = int((20.81 + std::log(Threads.size()) / 2) * std::log(i)); + Reductions[i] = int((20.26 + std::log(Threads.size()) / 2) * std::log(i)); } @@ -307,10 +307,10 @@ void Thread::search() { multiPV = std::min(multiPV, rootMoves.size()); - complexityAverage.set(174, 1); + complexityAverage.set(155, 1); trend = SCORE_ZERO; - optimism[ us] = Value(39); + optimism[ us] = Value(37); optimism[~us] = -optimism[us]; int searchAgainCounter = 0; @@ -353,16 +353,16 @@ void Thread::search() { if (rootDepth >= 4) { Value prev = rootMoves[pvIdx].averageScore; - delta = Value(16) + int(prev) * prev / 19178; + delta = Value(10) + int(prev) * prev / 15620; alpha = std::max(prev - delta,-VALUE_INFINITE); beta = std::min(prev + delta, VALUE_INFINITE); // Adjust trend and optimism based on root move's previousScore - int tr = sigmoid(prev, 3, 8, 90, 125, 1); + int tr = sigmoid(prev, 3, 10, 89, 116, 1); trend = (us == WHITE ? make_score(tr, tr / 2) : -make_score(tr, tr / 2)); - int opt = sigmoid(prev, 8, 17, 144, 15012, 183); + int opt = sigmoid(prev, 7, 20, 169, 19350, 164); optimism[ us] = Value(opt); optimism[~us] = -optimism[us]; } @@ -465,16 +465,16 @@ void Thread::search() { && !Threads.stop && !mainThread->stopOnPonderhit) { - double fallingEval = (69 + 12 * (mainThread->bestPreviousAverageScore - bestValue) - + 6 * (mainThread->iterValue[iterIdx] - bestValue)) / 781.4; + double fallingEval = (71 + 12 * (mainThread->bestPreviousAverageScore - bestValue) + + 6 * (mainThread->iterValue[iterIdx] - bestValue)) / 656.7; fallingEval = std::clamp(fallingEval, 0.5, 1.5); // If the bestMove is stable over several iterations, reduce time accordingly - timeReduction = lastBestMoveDepth + 10 < completedDepth ? 1.63 : 0.73; - double reduction = (1.56 + mainThread->previousTimeReduction) / (2.20 * timeReduction); + timeReduction = lastBestMoveDepth + 9 < completedDepth ? 1.37 : 0.65; + double reduction = (1.4 + mainThread->previousTimeReduction) / (2.15 * timeReduction); double bestMoveInstability = 1 + 1.7 * totBestMoveChanges / Threads.size(); int complexity = mainThread->complexityAverage.value(); - double complexPosition = std::min(1.0 + (complexity - 277) / 1819.1, 1.5); + double complexPosition = std::min(1.0 + (complexity - 261) / 1738.7, 1.5); double totalTime = Time.optimum() * fallingEval * reduction * bestMoveInstability * complexPosition; @@ -495,7 +495,7 @@ void Thread::search() { } else if ( Threads.increaseDepth && !mainThread->ponder - && Time.elapsed() > totalTime * 0.43) + && Time.elapsed() > totalTime * 0.53) Threads.increaseDepth = false; else Threads.increaseDepth = true; @@ -760,7 +760,7 @@ namespace { // Use static evaluation difference to improve quiet move ordering (~3 Elo) if (is_ok((ss-1)->currentMove) && !(ss-1)->inCheck && !priorCapture) { - int bonus = std::clamp(-16 * int((ss-1)->staticEval + ss->staticEval), -2000, 2000); + int bonus = std::clamp(-19 * int((ss-1)->staticEval + ss->staticEval), -1914, 1914); thisThread->mainHistory[~us][from_to((ss-1)->currentMove)] << bonus; } @@ -770,7 +770,7 @@ namespace { // margin and the improving flag are used in various pruning heuristics. improvement = (ss-2)->staticEval != VALUE_NONE ? ss->staticEval - (ss-2)->staticEval : (ss-4)->staticEval != VALUE_NONE ? ss->staticEval - (ss-4)->staticEval - : 175; + : 168; improving = improvement > 0; // Step 7. Razoring. @@ -778,7 +778,7 @@ namespace { // return a fail low. if ( !PvNode && depth <= 7 - && eval < alpha - 341 - 267 * depth * depth) + && eval < alpha - 369 - 254 * depth * depth) { value = qsearch(pos, ss, alpha - 1, alpha); if (value < alpha) @@ -789,18 +789,18 @@ namespace { // The depth condition is important for mate finding. if ( !ss->ttPv && depth < 8 - && eval - futility_margin(depth, improving) - (ss-1)->statScore / 256 >= beta + && eval - futility_margin(depth, improving) - (ss-1)->statScore / 303 >= beta && eval >= beta - && eval < 26305) // larger than VALUE_KNOWN_WIN, but smaller than TB wins. + && eval < 28031) // larger than VALUE_KNOWN_WIN, but smaller than TB wins. return eval; // Step 9. Null move search with verification search (~22 Elo) if ( !PvNode && (ss-1)->currentMove != MOVE_NULL - && (ss-1)->statScore < 15344 + && (ss-1)->statScore < 17139 && eval >= beta && eval >= ss->staticEval - && ss->staticEval >= beta - 15 * depth - improvement / 15 + 201 + complexity / 24 + && ss->staticEval >= beta - 20 * depth - improvement / 13 + 233 + complexity / 25 && !excludedMove && pos.non_pawn_material(us) && (ss->ply >= thisThread->nmpMinPly || us != thisThread->nmpColor)) @@ -808,7 +808,7 @@ namespace { assert(eval - beta >= 0); // Null move dynamic reduction based on depth, eval and complexity of position - Depth R = std::min(int(eval - beta) / 152, 5) + depth / 3 + 4 - (complexity > 650); + Depth R = std::min(int(eval - beta) / 168, 7) + depth / 3 + 4 - (complexity > 861); ss->currentMove = MOVE_NULL; ss->continuationHistory = &thisThread->continuationHistory[0][0][NO_PIECE][0]; @@ -844,7 +844,7 @@ namespace { } } - probCutBeta = beta + 173 - 46 * improving; + probCutBeta = beta + 191 - 54 * improving; // Step 10. ProbCut (~4 Elo) // If we have a good enough capture and a reduced search returns a value @@ -913,7 +913,7 @@ namespace { moves_loop: // When in check, search starts here // Step 12. A small Probcut idea, when we are in check (~0 Elo) - probCutBeta = beta + 481; + probCutBeta = beta + 417; if ( ss->inCheck && !PvNode && depth >= 2 @@ -1007,14 +1007,14 @@ moves_loop: // When in check, search starts here if ( !pos.empty(to_sq(move)) && !givesCheck && !PvNode - && lmrDepth < 6 + && lmrDepth < 7 && !ss->inCheck - && ss->staticEval + 277 + 187 * lmrDepth + PieceValue[EG][pos.piece_on(to_sq(move))] + && ss->staticEval + 180 + 201 * lmrDepth + PieceValue[EG][pos.piece_on(to_sq(move))] + captureHistory[movedPiece][to_sq(move)][type_of(pos.piece_on(to_sq(move)))] / 6 < alpha) continue; // SEE based pruning (~9 Elo) - if (!pos.see_ge(move, Value(-203) * depth)) + if (!pos.see_ge(move, Value(-222) * depth)) continue; } else @@ -1032,12 +1032,12 @@ moves_loop: // When in check, search starts here // Futility pruning: parent node (~9 Elo) if ( !ss->inCheck - && lmrDepth < 11 - && ss->staticEval + 122 + 138 * lmrDepth + history / 60 <= alpha) + && lmrDepth < 13 + && ss->staticEval + 106 + 145 * lmrDepth + history / 52 <= alpha) continue; // Prune moves with negative SEE (~3 Elo) - if (!pos.see_ge(move, Value(-25 * lmrDepth * lmrDepth - 20 * lmrDepth))) + if (!pos.see_ge(move, Value(-24 * lmrDepth * lmrDepth - 15 * lmrDepth))) continue; } } @@ -1052,7 +1052,7 @@ moves_loop: // When in check, search starts here // a reduced search on all the other moves but the ttMove and if the // result is lower than ttValue minus a margin, then we will extend the ttMove. if ( !rootNode - && depth >= 4 - (thisThread->previousDepth > 27) + 2 * (PvNode && tte->is_pv()) + && depth >= 4 - (thisThread->previousDepth > 24) + 2 * (PvNode && tte->is_pv()) && move == ttMove && !excludedMove // Avoid recursive singular search /* && ttValue != VALUE_NONE Already implicit in the next condition */ @@ -1074,8 +1074,8 @@ moves_loop: // When in check, search starts here // Avoid search explosion by limiting the number of double extensions if ( !PvNode - && value < singularBeta - 26 - && ss->doubleExtensions <= 8) + && value < singularBeta - 25 + && ss->doubleExtensions <= 9) extension = 2; } @@ -1099,14 +1099,14 @@ moves_loop: // When in check, search starts here // Check extensions (~1 Elo) else if ( givesCheck && depth > 9 - && abs(ss->staticEval) > 71) + && abs(ss->staticEval) > 82) extension = 1; // Quiet ttMove extensions (~0 Elo) else if ( PvNode && move == ttMove && move == ss->killers[0] - && (*contHist[0])[movedPiece][to_sq(move)] >= 5491) + && (*contHist[0])[movedPiece][to_sq(move)] >= 5177) extension = 1; } @@ -1159,7 +1159,7 @@ moves_loop: // When in check, search starts here // Decrease reduction for PvNodes based on depth if (PvNode) - r -= 1 + 15 / (3 + depth); + r -= 1 + 11 / (3 + depth); // Decrease reduction if ttMove has been singularly extended (~1 Elo) if (singularQuietLMR) @@ -1173,10 +1173,10 @@ moves_loop: // When in check, search starts here + (*contHist[0])[movedPiece][to_sq(move)] + (*contHist[1])[movedPiece][to_sq(move)] + (*contHist[3])[movedPiece][to_sq(move)] - - 4560; + - 4433; // Decrease/increase reduction for moves with a good/bad history (~30 Elo) - r -= ss->statScore / 15914; + r -= ss->statScore / 13628; // In general we want to cap the LMR depth search at newDepth, but when // reduction is negative, we allow this move a limited search extension @@ -1188,7 +1188,7 @@ moves_loop: // When in check, search starts here // Do full depth search when reduced LMR search fails high if (value > alpha && d < newDepth) { - const bool doDeeperSearch = value > (alpha + 73 + 12 * (newDepth - d)); + const bool doDeeperSearch = value > (alpha + 64 + 11 * (newDepth - d)); value = -search(pos, ss+1, -(alpha+1), -alpha, newDepth + doDeeperSearch, !cutNode); int bonus = value > alpha ? stat_bonus(newDepth) @@ -1280,8 +1280,8 @@ moves_loop: // When in check, search starts here alpha = value; // Reduce other moves if we have found at least one score improvement - if ( depth > 2 - && depth < 7 + if ( depth > 1 + && depth < 6 && beta < VALUE_KNOWN_WIN && alpha > -VALUE_KNOWN_WIN) depth -= 1; @@ -1344,7 +1344,7 @@ moves_loop: // When in check, search starts here //or fail low was really bad bool extraBonus = PvNode || cutNode - || bestValue < alpha - 66 * depth; + || bestValue < alpha - 62 * depth; update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, stat_bonus(depth) * (1 + extraBonus)); } @@ -1471,7 +1471,7 @@ moves_loop: // When in check, search starts here if (PvNode && bestValue > alpha) alpha = bestValue; - futilityBase = bestValue + 118; + futilityBase = bestValue + 153; } const PieceToHistory* contHist[] = { (ss-1)->continuationHistory, (ss-2)->continuationHistory, @@ -1675,8 +1675,8 @@ moves_loop: // When in check, search starts here if (!pos.capture(bestMove)) { - int bonus2 = bestValue > beta + PawnValueMg ? bonus1 // larger bonus - : stat_bonus(depth); // smaller bonus + int bonus2 = bestValue > beta + 137 ? bonus1 // larger bonus + : stat_bonus(depth); // smaller bonus // Increase stats for the best move in case it was a quiet move update_quiet_stats(pos, ss, bestMove, bonus2); From 9fa258ee1d36d5a432a7a3e857e0723d439528b0 Mon Sep 17 00:00:00 2001 From: Dubslow Date: Fri, 19 Aug 2022 22:49:29 -0500 Subject: [PATCH 59/84] Razor also on PV nodes Simplification introduced by xoto10 blue LTC vs new master: https://tests.stockfishchess.org/tests/view/631ad4ef9cfa5e9b648d1b4e LLR: 2.93 (-2.94,2.94) <-1.75,0.25> Total: 59184 W: 16002 L: 15828 D: 27354 Ptnml(0-2): 65, 5777, 17747, 5925, 78 blue STC vs old master: https://tests.stockfishchess.org/tests/view/6306b87b902a848543334c25 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 213944 W: 57184 L: 57159 D: 99601 Ptnml(0-2): 877, 23448, 58331, 23405, 911 blue LTC vs old master: https://tests.stockfishchess.org/tests/view/63070e6b902a8485433357e7 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 192080 W: 52050 L: 52006 D: 88024 Ptnml(0-2): 232, 18981, 57611, 18943, 273 closes https://github.com/official-stockfish/Stockfish/pull/4147 bench 4208975 --- src/search.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 162a0994..12576378 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -776,8 +776,7 @@ namespace { // Step 7. Razoring. // If eval is really low check with qsearch if it can exceed alpha, if it can't, // return a fail low. - if ( !PvNode - && depth <= 7 + if ( depth <= 7 && eval < alpha - 369 - 254 * depth * depth) { value = qsearch(pos, ss, alpha - 1, alpha); From 1591e5ac3b24f068f965471f17d7aae33ceaab9f Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Sat, 10 Sep 2022 12:30:25 +0300 Subject: [PATCH 60/84] Do less singular extensions for former PVnode Patch is a reintroduction of logic what was simplified a while ago in a slightly different form. Do bigger extension offset in case of non-pv node having a pv. passed STC https://tests.stockfishchess.org/tests/view/631977c048f27688a06e66d5 LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 23296 W: 6404 L: 6108 D: 10784 Ptnml(0-2): 88, 2539, 6118, 2795, 108 passed LTC https://tests.stockfishchess.org/tests/view/631989cb48f27688a06e696c LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 235592 W: 63890 L: 63188 D: 108514 Ptnml(0-2): 275, 23392, 69804, 24006, 319 closes https://github.com/official-stockfish/Stockfish/pull/4159 Bench: 3993611 --- src/search.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index 12576378..c998f20d 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1059,7 +1059,7 @@ moves_loop: // When in check, search starts here && (tte->bound() & BOUND_LOWER) && tte->depth() >= depth - 3) { - Value singularBeta = ttValue - 3 * depth; + Value singularBeta = ttValue - (3 + (ss->ttPv && !PvNode)) * depth; Depth singularDepth = (depth - 1) / 2; ss->excludedMove = move; From 82bb21dc7a198609589ef0cc78d185f00f619a90 Mon Sep 17 00:00:00 2001 From: mstembera Date: Tue, 6 Sep 2022 15:02:35 -0700 Subject: [PATCH 61/84] Optimize AVX2 path in NNUE evaluation always selecting AffineTransform specialization for small inputs. A related patch was tested as Initially tested as a simplification STC https://tests.stockfishchess.org/tests/view/6317c3f437f41b13973d6dff LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 58072 W: 15619 L: 15425 D: 27028 Ptnml(0-2): 241, 6191, 15992, 6357, 255 Elo gain speedup test STC https://tests.stockfishchess.org/tests/view/63181c1b37f41b13973d79dc LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 184496 W: 49922 L: 49401 D: 85173 Ptnml(0-2): 851, 19397, 51208, 19964, 828 and this patch gained in testing speedup = +0.0071 P(speedup > 0) = 1.0000 on CPU: 16 x AMD Ryzen 9 3950X closes https://github.com/official-stockfish/Stockfish/pull/4158 No functional change --- src/nnue/layers/affine_transform.h | 16 +++++++++++----- src/{ => nnue/layers}/simd.h | 0 2 files changed, 11 insertions(+), 5 deletions(-) rename src/{ => nnue/layers}/simd.h (100%) diff --git a/src/nnue/layers/affine_transform.h b/src/nnue/layers/affine_transform.h index 9a992608..461a7b83 100644 --- a/src/nnue/layers/affine_transform.h +++ b/src/nnue/layers/affine_transform.h @@ -25,7 +25,7 @@ #include #include #include "../nnue_common.h" -#include "../../simd.h" +#include "simd.h" /* This file contains the definition for a fully connected layer (aka affine transform). @@ -151,9 +151,15 @@ namespace Stockfish::Eval::NNUE::Layers { template class AffineTransform; +#if defined (USE_AVX512) + constexpr IndexType LargeInputSize = 2 * 64; +#else + constexpr IndexType LargeInputSize = std::numeric_limits::max(); +#endif + // A specialization for large inputs. template - class AffineTransform(InDims, MaxSimdWidth) >= 2*64)>> { + class AffineTransform(InDims, MaxSimdWidth) >= LargeInputSize)>> { public: // Input/output type using InputType = std::uint8_t; @@ -170,7 +176,7 @@ namespace Stockfish::Eval::NNUE::Layers { using OutputBuffer = OutputType[PaddedOutputDimensions]; - static_assert(PaddedInputDimensions >= 128, "Something went wrong. This specialization should not have been chosen."); + static_assert(PaddedInputDimensions >= LargeInputSize, "Something went wrong. This specialization should not have been chosen."); #if defined (USE_AVX512) static constexpr const IndexType InputSimdWidth = 64; @@ -369,7 +375,7 @@ namespace Stockfish::Eval::NNUE::Layers { }; template - class AffineTransform(InDims, MaxSimdWidth) < 2*64)>> { + class AffineTransform(InDims, MaxSimdWidth) < LargeInputSize)>> { public: // Input/output type // Input/output type @@ -387,7 +393,7 @@ namespace Stockfish::Eval::NNUE::Layers { using OutputBuffer = OutputType[PaddedOutputDimensions]; - static_assert(PaddedInputDimensions < 128, "Something went wrong. This specialization should not have been chosen."); + static_assert(PaddedInputDimensions < LargeInputSize, "Something went wrong. This specialization should not have been chosen."); #if defined (USE_SSSE3) static constexpr const IndexType OutputSimdWidth = SimdWidth / 4; diff --git a/src/simd.h b/src/nnue/layers/simd.h similarity index 100% rename from src/simd.h rename to src/nnue/layers/simd.h From 5a871e174f22894837c2363b5c215854ee155113 Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Sun, 11 Sep 2022 21:28:12 +0200 Subject: [PATCH 62/84] Explicitly annotate a few variables as [[maybe_unused]], avoiding the (void)foo trick. closes https://github.com/official-stockfish/Stockfish/pull/4162 No functional change --- src/misc.cpp | 6 ++---- src/movepick.cpp | 10 +--------- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/src/misc.cpp b/src/misc.cpp index 41c59b3f..d19cd840 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -378,10 +378,9 @@ void std_aligned_free(void* ptr) { #if defined(_WIN32) -static void* aligned_large_pages_alloc_windows(size_t allocSize) { +static void* aligned_large_pages_alloc_windows([[maybe_unused]] size_t allocSize) { #if !defined(_WIN64) - (void)allocSize; // suppress unused-parameter compiler warning return nullptr; #else @@ -626,8 +625,7 @@ string argv0; // path+name of the executable binary, as given by argv string binaryDirectory; // path of the executable directory string workingDirectory; // path of the working directory -void init(int argc, char* argv[]) { - (void)argc; +void init([[maybe_unused]] int argc, char* argv[]) { string pathSeparator; // extract the path+name of the executable binary diff --git a/src/movepick.cpp b/src/movepick.cpp index 60d041ab..d8d0612a 100644 --- a/src/movepick.cpp +++ b/src/movepick.cpp @@ -106,7 +106,7 @@ void MovePicker::score() { static_assert(Type == CAPTURES || Type == QUIETS || Type == EVASIONS, "Wrong type"); - Bitboard threatened, threatenedByPawn, threatenedByMinor, threatenedByRook; + [[maybe_unused]] Bitboard threatened, threatenedByPawn, threatenedByMinor, threatenedByRook; if constexpr (Type == QUIETS) { Color us = pos.side_to_move(); @@ -122,14 +122,6 @@ void MovePicker::score() { | (pos.pieces(us, ROOK) & threatenedByMinor) | (pos.pieces(us, KNIGHT, BISHOP) & threatenedByPawn); } - else - { - // Silence unused variable warnings - (void) threatened; - (void) threatenedByPawn; - (void) threatenedByMinor; - (void) threatenedByRook; - } for (auto& m : *this) if constexpr (Type == CAPTURES) From 154e7afed0fe9c6f45a2aee8ef6f38d44076cb19 Mon Sep 17 00:00:00 2001 From: atumanian Date: Mon, 12 Sep 2022 20:16:54 +0300 Subject: [PATCH 63/84] Simplify trend and optimism. This patch simplifies the formulas used to compute the trend and optimism values before each search iteration. As a side effect, this removes the parameters which make the relationship between the displayed evaluation value and the expected game result asymmetric. I've also provided links to the results of isotonic regression analysis of the relationship between the evaluation and game result (statistical data and a graph) for both tests, which demonstrate that the new version has a more symmetric relationship: STC: [Data and graph](https://github.com/official-stockfish/Stockfish/discussions/4150#discussioncomment-3548954) LTC: [Data and graph](https://github.com/official-stockfish/Stockfish/discussions/4150#discussioncomment-3626311) See also https://github.com/official-stockfish/Stockfish/issues/4142 passed STC: https://tests.stockfishchess.org/tests/view/6313f44b8202a039920e27e6 LLR: 2.96 (-2.94,2.94) <-1.75,0.25> Total: 108016 W: 28903 L: 28760 D: 50353 Ptnml(0-2): 461, 12075, 28850, 12104, 518 passed LTC: https://tests.stockfishchess.org/tests/view/631de45db85daa436625dfe6 LLR: 3.01 (-2.94,2.94) <-1.75,0.25> Total: 34792 W: 9412 L: 9209 D: 16171 Ptnml(0-2): 24, 3374, 10397, 3577, 24 Furthermore, this does not measurably impact Elo strength against weaker engines, as demonstrated in a match of master and patch vs SF13: This patch vs SF 13: https://tests.stockfishchess.org/tests/view/631fa34ae1612778c344c6eb Elo: 141.66 +-1.2 (95%) LOS: 100.0% Total: 100000 W: 48182 L: 9528 D: 42290 Ptnml(0-2): 96, 1426, 13277, 30130, 5071 nElo: 284.13 +-3.3 (95%) PairsRatio: 23.13 Master vs SF 13: https://tests.stockfishchess.org/tests/view/631fa3ece1612778c344c6ff Elo: 143.26 +-1.2 (95%) LOS: 100.0% Total: 100000 W: 48525 L: 9479 D: 41996 Ptnml(0-2): 94, 1537, 13098, 29771, 5500 nElo: 281.70 +-3.3 (95%) PairsRatio: 21.63 closes: https://github.com/official-stockfish/Stockfish/pull/4163 Bench: 4425574 --- src/misc.h | 27 --------------------------- src/search.cpp | 9 ++++----- 2 files changed, 4 insertions(+), 32 deletions(-) diff --git a/src/misc.h b/src/misc.h index fe1143de..77b81d50 100644 --- a/src/misc.h +++ b/src/misc.h @@ -126,33 +126,6 @@ private: }; -/// sigmoid(t, x0, y0, C, P, Q) implements a sigmoid-like function using only integers, -/// with the following properties: -/// -/// - sigmoid is centered in (x0, y0) -/// - sigmoid has amplitude [-P/Q , P/Q] instead of [-1 , +1] -/// - limit is (y0 - P/Q) when t tends to -infinity -/// - limit is (y0 + P/Q) when t tends to +infinity -/// - the slope can be adjusted using C > 0, smaller C giving a steeper sigmoid -/// - the slope of the sigmoid when t = x0 is P/(Q*C) -/// - sigmoid is increasing with t when P > 0 and Q > 0 -/// - to get a decreasing sigmoid, change sign of P -/// - mean value of the sigmoid is y0 -/// -/// Use to draw the sigmoid - -inline int64_t sigmoid(int64_t t, int64_t x0, - int64_t y0, - int64_t C, - int64_t P, - int64_t Q) -{ - assert(C > 0); - assert(Q != 0); - return y0 + P * (t-x0) / (Q * (std::abs(t-x0) + C)) ; -} - - /// xorshift64star Pseudo-Random Number Generator /// This class is based on original code written and dedicated /// to the public domain by Sebastiano Vigna (2014). diff --git a/src/search.cpp b/src/search.cpp index c998f20d..0f524093 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -309,9 +309,8 @@ void Thread::search() { complexityAverage.set(155, 1); - trend = SCORE_ZERO; - optimism[ us] = Value(37); - optimism[~us] = -optimism[us]; + trend = SCORE_ZERO; + optimism[us] = optimism[~us] = VALUE_ZERO; int searchAgainCounter = 0; @@ -358,11 +357,11 @@ void Thread::search() { beta = std::min(prev + delta, VALUE_INFINITE); // Adjust trend and optimism based on root move's previousScore - int tr = sigmoid(prev, 3, 10, 89, 116, 1); + int tr = 116 * prev / (std::abs(prev) + 89); trend = (us == WHITE ? make_score(tr, tr / 2) : -make_score(tr, tr / 2)); - int opt = sigmoid(prev, 7, 20, 169, 19350, 164); + int opt = 118 * prev / (std::abs(prev) + 169); optimism[ us] = Value(opt); optimism[~us] = -optimism[us]; } From dc0c441b7c5178baa1bb0cc51b2d0294f58759a4 Mon Sep 17 00:00:00 2001 From: mstembera Date: Wed, 14 Sep 2022 12:11:52 -0700 Subject: [PATCH 64/84] Prioritize checks in movepicker give a little bonus for moving pieces to squares where they give check STC: https://tests.stockfishchess.org/tests/view/631da742162491686d2e40b5 LLR: 2.95 (-2.94,2.94) <0.00,2.00> Total: 80072 W: 21753 L: 21368 D: 36951 Ptnml(0-2): 421, 8876, 21075, 9225, 439 LTC: https://tests.stockfishchess.org/tests/view/631dd9e6b85daa436625de1d LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 263480 W: 70916 L: 70158 D: 122406 Ptnml(0-2): 322, 26156, 78029, 26908, 325 similar ideas have been tested by Viz and Guenther closes https://github.com/official-stockfish/Stockfish/pull/4165 bench: 4326572 --- src/movepick.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/movepick.cpp b/src/movepick.cpp index d8d0612a..636f4ba7 100644 --- a/src/movepick.cpp +++ b/src/movepick.cpp @@ -139,8 +139,8 @@ void MovePicker::score() { : type_of(pos.moved_piece(m)) == ROOK && !(to_sq(m) & threatenedByMinor) ? 25000 : !(to_sq(m) & threatenedByPawn) ? 15000 : 0) - : 0); - + : 0) + + bool(pos.check_squares(type_of(pos.moved_piece(m))) & to_sq(m)) * 16384; else // Type == EVASIONS { if (pos.capture(m)) From 29295ecfd357b5421eb4f273761dce8d9661f130 Mon Sep 17 00:00:00 2001 From: mstembera Date: Sat, 17 Sep 2022 05:45:54 -0700 Subject: [PATCH 65/84] Simplify EVASIONS scoring remove some multipliers & adjust, doesn't change the move ordering STC https://tests.stockfishchess.org/tests/view/6325c1c9b9c0caa5f4a759ae LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 192760 W: 51528 L: 51482 D: 89750 Ptnml(0-2): 642, 20490, 54148, 20380, 720 Credit to locutus2 closes https://github.com/official-stockfish/Stockfish/pull/4171 No functional change --- src/movepick.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/movepick.cpp b/src/movepick.cpp index 636f4ba7..e10454b0 100644 --- a/src/movepick.cpp +++ b/src/movepick.cpp @@ -145,11 +145,11 @@ void MovePicker::score() { { if (pos.capture(m)) m.value = PieceValue[MG][pos.piece_on(to_sq(m))] - - Value(type_of(pos.moved_piece(m))); + - Value(type_of(pos.moved_piece(m))) + + (1 << 28); else - m.value = 2 * (*mainHistory)[pos.side_to_move()][from_to(m)] - + 2 * (*continuationHistory[0])[pos.moved_piece(m)][to_sq(m)] - - (1 << 28); + m.value = (*mainHistory)[pos.side_to_move()][from_to(m)] + + (*continuationHistory[0])[pos.moved_piece(m)][to_sq(m)]; } } From 70e51a5bc81bd15a73d2cb0be5008c7c02b1b0d5 Mon Sep 17 00:00:00 2001 From: Torsten Hellwig Date: Mon, 19 Sep 2022 18:22:56 +0200 Subject: [PATCH 66/84] Always output hashfull This removes the restriction that no hashfull information is printed within the first second of a search. On modern systems, a non-zero value is returned within 6 ms with default settings. passed STC: https://tests.stockfishchess.org/tests/view/63277b08b9c0caa5f4a798e4 LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 290096 W: 77505 L: 77561 D: 135030 Ptnml(0-2): 1008, 30713, 81592, 30797, 938 closes https://github.com/official-stockfish/Stockfish/pull/4174 No functional change --- src/search.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 0f524093..be0f3451 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1860,12 +1860,9 @@ string UCI::pv(const Position& pos, Depth depth, Value alpha, Value beta) { ss << (v >= beta ? " lowerbound" : v <= alpha ? " upperbound" : ""); ss << " nodes " << nodesSearched - << " nps " << nodesSearched * 1000 / elapsed; - - if (elapsed > 1000) // Earlier makes little sense - ss << " hashfull " << TT.hashfull(); - - ss << " tbhits " << tbHits + << " nps " << nodesSearched * 1000 / elapsed + << " hashfull " << TT.hashfull() + << " tbhits " << tbHits << " time " << elapsed << " pv"; From 4339a756ac0a97563442ee4fb67694a5dfc66da4 Mon Sep 17 00:00:00 2001 From: Brad Knox <64992190+bknox83@users.noreply.github.com> Date: Tue, 20 Sep 2022 16:15:15 -0500 Subject: [PATCH 67/84] Update README.md Adding some svg icons and additional information, insert links as references closes https://github.com/official-stockfish/Stockfish/pull/4176 No functional change --- README.md | 114 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 77 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index f84b79d1..b076ab6b 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,27 @@ +
+ + [![Stockfish][stockfish128-logo]][website-link] + + [![Build][build-badge]][build-link] + [![License][license-badge]][license-link] +
+ [![Release][release-badge]][release-link] + [![Commits][commits-badge]][commits-link] +
+ [![Website][website-badge]][website-link] + [![Fishtest][fishtest-badge]][fishtest-link] + [![Discord][discord-badge]][discord-link] + +
+ ## Overview -[![Build Status](https://github.com/official-stockfish/Stockfish/actions/workflows/stockfish.yml/badge.svg)](https://github.com/official-stockfish/Stockfish/actions) - -[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. +[Stockfish][website-link] 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 informationabout how to use +Stockfish with it. The Stockfish engine features two evaluation functions for chess. The efficiently updatable neural network (NNUE) based evaluation is the default and by far the strongest. @@ -20,28 +34,25 @@ avx2, neon, or similar). This distribution of Stockfish consists of the following files: - * [README.md](https://github.com/official-stockfish/Stockfish/blob/master/README.md), - the file you are currently reading. + * [README.md][readme-link], the file you are currently reading. - * [Copying.txt](https://github.com/official-stockfish/Stockfish/blob/master/Copying.txt), - a text file containing the GNU General Public License version 3. + * [Copying.txt][license-link], a text file containing the GNU General Public License + version 3. - * [AUTHORS](https://github.com/official-stockfish/Stockfish/blob/master/AUTHORS), - a text file with the list of authors for the project + * [AUTHORS][authors-link], a text file with the list of authors for the project. - * [src](https://github.com/official-stockfish/Stockfish/tree/master/src), - a subdirectory containing the full source code, including a Makefile + * [src][src-link], a subdirectory containing the full source code, including a Makefile that can be used to compile Stockfish on Unix-like systems. - * a file with the .nnue extension, storing the neural network for the NNUE - evaluation. Binary distributions will have this file embedded. + * a file with the .nnue extension, storing the neural network for the NNUE evaluation. + Binary distributions will have this file embedded. ## The UCI protocol and available options The Universal Chess Interface (UCI) is a standard protocol used to communicate with a chess engine, and is the recommended way to do so for typical graphical user interfaces (GUI) or chess tools. Stockfish implements the majority of its options as described -in [the UCI protocol](https://www.shredderchess.com/download/div/uci.zip). +in [the UCI protocol][uci-link]. Developers can see the default values for UCI options available in Stockfish by typing `./stockfish uci` in a terminal, but the majority of users will typically see them and @@ -179,12 +190,10 @@ 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) provided the first -version of the needed tools to train and develop the NNUE networks. Today, more -advanced training tools are available in -[the nnue-pytorch repository](https://github.com/glinscott/nnue-pytorch/), -while data generation tools are available in -[a dedicated branch](https://github.com/official-stockfish/Stockfish/tree/tools). +[The nodchip repository][nodchip-link] provided the first version of the needed tools +to train and develop the NNUE networks. Today, more advanced training tools are +available in [the nnue-pytorch repository][pytorch-link], while data generation tools +are available in [a dedicated branch][tools-link]. 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 @@ -250,8 +259,8 @@ 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) +[Enable the Lock Pages in Memory Option (Windows)][lockpages-link] +on how to enable this privilege, then run [RAMMap][rammap-link] 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 @@ -294,26 +303,26 @@ 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). +your hardware resources by installing the [Fishtest Worker][worker-link] +and view the current tests on [Fishtest][fishtest-link]. ### Improving the code If you want to help improve the code, there are several valuable resources: -* [In this wiki,](https://www.chessprogramming.org) many techniques used in +* [In this wiki,][programming-link] many techniques used in Stockfish are explained with a lot of background information. -* [The section on Stockfish](https://www.chessprogramming.org/Stockfish) +* [The section on Stockfish][programmingsf-link] describes many features and techniques used by Stockfish. However, it is generic rather than being focused on Stockfish's precise implementation. Nevertheless, a helpful resource. -* The latest source can always be found on [GitHub](https://github.com/official-stockfish/Stockfish). -Discussions about Stockfish take place these days mainly in the [FishCooking](https://groups.google.com/forum/#!forum/fishcooking) -group and on the [Stockfish Discord channel](https://discord.gg/nv8gDtt). -The engine testing is done on [Fishtest](https://tests.stockfishchess.org/tests). -If you want to help improve Stockfish, please read this [guideline](https://github.com/glinscott/fishtest/wiki/Creating-my-first-test) +* The latest source can always be found on [GitHub][github-link]. +Discussions about Stockfish take place these days mainly in the [FishCooking][fishcooking-link] +group and on the [Stockfish Discord channel][discord-link]. +The engine testing is done on [Fishtest][fishtest-link]. +If you want to help improve Stockfish, please read this [guideline][guideline-link] first, where the basics of Stockfish development are explained. @@ -333,4 +342,35 @@ exact binary you are distributing. If you make any changes to the source code, these changes must also be made available under the GPL v3. For full details, read the copy of the GPL v3 found in the file named -[*Copying.txt*](https://github.com/official-stockfish/Stockfish/blob/master/Copying.txt). +[*Copying.txt*][license-link]. + +[authors-link]:https://github.com/official-stockfish/Stockfish/blob/master/AUTHORS +[build-badge]:https://img.shields.io/github/workflow/status/official-stockfish/Stockfish/Stockfish?style=for-the-badge&label=stockfish&logo=github +[build-link]:https://github.com/official-stockfish/Stockfish/actions/workflows/stockfish.yml +[commits-badge]:https://img.shields.io/github/commits-since/official-stockfish/Stockfish/latest?style=for-the-badge +[commits-link]:https://github.com/official-stockfish/Stockfish/commits/master +[discord-badge]:https://img.shields.io/discord/435943710472011776?style=for-the-badge&label=discord&logo=Discord +[discord-link]:https://discord.com/invite/aefaxmq +[fishcooking-link]:https://groups.google.com/g/fishcooking +[fishtest-badge]:https://img.shields.io/website?style=for-the-badge&down_color=red&down_message=Offline&label=Fishtest&up_color=success&up_message=Online&url=https%3A%2F%2Ftests.stockfishchess.org%2Ftests +[fishtest-link]:https://tests.stockfishchess.org/tests +[github-link]:https://github.com/official-stockfish/Stockfish +[guideline-link]:https://github.com/glinscott/fishtest/wiki/Creating-my-first-test +[license-badge]:https://img.shields.io/github/license/official-stockfish/Stockfish?style=for-the-badge&label=license&color=success +[license-link]:https://github.com/official-stockfish/Stockfish/blob/master/Copying.txt +[lockpages-link]:https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/enable-the-lock-pages-in-memory-option-windows +[nodchip-link]:https://github.com/nodchip/Stockfish +[programming-link]:https://www.chessprogramming.org/Main_Page +[programmingsf-link]:https://www.chessprogramming.org/Stockfish +[pytorch-link]:https://github.com/glinscott/nnue-pytorch +[rammap-link]:https://docs.microsoft.com/en-us/sysinternals/downloads/rammap +[readme-link]:https://github.com/official-stockfish/Stockfish/blob/master/README.md +[release-badge]:https://img.shields.io/github/v/release/official-stockfish/Stockfish?style=for-the-badge&label=official%20release +[release-link]:https://github.com/official-stockfish/Stockfish/releases/latest +[src-link]:https://github.com/official-stockfish/Stockfish/tree/master/src +[stockfish128-logo]:https://stockfishchess.org/images/logo/icon_128x128.png +[tools-link]:https://github.com/official-stockfish/Stockfish/tree/tools +[uci-link]:https://www.shredderchess.com/download/div/uci.zip +[website-badge]:https://img.shields.io/website?style=for-the-badge&down_color=red&down_message=Offline&label=website&up_color=success&up_message=Online&url=https%3A%2F%2Fstockfishchess.org +[website-link]:https://stockfishchess.org +[worker-link]:https://github.com/glinscott/fishtest/wiki/Running-the-worker:-overview From 232bf19be43117cdecea054c9a825735f0b47842 Mon Sep 17 00:00:00 2001 From: peregrineshahin Date: Thu, 22 Sep 2022 08:49:21 +0300 Subject: [PATCH 68/84] Simplify both position calls in useClassical Simplify the use of classical evaluation when using default settings to only be dependent on piece count and decisive PSQ passed STC: https://tests.stockfishchess.org/tests/view/632d32a7006ef9eb96d86ce9 LLR: 2.96 (-2.94,2.94) <-1.75,0.25> Total: 108048 W: 28904 L: 28763 D: 50381 Ptnml(0-2): 383, 12060, 29006, 12183, 392 passed LTC: https://tests.stockfishchess.org/tests/view/632d705a006ef9eb96d87649 LLR: 2.93 (-2.94,2.94) <-1.75,0.25> Total: 76600 W: 20671 L: 20516 D: 35413 Ptnml(0-2): 34, 7533, 23023, 7664, 46 Inspired by sorais, credit to him. closes https://github.com/official-stockfish/Stockfish/pull/4177 bench 4173163 --- src/evaluate.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index eaad4d55..0657088f 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -1054,12 +1054,10 @@ Value Eval::evaluate(const Position& pos, int* complexity) { Color stm = pos.side_to_move(); Value psq = pos.psq_eg_stm(); - // Deciding between classical and NNUE eval: for high PSQ imbalance we use classical, - // but we switch to NNUE during long shuffling or with high material on the board. - bool useClassical = !useNNUE || - ((pos.count() > 7) - && abs(psq) * 5 > (856 + pos.non_pawn_material() / 64) * (10 + pos.rule50_count())); - + // We use the much less accurate but faster Classical eval when the NNUE + // option is set to false. Otherwise we use the NNUE eval unless the + // PSQ advantage is decisive and several pieces remain (~3 Elo) + bool useClassical = !useNNUE || (pos.count() > 7 && abs(psq) > 1760); if (useClassical) v = Evaluation(pos).value(); else From f436bf77ad2eb42228747d9aa58eeb7403e23d49 Mon Sep 17 00:00:00 2001 From: disservin <45608332+Disservin@users.noreply.github.com> Date: Sun, 18 Sep 2022 11:16:54 +0200 Subject: [PATCH 69/84] Use less reduction for escaping moves This patch reuses the threatenedPieces variable (which is calculated in movepicker) to reduce less in the search tree the moves which escape a capture. passed STC: LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 314352 W: 84042 L: 83328 D: 146982 Ptnml(0-2): 1105, 35084, 84207, 35552, 1228 https://tests.stockfishchess.org/tests/view/63355f37a004bed9a2e4a17f passed LTC: LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 90752 W: 24556 L: 24147 D: 42049 Ptnml(0-2): 59, 8855, 27123, 9296, 43 https://tests.stockfishchess.org/tests/view/63383a7735f43d649ff5fa8b closes https://github.com/official-stockfish/Stockfish/pull/4181 bench: 4114228 --- src/evaluate.cpp | 2 +- src/movepick.cpp | 17 ++++++++--------- src/movepick.h | 2 ++ src/search.cpp | 9 +++++++-- src/thread.cpp | 2 +- src/uci.cpp | 4 ++-- 6 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 0657088f..85700bcc 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -1054,7 +1054,7 @@ Value Eval::evaluate(const Position& pos, int* complexity) { Color stm = pos.side_to_move(); Value psq = pos.psq_eg_stm(); - // We use the much less accurate but faster Classical eval when the NNUE + // We use the much less accurate but faster Classical eval when the NNUE // option is set to false. Otherwise we use the NNUE eval unless the // PSQ advantage is decisive and several pieces remain (~3 Elo) bool useClassical = !useNNUE || (pos.count() > 7 && abs(psq) > 1760); diff --git a/src/movepick.cpp b/src/movepick.cpp index e10454b0..3428a764 100644 --- a/src/movepick.cpp +++ b/src/movepick.cpp @@ -69,6 +69,7 @@ MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHist stage = (pos.checkers() ? EVASION_TT : MAIN_TT) + !(ttm && pos.pseudo_legal(ttm)); + threatenedPieces = 0; } /// MovePicker constructor for quiescence search @@ -106,21 +107,19 @@ void MovePicker::score() { static_assert(Type == CAPTURES || Type == QUIETS || Type == EVASIONS, "Wrong type"); - [[maybe_unused]] Bitboard threatened, threatenedByPawn, threatenedByMinor, threatenedByRook; + [[maybe_unused]] Bitboard threatenedByPawn, threatenedByMinor, threatenedByRook; if constexpr (Type == QUIETS) { Color us = pos.side_to_move(); - // squares threatened by pawns + threatenedByPawn = pos.attacks_by(~us); - // squares threatened by minors or pawns threatenedByMinor = pos.attacks_by(~us) | pos.attacks_by(~us) | threatenedByPawn; - // squares threatened by rooks, minors or pawns threatenedByRook = pos.attacks_by(~us) | threatenedByMinor; - // pieces threatened by pieces of lesser material value - threatened = (pos.pieces(us, QUEEN) & threatenedByRook) - | (pos.pieces(us, ROOK) & threatenedByMinor) - | (pos.pieces(us, KNIGHT, BISHOP) & threatenedByPawn); + // Pieces threatened by pieces of lesser material value + threatenedPieces = (pos.pieces(us, QUEEN) & threatenedByRook) + | (pos.pieces(us, ROOK) & threatenedByMinor) + | (pos.pieces(us, KNIGHT, BISHOP) & threatenedByPawn); } for (auto& m : *this) @@ -134,7 +133,7 @@ void MovePicker::score() { + (*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)] - + (threatened & from_sq(m) ? + + (threatenedPieces & from_sq(m) ? (type_of(pos.moved_piece(m)) == QUEEN && !(to_sq(m) & threatenedByRook) ? 50000 : type_of(pos.moved_piece(m)) == ROOK && !(to_sq(m) & threatenedByMinor) ? 25000 : !(to_sq(m) & threatenedByPawn) ? 15000 diff --git a/src/movepick.h b/src/movepick.h index 979709ae..55fcc644 100644 --- a/src/movepick.h +++ b/src/movepick.h @@ -131,6 +131,8 @@ public: MovePicker(const Position&, Move, Value, Depth, const CapturePieceToHistory*); Move next_move(bool skipQuiets = false); + Bitboard threatenedPieces; + private: template Move select(Pred); template void score(); diff --git a/src/search.cpp b/src/search.cpp index be0f3451..4b6b497a 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -789,7 +789,7 @@ namespace { && depth < 8 && eval - futility_margin(depth, improving) - (ss-1)->statScore / 303 >= beta && eval >= beta - && eval < 28031) // larger than VALUE_KNOWN_WIN, but smaller than TB wins. + && eval < 28031) // larger than VALUE_KNOWN_WIN, but smaller than TB wins return eval; // Step 9. Null move search with verification search (~22 Elo) @@ -1163,7 +1163,12 @@ moves_loop: // When in check, search starts here if (singularQuietLMR) r--; - // Increase reduction if next ply has a lot of fail high else reset count to 0 + // Dicrease reduction if we move a threatened piece (~1 Elo) + if ( depth > 9 + && (mp.threatenedPieces & from_sq(move))) + r--; + + // Increase reduction if next ply has a lot of fail high if ((ss+1)->cutoffCnt > 3 && !PvNode) r++; diff --git a/src/thread.cpp b/src/thread.cpp index c834fa9f..288588b0 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -61,7 +61,7 @@ void Thread::clear() { mainHistory.fill(0); captureHistory.fill(0); previousDepth = 0; - + for (bool inCheck : { false, true }) for (StatsType c : { NoCaptures, Captures }) { diff --git a/src/uci.cpp b/src/uci.cpp index ec106ee9..d5e2c2c3 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -224,7 +224,7 @@ namespace { /// UCI::loop() waits for a command from the stdin, parses it and then calls the appropriate /// function. It also intercepts an end-of-file (EOF) indication from the stdin to ensure a -/// graceful exit if the GUI dies unexpectedly. When called with some command-line arguments, +/// graceful exit if the GUI dies unexpectedly. When called with some command-line arguments, /// like running 'bench', the function returns immediately after the command is executed. /// In addition to the UCI ones, some additional debug commands are also supported. @@ -240,7 +240,7 @@ void UCI::loop(int argc, char* argv[]) { cmd += std::string(argv[i]) + " "; do { - if (argc == 1 && !getline(cin, cmd)) // Wait for an input or an end-of-file (EOF) indication + if (argc == 1 && !getline(cin, cmd)) // Wait for an input or an end-of-file (EOF) indication cmd = "quit"; istringstream is(cmd); From 8bab09749dd00951bfa9c5f89f6e35bded76c8a9 Mon Sep 17 00:00:00 2001 From: FauziAkram Date: Mon, 3 Oct 2022 17:45:05 +0300 Subject: [PATCH 70/84] Mix alpha and statScore for reduction Idea by @xoto10, and tuning by @FauziAkram. Passed STC: LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 57832 W: 15540 L: 15199 D: 27093 Ptnml(0-2): 207, 6343, 15477, 6680, 209 https://tests.stockfishchess.org/tests/view/6338db6f35f43d649ff60fdc passed LTC: LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 50968 W: 13770 L: 13440 D: 23758 Ptnml(0-2): 25, 4905, 15306, 5211, 37 https://tests.stockfishchess.org/tests/view/6339777035f43d649ff62686 Links to the tuning sessions: https://tests.stockfishchess.org/tests/view/63345725a004bed9a2e47b28 https://tests.stockfishchess.org/tests/view/63345728a004bed9a2e47b2a closes https://github.com/official-stockfish/Stockfish/pull/4183 Bench: 4426602 --- src/search.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 4b6b497a..46463b32 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -787,9 +787,9 @@ namespace { // The depth condition is important for mate finding. if ( !ss->ttPv && depth < 8 - && eval - futility_margin(depth, improving) - (ss-1)->statScore / 303 >= beta + && eval - futility_margin(depth, improving) - (ss-1)->statScore / 301 >= beta && eval >= beta - && eval < 28031) // larger than VALUE_KNOWN_WIN, but smaller than TB wins + && eval < 28692) // larger than VALUE_KNOWN_WIN, but smaller than TB wins return eval; // Step 9. Null move search with verification search (~22 Elo) @@ -1179,7 +1179,7 @@ moves_loop: // When in check, search starts here - 4433; // Decrease/increase reduction for moves with a good/bad history (~30 Elo) - r -= ss->statScore / 13628; + r -= (ss->statScore + 5 * alpha) / 15448; // In general we want to cap the LMR depth search at newDepth, but when // reduction is negative, we allow this move a limited search extension From da937e219ee7981966ac29fc11c43470a505ff18 Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Wed, 5 Oct 2022 22:59:05 +0200 Subject: [PATCH 71/84] Revert "Mix alpha and statScore for reduction" This reverts commit 8bab09749dd00951bfa9c5f89f6e35bded76c8a9. In this form the patch reduces mate finding effectiveness, as the large alpha value has negative influence on the reductions. see also https://github.com/official-stockfish/Stockfish/pull/4183 Bench: 4114228 --- src/search.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 46463b32..4b6b497a 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -787,9 +787,9 @@ namespace { // The depth condition is important for mate finding. if ( !ss->ttPv && depth < 8 - && eval - futility_margin(depth, improving) - (ss-1)->statScore / 301 >= beta + && eval - futility_margin(depth, improving) - (ss-1)->statScore / 303 >= beta && eval >= beta - && eval < 28692) // larger than VALUE_KNOWN_WIN, but smaller than TB wins + && eval < 28031) // larger than VALUE_KNOWN_WIN, but smaller than TB wins return eval; // Step 9. Null move search with verification search (~22 Elo) @@ -1179,7 +1179,7 @@ moves_loop: // When in check, search starts here - 4433; // Decrease/increase reduction for moves with a good/bad history (~30 Elo) - r -= (ss->statScore + 5 * alpha) / 15448; + r -= ss->statScore / 13628; // In general we want to cap the LMR depth search at newDepth, but when // reduction is negative, we allow this move a limited search extension From d5271af0ee28cb52e1033f183f3b34754aa5efa0 Mon Sep 17 00:00:00 2001 From: Giacomo Lorenzetti Date: Wed, 5 Oct 2022 13:08:00 +0200 Subject: [PATCH 72/84] Remove old line in "Futility pruning for captures" The line is no longer needed after https://github.com/official-stockfish/Stockfish/commit/910cf8b21839eb9f1991934a5436eea112021723. This patch incidentally applies "Futility Pruning for Captures" also in case of en-passant, changing the bench signature. Passed STC: https://tests.stockfishchess.org/tests/view/6332c1f1208c26088697b731 LLR: 2.96 (-2.94,2.94) <-1.75,0.25> Total: 68760 W: 18440 L: 18256 D: 32064 Ptnml(0-2): 267, 7530, 18595, 7728, 260 Passed LTC: https://tests.stockfishchess.org/tests/view/633312e9208c26088697c59b LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 455552 W: 121910 L: 122123 D: 211519 Ptnml(0-2): 253, 45439, 136600, 45236, 248 closes https://github.com/official-stockfish/Stockfish/pull/4185 Bench: 4374521 --- src/search.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 4b6b497a..7019635d 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1002,8 +1002,7 @@ moves_loop: // When in check, search starts here || givesCheck) { // Futility pruning for captures (~0 Elo) - if ( !pos.empty(to_sq(move)) - && !givesCheck + if ( !givesCheck && !PvNode && lmrDepth < 7 && !ss->inCheck From e90341f9c9cd24e75aba2485b2ab1e445f4a5b70 Mon Sep 17 00:00:00 2001 From: Stefan Geschwentner Date: Tue, 4 Oct 2022 18:16:20 +0200 Subject: [PATCH 73/84] Tweak history initialization Simplify initialization of continuation history by using everywhere the same starting value. STC: LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 90952 W: 24312 L: 24153 D: 42487 Ptnml(0-2): 356, 10168, 24290, 10285, 377 https://tests.stockfishchess.org/tests/view/633948f235f43d649ff61fd0 LTC: LLR: 2.96 (-2.94,2.94) <-1.75,0.25> Total: 162416 W: 43540 L: 43466 D: 75410 Ptnml(0-2): 77, 16289, 48417, 16333, 92 https://tests.stockfishchess.org/tests/view/6339ee8a35f43d649ff63986 closes https://github.com/official-stockfish/Stockfish/pull/4186 Bench: 4156027 --- src/search.cpp | 4 ++-- src/search.h | 3 --- src/thread.cpp | 7 ++----- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 7019635d..3c2ae3e5 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1549,8 +1549,8 @@ moves_loop: // When in check, search starts here // Continuation history based pruning (~2 Elo) if ( !capture && bestValue > VALUE_TB_LOSS_IN_MAX_PLY - && (*contHist[0])[pos.moved_piece(move)][to_sq(move)] < CounterMovePruneThreshold - && (*contHist[1])[pos.moved_piece(move)][to_sq(move)] < CounterMovePruneThreshold) + && (*contHist[0])[pos.moved_piece(move)][to_sq(move)] < 0 + && (*contHist[1])[pos.moved_piece(move)][to_sq(move)] < 0) continue; // movecount pruning for quiet check evasions diff --git a/src/search.h b/src/search.h index 4ad5784f..f264bcae 100644 --- a/src/search.h +++ b/src/search.h @@ -31,9 +31,6 @@ class Position; namespace Search { -/// Threshold used for countermoves based pruning -constexpr int CounterMovePruneThreshold = 0; - /// Stack struct keeps track of the information we need to remember from nodes /// shallower and deeper in the tree during the search. Each search thread has diff --git a/src/thread.cpp b/src/thread.cpp index 288588b0..9ce408e0 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -64,12 +64,9 @@ void Thread::clear() { for (bool inCheck : { false, true }) for (StatsType c : { NoCaptures, Captures }) - { for (auto& to : continuationHistory[inCheck][c]) - for (auto& h : to) - h->fill(-71); - continuationHistory[inCheck][c][NO_PIECE][0]->fill(Search::CounterMovePruneThreshold - 1); - } + for (auto& h : to) + h->fill(-71); } From 93f71ecfe1d26e5ccc813318f420b8363cd26003 Mon Sep 17 00:00:00 2001 From: mstembera Date: Fri, 14 Oct 2022 14:41:08 -0700 Subject: [PATCH 74/84] Optimize make_index() using templates and lookup tables. https://tests.stockfishchess.org/tests/view/634517e54bc7650f07542f99 LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 642672 W: 171819 L: 170658 D: 300195 Ptnml(0-2): 2278, 68077, 179416, 69336, 2229 this also introduces `-flto-partition=one` as suggested by MinetaS (Syine Mineta) to avoid linking errors due to LTO on 32 bit mingw. This change was tested in isolation as well https://tests.stockfishchess.org/tests/view/634aacf84bc7650f0755188b LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 119352 W: 31986 L: 31862 D: 55504 Ptnml(0-2): 439, 12624, 33400, 12800, 413 closes https://github.com/official-stockfish/Stockfish/pull/4199 No functional change --- src/Makefile | 4 +- src/nnue/features/half_ka_v2_hm.cpp | 33 ++++++++------- src/nnue/features/half_ka_v2_hm.h | 62 +++++++++++++++++++-------- src/nnue/nnue_feature_transformer.h | 65 +++++++++++++++-------------- 4 files changed, 96 insertions(+), 68 deletions(-) diff --git a/src/Makefile b/src/Makefile index 8315f33d..880710fe 100644 --- a/src/Makefile +++ b/src/Makefile @@ -698,11 +698,9 @@ ifeq ($(debug), no) # To use LTO and static linking on Windows, # the tool chain requires gcc version 10.1 or later. else ifeq ($(comp),mingw) - ifneq ($(arch),i386) - CXXFLAGS += -flto + CXXFLAGS += -flto -flto-partition=one LDFLAGS += $(CXXFLAGS) -save-temps endif - endif endif endif diff --git a/src/nnue/features/half_ka_v2_hm.cpp b/src/nnue/features/half_ka_v2_hm.cpp index 07a1d7a1..11e05c94 100644 --- a/src/nnue/features/half_ka_v2_hm.cpp +++ b/src/nnue/features/half_ka_v2_hm.cpp @@ -24,50 +24,51 @@ namespace Stockfish::Eval::NNUE::Features { - // Orient a square according to perspective (rotates by 180 for black) - inline Square HalfKAv2_hm::orient(Color perspective, Square s, Square ksq) { - return Square(int(s) ^ (bool(perspective) * SQ_A8) ^ ((file_of(ksq) < FILE_E) * SQ_H1)); - } - // Index of a feature for a given king position and another piece on some square - inline IndexType HalfKAv2_hm::make_index(Color perspective, Square s, Piece pc, Square ksq) { - Square o_ksq = orient(perspective, ksq, ksq); - return IndexType(orient(perspective, s, ksq) + PieceSquareIndex[perspective][pc] + PS_NB * KingBuckets[o_ksq]); + template + inline IndexType HalfKAv2_hm::make_index(Square s, Piece pc, Square ksq) { + return IndexType((int(s) ^ OrientTBL[Perspective][ksq]) + PieceSquareIndex[Perspective][pc] + KingBuckets[Perspective][ksq]); } // Get a list of indices for active features + template void HalfKAv2_hm::append_active_indices( const Position& pos, - Color perspective, IndexList& active ) { - Square ksq = pos.square(perspective); + Square ksq = pos.square(Perspective); Bitboard bb = pos.pieces(); while (bb) { Square s = pop_lsb(bb); - active.push_back(make_index(perspective, s, pos.piece_on(s), ksq)); + active.push_back(make_index(s, pos.piece_on(s), ksq)); } } - + // Explicit template instantiations + template void HalfKAv2_hm::append_active_indices(const Position& pos, IndexList& active); + template void HalfKAv2_hm::append_active_indices(const Position& pos, IndexList& active); + // append_changed_indices() : get a list of indices for recently changed features - + template void HalfKAv2_hm::append_changed_indices( Square ksq, const DirtyPiece& dp, - Color perspective, IndexList& removed, IndexList& added ) { for (int i = 0; i < dp.dirty_num; ++i) { if (dp.from[i] != SQ_NONE) - removed.push_back(make_index(perspective, dp.from[i], dp.piece[i], ksq)); + removed.push_back(make_index(dp.from[i], dp.piece[i], ksq)); if (dp.to[i] != SQ_NONE) - added.push_back(make_index(perspective, dp.to[i], dp.piece[i], ksq)); + added.push_back(make_index(dp.to[i], dp.piece[i], ksq)); } } + // Explicit template instantiations + template void HalfKAv2_hm::append_changed_indices(Square ksq, const DirtyPiece& dp, IndexList& removed, IndexList& added); + template void HalfKAv2_hm::append_changed_indices(Square ksq, const DirtyPiece& dp, IndexList& removed, IndexList& added); + int HalfKAv2_hm::update_cost(const StateInfo* st) { return st->dirtyPiece.dirty_num; } diff --git a/src/nnue/features/half_ka_v2_hm.h b/src/nnue/features/half_ka_v2_hm.h index 1e6da0bf..a95d4328 100644 --- a/src/nnue/features/half_ka_v2_hm.h +++ b/src/nnue/features/half_ka_v2_hm.h @@ -49,8 +49,8 @@ namespace Stockfish::Eval::NNUE::Features { PS_B_ROOK = 7 * SQUARE_NB, PS_W_QUEEN = 8 * SQUARE_NB, PS_B_QUEEN = 9 * SQUARE_NB, - PS_KING = 10 * SQUARE_NB, - PS_NB = 11 * SQUARE_NB + PS_KING = 10 * SQUARE_NB, + PS_NB = 11 * SQUARE_NB }; static constexpr IndexType PieceSquareIndex[COLOR_NB][PIECE_NB] = { @@ -62,11 +62,9 @@ namespace Stockfish::Eval::NNUE::Features { PS_NONE, PS_W_PAWN, PS_W_KNIGHT, PS_W_BISHOP, PS_W_ROOK, PS_W_QUEEN, PS_KING, PS_NONE } }; - // Orient a square according to perspective (rotates by 180 for black) - static Square orient(Color perspective, Square s, Square ksq); - // Index of a feature for a given king position and another piece on some square - static IndexType make_index(Color perspective, Square s, Piece pc, Square ksq); + template + static IndexType make_index(Square s, Piece pc, Square ksq); public: // Feature name @@ -79,15 +77,45 @@ namespace Stockfish::Eval::NNUE::Features { static constexpr IndexType Dimensions = static_cast(SQUARE_NB) * static_cast(PS_NB) / 2; - static constexpr int KingBuckets[64] = { - -1, -1, -1, -1, 31, 30, 29, 28, - -1, -1, -1, -1, 27, 26, 25, 24, - -1, -1, -1, -1, 23, 22, 21, 20, - -1, -1, -1, -1, 19, 18, 17, 16, - -1, -1, -1, -1, 15, 14, 13, 12, - -1, -1, -1, -1, 11, 10, 9, 8, - -1, -1, -1, -1, 7, 6, 5, 4, - -1, -1, -1, -1, 3, 2, 1, 0 +#define B(v) (v * PS_NB) + static constexpr int KingBuckets[COLOR_NB][SQUARE_NB] = { + { B(28), B(29), B(30), B(31), B(31), B(30), B(29), B(28), + B(24), B(25), B(26), B(27), B(27), B(26), B(25), B(24), + B(20), B(21), B(22), B(23), B(23), B(22), B(21), B(20), + B(16), B(17), B(18), B(19), B(19), B(18), B(17), B(16), + B(12), B(13), B(14), B(15), B(15), B(14), B(13), B(12), + B( 8), B( 9), B(10), B(11), B(11), B(10), B( 9), B( 8), + B( 4), B( 5), B( 6), B( 7), B( 7), B( 6), B( 5), B( 4), + B( 0), B( 1), B( 2), B( 3), B( 3), B( 2), B( 1), B( 0) }, + { B( 0), B( 1), B( 2), B( 3), B( 3), B( 2), B( 1), B( 0), + B( 4), B( 5), B( 6), B( 7), B( 7), B( 6), B( 5), B( 4), + B( 8), B( 9), B(10), B(11), B(11), B(10), B( 9), B( 8), + B(12), B(13), B(14), B(15), B(15), B(14), B(13), B(12), + B(16), B(17), B(18), B(19), B(19), B(18), B(17), B(16), + B(20), B(21), B(22), B(23), B(23), B(22), B(21), B(20), + B(24), B(25), B(26), B(27), B(27), B(26), B(25), B(24), + B(28), B(29), B(30), B(31), B(31), B(30), B(29), B(28) } + }; +#undef B + + // Orient a square according to perspective (rotates by 180 for black) + static constexpr int OrientTBL[COLOR_NB][SQUARE_NB] = { + { SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1, + SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1, + SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1, + SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1, + SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1, + SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1, + SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1, + SQ_H1, SQ_H1, SQ_H1, SQ_H1, SQ_A1, SQ_A1, SQ_A1, SQ_A1 }, + { SQ_H8, SQ_H8, SQ_H8, SQ_H8, SQ_A8, SQ_A8, SQ_A8, SQ_A8, + SQ_H8, SQ_H8, SQ_H8, SQ_H8, SQ_A8, SQ_A8, SQ_A8, SQ_A8, + SQ_H8, SQ_H8, SQ_H8, SQ_H8, SQ_A8, SQ_A8, SQ_A8, SQ_A8, + SQ_H8, SQ_H8, SQ_H8, SQ_H8, SQ_A8, SQ_A8, SQ_A8, SQ_A8, + SQ_H8, SQ_H8, SQ_H8, SQ_H8, SQ_A8, SQ_A8, SQ_A8, SQ_A8, + SQ_H8, SQ_H8, SQ_H8, SQ_H8, SQ_A8, SQ_A8, SQ_A8, SQ_A8, + SQ_H8, SQ_H8, SQ_H8, SQ_H8, SQ_A8, SQ_A8, SQ_A8, SQ_A8, + SQ_H8, SQ_H8, SQ_H8, SQ_H8, SQ_A8, SQ_A8, SQ_A8, SQ_A8 } }; // Maximum number of simultaneously active features. @@ -95,16 +123,16 @@ namespace Stockfish::Eval::NNUE::Features { using IndexList = ValueList; // Get a list of indices for active features + template static void append_active_indices( const Position& pos, - Color perspective, IndexList& active); // Get a list of indices for recently changed features + template static void append_changed_indices( Square ksq, const DirtyPiece& dp, - Color perspective, IndexList& removed, IndexList& added ); diff --git a/src/nnue/nnue_feature_transformer.h b/src/nnue/nnue_feature_transformer.h index 34d7292c..b6dd54d3 100644 --- a/src/nnue/nnue_feature_transformer.h +++ b/src/nnue/nnue_feature_transformer.h @@ -271,8 +271,8 @@ namespace Stockfish::Eval::NNUE { // Convert input features std::int32_t transform(const Position& pos, OutputType* output, int bucket) const { - update_accumulator(pos, WHITE); - update_accumulator(pos, BLACK); + update_accumulator(pos); + update_accumulator(pos); const Color perspectives[2] = {pos.side_to_move(), ~pos.side_to_move()}; const auto& accumulation = pos.state()->accumulator.accumulation; @@ -338,7 +338,8 @@ namespace Stockfish::Eval::NNUE { private: - void update_accumulator(const Position& pos, const Color perspective) const { + template + void update_accumulator(const Position& pos) const { // The size must be enough to contain the largest possible update. // That might depend on the feature set and generally relies on the @@ -356,18 +357,18 @@ namespace Stockfish::Eval::NNUE { // of the estimated gain in terms of features to be added/subtracted. StateInfo *st = pos.state(), *next = nullptr; int gain = FeatureSet::refresh_cost(pos); - while (st->previous && !st->accumulator.computed[perspective]) + while (st->previous && !st->accumulator.computed[Perspective]) { // This governs when a full feature refresh is needed and how many // updates are better than just one full refresh. - if ( FeatureSet::requires_refresh(st, perspective) + if ( FeatureSet::requires_refresh(st, Perspective) || (gain -= FeatureSet::update_cost(st) + 1) < 0) break; next = st; st = st->previous; } - if (st->accumulator.computed[perspective]) + if (st->accumulator.computed[Perspective]) { if (next == nullptr) return; @@ -376,17 +377,17 @@ namespace Stockfish::Eval::NNUE { // accumulator. Then, we update the current accumulator (pos.state()). // Gather all features to be updated. - const Square ksq = pos.square(perspective); + const Square ksq = pos.square(Perspective); FeatureSet::IndexList removed[2], added[2]; - FeatureSet::append_changed_indices( - ksq, next->dirtyPiece, perspective, removed[0], added[0]); + FeatureSet::append_changed_indices( + ksq, next->dirtyPiece, removed[0], added[0]); for (StateInfo *st2 = pos.state(); st2 != next; st2 = st2->previous) - FeatureSet::append_changed_indices( - ksq, st2->dirtyPiece, perspective, removed[1], added[1]); + FeatureSet::append_changed_indices( + ksq, st2->dirtyPiece, removed[1], added[1]); // Mark the accumulators as computed. - next->accumulator.computed[perspective] = true; - pos.state()->accumulator.computed[perspective] = true; + next->accumulator.computed[Perspective] = true; + pos.state()->accumulator.computed[Perspective] = true; // Now update the accumulators listed in states_to_update[], where the last element is a sentinel. StateInfo *states_to_update[3] = @@ -396,7 +397,7 @@ namespace Stockfish::Eval::NNUE { { // Load accumulator auto accTile = reinterpret_cast( - &st->accumulator.accumulation[perspective][j * TileHeight]); + &st->accumulator.accumulation[Perspective][j * TileHeight]); for (IndexType k = 0; k < NumRegs; ++k) acc[k] = vec_load(&accTile[k]); @@ -422,7 +423,7 @@ namespace Stockfish::Eval::NNUE { // Store accumulator accTile = reinterpret_cast( - &states_to_update[i]->accumulator.accumulation[perspective][j * TileHeight]); + &states_to_update[i]->accumulator.accumulation[Perspective][j * TileHeight]); for (IndexType k = 0; k < NumRegs; ++k) vec_store(&accTile[k], acc[k]); } @@ -432,7 +433,7 @@ namespace Stockfish::Eval::NNUE { { // Load accumulator auto accTilePsqt = reinterpret_cast( - &st->accumulator.psqtAccumulation[perspective][j * PsqtTileHeight]); + &st->accumulator.psqtAccumulation[Perspective][j * PsqtTileHeight]); for (std::size_t k = 0; k < NumPsqtRegs; ++k) psqt[k] = vec_load_psqt(&accTilePsqt[k]); @@ -458,7 +459,7 @@ namespace Stockfish::Eval::NNUE { // Store accumulator accTilePsqt = reinterpret_cast( - &states_to_update[i]->accumulator.psqtAccumulation[perspective][j * PsqtTileHeight]); + &states_to_update[i]->accumulator.psqtAccumulation[Perspective][j * PsqtTileHeight]); for (std::size_t k = 0; k < NumPsqtRegs; ++k) vec_store_psqt(&accTilePsqt[k], psqt[k]); } @@ -467,12 +468,12 @@ namespace Stockfish::Eval::NNUE { #else for (IndexType i = 0; states_to_update[i]; ++i) { - std::memcpy(states_to_update[i]->accumulator.accumulation[perspective], - st->accumulator.accumulation[perspective], + std::memcpy(states_to_update[i]->accumulator.accumulation[Perspective], + st->accumulator.accumulation[Perspective], HalfDimensions * sizeof(BiasType)); for (std::size_t k = 0; k < PSQTBuckets; ++k) - states_to_update[i]->accumulator.psqtAccumulation[perspective][k] = st->accumulator.psqtAccumulation[perspective][k]; + states_to_update[i]->accumulator.psqtAccumulation[Perspective][k] = st->accumulator.psqtAccumulation[Perspective][k]; st = states_to_update[i]; @@ -482,10 +483,10 @@ namespace Stockfish::Eval::NNUE { const IndexType offset = HalfDimensions * index; for (IndexType j = 0; j < HalfDimensions; ++j) - st->accumulator.accumulation[perspective][j] -= weights[offset + j]; + st->accumulator.accumulation[Perspective][j] -= weights[offset + j]; for (std::size_t k = 0; k < PSQTBuckets; ++k) - st->accumulator.psqtAccumulation[perspective][k] -= psqtWeights[index * PSQTBuckets + k]; + st->accumulator.psqtAccumulation[Perspective][k] -= psqtWeights[index * PSQTBuckets + k]; } // Difference calculation for the activated features @@ -494,10 +495,10 @@ namespace Stockfish::Eval::NNUE { const IndexType offset = HalfDimensions * index; for (IndexType j = 0; j < HalfDimensions; ++j) - st->accumulator.accumulation[perspective][j] += weights[offset + j]; + st->accumulator.accumulation[Perspective][j] += weights[offset + j]; for (std::size_t k = 0; k < PSQTBuckets; ++k) - st->accumulator.psqtAccumulation[perspective][k] += psqtWeights[index * PSQTBuckets + k]; + st->accumulator.psqtAccumulation[Perspective][k] += psqtWeights[index * PSQTBuckets + k]; } } #endif @@ -506,9 +507,9 @@ namespace Stockfish::Eval::NNUE { { // Refresh the accumulator auto& accumulator = pos.state()->accumulator; - accumulator.computed[perspective] = true; + accumulator.computed[Perspective] = true; FeatureSet::IndexList active; - FeatureSet::append_active_indices(pos, perspective, active); + FeatureSet::append_active_indices(pos, active); #ifdef VECTOR for (IndexType j = 0; j < HalfDimensions / TileHeight; ++j) @@ -528,7 +529,7 @@ namespace Stockfish::Eval::NNUE { } auto accTile = reinterpret_cast( - &accumulator.accumulation[perspective][j * TileHeight]); + &accumulator.accumulation[Perspective][j * TileHeight]); for (unsigned k = 0; k < NumRegs; k++) vec_store(&accTile[k], acc[k]); } @@ -548,27 +549,27 @@ namespace Stockfish::Eval::NNUE { } auto accTilePsqt = reinterpret_cast( - &accumulator.psqtAccumulation[perspective][j * PsqtTileHeight]); + &accumulator.psqtAccumulation[Perspective][j * PsqtTileHeight]); for (std::size_t k = 0; k < NumPsqtRegs; ++k) vec_store_psqt(&accTilePsqt[k], psqt[k]); } #else - std::memcpy(accumulator.accumulation[perspective], biases, + std::memcpy(accumulator.accumulation[Perspective], biases, HalfDimensions * sizeof(BiasType)); for (std::size_t k = 0; k < PSQTBuckets; ++k) - accumulator.psqtAccumulation[perspective][k] = 0; + accumulator.psqtAccumulation[Perspective][k] = 0; for (const auto index : active) { const IndexType offset = HalfDimensions * index; for (IndexType j = 0; j < HalfDimensions; ++j) - accumulator.accumulation[perspective][j] += weights[offset + j]; + accumulator.accumulation[Perspective][j] += weights[offset + j]; for (std::size_t k = 0; k < PSQTBuckets; ++k) - accumulator.psqtAccumulation[perspective][k] += psqtWeights[index * PSQTBuckets + k]; + accumulator.psqtAccumulation[Perspective][k] += psqtWeights[index * PSQTBuckets + k]; } #endif } From f97a86e213fd352a1a7017e5c98608cefc3ef1fa Mon Sep 17 00:00:00 2001 From: Dubslow Date: Fri, 7 Oct 2022 05:44:29 -0500 Subject: [PATCH 75/84] Remove depth condition from razoring The eval condition depends on depth anyways, so this patch is nearly (not quite) non-functional passed STC: https://tests.stockfishchess.org/tests/view/63428169fb7ccb2ea9be2629 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 185992 W: 49612 L: 49558 D: 86822 Ptnml(0-2): 618, 19956, 51842, 19914, 666 passed LTC: https://tests.stockfishchess.org/tests/view/634418b14bc7650f07540760 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 126816 W: 34147 L: 34043 D: 58626 Ptnml(0-2): 74, 11941, 39281, 12031, 81 closes https://github.com/official-stockfish/Stockfish/pull/4196 bench 4148700 --- src/search.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 3c2ae3e5..898de875 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -775,8 +775,7 @@ namespace { // Step 7. Razoring. // If eval is really low check with qsearch if it can exceed alpha, if it can't, // return a fail low. - if ( depth <= 7 - && eval < alpha - 369 - 254 * depth * depth) + if (eval < alpha - 369 - 254 * depth * depth) { value = qsearch(pos, ss, alpha - 1, alpha); if (value < alpha) From d6b6360ff5dcdffa141f50d0a81d0be7c6324c71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ste=CC=81phane=20Nicolet?= Date: Sun, 9 Oct 2022 00:27:26 +0200 Subject: [PATCH 76/84] Tweak the formula for NNUE complexity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Joint work by Ofek Shochat and Stéphane Nicolet. passed STC: LLR: 2.95 (-2.94,2.94) <0.00,2.00> Total: 93288 W: 24996 L: 24601 D: 43691 Ptnml(0-2): 371, 10263, 24989, 10642, 379 https://tests.stockfishchess.org/tests/view/63448f4f4bc7650f07541987 passed LTC: LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 84168 W: 22771 L: 22377 D: 39020 Ptnml(0-2): 47, 8181, 25234, 8575, 47 https://tests.stockfishchess.org/tests/view/6345186d4bc7650f07542fbd ================ It seems there are two effects with this patch: effect A : If Stockfish is winning at root, we have optimism > 0 for all leaves in the search tree where Stockfish is to move. There, if (psq - nnue) > 0 (ie if the advantage is more materialistic than positional), then the product D = optimism * (psq - nnue) will be positive, nnueComplexity will increase, and the eval will increase from SF point of view. So the effect A is that if Stockfish is winning at root, she will slightly favor in the search tree (in other words, search more) the positions where she can convert her advantage via materialist means. effect B : If Stockfish is losing at root, we have optimism > 0 for all leaves in the search tree where the opponent is to move. There, if (psq - nnue) < 0 (ie if the opponent advantage is more positional than materialistic), then the product D = optimism * (psq-nnue) will be negative, nnueComplexity will decrease, and the eval will decrease from the opponent point of view. So the effect B is that Stockfish will slightly favor in the search tree (search more) the branches where she can defend by slowly reducing the opponent positional advantage. ================= closes https://github.com/official-stockfish/Stockfish/pull/4195 bench: 4673898 --- src/evaluate.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 85700bcc..d5844593 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -1051,25 +1051,33 @@ make_v: Value Eval::evaluate(const Position& pos, int* complexity) { Value v; - Color stm = pos.side_to_move(); Value psq = pos.psq_eg_stm(); // We use the much less accurate but faster Classical eval when the NNUE // option is set to false. Otherwise we use the NNUE eval unless the - // PSQ advantage is decisive and several pieces remain (~3 Elo) + // PSQ advantage is decisive and several pieces remain. (~3 Elo) bool useClassical = !useNNUE || (pos.count() > 7 && abs(psq) > 1760); + if (useClassical) v = Evaluation(pos).value(); else { int nnueComplexity; int scale = 1064 + 106 * pos.non_pawn_material() / 5120; + + Color stm = pos.side_to_move(); Value optimism = pos.this_thread()->optimism[stm]; Value nnue = NNUE::evaluate(pos, true, &nnueComplexity); + // Blend nnue complexity with (semi)classical complexity - nnueComplexity = (104 * nnueComplexity + 131 * abs(nnue - psq)) / 256; - if (complexity) // Return hybrid NNUE complexity to caller + nnueComplexity = ( 416 * nnueComplexity + + 424 * abs(psq - nnue) + + (optimism > 0 ? int(optimism) * int(psq - nnue) : 0) + ) / 1024; + + // Return hybrid NNUE complexity to caller + if (complexity) *complexity = nnueComplexity; optimism = optimism * (269 + nnueComplexity) / 256; From 9be2977da7921aedfd3215f1f4b5f522359effa0 Mon Sep 17 00:00:00 2001 From: xoto10 Date: Sat, 8 Oct 2022 14:53:14 +0100 Subject: [PATCH 77/84] Adjust timeman constants Adjust timeman constants to use more time in early part of game. STC @ 10+0.1 th 1 : LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 93984 W: 25177 L: 24787 D: 44020 Ptnml(0-2): 350, 10096, 25729, 10448, 369 https://tests.stockfishchess.org/tests/live_elo/6339077135f43d649ff6162a LTC @ 60+0.6 th 1 : LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 329368 W: 88953 L: 88093 D: 152322 Ptnml(0-2): 170, 31457, 100594, 32269, 194 https://tests.stockfishchess.org/tests/live_elo/6339baed35f43d649ff63142 Sudden death 10+0 : LLR: 2.94 (-2.94,2.94) <0.00,2.00> Total: 20400 W: 5908 L: 5588 D: 8904 Ptnml(0-2): 177, 2252, 5128, 2360, 283 https://tests.stockfishchess.org/tests/live_elo/6347c9384bc7650f07549ba7 Sudden death 10+0, no adjudication : LLR: 2.96 (-2.94,2.94) <0.00,2.00> Total: 17920 W: 4755 L: 4442 D: 8723 Ptnml(0-2): 137, 1985, 4466, 2172, 200 https://tests.stockfishchess.org/tests/live_elo/634806e84bc7650f0754a639 closes https://github.com/official-stockfish/Stockfish/pull/4188 No functional change --- src/timeman.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/timeman.cpp b/src/timeman.cpp index 0400401e..cab0d767 100644 --- a/src/timeman.cpp +++ b/src/timeman.cpp @@ -80,7 +80,7 @@ void TimeManagement::init(Search::LimitsType& limits, Color us, int ply) { // game time for the current move, so also cap to 20% of available game time. if (limits.movestogo == 0) { - optScale = std::min(0.0084 + std::pow(ply + 3.0, 0.5) * 0.0042, + optScale = std::min(0.0120 + std::pow(ply + 3.0, 0.45) * 0.0039, 0.2 * limits.time[us] / double(timeLeft)) * optExtra; maxScale = std::min(7.0, 4.0 + ply / 12.0); From 79c5f3a69247b44ee6362a3d9236cd9bc048c5f5 Mon Sep 17 00:00:00 2001 From: Rodrigo Roim Date: Fri, 7 Oct 2022 16:55:07 -0700 Subject: [PATCH 78/84] Fix tablebase probe for dtz >1000 w/o 50 move rule For qn4N1/6R1/3K4/8/B2k4/8/8/8 w - - 0 1, white loses with DTZ 1034. See https://syzygy-tables.info/?fen=qn4N1/6R1/3K4/8/B2k4/8/8/8_w_-_-_0_1 Prior to this fix, due to a too small hard-coded value, Stockfish interpreted this as winning. The new value picked (1<<18) is large enough to deal with the largest DTZ values that can be stored in the current syzygy format. closes https://github.com/official-stockfish/Stockfish/pull/4187 No functional change. --- AUTHORS | 1 + src/syzygy/tbprobe.cpp | 13 +++++++------ src/syzygy/tbprobe.h | 2 -- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/AUTHORS b/AUTHORS index fc885acb..804232f1 100644 --- a/AUTHORS +++ b/AUTHORS @@ -169,6 +169,7 @@ renouve Reuven Peleg Richard Lloyd Rodrigo Exterckötter Tjäder +Rodrigo Roim (roim) Ron Britvich (Britvich) Ronald de Man (syzygy1, syzygy) rqs diff --git a/src/syzygy/tbprobe.cpp b/src/syzygy/tbprobe.cpp index 43af89f0..f2de036d 100644 --- a/src/syzygy/tbprobe.cpp +++ b/src/syzygy/tbprobe.cpp @@ -59,6 +59,7 @@ namespace Stockfish { namespace { constexpr int TBPIECES = 7; // Max number of supported pieces +constexpr int MAX_DTZ = 1 << 18; // Max DTZ supported, large enough to deal with the syzygy TB limit. enum { BigEndian, LittleEndian }; enum TBType { WDL, DTZ }; // Used as template parameter @@ -1522,7 +1523,7 @@ bool Tablebases::root_probe(Position& pos, Search::RootMoves& rootMoves) { // Check whether a position was repeated since the last zeroing move. bool rep = pos.has_repeated(); - int dtz, bound = Options["Syzygy50MoveRule"] ? 900 : 1; + int dtz, bound = Options["Syzygy50MoveRule"] ? (MAX_DTZ - 100) : 1; // Probe and rank each move for (auto& m : rootMoves) @@ -1565,8 +1566,8 @@ bool Tablebases::root_probe(Position& pos, Search::RootMoves& rootMoves) { // Better moves are ranked higher. Certain wins are ranked equally. // Losing moves are ranked equally unless a 50-move draw is in sight. - int r = dtz > 0 ? (dtz + cnt50 <= 99 && !rep ? 1000 : 1000 - (dtz + cnt50)) - : dtz < 0 ? (-dtz * 2 + cnt50 < 100 ? -1000 : -1000 + (-dtz + cnt50)) + int r = dtz > 0 ? (dtz + cnt50 <= 99 && !rep ? MAX_DTZ : MAX_DTZ - (dtz + cnt50)) + : dtz < 0 ? (-dtz * 2 + cnt50 < 100 ? -MAX_DTZ : -MAX_DTZ + (-dtz + cnt50)) : 0; m.tbRank = r; @@ -1574,9 +1575,9 @@ bool Tablebases::root_probe(Position& pos, Search::RootMoves& rootMoves) { // 1 cp to cursed wins and let it grow to 49 cp as the positions gets // closer to a real win. m.tbScore = r >= bound ? VALUE_MATE - MAX_PLY - 1 - : r > 0 ? Value((std::max( 3, r - 800) * int(PawnValueEg)) / 200) + : r > 0 ? Value((std::max( 3, r - (MAX_DTZ - 200)) * int(PawnValueEg)) / 200) : r == 0 ? VALUE_DRAW - : r > -bound ? Value((std::min(-3, r + 800) * int(PawnValueEg)) / 200) + : r > -bound ? Value((std::min(-3, r + (MAX_DTZ - 200)) * int(PawnValueEg)) / 200) : -VALUE_MATE + MAX_PLY + 1; } @@ -1590,7 +1591,7 @@ bool Tablebases::root_probe(Position& pos, Search::RootMoves& rootMoves) { // A return value false indicates that not all probes were successful. bool Tablebases::root_probe_wdl(Position& pos, Search::RootMoves& rootMoves) { - static const int WDL_to_rank[] = { -1000, -899, 0, 899, 1000 }; + static const int WDL_to_rank[] = { -MAX_DTZ, -MAX_DTZ + 101, 0, MAX_DTZ - 101, MAX_DTZ }; ProbeState result; StateInfo st; diff --git a/src/syzygy/tbprobe.h b/src/syzygy/tbprobe.h index c2917fef..179c7572 100644 --- a/src/syzygy/tbprobe.h +++ b/src/syzygy/tbprobe.h @@ -31,8 +31,6 @@ enum WDLScore { WDLDraw = 0, // Draw WDLCursedWin = 1, // Win, but draw under 50-move rule WDLWin = 2, // Win - - WDLScoreNone = -1000 }; // Possible states after a probing operation From 234d2156fdf011a7bb850e3d6172ed2290ab3ad2 Mon Sep 17 00:00:00 2001 From: MinetaS Date: Mon, 17 Oct 2022 00:03:08 +0900 Subject: [PATCH 79/84] Apply -flto-partition=one / -flto=full This patch fixes a potential bug derived from an incompatibility between LTO and top-level assembly code (INCBIN). Passed non-regression STC (master e90341f): LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 119352 W: 31986 L: 31862 D: 55504 Ptnml(0-2): 439, 12624, 33400, 12800, 413 https://tests.stockfishchess.org/tests/view/634aacf84bc7650f0755188b closes https://github.com/official-stockfish/Stockfish/pull/4201 No functional change --- AUTHORS | 1 + src/Makefile | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/AUTHORS b/AUTHORS index 804232f1..89e7c9ed 100644 --- a/AUTHORS +++ b/AUTHORS @@ -189,6 +189,7 @@ Stefan Geschwentner (locutus2) Stefano Cardanobile (Stefano80) Steinar Gunderson (sesse) Stéphane Nicolet (snicolet) +Syine Mineta (MinetaS) Prokop Randáček (ProkopRandacek) Thanar2 thaspel diff --git a/src/Makefile b/src/Makefile index 880710fe..1d5137d1 100644 --- a/src/Makefile +++ b/src/Makefile @@ -678,7 +678,7 @@ endif ifeq ($(optimize),yes) ifeq ($(debug), no) ifeq ($(comp),clang) - CXXFLAGS += -flto + CXXFLAGS += -flto=full ifeq ($(target_windows),yes) CXXFLAGS += -fuse-ld=lld endif @@ -688,10 +688,10 @@ ifeq ($(debug), no) # GCC on some systems. else ifeq ($(comp),gcc) ifeq ($(gccisclang),) - CXXFLAGS += -flto + CXXFLAGS += -flto -flto-partition=one LDFLAGS += $(CXXFLAGS) -flto=jobserver else - CXXFLAGS += -flto + CXXFLAGS += -flto=full LDFLAGS += $(CXXFLAGS) endif From 804394b939614ca6ac99e31be236c019db365bb7 Mon Sep 17 00:00:00 2001 From: disservin Date: Sun, 16 Oct 2022 14:37:01 +0200 Subject: [PATCH 80/84] enable bit manipulation instruction set 1 bmi1 enables the use of _blsr_u64 for pop_lsb, and is availabe when avx2 is. verified a small speedup (0.2 - 0.6%) closes https://github.com/official-stockfish/Stockfish/pull/4202 No functional change --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 1d5137d1..727466f9 100644 --- a/src/Makefile +++ b/src/Makefile @@ -593,7 +593,7 @@ endif ifeq ($(avx2),yes) CXXFLAGS += -DUSE_AVX2 ifeq ($(comp),$(filter $(comp),gcc clang mingw)) - CXXFLAGS += -mavx2 + CXXFLAGS += -mavx2 -mbmi endif endif From 5604b255e6012ed44eb03e2e93949d904fc7279b Mon Sep 17 00:00:00 2001 From: Clement Date: Fri, 21 Oct 2022 02:29:57 +0000 Subject: [PATCH 81/84] Add RISC-V 64-bit support adds a riscv64 target architecture to the Makefile to support RISC-V 64-bit. Compiled and tested on VisionFive 2 board. closes https://github.com/official-stockfish/Stockfish/pull/4205 No functional change. --- AUTHORS | 1 + src/Makefile | 19 +++++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/AUTHORS b/AUTHORS index 89e7c9ed..d4b37e7a 100644 --- a/AUTHORS +++ b/AUTHORS @@ -43,6 +43,7 @@ Bryan Cross (crossbr) candirufish Chess13234 Chris Cain (ceebo) +clefrks Dale Weiler (graphitemaster) Dan Schmidt (dfannius) Daniel Axtens (daxtens) diff --git a/src/Makefile b/src/Makefile index 727466f9..e481aca5 100644 --- a/src/Makefile +++ b/src/Makefile @@ -116,7 +116,7 @@ ifeq ($(ARCH), $(filter $(ARCH), \ x86-64-vnni512 x86-64-vnni256 x86-64-avx512 x86-64-avxvnni x86-64-bmi2 \ x86-64-avx2 x86-64-sse41-popcnt x86-64-modern x86-64-ssse3 x86-64-sse3-popcnt \ x86-64 x86-32-sse41-popcnt x86-32-sse2 x86-32 ppc-64 ppc-32 e2k \ - armv7 armv7-neon armv8 apple-silicon general-64 general-32)) + armv7 armv7-neon armv8 apple-silicon general-64 general-32 riscv64)) SUPPORTED_ARCH=true else SUPPORTED_ARCH=false @@ -338,7 +338,11 @@ ifeq ($(findstring e2k,$(ARCH)),e2k) popcnt = yes endif +ifeq ($(ARCH),riscv64) + arch = riscv64 endif +endif + ### ========================================================================== ### Section 3. Low-level Configuration @@ -364,11 +368,14 @@ ifeq ($(COMP),gcc) CXX=g++ CXXFLAGS += -pedantic -Wextra -Wshadow - ifeq ($(arch),$(filter $(arch),armv7 armv8)) + ifeq ($(arch),$(filter $(arch),armv7 armv8 riscv64)) ifeq ($(OS),Android) CXXFLAGS += -m$(bits) LDFLAGS += -m$(bits) endif + ifeq ($(ARCH),riscv64) + CXXFLAGS += -latomic + endif else CXXFLAGS += -m$(bits) LDFLAGS += -m$(bits) @@ -429,11 +436,14 @@ ifeq ($(COMP),clang) endif endif - ifeq ($(arch),$(filter $(arch),armv7 armv8)) + ifeq ($(arch),$(filter $(arch),armv7 armv8 riscv64)) ifeq ($(OS),Android) CXXFLAGS += -m$(bits) LDFLAGS += -m$(bits) endif + ifeq ($(ARCH),riscv64) + CXXFLAGS += -latomic + endif else CXXFLAGS += -m$(bits) LDFLAGS += -m$(bits) @@ -757,6 +767,7 @@ help: @echo "apple-silicon > Apple silicon ARM64" @echo "general-64 > unspecified 64-bit" @echo "general-32 > unspecified 32-bit" + @echo "riscv64 > RISC-V 64-bit" @echo "" @echo "Supported compilers:" @echo "" @@ -916,7 +927,7 @@ config-sanity: net @test "$(SUPPORTED_ARCH)" = "true" @test "$(arch)" = "any" || test "$(arch)" = "x86_64" || test "$(arch)" = "i386" || \ test "$(arch)" = "ppc64" || test "$(arch)" = "ppc" || test "$(arch)" = "e2k" || \ - test "$(arch)" = "armv7" || test "$(arch)" = "armv8" || test "$(arch)" = "arm64" + test "$(arch)" = "armv7" || test "$(arch)" = "armv8" || test "$(arch)" = "arm64" || test "$(arch)" = "riscv64" @test "$(bits)" = "32" || test "$(bits)" = "64" @test "$(prefetch)" = "yes" || test "$(prefetch)" = "no" @test "$(popcnt)" = "yes" || test "$(popcnt)" = "no" From 4ec8945eafc5b271d1c9d276fab590fa26c24901 Mon Sep 17 00:00:00 2001 From: Michael Chaly Date: Fri, 21 Oct 2022 17:10:45 +0300 Subject: [PATCH 82/84] Use TT moves more often in qsearch During the recapture phase of quiescence search (where we limit the generated moves to recaptures on the last seen capture square), the move picker will now emit the tt move, even if the tt move is not a recapture. Passed STC : https://tests.stockfishchess.org/tests/view/6350df2928d3a71cb1eef838 LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 90280 W: 24001 L: 23845 D: 42434 Ptnml(0-2): 273, 9779, 24941, 9813, 334 Passed LTC : https://tests.stockfishchess.org/tests/view/6351308b28d3a71cb1ef06ce LLR: 2.96 (-2.94,2.94) <-1.75,0.25> Total: 104504 W: 27937 L: 27807 D: 48760 Ptnml(0-2): 54, 10378, 31260, 10504, 56 closes https://github.com/official-stockfish/Stockfish/pull/4206 Bench: 4540268 --- src/movepick.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/movepick.cpp b/src/movepick.cpp index 3428a764..587c6d79 100644 --- a/src/movepick.cpp +++ b/src/movepick.cpp @@ -83,7 +83,6 @@ MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHist stage = (pos.checkers() ? EVASION_TT : QSEARCH_TT) + !( ttm - && (pos.checkers() || depth > DEPTH_QS_RECAPTURES || to_sq(ttm) == recaptureSquare) && pos.pseudo_legal(ttm)); } From a5500edc555f6d4429b3b697392f5f27215cb1db Mon Sep 17 00:00:00 2001 From: dav1312 <63931154+dav1312@users.noreply.github.com> Date: Tue, 25 Oct 2022 11:15:00 +0200 Subject: [PATCH 83/84] Add issue template Add an issue template using GitHub's form schema https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema closes https://github.com/official-stockfish/Stockfish/pull/4210 No functional change. --- .github/ISSUE_TEMPLATE/BUG-REPORT.yml | 65 +++++++++++++++++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 8 ++++ README.md | 63 +++++++++++++------------- 3 files changed, 106 insertions(+), 30 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/BUG-REPORT.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml diff --git a/.github/ISSUE_TEMPLATE/BUG-REPORT.yml b/.github/ISSUE_TEMPLATE/BUG-REPORT.yml new file mode 100644 index 00000000..e46d2bf8 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/BUG-REPORT.yml @@ -0,0 +1,65 @@ +name: Report issue +description: Create a report to help us fix issues with the engine +body: +- type: textarea + attributes: + label: Describe the issue + description: A clear and concise description of what you're experiencing. + validations: + required: true + +- type: textarea + attributes: + label: Expected behavior + description: A clear and concise description of what you expected to happen. + validations: + required: true + +- type: textarea + attributes: + label: Steps to reproduce + description: | + Steps to reproduce the behavior. + You can also use this section to paste the command line output. + placeholder: | + ``` + position startpos moves g2g4 e7e5 f2f3 + go mate 1 + info string NNUE evaluation using nn-6877cd24400e.nnue enabled + info depth 1 seldepth 1 multipv 1 score mate 1 nodes 33 nps 11000 tbhits 0 time 3 pv d8h4 + bestmove d8h4 + ``` + validations: + required: true + +- type: textarea + attributes: + label: Anything else? + description: | + Anything that will give us more context about the issue you are encountering. + You can also use this section to propose ideas on how to solve the issue. + validations: + required: false + +- type: dropdown + attributes: + label: Operating system + options: + - All + - Windows + - Linux + - MacOS + - Android + - Other or N/A + validations: + required: true + +- type: input + attributes: + label: Stockfish version + description: | + This can be found by running the engine. + You can also use the commit ID. + placeholder: Stockfish 15 / e6e324e + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..1f8694d2 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: Discord server + url: https://discord.gg/GWDRS3kU6R + about: Feel free to ask for support or have a chat with us in our Discord server! + - name: Discussions, Q&A, ideas, show us something... + url: https://github.com/official-stockfish/Stockfish/discussions/new + about: Do you have an idea for Stockfish? Do you want to show something that you made? Please open a discussion about it! diff --git a/README.md b/README.md index b076ab6b..7066db4b 100644 --- a/README.md +++ b/README.md @@ -344,33 +344,36 @@ source code, these changes must also be made available under the GPL v3. For full details, read the copy of the GPL v3 found in the file named [*Copying.txt*][license-link]. -[authors-link]:https://github.com/official-stockfish/Stockfish/blob/master/AUTHORS -[build-badge]:https://img.shields.io/github/workflow/status/official-stockfish/Stockfish/Stockfish?style=for-the-badge&label=stockfish&logo=github -[build-link]:https://github.com/official-stockfish/Stockfish/actions/workflows/stockfish.yml -[commits-badge]:https://img.shields.io/github/commits-since/official-stockfish/Stockfish/latest?style=for-the-badge -[commits-link]:https://github.com/official-stockfish/Stockfish/commits/master -[discord-badge]:https://img.shields.io/discord/435943710472011776?style=for-the-badge&label=discord&logo=Discord -[discord-link]:https://discord.com/invite/aefaxmq -[fishcooking-link]:https://groups.google.com/g/fishcooking -[fishtest-badge]:https://img.shields.io/website?style=for-the-badge&down_color=red&down_message=Offline&label=Fishtest&up_color=success&up_message=Online&url=https%3A%2F%2Ftests.stockfishchess.org%2Ftests -[fishtest-link]:https://tests.stockfishchess.org/tests -[github-link]:https://github.com/official-stockfish/Stockfish -[guideline-link]:https://github.com/glinscott/fishtest/wiki/Creating-my-first-test -[license-badge]:https://img.shields.io/github/license/official-stockfish/Stockfish?style=for-the-badge&label=license&color=success -[license-link]:https://github.com/official-stockfish/Stockfish/blob/master/Copying.txt -[lockpages-link]:https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/enable-the-lock-pages-in-memory-option-windows -[nodchip-link]:https://github.com/nodchip/Stockfish -[programming-link]:https://www.chessprogramming.org/Main_Page -[programmingsf-link]:https://www.chessprogramming.org/Stockfish -[pytorch-link]:https://github.com/glinscott/nnue-pytorch -[rammap-link]:https://docs.microsoft.com/en-us/sysinternals/downloads/rammap -[readme-link]:https://github.com/official-stockfish/Stockfish/blob/master/README.md -[release-badge]:https://img.shields.io/github/v/release/official-stockfish/Stockfish?style=for-the-badge&label=official%20release -[release-link]:https://github.com/official-stockfish/Stockfish/releases/latest -[src-link]:https://github.com/official-stockfish/Stockfish/tree/master/src -[stockfish128-logo]:https://stockfishchess.org/images/logo/icon_128x128.png -[tools-link]:https://github.com/official-stockfish/Stockfish/tree/tools -[uci-link]:https://www.shredderchess.com/download/div/uci.zip -[website-badge]:https://img.shields.io/website?style=for-the-badge&down_color=red&down_message=Offline&label=website&up_color=success&up_message=Online&url=https%3A%2F%2Fstockfishchess.org -[website-link]:https://stockfishchess.org -[worker-link]:https://github.com/glinscott/fishtest/wiki/Running-the-worker:-overview + +[authors-link]: https://github.com/official-stockfish/Stockfish/blob/master/AUTHORS +[build-link]: https://github.com/official-stockfish/Stockfish/actions/workflows/stockfish.yml +[commits-link]: https://github.com/official-stockfish/Stockfish/commits/master +[discord-link]: https://discord.gg/GWDRS3kU6R +[fishcooking-link]: https://groups.google.com/g/fishcooking +[fishtest-link]: https://tests.stockfishchess.org/tests +[github-link]: https://github.com/official-stockfish/Stockfish +[guideline-link]: https://github.com/glinscott/fishtest/wiki/Creating-my-first-test +[license-link]: https://github.com/official-stockfish/Stockfish/blob/master/Copying.txt +[lockpages-link]: https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/enable-the-lock-pages-in-memory-option-windows +[nodchip-link]: https://github.com/nodchip/Stockfish +[programming-link]: https://www.chessprogramming.org/Main_Page +[programmingsf-link]: https://www.chessprogramming.org/Stockfish +[pytorch-link]: https://github.com/glinscott/nnue-pytorch +[rammap-link]: https://docs.microsoft.com/en-us/sysinternals/downloads/rammap +[readme-link]: https://github.com/official-stockfish/Stockfish/blob/master/README.md +[release-link]: https://github.com/official-stockfish/Stockfish/releases/latest +[src-link]: https://github.com/official-stockfish/Stockfish/tree/master/src +[stockfish128-logo]: https://stockfishchess.org/images/logo/icon_128x128.png +[tools-link]: https://github.com/official-stockfish/Stockfish/tree/tools +[uci-link]: https://www.shredderchess.com/download/div/uci.zip +[website-link]: https://stockfishchess.org +[worker-link]: https://github.com/glinscott/fishtest/wiki/Running-the-worker:-overview + +[build-badge]: https://img.shields.io/github/workflow/status/official-stockfish/Stockfish/Stockfish?style=for-the-badge&label=stockfish&logo=github +[commits-badge]: https://img.shields.io/github/commits-since/official-stockfish/Stockfish/latest?style=for-the-badge +[discord-badge]: https://img.shields.io/discord/435943710472011776?style=for-the-badge&label=discord&logo=Discord +[fishtest-badge]: https://img.shields.io/website?style=for-the-badge&down_color=red&down_message=Offline&label=Fishtest&up_color=success&up_message=Online&url=https%3A%2F%2Ftests.stockfishchess.org%2Ftests +[license-badge]: https://img.shields.io/github/license/official-stockfish/Stockfish?style=for-the-badge&label=license&color=success +[release-badge]: https://img.shields.io/github/v/release/official-stockfish/Stockfish?style=for-the-badge&label=official%20release + +[website-badge]: https://img.shields.io/website?style=for-the-badge&down_color=red&down_message=Offline&label=website&up_color=success&up_message=Online&url=https%3A%2F%2Fstockfishchess.org From 8333b2a94c7c7e6e13822153f35899b64a690ac2 Mon Sep 17 00:00:00 2001 From: Clausable <97650056+Clausable@users.noreply.github.com> Date: Mon, 24 Oct 2022 16:00:31 -0400 Subject: [PATCH 84/84] Fix README typos, update AUTHORS closes https://github.com/official-stockfish/Stockfish/pull/4208 No functional change --- AUTHORS | 7 ++++--- README.md | 27 +++++++++++++-------------- src/nnue/features/half_ka_v2_hm.cpp | 2 +- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/AUTHORS b/AUTHORS index d4b37e7a..173669d4 100644 --- a/AUTHORS +++ b/AUTHORS @@ -39,6 +39,7 @@ Boštjan Mejak (PedanticHacker) braich Brian Sheppard (SapphireBrand, briansheppard-toast) Bruno de Melo Costa (BM123499) +Bruno Pellanda (pellanda) Bryan Cross (crossbr) candirufish Chess13234 @@ -50,6 +51,7 @@ Daniel Axtens (daxtens) Daniel Dugovic (ddugovic) Dariusz Orzechowski (dorzechowski) David Zar +David (dav1312) Daylen Yang (daylen) Deshawn Mohan-Smith (GoldenRare) Dieter Dobbelaere (ddobbelaere) @@ -159,7 +161,6 @@ Panthee Pascal Romaret Pasquale Pigazzini (ppigazzini) Patrick Jansen (mibere) -pellanda Peter Schneider (pschneider1968) Peter Zsifkovits (CoffeeOne) Praveen Kumar Tummala (praveentml) @@ -167,8 +168,8 @@ Rahul Dsilva (silversolver1) Ralph Stößer (Ralph Stoesser) Raminder Singh renouve -Reuven Peleg -Richard Lloyd +Reuven Peleg (R-Peleg) +Richard Lloyd (Richard-Lloyd) Rodrigo Exterckötter Tjäder Rodrigo Roim (roim) Ron Britvich (Britvich) diff --git a/README.md b/README.md index 7066db4b..ac15fbfa 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@
- + [![Stockfish][stockfish128-logo]][website-link] - + [![Build][build-badge]][build-link] [![License][license-badge]][license-link]
@@ -11,7 +11,7 @@ [![Website][website-badge]][website-link] [![Fishtest][fishtest-badge]][fishtest-link] [![Discord][discord-badge]][discord-link] - +
## Overview @@ -20,14 +20,14 @@ 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 informationabout how to use +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 efficiently +The Stockfish engine features two evaluation functions for chess. The efficiently updatable neural network (NNUE) based evaluation is the default and by far the strongest. -The classical evaluation based on handcrafted terms remains available. The strongest +The classical evaluation based on handcrafted terms remains available. The strongest network is integrated in the binary and downloaded automatically during the build process. -The NNUE evaluation benefits from the vector intrinsics available on most CPUs (sse2, +The NNUE evaluation benefits from the vector intrinsics available on most CPUs (sse2, avx2, neon, or similar). ## Files @@ -152,8 +152,8 @@ change them via a chess GUI. This is a list of available UCI options in Stockfis For developers the following non-standard commands might be of interest, mainly useful for debugging: * #### bench *ttSize threads limit fenFile limitType evalType* - Performs a standard benchmark using various options. The signature of a version - (standard node count) is obtained using all defaults. `bench` is currently + Performs a standard benchmark using various options. The signature of a version + (standard node count) is obtained using all defaults. `bench` is currently `bench 16 1 13 default depth mixed`. * #### compiler @@ -201,9 +201,9 @@ 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 +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 +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 @@ -337,7 +337,7 @@ using it as the starting point for a software project of your own. The only real limitation is that whenever you distribute Stockfish in some way, you MUST always include the license and the full source code -(or a pointer to where the source code can be found) to generate the +(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 v3. @@ -372,8 +372,7 @@ For full details, read the copy of the GPL v3 found in the file named [build-badge]: https://img.shields.io/github/workflow/status/official-stockfish/Stockfish/Stockfish?style=for-the-badge&label=stockfish&logo=github [commits-badge]: https://img.shields.io/github/commits-since/official-stockfish/Stockfish/latest?style=for-the-badge [discord-badge]: https://img.shields.io/discord/435943710472011776?style=for-the-badge&label=discord&logo=Discord -[fishtest-badge]: https://img.shields.io/website?style=for-the-badge&down_color=red&down_message=Offline&label=Fishtest&up_color=success&up_message=Online&url=https%3A%2F%2Ftests.stockfishchess.org%2Ftests +[fishtest-badge]: https://img.shields.io/website?style=for-the-badge&down_color=red&down_message=Offline&label=Fishtest&up_color=success&up_message=Online&url=https%3A%2F%2Ftests.stockfishchess.org%2Ftests%2Ffinished [license-badge]: https://img.shields.io/github/license/official-stockfish/Stockfish?style=for-the-badge&label=license&color=success [release-badge]: https://img.shields.io/github/v/release/official-stockfish/Stockfish?style=for-the-badge&label=official%20release - [website-badge]: https://img.shields.io/website?style=for-the-badge&down_color=red&down_message=Offline&label=website&up_color=success&up_message=Online&url=https%3A%2F%2Fstockfishchess.org diff --git a/src/nnue/features/half_ka_v2_hm.cpp b/src/nnue/features/half_ka_v2_hm.cpp index 11e05c94..7dbd3415 100644 --- a/src/nnue/features/half_ka_v2_hm.cpp +++ b/src/nnue/features/half_ka_v2_hm.cpp @@ -48,7 +48,7 @@ namespace Stockfish::Eval::NNUE::Features { // Explicit template instantiations template void HalfKAv2_hm::append_active_indices(const Position& pos, IndexList& active); template void HalfKAv2_hm::append_active_indices(const Position& pos, IndexList& active); - + // append_changed_indices() : get a list of indices for recently changed features template void HalfKAv2_hm::append_changed_indices(