language: cpp
-sudo: required
dist: xenial
matrix:
-# List of authors for Stockfish, updated for version 10
+# List of authors for Stockfish, as of January 7, 2020
Tord Romstad (romstad)
Marco Costalba (mcostalba)
Balint Pfliegel
Ben Koshy (BKSpurgeon)
Bill Henry (VoyagerOne)
+Bojun Guo (noobpwnftw, Nooby)
braich
-Bojun Guo (noobpwnftw)
-Brian Sheppard (SapphireBrand)
+Brian Sheppard (SapphireBrand, briansheppard-toast)
Bryan Cross (crossbr)
+candirufish
+Chess13234
Chris Cain (ceebo)
-Dan Schmidt
+Dan Schmidt (dfannius)
+Daniel Axtens (daxtens)
Daniel Dugovic (ddugovic)
Dariusz Orzechowski
David Zar
Daylen Yang (daylen)
DiscanX
-Eelco de Groot
+double-beep
+Eduardo Cáceres (eduherminio)
+Eelco de Groot (KingDefender)
Elvin Liu (solarlight2)
erbsenzaehler
Ernesto Gatti
Jan Ondruš (hxim)
Jared Kish (Kurtbusch)
Jarrod Torriero (DU-jdto)
-Jean Gauthier (QuaisBla)
+Jean Gauthier (OuaisBla)
Jean-Francois Romang (jromang)
+Jekaa
Jerry Donald Watson (jerrydonaldwatson)
Jonathan Calovski (Mysseno)
-Jonathan D. (SFisGOD)
+Jonathan Dumale (SFisGOD)
Joost VandeVondele (vondele)
Jörg Oster (joergoster)
Joseph Ellis (jhellis3)
Joseph R. Prostko
jundery
-Justin Blanchard
+Justin Blanchard (UncombedCoconut)
Kelly Wilson
Ken Takusagawa
kinderchocolate
Kojirion
Leonardo Ljubičić (ICCF World Champion)
Leonid Pechenik (lp--)
-Linus Arver
+Linus Arver (listx)
loco-loco
Lub van den Berg (ElbertoOne)
Luca Brivio (lucabrivio)
Lucas Braesch (lucasart)
Lyudmil Antonov (lantonov)
Maciej Żenczykowski (zenczykowski)
-Matthew Lai (matthewlai)
-Matthew Sullivan
+Malcolm Campbell (xoto10)
Mark Tenzer (31m059)
+marotear
+Matthew Lai (matthewlai)
+Matthew Sullivan (Matt14916)
+Michael An (man)
Michael Byrne (MichaelB7)
-Michael Stembera (mstembera)
Michael Chaly (Vizvezdenec)
+Michael Stembera (mstembera)
+Michael Whiteley (protonspring)
Michel Van den Bergh (vdbergh)
Miguel Lahoz (miguel-l)
Mikael Bäckman (mbootsector)
-Michael Whiteley (protonspring)
+Mira
Miroslav Fontán (Hexik)
Moez Jellouli (MJZ1977)
Mohammed Li (tthsqe12)
Nick Pelling (nickpelling)
Nicklas Persson (NicklasPersson)
Niklas Fiekas (niklasf)
+Nikolay Kostov (NikolayIT)
Ondrej Mosnáček (WOnder93)
Oskar Werkelin Ahlin
Pablo Vazquez
+Panthee
Pascal Romaret
Pasquale Pigazzini (ppigazzini)
Patrick Jansen (mibere)
Richard Lloyd
Rodrigo Exterckötter Tjäder
Ron Britvich (Britvich)
-Ronald de Man (syzygy1)
+Ronald de Man (syzygy1, syzygy)
Ryan Schmitt
Ryan Takker
+Sami Kiminki (skiminki)
Sebastian Buchwald (UniQP)
Sergei Antonov (saproj)
+Sergei Ivanov (svivanov72)
sf-x
-shane31
-Steinar Gunderson (sesse)
+Shane Booth (shane31)
Stefan Geschwentner (locutus2)
Stefano Cardanobile (Stefano80)
+Steinar Gunderson (sesse)
Stéphane Nicolet (snicolet)
Thanar2
thaspel
+theo77186
+Tom Truscott
Tom Vijlbrief (tomtor)
-Torsten Franz (torfranz)
+Torsten Franz (torfranz, tfranzer)
+Tracey Emery (basepr1me)
Uri Blass (uriblass)
-Vince Negri
+Vince Negri (cuddlestmonkey)
+
-# Additionally, we acknowledge the authors of fishtest,
-# an essential framework for the development of Stockfish:
+# Additionally, we acknowledge the authors and maintainers of fishtest,
+# an amazing and essential framework for the development of Stockfish!
+#
# https://github.com/glinscott/fishtest/blob/master/AUTHORS
+
+
+
+
set/unset some switches in the compiler command line; see file *types.h*
for a quick reference.
+When reporting an issue or a bug, please tell us which version and
+compiler you used to create your executable. These informations can
+be found by typing the following commands in a console:
+
+```
+ ./stockfish
+ compiler
+```
## Understanding the code base and participating in the project
### 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)
-and view the current tests on [Fishtest](http://tests.stockfishchess.org/tests).
+your hardware resources by installing the [Fishtest Worker](https://github.com/glinscott/fishtest/wiki/Running-the-worker:-overview)
+and view the current tests on [Fishtest](https://tests.stockfishchess.org/tests).
### Improving the code
-If you want to help improve the code, there are several valuable ressources:
+If you want to help improve the code, there are several valuable resources:
* [In this wiki,](https://www.chessprogramming.org) many techniques used in
Stockfish are explained with a lot of background information.
* The latest source can always be found on [GitHub](https://github.com/official-stockfish/Stockfish).
Discussions about Stockfish take place in the [FishCooking](https://groups.google.com/forum/#!forum/fishcooking)
-group and engine testing is done on [Fishtest](http://tests.stockfishchess.org/tests).
+group and engine testing is done on [Fishtest](https://tests.stockfishchess.org/tests).
If you want to help improve Stockfish, please read this [guideline](https://github.com/glinscott/fishtest/wiki/Creating-my-first-test)
first, where the basics of Stockfish development are explained.
-Contributors with >10,000 CPU hours as of November 4, 2018
+Contributors with >10,000 CPU hours as of January 7, 2020
Thank you!
-Username CPU Hours Games played
-noobpwnftw 3730975 292309380
-mibere 535242 43333774
-crunchy 375564 29121434
-cw 371664 28748719
-fastgm 318178 22283584
-JojoM 295354 20958931
-dew 215476 17079219
-ctoks 214031 17312035
-glinscott 204517 13932027
-bking_US 187568 12233168
-velislav 168404 13336219
-CSU_Dynasty 168069 14417712
-Thanar 162373 13842179
-spams 149531 10940322
-Fisherman 141137 12099359
-drabel 134441 11180178
-leszek 133658 9812120
-marrco 133566 10115202
-sqrt2 128420 10022279
-vdbergh 123230 9200516
-tvijlbrief 123007 9498831
-vdv 120381 8555423
-malala 117291 8126488
-dsmith 114010 7622414
-BrunoBanani 104938 7448565
-CoffeeOne 100042 4593596
-Data 94621 8433010
-mgrabiak 92248 7787406
-bcross 89440 8506568
-brabos 81868 6647613
-BRAVONE 80811 5341681
-psk 77195 6156031
-nordlandia 74833 6231930
-robal 72818 5969856
-TueRens 72523 6383294
-sterni1971 71049 5647590
-sunu 65855 5360884
-mhoram 65034 5192880
-davar 64794 5457564
-nssy 64607 5371952
-Pking_cda 64499 5704075
-biffhero 63557 5480444
-teddybaer 62147 5585620
-solarlight 61278 5402642
-ElbertoOne 60156 5504304
-jromang 58854 4704502
-dv8silencer 57421 3961325
-tinker 56039 4204914
-Freja 50331 3808121
-renouve 50318 3544864
-robnjr 47504 4131742
-grandphish2 47377 4110003
-eva42 46857 4075716
-ttruscott 46802 3811534
-finfish 46244 3481661
-rap 46201 3219490
-ronaldjerum 45641 3964331
-xoto 44998 4170431
-gvreuls 44359 3902234
-bigpen0r 41780 3448224
-Bobo1239 40767 3657490
-Antihistamine 39218 2792761
-mhunt 38991 2697512
-racerschmacer 38929 3756111
-VoyagerOne 35896 3378887
-homyur 35561 3012398
-rkl 33217 2978536
-pb00067 33034 2803485
-speedycpu 32043 2531964
-SC 31954 2848432
-EthanOConnor 31638 2143255
-oryx 30962 2899534
-gri 30108 2429137
-csnodgrass 29396 2808611
-Garf 28887 2873564
-Pyafue 28885 1986098
-jkiiski 28014 1923255
-slakovv 27017 2031279
-Prcuvu 26300 2307154
-hyperbolic.tom 26248 2200777
-jbwiebe 25663 2129063
-anst 25525 2279159
-Patrick_G 24222 1835674
-nabildanial 23524 1586321
-achambord 23495 1942546
-Sharaf_DG 22975 1790697
-chriswk 22876 1947731
-ncfish1 22689 1830009
-cuistot 22201 1383031
-Zirie 21171 1493227
-Isidor 20634 1736219
-JanErik 20596 1791991
-xor12 20535 1819280
-team-oh 20364 1653708
-nesoneg 20264 1493435
-dex 20110 1682756
-rstoesser 19802 1335177
-Vizvezdenec 19750 1695579
-eastorwest 19531 1841839
-sg4032 18913 1720157
-horst.prack 18425 1708197
-cisco2015 18408 1793774
-ianh2105 18133 1668562
-MazeOfGalious 18022 1644593
-ville 17900 1539130
-j3corre 17607 975954
-eudhan 17502 1424648
-jmdana 17351 1287546
-iisiraider 17175 1118788
-jundery 17172 1115855
-wei 16852 1822582
-SFTUser 16635 1363975
-purplefishies 16621 1106850
-DragonLord 16599 1252348
-chris 15274 1575333
-IgorLeMasson 15201 1364148
-dju 15074 914278
-Flopzee 14700 1331632
-OssumOpossum 14149 1029265
-enedene 13762 935618
-ako027ako 13442 1250249
-AdrianSA 13324 924980
-bpfliegel 13318 886523
-Nikolay.IT 13260 1155612
-jpulman 12776 854815
-joster 12438 988413
-fatmurphy 12015 901134
-Nesa92 11711 1132245
-Adrian.Schmidt123 11542 898699
-modolief 11228 926456
-Dark_wizzie 11214 1017910
-mschmidt 10973 818594
-Andrew Grant 10780 947859
-infinity 10762 746397
-SapphireBrand 10692 1024604
-Thomas A. Anderson 10553 736094
-basepi 10434 935168
-lantonov 10325 972610
-pgontarz 10294 878746
-Spprtr 10189 823246
-crocogoat 10115 1017325
-stocky 10083 718114
\ No newline at end of file
+Username CPU Hours Games played
+--------------------------------------------------
+noobpwnftw 9305707 695548021
+mlang 780050 61648867
+dew 621626 43921547
+mibere 524702 42238645
+crunchy 354587 27344275
+cw 354495 27274181
+fastgm 332801 22804359
+JojoM 295750 20437451
+CSU_Dynasty 262015 21828122
+Fisherman 232181 18939229
+ctoks 218866 17622052
+glinscott 201989 13780820
+tvijlbrief 201204 15337115
+velislav 188630 14348485
+gvreuls 187164 15149976
+bking_US 180289 11876016
+nordlandia 172076 13467830
+leszek 157152 11443978
+Thanar 148021 12365359
+spams 141975 10319326
+drabel 138073 11121749
+vdv 137850 9394330
+mgrabiak 133578 10454324
+TueRens 132485 10878471
+bcross 129683 11557084
+marrco 126078 9356740
+sqrt2 125830 9724586
+robal 122873 9593418
+vdbergh 120766 8926915
+malala 115926 8002293
+CoffeeOne 114241 5004100
+dsmith 113189 7570238
+BrunoBanani 104644 7436849
+Data 92328 8220352
+mhoram 89333 6695109
+davar 87924 7009424
+xoto 81094 6869316
+ElbertoOne 80899 7023771
+grandphish2 78067 6160199
+brabos 77212 6186135
+psk 75733 5984901
+BRAVONE 73875 5054681
+sunu 70771 5597972
+sterni1971 70605 5590573
+MaZePallas 66886 5188978
+Vizvezdenec 63708 4967313
+nssy 63462 5259388
+jromang 61634 4940891
+teddybaer 61231 5407666
+Pking_cda 60099 5293873
+solarlight 57469 5028306
+dv8silencer 56913 3883992
+tinker 54936 4086118
+renouve 49732 3501516
+Freja 49543 3733019
+robnjr 46972 4053117
+rap 46563 3219146
+Bobo1239 46036 3817196
+ttruscott 45304 3649765
+racerschmacer 44881 3975413
+finfish 44764 3370515
+eva42 41783 3599691
+biffhero 40263 3111352
+bigpen0r 39817 3291647
+mhunt 38871 2691355
+ronaldjerum 38820 3240695
+Antihistamine 38785 2761312
+pb00067 38038 3086320
+speedycpu 37591 3003273
+rkl 37207 3289580
+VoyagerOne 37050 3441673
+jbwiebe 35320 2805433
+cuistot 34191 2146279
+homyur 33927 2850481
+manap 32873 2327384
+gri 32538 2515779
+oryx 31267 2899051
+EthanOConnor 30959 2090311
+SC 30832 2730764
+csnodgrass 29505 2688994
+jmdana 29458 2205261
+strelock 28219 2067805
+jkiiski 27832 1904470
+Pyafue 27533 1902349
+Garf 27515 2747562
+eastorwest 27421 2317535
+slakovv 26903 2021889
+Prcuvu 24835 2170122
+anst 24714 2190091
+hyperbolic.tom 24319 2017394
+Patrick_G 23687 1801617
+Sharaf_DG 22896 1786697
+nabildanial 22195 1519409
+chriswk 21931 1868317
+achambord 21665 1767323
+Zirie 20887 1472937
+team-oh 20217 1636708
+Isidor 20096 1680691
+ncfish1 19931 1520927
+nesoneg 19875 1463031
+Spprtr 19853 1548165
+JanErik 19849 1703875
+agg177 19478 1395014
+SFTUser 19231 1567999
+xor12 19017 1680165
+sg4032 18431 1641865
+rstoesser 18118 1293588
+MazeOfGalious 17917 1629593
+j3corre 17743 941444
+cisco2015 17725 1690126
+ianh2105 17706 1632562
+dex 17678 1467203
+jundery 17194 1115855
+iisiraider 17019 1101015
+horst.prack 17012 1465656
+Adrian.Schmidt123 16563 1281436
+purplefishies 16342 1092533
+wei 16274 1745989
+ville 16144 1384026
+eudhan 15712 1283717
+OuaisBla 15581 972000
+DragonLord 15559 1162790
+dju 14716 875569
+chris 14479 1487385
+0xB00B1ES 14079 1001120
+OssumOpossum 13776 1007129
+enedene 13460 905279
+bpfliegel 13346 884523
+Ente 13198 1156722
+IgorLeMasson 13087 1147232
+jpulman 13000 870599
+ako027ako 12775 1173203
+Nikolay.IT 12352 1068349
+Andrew Grant 12327 895539
+joster 12008 950160
+AdrianSA 11996 804972
+Nesa92 11455 1111993
+fatmurphy 11345 853210
+Dark_wizzie 11108 1007152
+modolief 10869 896470
+mschmidt 10757 803401
+infinity 10594 727027
+mabichito 10524 749391
+Thomas A. Anderson 10474 732094
+thijsk 10431 719357
+Flopzee 10339 894821
+crocogoat 10104 1013854
+SapphireBrand 10104 969604
+stocky 10017 699440
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
string fenFile = (is >> token) ? token : "default";
string limitType = (is >> token) ? token : "depth";
- go = "go " + limitType + " " + limit;
+ go = limitType == "eval" ? "eval" : "go " + limitType + " " + limit;
if (fenFile == "default")
fens = Defaults;
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
// bit 13-14: white pawn file (from FILE_A to FILE_D)
// bit 15-17: white pawn RANK_7 - rank (from RANK_7 - RANK_7 to RANK_7 - RANK_2)
unsigned index(Color us, Square bksq, Square wksq, Square psq) {
- return wksq | (bksq << 6) | (us << 12) | (file_of(psq) << 13) | ((RANK_7 - rank_of(psq)) << 15);
+ return int(wksq) | (bksq << 6) | (us << 12) | (file_of(psq) << 13) | ((RANK_7 - rank_of(psq)) << 15);
}
enum Result {
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2)
- SquareDistance[s1][s2] = std::max(distance<File>(s1, s2), distance<Rank>(s1, s2));
-
- int steps[][5] = { {}, { 7, 9 }, { 6, 10, 15, 17 }, {}, {}, {}, { 1, 7, 8, 9 } };
-
- for (Color c : { WHITE, BLACK })
- for (PieceType pt : { PAWN, KNIGHT, KING })
- for (Square s = SQ_A1; s <= SQ_H8; ++s)
- for (int i = 0; steps[pt][i]; ++i)
- {
- Square to = s + Direction(c == WHITE ? steps[pt][i] : -steps[pt][i]);
-
- if (is_ok(to) && distance(s, to) < 3)
- {
- if (pt == PAWN)
- PawnAttacks[c][s] |= to;
- else
- PseudoAttacks[pt][s] |= to;
- }
- }
+ SquareDistance[s1][s2] = std::max(distance<File>(s1, s2), distance<Rank>(s1, s2));
+
+ for (Square s = SQ_A1; s <= SQ_H8; ++s)
+ {
+ PawnAttacks[WHITE][s] = pawn_attacks_bb<WHITE>(square_bb(s));
+ PawnAttacks[BLACK][s] = pawn_attacks_bb<BLACK>(square_bb(s));
+ }
+
+ // Helper returning the target bitboard of a step from a square
+ auto landing_square_bb = [&](Square s, int step)
+ {
+ Square to = Square(s + step);
+ return is_ok(to) && distance(s, to) <= 2 ? square_bb(to) : Bitboard(0);
+ };
+
+ for (Square s = SQ_A1; s <= SQ_H8; ++s)
+ {
+ for (int step : {-9, -8, -7, -1, 1, 7, 8, 9} )
+ PseudoAttacks[KING][s] |= landing_square_bb(s, step);
+
+ for (int step : {-17, -15, -10, -6, 6, 10, 15, 17} )
+ PseudoAttacks[KNIGHT][s] |= landing_square_bb(s, step);
+ }
Direction RookDirections[] = { NORTH, EAST, SOUTH, WEST };
Direction BishopDirections[] = { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST };
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
inline Bitboard& operator|=(Bitboard& b, Square s) { return b |= square_bb(s); }
inline Bitboard& operator^=(Bitboard& b, Square s) { return b ^= square_bb(s); }
+inline Bitboard operator&(Square s, Bitboard b) { return b & s; }
+inline Bitboard operator|(Square s, Bitboard b) { return b | s; }
+inline Bitboard operator^(Square s, Bitboard b) { return b ^ s; }
+
+inline Bitboard operator|(Square s, Square s2) { return square_bb(s) | square_bb(s2); }
+
constexpr bool more_than_one(Bitboard b) {
return b & (b - 1);
}
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
assert(pos.count<PAWN>(strongSide) == 1);
if (file_of(pos.square<PAWN>(strongSide)) >= FILE_E)
- sq = Square(sq ^ 7); // Mirror SQ_H1 -> SQ_A1
+ sq = Square(int(sq) ^ 7); // Mirror SQ_H1 -> SQ_A1
return strongSide == WHITE ? sq : ~sq;
}
Square loserKSq = pos.square<KING>(weakSide);
Square bishopSq = pos.square<BISHOP>(strongSide);
- // If our Bishop does not attack A1/H8, we flip the enemy king square
+ // If our bishop does not attack A1/H8, we flip the enemy king square
// to drive to opposite corners (A8/H1).
Value result = VALUE_KNOWN_WIN
}
-/// KP vs K. This endgame is evaluated with the help of a bitbase.
+/// KP vs K. This endgame is evaluated with the help of a bitbase
template<>
Value Endgame<KPK>::operator()(const Position& pos) const {
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
constexpr Score KnightOnQueen = S( 16, 12);
constexpr Score LongDiagonalBishop = S( 45, 0);
constexpr Score MinorBehindPawn = S( 18, 3);
- constexpr Score Outpost = S( 32, 10);
+ constexpr Score Outpost = S( 30, 21);
constexpr Score PassedFile = S( 11, 8);
constexpr Score PawnlessFlank = S( 17, 95);
constexpr Score RestrictedPiece = S( 7, 7);
+ constexpr Score ReachableOutpost = S( 32, 10);
constexpr Score RookOnQueenFile = S( 7, 6);
constexpr Score SliderOnQueen = S( 59, 18);
constexpr Score ThreatByKing = S( 24, 89);
constexpr Score ThreatByPawnPush = S( 48, 39);
constexpr Score ThreatBySafePawn = S(173, 94);
- constexpr Score TrappedRook = S( 47, 4);
+ constexpr Score TrappedRook = S( 52, 10);
constexpr Score WeakQueen = S( 49, 15);
#undef S
void Evaluation<T>::initialize() {
constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
- constexpr Direction Up = (Us == WHITE ? NORTH : SOUTH);
- constexpr Direction Down = (Us == WHITE ? SOUTH : NORTH);
+ constexpr Direction Up = pawn_push(Us);
+ constexpr Direction Down = -Up;
constexpr Bitboard LowRanks = (Us == WHITE ? Rank2BB | Rank3BB : Rank7BB | Rank6BB);
const Square ksq = pos.square<KING>(Us);
// Find our pawns that are blocked or on the first two ranks
Bitboard b = pos.pieces(Us, PAWN) & (shift<Down>(pos.pieces()) | LowRanks);
- // Squares occupied by those pawns, by our king or queen or controlled by
- // enemy pawns are excluded from the mobility area.
- mobilityArea[Us] = ~(b | pos.pieces(Us, KING, QUEEN) | pe->pawn_attacks(Them));
+ // Squares occupied by those pawns, by our king or queen, by blockers to attacks on our king
+ // or controlled by enemy pawns are excluded from the mobility area.
+ mobilityArea[Us] = ~(b | pos.pieces(Us, KING, QUEEN) | pos.blockers_for_king(Us) | pe->pawn_attacks(Them));
// Initialize attackedBy[] for king and pawns
attackedBy[Us][KING] = pos.attacks_from<KING>(ksq);
attackedBy2[Us] = dblAttackByPawn | (attackedBy[Us][KING] & attackedBy[Us][PAWN]);
// Init our king safety tables
- kingRing[Us] = attackedBy[Us][KING];
- if (relative_rank(Us, ksq) == RANK_1)
- kingRing[Us] |= shift<Up>(kingRing[Us]);
-
- if (file_of(ksq) == FILE_H)
- kingRing[Us] |= shift<WEST>(kingRing[Us]);
-
- else if (file_of(ksq) == FILE_A)
- kingRing[Us] |= shift<EAST>(kingRing[Us]);
+ Square s = make_square(clamp(file_of(ksq), FILE_B, FILE_G),
+ clamp(rank_of(ksq), RANK_2, RANK_7));
+ kingRing[Us] = PseudoAttacks[KING][s] | s;
kingAttackersCount[Them] = popcount(kingRing[Us] & pe->pawn_attacks(Them));
kingAttacksCount[Them] = kingAttackersWeight[Them] = 0;
Score Evaluation<T>::pieces() {
constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
- constexpr Direction Down = (Us == WHITE ? SOUTH : NORTH);
+ constexpr Direction Down = -pawn_push(Us);
constexpr Bitboard OutpostRanks = (Us == WHITE ? Rank4BB | Rank5BB | Rank6BB
: Rank5BB | Rank4BB | Rank3BB);
const Square* pl = pos.squares<Pt>(Us);
score += Outpost * (Pt == KNIGHT ? 2 : 1);
else if (Pt == KNIGHT && bb & b & ~pos.pieces(Us))
- score += Outpost;
+ score += ReachableOutpost;
// Knight and Bishop bonus for being right behind a pawn
if (shift<Down>(pos.pieces(PAWN)) & s)
// Bonus for bishop on a long diagonal which can "see" both center squares
if (more_than_one(attacks_bb<BISHOP>(s, pos.pieces(PAWN)) & Center))
score += LongDiagonalBishop;
- }
- // An important Chess960 pattern: A cornered bishop blocked by a friendly
- // pawn diagonally in front of it is a very serious problem, especially
- // when that pawn is also blocked.
- if ( Pt == BISHOP
- && pos.is_chess960()
- && (s == relative_square(Us, SQ_A1) || s == relative_square(Us, SQ_H1)))
- {
- Direction d = pawn_push(Us) + (file_of(s) == FILE_A ? EAST : WEST);
- if (pos.piece_on(s + d) == make_piece(Us, PAWN))
- score -= !pos.empty(s + d + pawn_push(Us)) ? CorneredBishop * 4
- : pos.piece_on(s + d + d) == make_piece(Us, PAWN) ? CorneredBishop * 2
- : CorneredBishop;
+ // An important Chess960 pattern: a cornered bishop blocked by a friendly
+ // pawn diagonally in front of it is a very serious problem, especially
+ // when that pawn is also blocked.
+ if ( pos.is_chess960()
+ && (s == relative_square(Us, SQ_A1) || s == relative_square(Us, SQ_H1)))
+ {
+ Direction d = pawn_push(Us) + (file_of(s) == FILE_A ? EAST : WEST);
+ if (pos.piece_on(s + d) == make_piece(Us, PAWN))
+ score -= !pos.empty(s + d + pawn_push(Us)) ? CorneredBishop * 4
+ : pos.piece_on(s + d + d) == make_piece(Us, PAWN) ? CorneredBishop * 2
+ : CorneredBishop;
+ }
}
}
constexpr Bitboard Camp = (Us == WHITE ? AllSquares ^ Rank6BB ^ Rank7BB ^ Rank8BB
: AllSquares ^ Rank1BB ^ Rank2BB ^ Rank3BB);
- Bitboard weak, b1, b2, safe, unsafeChecks = 0;
+ Bitboard weak, b1, b2, b3, safe, unsafeChecks = 0;
Bitboard rookChecks, queenChecks, bishopChecks, knightChecks;
int kingDanger = 0;
const Square ksq = pos.square<KING>(Us);
else
unsafeChecks |= knightChecks;
- // Find the squares that opponent attacks in our king flank, and the squares
- // which are attacked twice in that flank.
+ // Find the squares that opponent attacks in our king flank, the squares
+ // which they attack twice in that flank, and the squares that we defend.
b1 = attackedBy[Them][ALL_PIECES] & KingFlank[file_of(ksq)] & Camp;
b2 = b1 & attackedBy2[Them];
+ b3 = attackedBy[Us][ALL_PIECES] & KingFlank[file_of(ksq)] & Camp;
- int kingFlankAttacks = popcount(b1) + popcount(b2);
+ int kingFlankAttack = popcount(b1) + popcount(b2);
+ int kingFlankDefense = popcount(b3);
kingDanger += kingAttackersCount[Them] * kingAttackersWeight[Them]
+ 185 * popcount(kingRing[Us] & weak)
+ 148 * popcount(unsafeChecks)
+ 98 * popcount(pos.blockers_for_king(Us))
+ 69 * kingAttacksCount[Them]
- + 3 * kingFlankAttacks * kingFlankAttacks / 8
+ + 3 * kingFlankAttack * kingFlankAttack / 8
+ mg_value(mobility[Them] - mobility[Us])
- 873 * !pos.count<QUEEN>(Them)
- 100 * bool(attackedBy[Us][KNIGHT] & attackedBy[Us][KING])
- - 35 * bool(attackedBy[Us][BISHOP] & attackedBy[Us][KING])
- 6 * mg_value(score) / 8
- - 7;
+ - 4 * kingFlankDefense
+ + 37;
// Transform the kingDanger units into a Score, and subtract it from the evaluation
if (kingDanger > 100)
score -= PawnlessFlank;
// Penalty if king flank is under attack, potentially moving toward the king
- score -= FlankAttacks * kingFlankAttacks;
+ score -= FlankAttacks * kingFlankAttack;
if (T)
Trace::add(KING, Us, score);
Score Evaluation<T>::threats() const {
constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
- constexpr Direction Up = (Us == WHITE ? NORTH : SOUTH);
+ constexpr Direction Up = pawn_push(Us);
constexpr Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB);
Bitboard b, weak, defended, nonPawnEnemies, stronglyProtected, safe;
Score Evaluation<T>::passed() const {
constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
- constexpr Direction Up = (Us == WHITE ? NORTH : SOUTH);
+ constexpr Direction Up = pawn_push(Us);
auto king_proximity = [&](Color c, Square s) {
return std::min(distance(pos.square<KING>(c), s), 5);
Square blockSq = s + Up;
// Adjust bonus based on the king's proximity
- bonus += make_score(0, ( king_proximity(Them, blockSq) * 5
- - king_proximity(Us, blockSq) * 2) * w);
+ bonus += make_score(0, ( (king_proximity(Them, blockSq) * 19) / 4
+ - king_proximity(Us, blockSq) * 2) * w);
// If blockSq is not the queening square then consider also a second push
if (r != RANK_7)
return SCORE_ZERO;
constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
- constexpr Direction Down = (Us == WHITE ? SOUTH : NORTH);
+ constexpr Direction Down = -pawn_push(Us);
constexpr Bitboard SpaceMask =
Us == WHITE ? CenterFiles & (Rank2BB | Rank3BB | Rank4BB)
: CenterFiles & (Rank7BB | Rank6BB | Rank5BB);
int outflanking = distance<File>(pos.square<KING>(WHITE), pos.square<KING>(BLACK))
- distance<Rank>(pos.square<KING>(WHITE), pos.square<KING>(BLACK));
+ bool infiltration = rank_of(pos.square<KING>(WHITE)) > RANK_4
+ || rank_of(pos.square<KING>(BLACK)) < RANK_5;
+
bool pawnsOnBothFlanks = (pos.pieces(PAWN) & QueenSide)
&& (pos.pieces(PAWN) & KingSide);
int complexity = 9 * pe->passed_count()
+ 11 * pos.count<PAWN>()
+ 9 * outflanking
- + 18 * pawnsOnBothFlanks
- + 49 * !pos.non_pawn_material()
- - 36 * almostUnwinnable
- -103 ;
+ + 12 * infiltration
+ + 21 * pawnsOnBothFlanks
+ + 51 * !pos.non_pawn_material()
+ - 43 * almostUnwinnable
+ - 100 ;
// Now apply the bonus: note that we find the attacking side by extracting the
// sign of the midgame or endgame values, and that we carefully cap the bonus
{
if ( pos.opposite_bishops()
&& pos.non_pawn_material() == 2 * BishopValueMg)
- sf = 16 + 4 * pe->passed_count();
+ sf = 22 ;
else
sf = std::min(sf, 36 + (pos.opposite_bishops() ? 2 : 7) * pos.count<PAWN>(strongSide));
std::string Eval::trace(const Position& pos) {
+ if (pos.checkers())
+ return "Total evaluation: none (in check)";
+
std::memset(scores, 0, sizeof(scores));
pos.this_thread()->contempt = SCORE_ZERO; // Reset any dynamic contempt
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/// 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 = "11";
/// 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
}
+/// compiler_info() returns a string trying to describe the compiler we use
+
+const std::string compiler_info() {
+
+ #define STRINGIFY2(x) #x
+ #define STRINGIFY(x) STRINGIFY2(x)
+ #define VER_STRING(major, minor, patch) STRINGIFY(major) "." STRINGIFY(minor) "." STRINGIFY(patch)
+
+/// Predefined macros hell:
+///
+/// __GNUC__ Compiler is gcc, Clang or Intel on Linux
+/// __INTEL_COMPILER Compiler is Intel
+/// _MSC_VER Compiler is MSVC or Intel on Windows
+/// _WIN32 Building on Windows (any)
+/// _WIN64 Building on Windows 64 bit
+
+ std::string compiler = "\nCompiled by ";
+
+ #ifdef __clang__
+ compiler += "clang++ ";
+ compiler += VER_STRING(__clang_major__, __clang_minor__, __clang_patchlevel__);
+ #elif __INTEL_COMPILER
+ compiler += "Intel compiler ";
+ compiler += "(version ";
+ compiler += STRINGIFY(__INTEL_COMPILER) " update " STRINGIFY(__INTEL_COMPILER_UPDATE);
+ compiler += ")";
+ #elif _MSC_VER
+ compiler += "MSVC ";
+ compiler += "(version ";
+ compiler += STRINGIFY(_MSC_FULL_VER) "." STRINGIFY(_MSC_BUILD);
+ compiler += ")";
+ #elif __GNUC__
+ compiler += "g++ (GNUC) ";
+ compiler += VER_STRING(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
+ #else
+ compiler += "Unknown compiler ";
+ compiler += "(unknown version)";
+ #endif
+
+ #if defined(__APPLE__)
+ compiler += " on Apple";
+ #elif defined(__CYGWIN__)
+ compiler += " on Cygwin";
+ #elif defined(__MINGW64__)
+ compiler += " on MinGW64";
+ #elif defined(__MINGW32__)
+ compiler += " on MinGW32";
+ #elif defined(__ANDROID__)
+ compiler += " on Android";
+ #elif defined(__linux__)
+ compiler += " on Linux";
+ #elif defined(_WIN64)
+ compiler += " on Microsoft Windows 64-bit";
+ #elif defined(_WIN32)
+ compiler += " on Microsoft Windows 32-bit";
+ #else
+ compiler += " on unknown system";
+ #endif
+
+ compiler += "\n __VERSION__ macro expands to: ";
+ #ifdef __VERSION__
+ compiler += __VERSION__;
+ #else
+ compiler += "(undefined macro)";
+ #endif
+ compiler += "\n";
+
+ return compiler;
+}
+
+
/// Debug functions used mainly to collect run-time statistics
static std::atomic<int64_t> hits[2], means[2];
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include "types.h"
const std::string engine_info(bool to_uci = false);
+const std::string compiler_info();
void prefetch(void* addr);
void start_logger(const std::string& fname);
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
constexpr Bitboard TRank7BB = (Us == WHITE ? Rank7BB : Rank2BB);
constexpr Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB);
- constexpr Direction Up = (Us == WHITE ? NORTH : SOUTH);
+ constexpr Direction Up = pawn_push(Us);
constexpr Direction UpRight = (Us == WHITE ? NORTH_EAST : SOUTH_WEST);
constexpr Direction UpLeft = (Us == WHITE ? NORTH_WEST : SOUTH_EAST);
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
// 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( 89), V(-285), V(-185), V(93), V(57), V( 45), V( 51) },
- { V( 44), V( -18), V( 123), V(46), V(39), V( -7), V( 23) },
- { V( 4), V( 52), V( 162), V(37), V( 7), V(-14), V( -2) },
- { V(-10), V( -14), V( 90), V(15), V( 2), V( -7), V(-16) }
+ { V( 85), V(-289), V(-166), V(97), V(50), V( 45), V( 50) },
+ { V( 46), V( -25), V( 122), V(45), V(37), V(-10), V( 20) },
+ { V( -6), V( 51), V( 168), V(34), V(-2), V(-22), V(-14) },
+ { V(-15), V( -11), V( 101), V( 4), V(11), V(-15), V(-29) }
};
#undef S
Score evaluate(const Position& pos, Pawns::Entry* e) {
constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
- constexpr Direction Up = (Us == WHITE ? NORTH : SOUTH);
+ constexpr Direction Up = pawn_push(Us);
Bitboard neighbours, stoppers, support, phalanx, opposed;
Bitboard lever, leverPush, blocked;
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
constexpr Piece Pieces[] = { W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING,
B_PAWN, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING };
-
-// min_attacker() is a helper function used by see_ge() to locate the least
-// valuable attacker for the side to move, remove the attacker we just found
-// from the bitboards and scan for new X-ray attacks behind it.
-
-template<PieceType Pt>
-PieceType min_attacker(const Bitboard* byTypeBB, Square to, Bitboard stmAttackers,
- Bitboard& occupied, Bitboard& attackers) {
-
- Bitboard b = stmAttackers & byTypeBB[Pt];
- if (!b)
- return min_attacker<PieceType(Pt + 1)>(byTypeBB, to, stmAttackers, occupied, attackers);
-
- occupied ^= lsb(b); // Remove the attacker from occupied
-
- // Add any X-ray attack behind the just removed piece. For instance with
- // rooks in a8 and a7 attacking a1, after removing a7 we add rook in a8.
- // Note that new added attackers can be of any color.
- if (Pt == PAWN || Pt == BISHOP || Pt == QUEEN)
- attackers |= attacks_bb<BISHOP>(to, occupied) & (byTypeBB[BISHOP] | byTypeBB[QUEEN]);
-
- if (Pt == ROOK || Pt == QUEEN)
- attackers |= attacks_bb<ROOK>(to, occupied) & (byTypeBB[ROOK] | byTypeBB[QUEEN]);
-
- // X-ray may add already processed pieces because byTypeBB[] is constant: in
- // the rook example, now attackers contains _again_ rook in a7, so remove it.
- attackers &= occupied;
- return Pt;
-}
-
-template<>
-PieceType min_attacker<KING>(const Bitboard*, Square, Bitboard, Bitboard&, Bitboard&) {
- return KING; // No need to update bitboards: it is the last cycle
-}
-
} // namespace
st->nonPawnMaterial[us] += PieceValue[MG][promotion];
}
- // Update pawn hash key and prefetch access to pawnsTable
+ // Update pawn hash key
st->pawnKey ^= Zobrist::psq[pc][from] ^ Zobrist::psq[pc][to];
// Reset rule 50 draw counter
}
-/// Position::do(undo)_null_move() is used to do(undo) a "null move": It flips
+/// Position::do(undo)_null_move() is used to do(undo) a "null move": it flips
/// the side to move without executing any move on the board.
void Position::do_null_move(StateInfo& newSt) {
if (type_of(m) != NORMAL)
return VALUE_ZERO >= threshold;
- Bitboard stmAttackers;
Square from = from_sq(m), to = to_sq(m);
- PieceType nextVictim = type_of(piece_on(from));
- Color us = color_of(piece_on(from));
- Color stm = ~us; // First consider opponent's move
- Value balance; // Values of the pieces taken by us minus opponent's ones
-
- // The opponent may be able to recapture so this is the best result
- // we can hope for.
- balance = PieceValue[MG][piece_on(to)] - threshold;
- if (balance < VALUE_ZERO)
+ int swap = PieceValue[MG][piece_on(to)] - threshold;
+ if (swap < 0)
return false;
- // Now assume the worst possible result: that the opponent can
- // capture our piece for free.
- balance -= PieceValue[MG][nextVictim];
-
- // If it is enough (like in PxQ) then return immediately. Note that
- // in case nextVictim == KING we always return here, this is ok
- // if the given move is legal.
- if (balance >= VALUE_ZERO)
+ swap = PieceValue[MG][piece_on(from)] - swap;
+ if (swap <= 0)
return true;
- // Find all attackers to the destination square, with the moving piece
- // removed, but possibly an X-ray attacker added behind it.
Bitboard occupied = pieces() ^ from ^ to;
- Bitboard attackers = attackers_to(to, occupied) & occupied;
+ Color stm = color_of(piece_on(from));
+ Bitboard attackers = attackers_to(to, occupied);
+ Bitboard stmAttackers, bb;
+ int res = 1;
while (true)
{
- stmAttackers = attackers & pieces(stm);
+ stm = ~stm;
+ attackers &= occupied;
+
+ // If stm has no more attackers then give up: stm loses
+ if (!(stmAttackers = attackers & pieces(stm)))
+ break;
// Don't allow pinned pieces to attack (except the king) as long as
- // any pinners are on their original square.
+ // there are pinners on their original square.
if (st->pinners[~stm] & occupied)
stmAttackers &= ~st->blockersForKing[stm];
- // If stm has no more attackers then give up: stm loses
if (!stmAttackers)
break;
+ res ^= 1;
+
// Locate and remove the next least valuable attacker, and add to
- // the bitboard 'attackers' the possibly X-ray attackers behind it.
- nextVictim = min_attacker<PAWN>(byTypeBB, to, stmAttackers, occupied, attackers);
+ // the bitboard 'attackers' any X-ray attackers behind it.
+ if ((bb = stmAttackers & pieces(PAWN)))
+ {
+ if ((swap = PawnValueMg - swap) < res)
+ break;
- stm = ~stm; // Switch side to move
+ occupied ^= lsb(bb);
+ attackers |= attacks_bb<BISHOP>(to, occupied) & pieces(BISHOP, QUEEN);
+ }
- // Negamax the balance with alpha = balance, beta = balance+1 and
- // add nextVictim's value.
- //
- // (balance, balance+1) -> (-balance-1, -balance)
- //
- assert(balance < VALUE_ZERO);
+ else if ((bb = stmAttackers & pieces(KNIGHT)))
+ {
+ if ((swap = KnightValueMg - swap) < res)
+ break;
- balance = -balance - 1 - PieceValue[MG][nextVictim];
+ occupied ^= lsb(bb);
+ }
- // If balance is still non-negative after giving away nextVictim then we
- // win. The only thing to be careful about it is that we should revert
- // stm if we captured with the king when the opponent still has attackers.
- if (balance >= VALUE_ZERO)
+ else if ((bb = stmAttackers & pieces(BISHOP)))
{
- if (nextVictim == KING && (attackers & pieces(stm)))
- stm = ~stm;
- break;
+ if ((swap = BishopValueMg - swap) < res)
+ break;
+
+ occupied ^= lsb(bb);
+ attackers |= attacks_bb<BISHOP>(to, occupied) & pieces(BISHOP, QUEEN);
+ }
+
+ else if ((bb = stmAttackers & pieces(ROOK)))
+ {
+ if ((swap = RookValueMg - swap) < res)
+ break;
+
+ occupied ^= lsb(bb);
+ attackers |= attacks_bb<ROOK>(to, occupied) & pieces(ROOK, QUEEN);
+ }
+
+ else if ((bb = stmAttackers & pieces(QUEEN)))
+ {
+ if ((swap = QueenValueMg - swap) < res)
+ break;
+
+ occupied ^= lsb(bb);
+ attackers |= (attacks_bb<BISHOP>(to, occupied) & pieces(BISHOP, QUEEN))
+ | (attacks_bb<ROOK >(to, occupied) & pieces(ROOK , QUEEN));
}
- assert(nextVictim != KING);
+
+ else // KING
+ // If we "capture" with the king but opponent still has attackers,
+ // reverse the result.
+ return (attackers & ~pieces(stm)) ? res ^ 1 : res;
}
- return us != stm; // We break the above loop when stm loses
-}
+ return bool(res);
+}
/// Position::is_draw() tests whether the position is drawn by 50-move rule
/// or by repetition. It does not detect stalemates.
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Square epSquare;
// Not copied when making a move (will be recomputed anyhow)
- int repetition;
Key key;
Bitboard checkersBB;
Piece capturedPiece;
Bitboard blockersForKing[COLOR_NB];
Bitboard pinners[COLOR_NB];
Bitboard checkSquares[PIECE_TYPE_NB];
+ int repetition;
};
/// A list to keep track of the position states along the setup moves (from the
}
inline bool Position::castling_impeded(CastlingRights cr) const {
+ assert(cr == WHITE_OO || cr == WHITE_OOO || cr == BLACK_OO || cr == BLACK_OOO);
+
return byTypeBB[ALL_PIECES] & castlingPath[cr];
}
inline Square Position::castling_rook_square(CastlingRights cr) const {
+ assert(cr == WHITE_OO || cr == WHITE_OOO || cr == BLACK_OO || cr == BLACK_OOO);
+
return castlingRookSquare[cr];
}
// index[from] is not updated and becomes stale. This works as long as index[]
// is accessed just by known occupied squares.
- Bitboard fromTo = square_bb(from) | square_bb(to);
+ Bitboard fromTo = from | to;
byTypeBB[ALL_PIECES] ^= fromTo;
byTypeBB[type_of(pc)] ^= fromTo;
byColorBB[color_of(pc)] ^= fromTo;
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
{ },
{ },
{ // Knight
- { S(-169,-105), S(-96,-74), S(-80,-46), S(-79,-18) },
- { S( -79, -70), S(-39,-56), S(-24,-15), S( -9, 6) },
- { S( -64, -38), S(-20,-33), S( 4, -5), S( 19, 27) },
- { S( -28, -36), S( 5, 0), S( 41, 13), S( 47, 34) },
- { S( -29, -41), S( 13,-20), S( 42, 4), S( 52, 35) },
- { S( -11, -51), S( 28,-38), S( 63,-17), S( 55, 19) },
- { S( -67, -64), S(-21,-45), S( 6,-37), S( 37, 16) },
- { S(-200, -98), S(-80,-89), S(-53,-53), S(-32,-16) }
+ { S(-175, -96), S(-92,-65), S(-74,-49), S(-73,-21) },
+ { S( -77, -67), S(-41,-54), S(-27,-18), S(-15, 8) },
+ { S( -61, -40), S(-17,-27), S( 6, -8), S( 12, 29) },
+ { S( -35, -35), S( 8, -2), S( 40, 13), S( 49, 28) },
+ { S( -34, -45), S( 13,-16), S( 44, 9), S( 51, 39) },
+ { S( -9, -51), S( 22,-44), S( 58,-16), S( 53, 17) },
+ { S( -67, -69), S(-27,-50), S( 4,-51), S( 37, 12) },
+ { S(-201,-100), S(-83,-88), S(-56,-56), S(-26,-17) }
},
{ // Bishop
- { S(-44,-63), S( -4,-30), S(-11,-35), S(-28, -8) },
- { S(-18,-38), S( 7,-13), S( 14,-14), S( 3, 0) },
- { S( -8,-18), S( 24, 0), S( -3, -7), S( 15, 13) },
- { S( 1,-26), S( 8, -3), S( 26, 1), S( 37, 16) },
- { S( -7,-24), S( 30, -6), S( 23,-10), S( 28, 17) },
- { S(-17,-26), S( 4, 2), S( -1, 1), S( 8, 16) },
- { S(-21,-34), S(-19,-18), S( 10, -7), S( -6, 9) },
- { S(-48,-51), S( -3,-40), S(-12,-39), S(-25,-20) }
+ { S(-53,-57), S( -5,-30), S( -8,-37), S(-23,-12) },
+ { S(-15,-37), S( 8,-13), S( 19,-17), S( 4, 1) },
+ { S( -7,-16), S( 21, -1), S( -5, -2), S( 17, 10) },
+ { S( -5,-20), S( 11, -6), S( 25, 0), S( 39, 17) },
+ { S(-12,-17), S( 29, -1), S( 22,-14), S( 31, 15) },
+ { S(-16,-30), S( 6, 6), S( 1, 4), S( 11, 6) },
+ { S(-17,-31), S(-14,-20), S( 5, -1), S( 0, 1) },
+ { S(-48,-46), S( 1,-42), S(-14,-37), S(-23,-24) }
},
{ // Rook
{ S(-31, -9), S(-20,-13), S(-14,-10), S(-5, -9) },
{ S(-2,-75), S(-2,-52), S( 1,-43), S(-2,-36) }
},
{ // King
- { S(272, 0), S(325, 41), S(273, 80), S(190, 93) },
- { S(277, 57), S(305, 98), S(241,138), S(183,131) },
- { S(198, 86), S(253,138), S(168,165), S(120,173) },
- { S(169,103), S(191,152), S(136,168), S(108,169) },
- { S(145, 98), S(176,166), S(112,197), S( 69,194) },
- { S(122, 87), S(159,164), S( 85,174), S( 36,189) },
- { S( 87, 40), S(120, 99), S( 64,128), S( 25,141) },
- { S( 64, 5), S( 87, 60), S( 49, 75), S( 0, 75) }
+ { S(271, 1), S(327, 45), S(271, 85), S(198, 76) },
+ { S(278, 53), S(303,100), S(234,133), S(179,135) },
+ { S(195, 88), S(258,130), S(169,169), S(120,175) },
+ { S(164,103), S(190,156), S(138,172), S( 98,172) },
+ { S(154, 96), S(179,166), S(105,199), S( 70,199) },
+ { S(123, 92), S(145,172), S( 81,184), S( 31,191) },
+ { S( 88, 47), S(120,121), S( 65,116), S( 33,131) },
+ { S( 59, 11), S( 89, 59), S( 45, 73), S( -1, 78) }
}
};
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
// Different node types, used as a template parameter
enum NodeType { NonPV, PV };
+ constexpr uint64_t ttHitAverageWindow = 4096;
+ constexpr uint64_t ttHitAverageResolution = 1024;
+
// Razor and futility margins
- constexpr int RazorMargin = 661;
+ constexpr int RazorMargin = 531;
Value futility_margin(Depth d, bool improving) {
- return Value(198 * (d - improving));
+ return Value(217 * (d - improving));
}
// Reductions lookup table, initialized at startup
Depth reduction(bool i, Depth d, int mn) {
int r = Reductions[d] * Reductions[mn];
- return (r + 520) / 1024 + (!i && r > 999);
+ return (r + 511) / 1024 + (!i && r > 1007);
}
constexpr int futility_move_count(bool improving, Depth depth) {
- return (5 + depth * depth) * (1 + improving) / 2;
+ return (5 + depth * depth) * (1 + improving) / 2 - 1;
}
// History and stats update bonus, based on depth
int stat_bonus(Depth d) {
- return d > 17 ? -8 : 22 * d * d + 151 * d - 140;
+ return d > 15 ? -8 : 19 * d * d + 155 * d - 132;
}
// Add a small random component to draw evaluations to avoid 3fold-blindness
Value qsearch(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth = 0);
Value value_to_tt(Value v, int ply);
- Value value_from_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_continuation_histories(Stack* ss, Piece pc, Square to, int bonus);
void update_quiet_stats(const Position& pos, Stack* ss, Move move, int bonus);
void Search::init() {
for (int i = 1; i < MAX_MOVES; ++i)
- Reductions[i] = int((23.4 + std::log(Threads.size()) / 2) * std::log(i));
+ Reductions[i] = int((24.8 + std::log(Threads.size()) / 2) * std::log(i));
}
MainThread* mainThread = (this == Threads.main() ? Threads.main() : nullptr);
double timeReduction = 1, totBestMoveChanges = 0;
Color us = rootPos.side_to_move();
+ int iterIdx = 0;
std::memset(ss-7, 0, 10 * sizeof(Stack));
for (int i = 7; i > 0; i--)
bestValue = delta = alpha = -VALUE_INFINITE;
beta = VALUE_INFINITE;
+ if (mainThread)
+ {
+ if (mainThread->previousScore == VALUE_INFINITE)
+ for (int i=0; i<4; ++i)
+ mainThread->iterValue[i] = VALUE_ZERO;
+ else
+ for (int i=0; i<4; ++i)
+ mainThread->iterValue[i] = mainThread->previousScore;
+ }
+
size_t multiPV = Options["MultiPV"];
// Pick integer skill levels, but non-deterministically round up or down
multiPV = std::max(multiPV, (size_t)4);
multiPV = std::min(multiPV, rootMoves.size());
+ ttHitAverage = ttHitAverageWindow * ttHitAverageResolution / 2;
int ct = int(Options["Contempt"]) * PawnValueEg / 100; // From centipawns
contempt = (us == WHITE ? make_score(ct, ct / 2)
: -make_score(ct, ct / 2));
+ int searchAgainCounter = 0;
+
// Iterative deepening loop until requested to stop or the target depth is reached
while ( ++rootDepth < MAX_PLY
&& !Threads.stop
size_t pvFirst = 0;
pvLast = 0;
+ if (!Threads.increaseDepth)
+ searchAgainCounter++;
+
// MultiPV loop. We perform a full root search for each PV line
for (pvIdx = 0; pvIdx < multiPV && !Threads.stop; ++pvIdx)
{
if (rootDepth >= 4)
{
Value previousScore = rootMoves[pvIdx].previousScore;
- delta = Value(21 + abs(previousScore) / 128);
+ delta = Value(21 + abs(previousScore) / 256);
alpha = std::max(previousScore - delta,-VALUE_INFINITE);
beta = std::min(previousScore + delta, VALUE_INFINITE);
// Adjust contempt based on root move's previousScore (dynamic contempt)
- int dct = ct + 86 * previousScore / (abs(previousScore) + 176);
+ int dct = ct + (102 - ct / 2) * previousScore / (abs(previousScore) + 157);
contempt = (us == WHITE ? make_score(dct, dct / 2)
: -make_score(dct, dct / 2));
int failedHighCnt = 0;
while (true)
{
- Depth adjustedDepth = std::max(1, rootDepth - failedHighCnt);
+ Depth adjustedDepth = std::max(1, rootDepth - failedHighCnt - searchAgainCounter);
bestValue = ::search<PV>(rootPos, ss, alpha, beta, adjustedDepth, false);
// Bring the best move to the front. It is critical that sorting
&& !Threads.stop
&& !mainThread->stopOnPonderhit)
{
- double fallingEval = (354 + 10 * (mainThread->previousScore - bestValue)) / 692.0;
+ double fallingEval = (332 + 6 * (mainThread->previousScore - bestValue)
+ + 6 * (mainThread->iterValue[iterIdx] - bestValue)) / 704.0;
fallingEval = clamp(fallingEval, 0.5, 1.5);
// If the bestMove is stable over several iterations, reduce time accordingly
- timeReduction = lastBestMoveDepth + 9 < completedDepth ? 1.97 : 0.98;
- double reduction = (1.36 + mainThread->previousTimeReduction) / (2.29 * timeReduction);
+ timeReduction = lastBestMoveDepth + 9 < completedDepth ? 1.94 : 0.91;
+ double reduction = (1.41 + mainThread->previousTimeReduction) / (2.27 * timeReduction);
// Use part of the gained time from a previous stable move for the current move
for (Thread* th : Threads)
else
Threads.stop = true;
}
+ else if ( Threads.increaseDepth
+ && !mainThread->ponder
+ && Time.elapsed() > Time.optimum() * fallingEval * reduction * bestMoveInstability * 0.6)
+ Threads.increaseDepth = false;
+ else
+ Threads.increaseDepth = true;
}
+
+ mainThread->iterValue[iterIdx] = bestValue;
+ iterIdx = (iterIdx + 1) & 3;
}
if (!mainThread)
excludedMove = ss->excludedMove;
posKey = pos.key() ^ Key(excludedMove << 16); // Isn't a very good hash
tte = TT.probe(posKey, ttHit);
- ttValue = ttHit ? value_from_tt(tte->value(), ss->ply) : VALUE_NONE;
+ ttValue = ttHit ? value_from_tt(tte->value(), ss->ply, pos.rule50_count()) : VALUE_NONE;
ttMove = rootNode ? thisThread->rootMoves[thisThread->pvIdx].pv[0]
: ttHit ? tte->move() : MOVE_NONE;
ttPv = PvNode || (ttHit && tte->is_pv());
+ // thisThread->ttHitAverage can be used to approximate the running average of ttHit
+ thisThread->ttHitAverage = (ttHitAverageWindow - 1) * thisThread->ttHitAverage / ttHitAverageWindow
+ + ttHitAverageResolution * ttHit;
// At non-PV nodes we check for an early TT cutoff
if ( !PvNode
update_continuation_histories(ss, pos.moved_piece(ttMove), to_sq(ttMove), penalty);
}
}
- return ttValue;
+
+ if (pos.rule50_count() < 90)
+ return ttValue;
}
// Step 5. Tablebases probe
tte->save(posKey, VALUE_NONE, ttPv, BOUND_NONE, DEPTH_NONE, MOVE_NONE, eval);
}
- // Step 7. Razoring (~2 Elo)
+ // Step 7. Razoring (~1 Elo)
if ( !rootNode // The required rootNode PV handling is not available in qsearch
&& depth < 2
&& eval <= alpha - RazorMargin)
return qsearch<NT>(pos, ss, alpha, beta);
- improving = ss->staticEval >= (ss-2)->staticEval
- || (ss-2)->staticEval == VALUE_NONE;
+ improving = (ss-2)->staticEval == VALUE_NONE ? (ss->staticEval >= (ss-4)->staticEval
+ || (ss-4)->staticEval == VALUE_NONE) : ss->staticEval >= (ss-2)->staticEval;
- // Step 8. Futility pruning: child node (~30 Elo)
+ // Step 8. Futility pruning: child node (~50 Elo)
if ( !PvNode
- && depth < 7
+ && depth < 6
&& eval - futility_margin(depth, improving) >= beta
&& eval < VALUE_KNOWN_WIN) // Do not return unproven wins
return eval;
// Step 9. Null move search with verification search (~40 Elo)
if ( !PvNode
&& (ss-1)->currentMove != MOVE_NULL
- && (ss-1)->statScore < 22661
+ && (ss-1)->statScore < 23397
&& eval >= beta
&& eval >= ss->staticEval
- && ss->staticEval >= beta - 33 * depth + 299 - improving * 30
+ && ss->staticEval >= beta - 32 * depth + 292 - improving * 30
&& !excludedMove
&& pos.non_pawn_material(us)
&& (ss->ply >= thisThread->nmpMinPly || us != thisThread->nmpColor))
assert(eval - beta >= 0);
// Null move dynamic reduction based on depth and value
- Depth R = (835 + 70 * depth) / 256 + std::min(int(eval - beta) / 185, 3);
+ Depth R = (854 + 68 * depth) / 258 + std::min(int(eval - beta) / 192, 3);
ss->currentMove = MOVE_NULL;
ss->continuationHistory = &thisThread->continuationHistory[0][0][NO_PIECE][0];
&& depth >= 5
&& abs(beta) < VALUE_MATE_IN_MAX_PLY)
{
- Value raisedBeta = std::min(beta + 191 - 46 * improving, VALUE_INFINITE);
+ Value raisedBeta = std::min(beta + 189 - 45 * improving, VALUE_INFINITE);
MovePicker mp(pos, ttMove, raisedBeta - ss->staticEval, &thisThread->captureHistory);
int probCutCount = 0;
}
}
- // Step 11. Internal iterative deepening (~2 Elo)
+ // Step 11. Internal iterative deepening (~1 Elo)
if (depth >= 7 && !ttMove)
{
search<NT>(pos, ss, alpha, beta, depth - 7, cutNode);
tte = TT.probe(posKey, ttHit);
- ttValue = ttHit ? value_from_tt(tte->value(), ss->ply) : VALUE_NONE;
+ ttValue = ttHit ? value_from_tt(tte->value(), ss->ply, pos.rule50_count()) : VALUE_NONE;
ttMove = ttHit ? tte->move() : MOVE_NONE;
}
movedPiece = pos.moved_piece(move);
givesCheck = pos.gives_check(move);
- // Step 13. Extensions (~70 Elo)
+ // Calculate new depth for this move
+ newDepth = depth - 1;
+
+ // Step 13. Pruning at shallow depth (~200 Elo)
+ if ( !rootNode
+ && pos.non_pawn_material(us)
+ && bestValue > VALUE_MATED_IN_MAX_PLY)
+ {
+ // Skip quiet moves if movecount exceeds our FutilityMoveCount threshold
+ moveCountPruning = moveCount >= futility_move_count(improving, depth);
+
+ if ( !captureOrPromotion
+ && !givesCheck)
+ {
+ // Reduced depth of the next LMR search
+ int lmrDepth = std::max(newDepth - reduction(improving, depth, moveCount), 0);
+
+ // Countermoves based pruning (~20 Elo)
+ if ( lmrDepth < 4 + ((ss-1)->statScore > 0 || (ss-1)->moveCount == 1)
+ && (*contHist[0])[movedPiece][to_sq(move)] < CounterMovePruneThreshold
+ && (*contHist[1])[movedPiece][to_sq(move)] < CounterMovePruneThreshold)
+ continue;
+
+ // Futility pruning: parent node (~5 Elo)
+ if ( lmrDepth < 6
+ && !inCheck
+ && ss->staticEval + 235 + 172 * lmrDepth <= alpha
+ && thisThread->mainHistory[us][from_to(move)]
+ + (*contHist[0])[movedPiece][to_sq(move)]
+ + (*contHist[1])[movedPiece][to_sq(move)]
+ + (*contHist[3])[movedPiece][to_sq(move)] < 25000)
+ continue;
+
+ // Prune moves with negative SEE (~20 Elo)
+ if (!pos.see_ge(move, Value(-(32 - std::min(lmrDepth, 18)) * lmrDepth * lmrDepth)))
+ continue;
+ }
+ else if (!pos.see_ge(move, Value(-194) * depth)) // (~25 Elo)
+ continue;
+ }
+
+ // Step 14. Extensions (~75 Elo)
- // Singular extension search (~60 Elo). If all moves but one fail low on a
+ // Singular extension search (~70 Elo). If all moves but one fail low on a
// search of (alpha-s, beta-s), and just one fails high on (alpha, beta),
// then that move is singular and should be extended. To verify this we do
// a reduced search on all the other moves but the ttMove and if the
// search without the ttMove. So we assume this expected Cut-node is not singular,
// that multiple moves fail high, and we can prune the whole subtree by returning
// a soft bound.
- else if ( eval >= beta
- && singularBeta >= beta)
+ else if (singularBeta >= beta)
return singularBeta;
}
&& (pos.is_discovery_check_on_king(~us, move) || pos.see_ge(move)))
extension = 1;
- // Shuffle extension
- else if ( PvNode
- && pos.rule50_count() > 18
- && depth < 3
- && ++thisThread->shuffleExts < thisThread->nodes.load(std::memory_order_relaxed) / 4) // To avoid too many extensions
- extension = 1;
-
// Passed pawn extension
else if ( move == ss->killers[0]
&& pos.advanced_pawn_push(move)
&& pos.pawn_passed(us, to_sq(move)))
extension = 1;
+ // Last captures extension
+ else if ( PieceValue[EG][pos.captured_piece()] > PawnValueEg
+ && pos.non_pawn_material() <= 2 * RookValueMg)
+ extension = 1;
+
// Castling extension
if (type_of(move) == CASTLING)
extension = 1;
- // Calculate new depth for this move
- newDepth = depth - 1 + extension;
-
- // Step 14. Pruning at shallow depth (~170 Elo)
- if ( !rootNode
- && pos.non_pawn_material(us)
- && bestValue > VALUE_MATED_IN_MAX_PLY)
- {
- // Skip quiet moves if movecount exceeds our FutilityMoveCount threshold
- moveCountPruning = moveCount >= futility_move_count(improving, depth);
-
- if ( !captureOrPromotion
- && !givesCheck
- && (!pos.advanced_pawn_push(move) || pos.non_pawn_material(~us) > BishopValueMg))
- {
- // Move count based pruning
- if (moveCountPruning)
- continue;
-
- // Reduced depth of the next LMR search
- int lmrDepth = std::max(newDepth - reduction(improving, depth, moveCount), 0);
-
- // Countermoves based pruning (~20 Elo)
- if ( lmrDepth < 4 + ((ss-1)->statScore > 0 || (ss-1)->moveCount == 1)
- && (*contHist[0])[movedPiece][to_sq(move)] < CounterMovePruneThreshold
- && (*contHist[1])[movedPiece][to_sq(move)] < CounterMovePruneThreshold)
- continue;
-
- // Futility pruning: parent node (~2 Elo)
- if ( lmrDepth < 6
- && !inCheck
- && ss->staticEval + 250 + 211 * lmrDepth <= alpha)
- continue;
-
- // Prune moves with negative SEE (~10 Elo)
- if (!pos.see_ge(move, Value(-(31 - std::min(lmrDepth, 18)) * lmrDepth * lmrDepth)))
- continue;
- }
- else if ( !(givesCheck && extension)
- && !pos.see_ge(move, Value(-199) * depth)) // (~20 Elo)
- continue;
- }
+ // Add extension to new depth
+ newDepth += extension;
// Speculative prefetch as early as possible
prefetch(TT.first_entry(pos.key_after(move)));
// Step 15. Make the move
pos.do_move(move, st, givesCheck);
- // Step 16. Reduced depth search (LMR). If the move fails high it will be
+ // Step 16. Reduced depth search (LMR, ~200 Elo). If the move fails high it will be
// re-searched at full depth.
if ( depth >= 3
- && moveCount > 1 + 2 * rootNode
+ && moveCount > 1 + rootNode + (rootNode && bestValue < alpha)
&& (!rootNode || thisThread->best_move_count(move) == 0)
&& ( !captureOrPromotion
|| moveCountPruning
|| ss->staticEval + PieceValue[EG][pos.captured_piece()] <= alpha
- || cutNode))
+ || cutNode
+ || thisThread->ttHitAverage < 375 * ttHitAverageResolution * ttHitAverageWindow / 1024))
{
Depth r = reduction(improving, depth, moveCount);
+ // Decrease reduction if the ttHit running average is large
+ if (thisThread->ttHitAverage > 500 * ttHitAverageResolution * ttHitAverageWindow / 1024)
+ r--;
+
// Reduction if other threads are searching this position.
if (th.marked())
r++;
- // Decrease reduction if position is or has been on the PV
+ // Decrease reduction if position is or has been on the PV (~10 Elo)
if (ttPv)
r -= 2;
- // Decrease reduction if opponent's move count is high (~10 Elo)
- if ((ss-1)->moveCount > 15)
+ // Decrease reduction if opponent's move count is high (~5 Elo)
+ if ((ss-1)->moveCount > 14)
r--;
- // Decrease reduction if ttMove has been singularly extended
+ // Decrease reduction if ttMove has been singularly extended (~3 Elo)
if (singularLMR)
r -= 2;
if (!captureOrPromotion)
{
- // Increase reduction if ttMove is a capture (~0 Elo)
+ // Increase reduction if ttMove is a capture (~5 Elo)
if (ttCapture)
r++;
- // Increase reduction for cut nodes (~5 Elo)
+ // Increase reduction for cut nodes (~10 Elo)
if (cutNode)
r += 2;
// Decrease reduction for moves that escape a capture. Filter out
// castling moves, because they are coded as "king captures rook" and
- // hence break make_move(). (~5 Elo)
+ // hence break make_move(). (~2 Elo)
else if ( type_of(move) == NORMAL
&& !pos.see_ge(reverse_move(move)))
r -= 2;
+ (*contHist[0])[movedPiece][to_sq(move)]
+ (*contHist[1])[movedPiece][to_sq(move)]
+ (*contHist[3])[movedPiece][to_sq(move)]
- - 4729;
+ - 4926;
// Reset statScore to zero if negative and most stats shows >= 0
if ( ss->statScore < 0
ss->statScore = 0;
// Decrease/increase reduction by comparing opponent's stat score (~10 Elo)
- if (ss->statScore >= -99 && (ss-1)->statScore < -116)
+ if (ss->statScore >= -102 && (ss-1)->statScore < -114)
r--;
- else if ((ss-1)->statScore >= -117 && ss->statScore < -144)
+ else if ((ss-1)->statScore >= -116 && ss->statScore < -154)
r++;
// Decrease/increase reduction for moves with a good/bad history (~30 Elo)
r -= ss->statScore / 16384;
}
+ // Increase reduction for captures/promotions if late move and at low depth
+ else if (depth < 8 && moveCount > 2)
+ r++;
+
Depth d = clamp(newDepth - r, 1, newDepth);
value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, d, true);
// Transposition table lookup
posKey = pos.key();
tte = TT.probe(posKey, ttHit);
- ttValue = ttHit ? value_from_tt(tte->value(), ss->ply) : VALUE_NONE;
+ ttValue = ttHit ? value_from_tt(tte->value(), ss->ply, pos.rule50_count()) : VALUE_NONE;
ttMove = ttHit ? tte->move() : MOVE_NONE;
pvHit = ttHit && tte->is_pv();
if (PvNode && bestValue > alpha)
alpha = bestValue;
- futilityBase = bestValue + 153;
+ futilityBase = bestValue + 154;
}
const PieceToHistory* contHist[] = { (ss-1)->continuationHistory, (ss-2)->continuationHistory,
&& !pos.capture(move);
// Don't search moves with negative SEE values
- if ( (!inCheck || evasionPrunable)
- && !(givesCheck && pos.is_discovery_check_on_king(~pos.side_to_move(), move))
- && !pos.see_ge(move))
+ if ( (!inCheck || evasionPrunable) && !pos.see_ge(move))
continue;
// Speculative prefetch as early as possible
// from the transposition table (which refers to the plies to mate/be mated
// from current position) to "plies to mate/be mated from the root".
- Value value_from_tt(Value v, int ply) {
+ Value value_from_tt(Value v, int ply, int r50c) {
return v == VALUE_NONE ? VALUE_NONE
- : v >= VALUE_MATE_IN_MAX_PLY ? v - ply
- : v <= VALUE_MATED_IN_MAX_PLY ? v + ply : v;
+ : v >= VALUE_MATE_IN_MAX_PLY ? VALUE_MATE - v > 99 - r50c ? VALUE_MATE_IN_MAX_PLY : v - ply
+ : v <= VALUE_MATED_IN_MAX_PLY ? VALUE_MATE + v > 99 - r50c ? VALUE_MATED_IN_MAX_PLY : v + ply : v;
}
for (size_t i = 0; i < multiPV; ++i)
{
- bool updated = (i <= pvIdx && rootMoves[i].score != -VALUE_INFINITE);
+ bool updated = rootMoves[i].score != -VALUE_INFINITE;
if (depth == 1 && !updated)
continue;
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (c) 2013 Ronald de Man
- Copyright (C) 2016-2019 Marco Costalba, Lucas Braesch
+ Copyright (C) 2016-2020 Marco Costalba, Lucas Braesch
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
bool blackStronger = (pos.material_key() != entry->key);
int flipColor = (symmetricBlackToMove || blackStronger) * 8;
- int flipSquares = (symmetricBlackToMove || blackStronger) * 070;
+ int flipSquares = (symmetricBlackToMove || blackStronger) * 56;
int stm = (symmetricBlackToMove || blackStronger) ^ pos.side_to_move();
// For pawns, TB files store 4 separate tables according if leading pawn is on
// Then we reorder the pieces to have the same sequence as the one stored
// in pieces[i]: the sequence that ensures the best compression.
- for (int i = leadPawnsCnt; i < size; ++i)
- for (int j = i; j < size; ++j)
+ for (int i = leadPawnsCnt; i < size - 1; ++i)
+ for (int j = i + 1; j < size; ++j)
if (d->pieces[i] == pieces[j])
{
std::swap(pieces[i], pieces[j]);
// piece is below RANK_5.
if (rank_of(squares[0]) > RANK_4)
for (int i = 0; i < size; ++i)
- squares[i] ^= 070; // Vertical flip: SQ_A8 -> SQ_A1
+ squares[i] ^= SQ_A8; // Vertical flip: SQ_A8 -> SQ_A1
// Look for the first piece of the leading group not on the A1-D4 diagonal
// and ensure it is mapped below the diagonal.
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (c) 2013 Ronald de Man
- Copyright (C) 2016-2019 Marco Costalba, Lucas Braesch
+ Copyright (C) 2016-2020 Marco Costalba, Lucas Braesch
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
main()->wait_for_search_finished();
main()->stopOnPonderhit = stop = false;
+ increaseDepth = true;
main()->ponder = ponderMode;
Search::Limits = limits;
Search::RootMoves rootMoves;
for (Thread* th : *this)
{
- th->shuffleExts = th->nodes = th->tbHits = th->nmpMinPly = 0;
+ th->nodes = th->tbHits = th->nmpMinPly = 0;
th->rootDepth = th->completedDepth = 0;
th->rootMoves = rootMoves;
th->rootPos.set(pos.fen(), pos.is_chess960(), &setupStates->back(), th);
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Pawns::Table pawnsTable;
Material::Table materialTable;
- size_t pvIdx, pvLast, shuffleExts;
+ size_t pvIdx, pvLast;
+ uint64_t ttHitAverage;
int selDepth, nmpMinPly;
Color nmpColor;
std::atomic<uint64_t> nodes, tbHits, bestMoveChanges;
double previousTimeReduction;
Value previousScore;
+ Value iterValue[4];
int callsCnt;
bool stopOnPonderhit;
std::atomic_bool ponder;
uint64_t nodes_searched() const { return accumulate(&Thread::nodes); }
uint64_t tb_hits() const { return accumulate(&Thread::tbHits); }
- std::atomic_bool stop;
+ std::atomic_bool stop, increaseDepth;
private:
StateListPtr setupStates;
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
VALUE_MATED_IN_MAX_PLY = -VALUE_MATE + 2 * MAX_PLY,
PawnValueMg = 128, PawnValueEg = 213,
- KnightValueMg = 782, KnightValueEg = 865,
- BishopValueMg = 830, BishopValueEg = 918,
- RookValueMg = 1289, RookValueEg = 1378,
- QueenValueMg = 2529, QueenValueEg = 2687,
+ KnightValueMg = 781, KnightValueEg = 854,
+ BishopValueMg = 825, BishopValueEg = 915,
+ RookValueMg = 1276, RookValueEg = 1380,
+ QueenValueMg = 2538, QueenValueEg = 2682,
MidgameLimit = 15258, EndgameLimit = 3915
};
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
uint64_t num, nodes = 0, cnt = 1;
vector<string> list = setup_bench(pos, args);
- num = count_if(list.begin(), list.end(), [](string s) { return s.find("go ") == 0; });
+ num = count_if(list.begin(), list.end(), [](string s) { return s.find("go ") == 0 || s.find("eval") == 0; });
TimePoint elapsed = now();
istringstream is(cmd);
is >> skipws >> token;
- if (token == "go")
+ if (token == "go" || token == "eval")
{
cerr << "\nPosition: " << cnt++ << '/' << num << endl;
- go(pos, is, states);
- Threads.main()->wait_for_search_finished();
- nodes += Threads.nodes_searched();
+ if (token == "go")
+ {
+ go(pos, is, states);
+ Threads.main()->wait_for_search_finished();
+ nodes += Threads.nodes_searched();
+ }
+ else
+ sync_cout << "\n" << Eval::trace(pos) << sync_endl;
}
else if (token == "setoption") setoption(is);
else if (token == "position") position(pos, is, states);
// Additional custom non-UCI commands, mainly for debugging.
// Do not use these commands during a search!
- else if (token == "flip") pos.flip();
- else if (token == "bench") bench(pos, is, states);
- else if (token == "d") sync_cout << pos << sync_endl;
- else if (token == "eval") sync_cout << Eval::trace(pos) << sync_endl;
+ else if (token == "flip") pos.flip();
+ else if (token == "bench") bench(pos, is, states);
+ else if (token == "d") sync_cout << pos << sync_endl;
+ else if (token == "eval") sync_cout << Eval::trace(pos) << sync_endl;
+ else if (token == "compiler") sync_cout << compiler_info() << sync_endl;
else
sync_cout << "Unknown command: " << cmd << sync_endl;
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
- Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+ Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by