1
0
Fork 0
mirror of https://github.com/sockspls/badfish synced 2025-07-12 12:09:14 +00:00

Merge branch 'master' into clusterMergeMaster8

This commit is contained in:
Joost VandeVondele 2020-01-18 08:26:43 +01:00
commit 8ec5faa46e
42 changed files with 771 additions and 604 deletions

View file

@ -1,5 +1,4 @@
language: cpp language: cpp
sudo: required
dist: xenial dist: xenial
matrix: matrix:

63
AUTHORS
View file

@ -1,4 +1,4 @@
# List of authors for Stockfish, updated for version 10 # List of authors for Stockfish, as of January 7, 2020
Tord Romstad (romstad) Tord Romstad (romstad)
Marco Costalba (mcostalba) Marco Costalba (mcostalba)
@ -22,18 +22,23 @@ Auguste Pop
Balint Pfliegel Balint Pfliegel
Ben Koshy (BKSpurgeon) Ben Koshy (BKSpurgeon)
Bill Henry (VoyagerOne) Bill Henry (VoyagerOne)
Bojun Guo (noobpwnftw, Nooby)
braich braich
Bojun Guo (noobpwnftw) Brian Sheppard (SapphireBrand, briansheppard-toast)
Brian Sheppard (SapphireBrand)
Bryan Cross (crossbr) Bryan Cross (crossbr)
candirufish
Chess13234
Chris Cain (ceebo) Chris Cain (ceebo)
Dan Schmidt Dan Schmidt (dfannius)
Daniel Axtens (daxtens)
Daniel Dugovic (ddugovic) Daniel Dugovic (ddugovic)
Dariusz Orzechowski Dariusz Orzechowski
David Zar David Zar
Daylen Yang (daylen) Daylen Yang (daylen)
DiscanX DiscanX
Eelco de Groot double-beep
Eduardo Cáceres (eduherminio)
Eelco de Groot (KingDefender)
Elvin Liu (solarlight2) Elvin Liu (solarlight2)
erbsenzaehler erbsenzaehler
Ernesto Gatti Ernesto Gatti
@ -60,17 +65,18 @@ Jacques B. (Timshel)
Jan Ondruš (hxim) Jan Ondruš (hxim)
Jared Kish (Kurtbusch) Jared Kish (Kurtbusch)
Jarrod Torriero (DU-jdto) Jarrod Torriero (DU-jdto)
Jean Gauthier (QuaisBla) Jean Gauthier (OuaisBla)
Jean-Francois Romang (jromang) Jean-Francois Romang (jromang)
Jekaa
Jerry Donald Watson (jerrydonaldwatson) Jerry Donald Watson (jerrydonaldwatson)
Jonathan Calovski (Mysseno) Jonathan Calovski (Mysseno)
Jonathan D. (SFisGOD) Jonathan Dumale (SFisGOD)
Joost VandeVondele (vondele) Joost VandeVondele (vondele)
Jörg Oster (joergoster) Jörg Oster (joergoster)
Joseph Ellis (jhellis3) Joseph Ellis (jhellis3)
Joseph R. Prostko Joseph R. Prostko
jundery jundery
Justin Blanchard Justin Blanchard (UncombedCoconut)
Kelly Wilson Kelly Wilson
Ken Takusagawa Ken Takusagawa
kinderchocolate kinderchocolate
@ -78,23 +84,27 @@ Kiran Panditrao (Krgp)
Kojirion Kojirion
Leonardo Ljubičić (ICCF World Champion) Leonardo Ljubičić (ICCF World Champion)
Leonid Pechenik (lp--) Leonid Pechenik (lp--)
Linus Arver Linus Arver (listx)
loco-loco loco-loco
Lub van den Berg (ElbertoOne) Lub van den Berg (ElbertoOne)
Luca Brivio (lucabrivio) Luca Brivio (lucabrivio)
Lucas Braesch (lucasart) Lucas Braesch (lucasart)
Lyudmil Antonov (lantonov) Lyudmil Antonov (lantonov)
Maciej Żenczykowski (zenczykowski) Maciej Żenczykowski (zenczykowski)
Matthew Lai (matthewlai) Malcolm Campbell (xoto10)
Matthew Sullivan
Mark Tenzer (31m059) Mark Tenzer (31m059)
marotear
Matthew Lai (matthewlai)
Matthew Sullivan (Matt14916)
Michael An (man)
Michael Byrne (MichaelB7) Michael Byrne (MichaelB7)
Michael Stembera (mstembera)
Michael Chaly (Vizvezdenec) Michael Chaly (Vizvezdenec)
Michael Stembera (mstembera)
Michael Whiteley (protonspring)
Michel Van den Bergh (vdbergh) Michel Van den Bergh (vdbergh)
Miguel Lahoz (miguel-l) Miguel Lahoz (miguel-l)
Mikael Bäckman (mbootsector) Mikael Bäckman (mbootsector)
Michael Whiteley (protonspring) Mira
Miroslav Fontán (Hexik) Miroslav Fontán (Hexik)
Moez Jellouli (MJZ1977) Moez Jellouli (MJZ1977)
Mohammed Li (tthsqe12) Mohammed Li (tthsqe12)
@ -102,9 +112,11 @@ Nathan Rugg (nmrugg)
Nick Pelling (nickpelling) Nick Pelling (nickpelling)
Nicklas Persson (NicklasPersson) Nicklas Persson (NicklasPersson)
Niklas Fiekas (niklasf) Niklas Fiekas (niklasf)
Nikolay Kostov (NikolayIT)
Ondrej Mosnáček (WOnder93) Ondrej Mosnáček (WOnder93)
Oskar Werkelin Ahlin Oskar Werkelin Ahlin
Pablo Vazquez Pablo Vazquez
Panthee
Pascal Romaret Pascal Romaret
Pasquale Pigazzini (ppigazzini) Pasquale Pigazzini (ppigazzini)
Patrick Jansen (mibere) Patrick Jansen (mibere)
@ -117,24 +129,35 @@ Reuven Peleg
Richard Lloyd Richard Lloyd
Rodrigo Exterckötter Tjäder Rodrigo Exterckötter Tjäder
Ron Britvich (Britvich) Ron Britvich (Britvich)
Ronald de Man (syzygy1) Ronald de Man (syzygy1, syzygy)
Ryan Schmitt Ryan Schmitt
Ryan Takker Ryan Takker
Sami Kiminki (skiminki)
Sebastian Buchwald (UniQP) Sebastian Buchwald (UniQP)
Sergei Antonov (saproj) Sergei Antonov (saproj)
Sergei Ivanov (svivanov72)
sf-x sf-x
shane31 Shane Booth (shane31)
Steinar Gunderson (sesse)
Stefan Geschwentner (locutus2) Stefan Geschwentner (locutus2)
Stefano Cardanobile (Stefano80) Stefano Cardanobile (Stefano80)
Steinar Gunderson (sesse)
Stéphane Nicolet (snicolet) Stéphane Nicolet (snicolet)
Thanar2 Thanar2
thaspel thaspel
theo77186
Tom Truscott
Tom Vijlbrief (tomtor) Tom Vijlbrief (tomtor)
Torsten Franz (torfranz) Torsten Franz (torfranz, tfranzer)
Tracey Emery (basepr1me)
Uri Blass (uriblass) 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 # https://github.com/glinscott/fishtest/blob/master/AUTHORS

View file

@ -181,6 +181,14 @@ compile (for instance with Microsoft MSVC) you need to manually
set/unset some switches in the compiler command line; see file *types.h* set/unset some switches in the compiler command line; see file *types.h*
for a quick reference. 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 ## Understanding the code base and participating in the project
@ -190,12 +198,12 @@ community effort. There are a few ways to help contribute to its growth.
### Donating hardware ### Donating hardware
Improving Stockfish requires a massive amount of testing. You can donate 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) 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](http://tests.stockfishchess.org/tests). and view the current tests on [Fishtest](https://tests.stockfishchess.org/tests).
### Improving the code ### 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 * [In this wiki,](https://www.chessprogramming.org) many techniques used in
Stockfish are explained with a lot of background information. Stockfish are explained with a lot of background information.
@ -207,7 +215,7 @@ Nevertheless, a helpful resource.
* The latest source can always be found on [GitHub](https://github.com/official-stockfish/Stockfish). * 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) 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) 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. first, where the basics of Stockfish development are explained.

View file

@ -1,146 +1,154 @@
Contributors with >10,000 CPU hours as of November 4, 2018 Contributors with >10,000 CPU hours as of January 7, 2020
Thank you! Thank you!
Username CPU Hours Games played Username CPU Hours Games played
noobpwnftw 3730975 292309380 --------------------------------------------------
mibere 535242 43333774 noobpwnftw 9305707 695548021
crunchy 375564 29121434 mlang 780050 61648867
cw 371664 28748719 dew 621626 43921547
fastgm 318178 22283584 mibere 524702 42238645
JojoM 295354 20958931 crunchy 354587 27344275
dew 215476 17079219 cw 354495 27274181
ctoks 214031 17312035 fastgm 332801 22804359
glinscott 204517 13932027 JojoM 295750 20437451
bking_US 187568 12233168 CSU_Dynasty 262015 21828122
velislav 168404 13336219 Fisherman 232181 18939229
CSU_Dynasty 168069 14417712 ctoks 218866 17622052
Thanar 162373 13842179 glinscott 201989 13780820
spams 149531 10940322 tvijlbrief 201204 15337115
Fisherman 141137 12099359 velislav 188630 14348485
drabel 134441 11180178 gvreuls 187164 15149976
leszek 133658 9812120 bking_US 180289 11876016
marrco 133566 10115202 nordlandia 172076 13467830
sqrt2 128420 10022279 leszek 157152 11443978
vdbergh 123230 9200516 Thanar 148021 12365359
tvijlbrief 123007 9498831 spams 141975 10319326
vdv 120381 8555423 drabel 138073 11121749
malala 117291 8126488 vdv 137850 9394330
dsmith 114010 7622414 mgrabiak 133578 10454324
BrunoBanani 104938 7448565 TueRens 132485 10878471
CoffeeOne 100042 4593596 bcross 129683 11557084
Data 94621 8433010 marrco 126078 9356740
mgrabiak 92248 7787406 sqrt2 125830 9724586
bcross 89440 8506568 robal 122873 9593418
brabos 81868 6647613 vdbergh 120766 8926915
BRAVONE 80811 5341681 malala 115926 8002293
psk 77195 6156031 CoffeeOne 114241 5004100
nordlandia 74833 6231930 dsmith 113189 7570238
robal 72818 5969856 BrunoBanani 104644 7436849
TueRens 72523 6383294 Data 92328 8220352
sterni1971 71049 5647590 mhoram 89333 6695109
sunu 65855 5360884 davar 87924 7009424
mhoram 65034 5192880 xoto 81094 6869316
davar 64794 5457564 ElbertoOne 80899 7023771
nssy 64607 5371952 grandphish2 78067 6160199
Pking_cda 64499 5704075 brabos 77212 6186135
biffhero 63557 5480444 psk 75733 5984901
teddybaer 62147 5585620 BRAVONE 73875 5054681
solarlight 61278 5402642 sunu 70771 5597972
ElbertoOne 60156 5504304 sterni1971 70605 5590573
jromang 58854 4704502 MaZePallas 66886 5188978
dv8silencer 57421 3961325 Vizvezdenec 63708 4967313
tinker 56039 4204914 nssy 63462 5259388
Freja 50331 3808121 jromang 61634 4940891
renouve 50318 3544864 teddybaer 61231 5407666
robnjr 47504 4131742 Pking_cda 60099 5293873
grandphish2 47377 4110003 solarlight 57469 5028306
eva42 46857 4075716 dv8silencer 56913 3883992
ttruscott 46802 3811534 tinker 54936 4086118
finfish 46244 3481661 renouve 49732 3501516
rap 46201 3219490 Freja 49543 3733019
ronaldjerum 45641 3964331 robnjr 46972 4053117
xoto 44998 4170431 rap 46563 3219146
gvreuls 44359 3902234 Bobo1239 46036 3817196
bigpen0r 41780 3448224 ttruscott 45304 3649765
Bobo1239 40767 3657490 racerschmacer 44881 3975413
Antihistamine 39218 2792761 finfish 44764 3370515
mhunt 38991 2697512 eva42 41783 3599691
racerschmacer 38929 3756111 biffhero 40263 3111352
VoyagerOne 35896 3378887 bigpen0r 39817 3291647
homyur 35561 3012398 mhunt 38871 2691355
rkl 33217 2978536 ronaldjerum 38820 3240695
pb00067 33034 2803485 Antihistamine 38785 2761312
speedycpu 32043 2531964 pb00067 38038 3086320
SC 31954 2848432 speedycpu 37591 3003273
EthanOConnor 31638 2143255 rkl 37207 3289580
oryx 30962 2899534 VoyagerOne 37050 3441673
gri 30108 2429137 jbwiebe 35320 2805433
csnodgrass 29396 2808611 cuistot 34191 2146279
Garf 28887 2873564 homyur 33927 2850481
Pyafue 28885 1986098 manap 32873 2327384
jkiiski 28014 1923255 gri 32538 2515779
slakovv 27017 2031279 oryx 31267 2899051
Prcuvu 26300 2307154 EthanOConnor 30959 2090311
hyperbolic.tom 26248 2200777 SC 30832 2730764
jbwiebe 25663 2129063 csnodgrass 29505 2688994
anst 25525 2279159 jmdana 29458 2205261
Patrick_G 24222 1835674 strelock 28219 2067805
nabildanial 23524 1586321 jkiiski 27832 1904470
achambord 23495 1942546 Pyafue 27533 1902349
Sharaf_DG 22975 1790697 Garf 27515 2747562
chriswk 22876 1947731 eastorwest 27421 2317535
ncfish1 22689 1830009 slakovv 26903 2021889
cuistot 22201 1383031 Prcuvu 24835 2170122
Zirie 21171 1493227 anst 24714 2190091
Isidor 20634 1736219 hyperbolic.tom 24319 2017394
JanErik 20596 1791991 Patrick_G 23687 1801617
xor12 20535 1819280 Sharaf_DG 22896 1786697
team-oh 20364 1653708 nabildanial 22195 1519409
nesoneg 20264 1493435 chriswk 21931 1868317
dex 20110 1682756 achambord 21665 1767323
rstoesser 19802 1335177 Zirie 20887 1472937
Vizvezdenec 19750 1695579 team-oh 20217 1636708
eastorwest 19531 1841839 Isidor 20096 1680691
sg4032 18913 1720157 ncfish1 19931 1520927
horst.prack 18425 1708197 nesoneg 19875 1463031
cisco2015 18408 1793774 Spprtr 19853 1548165
ianh2105 18133 1668562 JanErik 19849 1703875
MazeOfGalious 18022 1644593 agg177 19478 1395014
ville 17900 1539130 SFTUser 19231 1567999
j3corre 17607 975954 xor12 19017 1680165
eudhan 17502 1424648 sg4032 18431 1641865
jmdana 17351 1287546 rstoesser 18118 1293588
iisiraider 17175 1118788 MazeOfGalious 17917 1629593
jundery 17172 1115855 j3corre 17743 941444
wei 16852 1822582 cisco2015 17725 1690126
SFTUser 16635 1363975 ianh2105 17706 1632562
purplefishies 16621 1106850 dex 17678 1467203
DragonLord 16599 1252348 jundery 17194 1115855
chris 15274 1575333 iisiraider 17019 1101015
IgorLeMasson 15201 1364148 horst.prack 17012 1465656
dju 15074 914278 Adrian.Schmidt123 16563 1281436
Flopzee 14700 1331632 purplefishies 16342 1092533
OssumOpossum 14149 1029265 wei 16274 1745989
enedene 13762 935618 ville 16144 1384026
ako027ako 13442 1250249 eudhan 15712 1283717
AdrianSA 13324 924980 OuaisBla 15581 972000
bpfliegel 13318 886523 DragonLord 15559 1162790
Nikolay.IT 13260 1155612 dju 14716 875569
jpulman 12776 854815 chris 14479 1487385
joster 12438 988413 0xB00B1ES 14079 1001120
fatmurphy 12015 901134 OssumOpossum 13776 1007129
Nesa92 11711 1132245 enedene 13460 905279
Adrian.Schmidt123 11542 898699 bpfliegel 13346 884523
modolief 11228 926456 Ente 13198 1156722
Dark_wizzie 11214 1017910 IgorLeMasson 13087 1147232
mschmidt 10973 818594 jpulman 13000 870599
Andrew Grant 10780 947859 ako027ako 12775 1173203
infinity 10762 746397 Nikolay.IT 12352 1068349
SapphireBrand 10692 1024604 Andrew Grant 12327 895539
Thomas A. Anderson 10553 736094 joster 12008 950160
basepi 10434 935168 AdrianSA 11996 804972
lantonov 10325 972610 Nesa92 11455 1111993
pgontarz 10294 878746 fatmurphy 11345 853210
Spprtr 10189 823246 Dark_wizzie 11108 1007152
crocogoat 10115 1017325 modolief 10869 896470
stocky 10083 718114 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

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -117,7 +117,7 @@ vector<string> setup_bench(const Position& current, istream& is) {
string fenFile = (is >> token) ? token : "default"; string fenFile = (is >> token) ? token : "default";
string limitType = (is >> token) ? token : "depth"; string limitType = (is >> token) ? token : "depth";
go = "go " + limitType + " " + limit; go = limitType == "eval" ? "eval" : "go " + limitType + " " + limit;
if (fenFile == "default") if (fenFile == "default")
fens = Defaults; fens = Defaults;

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -44,7 +44,7 @@ namespace {
// bit 13-14: white pawn file (from FILE_A to FILE_D) // 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) // 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) { 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 { enum Result {

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -76,25 +76,29 @@ void Bitboards::init() {
for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1) for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2) for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2)
SquareDistance[s1][s2] = std::max(distance<File>(s1, s2), distance<Rank>(s1, 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 (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));
}
for (Color c : { WHITE, BLACK }) // Helper returning the target bitboard of a step from a square
for (PieceType pt : { PAWN, KNIGHT, KING }) auto landing_square_bb = [&](Square s, int step)
for (Square s = SQ_A1; s <= SQ_H8; ++s) {
for (int i = 0; steps[pt][i]; ++i) Square to = Square(s + step);
{ return is_ok(to) && distance(s, to) <= 2 ? square_bb(to) : Bitboard(0);
Square to = s + Direction(c == WHITE ? steps[pt][i] : -steps[pt][i]); };
if (is_ok(to) && distance(s, to) < 3) for (Square s = SQ_A1; s <= SQ_H8; ++s)
{ {
if (pt == PAWN) for (int step : {-9, -8, -7, -1, 1, 7, 8, 9} )
PawnAttacks[c][s] |= to; PseudoAttacks[KING][s] |= landing_square_bb(s, step);
else
PseudoAttacks[pt][s] |= to; 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 RookDirections[] = { NORTH, EAST, SOUTH, WEST };
Direction BishopDirections[] = { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }; Direction BishopDirections[] = { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST };

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -119,6 +119,12 @@ inline Bitboard operator^( Bitboard b, Square s) { return b ^ square_bb(s); }
inline Bitboard& operator|=(Bitboard& b, Square s) { return b |= square_bb(s); } inline Bitboard& operator|=(Bitboard& b, Square s) { return b |= square_bb(s); }
inline Bitboard& operator^=(Bitboard& b, Square s) { return b ^= square_bb(s); } inline Bitboard& operator^=(Bitboard& b, Square s) { return b ^= square_bb(s); }
inline Bitboard operator&(Square s, Bitboard b) { return b & s; }
inline Bitboard operator|(Square s, Bitboard b) { return b | s; }
inline Bitboard operator^(Square s, Bitboard b) { return b ^ s; }
inline Bitboard operator|(Square s, Square s2) { return square_bb(s) | square_bb(s2); }
constexpr bool more_than_one(Bitboard b) { constexpr bool more_than_one(Bitboard b) {
return b & (b - 1); return b & (b - 1);
} }

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -74,7 +74,7 @@ namespace {
assert(pos.count<PAWN>(strongSide) == 1); assert(pos.count<PAWN>(strongSide) == 1);
if (file_of(pos.square<PAWN>(strongSide)) >= FILE_E) 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; return strongSide == WHITE ? sq : ~sq;
} }
@ -155,7 +155,7 @@ Value Endgame<KBNK>::operator()(const Position& pos) const {
Square loserKSq = pos.square<KING>(weakSide); Square loserKSq = pos.square<KING>(weakSide);
Square bishopSq = pos.square<BISHOP>(strongSide); 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). // to drive to opposite corners (A8/H1).
Value result = VALUE_KNOWN_WIN Value result = VALUE_KNOWN_WIN
@ -167,7 +167,7 @@ Value Endgame<KBNK>::operator()(const Position& pos) const {
} }
/// 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<> template<>
Value Endgame<KPK>::operator()(const Position& pos) const { Value Endgame<KPK>::operator()(const Position& pos) const {

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -135,16 +135,17 @@ namespace {
constexpr Score KnightOnQueen = S( 16, 12); constexpr Score KnightOnQueen = S( 16, 12);
constexpr Score LongDiagonalBishop = S( 45, 0); constexpr Score LongDiagonalBishop = S( 45, 0);
constexpr Score MinorBehindPawn = S( 18, 3); 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 PassedFile = S( 11, 8);
constexpr Score PawnlessFlank = S( 17, 95); constexpr Score PawnlessFlank = S( 17, 95);
constexpr Score RestrictedPiece = S( 7, 7); constexpr Score RestrictedPiece = S( 7, 7);
constexpr Score ReachableOutpost = S( 32, 10);
constexpr Score RookOnQueenFile = S( 7, 6); constexpr Score RookOnQueenFile = S( 7, 6);
constexpr Score SliderOnQueen = S( 59, 18); constexpr Score SliderOnQueen = S( 59, 18);
constexpr Score ThreatByKing = S( 24, 89); constexpr Score ThreatByKing = S( 24, 89);
constexpr Score ThreatByPawnPush = S( 48, 39); constexpr Score ThreatByPawnPush = S( 48, 39);
constexpr Score ThreatBySafePawn = S(173, 94); constexpr Score ThreatBySafePawn = S(173, 94);
constexpr Score TrappedRook = S( 47, 4); constexpr Score TrappedRook = S( 52, 10);
constexpr Score WeakQueen = S( 49, 15); constexpr Score WeakQueen = S( 49, 15);
#undef S #undef S
@ -213,8 +214,8 @@ namespace {
void Evaluation<T>::initialize() { void Evaluation<T>::initialize() {
constexpr Color Them = (Us == WHITE ? BLACK : WHITE); constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
constexpr Direction Up = (Us == WHITE ? NORTH : SOUTH); constexpr Direction Up = pawn_push(Us);
constexpr Direction Down = (Us == WHITE ? SOUTH : NORTH); constexpr Direction Down = -Up;
constexpr Bitboard LowRanks = (Us == WHITE ? Rank2BB | Rank3BB : Rank7BB | Rank6BB); constexpr Bitboard LowRanks = (Us == WHITE ? Rank2BB | Rank3BB : Rank7BB | Rank6BB);
const Square ksq = pos.square<KING>(Us); const Square ksq = pos.square<KING>(Us);
@ -224,9 +225,9 @@ namespace {
// Find our pawns that are blocked or on the first two ranks // Find our pawns that are blocked or on the first two ranks
Bitboard b = pos.pieces(Us, PAWN) & (shift<Down>(pos.pieces()) | LowRanks); Bitboard b = pos.pieces(Us, PAWN) & (shift<Down>(pos.pieces()) | LowRanks);
// Squares occupied by those pawns, by our king or queen or controlled by // Squares occupied by those pawns, by our king or queen, by blockers to attacks on our king
// enemy pawns are excluded from the mobility area. // or controlled by enemy pawns are excluded from the mobility area.
mobilityArea[Us] = ~(b | pos.pieces(Us, KING, QUEEN) | pe->pawn_attacks(Them)); mobilityArea[Us] = ~(b | pos.pieces(Us, KING, QUEEN) | pos.blockers_for_king(Us) | pe->pawn_attacks(Them));
// Initialize attackedBy[] for king and pawns // Initialize attackedBy[] for king and pawns
attackedBy[Us][KING] = pos.attacks_from<KING>(ksq); attackedBy[Us][KING] = pos.attacks_from<KING>(ksq);
@ -235,15 +236,9 @@ namespace {
attackedBy2[Us] = dblAttackByPawn | (attackedBy[Us][KING] & attackedBy[Us][PAWN]); attackedBy2[Us] = dblAttackByPawn | (attackedBy[Us][KING] & attackedBy[Us][PAWN]);
// Init our king safety tables // Init our king safety tables
kingRing[Us] = attackedBy[Us][KING]; Square s = make_square(clamp(file_of(ksq), FILE_B, FILE_G),
if (relative_rank(Us, ksq) == RANK_1) clamp(rank_of(ksq), RANK_2, RANK_7));
kingRing[Us] |= shift<Up>(kingRing[Us]); kingRing[Us] = PseudoAttacks[KING][s] | s;
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]);
kingAttackersCount[Them] = popcount(kingRing[Us] & pe->pawn_attacks(Them)); kingAttackersCount[Them] = popcount(kingRing[Us] & pe->pawn_attacks(Them));
kingAttacksCount[Them] = kingAttackersWeight[Them] = 0; kingAttacksCount[Them] = kingAttackersWeight[Them] = 0;
@ -258,7 +253,7 @@ namespace {
Score Evaluation<T>::pieces() { Score Evaluation<T>::pieces() {
constexpr Color Them = (Us == WHITE ? BLACK : WHITE); 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 constexpr Bitboard OutpostRanks = (Us == WHITE ? Rank4BB | Rank5BB | Rank6BB
: Rank5BB | Rank4BB | Rank3BB); : Rank5BB | Rank4BB | Rank3BB);
const Square* pl = pos.squares<Pt>(Us); const Square* pl = pos.squares<Pt>(Us);
@ -301,7 +296,7 @@ namespace {
score += Outpost * (Pt == KNIGHT ? 2 : 1); score += Outpost * (Pt == KNIGHT ? 2 : 1);
else if (Pt == KNIGHT && bb & b & ~pos.pieces(Us)) else if (Pt == KNIGHT && bb & b & ~pos.pieces(Us))
score += Outpost; score += ReachableOutpost;
// Knight and Bishop bonus for being right behind a pawn // Knight and Bishop bonus for being right behind a pawn
if (shift<Down>(pos.pieces(PAWN)) & s) if (shift<Down>(pos.pieces(PAWN)) & s)
@ -322,20 +317,19 @@ namespace {
// Bonus for bishop on a long diagonal which can "see" both center squares // 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)) if (more_than_one(attacks_bb<BISHOP>(s, pos.pieces(PAWN)) & Center))
score += LongDiagonalBishop; score += LongDiagonalBishop;
}
// An important Chess960 pattern: A cornered bishop blocked by a friendly // An important Chess960 pattern: a cornered bishop blocked by a friendly
// pawn diagonally in front of it is a very serious problem, especially // pawn diagonally in front of it is a very serious problem, especially
// when that pawn is also blocked. // when that pawn is also blocked.
if ( Pt == BISHOP if ( pos.is_chess960()
&& pos.is_chess960() && (s == relative_square(Us, SQ_A1) || s == relative_square(Us, SQ_H1)))
&& (s == relative_square(Us, SQ_A1) || s == relative_square(Us, SQ_H1))) {
{ Direction d = pawn_push(Us) + (file_of(s) == FILE_A ? EAST : WEST);
Direction d = pawn_push(Us) + (file_of(s) == FILE_A ? EAST : WEST); if (pos.piece_on(s + d) == make_piece(Us, PAWN))
if (pos.piece_on(s + d) == make_piece(Us, PAWN)) score -= !pos.empty(s + d + pawn_push(Us)) ? CorneredBishop * 4
score -= !pos.empty(s + d + pawn_push(Us)) ? CorneredBishop * 4 : pos.piece_on(s + d + d) == make_piece(Us, PAWN) ? CorneredBishop * 2
: pos.piece_on(s + d + d) == make_piece(Us, PAWN) ? CorneredBishop * 2 : CorneredBishop;
: CorneredBishop; }
} }
} }
@ -381,7 +375,7 @@ namespace {
constexpr Bitboard Camp = (Us == WHITE ? AllSquares ^ Rank6BB ^ Rank7BB ^ Rank8BB constexpr Bitboard Camp = (Us == WHITE ? AllSquares ^ Rank6BB ^ Rank7BB ^ Rank8BB
: AllSquares ^ Rank1BB ^ Rank2BB ^ Rank3BB); : AllSquares ^ Rank1BB ^ Rank2BB ^ Rank3BB);
Bitboard weak, b1, b2, safe, unsafeChecks = 0; Bitboard weak, b1, b2, b3, safe, unsafeChecks = 0;
Bitboard rookChecks, queenChecks, bishopChecks, knightChecks; Bitboard rookChecks, queenChecks, bishopChecks, knightChecks;
int kingDanger = 0; int kingDanger = 0;
const Square ksq = pos.square<KING>(Us); const Square ksq = pos.square<KING>(Us);
@ -440,25 +434,27 @@ namespace {
else else
unsafeChecks |= knightChecks; unsafeChecks |= knightChecks;
// Find the squares that opponent attacks in our king flank, and the squares // Find the squares that opponent attacks in our king flank, the squares
// which are attacked twice in that flank. // which they attack twice in that flank, and the squares that we defend.
b1 = attackedBy[Them][ALL_PIECES] & KingFlank[file_of(ksq)] & Camp; b1 = attackedBy[Them][ALL_PIECES] & KingFlank[file_of(ksq)] & Camp;
b2 = b1 & attackedBy2[Them]; 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] kingDanger += kingAttackersCount[Them] * kingAttackersWeight[Them]
+ 69 * kingAttacksCount[Them]
+ 185 * popcount(kingRing[Us] & weak) + 185 * popcount(kingRing[Us] & weak)
- 100 * bool(attackedBy[Us][KNIGHT] & attackedBy[Us][KING])
- 35 * bool(attackedBy[Us][BISHOP] & attackedBy[Us][KING])
+ 148 * popcount(unsafeChecks) + 148 * popcount(unsafeChecks)
+ 98 * popcount(pos.blockers_for_king(Us)) + 98 * popcount(pos.blockers_for_king(Us))
- 873 * !pos.count<QUEEN>(Them) + 69 * kingAttacksCount[Them]
- 6 * mg_value(score) / 8 + 3 * kingFlankAttack * kingFlankAttack / 8
+ mg_value(mobility[Them] - mobility[Us]) + mg_value(mobility[Them] - mobility[Us])
+ 3 * kingFlankAttacks * kingFlankAttacks / 8 - 873 * !pos.count<QUEEN>(Them)
- 7; - 100 * bool(attackedBy[Us][KNIGHT] & attackedBy[Us][KING])
- 6 * mg_value(score) / 8
- 4 * kingFlankDefense
+ 37;
// Transform the kingDanger units into a Score, and subtract it from the evaluation // Transform the kingDanger units into a Score, and subtract it from the evaluation
if (kingDanger > 100) if (kingDanger > 100)
@ -469,7 +465,7 @@ namespace {
score -= PawnlessFlank; score -= PawnlessFlank;
// Penalty if king flank is under attack, potentially moving toward the king // Penalty if king flank is under attack, potentially moving toward the king
score -= FlankAttacks * kingFlankAttacks; score -= FlankAttacks * kingFlankAttack;
if (T) if (T)
Trace::add(KING, Us, score); Trace::add(KING, Us, score);
@ -484,7 +480,7 @@ namespace {
Score Evaluation<T>::threats() const { Score Evaluation<T>::threats() const {
constexpr Color Them = (Us == WHITE ? BLACK : WHITE); 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); constexpr Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB);
Bitboard b, weak, defended, nonPawnEnemies, stronglyProtected, safe; Bitboard b, weak, defended, nonPawnEnemies, stronglyProtected, safe;
@ -578,7 +574,7 @@ namespace {
Score Evaluation<T>::passed() const { Score Evaluation<T>::passed() const {
constexpr Color Them = (Us == WHITE ? BLACK : WHITE); 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) { auto king_proximity = [&](Color c, Square s) {
return std::min(distance(pos.square<KING>(c), s), 5); return std::min(distance(pos.square<KING>(c), s), 5);
@ -596,7 +592,6 @@ namespace {
assert(!(pos.pieces(Them, PAWN) & forward_file_bb(Us, s + Up))); assert(!(pos.pieces(Them, PAWN) & forward_file_bb(Us, s + Up)));
int r = relative_rank(Us, s); int r = relative_rank(Us, s);
File f = file_of(s);
Score bonus = PassedRank[r]; Score bonus = PassedRank[r];
@ -606,8 +601,8 @@ namespace {
Square blockSq = s + Up; Square blockSq = s + Up;
// Adjust bonus based on the king's proximity // Adjust bonus based on the king's proximity
bonus += make_score(0, ( king_proximity(Them, blockSq) * 5 bonus += make_score(0, ( (king_proximity(Them, blockSq) * 19) / 4
- king_proximity(Us, blockSq) * 2) * w); - king_proximity(Us, blockSq) * 2) * w);
// If blockSq is not the queening square then consider also a second push // If blockSq is not the queening square then consider also a second push
if (r != RANK_7) if (r != RANK_7)
@ -646,7 +641,7 @@ namespace {
|| (pos.pieces(PAWN) & (s + Up))) || (pos.pieces(PAWN) & (s + Up)))
bonus = bonus / 2; bonus = bonus / 2;
score += bonus - PassedFile * map_to_queenside(f); score += bonus - PassedFile * map_to_queenside(file_of(s));
} }
if (T) if (T)
@ -670,7 +665,7 @@ namespace {
return SCORE_ZERO; return SCORE_ZERO;
constexpr Color Them = (Us == WHITE ? BLACK : WHITE); constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
constexpr Direction Down = (Us == WHITE ? SOUTH : NORTH); constexpr Direction Down = -pawn_push(Us);
constexpr Bitboard SpaceMask = constexpr Bitboard SpaceMask =
Us == WHITE ? CenterFiles & (Rank2BB | Rank3BB | Rank4BB) Us == WHITE ? CenterFiles & (Rank2BB | Rank3BB | Rank4BB)
: CenterFiles & (Rank7BB | Rank6BB | Rank5BB); : CenterFiles & (Rank7BB | Rank6BB | Rank5BB);
@ -709,6 +704,9 @@ namespace {
int outflanking = distance<File>(pos.square<KING>(WHITE), pos.square<KING>(BLACK)) int outflanking = distance<File>(pos.square<KING>(WHITE), pos.square<KING>(BLACK))
- distance<Rank>(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) bool pawnsOnBothFlanks = (pos.pieces(PAWN) & QueenSide)
&& (pos.pieces(PAWN) & KingSide); && (pos.pieces(PAWN) & KingSide);
@ -720,10 +718,11 @@ namespace {
int complexity = 9 * pe->passed_count() int complexity = 9 * pe->passed_count()
+ 11 * pos.count<PAWN>() + 11 * pos.count<PAWN>()
+ 9 * outflanking + 9 * outflanking
+ 18 * pawnsOnBothFlanks + 12 * infiltration
+ 49 * !pos.non_pawn_material() + 21 * pawnsOnBothFlanks
- 36 * almostUnwinnable + 51 * !pos.non_pawn_material()
-103 ; - 43 * almostUnwinnable
- 100 ;
// Now apply the bonus: note that we find the attacking side by extracting the // 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 // sign of the midgame or endgame values, and that we carefully cap the bonus
@ -751,11 +750,11 @@ namespace {
{ {
if ( pos.opposite_bishops() if ( pos.opposite_bishops()
&& pos.non_pawn_material() == 2 * BishopValueMg) && pos.non_pawn_material() == 2 * BishopValueMg)
sf = 16 + 4 * pe->passed_count(); sf = 22 ;
else else
sf = std::min(sf, 36 + (pos.opposite_bishops() ? 2 : 7) * pos.count<PAWN>(strongSide)); sf = std::min(sf, 36 + (pos.opposite_bishops() ? 2 : 7) * pos.count<PAWN>(strongSide));
sf = std::max(0, sf - (pos.rule50_count() - 12) / 4 ); sf = std::max(0, sf - (pos.rule50_count() - 12) / 4);
} }
return ScaleFactor(sf); return ScaleFactor(sf);
@ -851,6 +850,9 @@ Value Eval::evaluate(const Position& pos) {
std::string Eval::trace(const Position& pos) { std::string Eval::trace(const Position& pos) {
if (pos.checkers())
return "Total evaluation: none (in check)";
std::memset(scores, 0, sizeof(scores)); std::memset(scores, 0, sizeof(scores));
pos.this_thread()->contempt = SCORE_ZERO; // Reset any dynamic contempt pos.this_thread()->contempt = SCORE_ZERO; // Reset any dynamic contempt

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -56,7 +56,7 @@ namespace {
/// Version number. If Version is left empty, then compile date in the format /// Version number. If Version is left empty, then compile date in the format
/// DD-MM-YY and show in engine_info. /// 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 /// 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 /// cout.rdbuf() with two Tie objects that tie cin and cout to a file stream. We
@ -102,6 +102,13 @@ public:
if (!fname.empty() && !l.file.is_open()) if (!fname.empty() && !l.file.is_open())
{ {
l.file.open(fname, ifstream::out); l.file.open(fname, ifstream::out);
if (!l.file.is_open())
{
cerr << "Unable to open debug log file " << fname << endl;
exit(EXIT_FAILURE);
}
cin.rdbuf(&l.in); cin.rdbuf(&l.in);
cout.rdbuf(&l.out); cout.rdbuf(&l.out);
} }
@ -144,6 +151,77 @@ const string engine_info(bool to_uci) {
} }
/// 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 /// Debug functions used mainly to collect run-time statistics
static std::atomic<int64_t> hits[2], means[2]; static std::atomic<int64_t> hits[2], means[2];

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -30,6 +30,7 @@
#include "types.h" #include "types.h"
const std::string engine_info(bool to_uci = false); const std::string engine_info(bool to_uci = false);
const std::string compiler_info();
void prefetch(void* addr); void prefetch(void* addr);
void start_logger(const std::string& fname); void start_logger(const std::string& fname);

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -56,10 +56,11 @@ namespace {
constexpr Color Them = (Us == WHITE ? BLACK : WHITE); constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
constexpr Bitboard TRank7BB = (Us == WHITE ? Rank7BB : Rank2BB); constexpr Bitboard TRank7BB = (Us == WHITE ? Rank7BB : Rank2BB);
constexpr Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB); 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 UpRight = (Us == WHITE ? NORTH_EAST : SOUTH_WEST);
constexpr Direction UpLeft = (Us == WHITE ? NORTH_WEST : SOUTH_EAST); constexpr Direction UpLeft = (Us == WHITE ? NORTH_WEST : SOUTH_EAST);
const Square ksq = pos.square<KING>(Them);
Bitboard emptySquares; Bitboard emptySquares;
Bitboard pawnsOn7 = pos.pieces(Us, PAWN) & TRank7BB; Bitboard pawnsOn7 = pos.pieces(Us, PAWN) & TRank7BB;
@ -84,8 +85,6 @@ namespace {
if (Type == QUIET_CHECKS) if (Type == QUIET_CHECKS)
{ {
Square ksq = pos.square<KING>(Them);
b1 &= pos.attacks_from<PAWN>(ksq, Them); b1 &= pos.attacks_from<PAWN>(ksq, Them);
b2 &= pos.attacks_from<PAWN>(ksq, Them); b2 &= pos.attacks_from<PAWN>(ksq, Them);
@ -130,8 +129,6 @@ namespace {
Bitboard b2 = shift<UpLeft >(pawnsOn7) & enemies; Bitboard b2 = shift<UpLeft >(pawnsOn7) & enemies;
Bitboard b3 = shift<Up >(pawnsOn7) & emptySquares; Bitboard b3 = shift<Up >(pawnsOn7) & emptySquares;
Square ksq = pos.square<KING>(Them);
while (b1) while (b1)
moveList = make_promotions<Type, UpRight>(moveList, pop_lsb(&b1), ksq); moveList = make_promotions<Type, UpRight>(moveList, pop_lsb(&b1), ksq);
@ -187,7 +184,7 @@ namespace {
ExtMove* generate_moves(const Position& pos, ExtMove* moveList, Color us, ExtMove* generate_moves(const Position& pos, ExtMove* moveList, Color us,
Bitboard target) { Bitboard target) {
assert(Pt != KING && Pt != PAWN); static_assert(Pt != KING && Pt != PAWN, "Unsupported piece type in generate_moves()");
const Square* pl = pos.squares<Pt>(us); const Square* pl = pos.squares<Pt>(us);
@ -261,7 +258,7 @@ namespace {
template<GenType Type> template<GenType Type>
ExtMove* generate(const Position& pos, ExtMove* moveList) { ExtMove* generate(const Position& pos, ExtMove* moveList) {
assert(Type == CAPTURES || Type == QUIETS || Type == NON_EVASIONS); static_assert(Type == CAPTURES || Type == QUIETS || Type == NON_EVASIONS, "Unsupported type in generate()");
assert(!pos.checkers()); assert(!pos.checkers());
Color us = pos.side_to_move(); Color us = pos.side_to_move();

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -56,10 +56,10 @@ namespace {
// is behind our king. Note that UnblockedStorm[0][1-2] accommodate opponent pawn // is behind our king. Note that UnblockedStorm[0][1-2] accommodate opponent pawn
// on edge, likely blocked by our king. // on edge, likely blocked by our king.
constexpr Value UnblockedStorm[int(FILE_NB) / 2][RANK_NB] = { constexpr Value UnblockedStorm[int(FILE_NB) / 2][RANK_NB] = {
{ V( 89), V(-285), V(-185), V(93), V(57), V( 45), V( 51) }, { V( 85), V(-289), V(-166), V(97), V(50), V( 45), V( 50) },
{ V( 44), V( -18), V( 123), V(46), V(39), V( -7), V( 23) }, { V( 46), V( -25), V( 122), V(45), V(37), V(-10), V( 20) },
{ V( 4), V( 52), V( 162), V(37), V( 7), V(-14), V( -2) }, { V( -6), V( 51), V( 168), V(34), V(-2), V(-22), V(-14) },
{ V(-10), V( -14), V( 90), V(15), V( 2), V( -7), V(-16) } { V(-15), V( -11), V( 101), V( 4), V(11), V(-15), V(-29) }
}; };
#undef S #undef S
@ -69,7 +69,7 @@ namespace {
Score evaluate(const Position& pos, Pawns::Entry* e) { Score evaluate(const Position& pos, Pawns::Entry* e) {
constexpr Color Them = (Us == WHITE ? BLACK : WHITE); 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 neighbours, stoppers, support, phalanx, opposed;
Bitboard lever, leverPush, blocked; Bitboard lever, leverPush, blocked;
@ -108,7 +108,7 @@ namespace {
// A pawn is backward when it is behind all pawns of the same color on // A pawn is backward when it is behind all pawns of the same color on
// the adjacent files and cannot safely advance. // the adjacent files and cannot safely advance.
backward = !(neighbours & forward_ranks_bb(Them, s + Up)) backward = !(neighbours & forward_ranks_bb(Them, s + Up))
&& (stoppers & (leverPush | blocked)); && (leverPush | blocked);
// Compute additional span if pawn is not backward nor blocked // Compute additional span if pawn is not backward nor blocked
if (!backward && !blocked) if (!backward && !blocked)

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -50,41 +50,6 @@ const string PieceToChar(" PNBRQK pnbrqk");
constexpr Piece Pieces[] = { W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING, 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 }; 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 } // namespace
@ -852,7 +817,7 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
st->nonPawnMaterial[us] += PieceValue[MG][promotion]; 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]; st->pawnKey ^= Zobrist::psq[pc][from] ^ Zobrist::psq[pc][to];
// Reset rule 50 draw counter // Reset rule 50 draw counter
@ -979,7 +944,7 @@ void Position::do_castling(Color us, Square from, Square& to, Square& rfrom, Squ
} }
/// 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. /// the side to move without executing any move on the board.
void Position::do_null_move(StateInfo& newSt) { void Position::do_null_move(StateInfo& newSt) {
@ -1052,77 +1017,96 @@ bool Position::see_ge(Move m, Value threshold) const {
if (type_of(m) != NORMAL) if (type_of(m) != NORMAL)
return VALUE_ZERO >= threshold; return VALUE_ZERO >= threshold;
Bitboard stmAttackers;
Square from = from_sq(m), to = to_sq(m); 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 int swap = PieceValue[MG][piece_on(to)] - threshold;
// we can hope for. if (swap < 0)
balance = PieceValue[MG][piece_on(to)] - threshold;
if (balance < VALUE_ZERO)
return false; return false;
// Now assume the worst possible result: that the opponent can swap = PieceValue[MG][piece_on(from)] - swap;
// capture our piece for free. if (swap <= 0)
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)
return true; 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 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) 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 // 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) if (st->pinners[~stm] & occupied)
stmAttackers &= ~st->blockersForKing[stm]; stmAttackers &= ~st->blockersForKing[stm];
// If stm has no more attackers then give up: stm loses
if (!stmAttackers) if (!stmAttackers)
break; break;
res ^= 1;
// Locate and remove the next least valuable attacker, and add to // Locate and remove the next least valuable attacker, and add to
// the bitboard 'attackers' the possibly X-ray attackers behind it. // the bitboard 'attackers' any X-ray attackers behind it.
nextVictim = min_attacker<PAWN>(byTypeBB, to, stmAttackers, occupied, attackers); if ((bb = stmAttackers & pieces(PAWN)))
stm = ~stm; // Switch side to move
// Negamax the balance with alpha = balance, beta = balance+1 and
// add nextVictim's value.
//
// (balance, balance+1) -> (-balance-1, -balance)
//
assert(balance < VALUE_ZERO);
balance = -balance - 1 - PieceValue[MG][nextVictim];
// 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)
{ {
if (nextVictim == KING && (attackers & pieces(stm))) if ((swap = PawnValueMg - swap) < res)
stm = ~stm; break;
break;
}
assert(nextVictim != KING);
}
return us != stm; // We break the above loop when stm loses
}
occupied ^= lsb(bb);
attackers |= attacks_bb<BISHOP>(to, occupied) & pieces(BISHOP, QUEEN);
}
else if ((bb = stmAttackers & pieces(KNIGHT)))
{
if ((swap = KnightValueMg - swap) < res)
break;
occupied ^= lsb(bb);
}
else if ((bb = stmAttackers & pieces(BISHOP)))
{
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));
}
else // KING
// If we "capture" with the king but opponent still has attackers,
// reverse the result.
return (attackers & ~pieces(stm)) ? res ^ 1 : res;
}
return bool(res);
}
/// Position::is_draw() tests whether the position is drawn by 50-move rule /// Position::is_draw() tests whether the position is drawn by 50-move rule
/// or by repetition. It does not detect stalemates. /// or by repetition. It does not detect stalemates.

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -46,7 +46,6 @@ struct StateInfo {
Square epSquare; Square epSquare;
// Not copied when making a move (will be recomputed anyhow) // Not copied when making a move (will be recomputed anyhow)
int repetition;
Key key; Key key;
Bitboard checkersBB; Bitboard checkersBB;
Piece capturedPiece; Piece capturedPiece;
@ -54,6 +53,7 @@ struct StateInfo {
Bitboard blockersForKing[COLOR_NB]; Bitboard blockersForKing[COLOR_NB];
Bitboard pinners[COLOR_NB]; Bitboard pinners[COLOR_NB];
Bitboard checkSquares[PIECE_TYPE_NB]; Bitboard checkSquares[PIECE_TYPE_NB];
int repetition;
}; };
/// A list to keep track of the position states along the setup moves (from the /// A list to keep track of the position states along the setup moves (from the
@ -277,16 +277,21 @@ inline int Position::castling_rights(Color c) const {
} }
inline bool Position::castling_impeded(CastlingRights cr) const { inline bool Position::castling_impeded(CastlingRights cr) const {
assert(cr == WHITE_OO || cr == WHITE_OOO || cr == BLACK_OO || cr == BLACK_OOO);
return byTypeBB[ALL_PIECES] & castlingPath[cr]; return byTypeBB[ALL_PIECES] & castlingPath[cr];
} }
inline Square Position::castling_rook_square(CastlingRights cr) const { 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]; return castlingRookSquare[cr];
} }
template<PieceType Pt> template<PieceType Pt>
inline Bitboard Position::attacks_from(Square s) const { inline Bitboard Position::attacks_from(Square s) const {
assert(Pt != PAWN); static_assert(Pt != PAWN, "Pawn attacks need color");
return Pt == BISHOP || Pt == ROOK ? attacks_bb<Pt>(s, byTypeBB[ALL_PIECES]) return Pt == BISHOP || Pt == ROOK ? attacks_bb<Pt>(s, byTypeBB[ALL_PIECES])
: Pt == QUEEN ? attacks_from<ROOK>(s) | attacks_from<BISHOP>(s) : Pt == QUEEN ? attacks_from<ROOK>(s) | attacks_from<BISHOP>(s)
: PseudoAttacks[Pt][s]; : PseudoAttacks[Pt][s];
@ -429,7 +434,7 @@ inline void Position::move_piece(Piece pc, Square from, Square to) {
// index[from] is not updated and becomes stale. This works as long as index[] // index[from] is not updated and becomes stale. This works as long as index[]
// is accessed just by known occupied squares. // is accessed just by known occupied squares.
Bitboard fromTo = square_bb(from) | square_bb(to); Bitboard fromTo = from | to;
byTypeBB[ALL_PIECES] ^= fromTo; byTypeBB[ALL_PIECES] ^= fromTo;
byTypeBB[type_of(pc)] ^= fromTo; byTypeBB[type_of(pc)] ^= fromTo;
byColorBB[color_of(pc)] ^= fromTo; byColorBB[color_of(pc)] ^= fromTo;

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -39,24 +39,24 @@ constexpr Score Bonus[][RANK_NB][int(FILE_NB) / 2] = {
{ }, { },
{ }, { },
{ // Knight { // Knight
{ S(-169,-105), S(-96,-74), S(-80,-46), S(-79,-18) }, { S(-175, -96), S(-92,-65), S(-74,-49), S(-73,-21) },
{ S( -79, -70), S(-39,-56), S(-24,-15), S( -9, 6) }, { S( -77, -67), S(-41,-54), S(-27,-18), S(-15, 8) },
{ S( -64, -38), S(-20,-33), S( 4, -5), S( 19, 27) }, { S( -61, -40), S(-17,-27), S( 6, -8), S( 12, 29) },
{ S( -28, -36), S( 5, 0), S( 41, 13), S( 47, 34) }, { S( -35, -35), S( 8, -2), S( 40, 13), S( 49, 28) },
{ S( -29, -41), S( 13,-20), S( 42, 4), S( 52, 35) }, { S( -34, -45), S( 13,-16), S( 44, 9), S( 51, 39) },
{ S( -11, -51), S( 28,-38), S( 63,-17), S( 55, 19) }, { S( -9, -51), S( 22,-44), S( 58,-16), S( 53, 17) },
{ S( -67, -64), S(-21,-45), S( 6,-37), S( 37, 16) }, { S( -67, -69), S(-27,-50), S( 4,-51), S( 37, 12) },
{ S(-200, -98), S(-80,-89), S(-53,-53), S(-32,-16) } { S(-201,-100), S(-83,-88), S(-56,-56), S(-26,-17) }
}, },
{ // Bishop { // Bishop
{ S(-44,-63), S( -4,-30), S(-11,-35), S(-28, -8) }, { S(-53,-57), S( -5,-30), S( -8,-37), S(-23,-12) },
{ S(-18,-38), S( 7,-13), S( 14,-14), S( 3, 0) }, { S(-15,-37), S( 8,-13), S( 19,-17), S( 4, 1) },
{ S( -8,-18), S( 24, 0), S( -3, -7), S( 15, 13) }, { S( -7,-16), S( 21, -1), S( -5, -2), S( 17, 10) },
{ S( 1,-26), S( 8, -3), S( 26, 1), S( 37, 16) }, { S( -5,-20), S( 11, -6), S( 25, 0), S( 39, 17) },
{ S( -7,-24), S( 30, -6), S( 23,-10), S( 28, 17) }, { S(-12,-17), S( 29, -1), S( 22,-14), S( 31, 15) },
{ S(-17,-26), S( 4, 2), S( -1, 1), S( 8, 16) }, { S(-16,-30), S( 6, 6), S( 1, 4), S( 11, 6) },
{ S(-21,-34), S(-19,-18), S( 10, -7), S( -6, 9) }, { S(-17,-31), S(-14,-20), S( 5, -1), S( 0, 1) },
{ S(-48,-51), S( -3,-40), S(-12,-39), S(-25,-20) } { S(-48,-46), S( 1,-42), S(-14,-37), S(-23,-24) }
}, },
{ // Rook { // Rook
{ S(-31, -9), S(-20,-13), S(-14,-10), S(-5, -9) }, { S(-31, -9), S(-20,-13), S(-14,-10), S(-5, -9) },
@ -79,14 +79,14 @@ constexpr Score Bonus[][RANK_NB][int(FILE_NB) / 2] = {
{ S(-2,-75), S(-2,-52), S( 1,-43), S(-2,-36) } { S(-2,-75), S(-2,-52), S( 1,-43), S(-2,-36) }
}, },
{ // King { // King
{ S(272, 0), S(325, 41), S(273, 80), S(190, 93) }, { S(271, 1), S(327, 45), S(271, 85), S(198, 76) },
{ S(277, 57), S(305, 98), S(241,138), S(183,131) }, { S(278, 53), S(303,100), S(234,133), S(179,135) },
{ S(198, 86), S(253,138), S(168,165), S(120,173) }, { S(195, 88), S(258,130), S(169,169), S(120,175) },
{ S(169,103), S(191,152), S(136,168), S(108,169) }, { S(164,103), S(190,156), S(138,172), S( 98,172) },
{ S(145, 98), S(176,166), S(112,197), S( 69,194) }, { S(154, 96), S(179,166), S(105,199), S( 70,199) },
{ S(122, 87), S(159,164), S( 85,174), S( 36,189) }, { S(123, 92), S(145,172), S( 81,184), S( 31,191) },
{ S( 87, 40), S(120, 99), S( 64,128), S( 25,141) }, { S( 88, 47), S(120,121), S( 65,116), S( 33,131) },
{ S( 64, 5), S( 87, 60), S( 49, 75), S( 0, 75) } { S( 59, 11), S( 89, 59), S( 45, 73), S( -1, 78) }
} }
}; };

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -62,10 +62,13 @@ namespace {
// Different node types, used as a template parameter // Different node types, used as a template parameter
enum NodeType { NonPV, PV }; enum NodeType { NonPV, PV };
constexpr uint64_t ttHitAverageWindow = 4096;
constexpr uint64_t ttHitAverageResolution = 1024;
// Razor and futility margins // Razor and futility margins
constexpr int RazorMargin = 661; constexpr int RazorMargin = 531;
Value futility_margin(Depth d, bool improving) { Value futility_margin(Depth d, bool improving) {
return Value(198 * (d - improving)); return Value(217 * (d - improving));
} }
// Reductions lookup table, initialized at startup // Reductions lookup table, initialized at startup
@ -73,16 +76,16 @@ namespace {
Depth reduction(bool i, Depth d, int mn) { Depth reduction(bool i, Depth d, int mn) {
int r = Reductions[d] * Reductions[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, int depth) { 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 // History and stats update bonus, based on depth
int stat_bonus(Depth d) { 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 // Add a small random component to draw evaluations to avoid 3fold-blindness
@ -151,11 +154,12 @@ namespace {
Value qsearch(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth = 0); Value qsearch(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth = 0);
Value value_to_tt(Value v, int ply); 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_pv(Move* pv, Move move, Move* childPv);
void update_continuation_histories(Stack* ss, Piece pc, Square to, int bonus); void update_continuation_histories(Stack* ss, Piece pc, Square to, int bonus);
void update_quiet_stats(const Position& pos, Stack* ss, Move move, Move* quiets, int quietCount, int bonus); void update_quiet_stats(const Position& pos, Stack* ss, Move move, int bonus);
void update_capture_stats(const Position& pos, Move move, Move* captures, int captureCount, int bonus); 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);
// perft() is our utility to verify move generation. All the leaf nodes up // perft() is our utility to verify move generation. All the leaf nodes up
// to the given depth are generated and counted, and the sum is returned. // to the given depth are generated and counted, and the sum is returned.
@ -191,7 +195,7 @@ namespace {
void Search::init() { void Search::init() {
for (int i = 1; i < MAX_MOVES; ++i) 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));
} }
@ -361,6 +365,7 @@ void Thread::search() {
MainThread* mainThread = (this == Threads.main() ? Threads.main() : nullptr); MainThread* mainThread = (this == Threads.main() ? Threads.main() : nullptr);
double timeReduction = 1, totBestMoveChanges = 0; double timeReduction = 1, totBestMoveChanges = 0;
Color us = rootPos.side_to_move(); Color us = rootPos.side_to_move();
int iterIdx = 0;
std::memset(ss-7, 0, 10 * sizeof(Stack)); std::memset(ss-7, 0, 10 * sizeof(Stack));
for (int i = 7; i > 0; i--) for (int i = 7; i > 0; i--)
@ -371,6 +376,16 @@ void Thread::search() {
bestValue = delta = alpha = -VALUE_INFINITE; bestValue = delta = alpha = -VALUE_INFINITE;
beta = 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"]; size_t multiPV = Options["MultiPV"];
// Pick integer skill levels, but non-deterministically round up or down // Pick integer skill levels, but non-deterministically round up or down
@ -392,6 +407,7 @@ void Thread::search() {
multiPV = std::max(multiPV, (size_t)4); multiPV = std::max(multiPV, (size_t)4);
multiPV = std::min(multiPV, rootMoves.size()); multiPV = std::min(multiPV, rootMoves.size());
ttHitAverage = ttHitAverageWindow * ttHitAverageResolution / 2;
int ct = int(Options["Contempt"]) * PawnValueEg / 100; // From centipawns int ct = int(Options["Contempt"]) * PawnValueEg / 100; // From centipawns
@ -407,6 +423,8 @@ void Thread::search() {
contempt = (us == WHITE ? make_score(ct, ct / 2) contempt = (us == WHITE ? make_score(ct, ct / 2)
: -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 // Iterative deepening loop until requested to stop or the target depth is reached
while ( ++rootDepth < MAX_PLY while ( ++rootDepth < MAX_PLY
&& !Threads.stop && !Threads.stop
@ -425,6 +443,9 @@ void Thread::search() {
size_t pvFirst = 0; size_t pvFirst = 0;
pvLast = 0; pvLast = 0;
if (!Threads.increaseDepth)
searchAgainCounter++;
// MultiPV loop. We perform a full root search for each PV line // MultiPV loop. We perform a full root search for each PV line
for (pvIdx = 0; pvIdx < multiPV && !Threads.stop; ++pvIdx) for (pvIdx = 0; pvIdx < multiPV && !Threads.stop; ++pvIdx)
{ {
@ -443,12 +464,12 @@ void Thread::search() {
if (rootDepth >= 4) if (rootDepth >= 4)
{ {
Value previousScore = rootMoves[pvIdx].previousScore; Value previousScore = rootMoves[pvIdx].previousScore;
delta = Value(21 + abs(previousScore) / 128); delta = Value(21 + abs(previousScore) / 256);
alpha = std::max(previousScore - delta,-VALUE_INFINITE); alpha = std::max(previousScore - delta,-VALUE_INFINITE);
beta = std::min(previousScore + delta, VALUE_INFINITE); beta = std::min(previousScore + delta, VALUE_INFINITE);
// Adjust contempt based on root move's previousScore (dynamic contempt) // 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) contempt = (us == WHITE ? make_score(dct, dct / 2)
: -make_score(dct, dct / 2)); : -make_score(dct, dct / 2));
@ -460,7 +481,7 @@ void Thread::search() {
int failedHighCnt = 0; int failedHighCnt = 0;
while (true) 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); bestValue = ::search<PV>(rootPos, ss, alpha, beta, adjustedDepth, false);
// Bring the best move to the front. It is critical that sorting // Bring the best move to the front. It is critical that sorting
@ -553,12 +574,13 @@ void Thread::search() {
&& !Threads.stop && !Threads.stop
&& !mainThread->stopOnPonderhit) && !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); fallingEval = clamp(fallingEval, 0.5, 1.5);
// If the bestMove is stable over several iterations, reduce time accordingly // If the bestMove is stable over several iterations, reduce time accordingly
timeReduction = lastBestMoveDepth + 9 < completedDepth ? 1.97 : 0.98; timeReduction = lastBestMoveDepth + 9 < completedDepth ? 1.94 : 0.91;
double reduction = (1.36 + mainThread->previousTimeReduction) / (2.29 * timeReduction); double reduction = (1.41 + mainThread->previousTimeReduction) / (2.27 * timeReduction);
// Use part of the gained time from a previous stable move for the current move // Use part of the gained time from a previous stable move for the current move
for (Thread* th : Threads) for (Thread* th : Threads)
@ -579,7 +601,16 @@ void Thread::search() {
else else
Threads.stop = true; 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) if (!mainThread)
@ -632,17 +663,17 @@ namespace {
Move ttMove, move, excludedMove, bestMove; Move ttMove, move, excludedMove, bestMove;
Depth extension, newDepth; Depth extension, newDepth;
Value bestValue, value, ttValue, eval, maxValue; Value bestValue, value, ttValue, eval, maxValue;
bool ttHit, ttPv, inCheck, givesCheck, improving, doLMR, priorCapture; bool ttHit, ttPv, inCheck, givesCheck, improving, didLMR, priorCapture;
bool captureOrPromotion, doFullDepthSearch, moveCountPruning, ttCapture; bool captureOrPromotion, doFullDepthSearch, moveCountPruning, ttCapture, singularLMR;
Piece movedPiece; Piece movedPiece;
int moveCount, captureCount, quietCount, singularLMR; int moveCount, captureCount, quietCount;
// Step 1. Initialize node // Step 1. Initialize node
Thread* thisThread = pos.this_thread(); Thread* thisThread = pos.this_thread();
inCheck = pos.checkers(); inCheck = pos.checkers();
priorCapture = pos.captured_piece(); priorCapture = pos.captured_piece();
Color us = pos.side_to_move(); Color us = pos.side_to_move();
moveCount = captureCount = quietCount = singularLMR = ss->moveCount = 0; moveCount = captureCount = quietCount = ss->moveCount = 0;
bestValue = -VALUE_INFINITE; bestValue = -VALUE_INFINITE;
maxValue = VALUE_INFINITE; maxValue = VALUE_INFINITE;
@ -698,10 +729,13 @@ namespace {
excludedMove = ss->excludedMove; excludedMove = ss->excludedMove;
posKey = pos.key() ^ Key(excludedMove << 16); // Isn't a very good hash posKey = pos.key() ^ Key(excludedMove << 16); // Isn't a very good hash
tte = TT.probe(posKey, ttHit); 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] ttMove = rootNode ? thisThread->rootMoves[thisThread->pvIdx].pv[0]
: ttHit ? tte->move() : MOVE_NONE; : ttHit ? tte->move() : MOVE_NONE;
ttPv = PvNode || (ttHit && tte->is_pv()); 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 // At non-PV nodes we check for an early TT cutoff
if ( !PvNode if ( !PvNode
@ -717,7 +751,7 @@ namespace {
if (ttValue >= beta) if (ttValue >= beta)
{ {
if (!pos.capture_or_promotion(ttMove)) if (!pos.capture_or_promotion(ttMove))
update_quiet_stats(pos, ss, ttMove, nullptr, 0, stat_bonus(depth)); update_quiet_stats(pos, ss, ttMove, stat_bonus(depth));
// Extra penalty for early quiet moves of the previous ply // Extra penalty for early quiet moves of the previous ply
if ((ss-1)->moveCount <= 2 && !priorCapture) if ((ss-1)->moveCount <= 2 && !priorCapture)
@ -731,7 +765,9 @@ namespace {
update_continuation_histories(ss, pos.moved_piece(ttMove), to_sq(ttMove), penalty); 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 // Step 5. Tablebases probe
@ -824,18 +860,18 @@ namespace {
eval); eval);
} }
// Step 7. Razoring (~2 Elo) // Step 7. Razoring (~1 Elo)
if ( !rootNode // The required rootNode PV handling is not available in qsearch if ( !rootNode // The required rootNode PV handling is not available in qsearch
&& depth < 2 && depth < 2
&& eval <= alpha - RazorMargin) && eval <= alpha - RazorMargin)
return qsearch<NT>(pos, ss, alpha, beta); return qsearch<NT>(pos, ss, alpha, beta);
improving = ss->staticEval >= (ss-2)->staticEval improving = (ss-2)->staticEval == VALUE_NONE ? (ss->staticEval >= (ss-4)->staticEval
|| (ss-2)->staticEval == VALUE_NONE; || (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 if ( !PvNode
&& depth < 7 && depth < 6
&& eval - futility_margin(depth, improving) >= beta && eval - futility_margin(depth, improving) >= beta
&& eval < VALUE_KNOWN_WIN) // Do not return unproven wins && eval < VALUE_KNOWN_WIN) // Do not return unproven wins
return eval; return eval;
@ -843,10 +879,10 @@ namespace {
// Step 9. Null move search with verification search (~40 Elo) // Step 9. Null move search with verification search (~40 Elo)
if ( !PvNode if ( !PvNode
&& (ss-1)->currentMove != MOVE_NULL && (ss-1)->currentMove != MOVE_NULL
&& (ss-1)->statScore < 22661 && (ss-1)->statScore < 23397
&& eval >= beta && eval >= beta
&& eval >= ss->staticEval && eval >= ss->staticEval
&& ss->staticEval >= beta - 33 * depth + 299 - improving * 30 && ss->staticEval >= beta - 32 * depth + 292 - improving * 30
&& !excludedMove && !excludedMove
&& pos.non_pawn_material(us) && pos.non_pawn_material(us)
&& (ss->ply >= thisThread->nmpMinPly || us != thisThread->nmpColor)) && (ss->ply >= thisThread->nmpMinPly || us != thisThread->nmpColor))
@ -854,7 +890,7 @@ namespace {
assert(eval - beta >= 0); assert(eval - beta >= 0);
// Null move dynamic reduction based on depth and value // 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->currentMove = MOVE_NULL;
ss->continuationHistory = &thisThread->continuationHistory[0][0][NO_PIECE][0]; ss->continuationHistory = &thisThread->continuationHistory[0][0][NO_PIECE][0];
@ -897,7 +933,7 @@ namespace {
&& depth >= 5 && depth >= 5
&& abs(beta) < VALUE_MATE_IN_MAX_PLY) && 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); MovePicker mp(pos, ttMove, raisedBeta - ss->staticEval, &thisThread->captureHistory);
int probCutCount = 0; int probCutCount = 0;
@ -933,13 +969,13 @@ namespace {
} }
} }
// Step 11. Internal iterative deepening (~2 Elo) // Step 11. Internal iterative deepening (~1 Elo)
if (depth >= 7 && !ttMove) if (depth >= 7 && !ttMove)
{ {
search<NT>(pos, ss, alpha, beta, depth - 7, cutNode); search<NT>(pos, ss, alpha, beta, depth - 7, cutNode);
tte = TT.probe(posKey, ttHit); 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; ttMove = ttHit ? tte->move() : MOVE_NONE;
} }
@ -958,7 +994,7 @@ moves_loop: // When in check, search starts from here
ss->killers); ss->killers);
value = bestValue; value = bestValue;
moveCountPruning = false; singularLMR = moveCountPruning = false;
ttCapture = ttMove && pos.capture_or_promotion(ttMove); ttCapture = ttMove && pos.capture_or_promotion(ttMove);
// Mark this node as being searched // Mark this node as being searched
@ -995,9 +1031,50 @@ moves_loop: // When in check, search starts from here
movedPiece = pos.moved_piece(move); movedPiece = pos.moved_piece(move);
givesCheck = pos.gives_check(move); givesCheck = pos.gives_check(move);
// Step 13. Extensions (~70 Elo) // Calculate new depth for this move
newDepth = depth - 1;
// Singular extension search (~60 Elo). If all moves but one fail low on a // 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 (~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), // 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 // 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 // a reduced search on all the other moves but the ttMove and if the
@ -1021,10 +1098,7 @@ moves_loop: // When in check, search starts from here
if (value < singularBeta) if (value < singularBeta)
{ {
extension = 1; extension = 1;
singularLMR++; singularLMR = true;
if (value < singularBeta - std::min(4 * depth, 36))
singularLMR++;
} }
// Multi-cut pruning // Multi-cut pruning
@ -1032,8 +1106,7 @@ moves_loop: // When in check, search starts from here
// search without the ttMove. So we assume this expected Cut-node is not singular, // 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 // that multiple moves fail high, and we can prune the whole subtree by returning
// a soft bound. // a soft bound.
else if ( eval >= beta else if (singularBeta >= beta)
&& singularBeta >= beta)
return singularBeta; return singularBeta;
} }
@ -1042,65 +1115,23 @@ moves_loop: // When in check, search starts from here
&& (pos.is_discovery_check_on_king(~us, move) || pos.see_ge(move))) && (pos.is_discovery_check_on_king(~us, move) || pos.see_ge(move)))
extension = 1; 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 // Passed pawn extension
else if ( move == ss->killers[0] else if ( move == ss->killers[0]
&& pos.advanced_pawn_push(move) && pos.advanced_pawn_push(move)
&& pos.pawn_passed(us, to_sq(move))) && pos.pawn_passed(us, to_sq(move)))
extension = 1; extension = 1;
// Last captures extension
else if ( PieceValue[EG][pos.captured_piece()] > PawnValueEg
&& pos.non_pawn_material() <= 2 * RookValueMg)
extension = 1;
// Castling extension // Castling extension
if (type_of(move) == CASTLING) if (type_of(move) == CASTLING)
extension = 1; extension = 1;
// Calculate new depth for this move // Add extension to new depth
newDepth = depth - 1 + extension; newDepth += 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;
}
// Speculative prefetch as early as possible // Speculative prefetch as early as possible
prefetch(TT.first_entry(pos.key_after(move))); prefetch(TT.first_entry(pos.key_after(move)));
@ -1122,46 +1153,52 @@ moves_loop: // When in check, search starts from here
// Step 15. Make the move // Step 15. Make the move
pos.do_move(move, st, givesCheck); 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. // re-searched at full depth.
if ( depth >= 3 if ( depth >= 3
&& moveCount > 1 + 2 * rootNode && moveCount > 1 + rootNode + (rootNode && bestValue < alpha)
&& (!rootNode || thisThread->best_move_count(move) == 0) && (!rootNode || thisThread->best_move_count(move) == 0)
&& ( !captureOrPromotion && ( !captureOrPromotion
|| moveCountPruning || moveCountPruning
|| ss->staticEval + PieceValue[EG][pos.captured_piece()] <= alpha || ss->staticEval + PieceValue[EG][pos.captured_piece()] <= alpha
|| cutNode)) || cutNode
|| thisThread->ttHitAverage < 375 * ttHitAverageResolution * ttHitAverageWindow / 1024))
{ {
Depth r = reduction(improving, depth, moveCount); 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. // Reduction if other threads are searching this position.
if (th.marked()) if (th.marked())
r++; 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) if (ttPv)
r -= 2; r -= 2;
// Decrease reduction if opponent's move count is high (~10 Elo) // Decrease reduction if opponent's move count is high (~5 Elo)
if ((ss-1)->moveCount > 15) if ((ss-1)->moveCount > 14)
r--; r--;
// Decrease reduction if ttMove has been singularly extended // Decrease reduction if ttMove has been singularly extended (~3 Elo)
r -= singularLMR; if (singularLMR)
r -= 2;
if (!captureOrPromotion) if (!captureOrPromotion)
{ {
// Increase reduction if ttMove is a capture (~0 Elo) // Increase reduction if ttMove is a capture (~5 Elo)
if (ttCapture) if (ttCapture)
r++; r++;
// Increase reduction for cut nodes (~5 Elo) // Increase reduction for cut nodes (~10 Elo)
if (cutNode) if (cutNode)
r += 2; r += 2;
// Decrease reduction for moves that escape a capture. Filter out // Decrease reduction for moves that escape a capture. Filter out
// castling moves, because they are coded as "king captures rook" and // 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 else if ( type_of(move) == NORMAL
&& !pos.see_ge(reverse_move(move))) && !pos.see_ge(reverse_move(move)))
r -= 2; r -= 2;
@ -1170,7 +1207,7 @@ moves_loop: // When in check, search starts from here
+ (*contHist[0])[movedPiece][to_sq(move)] + (*contHist[0])[movedPiece][to_sq(move)]
+ (*contHist[1])[movedPiece][to_sq(move)] + (*contHist[1])[movedPiece][to_sq(move)]
+ (*contHist[3])[movedPiece][to_sq(move)] + (*contHist[3])[movedPiece][to_sq(move)]
- 4729; - 4926;
// Reset statScore to zero if negative and most stats shows >= 0 // Reset statScore to zero if negative and most stats shows >= 0
if ( ss->statScore < 0 if ( ss->statScore < 0
@ -1180,31 +1217,35 @@ moves_loop: // When in check, search starts from here
ss->statScore = 0; ss->statScore = 0;
// Decrease/increase reduction by comparing opponent's stat score (~10 Elo) // 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--; r--;
else if ((ss-1)->statScore >= -117 && ss->statScore < -144) else if ((ss-1)->statScore >= -116 && ss->statScore < -154)
r++; r++;
// Decrease/increase reduction for moves with a good/bad history (~30 Elo) // Decrease/increase reduction for moves with a good/bad history (~30 Elo)
r -= ss->statScore / 16384; 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); Depth d = clamp(newDepth - r, 1, newDepth);
value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, d, true); value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, d, true);
doFullDepthSearch = (value > alpha && d != newDepth), doLMR = true; doFullDepthSearch = (value > alpha && d != newDepth), didLMR = true;
} }
else else
doFullDepthSearch = !PvNode || moveCount > 1, doLMR = false; doFullDepthSearch = !PvNode || moveCount > 1, didLMR = false;
// Step 17. Full depth search when LMR is skipped or fails high // Step 17. Full depth search when LMR is skipped or fails high
if (doFullDepthSearch) if (doFullDepthSearch)
{ {
value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, newDepth, !cutNode); value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, newDepth, !cutNode);
if (doLMR && !captureOrPromotion) if (didLMR && !captureOrPromotion)
{ {
int bonus = value > alpha ? stat_bonus(newDepth) int bonus = value > alpha ? stat_bonus(newDepth)
: -stat_bonus(newDepth); : -stat_bonus(newDepth);
@ -1319,21 +1360,11 @@ moves_loop: // When in check, search starts from here
if (!moveCount) if (!moveCount)
bestValue = excludedMove ? alpha bestValue = excludedMove ? alpha
: inCheck ? mated_in(ss->ply) : VALUE_DRAW; : inCheck ? mated_in(ss->ply) : VALUE_DRAW;
else if (bestMove) else if (bestMove)
{ update_all_stats(pos, ss, bestMove, bestValue, beta, prevSq,
// Quiet best move: update move sorting heuristics quietsSearched, quietCount, capturesSearched, captureCount, depth);
if (!pos.capture_or_promotion(bestMove))
update_quiet_stats(pos, ss, bestMove, quietsSearched, quietCount,
stat_bonus(depth + (bestValue > beta + PawnValueMg)));
update_capture_stats(pos, bestMove, capturesSearched, captureCount, stat_bonus(depth + 1));
// Extra penalty for a quiet TT or main killer move in previous ply when it gets refuted
if ( ((ss-1)->moveCount == 1 || ((ss-1)->currentMove == (ss-1)->killers[0]))
&& !priorCapture)
update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, -stat_bonus(depth + 1));
}
// Bonus for prior countermove that caused the fail low // Bonus for prior countermove that caused the fail low
else if ( (depth >= 3 || PvNode) else if ( (depth >= 3 || PvNode)
&& !priorCapture) && !priorCapture)
@ -1404,7 +1435,7 @@ moves_loop: // When in check, search starts from here
// Transposition table lookup // Transposition table lookup
posKey = pos.key(); posKey = pos.key();
tte = TT.probe(posKey, ttHit); 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; ttMove = ttHit ? tte->move() : MOVE_NONE;
pvHit = ttHit && tte->is_pv(); pvHit = ttHit && tte->is_pv();
@ -1454,7 +1485,7 @@ moves_loop: // When in check, search starts from here
if (PvNode && bestValue > alpha) if (PvNode && bestValue > alpha)
alpha = bestValue; alpha = bestValue;
futilityBase = bestValue + 153; futilityBase = bestValue + 154;
} }
const PieceToHistory* contHist[] = { (ss-1)->continuationHistory, (ss-2)->continuationHistory, const PieceToHistory* contHist[] = { (ss-1)->continuationHistory, (ss-2)->continuationHistory,
@ -1510,9 +1541,7 @@ moves_loop: // When in check, search starts from here
&& !pos.capture(move); && !pos.capture(move);
// Don't search moves with negative SEE values // Don't search moves with negative SEE values
if ( (!inCheck || evasionPrunable) if ( (!inCheck || evasionPrunable) && !pos.see_ge(move))
&& (!givesCheck || !(pos.blockers_for_king(~pos.side_to_move()) & from_sq(move)))
&& !pos.see_ge(move))
continue; continue;
// Speculative prefetch as early as possible // Speculative prefetch as early as possible
@ -1592,11 +1621,11 @@ moves_loop: // When in check, search starts from here
// from the transposition table (which refers to the plies to mate/be mated // 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". // 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 return v == VALUE_NONE ? VALUE_NONE
: v >= VALUE_MATE_IN_MAX_PLY ? v - ply : v >= VALUE_MATE_IN_MAX_PLY ? VALUE_MATE - v > 99 - r50c ? VALUE_MATE_IN_MAX_PLY : v - ply
: v <= VALUE_MATED_IN_MAX_PLY ? v + ply : v; : v <= VALUE_MATED_IN_MAX_PLY ? VALUE_MATE + v > 99 - r50c ? VALUE_MATED_IN_MAX_PLY : v + ply : v;
} }
@ -1610,6 +1639,51 @@ moves_loop: // When in check, search starts from here
} }
// update_all_stats() updates stats at the end of search() when a bestMove is found
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
if (!pos.capture_or_promotion(bestMove))
{
update_quiet_stats(pos, ss, bestMove, bonus2);
// Decrease all the non-best quiet moves
for (int i = 0; i < quietCount; ++i)
{
thisThread->mainHistory[us][from_to(quietsSearched[i])] << -bonus2;
update_continuation_histories(ss, pos.moved_piece(quietsSearched[i]), to_sq(quietsSearched[i]), -bonus2);
}
}
else
captureHistory[moved_piece][to_sq(bestMove)][captured] << bonus1;
// Extra penalty for a quiet TT or main killer move in previous ply when it gets refuted
if ( ((ss-1)->moveCount == 1 || ((ss-1)->currentMove == (ss-1)->killers[0]))
&& !pos.captured_piece())
update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, -bonus1);
// Decrease all the non-best capture moves
for (int i = 0; i < captureCount; ++i)
{
moved_piece = pos.moved_piece(capturesSearched[i]);
captured = type_of(pos.piece_on(to_sq(capturesSearched[i])));
captureHistory[moved_piece][to_sq(capturesSearched[i])][captured] << -bonus1;
}
}
// update_continuation_histories() updates histories of the move pairs formed // update_continuation_histories() updates histories of the move pairs formed
// by moves at ply -1, -2, and -4 with current move. // by moves at ply -1, -2, and -4 with current move.
@ -1621,32 +1695,9 @@ moves_loop: // When in check, search starts from here
} }
// update_capture_stats() updates move sorting heuristics when a new capture best move is found // update_quiet_stats() updates move sorting heuristics
void update_capture_stats(const Position& pos, Move move, void update_quiet_stats(const Position& pos, Stack* ss, Move move, int bonus) {
Move* captures, int captureCount, int bonus) {
CapturePieceToHistory& captureHistory = pos.this_thread()->captureHistory;
Piece moved_piece = pos.moved_piece(move);
PieceType captured = type_of(pos.piece_on(to_sq(move)));
if (pos.capture_or_promotion(move))
captureHistory[moved_piece][to_sq(move)][captured] << bonus;
// Decrease all the other played capture moves
for (int i = 0; i < captureCount; ++i)
{
moved_piece = pos.moved_piece(captures[i]);
captured = type_of(pos.piece_on(to_sq(captures[i])));
captureHistory[moved_piece][to_sq(captures[i])][captured] << -bonus;
}
}
// update_quiet_stats() updates move sorting heuristics when a new quiet best move is found
void update_quiet_stats(const Position& pos, Stack* ss, Move move,
Move* quiets, int quietCount, int bonus) {
if (ss->killers[0] != move) if (ss->killers[0] != move)
{ {
@ -1667,13 +1718,6 @@ moves_loop: // When in check, search starts from here
Square prevSq = to_sq((ss-1)->currentMove); Square prevSq = to_sq((ss-1)->currentMove);
thisThread->counterMoves[pos.piece_on(prevSq)][prevSq] = move; thisThread->counterMoves[pos.piece_on(prevSq)][prevSq] = move;
} }
// Decrease all the other played quiet moves
for (int i = 0; i < quietCount; ++i)
{
thisThread->mainHistory[us][from_to(quiets[i])] << -bonus;
update_continuation_histories(ss, pos.moved_piece(quiets[i]), to_sq(quiets[i]), -bonus);
}
} }
// When playing with strength handicap, choose best move among a set of RootMoves // When playing with strength handicap, choose best move among a set of RootMoves
@ -1762,7 +1806,7 @@ string UCI::pv(const Position& pos, Depth depth, Value alpha, Value beta) {
for (size_t i = 0; i < multiPV; ++i) 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) if (depth == 1 && !updated)
continue; continue;

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View file

@ -1,7 +1,7 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (c) 2013 Ronald de Man 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -684,7 +684,7 @@ Ret do_probe_table(const Position& pos, T* entry, WDLScore wdl, ProbeState* resu
bool blackStronger = (pos.material_key() != entry->key); bool blackStronger = (pos.material_key() != entry->key);
int flipColor = (symmetricBlackToMove || blackStronger) * 8; int flipColor = (symmetricBlackToMove || blackStronger) * 8;
int flipSquares = (symmetricBlackToMove || blackStronger) * 070; int flipSquares = (symmetricBlackToMove || blackStronger) * 56;
int stm = (symmetricBlackToMove || blackStronger) ^ pos.side_to_move(); int stm = (symmetricBlackToMove || blackStronger) ^ pos.side_to_move();
// For pawns, TB files store 4 separate tables according if leading pawn is on // For pawns, TB files store 4 separate tables according if leading pawn is on
@ -707,9 +707,7 @@ Ret do_probe_table(const Position& pos, T* entry, WDLScore wdl, ProbeState* resu
std::swap(squares[0], *std::max_element(squares, squares + leadPawnsCnt, pawns_comp)); std::swap(squares[0], *std::max_element(squares, squares + leadPawnsCnt, pawns_comp));
tbFile = file_of(squares[0]); tbFile = map_to_queenside(file_of(squares[0]));
if (tbFile > FILE_D)
tbFile = file_of(squares[0] ^ 7); // Horizontal flip: SQ_H1 -> SQ_A1
} }
// DTZ tables are one-sided, i.e. they store positions only for white to // DTZ tables are one-sided, i.e. they store positions only for white to
@ -733,8 +731,8 @@ Ret do_probe_table(const Position& pos, T* entry, WDLScore wdl, ProbeState* resu
// Then we reorder the pieces to have the same sequence as the one stored // Then we reorder the pieces to have the same sequence as the one stored
// in pieces[i]: the sequence that ensures the best compression. // in pieces[i]: the sequence that ensures the best compression.
for (int i = leadPawnsCnt; i < size; ++i) for (int i = leadPawnsCnt; i < size - 1; ++i)
for (int j = i; j < size; ++j) for (int j = i + 1; j < size; ++j)
if (d->pieces[i] == pieces[j]) if (d->pieces[i] == pieces[j])
{ {
std::swap(pieces[i], pieces[j]); std::swap(pieces[i], pieces[j]);
@ -765,7 +763,7 @@ Ret do_probe_table(const Position& pos, T* entry, WDLScore wdl, ProbeState* resu
// piece is below RANK_5. // piece is below RANK_5.
if (rank_of(squares[0]) > RANK_4) if (rank_of(squares[0]) > RANK_4)
for (int i = 0; i < size; ++i) 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 // Look for the first piece of the leading group not on the A1-D4 diagonal
// and ensure it is mapped below the diagonal. // and ensure it is mapped below the diagonal.
@ -1063,8 +1061,8 @@ void set(T& e, uint8_t* data) {
enum { Split = 1, HasPawns = 2 }; enum { Split = 1, HasPawns = 2 };
assert(e.hasPawns == !!(*data & HasPawns)); assert(e.hasPawns == bool(*data & HasPawns));
assert((e.key != e.key2) == !!(*data & Split)); assert((e.key != e.key2) == bool(*data & Split));
data++; // First byte stores flags data++; // First byte stores flags

View file

@ -1,7 +1,7 @@
/* /*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (c) 2013 Ronald de Man 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -71,13 +71,13 @@ void Thread::clear() {
captureHistory.fill(0); captureHistory.fill(0);
for (bool inCheck : { false, true }) for (bool inCheck : { false, true })
for (StatsType c : { NoCaptures, Captures }) for (StatsType c : { NoCaptures, Captures })
for (auto& to : continuationHistory[inCheck][c]) for (auto& to : continuationHistory[inCheck][c])
for (auto& h : to) for (auto& h : to)
h->fill(0); h->fill(0);
for (bool inCheck : { false, true }) for (bool inCheck : { false, true })
for (StatsType c : { NoCaptures, Captures }) for (StatsType c : { NoCaptures, Captures })
continuationHistory[inCheck][c][NO_PIECE][0]->fill(Search::CounterMovePruneThreshold - 1); continuationHistory[inCheck][c][NO_PIECE][0]->fill(Search::CounterMovePruneThreshold - 1);
} }
@ -182,6 +182,7 @@ void ThreadPool::start_thinking(Position& pos, StateListPtr& states,
main()->wait_for_search_finished(); main()->wait_for_search_finished();
main()->stopOnPonderhit = stop = false; main()->stopOnPonderhit = stop = false;
increaseDepth = true;
main()->ponder = ponderMode; main()->ponder = ponderMode;
Search::Limits = limits; Search::Limits = limits;
Search::RootMoves rootMoves; Search::RootMoves rootMoves;
@ -210,7 +211,7 @@ void ThreadPool::start_thinking(Position& pos, StateListPtr& states,
for (Thread* th : *this) for (Thread* th : *this)
{ {
th->shuffleExts = th->nodes = th->tbHits = th->TTsaves = th->nmpMinPly = 0; th->nodes = th->tbHits = th->TTsaves = th->nmpMinPly = 0;
th->rootDepth = th->completedDepth = 0; th->rootDepth = th->completedDepth = 0;
th->rootMoves = rootMoves; th->rootMoves = rootMoves;
th->rootPos.set(pos.fen(), pos.is_chess960(), &setupStates->back(), th); th->rootPos.set(pos.fen(), pos.is_chess960(), &setupStates->back(), th);

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -61,7 +61,8 @@ public:
Pawns::Table pawnsTable; Pawns::Table pawnsTable;
Material::Table materialTable; Material::Table materialTable;
size_t pvIdx, pvLast, shuffleExts; size_t pvIdx, pvLast;
uint64_t ttHitAverage;
int selDepth, nmpMinPly; int selDepth, nmpMinPly;
Color nmpColor; Color nmpColor;
std::atomic<uint64_t> nodes, tbHits, TTsaves, bestMoveChanges; std::atomic<uint64_t> nodes, tbHits, TTsaves, bestMoveChanges;
@ -95,6 +96,7 @@ struct MainThread : public Thread {
double previousTimeReduction; double previousTimeReduction;
Value previousScore; Value previousScore;
Value iterValue[4];
int callsCnt; int callsCnt;
bool stopOnPonderhit; bool stopOnPonderhit;
std::atomic_bool ponder; std::atomic_bool ponder;
@ -116,7 +118,7 @@ struct ThreadPool : public std::vector<Thread*> {
uint64_t tb_hits() const { return accumulate(&Thread::tbHits); } uint64_t tb_hits() const { return accumulate(&Thread::tbHits); }
uint64_t TT_saves() const { return accumulate(&Thread::TTsaves); } uint64_t TT_saves() const { return accumulate(&Thread::TTsaves); }
std::atomic_bool stop; std::atomic_bool stop, increaseDepth;
private: private:
StateListPtr setupStates; StateListPtr setupStates;

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -180,10 +180,10 @@ enum Value : int {
VALUE_MATED_IN_MAX_PLY = -VALUE_MATE + 2 * MAX_PLY, VALUE_MATED_IN_MAX_PLY = -VALUE_MATE + 2 * MAX_PLY,
PawnValueMg = 128, PawnValueEg = 213, PawnValueMg = 128, PawnValueEg = 213,
KnightValueMg = 782, KnightValueEg = 865, KnightValueMg = 781, KnightValueEg = 854,
BishopValueMg = 830, BishopValueEg = 918, BishopValueMg = 825, BishopValueEg = 915,
RookValueMg = 1289, RookValueEg = 1378, RookValueMg = 1276, RookValueEg = 1380,
QueenValueMg = 2529, QueenValueEg = 2687, QueenValueMg = 2538, QueenValueEg = 2682,
MidgameLimit = 15258, EndgameLimit = 3915 MidgameLimit = 15258, EndgameLimit = 3915
}; };
@ -341,7 +341,7 @@ inline Score operator*(Score s, int i) {
return result; return result;
} }
/// Multiplication of a Score by an boolean /// Multiplication of a Score by a boolean
inline Score operator*(Score s, bool b) { inline Score operator*(Score s, bool b) {
return Score(int(s) * int(b)); return Score(int(s) * int(b));
} }

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -147,7 +147,7 @@ namespace {
uint64_t num, nodes = 0, cnt = 1; uint64_t num, nodes = 0, cnt = 1;
vector<string> list = setup_bench(pos, args); 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(); TimePoint elapsed = now();
@ -156,13 +156,18 @@ namespace {
istringstream is(cmd); istringstream is(cmd);
is >> skipws >> token; is >> skipws >> token;
if (token == "go") if (token == "go" || token == "eval")
{ {
if (Cluster::is_root()) if (Cluster::is_root())
cerr << "\nPosition: " << cnt++ << '/' << num << endl; cerr << "\nPosition: " << cnt++ << '/' << num << endl;
go(pos, is, states); if (token == "go")
Threads.main()->wait_for_search_finished(); {
nodes += Cluster::nodes_searched(); go(pos, is, states);
Threads.main()->wait_for_search_finished();
nodes += Threads.nodes_searched();
}
else if (Cluster::is_root())
sync_cout << "\n" << Eval::trace(pos) << sync_endl;
} }
else if (token == "setoption") setoption(is); else if (token == "setoption") setoption(is);
else if (token == "position") position(pos, is, states); else if (token == "position") position(pos, is, states);
@ -234,12 +239,14 @@ void UCI::loop(int argc, char* argv[]) {
// Additional custom non-UCI commands, mainly for debugging. // Additional custom non-UCI commands, mainly for debugging.
// Do not use these commands during a search! // Do not use these commands during a search!
else if (token == "flip") pos.flip(); else if (token == "flip") pos.flip();
else if (token == "bench") bench(pos, is, states); else if (token == "bench") bench(pos, is, states);
else if (token == "d" && Cluster::is_root()) else if (token == "d" && Cluster::is_root())
sync_cout << pos << sync_endl; sync_cout << pos << sync_endl;
else if (token == "eval" && Cluster::is_root()) else if (token == "eval" && Cluster::is_root())
sync_cout << Eval::trace(pos) << sync_endl; sync_cout << Eval::trace(pos) << sync_endl;
else if (token == "compiler" && Cluster::is_root())
sync_cout << compiler_info() << sync_endl;
else if (Cluster::is_root()) else if (Cluster::is_root())
sync_cout << "Unknown command: " << cmd << sync_endl; sync_cout << "Unknown command: " << cmd << sync_endl;

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View file

@ -2,7 +2,7 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 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 Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by