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