Hectozar commited on
Commit
9e63a92
·
verified ·
1 Parent(s): 03dab0c

Delete stockfish-8-linux

Browse files
Files changed (48) hide show
  1. stockfish-8-linux/.travis.yml +0 -55
  2. stockfish-8-linux/AUTHORS +0 -98
  3. stockfish-8-linux/Copying.txt +0 -674
  4. stockfish-8-linux/Linux/stockfish_8_x64 +0 -3
  5. stockfish-8-linux/Linux/stockfish_8_x64_bmi2 +0 -3
  6. stockfish-8-linux/Linux/stockfish_8_x64_modern +0 -3
  7. stockfish-8-linux/Readme.md +0 -115
  8. stockfish-8-linux/appveyor.yml +0 -45
  9. stockfish-8-linux/src/Makefile +0 -545
  10. stockfish-8-linux/src/benchmark.cpp +0 -183
  11. stockfish-8-linux/src/bitbase.cpp +0 -180
  12. stockfish-8-linux/src/bitboard.cpp +0 -333
  13. stockfish-8-linux/src/bitboard.h +0 -338
  14. stockfish-8-linux/src/endgame.cpp +0 -845
  15. stockfish-8-linux/src/endgame.h +0 -125
  16. stockfish-8-linux/src/evaluate.cpp +0 -927
  17. stockfish-8-linux/src/evaluate.h +0 -40
  18. stockfish-8-linux/src/main.cpp +0 -54
  19. stockfish-8-linux/src/material.cpp +0 -225
  20. stockfish-8-linux/src/material.h +0 -73
  21. stockfish-8-linux/src/misc.cpp +0 -187
  22. stockfish-8-linux/src/misc.h +0 -100
  23. stockfish-8-linux/src/movegen.cpp +0 -420
  24. stockfish-8-linux/src/movegen.h +0 -70
  25. stockfish-8-linux/src/movepick.cpp +0 -350
  26. stockfish-8-linux/src/movepick.h +0 -123
  27. stockfish-8-linux/src/pawns.cpp +0 -291
  28. stockfish-8-linux/src/pawns.h +0 -88
  29. stockfish-8-linux/src/position.cpp +0 -1168
  30. stockfish-8-linux/src/position.h +0 -414
  31. stockfish-8-linux/src/psqt.cpp +0 -126
  32. stockfish-8-linux/src/search.cpp +0 -1656
  33. stockfish-8-linux/src/search.h +0 -111
  34. stockfish-8-linux/src/syzygy/tbcore.cpp +0 -1378
  35. stockfish-8-linux/src/syzygy/tbcore.h +0 -169
  36. stockfish-8-linux/src/syzygy/tbprobe.cpp +0 -824
  37. stockfish-8-linux/src/syzygy/tbprobe.h +0 -19
  38. stockfish-8-linux/src/thread.cpp +0 -223
  39. stockfish-8-linux/src/thread.h +0 -111
  40. stockfish-8-linux/src/thread_win32.h +0 -70
  41. stockfish-8-linux/src/timeman.cpp +0 -132
  42. stockfish-8-linux/src/timeman.h +0 -48
  43. stockfish-8-linux/src/tt.cpp +0 -117
  44. stockfish-8-linux/src/tt.h +0 -121
  45. stockfish-8-linux/src/types.h +0 -435
  46. stockfish-8-linux/src/uci.cpp +0 -289
  47. stockfish-8-linux/src/uci.h +0 -80
  48. stockfish-8-linux/src/ucioption.cpp +0 -163
stockfish-8-linux/.travis.yml DELETED
@@ -1,55 +0,0 @@
1
- language: cpp
2
- sudo: required
3
- dist: trusty
4
-
5
- matrix:
6
- include:
7
- - os: linux
8
- compiler: gcc
9
- addons:
10
- apt:
11
- sources: ['ubuntu-toolchain-r-test']
12
- packages: ['g++-6', 'g++-6-multilib', 'g++-multilib', 'valgrind']
13
- env:
14
- - COMPILER=g++-6
15
- - COMP=gcc
16
-
17
- - os: linux
18
- compiler: clang
19
- addons:
20
- apt:
21
- sources: ['ubuntu-toolchain-r-test']
22
- packages: ['clang', 'g++-multilib', 'valgrind']
23
- env:
24
- - COMPILER=clang++
25
- - COMP=clang
26
-
27
- - os: osx
28
- compiler: gcc
29
- env:
30
- - COMPILER=g++
31
- - COMP=gcc
32
-
33
- - os: osx
34
- compiler: clang
35
- env:
36
- - COMPILER=clang++ V='Apple LLVM 6.0' # Apple LLVM version 6.0 (clang-600.0.54) (based on LLVM 3.5svn)
37
- - COMP=clang
38
-
39
- branches:
40
- only:
41
- - master
42
-
43
- before_script:
44
- - cd src
45
-
46
- script:
47
- - make clean && make build ARCH=x86-64 && ./stockfish bench 2>&1 >/dev/null | grep 'Nodes searched' | tee bench1
48
- - make clean && make build ARCH=x86-32 && ./stockfish bench 2>&1 >/dev/null | grep 'Nodes searched' | tee bench2
49
- - echo "Checking for same bench numbers..."
50
- - diff bench1 bench2 > result
51
- - test ! -s result
52
- # if valgrind is available check the build is without error, reduce depth to speedup testing, but not too shallow to catch more cases.
53
- - if [ -x "$(command -v valgrind )" ] ; then make clean && make ARCH=x86-64 debug=yes build && valgrind --error-exitcode=42 ./stockfish bench 128 1 10 default depth 1>/dev/null ; fi
54
- # use g++-6 as a proxy for having sanitizers ... might need revision as they become available for more recent versions of clang/gcc than trusty provides
55
- - if [[ "$COMPILER" == "g++-6" ]]; then make clean && make ARCH=x86-64 sanitize=yes build && ! ./stockfish bench 2>&1 | grep "runtime error:" ; fi
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/AUTHORS DELETED
@@ -1,98 +0,0 @@
1
- # Generated with git shortlog -sn | cut -c8-', which sorts by commits (manually ordered the first four authors)
2
-
3
- Tord Romstad
4
- Marco Costalba
5
- Joona Kiiski
6
- Gary Linscott
7
- lucasart
8
- mstembera
9
- Lucas Braesch
10
- Stefan Geschwentner
11
- Reuven Peleg
12
- Chris Caino
13
- joergoster
14
- VoyagerOne
15
- Jean-Francois Romang
16
- homoSapiensSapiens
17
- Alain SAVARD
18
- Arjun Temurnikar
19
- Stéphane Nicolet
20
- Uri Blass
21
- jundery
22
- Ralph Stößer
23
- Ajith
24
- Leonid Pechenik
25
- Stefano80
26
- Tom Vijlbrief
27
- hxim
28
- snicolet
29
- Daylen Yang
30
- Henri Wiechers
31
- Jonathan Calovski
32
- mbootsector
33
- David Zar
34
- Eelco de Groot
35
- Jerry Donald
36
- Joerg Oster
37
- Jörg Oster
38
- Ryan Schmitt
39
- mcostalba
40
- Alexander Kure
41
- Dan Schmidt
42
- H. Felix Wittmann
43
- Joseph R. Prostko
44
- Justin Blanchard
45
- Linus Arver
46
- NicklasPersson
47
- Rodrigo Exterckötter Tjäder
48
- Ron Britvich
49
- Ronald de Man
50
- RyanTaker
51
- Vince Negri
52
- ceebo
53
- jhellis3
54
- ppigazzini
55
- shane31
56
- Andy Duplain
57
- Auguste Pop
58
- Balint Pfliegel
59
- Chris Cain
60
- DU-jdto
61
- Dariusz Orzechowski
62
- DiscanX
63
- Ernesto Gatti
64
- Gregor Cramer
65
- Guenther Demetz
66
- Hiraoka Takuya
67
- Hongzhi Cheng
68
- Joseph Hellis
69
- Kelly Wilson
70
- Ken T Takusagawa
71
- Kojirion
72
- Luca Brivio
73
- Matt Sullivan
74
- Matthew Lai
75
- Matthew Sullivan
76
- Michel Van den Bergh
77
- Mysseno
78
- Oskar Werkelin Ahlin
79
- Pablo Vazquez
80
- Pascal Romaret
81
- Ralph Stoesser
82
- Ralph St��er
83
- Raminder Singh
84
- Richard Lloyd
85
- Ryan Takker
86
- Stephane Nicolet
87
- Thanar2
88
- absimaldata
89
- braich
90
- gguliash
91
- kinderchocolate
92
- loco-loco
93
- pellanda
94
- renouve
95
- sf-x
96
- thaspel
97
- unknown
98
- uriblass
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/Copying.txt DELETED
@@ -1,674 +0,0 @@
1
- GNU GENERAL PUBLIC LICENSE
2
- Version 3, 29 June 2007
3
-
4
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5
- Everyone is permitted to copy and distribute verbatim copies
6
- of this license document, but changing it is not allowed.
7
-
8
- Preamble
9
-
10
- The GNU General Public License is a free, copyleft license for
11
- software and other kinds of works.
12
-
13
- The licenses for most software and other practical works are designed
14
- to take away your freedom to share and change the works. By contrast,
15
- the GNU General Public License is intended to guarantee your freedom to
16
- share and change all versions of a program--to make sure it remains free
17
- software for all its users. We, the Free Software Foundation, use the
18
- GNU General Public License for most of our software; it applies also to
19
- any other work released this way by its authors. You can apply it to
20
- your programs, too.
21
-
22
- When we speak of free software, we are referring to freedom, not
23
- price. Our General Public Licenses are designed to make sure that you
24
- have the freedom to distribute copies of free software (and charge for
25
- them if you wish), that you receive source code or can get it if you
26
- want it, that you can change the software or use pieces of it in new
27
- free programs, and that you know you can do these things.
28
-
29
- To protect your rights, we need to prevent others from denying you
30
- these rights or asking you to surrender the rights. Therefore, you have
31
- certain responsibilities if you distribute copies of the software, or if
32
- you modify it: responsibilities to respect the freedom of others.
33
-
34
- For example, if you distribute copies of such a program, whether
35
- gratis or for a fee, you must pass on to the recipients the same
36
- freedoms that you received. You must make sure that they, too, receive
37
- or can get the source code. And you must show them these terms so they
38
- know their rights.
39
-
40
- Developers that use the GNU GPL protect your rights with two steps:
41
- (1) assert copyright on the software, and (2) offer you this License
42
- giving you legal permission to copy, distribute and/or modify it.
43
-
44
- For the developers' and authors' protection, the GPL clearly explains
45
- that there is no warranty for this free software. For both users' and
46
- authors' sake, the GPL requires that modified versions be marked as
47
- changed, so that their problems will not be attributed erroneously to
48
- authors of previous versions.
49
-
50
- Some devices are designed to deny users access to install or run
51
- modified versions of the software inside them, although the manufacturer
52
- can do so. This is fundamentally incompatible with the aim of
53
- protecting users' freedom to change the software. The systematic
54
- pattern of such abuse occurs in the area of products for individuals to
55
- use, which is precisely where it is most unacceptable. Therefore, we
56
- have designed this version of the GPL to prohibit the practice for those
57
- products. If such problems arise substantially in other domains, we
58
- stand ready to extend this provision to those domains in future versions
59
- of the GPL, as needed to protect the freedom of users.
60
-
61
- Finally, every program is threatened constantly by software patents.
62
- States should not allow patents to restrict development and use of
63
- software on general-purpose computers, but in those that do, we wish to
64
- avoid the special danger that patents applied to a free program could
65
- make it effectively proprietary. To prevent this, the GPL assures that
66
- patents cannot be used to render the program non-free.
67
-
68
- The precise terms and conditions for copying, distribution and
69
- modification follow.
70
-
71
- TERMS AND CONDITIONS
72
-
73
- 0. Definitions.
74
-
75
- "This License" refers to version 3 of the GNU General Public License.
76
-
77
- "Copyright" also means copyright-like laws that apply to other kinds of
78
- works, such as semiconductor masks.
79
-
80
- "The Program" refers to any copyrightable work licensed under this
81
- License. Each licensee is addressed as "you". "Licensees" and
82
- "recipients" may be individuals or organizations.
83
-
84
- To "modify" a work means to copy from or adapt all or part of the work
85
- in a fashion requiring copyright permission, other than the making of an
86
- exact copy. The resulting work is called a "modified version" of the
87
- earlier work or a work "based on" the earlier work.
88
-
89
- A "covered work" means either the unmodified Program or a work based
90
- on the Program.
91
-
92
- To "propagate" a work means to do anything with it that, without
93
- permission, would make you directly or secondarily liable for
94
- infringement under applicable copyright law, except executing it on a
95
- computer or modifying a private copy. Propagation includes copying,
96
- distribution (with or without modification), making available to the
97
- public, and in some countries other activities as well.
98
-
99
- To "convey" a work means any kind of propagation that enables other
100
- parties to make or receive copies. Mere interaction with a user through
101
- a computer network, with no transfer of a copy, is not conveying.
102
-
103
- An interactive user interface displays "Appropriate Legal Notices"
104
- to the extent that it includes a convenient and prominently visible
105
- feature that (1) displays an appropriate copyright notice, and (2)
106
- tells the user that there is no warranty for the work (except to the
107
- extent that warranties are provided), that licensees may convey the
108
- work under this License, and how to view a copy of this License. If
109
- the interface presents a list of user commands or options, such as a
110
- menu, a prominent item in the list meets this criterion.
111
-
112
- 1. Source Code.
113
-
114
- The "source code" for a work means the preferred form of the work
115
- for making modifications to it. "Object code" means any non-source
116
- form of a work.
117
-
118
- A "Standard Interface" means an interface that either is an official
119
- standard defined by a recognized standards body, or, in the case of
120
- interfaces specified for a particular programming language, one that
121
- is widely used among developers working in that language.
122
-
123
- The "System Libraries" of an executable work include anything, other
124
- than the work as a whole, that (a) is included in the normal form of
125
- packaging a Major Component, but which is not part of that Major
126
- Component, and (b) serves only to enable use of the work with that
127
- Major Component, or to implement a Standard Interface for which an
128
- implementation is available to the public in source code form. A
129
- "Major Component", in this context, means a major essential component
130
- (kernel, window system, and so on) of the specific operating system
131
- (if any) on which the executable work runs, or a compiler used to
132
- produce the work, or an object code interpreter used to run it.
133
-
134
- The "Corresponding Source" for a work in object code form means all
135
- the source code needed to generate, install, and (for an executable
136
- work) run the object code and to modify the work, including scripts to
137
- control those activities. However, it does not include the work's
138
- System Libraries, or general-purpose tools or generally available free
139
- programs which are used unmodified in performing those activities but
140
- which are not part of the work. For example, Corresponding Source
141
- includes interface definition files associated with source files for
142
- the work, and the source code for shared libraries and dynamically
143
- linked subprograms that the work is specifically designed to require,
144
- such as by intimate data communication or control flow between those
145
- subprograms and other parts of the work.
146
-
147
- The Corresponding Source need not include anything that users
148
- can regenerate automatically from other parts of the Corresponding
149
- Source.
150
-
151
- The Corresponding Source for a work in source code form is that
152
- same work.
153
-
154
- 2. Basic Permissions.
155
-
156
- All rights granted under this License are granted for the term of
157
- copyright on the Program, and are irrevocable provided the stated
158
- conditions are met. This License explicitly affirms your unlimited
159
- permission to run the unmodified Program. The output from running a
160
- covered work is covered by this License only if the output, given its
161
- content, constitutes a covered work. This License acknowledges your
162
- rights of fair use or other equivalent, as provided by copyright law.
163
-
164
- You may make, run and propagate covered works that you do not
165
- convey, without conditions so long as your license otherwise remains
166
- in force. You may convey covered works to others for the sole purpose
167
- of having them make modifications exclusively for you, or provide you
168
- with facilities for running those works, provided that you comply with
169
- the terms of this License in conveying all material for which you do
170
- not control copyright. Those thus making or running the covered works
171
- for you must do so exclusively on your behalf, under your direction
172
- and control, on terms that prohibit them from making any copies of
173
- your copyrighted material outside their relationship with you.
174
-
175
- Conveying under any other circumstances is permitted solely under
176
- the conditions stated below. Sublicensing is not allowed; section 10
177
- makes it unnecessary.
178
-
179
- 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180
-
181
- No covered work shall be deemed part of an effective technological
182
- measure under any applicable law fulfilling obligations under article
183
- 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184
- similar laws prohibiting or restricting circumvention of such
185
- measures.
186
-
187
- When you convey a covered work, you waive any legal power to forbid
188
- circumvention of technological measures to the extent such circumvention
189
- is effected by exercising rights under this License with respect to
190
- the covered work, and you disclaim any intention to limit operation or
191
- modification of the work as a means of enforcing, against the work's
192
- users, your or third parties' legal rights to forbid circumvention of
193
- technological measures.
194
-
195
- 4. Conveying Verbatim Copies.
196
-
197
- You may convey verbatim copies of the Program's source code as you
198
- receive it, in any medium, provided that you conspicuously and
199
- appropriately publish on each copy an appropriate copyright notice;
200
- keep intact all notices stating that this License and any
201
- non-permissive terms added in accord with section 7 apply to the code;
202
- keep intact all notices of the absence of any warranty; and give all
203
- recipients a copy of this License along with the Program.
204
-
205
- You may charge any price or no price for each copy that you convey,
206
- and you may offer support or warranty protection for a fee.
207
-
208
- 5. Conveying Modified Source Versions.
209
-
210
- You may convey a work based on the Program, or the modifications to
211
- produce it from the Program, in the form of source code under the
212
- terms of section 4, provided that you also meet all of these conditions:
213
-
214
- a) The work must carry prominent notices stating that you modified
215
- it, and giving a relevant date.
216
-
217
- b) The work must carry prominent notices stating that it is
218
- released under this License and any conditions added under section
219
- 7. This requirement modifies the requirement in section 4 to
220
- "keep intact all notices".
221
-
222
- c) You must license the entire work, as a whole, under this
223
- License to anyone who comes into possession of a copy. This
224
- License will therefore apply, along with any applicable section 7
225
- additional terms, to the whole of the work, and all its parts,
226
- regardless of how they are packaged. This License gives no
227
- permission to license the work in any other way, but it does not
228
- invalidate such permission if you have separately received it.
229
-
230
- d) If the work has interactive user interfaces, each must display
231
- Appropriate Legal Notices; however, if the Program has interactive
232
- interfaces that do not display Appropriate Legal Notices, your
233
- work need not make them do so.
234
-
235
- A compilation of a covered work with other separate and independent
236
- works, which are not by their nature extensions of the covered work,
237
- and which are not combined with it such as to form a larger program,
238
- in or on a volume of a storage or distribution medium, is called an
239
- "aggregate" if the compilation and its resulting copyright are not
240
- used to limit the access or legal rights of the compilation's users
241
- beyond what the individual works permit. Inclusion of a covered work
242
- in an aggregate does not cause this License to apply to the other
243
- parts of the aggregate.
244
-
245
- 6. Conveying Non-Source Forms.
246
-
247
- You may convey a covered work in object code form under the terms
248
- of sections 4 and 5, provided that you also convey the
249
- machine-readable Corresponding Source under the terms of this License,
250
- in one of these ways:
251
-
252
- a) Convey the object code in, or embodied in, a physical product
253
- (including a physical distribution medium), accompanied by the
254
- Corresponding Source fixed on a durable physical medium
255
- customarily used for software interchange.
256
-
257
- b) Convey the object code in, or embodied in, a physical product
258
- (including a physical distribution medium), accompanied by a
259
- written offer, valid for at least three years and valid for as
260
- long as you offer spare parts or customer support for that product
261
- model, to give anyone who possesses the object code either (1) a
262
- copy of the Corresponding Source for all the software in the
263
- product that is covered by this License, on a durable physical
264
- medium customarily used for software interchange, for a price no
265
- more than your reasonable cost of physically performing this
266
- conveying of source, or (2) access to copy the
267
- Corresponding Source from a network server at no charge.
268
-
269
- c) Convey individual copies of the object code with a copy of the
270
- written offer to provide the Corresponding Source. This
271
- alternative is allowed only occasionally and noncommercially, and
272
- only if you received the object code with such an offer, in accord
273
- with subsection 6b.
274
-
275
- d) Convey the object code by offering access from a designated
276
- place (gratis or for a charge), and offer equivalent access to the
277
- Corresponding Source in the same way through the same place at no
278
- further charge. You need not require recipients to copy the
279
- Corresponding Source along with the object code. If the place to
280
- copy the object code is a network server, the Corresponding Source
281
- may be on a different server (operated by you or a third party)
282
- that supports equivalent copying facilities, provided you maintain
283
- clear directions next to the object code saying where to find the
284
- Corresponding Source. Regardless of what server hosts the
285
- Corresponding Source, you remain obligated to ensure that it is
286
- available for as long as needed to satisfy these requirements.
287
-
288
- e) Convey the object code using peer-to-peer transmission, provided
289
- you inform other peers where the object code and Corresponding
290
- Source of the work are being offered to the general public at no
291
- charge under subsection 6d.
292
-
293
- A separable portion of the object code, whose source code is excluded
294
- from the Corresponding Source as a System Library, need not be
295
- included in conveying the object code work.
296
-
297
- A "User Product" is either (1) a "consumer product", which means any
298
- tangible personal property which is normally used for personal, family,
299
- or household purposes, or (2) anything designed or sold for incorporation
300
- into a dwelling. In determining whether a product is a consumer product,
301
- doubtful cases shall be resolved in favor of coverage. For a particular
302
- product received by a particular user, "normally used" refers to a
303
- typical or common use of that class of product, regardless of the status
304
- of the particular user or of the way in which the particular user
305
- actually uses, or expects or is expected to use, the product. A product
306
- is a consumer product regardless of whether the product has substantial
307
- commercial, industrial or non-consumer uses, unless such uses represent
308
- the only significant mode of use of the product.
309
-
310
- "Installation Information" for a User Product means any methods,
311
- procedures, authorization keys, or other information required to install
312
- and execute modified versions of a covered work in that User Product from
313
- a modified version of its Corresponding Source. The information must
314
- suffice to ensure that the continued functioning of the modified object
315
- code is in no case prevented or interfered with solely because
316
- modification has been made.
317
-
318
- If you convey an object code work under this section in, or with, or
319
- specifically for use in, a User Product, and the conveying occurs as
320
- part of a transaction in which the right of possession and use of the
321
- User Product is transferred to the recipient in perpetuity or for a
322
- fixed term (regardless of how the transaction is characterized), the
323
- Corresponding Source conveyed under this section must be accompanied
324
- by the Installation Information. But this requirement does not apply
325
- if neither you nor any third party retains the ability to install
326
- modified object code on the User Product (for example, the work has
327
- been installed in ROM).
328
-
329
- The requirement to provide Installation Information does not include a
330
- requirement to continue to provide support service, warranty, or updates
331
- for a work that has been modified or installed by the recipient, or for
332
- the User Product in which it has been modified or installed. Access to a
333
- network may be denied when the modification itself materially and
334
- adversely affects the operation of the network or violates the rules and
335
- protocols for communication across the network.
336
-
337
- Corresponding Source conveyed, and Installation Information provided,
338
- in accord with this section must be in a format that is publicly
339
- documented (and with an implementation available to the public in
340
- source code form), and must require no special password or key for
341
- unpacking, reading or copying.
342
-
343
- 7. Additional Terms.
344
-
345
- "Additional permissions" are terms that supplement the terms of this
346
- License by making exceptions from one or more of its conditions.
347
- Additional permissions that are applicable to the entire Program shall
348
- be treated as though they were included in this License, to the extent
349
- that they are valid under applicable law. If additional permissions
350
- apply only to part of the Program, that part may be used separately
351
- under those permissions, but the entire Program remains governed by
352
- this License without regard to the additional permissions.
353
-
354
- When you convey a copy of a covered work, you may at your option
355
- remove any additional permissions from that copy, or from any part of
356
- it. (Additional permissions may be written to require their own
357
- removal in certain cases when you modify the work.) You may place
358
- additional permissions on material, added by you to a covered work,
359
- for which you have or can give appropriate copyright permission.
360
-
361
- Notwithstanding any other provision of this License, for material you
362
- add to a covered work, you may (if authorized by the copyright holders of
363
- that material) supplement the terms of this License with terms:
364
-
365
- a) Disclaiming warranty or limiting liability differently from the
366
- terms of sections 15 and 16 of this License; or
367
-
368
- b) Requiring preservation of specified reasonable legal notices or
369
- author attributions in that material or in the Appropriate Legal
370
- Notices displayed by works containing it; or
371
-
372
- c) Prohibiting misrepresentation of the origin of that material, or
373
- requiring that modified versions of such material be marked in
374
- reasonable ways as different from the original version; or
375
-
376
- d) Limiting the use for publicity purposes of names of licensors or
377
- authors of the material; or
378
-
379
- e) Declining to grant rights under trademark law for use of some
380
- trade names, trademarks, or service marks; or
381
-
382
- f) Requiring indemnification of licensors and authors of that
383
- material by anyone who conveys the material (or modified versions of
384
- it) with contractual assumptions of liability to the recipient, for
385
- any liability that these contractual assumptions directly impose on
386
- those licensors and authors.
387
-
388
- All other non-permissive additional terms are considered "further
389
- restrictions" within the meaning of section 10. If the Program as you
390
- received it, or any part of it, contains a notice stating that it is
391
- governed by this License along with a term that is a further
392
- restriction, you may remove that term. If a license document contains
393
- a further restriction but permits relicensing or conveying under this
394
- License, you may add to a covered work material governed by the terms
395
- of that license document, provided that the further restriction does
396
- not survive such relicensing or conveying.
397
-
398
- If you add terms to a covered work in accord with this section, you
399
- must place, in the relevant source files, a statement of the
400
- additional terms that apply to those files, or a notice indicating
401
- where to find the applicable terms.
402
-
403
- Additional terms, permissive or non-permissive, may be stated in the
404
- form of a separately written license, or stated as exceptions;
405
- the above requirements apply either way.
406
-
407
- 8. Termination.
408
-
409
- You may not propagate or modify a covered work except as expressly
410
- provided under this License. Any attempt otherwise to propagate or
411
- modify it is void, and will automatically terminate your rights under
412
- this License (including any patent licenses granted under the third
413
- paragraph of section 11).
414
-
415
- However, if you cease all violation of this License, then your
416
- license from a particular copyright holder is reinstated (a)
417
- provisionally, unless and until the copyright holder explicitly and
418
- finally terminates your license, and (b) permanently, if the copyright
419
- holder fails to notify you of the violation by some reasonable means
420
- prior to 60 days after the cessation.
421
-
422
- Moreover, your license from a particular copyright holder is
423
- reinstated permanently if the copyright holder notifies you of the
424
- violation by some reasonable means, this is the first time you have
425
- received notice of violation of this License (for any work) from that
426
- copyright holder, and you cure the violation prior to 30 days after
427
- your receipt of the notice.
428
-
429
- Termination of your rights under this section does not terminate the
430
- licenses of parties who have received copies or rights from you under
431
- this License. If your rights have been terminated and not permanently
432
- reinstated, you do not qualify to receive new licenses for the same
433
- material under section 10.
434
-
435
- 9. Acceptance Not Required for Having Copies.
436
-
437
- You are not required to accept this License in order to receive or
438
- run a copy of the Program. Ancillary propagation of a covered work
439
- occurring solely as a consequence of using peer-to-peer transmission
440
- to receive a copy likewise does not require acceptance. However,
441
- nothing other than this License grants you permission to propagate or
442
- modify any covered work. These actions infringe copyright if you do
443
- not accept this License. Therefore, by modifying or propagating a
444
- covered work, you indicate your acceptance of this License to do so.
445
-
446
- 10. Automatic Licensing of Downstream Recipients.
447
-
448
- Each time you convey a covered work, the recipient automatically
449
- receives a license from the original licensors, to run, modify and
450
- propagate that work, subject to this License. You are not responsible
451
- for enforcing compliance by third parties with this License.
452
-
453
- An "entity transaction" is a transaction transferring control of an
454
- organization, or substantially all assets of one, or subdividing an
455
- organization, or merging organizations. If propagation of a covered
456
- work results from an entity transaction, each party to that
457
- transaction who receives a copy of the work also receives whatever
458
- licenses to the work the party's predecessor in interest had or could
459
- give under the previous paragraph, plus a right to possession of the
460
- Corresponding Source of the work from the predecessor in interest, if
461
- the predecessor has it or can get it with reasonable efforts.
462
-
463
- You may not impose any further restrictions on the exercise of the
464
- rights granted or affirmed under this License. For example, you may
465
- not impose a license fee, royalty, or other charge for exercise of
466
- rights granted under this License, and you may not initiate litigation
467
- (including a cross-claim or counterclaim in a lawsuit) alleging that
468
- any patent claim is infringed by making, using, selling, offering for
469
- sale, or importing the Program or any portion of it.
470
-
471
- 11. Patents.
472
-
473
- A "contributor" is a copyright holder who authorizes use under this
474
- License of the Program or a work on which the Program is based. The
475
- work thus licensed is called the contributor's "contributor version".
476
-
477
- A contributor's "essential patent claims" are all patent claims
478
- owned or controlled by the contributor, whether already acquired or
479
- hereafter acquired, that would be infringed by some manner, permitted
480
- by this License, of making, using, or selling its contributor version,
481
- but do not include claims that would be infringed only as a
482
- consequence of further modification of the contributor version. For
483
- purposes of this definition, "control" includes the right to grant
484
- patent sublicenses in a manner consistent with the requirements of
485
- this License.
486
-
487
- Each contributor grants you a non-exclusive, worldwide, royalty-free
488
- patent license under the contributor's essential patent claims, to
489
- make, use, sell, offer for sale, import and otherwise run, modify and
490
- propagate the contents of its contributor version.
491
-
492
- In the following three paragraphs, a "patent license" is any express
493
- agreement or commitment, however denominated, not to enforce a patent
494
- (such as an express permission to practice a patent or covenant not to
495
- sue for patent infringement). To "grant" such a patent license to a
496
- party means to make such an agreement or commitment not to enforce a
497
- patent against the party.
498
-
499
- If you convey a covered work, knowingly relying on a patent license,
500
- and the Corresponding Source of the work is not available for anyone
501
- to copy, free of charge and under the terms of this License, through a
502
- publicly available network server or other readily accessible means,
503
- then you must either (1) cause the Corresponding Source to be so
504
- available, or (2) arrange to deprive yourself of the benefit of the
505
- patent license for this particular work, or (3) arrange, in a manner
506
- consistent with the requirements of this License, to extend the patent
507
- license to downstream recipients. "Knowingly relying" means you have
508
- actual knowledge that, but for the patent license, your conveying the
509
- covered work in a country, or your recipient's use of the covered work
510
- in a country, would infringe one or more identifiable patents in that
511
- country that you have reason to believe are valid.
512
-
513
- If, pursuant to or in connection with a single transaction or
514
- arrangement, you convey, or propagate by procuring conveyance of, a
515
- covered work, and grant a patent license to some of the parties
516
- receiving the covered work authorizing them to use, propagate, modify
517
- or convey a specific copy of the covered work, then the patent license
518
- you grant is automatically extended to all recipients of the covered
519
- work and works based on it.
520
-
521
- A patent license is "discriminatory" if it does not include within
522
- the scope of its coverage, prohibits the exercise of, or is
523
- conditioned on the non-exercise of one or more of the rights that are
524
- specifically granted under this License. You may not convey a covered
525
- work if you are a party to an arrangement with a third party that is
526
- in the business of distributing software, under which you make payment
527
- to the third party based on the extent of your activity of conveying
528
- the work, and under which the third party grants, to any of the
529
- parties who would receive the covered work from you, a discriminatory
530
- patent license (a) in connection with copies of the covered work
531
- conveyed by you (or copies made from those copies), or (b) primarily
532
- for and in connection with specific products or compilations that
533
- contain the covered work, unless you entered into that arrangement,
534
- or that patent license was granted, prior to 28 March 2007.
535
-
536
- Nothing in this License shall be construed as excluding or limiting
537
- any implied license or other defenses to infringement that may
538
- otherwise be available to you under applicable patent law.
539
-
540
- 12. No Surrender of Others' Freedom.
541
-
542
- If conditions are imposed on you (whether by court order, agreement or
543
- otherwise) that contradict the conditions of this License, they do not
544
- excuse you from the conditions of this License. If you cannot convey a
545
- covered work so as to satisfy simultaneously your obligations under this
546
- License and any other pertinent obligations, then as a consequence you may
547
- not convey it at all. For example, if you agree to terms that obligate you
548
- to collect a royalty for further conveying from those to whom you convey
549
- the Program, the only way you could satisfy both those terms and this
550
- License would be to refrain entirely from conveying the Program.
551
-
552
- 13. Use with the GNU Affero General Public License.
553
-
554
- Notwithstanding any other provision of this License, you have
555
- permission to link or combine any covered work with a work licensed
556
- under version 3 of the GNU Affero General Public License into a single
557
- combined work, and to convey the resulting work. The terms of this
558
- License will continue to apply to the part which is the covered work,
559
- but the special requirements of the GNU Affero General Public License,
560
- section 13, concerning interaction through a network will apply to the
561
- combination as such.
562
-
563
- 14. Revised Versions of this License.
564
-
565
- The Free Software Foundation may publish revised and/or new versions of
566
- the GNU General Public License from time to time. Such new versions will
567
- be similar in spirit to the present version, but may differ in detail to
568
- address new problems or concerns.
569
-
570
- Each version is given a distinguishing version number. If the
571
- Program specifies that a certain numbered version of the GNU General
572
- Public License "or any later version" applies to it, you have the
573
- option of following the terms and conditions either of that numbered
574
- version or of any later version published by the Free Software
575
- Foundation. If the Program does not specify a version number of the
576
- GNU General Public License, you may choose any version ever published
577
- by the Free Software Foundation.
578
-
579
- If the Program specifies that a proxy can decide which future
580
- versions of the GNU General Public License can be used, that proxy's
581
- public statement of acceptance of a version permanently authorizes you
582
- to choose that version for the Program.
583
-
584
- Later license versions may give you additional or different
585
- permissions. However, no additional obligations are imposed on any
586
- author or copyright holder as a result of your choosing to follow a
587
- later version.
588
-
589
- 15. Disclaimer of Warranty.
590
-
591
- THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592
- APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593
- HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594
- OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595
- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596
- PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597
- IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598
- ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599
-
600
- 16. Limitation of Liability.
601
-
602
- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603
- WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604
- THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605
- GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606
- USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607
- DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608
- PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609
- EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610
- SUCH DAMAGES.
611
-
612
- 17. Interpretation of Sections 15 and 16.
613
-
614
- If the disclaimer of warranty and limitation of liability provided
615
- above cannot be given local legal effect according to their terms,
616
- reviewing courts shall apply local law that most closely approximates
617
- an absolute waiver of all civil liability in connection with the
618
- Program, unless a warranty or assumption of liability accompanies a
619
- copy of the Program in return for a fee.
620
-
621
- END OF TERMS AND CONDITIONS
622
-
623
- How to Apply These Terms to Your New Programs
624
-
625
- If you develop a new program, and you want it to be of the greatest
626
- possible use to the public, the best way to achieve this is to make it
627
- free software which everyone can redistribute and change under these terms.
628
-
629
- To do so, attach the following notices to the program. It is safest
630
- to attach them to the start of each source file to most effectively
631
- state the exclusion of warranty; and each file should have at least
632
- the "copyright" line and a pointer to where the full notice is found.
633
-
634
- <one line to give the program's name and a brief idea of what it does.>
635
- Copyright (C) <year> <name of author>
636
-
637
- This program is free software: you can redistribute it and/or modify
638
- it under the terms of the GNU General Public License as published by
639
- the Free Software Foundation, either version 3 of the License, or
640
- (at your option) any later version.
641
-
642
- This program is distributed in the hope that it will be useful,
643
- but WITHOUT ANY WARRANTY; without even the implied warranty of
644
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645
- GNU General Public License for more details.
646
-
647
- You should have received a copy of the GNU General Public License
648
- along with this program. If not, see <http://www.gnu.org/licenses/>.
649
-
650
- Also add information on how to contact you by electronic and paper mail.
651
-
652
- If the program does terminal interaction, make it output a short
653
- notice like this when it starts in an interactive mode:
654
-
655
- <program> Copyright (C) <year> <name of author>
656
- This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657
- This is free software, and you are welcome to redistribute it
658
- under certain conditions; type `show c' for details.
659
-
660
- The hypothetical commands `show w' and `show c' should show the appropriate
661
- parts of the General Public License. Of course, your program's commands
662
- might be different; for a GUI interface, you would use an "about box".
663
-
664
- You should also get your employer (if you work as a programmer) or school,
665
- if any, to sign a "copyright disclaimer" for the program, if necessary.
666
- For more information on this, and how to apply and follow the GNU GPL, see
667
- <http://www.gnu.org/licenses/>.
668
-
669
- The GNU General Public License does not permit incorporating your program
670
- into proprietary programs. If your program is a subroutine library, you
671
- may consider it more useful to permit linking proprietary applications with
672
- the library. If this is what you want to do, use the GNU Lesser General
673
- Public License instead of this License. But first, please read
674
- <http://www.gnu.org/philosophy/why-not-lgpl.html>.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/Linux/stockfish_8_x64 DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:d8d492ad30488ee16c84f1b8e81ba347eb19aa04d23f9b5ee9fcd57b37fe40ff
3
- size 1163544
 
 
 
 
stockfish-8-linux/Linux/stockfish_8_x64_bmi2 DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:0dfd94228e9e59c766935dd0be15af17d0e112b139a0d0df44f869a908caa7d7
3
- size 1155352
 
 
 
 
stockfish-8-linux/Linux/stockfish_8_x64_modern DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:8bb21573bf736df1b99d5c1e200d16518c839fe9ac974e87b3ab679d29484f90
3
- size 1155352
 
 
 
 
stockfish-8-linux/Readme.md DELETED
@@ -1,115 +0,0 @@
1
- ### Overview
2
-
3
- [![Build Status](https://travis-ci.org/official-stockfish/Stockfish.svg?branch=master)](https://travis-ci.org/official-stockfish/Stockfish)
4
- [![Build Status](https://ci.appveyor.com/api/projects/status/github/official-stockfish/Stockfish?svg=true)](https://ci.appveyor.com/project/mcostalba/stockfish)
5
-
6
- Stockfish is a free UCI chess engine derived from Glaurung 2.1. It is
7
- not a complete chess program and requires some UCI-compatible GUI
8
- (e.g. XBoard with PolyGlot, eboard, Arena, Sigma Chess, Shredder, Chess
9
- Partner or Fritz) in order to be used comfortably. Read the
10
- documentation for your GUI of choice for information about how to use
11
- Stockfish with it.
12
-
13
- This version of Stockfish supports up to 128 cores. The engine defaults
14
- to one search thread, so it is therefore recommended to inspect the value of
15
- the *Threads* UCI parameter, and to make sure it equals the number of CPU
16
- cores on your computer.
17
-
18
- This version of Stockfish has support for Syzygybases.
19
-
20
-
21
- ### Files
22
-
23
- This distribution of Stockfish consists of the following files:
24
-
25
- * Readme.md, the file you are currently reading.
26
-
27
- * Copying.txt, a text file containing the GNU General Public License.
28
-
29
- * src, a subdirectory containing the full source code, including a Makefile
30
- that can be used to compile Stockfish on Unix-like systems.
31
-
32
-
33
- ### Syzygybases
34
-
35
- **Configuration**
36
-
37
- Syzygybases are configured using the UCI options "SyzygyPath",
38
- "SyzygyProbeDepth", "Syzygy50MoveRule" and "SyzygyProbeLimit".
39
-
40
- The option "SyzygyPath" should be set to the directory or directories that
41
- contain the .rtbw and .rtbz files. Multiple directories should be
42
- separated by ";" on Windows and by ":" on Unix-based operating systems.
43
- **Do not use spaces around the ";" or ":".**
44
-
45
- Example: `C:\tablebases\wdl345;C:\tablebases\wdl6;D:\tablebases\dtz345;D:\tablebases\dtz6`
46
-
47
- It is recommended to store .rtbw files on an SSD. There is no loss in
48
- storing the .rtbz files on a regular HD.
49
-
50
- Increasing the "SyzygyProbeDepth" option lets the engine probe less
51
- aggressively. Set this option to a higher value if you experience too much
52
- slowdown (in terms of nps) due to TB probing.
53
-
54
- Set the "Syzygy50MoveRule" option to false if you want tablebase positions
55
- that are drawn by the 50-move rule to count as win or loss. This may be useful
56
- for correspondence games (because of tablebase adjudication).
57
-
58
- The "SyzygyProbeLimit" option should normally be left at its default value.
59
-
60
- **What to expect**
61
- If the engine is searching a position that is not in the tablebases (e.g.
62
- a position with 7 pieces), it will access the tablebases during the search.
63
- If the engine reports a very large score (typically 123.xx), this means
64
- that it has found a winning line into a tablebase position.
65
-
66
- If the engine is given a position to search that is in the tablebases, it
67
- will use the tablebases at the beginning of the search to preselect all
68
- good moves, i.e. all moves that preserve the win or preserve the draw while
69
- taking into account the 50-move rule.
70
- It will then perform a search only on those moves. **The engine will not move
71
- immediately**, unless there is only a single good move. **The engine likely
72
- will not report a mate score even if the position is known to be won.**
73
-
74
- It is therefore clear that behaviour is not identical to what one might
75
- be used to with Nalimov tablebases. There are technical reasons for this
76
- difference, the main technical reason being that Nalimov tablebases use the
77
- DTM metric (distance-to-mate), while Syzygybases use a variation of the
78
- DTZ metric (distance-to-zero, zero meaning any move that resets the 50-move
79
- counter). This special metric is one of the reasons that Syzygybases are
80
- more compact than Nalimov tablebases, while still storing all information
81
- needed for optimal play and in addition being able to take into account
82
- the 50-move rule.
83
-
84
-
85
- ### Compiling it yourself
86
-
87
- On Unix-like systems, it should be possible to compile Stockfish
88
- directly from the source code with the included Makefile.
89
-
90
- Stockfish has support for 32 or 64-bit CPUs, the hardware POPCNT
91
- instruction, big-endian machines such as Power PC, and other platforms.
92
-
93
- In general it is recommended to run `make help` to see a list of make
94
- targets with corresponding descriptions. When not using the Makefile to
95
- compile (for instance with Microsoft MSVC) you need to manually
96
- set/unset some switches in the compiler command line; see file *types.h*
97
- for a quick reference.
98
-
99
-
100
- ### Terms of use
101
-
102
- Stockfish is free, and distributed under the **GNU General Public License**
103
- (GPL). Essentially, this means that you are free to do almost exactly
104
- what you want with the program, including distributing it among your
105
- friends, making it available for download from your web site, selling
106
- it (either by itself or as part of some bigger software package), or
107
- using it as the starting point for a software project of your own.
108
-
109
- The only real limitation is that whenever you distribute Stockfish in
110
- some way, you must always include the full source code, or a pointer
111
- to where the source code can be found. If you make any changes to the
112
- source code, these changes must also be made available under the GPL.
113
-
114
- For full details, read the copy of the GPL found in the file named
115
- *Copying.txt*.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/appveyor.yml DELETED
@@ -1,45 +0,0 @@
1
- version: 1.0.{build}
2
- clone_depth: 5
3
-
4
- branches:
5
- only:
6
- - master
7
- - appveyor
8
-
9
- # Operating system (build VM template)
10
- os: Visual Studio 2015
11
-
12
- # Build platform, i.e. x86, x64, AnyCPU. This setting is optional.
13
- platform:
14
- - x86
15
- - x64
16
- - Any CPU
17
-
18
- # build Configuration, i.e. Debug, Release, etc.
19
- configuration: Debug
20
-
21
- matrix:
22
- # The build fail immediately once one of the job fails
23
- fast_finish: true
24
-
25
- # Scripts that are called at very beginning, before repo cloning
26
- init:
27
- - cmake --version
28
- - msbuild /version
29
-
30
- before_build:
31
- - cd src
32
- - echo project (Stockfish) >> CMakeLists.txt
33
- - echo add_executable(stockfish benchmark.cpp bitbase.cpp bitboard.cpp endgame.cpp evaluate.cpp >> CMakeLists.txt
34
- - echo main.cpp material.cpp misc.cpp movegen.cpp movepick.cpp pawns.cpp position.cpp psqt.cpp >> CMakeLists.txt
35
- - echo search.cpp thread.cpp timeman.cpp tt.cpp uci.cpp ucioption.cpp syzygy/tbprobe.cpp) >> CMakeLists.txt
36
- - echo set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/src) >> CMakeLists.txt
37
- # - echo target_compile_options(stockfish PUBLIC "/Ox") >> CMakeLists.txt
38
-
39
- build_script:
40
- - cmake -G "Visual Studio 14 2015 Win64" .
41
- - cmake --build .
42
-
43
- before_test:
44
- - cd Debug
45
- - stockfish.exe bench > null
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/Makefile DELETED
@@ -1,545 +0,0 @@
1
- # Stockfish, a UCI chess playing engine derived from Glaurung 2.1
2
- # Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
3
- # Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
4
- # Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
5
- #
6
- # Stockfish is free software: you can redistribute it and/or modify
7
- # it under the terms of the GNU General Public License as published by
8
- # the Free Software Foundation, either version 3 of the License, or
9
- # (at your option) any later version.
10
- #
11
- # Stockfish is distributed in the hope that it will be useful,
12
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- # GNU General Public License for more details.
15
- #
16
- # You should have received a copy of the GNU General Public License
17
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
-
19
-
20
- ### ==========================================================================
21
- ### Section 1. General Configuration
22
- ### ==========================================================================
23
-
24
- ### Establish the operating system name
25
- KERNEL = $(shell uname -s)
26
- ifeq ($(KERNEL),Linux)
27
- OS = $(shell uname -o)
28
- endif
29
-
30
- ### Executable name
31
- EXE = stockfish
32
-
33
- ### Installation dir definitions
34
- PREFIX = /usr/local
35
- BINDIR = $(PREFIX)/bin
36
-
37
- ### Built-in benchmark for pgo-builds
38
- PGOBENCH = ./$(EXE) bench
39
-
40
- ### Object files
41
- OBJS = benchmark.o bitbase.o bitboard.o endgame.o evaluate.o main.o \
42
- material.o misc.o movegen.o movepick.o pawns.o position.o psqt.o \
43
- search.o thread.o timeman.o tt.o uci.o ucioption.o syzygy/tbprobe.o
44
-
45
- ### ==========================================================================
46
- ### Section 2. High-level Configuration
47
- ### ==========================================================================
48
- #
49
- # flag --- Comp switch --- Description
50
- # ----------------------------------------------------------------------------
51
- #
52
- # debug = yes/no --- -DNDEBUG --- Enable/Disable debug mode
53
- # sanitize = yes/no --- (-fsanitize ) --- enable undefined behavior checks
54
- # optimize = yes/no --- (-O3/-fast etc.) --- Enable/Disable optimizations
55
- # arch = (name) --- (-arch) --- Target architecture
56
- # bits = 64/32 --- -DIS_64BIT --- 64-/32-bit operating system
57
- # prefetch = yes/no --- -DUSE_PREFETCH --- Use prefetch asm-instruction
58
- # popcnt = yes/no --- -DUSE_POPCNT --- Use popcnt asm-instruction
59
- # sse = yes/no --- -msse --- Use Intel Streaming SIMD Extensions
60
- # pext = yes/no --- -DUSE_PEXT --- Use pext x86_64 asm-instruction
61
- #
62
- # Note that Makefile is space sensitive, so when adding new architectures
63
- # or modifying existing flags, you have to make sure there are no extra spaces
64
- # at the end of the line for flag values.
65
-
66
- ### 2.1. General and architecture defaults
67
- optimize = yes
68
- debug = no
69
- sanitize = no
70
- bits = 32
71
- prefetch = no
72
- popcnt = no
73
- sse = no
74
- pext = no
75
-
76
- ### 2.2 Architecture specific
77
-
78
- ifeq ($(ARCH),general-32)
79
- arch = any
80
- endif
81
-
82
- ifeq ($(ARCH),x86-32-old)
83
- arch = i386
84
- endif
85
-
86
- ifeq ($(ARCH),x86-32)
87
- arch = i386
88
- prefetch = yes
89
- sse = yes
90
- endif
91
-
92
- ifeq ($(ARCH),general-64)
93
- arch = any
94
- bits = 64
95
- endif
96
-
97
- ifeq ($(ARCH),x86-64)
98
- arch = x86_64
99
- bits = 64
100
- prefetch = yes
101
- sse = yes
102
- endif
103
-
104
- ifeq ($(ARCH),x86-64-modern)
105
- arch = x86_64
106
- bits = 64
107
- prefetch = yes
108
- popcnt = yes
109
- sse = yes
110
- endif
111
-
112
- ifeq ($(ARCH),x86-64-bmi2)
113
- arch = x86_64
114
- bits = 64
115
- prefetch = yes
116
- popcnt = yes
117
- sse = yes
118
- pext = yes
119
- endif
120
-
121
- ifeq ($(ARCH),armv7)
122
- arch = armv7
123
- prefetch = yes
124
- endif
125
-
126
- ifeq ($(ARCH),ppc-32)
127
- arch = ppc
128
- endif
129
-
130
- ifeq ($(ARCH),ppc-64)
131
- arch = ppc64
132
- bits = 64
133
- endif
134
-
135
-
136
- ### ==========================================================================
137
- ### Section 3. Low-level configuration
138
- ### ==========================================================================
139
-
140
- ### 3.1 Selecting compiler (default = gcc)
141
-
142
- CXXFLAGS += -Wall -Wcast-qual -fno-exceptions -fno-rtti -std=c++11 $(EXTRACXXFLAGS)
143
- DEPENDFLAGS += -std=c++11
144
- LDFLAGS += $(EXTRALDFLAGS)
145
-
146
- ifeq ($(COMP),)
147
- COMP=gcc
148
- endif
149
-
150
- ifeq ($(COMP),gcc)
151
- comp=gcc
152
- CXX=g++
153
- CXXFLAGS += -pedantic -Wextra -Wshadow
154
-
155
- ifeq ($(ARCH),armv7)
156
- ifeq ($(OS),Android)
157
- CXXFLAGS += -m$(bits)
158
- endif
159
- else
160
- CXXFLAGS += -m$(bits)
161
- endif
162
-
163
- ifneq ($(KERNEL),Darwin)
164
- LDFLAGS += -Wl,--no-as-needed
165
- endif
166
- endif
167
-
168
- ifeq ($(COMP),mingw)
169
- comp=mingw
170
-
171
- ifeq ($(KERNEL),Linux)
172
- ifeq ($(bits),64)
173
- ifeq ($(shell which x86_64-w64-mingw32-c++-posix),)
174
- CXX=x86_64-w64-mingw32-c++
175
- else
176
- CXX=x86_64-w64-mingw32-c++-posix
177
- endif
178
- else
179
- ifeq ($(shell which i686-w64-mingw32-c++-posix),)
180
- CXX=i686-w64-mingw32-c++
181
- else
182
- CXX=i686-w64-mingw32-c++-posix
183
- endif
184
- endif
185
- else
186
- CXX=g++
187
- endif
188
-
189
- CXXFLAGS += -Wextra -Wshadow
190
- LDFLAGS += -static
191
- endif
192
-
193
- ifeq ($(COMP),icc)
194
- comp=icc
195
- CXX=icpc
196
- CXXFLAGS += -diag-disable 1476,10120 -Wcheck -Wabi -Wdeprecated -strict-ansi
197
- endif
198
-
199
- ifeq ($(COMP),clang)
200
- comp=clang
201
- CXX=clang++
202
- CXXFLAGS += -pedantic -Wextra -Wshadow
203
-
204
- ifeq ($(ARCH),armv7)
205
- ifeq ($(OS),Android)
206
- CXXFLAGS += -m$(bits)
207
- LDFLAGS += -m$(bits)
208
- endif
209
- else
210
- CXXFLAGS += -m$(bits)
211
- LDFLAGS += -m$(bits)
212
- endif
213
-
214
- ifeq ($(KERNEL),Darwin)
215
- CXXFLAGS += -stdlib=libc++
216
- DEPENDFLAGS += -stdlib=libc++
217
- endif
218
- endif
219
-
220
- ifeq ($(comp),icc)
221
- profile_prepare = icc-profile-prepare
222
- profile_make = icc-profile-make
223
- profile_use = icc-profile-use
224
- profile_clean = icc-profile-clean
225
- else
226
- profile_prepare = gcc-profile-prepare
227
- profile_make = gcc-profile-make
228
- profile_use = gcc-profile-use
229
- profile_clean = gcc-profile-clean
230
- endif
231
-
232
- ifeq ($(KERNEL),Darwin)
233
- CXXFLAGS += -arch $(arch) -mmacosx-version-min=10.9
234
- LDFLAGS += -arch $(arch) -mmacosx-version-min=10.9
235
- endif
236
-
237
- ### Travis CI script uses COMPILER to overwrite CXX
238
- ifdef COMPILER
239
- COMPCXX=$(COMPILER)
240
- endif
241
-
242
- ### Allow overwriting CXX from command line
243
- ifdef COMPCXX
244
- CXX=$(COMPCXX)
245
- endif
246
-
247
- ### On mingw use Windows threads, otherwise POSIX
248
- ifneq ($(comp),mingw)
249
- # On Android Bionic's C library comes with its own pthread implementation bundled in
250
- ifneq ($(OS),Android)
251
- # Haiku has pthreads in its libroot, so only link it in on other platforms
252
- ifneq ($(KERNEL),Haiku)
253
- LDFLAGS += -lpthread
254
- endif
255
- endif
256
- endif
257
-
258
- ### 3.2.1 Debugging
259
- ifeq ($(debug),no)
260
- CXXFLAGS += -DNDEBUG
261
- else
262
- CXXFLAGS += -g
263
- endif
264
-
265
- ### 3.2.2 Debugging with undefined behavior sanitizers
266
- ifeq ($(sanitize),yes)
267
- CXXFLAGS += -g3 -fsanitize=undefined
268
- endif
269
-
270
- ### 3.3 Optimization
271
- ifeq ($(optimize),yes)
272
-
273
- CXXFLAGS += -O3
274
-
275
- ifeq ($(comp),gcc)
276
-
277
- ifeq ($(KERNEL),Darwin)
278
- ifeq ($(arch),i386)
279
- CXXFLAGS += -mdynamic-no-pic
280
- endif
281
- ifeq ($(arch),x86_64)
282
- CXXFLAGS += -mdynamic-no-pic
283
- endif
284
- endif
285
-
286
- ifeq ($(OS), Android)
287
- CXXFLAGS += -fno-gcse -mthumb -march=armv7-a -mfloat-abi=softfp
288
- endif
289
- endif
290
-
291
- ifeq ($(comp),icc)
292
- ifeq ($(KERNEL),Darwin)
293
- CXXFLAGS += -mdynamic-no-pic
294
- endif
295
- endif
296
-
297
- ifeq ($(comp),clang)
298
- ifeq ($(KERNEL),Darwin)
299
- ifeq ($(pext),no)
300
- CXXFLAGS += -flto
301
- LDFLAGS += $(CXXFLAGS)
302
- endif
303
- ifeq ($(arch),i386)
304
- CXXFLAGS += -mdynamic-no-pic
305
- endif
306
- ifeq ($(arch),x86_64)
307
- CXXFLAGS += -mdynamic-no-pic
308
- endif
309
- endif
310
- endif
311
- endif
312
-
313
- ### 3.4 Bits
314
- ifeq ($(bits),64)
315
- CXXFLAGS += -DIS_64BIT
316
- endif
317
-
318
- ### 3.5 prefetch
319
- ifeq ($(prefetch),yes)
320
- ifeq ($(sse),yes)
321
- CXXFLAGS += -msse
322
- DEPENDFLAGS += -msse
323
- endif
324
- else
325
- CXXFLAGS += -DNO_PREFETCH
326
- endif
327
-
328
- ### 3.6 popcnt
329
- ifeq ($(popcnt),yes)
330
- ifeq ($(comp),icc)
331
- CXXFLAGS += -msse3 -DUSE_POPCNT
332
- else
333
- CXXFLAGS += -msse3 -mpopcnt -DUSE_POPCNT
334
- endif
335
- endif
336
-
337
- ### 3.7 pext
338
- ifeq ($(pext),yes)
339
- CXXFLAGS += -DUSE_PEXT
340
- ifeq ($(comp),$(filter $(comp),gcc clang mingw))
341
- CXXFLAGS += -mbmi2
342
- endif
343
- endif
344
-
345
- ### 3.8 Link Time Optimization, it works since gcc 4.5 but not on mingw under Windows.
346
- ### This is a mix of compile and link time options because the lto link phase
347
- ### needs access to the optimization flags.
348
- ifeq ($(comp),gcc)
349
- ifeq ($(optimize),yes)
350
- ifeq ($(debug),no)
351
- CXXFLAGS += -flto
352
- LDFLAGS += $(CXXFLAGS)
353
- endif
354
- endif
355
- endif
356
-
357
- ifeq ($(comp),mingw)
358
- ifeq ($(KERNEL),Linux)
359
- ifeq ($(optimize),yes)
360
- ifeq ($(debug),no)
361
- CXXFLAGS += -flto
362
- LDFLAGS += $(CXXFLAGS)
363
- endif
364
- endif
365
- endif
366
- endif
367
-
368
- ### 3.9 Android 5 can only run position independent executables. Note that this
369
- ### breaks Android 4.0 and earlier.
370
- ifeq ($(OS), Android)
371
- CXXFLAGS += -fPIE
372
- LDFLAGS += -fPIE -pie
373
- endif
374
-
375
-
376
- ### ==========================================================================
377
- ### Section 4. Public targets
378
- ### ==========================================================================
379
-
380
- help:
381
- @echo ""
382
- @echo "To compile stockfish, type: "
383
- @echo ""
384
- @echo "make target ARCH=arch [COMP=compiler] [COMPCXX=cxx]"
385
- @echo ""
386
- @echo "Supported targets:"
387
- @echo ""
388
- @echo "build > Standard build"
389
- @echo "profile-build > PGO build"
390
- @echo "strip > Strip executable"
391
- @echo "install > Install executable"
392
- @echo "clean > Clean up"
393
- @echo ""
394
- @echo "Supported archs:"
395
- @echo ""
396
- @echo "x86-64 > x86 64-bit"
397
- @echo "x86-64-modern > x86 64-bit with popcnt support"
398
- @echo "x86-64-bmi2 > x86 64-bit with pext support"
399
- @echo "x86-32 > x86 32-bit with SSE support"
400
- @echo "x86-32-old > x86 32-bit fall back for old hardware"
401
- @echo "ppc-64 > PPC 64-bit"
402
- @echo "ppc-32 > PPC 32-bit"
403
- @echo "armv7 > ARMv7 32-bit"
404
- @echo "general-64 > unspecified 64-bit"
405
- @echo "general-32 > unspecified 32-bit"
406
- @echo ""
407
- @echo "Supported compilers:"
408
- @echo ""
409
- @echo "gcc > Gnu compiler (default)"
410
- @echo "mingw > Gnu compiler with MinGW under Windows"
411
- @echo "clang > LLVM Clang compiler"
412
- @echo "icc > Intel compiler"
413
- @echo ""
414
- @echo "Simple examples. If you don't know what to do, you likely want to run: "
415
- @echo ""
416
- @echo "make build ARCH=x86-64 (This is for 64-bit systems)"
417
- @echo "make build ARCH=x86-32 (This is for 32-bit systems)"
418
- @echo ""
419
- @echo "Advanced examples, for experienced users: "
420
- @echo ""
421
- @echo "make build ARCH=x86-64 COMP=clang"
422
- @echo "make profile-build ARCH=x86-64-modern COMP=gcc COMPCXX=g++-4.8"
423
- @echo ""
424
-
425
-
426
- .PHONY: build profile-build
427
- build:
428
- $(MAKE) ARCH=$(ARCH) COMP=$(COMP) config-sanity
429
- $(MAKE) ARCH=$(ARCH) COMP=$(COMP) all
430
-
431
- profile-build:
432
- $(MAKE) ARCH=$(ARCH) COMP=$(COMP) config-sanity
433
- @echo ""
434
- @echo "Step 0/4. Preparing for profile build."
435
- $(MAKE) ARCH=$(ARCH) COMP=$(COMP) $(profile_prepare)
436
- @echo ""
437
- @echo "Step 1/4. Building executable for benchmark ..."
438
- @touch *.cpp *.h syzygy/*.cpp syzygy/*.h
439
- $(MAKE) ARCH=$(ARCH) COMP=$(COMP) $(profile_make)
440
- @echo ""
441
- @echo "Step 2/4. Running benchmark for pgo-build ..."
442
- $(PGOBENCH) > /dev/null
443
- @echo ""
444
- @echo "Step 3/4. Building final executable ..."
445
- @touch *.cpp *.h syzygy/*.cpp syzygy/*.h
446
- $(MAKE) ARCH=$(ARCH) COMP=$(COMP) $(profile_use)
447
- @echo ""
448
- @echo "Step 4/4. Deleting profile data ..."
449
- $(MAKE) ARCH=$(ARCH) COMP=$(COMP) $(profile_clean)
450
-
451
- strip:
452
- strip $(EXE)
453
-
454
- install:
455
- -mkdir -p -m 755 $(BINDIR)
456
- -cp $(EXE) $(BINDIR)
457
- -strip $(BINDIR)/$(EXE)
458
-
459
- clean:
460
- $(RM) $(EXE) $(EXE).exe *.o .depend *~ core bench.txt *.gcda ./syzygy/*.o ./syzygy/*.gcda
461
-
462
- default:
463
- help
464
-
465
- ### ==========================================================================
466
- ### Section 5. Private targets
467
- ### ==========================================================================
468
-
469
- all: $(EXE) .depend
470
-
471
- config-sanity:
472
- @echo ""
473
- @echo "Config:"
474
- @echo "debug: '$(debug)'"
475
- @echo "optimize: '$(optimize)'"
476
- @echo "arch: '$(arch)'"
477
- @echo "bits: '$(bits)'"
478
- @echo "kernel: '$(KERNEL)'"
479
- @echo "os: '$(OS)'"
480
- @echo "prefetch: '$(prefetch)'"
481
- @echo "popcnt: '$(popcnt)'"
482
- @echo "sse: '$(sse)'"
483
- @echo "pext: '$(pext)'"
484
- @echo ""
485
- @echo "Flags:"
486
- @echo "CXX: $(CXX)"
487
- @echo "CXXFLAGS: $(CXXFLAGS)"
488
- @echo "LDFLAGS: $(LDFLAGS)"
489
- @echo ""
490
- @echo "Testing config sanity. If this fails, try 'make help' ..."
491
- @echo ""
492
- @test "$(debug)" = "yes" || test "$(debug)" = "no"
493
- @test "$(optimize)" = "yes" || test "$(optimize)" = "no"
494
- @test "$(arch)" = "any" || test "$(arch)" = "x86_64" || test "$(arch)" = "i386" || \
495
- test "$(arch)" = "ppc64" || test "$(arch)" = "ppc" || test "$(arch)" = "armv7"
496
- @test "$(bits)" = "32" || test "$(bits)" = "64"
497
- @test "$(prefetch)" = "yes" || test "$(prefetch)" = "no"
498
- @test "$(popcnt)" = "yes" || test "$(popcnt)" = "no"
499
- @test "$(sse)" = "yes" || test "$(sse)" = "no"
500
- @test "$(pext)" = "yes" || test "$(pext)" = "no"
501
- @test "$(comp)" = "gcc" || test "$(comp)" = "icc" || test "$(comp)" = "mingw" || test "$(comp)" = "clang"
502
-
503
- $(EXE): $(OBJS)
504
- $(CXX) -o $@ $(OBJS) $(LDFLAGS)
505
-
506
- gcc-profile-prepare:
507
- $(MAKE) ARCH=$(ARCH) COMP=$(COMP) gcc-profile-clean
508
-
509
- gcc-profile-make:
510
- $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
511
- EXTRACXXFLAGS='-fprofile-generate' \
512
- EXTRALDFLAGS='-lgcov' \
513
- all
514
-
515
- gcc-profile-use:
516
- $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
517
- EXTRACXXFLAGS='-fprofile-use -fno-peel-loops -fno-tracer' \
518
- EXTRALDFLAGS='-lgcov' \
519
- all
520
-
521
- gcc-profile-clean:
522
- @rm -rf *.gcda *.gcno syzygy/*.gcda syzygy/*.gcno bench.txt
523
-
524
- icc-profile-prepare:
525
- $(MAKE) ARCH=$(ARCH) COMP=$(COMP) icc-profile-clean
526
- @mkdir profdir
527
-
528
- icc-profile-make:
529
- $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
530
- EXTRACXXFLAGS='-prof-gen=srcpos -prof_dir ./profdir' \
531
- all
532
-
533
- icc-profile-use:
534
- $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
535
- EXTRACXXFLAGS='-prof_use -prof_dir ./profdir' \
536
- all
537
-
538
- icc-profile-clean:
539
- @rm -rf profdir bench.txt
540
-
541
- .depend:
542
- -@$(CXX) $(DEPENDFLAGS) -MM $(OBJS:.o=.cpp) > $@ 2> /dev/null
543
-
544
- -include .depend
545
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/benchmark.cpp DELETED
@@ -1,183 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #include <fstream>
22
- #include <iostream>
23
- #include <istream>
24
- #include <vector>
25
-
26
- #include "misc.h"
27
- #include "position.h"
28
- #include "search.h"
29
- #include "thread.h"
30
- #include "uci.h"
31
-
32
- using namespace std;
33
-
34
- namespace {
35
-
36
- const vector<string> Defaults = {
37
- "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
38
- "r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 10",
39
- "8/2p5/3p4/KP5r/1R3p1k/8/4P1P1/8 w - - 0 11",
40
- "4rrk1/pp1n3p/3q2pQ/2p1pb2/2PP4/2P3N1/P2B2PP/4RRK1 b - - 7 19",
41
- "rq3rk1/ppp2ppp/1bnpb3/3N2B1/3NP3/7P/PPPQ1PP1/2KR3R w - - 7 14",
42
- "r1bq1r1k/1pp1n1pp/1p1p4/4p2Q/4Pp2/1BNP4/PPP2PPP/3R1RK1 w - - 2 14",
43
- "r3r1k1/2p2ppp/p1p1bn2/8/1q2P3/2NPQN2/PPP3PP/R4RK1 b - - 2 15",
44
- "r1bbk1nr/pp3p1p/2n5/1N4p1/2Np1B2/8/PPP2PPP/2KR1B1R w kq - 0 13",
45
- "r1bq1rk1/ppp1nppp/4n3/3p3Q/3P4/1BP1B3/PP1N2PP/R4RK1 w - - 1 16",
46
- "4r1k1/r1q2ppp/ppp2n2/4P3/5Rb1/1N1BQ3/PPP3PP/R5K1 w - - 1 17",
47
- "2rqkb1r/ppp2p2/2npb1p1/1N1Nn2p/2P1PP2/8/PP2B1PP/R1BQK2R b KQ - 0 11",
48
- "r1bq1r1k/b1p1npp1/p2p3p/1p6/3PP3/1B2NN2/PP3PPP/R2Q1RK1 w - - 1 16",
49
- "3r1rk1/p5pp/bpp1pp2/8/q1PP1P2/b3P3/P2NQRPP/1R2B1K1 b - - 6 22",
50
- "r1q2rk1/2p1bppp/2Pp4/p6b/Q1PNp3/4B3/PP1R1PPP/2K4R w - - 2 18",
51
- "4k2r/1pb2ppp/1p2p3/1R1p4/3P4/2r1PN2/P4PPP/1R4K1 b - - 3 22",
52
- "3q2k1/pb3p1p/4pbp1/2r5/PpN2N2/1P2P2P/5PP1/Q2R2K1 b - - 4 26",
53
- "6k1/6p1/6Pp/ppp5/3pn2P/1P3K2/1PP2P2/3N4 b - - 0 1",
54
- "3b4/5kp1/1p1p1p1p/pP1PpP1P/P1P1P3/3KN3/8/8 w - - 0 1",
55
- "2K5/p7/7P/5pR1/8/5k2/r7/8 w - - 0 1",
56
- "8/6pk/1p6/8/PP3p1p/5P2/4KP1q/3Q4 w - - 0 1",
57
- "7k/3p2pp/4q3/8/4Q3/5Kp1/P6b/8 w - - 0 1",
58
- "8/2p5/8/2kPKp1p/2p4P/2P5/3P4/8 w - - 0 1",
59
- "8/1p3pp1/7p/5P1P/2k3P1/8/2K2P2/8 w - - 0 1",
60
- "8/pp2r1k1/2p1p3/3pP2p/1P1P1P1P/P5KR/8/8 w - - 0 1",
61
- "8/3p4/p1bk3p/Pp6/1Kp1PpPp/2P2P1P/2P5/5B2 b - - 0 1",
62
- "5k2/7R/4P2p/5K2/p1r2P1p/8/8/8 b - - 0 1",
63
- "6k1/6p1/P6p/r1N5/5p2/7P/1b3PP1/4R1K1 w - - 0 1",
64
- "1r3k2/4q3/2Pp3b/3Bp3/2Q2p2/1p1P2P1/1P2KP2/3N4 w - - 0 1",
65
- "6k1/4pp1p/3p2p1/P1pPb3/R7/1r2P1PP/3B1P2/6K1 w - - 0 1",
66
- "8/3p3B/5p2/5P2/p7/PP5b/k7/6K1 w - - 0 1",
67
-
68
- // 5-man positions
69
- "8/8/8/8/5kp1/P7/8/1K1N4 w - - 0 1", // Kc2 - mate
70
- "8/8/8/5N2/8/p7/8/2NK3k w - - 0 1", // Na2 - mate
71
- "8/3k4/8/8/8/4B3/4KB2/2B5 w - - 0 1", // draw
72
-
73
- // 6-man positions
74
- "8/8/1P6/5pr1/8/4R3/7k/2K5 w - - 0 1", // Re5 - mate
75
- "8/2p4P/8/kr6/6R1/8/8/1K6 w - - 0 1", // Ka2 - mate
76
- "8/8/3P3k/8/1p6/8/1P6/1K3n2 b - - 0 1", // Nd2 - draw
77
-
78
- // 7-man positions
79
- "8/R7/2q5/8/6k1/8/1P5p/K6R w - - 0 124", // Draw
80
-
81
- // Mate and stalemate positions
82
- "8/8/8/8/8/6k1/6p1/6K1 w - -",
83
- "5k2/5P2/5K2/8/8/8/8/8 b - -",
84
- "8/8/8/8/8/4k3/4p3/4K3 w - -",
85
- "8/8/8/8/8/5K2/8/3Q1k2 b - -",
86
- "7k/7P/6K1/8/3B4/8/8/8 b - -"
87
- };
88
-
89
- } // namespace
90
-
91
- /// benchmark() runs a simple benchmark by letting Stockfish analyze a set
92
- /// of positions for a given limit each. There are five parameters: the
93
- /// transposition table size, the number of search threads that should
94
- /// be used, the limit value spent for each position (optional, default is
95
- /// depth 13), an optional file name where to look for positions in FEN
96
- /// format (defaults are the positions defined above) and the type of the
97
- /// limit value: depth (default), time in millisecs or number of nodes.
98
-
99
- void benchmark(const Position& current, istream& is) {
100
-
101
- string token;
102
- vector<string> fens;
103
- Search::LimitsType limits;
104
-
105
- // Assign default values to missing arguments
106
- string ttSize = (is >> token) ? token : "16";
107
- string threads = (is >> token) ? token : "1";
108
- string limit = (is >> token) ? token : "13";
109
- string fenFile = (is >> token) ? token : "default";
110
- string limitType = (is >> token) ? token : "depth";
111
-
112
- Options["Hash"] = ttSize;
113
- Options["Threads"] = threads;
114
- Search::clear();
115
-
116
- if (limitType == "time")
117
- limits.movetime = stoi(limit); // movetime is in millisecs
118
-
119
- else if (limitType == "nodes")
120
- limits.nodes = stoi(limit);
121
-
122
- else if (limitType == "mate")
123
- limits.mate = stoi(limit);
124
-
125
- else
126
- limits.depth = stoi(limit);
127
-
128
- if (fenFile == "default")
129
- fens = Defaults;
130
-
131
- else if (fenFile == "current")
132
- fens.push_back(current.fen());
133
-
134
- else
135
- {
136
- string fen;
137
- ifstream file(fenFile);
138
-
139
- if (!file.is_open())
140
- {
141
- cerr << "Unable to open file " << fenFile << endl;
142
- return;
143
- }
144
-
145
- while (getline(file, fen))
146
- if (!fen.empty())
147
- fens.push_back(fen);
148
-
149
- file.close();
150
- }
151
-
152
- uint64_t nodes = 0;
153
- TimePoint elapsed = now();
154
- Position pos;
155
-
156
- for (size_t i = 0; i < fens.size(); ++i)
157
- {
158
- StateListPtr states(new std::deque<StateInfo>(1));
159
- pos.set(fens[i], Options["UCI_Chess960"], &states->back(), Threads.main());
160
-
161
- cerr << "\nPosition: " << i + 1 << '/' << fens.size() << endl;
162
-
163
- if (limitType == "perft")
164
- nodes += Search::perft(pos, limits.depth * ONE_PLY);
165
-
166
- else
167
- {
168
- limits.startTime = now();
169
- Threads.start_thinking(pos, states, limits);
170
- Threads.main()->wait_for_search_finished();
171
- nodes += Threads.nodes_searched();
172
- }
173
- }
174
-
175
- elapsed = now() - elapsed + 1; // Ensure positivity to avoid a 'divide by zero'
176
-
177
- dbg_print(); // Just before exiting
178
-
179
- cerr << "\n==========================="
180
- << "\nTotal time (ms) : " << elapsed
181
- << "\nNodes searched : " << nodes
182
- << "\nNodes/second : " << 1000 * nodes / elapsed << endl;
183
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/bitbase.cpp DELETED
@@ -1,180 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #include <algorithm>
22
- #include <cassert>
23
- #include <numeric>
24
- #include <vector>
25
-
26
- #include "bitboard.h"
27
- #include "types.h"
28
-
29
- namespace {
30
-
31
- // There are 24 possible pawn squares: the first 4 files and ranks from 2 to 7
32
- const unsigned MAX_INDEX = 2*24*64*64; // stm * psq * wksq * bksq = 196608
33
-
34
- // Each uint32_t stores results of 32 positions, one per bit
35
- uint32_t KPKBitbase[MAX_INDEX / 32];
36
-
37
- // A KPK bitbase index is an integer in [0, IndexMax] range
38
- //
39
- // Information is mapped in a way that minimizes the number of iterations:
40
- //
41
- // bit 0- 5: white king square (from SQ_A1 to SQ_H8)
42
- // bit 6-11: black king square (from SQ_A1 to SQ_H8)
43
- // bit 12: side to move (WHITE or BLACK)
44
- // bit 13-14: white pawn file (from FILE_A to FILE_D)
45
- // bit 15-17: white pawn RANK_7 - rank (from RANK_7 - RANK_7 to RANK_7 - RANK_2)
46
- unsigned index(Color us, Square bksq, Square wksq, Square psq) {
47
- return wksq | (bksq << 6) | (us << 12) | (file_of(psq) << 13) | ((RANK_7 - rank_of(psq)) << 15);
48
- }
49
-
50
- enum Result {
51
- INVALID = 0,
52
- UNKNOWN = 1,
53
- DRAW = 2,
54
- WIN = 4
55
- };
56
-
57
- Result& operator|=(Result& r, Result v) { return r = Result(r | v); }
58
-
59
- struct KPKPosition {
60
- KPKPosition() = default;
61
- explicit KPKPosition(unsigned idx);
62
- operator Result() const { return result; }
63
- Result classify(const std::vector<KPKPosition>& db)
64
- { return us == WHITE ? classify<WHITE>(db) : classify<BLACK>(db); }
65
-
66
- template<Color Us> Result classify(const std::vector<KPKPosition>& db);
67
-
68
- Color us;
69
- Square ksq[COLOR_NB], psq;
70
- Result result;
71
- };
72
-
73
- } // namespace
74
-
75
-
76
- bool Bitbases::probe(Square wksq, Square wpsq, Square bksq, Color us) {
77
-
78
- assert(file_of(wpsq) <= FILE_D);
79
-
80
- unsigned idx = index(us, bksq, wksq, wpsq);
81
- return KPKBitbase[idx / 32] & (1 << (idx & 0x1F));
82
- }
83
-
84
-
85
- void Bitbases::init() {
86
-
87
- std::vector<KPKPosition> db(MAX_INDEX);
88
- unsigned idx, repeat = 1;
89
-
90
- // Initialize db with known win / draw positions
91
- for (idx = 0; idx < MAX_INDEX; ++idx)
92
- db[idx] = KPKPosition(idx);
93
-
94
- // Iterate through the positions until none of the unknown positions can be
95
- // changed to either wins or draws (15 cycles needed).
96
- while (repeat)
97
- for (repeat = idx = 0; idx < MAX_INDEX; ++idx)
98
- repeat |= (db[idx] == UNKNOWN && db[idx].classify(db) != UNKNOWN);
99
-
100
- // Map 32 results into one KPKBitbase[] entry
101
- for (idx = 0; idx < MAX_INDEX; ++idx)
102
- if (db[idx] == WIN)
103
- KPKBitbase[idx / 32] |= 1 << (idx & 0x1F);
104
- }
105
-
106
-
107
- namespace {
108
-
109
- KPKPosition::KPKPosition(unsigned idx) {
110
-
111
- ksq[WHITE] = Square((idx >> 0) & 0x3F);
112
- ksq[BLACK] = Square((idx >> 6) & 0x3F);
113
- us = Color ((idx >> 12) & 0x01);
114
- psq = make_square(File((idx >> 13) & 0x3), RANK_7 - Rank((idx >> 15) & 0x7));
115
-
116
- // Check if two pieces are on the same square or if a king can be captured
117
- if ( distance(ksq[WHITE], ksq[BLACK]) <= 1
118
- || ksq[WHITE] == psq
119
- || ksq[BLACK] == psq
120
- || (us == WHITE && (StepAttacksBB[PAWN][psq] & ksq[BLACK])))
121
- result = INVALID;
122
-
123
- // Immediate win if a pawn can be promoted without getting captured
124
- else if ( us == WHITE
125
- && rank_of(psq) == RANK_7
126
- && ksq[us] != psq + NORTH
127
- && ( distance(ksq[~us], psq + NORTH) > 1
128
- || (StepAttacksBB[KING][ksq[us]] & (psq + NORTH))))
129
- result = WIN;
130
-
131
- // Immediate draw if it is a stalemate or a king captures undefended pawn
132
- else if ( us == BLACK
133
- && ( !(StepAttacksBB[KING][ksq[us]] & ~(StepAttacksBB[KING][ksq[~us]] | StepAttacksBB[PAWN][psq]))
134
- || (StepAttacksBB[KING][ksq[us]] & psq & ~StepAttacksBB[KING][ksq[~us]])))
135
- result = DRAW;
136
-
137
- // Position will be classified later
138
- else
139
- result = UNKNOWN;
140
- }
141
-
142
- template<Color Us>
143
- Result KPKPosition::classify(const std::vector<KPKPosition>& db) {
144
-
145
- // White to move: If one move leads to a position classified as WIN, the result
146
- // of the current position is WIN. If all moves lead to positions classified
147
- // as DRAW, the current position is classified as DRAW, otherwise the current
148
- // position is classified as UNKNOWN.
149
- //
150
- // Black to move: If one move leads to a position classified as DRAW, the result
151
- // of the current position is DRAW. If all moves lead to positions classified
152
- // as WIN, the position is classified as WIN, otherwise the current position is
153
- // classified as UNKNOWN.
154
-
155
- const Color Them = (Us == WHITE ? BLACK : WHITE);
156
- const Result Good = (Us == WHITE ? WIN : DRAW);
157
- const Result Bad = (Us == WHITE ? DRAW : WIN);
158
-
159
- Result r = INVALID;
160
- Bitboard b = StepAttacksBB[KING][ksq[Us]];
161
-
162
- while (b)
163
- r |= Us == WHITE ? db[index(Them, ksq[Them] , pop_lsb(&b), psq)]
164
- : db[index(Them, pop_lsb(&b), ksq[Them] , psq)];
165
-
166
- if (Us == WHITE)
167
- {
168
- if (rank_of(psq) < RANK_7) // Single push
169
- r |= db[index(Them, ksq[Them], ksq[Us], psq + NORTH)];
170
-
171
- if ( rank_of(psq) == RANK_2 // Double push
172
- && psq + NORTH != ksq[Us]
173
- && psq + NORTH != ksq[Them])
174
- r |= db[index(Them, ksq[Them], ksq[Us], psq + NORTH + NORTH)];
175
- }
176
-
177
- return result = r & Good ? Good : r & UNKNOWN ? UNKNOWN : Bad;
178
- }
179
-
180
- } // namespace
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/bitboard.cpp DELETED
@@ -1,333 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #include <algorithm>
22
-
23
- #include "bitboard.h"
24
- #include "misc.h"
25
-
26
- uint8_t PopCnt16[1 << 16];
27
- int SquareDistance[SQUARE_NB][SQUARE_NB];
28
-
29
- Bitboard RookMasks [SQUARE_NB];
30
- Bitboard RookMagics [SQUARE_NB];
31
- Bitboard* RookAttacks[SQUARE_NB];
32
- unsigned RookShifts [SQUARE_NB];
33
-
34
- Bitboard BishopMasks [SQUARE_NB];
35
- Bitboard BishopMagics [SQUARE_NB];
36
- Bitboard* BishopAttacks[SQUARE_NB];
37
- unsigned BishopShifts [SQUARE_NB];
38
-
39
- Bitboard SquareBB[SQUARE_NB];
40
- Bitboard FileBB[FILE_NB];
41
- Bitboard RankBB[RANK_NB];
42
- Bitboard AdjacentFilesBB[FILE_NB];
43
- Bitboard InFrontBB[COLOR_NB][RANK_NB];
44
- Bitboard StepAttacksBB[PIECE_NB][SQUARE_NB];
45
- Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
46
- Bitboard LineBB[SQUARE_NB][SQUARE_NB];
47
- Bitboard DistanceRingBB[SQUARE_NB][8];
48
- Bitboard ForwardBB[COLOR_NB][SQUARE_NB];
49
- Bitboard PassedPawnMask[COLOR_NB][SQUARE_NB];
50
- Bitboard PawnAttackSpan[COLOR_NB][SQUARE_NB];
51
- Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB];
52
-
53
- namespace {
54
-
55
- // De Bruijn sequences. See chessprogramming.wikispaces.com/BitScan
56
- const uint64_t DeBruijn64 = 0x3F79D71B4CB0A89ULL;
57
- const uint32_t DeBruijn32 = 0x783A9B23;
58
-
59
- int MSBTable[256]; // To implement software msb()
60
- Square BSFTable[SQUARE_NB]; // To implement software bitscan
61
- Bitboard RookTable[0x19000]; // To store rook attacks
62
- Bitboard BishopTable[0x1480]; // To store bishop attacks
63
-
64
- typedef unsigned (Fn)(Square, Bitboard);
65
-
66
- void init_magics(Bitboard table[], Bitboard* attacks[], Bitboard magics[],
67
- Bitboard masks[], unsigned shifts[], Square deltas[], Fn index);
68
-
69
- // bsf_index() returns the index into BSFTable[] to look up the bitscan. Uses
70
- // Matt Taylor's folding for 32 bit case, extended to 64 bit by Kim Walisch.
71
-
72
- unsigned bsf_index(Bitboard b) {
73
- b ^= b - 1;
74
- return Is64Bit ? (b * DeBruijn64) >> 58
75
- : ((unsigned(b) ^ unsigned(b >> 32)) * DeBruijn32) >> 26;
76
- }
77
-
78
-
79
- // popcount16() counts the non-zero bits using SWAR-Popcount algorithm
80
-
81
- unsigned popcount16(unsigned u) {
82
- u -= (u >> 1) & 0x5555U;
83
- u = ((u >> 2) & 0x3333U) + (u & 0x3333U);
84
- u = ((u >> 4) + u) & 0x0F0FU;
85
- return (u * 0x0101U) >> 8;
86
- }
87
- }
88
-
89
- #ifdef NO_BSF
90
-
91
- /// Software fall-back of lsb() and msb() for CPU lacking hardware support
92
-
93
- Square lsb(Bitboard b) {
94
- assert(b);
95
- return BSFTable[bsf_index(b)];
96
- }
97
-
98
- Square msb(Bitboard b) {
99
-
100
- assert(b);
101
- unsigned b32;
102
- int result = 0;
103
-
104
- if (b > 0xFFFFFFFF)
105
- {
106
- b >>= 32;
107
- result = 32;
108
- }
109
-
110
- b32 = unsigned(b);
111
-
112
- if (b32 > 0xFFFF)
113
- {
114
- b32 >>= 16;
115
- result += 16;
116
- }
117
-
118
- if (b32 > 0xFF)
119
- {
120
- b32 >>= 8;
121
- result += 8;
122
- }
123
-
124
- return Square(result + MSBTable[b32]);
125
- }
126
-
127
- #endif // ifdef NO_BSF
128
-
129
-
130
- /// Bitboards::pretty() returns an ASCII representation of a bitboard suitable
131
- /// to be printed to standard output. Useful for debugging.
132
-
133
- const std::string Bitboards::pretty(Bitboard b) {
134
-
135
- std::string s = "+---+---+---+---+---+---+---+---+\n";
136
-
137
- for (Rank r = RANK_8; r >= RANK_1; --r)
138
- {
139
- for (File f = FILE_A; f <= FILE_H; ++f)
140
- s += b & make_square(f, r) ? "| X " : "| ";
141
-
142
- s += "|\n+---+---+---+---+---+---+---+---+\n";
143
- }
144
-
145
- return s;
146
- }
147
-
148
-
149
- /// Bitboards::init() initializes various bitboard tables. It is called at
150
- /// startup and relies on global objects to be already zero-initialized.
151
-
152
- void Bitboards::init() {
153
-
154
- for (unsigned i = 0; i < (1 << 16); ++i)
155
- PopCnt16[i] = (uint8_t) popcount16(i);
156
-
157
- for (Square s = SQ_A1; s <= SQ_H8; ++s)
158
- {
159
- SquareBB[s] = 1ULL << s;
160
- BSFTable[bsf_index(SquareBB[s])] = s;
161
- }
162
-
163
- for (Bitboard b = 2; b < 256; ++b)
164
- MSBTable[b] = MSBTable[b - 1] + !more_than_one(b);
165
-
166
- for (File f = FILE_A; f <= FILE_H; ++f)
167
- FileBB[f] = f > FILE_A ? FileBB[f - 1] << 1 : FileABB;
168
-
169
- for (Rank r = RANK_1; r <= RANK_8; ++r)
170
- RankBB[r] = r > RANK_1 ? RankBB[r - 1] << 8 : Rank1BB;
171
-
172
- for (File f = FILE_A; f <= FILE_H; ++f)
173
- AdjacentFilesBB[f] = (f > FILE_A ? FileBB[f - 1] : 0) | (f < FILE_H ? FileBB[f + 1] : 0);
174
-
175
- for (Rank r = RANK_1; r < RANK_8; ++r)
176
- InFrontBB[WHITE][r] = ~(InFrontBB[BLACK][r + 1] = InFrontBB[BLACK][r] | RankBB[r]);
177
-
178
- for (Color c = WHITE; c <= BLACK; ++c)
179
- for (Square s = SQ_A1; s <= SQ_H8; ++s)
180
- {
181
- ForwardBB[c][s] = InFrontBB[c][rank_of(s)] & FileBB[file_of(s)];
182
- PawnAttackSpan[c][s] = InFrontBB[c][rank_of(s)] & AdjacentFilesBB[file_of(s)];
183
- PassedPawnMask[c][s] = ForwardBB[c][s] | PawnAttackSpan[c][s];
184
- }
185
-
186
- for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
187
- for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2)
188
- if (s1 != s2)
189
- {
190
- SquareDistance[s1][s2] = std::max(distance<File>(s1, s2), distance<Rank>(s1, s2));
191
- DistanceRingBB[s1][SquareDistance[s1][s2] - 1] |= s2;
192
- }
193
-
194
- int steps[][9] = { {}, { 7, 9 }, { 17, 15, 10, 6, -6, -10, -15, -17 },
195
- {}, {}, {}, { 9, 7, -7, -9, 8, 1, -1, -8 } };
196
-
197
- for (Color c = WHITE; c <= BLACK; ++c)
198
- for (PieceType pt = PAWN; pt <= KING; ++pt)
199
- for (Square s = SQ_A1; s <= SQ_H8; ++s)
200
- for (int i = 0; steps[pt][i]; ++i)
201
- {
202
- Square to = s + Square(c == WHITE ? steps[pt][i] : -steps[pt][i]);
203
-
204
- if (is_ok(to) && distance(s, to) < 3)
205
- StepAttacksBB[make_piece(c, pt)][s] |= to;
206
- }
207
-
208
- Square RookDeltas[] = { NORTH, EAST, SOUTH, WEST };
209
- Square BishopDeltas[] = { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST };
210
-
211
- init_magics(RookTable, RookAttacks, RookMagics, RookMasks, RookShifts, RookDeltas, magic_index<ROOK>);
212
- init_magics(BishopTable, BishopAttacks, BishopMagics, BishopMasks, BishopShifts, BishopDeltas, magic_index<BISHOP>);
213
-
214
- for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
215
- {
216
- PseudoAttacks[QUEEN][s1] = PseudoAttacks[BISHOP][s1] = attacks_bb<BISHOP>(s1, 0);
217
- PseudoAttacks[QUEEN][s1] |= PseudoAttacks[ ROOK][s1] = attacks_bb< ROOK>(s1, 0);
218
-
219
- for (Piece pc = W_BISHOP; pc <= W_ROOK; ++pc)
220
- for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2)
221
- {
222
- if (!(PseudoAttacks[pc][s1] & s2))
223
- continue;
224
-
225
- LineBB[s1][s2] = (attacks_bb(pc, s1, 0) & attacks_bb(pc, s2, 0)) | s1 | s2;
226
- BetweenBB[s1][s2] = attacks_bb(pc, s1, SquareBB[s2]) & attacks_bb(pc, s2, SquareBB[s1]);
227
- }
228
- }
229
- }
230
-
231
-
232
- namespace {
233
-
234
- Bitboard sliding_attack(Square deltas[], Square sq, Bitboard occupied) {
235
-
236
- Bitboard attack = 0;
237
-
238
- for (int i = 0; i < 4; ++i)
239
- for (Square s = sq + deltas[i];
240
- is_ok(s) && distance(s, s - deltas[i]) == 1;
241
- s += deltas[i])
242
- {
243
- attack |= s;
244
-
245
- if (occupied & s)
246
- break;
247
- }
248
-
249
- return attack;
250
- }
251
-
252
-
253
- // init_magics() computes all rook and bishop attacks at startup. Magic
254
- // bitboards are used to look up attacks of sliding pieces. As a reference see
255
- // chessprogramming.wikispaces.com/Magic+Bitboards. In particular, here we
256
- // use the so called "fancy" approach.
257
-
258
- void init_magics(Bitboard table[], Bitboard* attacks[], Bitboard magics[],
259
- Bitboard masks[], unsigned shifts[], Square deltas[], Fn index) {
260
-
261
- int seeds[][RANK_NB] = { { 8977, 44560, 54343, 38998, 5731, 95205, 104912, 17020 },
262
- { 728, 10316, 55013, 32803, 12281, 15100, 16645, 255 } };
263
-
264
- Bitboard occupancy[4096], reference[4096], edges, b;
265
- int age[4096] = {0}, current = 0, i, size;
266
-
267
- // attacks[s] is a pointer to the beginning of the attacks table for square 's'
268
- attacks[SQ_A1] = table;
269
-
270
- for (Square s = SQ_A1; s <= SQ_H8; ++s)
271
- {
272
- // Board edges are not considered in the relevant occupancies
273
- edges = ((Rank1BB | Rank8BB) & ~rank_bb(s)) | ((FileABB | FileHBB) & ~file_bb(s));
274
-
275
- // Given a square 's', the mask is the bitboard of sliding attacks from
276
- // 's' computed on an empty board. The index must be big enough to contain
277
- // all the attacks for each possible subset of the mask and so is 2 power
278
- // the number of 1s of the mask. Hence we deduce the size of the shift to
279
- // apply to the 64 or 32 bits word to get the index.
280
- masks[s] = sliding_attack(deltas, s, 0) & ~edges;
281
- shifts[s] = (Is64Bit ? 64 : 32) - popcount(masks[s]);
282
-
283
- // Use Carry-Rippler trick to enumerate all subsets of masks[s] and
284
- // store the corresponding sliding attack bitboard in reference[].
285
- b = size = 0;
286
- do {
287
- occupancy[size] = b;
288
- reference[size] = sliding_attack(deltas, s, b);
289
-
290
- if (HasPext)
291
- attacks[s][pext(b, masks[s])] = reference[size];
292
-
293
- size++;
294
- b = (b - masks[s]) & masks[s];
295
- } while (b);
296
-
297
- // Set the offset for the table of the next square. We have individual
298
- // table sizes for each square with "Fancy Magic Bitboards".
299
- if (s < SQ_H8)
300
- attacks[s + 1] = attacks[s] + size;
301
-
302
- if (HasPext)
303
- continue;
304
-
305
- PRNG rng(seeds[Is64Bit][rank_of(s)]);
306
-
307
- // Find a magic for square 's' picking up an (almost) random number
308
- // until we find the one that passes the verification test.
309
- do {
310
- do
311
- magics[s] = rng.sparse_rand<Bitboard>();
312
- while (popcount((magics[s] * masks[s]) >> 56) < 6);
313
-
314
- // A good magic must map every possible occupancy to an index that
315
- // looks up the correct sliding attack in the attacks[s] database.
316
- // Note that we build up the database for square 's' as a side
317
- // effect of verifying the magic.
318
- for (++current, i = 0; i < size; ++i)
319
- {
320
- unsigned idx = index(s, occupancy[i]);
321
-
322
- if (age[idx] < current)
323
- {
324
- age[idx] = current;
325
- attacks[s][idx] = reference[i];
326
- }
327
- else if (attacks[s][idx] != reference[i])
328
- break;
329
- }
330
- } while (i < size);
331
- }
332
- }
333
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/bitboard.h DELETED
@@ -1,338 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #ifndef BITBOARD_H_INCLUDED
22
- #define BITBOARD_H_INCLUDED
23
-
24
- #include <string>
25
-
26
- #include "types.h"
27
-
28
- namespace Bitbases {
29
-
30
- void init();
31
- bool probe(Square wksq, Square wpsq, Square bksq, Color us);
32
-
33
- }
34
-
35
- namespace Bitboards {
36
-
37
- void init();
38
- const std::string pretty(Bitboard b);
39
-
40
- }
41
-
42
- const Bitboard DarkSquares = 0xAA55AA55AA55AA55ULL;
43
-
44
- const Bitboard FileABB = 0x0101010101010101ULL;
45
- const Bitboard FileBBB = FileABB << 1;
46
- const Bitboard FileCBB = FileABB << 2;
47
- const Bitboard FileDBB = FileABB << 3;
48
- const Bitboard FileEBB = FileABB << 4;
49
- const Bitboard FileFBB = FileABB << 5;
50
- const Bitboard FileGBB = FileABB << 6;
51
- const Bitboard FileHBB = FileABB << 7;
52
-
53
- const Bitboard Rank1BB = 0xFF;
54
- const Bitboard Rank2BB = Rank1BB << (8 * 1);
55
- const Bitboard Rank3BB = Rank1BB << (8 * 2);
56
- const Bitboard Rank4BB = Rank1BB << (8 * 3);
57
- const Bitboard Rank5BB = Rank1BB << (8 * 4);
58
- const Bitboard Rank6BB = Rank1BB << (8 * 5);
59
- const Bitboard Rank7BB = Rank1BB << (8 * 6);
60
- const Bitboard Rank8BB = Rank1BB << (8 * 7);
61
-
62
- extern int SquareDistance[SQUARE_NB][SQUARE_NB];
63
-
64
- extern Bitboard SquareBB[SQUARE_NB];
65
- extern Bitboard FileBB[FILE_NB];
66
- extern Bitboard RankBB[RANK_NB];
67
- extern Bitboard AdjacentFilesBB[FILE_NB];
68
- extern Bitboard InFrontBB[COLOR_NB][RANK_NB];
69
- extern Bitboard StepAttacksBB[PIECE_NB][SQUARE_NB];
70
- extern Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
71
- extern Bitboard LineBB[SQUARE_NB][SQUARE_NB];
72
- extern Bitboard DistanceRingBB[SQUARE_NB][8];
73
- extern Bitboard ForwardBB[COLOR_NB][SQUARE_NB];
74
- extern Bitboard PassedPawnMask[COLOR_NB][SQUARE_NB];
75
- extern Bitboard PawnAttackSpan[COLOR_NB][SQUARE_NB];
76
- extern Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB];
77
-
78
-
79
- /// Overloads of bitwise operators between a Bitboard and a Square for testing
80
- /// whether a given bit is set in a bitboard, and for setting and clearing bits.
81
-
82
- inline Bitboard operator&(Bitboard b, Square s) {
83
- return b & SquareBB[s];
84
- }
85
-
86
- inline Bitboard operator|(Bitboard b, Square s) {
87
- return b | SquareBB[s];
88
- }
89
-
90
- inline Bitboard operator^(Bitboard b, Square s) {
91
- return b ^ SquareBB[s];
92
- }
93
-
94
- inline Bitboard& operator|=(Bitboard& b, Square s) {
95
- return b |= SquareBB[s];
96
- }
97
-
98
- inline Bitboard& operator^=(Bitboard& b, Square s) {
99
- return b ^= SquareBB[s];
100
- }
101
-
102
- inline bool more_than_one(Bitboard b) {
103
- return b & (b - 1);
104
- }
105
-
106
-
107
- /// rank_bb() and file_bb() return a bitboard representing all the squares on
108
- /// the given file or rank.
109
-
110
- inline Bitboard rank_bb(Rank r) {
111
- return RankBB[r];
112
- }
113
-
114
- inline Bitboard rank_bb(Square s) {
115
- return RankBB[rank_of(s)];
116
- }
117
-
118
- inline Bitboard file_bb(File f) {
119
- return FileBB[f];
120
- }
121
-
122
- inline Bitboard file_bb(Square s) {
123
- return FileBB[file_of(s)];
124
- }
125
-
126
-
127
- /// shift() moves a bitboard one step along direction D. Mainly for pawns
128
-
129
- template<Square D>
130
- inline Bitboard shift(Bitboard b) {
131
- return D == NORTH ? b << 8 : D == SOUTH ? b >> 8
132
- : D == NORTH_EAST ? (b & ~FileHBB) << 9 : D == SOUTH_EAST ? (b & ~FileHBB) >> 7
133
- : D == NORTH_WEST ? (b & ~FileABB) << 7 : D == SOUTH_WEST ? (b & ~FileABB) >> 9
134
- : 0;
135
- }
136
-
137
-
138
- /// adjacent_files_bb() returns a bitboard representing all the squares on the
139
- /// adjacent files of the given one.
140
-
141
- inline Bitboard adjacent_files_bb(File f) {
142
- return AdjacentFilesBB[f];
143
- }
144
-
145
-
146
- /// between_bb() returns a bitboard representing all the squares between the two
147
- /// given ones. For instance, between_bb(SQ_C4, SQ_F7) returns a bitboard with
148
- /// the bits for square d5 and e6 set. If s1 and s2 are not on the same rank, file
149
- /// or diagonal, 0 is returned.
150
-
151
- inline Bitboard between_bb(Square s1, Square s2) {
152
- return BetweenBB[s1][s2];
153
- }
154
-
155
-
156
- /// in_front_bb() returns a bitboard representing all the squares on all the ranks
157
- /// in front of the given one, from the point of view of the given color. For
158
- /// instance, in_front_bb(BLACK, RANK_3) will return the squares on ranks 1 and 2.
159
-
160
- inline Bitboard in_front_bb(Color c, Rank r) {
161
- return InFrontBB[c][r];
162
- }
163
-
164
-
165
- /// forward_bb() returns a bitboard representing all the squares along the line
166
- /// in front of the given one, from the point of view of the given color:
167
- /// ForwardBB[c][s] = in_front_bb(c, s) & file_bb(s)
168
-
169
- inline Bitboard forward_bb(Color c, Square s) {
170
- return ForwardBB[c][s];
171
- }
172
-
173
-
174
- /// pawn_attack_span() returns a bitboard representing all the squares that can be
175
- /// attacked by a pawn of the given color when it moves along its file, starting
176
- /// from the given square:
177
- /// PawnAttackSpan[c][s] = in_front_bb(c, s) & adjacent_files_bb(s);
178
-
179
- inline Bitboard pawn_attack_span(Color c, Square s) {
180
- return PawnAttackSpan[c][s];
181
- }
182
-
183
-
184
- /// passed_pawn_mask() returns a bitboard mask which can be used to test if a
185
- /// pawn of the given color and on the given square is a passed pawn:
186
- /// PassedPawnMask[c][s] = pawn_attack_span(c, s) | forward_bb(c, s)
187
-
188
- inline Bitboard passed_pawn_mask(Color c, Square s) {
189
- return PassedPawnMask[c][s];
190
- }
191
-
192
-
193
- /// aligned() returns true if the squares s1, s2 and s3 are aligned either on a
194
- /// straight or on a diagonal line.
195
-
196
- inline bool aligned(Square s1, Square s2, Square s3) {
197
- return LineBB[s1][s2] & s3;
198
- }
199
-
200
-
201
- /// distance() functions return the distance between x and y, defined as the
202
- /// number of steps for a king in x to reach y. Works with squares, ranks, files.
203
-
204
- template<typename T> inline int distance(T x, T y) { return x < y ? y - x : x - y; }
205
- template<> inline int distance<Square>(Square x, Square y) { return SquareDistance[x][y]; }
206
-
207
- template<typename T1, typename T2> inline int distance(T2 x, T2 y);
208
- template<> inline int distance<File>(Square x, Square y) { return distance(file_of(x), file_of(y)); }
209
- template<> inline int distance<Rank>(Square x, Square y) { return distance(rank_of(x), rank_of(y)); }
210
-
211
-
212
- /// attacks_bb() returns a bitboard representing all the squares attacked by a
213
- /// piece of type Pt (bishop or rook) placed on 's'. The helper magic_index()
214
- /// looks up the index using the 'magic bitboards' approach.
215
- template<PieceType Pt>
216
- inline unsigned magic_index(Square s, Bitboard occupied) {
217
-
218
- extern Bitboard RookMasks[SQUARE_NB];
219
- extern Bitboard RookMagics[SQUARE_NB];
220
- extern unsigned RookShifts[SQUARE_NB];
221
- extern Bitboard BishopMasks[SQUARE_NB];
222
- extern Bitboard BishopMagics[SQUARE_NB];
223
- extern unsigned BishopShifts[SQUARE_NB];
224
-
225
- Bitboard* const Masks = Pt == ROOK ? RookMasks : BishopMasks;
226
- Bitboard* const Magics = Pt == ROOK ? RookMagics : BishopMagics;
227
- unsigned* const Shifts = Pt == ROOK ? RookShifts : BishopShifts;
228
-
229
- if (HasPext)
230
- return unsigned(pext(occupied, Masks[s]));
231
-
232
- if (Is64Bit)
233
- return unsigned(((occupied & Masks[s]) * Magics[s]) >> Shifts[s]);
234
-
235
- unsigned lo = unsigned(occupied) & unsigned(Masks[s]);
236
- unsigned hi = unsigned(occupied >> 32) & unsigned(Masks[s] >> 32);
237
- return (lo * unsigned(Magics[s]) ^ hi * unsigned(Magics[s] >> 32)) >> Shifts[s];
238
- }
239
-
240
- template<PieceType Pt>
241
- inline Bitboard attacks_bb(Square s, Bitboard occupied) {
242
-
243
- extern Bitboard* RookAttacks[SQUARE_NB];
244
- extern Bitboard* BishopAttacks[SQUARE_NB];
245
-
246
- return (Pt == ROOK ? RookAttacks : BishopAttacks)[s][magic_index<Pt>(s, occupied)];
247
- }
248
-
249
- inline Bitboard attacks_bb(Piece pc, Square s, Bitboard occupied) {
250
-
251
- switch (type_of(pc))
252
- {
253
- case BISHOP: return attacks_bb<BISHOP>(s, occupied);
254
- case ROOK : return attacks_bb<ROOK>(s, occupied);
255
- case QUEEN : return attacks_bb<BISHOP>(s, occupied) | attacks_bb<ROOK>(s, occupied);
256
- default : return StepAttacksBB[pc][s];
257
- }
258
- }
259
-
260
-
261
- /// popcount() counts the number of non-zero bits in a bitboard
262
-
263
- inline int popcount(Bitboard b) {
264
-
265
- #ifndef USE_POPCNT
266
-
267
- extern uint8_t PopCnt16[1 << 16];
268
- union { Bitboard bb; uint16_t u[4]; } v = { b };
269
- return PopCnt16[v.u[0]] + PopCnt16[v.u[1]] + PopCnt16[v.u[2]] + PopCnt16[v.u[3]];
270
-
271
- #elif defined(_MSC_VER) || defined(__INTEL_COMPILER)
272
-
273
- return (int)_mm_popcnt_u64(b);
274
-
275
- #else // Assumed gcc or compatible compiler
276
-
277
- return __builtin_popcountll(b);
278
-
279
- #endif
280
- }
281
-
282
-
283
- /// lsb() and msb() return the least/most significant bit in a non-zero bitboard
284
-
285
- #if defined(__GNUC__)
286
-
287
- inline Square lsb(Bitboard b) {
288
- assert(b);
289
- return Square(__builtin_ctzll(b));
290
- }
291
-
292
- inline Square msb(Bitboard b) {
293
- assert(b);
294
- return Square(63 - __builtin_clzll(b));
295
- }
296
-
297
- #elif defined(_WIN64) && defined(_MSC_VER)
298
-
299
- inline Square lsb(Bitboard b) {
300
- assert(b);
301
- unsigned long idx;
302
- _BitScanForward64(&idx, b);
303
- return (Square) idx;
304
- }
305
-
306
- inline Square msb(Bitboard b) {
307
- assert(b);
308
- unsigned long idx;
309
- _BitScanReverse64(&idx, b);
310
- return (Square) idx;
311
- }
312
-
313
- #else
314
-
315
- #define NO_BSF // Fallback on software implementation for other cases
316
-
317
- Square lsb(Bitboard b);
318
- Square msb(Bitboard b);
319
-
320
- #endif
321
-
322
-
323
- /// pop_lsb() finds and clears the least significant bit in a non-zero bitboard
324
-
325
- inline Square pop_lsb(Bitboard* b) {
326
- const Square s = lsb(*b);
327
- *b &= *b - 1;
328
- return s;
329
- }
330
-
331
-
332
- /// frontmost_sq() and backmost_sq() return the square corresponding to the
333
- /// most/least advanced bit relative to the given color.
334
-
335
- inline Square frontmost_sq(Color c, Bitboard b) { return c == WHITE ? msb(b) : lsb(b); }
336
- inline Square backmost_sq(Color c, Bitboard b) { return c == WHITE ? lsb(b) : msb(b); }
337
-
338
- #endif // #ifndef BITBOARD_H_INCLUDED
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/endgame.cpp DELETED
@@ -1,845 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #include <algorithm>
22
- #include <cassert>
23
-
24
- #include "bitboard.h"
25
- #include "endgame.h"
26
- #include "movegen.h"
27
-
28
- using std::string;
29
-
30
- namespace {
31
-
32
- // Table used to drive the king towards the edge of the board
33
- // in KX vs K and KQ vs KR endgames.
34
- const int PushToEdges[SQUARE_NB] = {
35
- 100, 90, 80, 70, 70, 80, 90, 100,
36
- 90, 70, 60, 50, 50, 60, 70, 90,
37
- 80, 60, 40, 30, 30, 40, 60, 80,
38
- 70, 50, 30, 20, 20, 30, 50, 70,
39
- 70, 50, 30, 20, 20, 30, 50, 70,
40
- 80, 60, 40, 30, 30, 40, 60, 80,
41
- 90, 70, 60, 50, 50, 60, 70, 90,
42
- 100, 90, 80, 70, 70, 80, 90, 100
43
- };
44
-
45
- // Table used to drive the king towards a corner square of the
46
- // right color in KBN vs K endgames.
47
- const int PushToCorners[SQUARE_NB] = {
48
- 200, 190, 180, 170, 160, 150, 140, 130,
49
- 190, 180, 170, 160, 150, 140, 130, 140,
50
- 180, 170, 155, 140, 140, 125, 140, 150,
51
- 170, 160, 140, 120, 110, 140, 150, 160,
52
- 160, 150, 140, 110, 120, 140, 160, 170,
53
- 150, 140, 125, 140, 140, 155, 170, 180,
54
- 140, 130, 140, 150, 160, 170, 180, 190,
55
- 130, 140, 150, 160, 170, 180, 190, 200
56
- };
57
-
58
- // Tables used to drive a piece towards or away from another piece
59
- const int PushClose[8] = { 0, 0, 100, 80, 60, 40, 20, 10 };
60
- const int PushAway [8] = { 0, 5, 20, 40, 60, 80, 90, 100 };
61
-
62
- // Pawn Rank based scaling factors used in KRPPKRP endgame
63
- const int KRPPKRPScaleFactors[RANK_NB] = { 0, 9, 10, 14, 21, 44, 0, 0 };
64
-
65
- #ifndef NDEBUG
66
- bool verify_material(const Position& pos, Color c, Value npm, int pawnsCnt) {
67
- return pos.non_pawn_material(c) == npm && pos.count<PAWN>(c) == pawnsCnt;
68
- }
69
- #endif
70
-
71
- // Map the square as if strongSide is white and strongSide's only pawn
72
- // is on the left half of the board.
73
- Square normalize(const Position& pos, Color strongSide, Square sq) {
74
-
75
- assert(pos.count<PAWN>(strongSide) == 1);
76
-
77
- if (file_of(pos.square<PAWN>(strongSide)) >= FILE_E)
78
- sq = Square(sq ^ 7); // Mirror SQ_H1 -> SQ_A1
79
-
80
- if (strongSide == BLACK)
81
- sq = ~sq;
82
-
83
- return sq;
84
- }
85
-
86
- // Get the material key of Position out of the given endgame key code
87
- // like "KBPKN". The trick here is to first forge an ad-hoc FEN string
88
- // and then let a Position object do the work for us.
89
- Key key(const string& code, Color c) {
90
-
91
- assert(code.length() > 0 && code.length() < 8);
92
- assert(code[0] == 'K');
93
-
94
- string sides[] = { code.substr(code.find('K', 1)), // Weak
95
- code.substr(0, code.find('K', 1)) }; // Strong
96
-
97
- std::transform(sides[c].begin(), sides[c].end(), sides[c].begin(), tolower);
98
-
99
- string fen = sides[0] + char(8 - sides[0].length() + '0') + "/8/8/8/8/8/8/"
100
- + sides[1] + char(8 - sides[1].length() + '0') + " w - - 0 10";
101
-
102
- StateInfo st;
103
- return Position().set(fen, false, &st, nullptr).material_key();
104
- }
105
-
106
- } // namespace
107
-
108
-
109
- /// Endgames members definitions
110
-
111
- Endgames::Endgames() {
112
-
113
- add<KPK>("KPK");
114
- add<KNNK>("KNNK");
115
- add<KBNK>("KBNK");
116
- add<KRKP>("KRKP");
117
- add<KRKB>("KRKB");
118
- add<KRKN>("KRKN");
119
- add<KQKP>("KQKP");
120
- add<KQKR>("KQKR");
121
-
122
- add<KNPK>("KNPK");
123
- add<KNPKB>("KNPKB");
124
- add<KRPKR>("KRPKR");
125
- add<KRPKB>("KRPKB");
126
- add<KBPKB>("KBPKB");
127
- add<KBPKN>("KBPKN");
128
- add<KBPPKB>("KBPPKB");
129
- add<KRPPKRP>("KRPPKRP");
130
- }
131
-
132
-
133
- template<EndgameType E, typename T>
134
- void Endgames::add(const string& code) {
135
- map<T>()[key(code, WHITE)] = std::unique_ptr<EndgameBase<T>>(new Endgame<E>(WHITE));
136
- map<T>()[key(code, BLACK)] = std::unique_ptr<EndgameBase<T>>(new Endgame<E>(BLACK));
137
- }
138
-
139
-
140
- /// Mate with KX vs K. This function is used to evaluate positions with
141
- /// king and plenty of material vs a lone king. It simply gives the
142
- /// attacking side a bonus for driving the defending king towards the edge
143
- /// of the board, and for keeping the distance between the two kings small.
144
- template<>
145
- Value Endgame<KXK>::operator()(const Position& pos) const {
146
-
147
- assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
148
- assert(!pos.checkers()); // Eval is never called when in check
149
-
150
- // Stalemate detection with lone king
151
- if (pos.side_to_move() == weakSide && !MoveList<LEGAL>(pos).size())
152
- return VALUE_DRAW;
153
-
154
- Square winnerKSq = pos.square<KING>(strongSide);
155
- Square loserKSq = pos.square<KING>(weakSide);
156
-
157
- Value result = pos.non_pawn_material(strongSide)
158
- + pos.count<PAWN>(strongSide) * PawnValueEg
159
- + PushToEdges[loserKSq]
160
- + PushClose[distance(winnerKSq, loserKSq)];
161
-
162
- if ( pos.count<QUEEN>(strongSide)
163
- || pos.count<ROOK>(strongSide)
164
- ||(pos.count<BISHOP>(strongSide) && pos.count<KNIGHT>(strongSide))
165
- ||(pos.count<BISHOP>(strongSide) > 1 && opposite_colors(pos.squares<BISHOP>(strongSide)[0],
166
- pos.squares<BISHOP>(strongSide)[1])))
167
- result = std::min(result + VALUE_KNOWN_WIN, VALUE_MATE_IN_MAX_PLY - 1);
168
-
169
- return strongSide == pos.side_to_move() ? result : -result;
170
- }
171
-
172
-
173
- /// Mate with KBN vs K. This is similar to KX vs K, but we have to drive the
174
- /// defending king towards a corner square of the right color.
175
- template<>
176
- Value Endgame<KBNK>::operator()(const Position& pos) const {
177
-
178
- assert(verify_material(pos, strongSide, KnightValueMg + BishopValueMg, 0));
179
- assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
180
-
181
- Square winnerKSq = pos.square<KING>(strongSide);
182
- Square loserKSq = pos.square<KING>(weakSide);
183
- Square bishopSq = pos.square<BISHOP>(strongSide);
184
-
185
- // kbnk_mate_table() tries to drive toward corners A1 or H8. If we have a
186
- // bishop that cannot reach the above squares, we flip the kings in order
187
- // to drive the enemy toward corners A8 or H1.
188
- if (opposite_colors(bishopSq, SQ_A1))
189
- {
190
- winnerKSq = ~winnerKSq;
191
- loserKSq = ~loserKSq;
192
- }
193
-
194
- Value result = VALUE_KNOWN_WIN
195
- + PushClose[distance(winnerKSq, loserKSq)]
196
- + PushToCorners[loserKSq];
197
-
198
- return strongSide == pos.side_to_move() ? result : -result;
199
- }
200
-
201
-
202
- /// KP vs K. This endgame is evaluated with the help of a bitbase.
203
- template<>
204
- Value Endgame<KPK>::operator()(const Position& pos) const {
205
-
206
- assert(verify_material(pos, strongSide, VALUE_ZERO, 1));
207
- assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
208
-
209
- // Assume strongSide is white and the pawn is on files A-D
210
- Square wksq = normalize(pos, strongSide, pos.square<KING>(strongSide));
211
- Square bksq = normalize(pos, strongSide, pos.square<KING>(weakSide));
212
- Square psq = normalize(pos, strongSide, pos.square<PAWN>(strongSide));
213
-
214
- Color us = strongSide == pos.side_to_move() ? WHITE : BLACK;
215
-
216
- if (!Bitbases::probe(wksq, psq, bksq, us))
217
- return VALUE_DRAW;
218
-
219
- Value result = VALUE_KNOWN_WIN + PawnValueEg + Value(rank_of(psq));
220
-
221
- return strongSide == pos.side_to_move() ? result : -result;
222
- }
223
-
224
-
225
- /// KR vs KP. This is a somewhat tricky endgame to evaluate precisely without
226
- /// a bitbase. The function below returns drawish scores when the pawn is
227
- /// far advanced with support of the king, while the attacking king is far
228
- /// away.
229
- template<>
230
- Value Endgame<KRKP>::operator()(const Position& pos) const {
231
-
232
- assert(verify_material(pos, strongSide, RookValueMg, 0));
233
- assert(verify_material(pos, weakSide, VALUE_ZERO, 1));
234
-
235
- Square wksq = relative_square(strongSide, pos.square<KING>(strongSide));
236
- Square bksq = relative_square(strongSide, pos.square<KING>(weakSide));
237
- Square rsq = relative_square(strongSide, pos.square<ROOK>(strongSide));
238
- Square psq = relative_square(strongSide, pos.square<PAWN>(weakSide));
239
-
240
- Square queeningSq = make_square(file_of(psq), RANK_1);
241
- Value result;
242
-
243
- // If the stronger side's king is in front of the pawn, it's a win
244
- if (wksq < psq && file_of(wksq) == file_of(psq))
245
- result = RookValueEg - distance(wksq, psq);
246
-
247
- // If the weaker side's king is too far from the pawn and the rook,
248
- // it's a win.
249
- else if ( distance(bksq, psq) >= 3 + (pos.side_to_move() == weakSide)
250
- && distance(bksq, rsq) >= 3)
251
- result = RookValueEg - distance(wksq, psq);
252
-
253
- // If the pawn is far advanced and supported by the defending king,
254
- // the position is drawish
255
- else if ( rank_of(bksq) <= RANK_3
256
- && distance(bksq, psq) == 1
257
- && rank_of(wksq) >= RANK_4
258
- && distance(wksq, psq) > 2 + (pos.side_to_move() == strongSide))
259
- result = Value(80) - 8 * distance(wksq, psq);
260
-
261
- else
262
- result = Value(200) - 8 * ( distance(wksq, psq + SOUTH)
263
- - distance(bksq, psq + SOUTH)
264
- - distance(psq, queeningSq));
265
-
266
- return strongSide == pos.side_to_move() ? result : -result;
267
- }
268
-
269
-
270
- /// KR vs KB. This is very simple, and always returns drawish scores. The
271
- /// score is slightly bigger when the defending king is close to the edge.
272
- template<>
273
- Value Endgame<KRKB>::operator()(const Position& pos) const {
274
-
275
- assert(verify_material(pos, strongSide, RookValueMg, 0));
276
- assert(verify_material(pos, weakSide, BishopValueMg, 0));
277
-
278
- Value result = Value(PushToEdges[pos.square<KING>(weakSide)]);
279
- return strongSide == pos.side_to_move() ? result : -result;
280
- }
281
-
282
-
283
- /// KR vs KN. The attacking side has slightly better winning chances than
284
- /// in KR vs KB, particularly if the king and the knight are far apart.
285
- template<>
286
- Value Endgame<KRKN>::operator()(const Position& pos) const {
287
-
288
- assert(verify_material(pos, strongSide, RookValueMg, 0));
289
- assert(verify_material(pos, weakSide, KnightValueMg, 0));
290
-
291
- Square bksq = pos.square<KING>(weakSide);
292
- Square bnsq = pos.square<KNIGHT>(weakSide);
293
- Value result = Value(PushToEdges[bksq] + PushAway[distance(bksq, bnsq)]);
294
- return strongSide == pos.side_to_move() ? result : -result;
295
- }
296
-
297
-
298
- /// KQ vs KP. In general, this is a win for the stronger side, but there are a
299
- /// few important exceptions. A pawn on 7th rank and on the A,C,F or H files
300
- /// with a king positioned next to it can be a draw, so in that case, we only
301
- /// use the distance between the kings.
302
- template<>
303
- Value Endgame<KQKP>::operator()(const Position& pos) const {
304
-
305
- assert(verify_material(pos, strongSide, QueenValueMg, 0));
306
- assert(verify_material(pos, weakSide, VALUE_ZERO, 1));
307
-
308
- Square winnerKSq = pos.square<KING>(strongSide);
309
- Square loserKSq = pos.square<KING>(weakSide);
310
- Square pawnSq = pos.square<PAWN>(weakSide);
311
-
312
- Value result = Value(PushClose[distance(winnerKSq, loserKSq)]);
313
-
314
- if ( relative_rank(weakSide, pawnSq) != RANK_7
315
- || distance(loserKSq, pawnSq) != 1
316
- || !((FileABB | FileCBB | FileFBB | FileHBB) & pawnSq))
317
- result += QueenValueEg - PawnValueEg;
318
-
319
- return strongSide == pos.side_to_move() ? result : -result;
320
- }
321
-
322
-
323
- /// KQ vs KR. This is almost identical to KX vs K: We give the attacking
324
- /// king a bonus for having the kings close together, and for forcing the
325
- /// defending king towards the edge. If we also take care to avoid null move for
326
- /// the defending side in the search, this is usually sufficient to win KQ vs KR.
327
- template<>
328
- Value Endgame<KQKR>::operator()(const Position& pos) const {
329
-
330
- assert(verify_material(pos, strongSide, QueenValueMg, 0));
331
- assert(verify_material(pos, weakSide, RookValueMg, 0));
332
-
333
- Square winnerKSq = pos.square<KING>(strongSide);
334
- Square loserKSq = pos.square<KING>(weakSide);
335
-
336
- Value result = QueenValueEg
337
- - RookValueEg
338
- + PushToEdges[loserKSq]
339
- + PushClose[distance(winnerKSq, loserKSq)];
340
-
341
- return strongSide == pos.side_to_move() ? result : -result;
342
- }
343
-
344
-
345
- /// Some cases of trivial draws
346
- template<> Value Endgame<KNNK>::operator()(const Position&) const { return VALUE_DRAW; }
347
-
348
-
349
- /// KB and one or more pawns vs K. It checks for draws with rook pawns and
350
- /// a bishop of the wrong color. If such a draw is detected, SCALE_FACTOR_DRAW
351
- /// is returned. If not, the return value is SCALE_FACTOR_NONE, i.e. no scaling
352
- /// will be used.
353
- template<>
354
- ScaleFactor Endgame<KBPsK>::operator()(const Position& pos) const {
355
-
356
- assert(pos.non_pawn_material(strongSide) == BishopValueMg);
357
- assert(pos.count<PAWN>(strongSide) >= 1);
358
-
359
- // No assertions about the material of weakSide, because we want draws to
360
- // be detected even when the weaker side has some pawns.
361
-
362
- Bitboard pawns = pos.pieces(strongSide, PAWN);
363
- File pawnsFile = file_of(lsb(pawns));
364
-
365
- // All pawns are on a single rook file?
366
- if ( (pawnsFile == FILE_A || pawnsFile == FILE_H)
367
- && !(pawns & ~file_bb(pawnsFile)))
368
- {
369
- Square bishopSq = pos.square<BISHOP>(strongSide);
370
- Square queeningSq = relative_square(strongSide, make_square(pawnsFile, RANK_8));
371
- Square kingSq = pos.square<KING>(weakSide);
372
-
373
- if ( opposite_colors(queeningSq, bishopSq)
374
- && distance(queeningSq, kingSq) <= 1)
375
- return SCALE_FACTOR_DRAW;
376
- }
377
-
378
- // If all the pawns are on the same B or G file, then it's potentially a draw
379
- if ( (pawnsFile == FILE_B || pawnsFile == FILE_G)
380
- && !(pos.pieces(PAWN) & ~file_bb(pawnsFile))
381
- && pos.non_pawn_material(weakSide) == 0
382
- && pos.count<PAWN>(weakSide) >= 1)
383
- {
384
- // Get weakSide pawn that is closest to the home rank
385
- Square weakPawnSq = backmost_sq(weakSide, pos.pieces(weakSide, PAWN));
386
-
387
- Square strongKingSq = pos.square<KING>(strongSide);
388
- Square weakKingSq = pos.square<KING>(weakSide);
389
- Square bishopSq = pos.square<BISHOP>(strongSide);
390
-
391
- // There's potential for a draw if our pawn is blocked on the 7th rank,
392
- // the bishop cannot attack it or they only have one pawn left
393
- if ( relative_rank(strongSide, weakPawnSq) == RANK_7
394
- && (pos.pieces(strongSide, PAWN) & (weakPawnSq + pawn_push(weakSide)))
395
- && (opposite_colors(bishopSq, weakPawnSq) || pos.count<PAWN>(strongSide) == 1))
396
- {
397
- int strongKingDist = distance(weakPawnSq, strongKingSq);
398
- int weakKingDist = distance(weakPawnSq, weakKingSq);
399
-
400
- // It's a draw if the weak king is on its back two ranks, within 2
401
- // squares of the blocking pawn and the strong king is not
402
- // closer. (I think this rule only fails in practically
403
- // unreachable positions such as 5k1K/6p1/6P1/8/8/3B4/8/8 w
404
- // and positions where qsearch will immediately correct the
405
- // problem such as 8/4k1p1/6P1/1K6/3B4/8/8/8 w)
406
- if ( relative_rank(strongSide, weakKingSq) >= RANK_7
407
- && weakKingDist <= 2
408
- && weakKingDist <= strongKingDist)
409
- return SCALE_FACTOR_DRAW;
410
- }
411
- }
412
-
413
- return SCALE_FACTOR_NONE;
414
- }
415
-
416
-
417
- /// KQ vs KR and one or more pawns. It tests for fortress draws with a rook on
418
- /// the third rank defended by a pawn.
419
- template<>
420
- ScaleFactor Endgame<KQKRPs>::operator()(const Position& pos) const {
421
-
422
- assert(verify_material(pos, strongSide, QueenValueMg, 0));
423
- assert(pos.count<ROOK>(weakSide) == 1);
424
- assert(pos.count<PAWN>(weakSide) >= 1);
425
-
426
- Square kingSq = pos.square<KING>(weakSide);
427
- Square rsq = pos.square<ROOK>(weakSide);
428
-
429
- if ( relative_rank(weakSide, kingSq) <= RANK_2
430
- && relative_rank(weakSide, pos.square<KING>(strongSide)) >= RANK_4
431
- && relative_rank(weakSide, rsq) == RANK_3
432
- && ( pos.pieces(weakSide, PAWN)
433
- & pos.attacks_from<KING>(kingSq)
434
- & pos.attacks_from<PAWN>(rsq, strongSide)))
435
- return SCALE_FACTOR_DRAW;
436
-
437
- return SCALE_FACTOR_NONE;
438
- }
439
-
440
-
441
- /// KRP vs KR. This function knows a handful of the most important classes of
442
- /// drawn positions, but is far from perfect. It would probably be a good idea
443
- /// to add more knowledge in the future.
444
- ///
445
- /// It would also be nice to rewrite the actual code for this function,
446
- /// which is mostly copied from Glaurung 1.x, and isn't very pretty.
447
- template<>
448
- ScaleFactor Endgame<KRPKR>::operator()(const Position& pos) const {
449
-
450
- assert(verify_material(pos, strongSide, RookValueMg, 1));
451
- assert(verify_material(pos, weakSide, RookValueMg, 0));
452
-
453
- // Assume strongSide is white and the pawn is on files A-D
454
- Square wksq = normalize(pos, strongSide, pos.square<KING>(strongSide));
455
- Square bksq = normalize(pos, strongSide, pos.square<KING>(weakSide));
456
- Square wrsq = normalize(pos, strongSide, pos.square<ROOK>(strongSide));
457
- Square wpsq = normalize(pos, strongSide, pos.square<PAWN>(strongSide));
458
- Square brsq = normalize(pos, strongSide, pos.square<ROOK>(weakSide));
459
-
460
- File f = file_of(wpsq);
461
- Rank r = rank_of(wpsq);
462
- Square queeningSq = make_square(f, RANK_8);
463
- int tempo = (pos.side_to_move() == strongSide);
464
-
465
- // If the pawn is not too far advanced and the defending king defends the
466
- // queening square, use the third-rank defence.
467
- if ( r <= RANK_5
468
- && distance(bksq, queeningSq) <= 1
469
- && wksq <= SQ_H5
470
- && (rank_of(brsq) == RANK_6 || (r <= RANK_3 && rank_of(wrsq) != RANK_6)))
471
- return SCALE_FACTOR_DRAW;
472
-
473
- // The defending side saves a draw by checking from behind in case the pawn
474
- // has advanced to the 6th rank with the king behind.
475
- if ( r == RANK_6
476
- && distance(bksq, queeningSq) <= 1
477
- && rank_of(wksq) + tempo <= RANK_6
478
- && (rank_of(brsq) == RANK_1 || (!tempo && distance<File>(brsq, wpsq) >= 3)))
479
- return SCALE_FACTOR_DRAW;
480
-
481
- if ( r >= RANK_6
482
- && bksq == queeningSq
483
- && rank_of(brsq) == RANK_1
484
- && (!tempo || distance(wksq, wpsq) >= 2))
485
- return SCALE_FACTOR_DRAW;
486
-
487
- // White pawn on a7 and rook on a8 is a draw if black's king is on g7 or h7
488
- // and the black rook is behind the pawn.
489
- if ( wpsq == SQ_A7
490
- && wrsq == SQ_A8
491
- && (bksq == SQ_H7 || bksq == SQ_G7)
492
- && file_of(brsq) == FILE_A
493
- && (rank_of(brsq) <= RANK_3 || file_of(wksq) >= FILE_D || rank_of(wksq) <= RANK_5))
494
- return SCALE_FACTOR_DRAW;
495
-
496
- // If the defending king blocks the pawn and the attacking king is too far
497
- // away, it's a draw.
498
- if ( r <= RANK_5
499
- && bksq == wpsq + NORTH
500
- && distance(wksq, wpsq) - tempo >= 2
501
- && distance(wksq, brsq) - tempo >= 2)
502
- return SCALE_FACTOR_DRAW;
503
-
504
- // Pawn on the 7th rank supported by the rook from behind usually wins if the
505
- // attacking king is closer to the queening square than the defending king,
506
- // and the defending king cannot gain tempi by threatening the attacking rook.
507
- if ( r == RANK_7
508
- && f != FILE_A
509
- && file_of(wrsq) == f
510
- && wrsq != queeningSq
511
- && (distance(wksq, queeningSq) < distance(bksq, queeningSq) - 2 + tempo)
512
- && (distance(wksq, queeningSq) < distance(bksq, wrsq) + tempo))
513
- return ScaleFactor(SCALE_FACTOR_MAX - 2 * distance(wksq, queeningSq));
514
-
515
- // Similar to the above, but with the pawn further back
516
- if ( f != FILE_A
517
- && file_of(wrsq) == f
518
- && wrsq < wpsq
519
- && (distance(wksq, queeningSq) < distance(bksq, queeningSq) - 2 + tempo)
520
- && (distance(wksq, wpsq + NORTH) < distance(bksq, wpsq + NORTH) - 2 + tempo)
521
- && ( distance(bksq, wrsq) + tempo >= 3
522
- || ( distance(wksq, queeningSq) < distance(bksq, wrsq) + tempo
523
- && (distance(wksq, wpsq + NORTH) < distance(bksq, wrsq) + tempo))))
524
- return ScaleFactor( SCALE_FACTOR_MAX
525
- - 8 * distance(wpsq, queeningSq)
526
- - 2 * distance(wksq, queeningSq));
527
-
528
- // If the pawn is not far advanced and the defending king is somewhere in
529
- // the pawn's path, it's probably a draw.
530
- if (r <= RANK_4 && bksq > wpsq)
531
- {
532
- if (file_of(bksq) == file_of(wpsq))
533
- return ScaleFactor(10);
534
- if ( distance<File>(bksq, wpsq) == 1
535
- && distance(wksq, bksq) > 2)
536
- return ScaleFactor(24 - 2 * distance(wksq, bksq));
537
- }
538
- return SCALE_FACTOR_NONE;
539
- }
540
-
541
- template<>
542
- ScaleFactor Endgame<KRPKB>::operator()(const Position& pos) const {
543
-
544
- assert(verify_material(pos, strongSide, RookValueMg, 1));
545
- assert(verify_material(pos, weakSide, BishopValueMg, 0));
546
-
547
- // Test for a rook pawn
548
- if (pos.pieces(PAWN) & (FileABB | FileHBB))
549
- {
550
- Square ksq = pos.square<KING>(weakSide);
551
- Square bsq = pos.square<BISHOP>(weakSide);
552
- Square psq = pos.square<PAWN>(strongSide);
553
- Rank rk = relative_rank(strongSide, psq);
554
- Square push = pawn_push(strongSide);
555
-
556
- // If the pawn is on the 5th rank and the pawn (currently) is on
557
- // the same color square as the bishop then there is a chance of
558
- // a fortress. Depending on the king position give a moderate
559
- // reduction or a stronger one if the defending king is near the
560
- // corner but not trapped there.
561
- if (rk == RANK_5 && !opposite_colors(bsq, psq))
562
- {
563
- int d = distance(psq + 3 * push, ksq);
564
-
565
- if (d <= 2 && !(d == 0 && ksq == pos.square<KING>(strongSide) + 2 * push))
566
- return ScaleFactor(24);
567
- else
568
- return ScaleFactor(48);
569
- }
570
-
571
- // When the pawn has moved to the 6th rank we can be fairly sure
572
- // it's drawn if the bishop attacks the square in front of the
573
- // pawn from a reasonable distance and the defending king is near
574
- // the corner
575
- if ( rk == RANK_6
576
- && distance(psq + 2 * push, ksq) <= 1
577
- && (PseudoAttacks[BISHOP][bsq] & (psq + push))
578
- && distance<File>(bsq, psq) >= 2)
579
- return ScaleFactor(8);
580
- }
581
-
582
- return SCALE_FACTOR_NONE;
583
- }
584
-
585
- /// KRPP vs KRP. There is just a single rule: if the stronger side has no passed
586
- /// pawns and the defending king is actively placed, the position is drawish.
587
- template<>
588
- ScaleFactor Endgame<KRPPKRP>::operator()(const Position& pos) const {
589
-
590
- assert(verify_material(pos, strongSide, RookValueMg, 2));
591
- assert(verify_material(pos, weakSide, RookValueMg, 1));
592
-
593
- Square wpsq1 = pos.squares<PAWN>(strongSide)[0];
594
- Square wpsq2 = pos.squares<PAWN>(strongSide)[1];
595
- Square bksq = pos.square<KING>(weakSide);
596
-
597
- // Does the stronger side have a passed pawn?
598
- if (pos.pawn_passed(strongSide, wpsq1) || pos.pawn_passed(strongSide, wpsq2))
599
- return SCALE_FACTOR_NONE;
600
-
601
- Rank r = std::max(relative_rank(strongSide, wpsq1), relative_rank(strongSide, wpsq2));
602
-
603
- if ( distance<File>(bksq, wpsq1) <= 1
604
- && distance<File>(bksq, wpsq2) <= 1
605
- && relative_rank(strongSide, bksq) > r)
606
- {
607
- assert(r > RANK_1 && r < RANK_7);
608
- return ScaleFactor(KRPPKRPScaleFactors[r]);
609
- }
610
- return SCALE_FACTOR_NONE;
611
- }
612
-
613
-
614
- /// K and two or more pawns vs K. There is just a single rule here: If all pawns
615
- /// are on the same rook file and are blocked by the defending king, it's a draw.
616
- template<>
617
- ScaleFactor Endgame<KPsK>::operator()(const Position& pos) const {
618
-
619
- assert(pos.non_pawn_material(strongSide) == VALUE_ZERO);
620
- assert(pos.count<PAWN>(strongSide) >= 2);
621
- assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
622
-
623
- Square ksq = pos.square<KING>(weakSide);
624
- Bitboard pawns = pos.pieces(strongSide, PAWN);
625
-
626
- // If all pawns are ahead of the king, on a single rook file and
627
- // the king is within one file of the pawns, it's a draw.
628
- if ( !(pawns & ~in_front_bb(weakSide, rank_of(ksq)))
629
- && !((pawns & ~FileABB) && (pawns & ~FileHBB))
630
- && distance<File>(ksq, lsb(pawns)) <= 1)
631
- return SCALE_FACTOR_DRAW;
632
-
633
- return SCALE_FACTOR_NONE;
634
- }
635
-
636
-
637
- /// KBP vs KB. There are two rules: if the defending king is somewhere along the
638
- /// path of the pawn, and the square of the king is not of the same color as the
639
- /// stronger side's bishop, it's a draw. If the two bishops have opposite color,
640
- /// it's almost always a draw.
641
- template<>
642
- ScaleFactor Endgame<KBPKB>::operator()(const Position& pos) const {
643
-
644
- assert(verify_material(pos, strongSide, BishopValueMg, 1));
645
- assert(verify_material(pos, weakSide, BishopValueMg, 0));
646
-
647
- Square pawnSq = pos.square<PAWN>(strongSide);
648
- Square strongBishopSq = pos.square<BISHOP>(strongSide);
649
- Square weakBishopSq = pos.square<BISHOP>(weakSide);
650
- Square weakKingSq = pos.square<KING>(weakSide);
651
-
652
- // Case 1: Defending king blocks the pawn, and cannot be driven away
653
- if ( file_of(weakKingSq) == file_of(pawnSq)
654
- && relative_rank(strongSide, pawnSq) < relative_rank(strongSide, weakKingSq)
655
- && ( opposite_colors(weakKingSq, strongBishopSq)
656
- || relative_rank(strongSide, weakKingSq) <= RANK_6))
657
- return SCALE_FACTOR_DRAW;
658
-
659
- // Case 2: Opposite colored bishops
660
- if (opposite_colors(strongBishopSq, weakBishopSq))
661
- {
662
- // We assume that the position is drawn in the following three situations:
663
- //
664
- // a. The pawn is on rank 5 or further back.
665
- // b. The defending king is somewhere in the pawn's path.
666
- // c. The defending bishop attacks some square along the pawn's path,
667
- // and is at least three squares away from the pawn.
668
- //
669
- // These rules are probably not perfect, but in practice they work
670
- // reasonably well.
671
-
672
- if (relative_rank(strongSide, pawnSq) <= RANK_5)
673
- return SCALE_FACTOR_DRAW;
674
- else
675
- {
676
- Bitboard path = forward_bb(strongSide, pawnSq);
677
-
678
- if (path & pos.pieces(weakSide, KING))
679
- return SCALE_FACTOR_DRAW;
680
-
681
- if ( (pos.attacks_from<BISHOP>(weakBishopSq) & path)
682
- && distance(weakBishopSq, pawnSq) >= 3)
683
- return SCALE_FACTOR_DRAW;
684
- }
685
- }
686
- return SCALE_FACTOR_NONE;
687
- }
688
-
689
-
690
- /// KBPP vs KB. It detects a few basic draws with opposite-colored bishops
691
- template<>
692
- ScaleFactor Endgame<KBPPKB>::operator()(const Position& pos) const {
693
-
694
- assert(verify_material(pos, strongSide, BishopValueMg, 2));
695
- assert(verify_material(pos, weakSide, BishopValueMg, 0));
696
-
697
- Square wbsq = pos.square<BISHOP>(strongSide);
698
- Square bbsq = pos.square<BISHOP>(weakSide);
699
-
700
- if (!opposite_colors(wbsq, bbsq))
701
- return SCALE_FACTOR_NONE;
702
-
703
- Square ksq = pos.square<KING>(weakSide);
704
- Square psq1 = pos.squares<PAWN>(strongSide)[0];
705
- Square psq2 = pos.squares<PAWN>(strongSide)[1];
706
- Rank r1 = rank_of(psq1);
707
- Rank r2 = rank_of(psq2);
708
- Square blockSq1, blockSq2;
709
-
710
- if (relative_rank(strongSide, psq1) > relative_rank(strongSide, psq2))
711
- {
712
- blockSq1 = psq1 + pawn_push(strongSide);
713
- blockSq2 = make_square(file_of(psq2), rank_of(psq1));
714
- }
715
- else
716
- {
717
- blockSq1 = psq2 + pawn_push(strongSide);
718
- blockSq2 = make_square(file_of(psq1), rank_of(psq2));
719
- }
720
-
721
- switch (distance<File>(psq1, psq2))
722
- {
723
- case 0:
724
- // Both pawns are on the same file. It's an easy draw if the defender firmly
725
- // controls some square in the frontmost pawn's path.
726
- if ( file_of(ksq) == file_of(blockSq1)
727
- && relative_rank(strongSide, ksq) >= relative_rank(strongSide, blockSq1)
728
- && opposite_colors(ksq, wbsq))
729
- return SCALE_FACTOR_DRAW;
730
- else
731
- return SCALE_FACTOR_NONE;
732
-
733
- case 1:
734
- // Pawns on adjacent files. It's a draw if the defender firmly controls the
735
- // square in front of the frontmost pawn's path, and the square diagonally
736
- // behind this square on the file of the other pawn.
737
- if ( ksq == blockSq1
738
- && opposite_colors(ksq, wbsq)
739
- && ( bbsq == blockSq2
740
- || (pos.attacks_from<BISHOP>(blockSq2) & pos.pieces(weakSide, BISHOP))
741
- || distance(r1, r2) >= 2))
742
- return SCALE_FACTOR_DRAW;
743
-
744
- else if ( ksq == blockSq2
745
- && opposite_colors(ksq, wbsq)
746
- && ( bbsq == blockSq1
747
- || (pos.attacks_from<BISHOP>(blockSq1) & pos.pieces(weakSide, BISHOP))))
748
- return SCALE_FACTOR_DRAW;
749
- else
750
- return SCALE_FACTOR_NONE;
751
-
752
- default:
753
- // The pawns are not on the same file or adjacent files. No scaling.
754
- return SCALE_FACTOR_NONE;
755
- }
756
- }
757
-
758
-
759
- /// KBP vs KN. There is a single rule: If the defending king is somewhere along
760
- /// the path of the pawn, and the square of the king is not of the same color as
761
- /// the stronger side's bishop, it's a draw.
762
- template<>
763
- ScaleFactor Endgame<KBPKN>::operator()(const Position& pos) const {
764
-
765
- assert(verify_material(pos, strongSide, BishopValueMg, 1));
766
- assert(verify_material(pos, weakSide, KnightValueMg, 0));
767
-
768
- Square pawnSq = pos.square<PAWN>(strongSide);
769
- Square strongBishopSq = pos.square<BISHOP>(strongSide);
770
- Square weakKingSq = pos.square<KING>(weakSide);
771
-
772
- if ( file_of(weakKingSq) == file_of(pawnSq)
773
- && relative_rank(strongSide, pawnSq) < relative_rank(strongSide, weakKingSq)
774
- && ( opposite_colors(weakKingSq, strongBishopSq)
775
- || relative_rank(strongSide, weakKingSq) <= RANK_6))
776
- return SCALE_FACTOR_DRAW;
777
-
778
- return SCALE_FACTOR_NONE;
779
- }
780
-
781
-
782
- /// KNP vs K. There is a single rule: if the pawn is a rook pawn on the 7th rank
783
- /// and the defending king prevents the pawn from advancing, the position is drawn.
784
- template<>
785
- ScaleFactor Endgame<KNPK>::operator()(const Position& pos) const {
786
-
787
- assert(verify_material(pos, strongSide, KnightValueMg, 1));
788
- assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
789
-
790
- // Assume strongSide is white and the pawn is on files A-D
791
- Square pawnSq = normalize(pos, strongSide, pos.square<PAWN>(strongSide));
792
- Square weakKingSq = normalize(pos, strongSide, pos.square<KING>(weakSide));
793
-
794
- if (pawnSq == SQ_A7 && distance(SQ_A8, weakKingSq) <= 1)
795
- return SCALE_FACTOR_DRAW;
796
-
797
- return SCALE_FACTOR_NONE;
798
- }
799
-
800
-
801
- /// KNP vs KB. If knight can block bishop from taking pawn, it's a win.
802
- /// Otherwise the position is drawn.
803
- template<>
804
- ScaleFactor Endgame<KNPKB>::operator()(const Position& pos) const {
805
-
806
- Square pawnSq = pos.square<PAWN>(strongSide);
807
- Square bishopSq = pos.square<BISHOP>(weakSide);
808
- Square weakKingSq = pos.square<KING>(weakSide);
809
-
810
- // King needs to get close to promoting pawn to prevent knight from blocking.
811
- // Rules for this are very tricky, so just approximate.
812
- if (forward_bb(strongSide, pawnSq) & pos.attacks_from<BISHOP>(bishopSq))
813
- return ScaleFactor(distance(weakKingSq, pawnSq));
814
-
815
- return SCALE_FACTOR_NONE;
816
- }
817
-
818
-
819
- /// KP vs KP. This is done by removing the weakest side's pawn and probing the
820
- /// KP vs K bitbase: If the weakest side has a draw without the pawn, it probably
821
- /// has at least a draw with the pawn as well. The exception is when the stronger
822
- /// side's pawn is far advanced and not on a rook file; in this case it is often
823
- /// possible to win (e.g. 8/4k3/3p4/3P4/6K1/8/8/8 w - - 0 1).
824
- template<>
825
- ScaleFactor Endgame<KPKP>::operator()(const Position& pos) const {
826
-
827
- assert(verify_material(pos, strongSide, VALUE_ZERO, 1));
828
- assert(verify_material(pos, weakSide, VALUE_ZERO, 1));
829
-
830
- // Assume strongSide is white and the pawn is on files A-D
831
- Square wksq = normalize(pos, strongSide, pos.square<KING>(strongSide));
832
- Square bksq = normalize(pos, strongSide, pos.square<KING>(weakSide));
833
- Square psq = normalize(pos, strongSide, pos.square<PAWN>(strongSide));
834
-
835
- Color us = strongSide == pos.side_to_move() ? WHITE : BLACK;
836
-
837
- // If the pawn has advanced to the fifth rank or further, and is not a
838
- // rook pawn, it's too dangerous to assume that it's at least a draw.
839
- if (rank_of(psq) >= RANK_5 && file_of(psq) != FILE_A)
840
- return SCALE_FACTOR_NONE;
841
-
842
- // Probe the KPK bitbase with the weakest side's pawn removed. If it's a draw,
843
- // it's probably at least a draw even with the pawn.
844
- return Bitbases::probe(wksq, psq, bksq, us) ? SCALE_FACTOR_NONE : SCALE_FACTOR_DRAW;
845
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/endgame.h DELETED
@@ -1,125 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #ifndef ENDGAME_H_INCLUDED
22
- #define ENDGAME_H_INCLUDED
23
-
24
- #include <map>
25
- #include <memory>
26
- #include <string>
27
- #include <type_traits>
28
- #include <utility>
29
-
30
- #include "position.h"
31
- #include "types.h"
32
-
33
-
34
- /// EndgameType lists all supported endgames
35
-
36
- enum EndgameType {
37
-
38
- // Evaluation functions
39
-
40
- KNNK, // KNN vs K
41
- KXK, // Generic "mate lone king" eval
42
- KBNK, // KBN vs K
43
- KPK, // KP vs K
44
- KRKP, // KR vs KP
45
- KRKB, // KR vs KB
46
- KRKN, // KR vs KN
47
- KQKP, // KQ vs KP
48
- KQKR, // KQ vs KR
49
-
50
-
51
- // Scaling functions
52
- SCALING_FUNCTIONS,
53
-
54
- KBPsK, // KB and pawns vs K
55
- KQKRPs, // KQ vs KR and pawns
56
- KRPKR, // KRP vs KR
57
- KRPKB, // KRP vs KB
58
- KRPPKRP, // KRPP vs KRP
59
- KPsK, // K and pawns vs K
60
- KBPKB, // KBP vs KB
61
- KBPPKB, // KBPP vs KB
62
- KBPKN, // KBP vs KN
63
- KNPK, // KNP vs K
64
- KNPKB, // KNP vs KB
65
- KPKP // KP vs KP
66
- };
67
-
68
-
69
- /// Endgame functions can be of two types depending on whether they return a
70
- /// Value or a ScaleFactor.
71
- template<EndgameType E> using
72
- eg_type = typename std::conditional<(E < SCALING_FUNCTIONS), Value, ScaleFactor>::type;
73
-
74
-
75
- /// Base and derived templates for endgame evaluation and scaling functions
76
-
77
- template<typename T>
78
- struct EndgameBase {
79
-
80
- virtual ~EndgameBase() = default;
81
- virtual Color strong_side() const = 0;
82
- virtual T operator()(const Position&) const = 0;
83
- };
84
-
85
-
86
- template<EndgameType E, typename T = eg_type<E>>
87
- struct Endgame : public EndgameBase<T> {
88
-
89
- explicit Endgame(Color c) : strongSide(c), weakSide(~c) {}
90
- Color strong_side() const { return strongSide; }
91
- T operator()(const Position&) const;
92
-
93
- private:
94
- Color strongSide, weakSide;
95
- };
96
-
97
-
98
- /// The Endgames class stores the pointers to endgame evaluation and scaling
99
- /// base objects in two std::map. We use polymorphism to invoke the actual
100
- /// endgame function by calling its virtual operator().
101
-
102
- class Endgames {
103
-
104
- template<typename T> using Map = std::map<Key, std::unique_ptr<EndgameBase<T>>>;
105
-
106
- template<EndgameType E, typename T = eg_type<E>>
107
- void add(const std::string& code);
108
-
109
- template<typename T>
110
- Map<T>& map() {
111
- return std::get<std::is_same<T, ScaleFactor>::value>(maps);
112
- }
113
-
114
- std::pair<Map<Value>, Map<ScaleFactor>> maps;
115
-
116
- public:
117
- Endgames();
118
-
119
- template<typename T>
120
- EndgameBase<T>* probe(Key key) {
121
- return map<T>().count(key) ? map<T>()[key].get() : nullptr;
122
- }
123
- };
124
-
125
- #endif // #ifndef ENDGAME_H_INCLUDED
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/evaluate.cpp DELETED
@@ -1,927 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #include <algorithm>
22
- #include <cassert>
23
- #include <cstring> // For std::memset
24
- #include <iomanip>
25
- #include <sstream>
26
-
27
- #include "bitboard.h"
28
- #include "evaluate.h"
29
- #include "material.h"
30
- #include "pawns.h"
31
-
32
- namespace {
33
-
34
- namespace Trace {
35
-
36
- enum Term { // The first 8 entries are for PieceType
37
- MATERIAL = 8, IMBALANCE, MOBILITY, THREAT, PASSED, SPACE, TOTAL, TERM_NB
38
- };
39
-
40
- double scores[TERM_NB][COLOR_NB][PHASE_NB];
41
-
42
- double to_cp(Value v) { return double(v) / PawnValueEg; }
43
-
44
- void add(int idx, Color c, Score s) {
45
- scores[idx][c][MG] = to_cp(mg_value(s));
46
- scores[idx][c][EG] = to_cp(eg_value(s));
47
- }
48
-
49
- void add(int idx, Score w, Score b = SCORE_ZERO) {
50
- add(idx, WHITE, w); add(idx, BLACK, b);
51
- }
52
-
53
- std::ostream& operator<<(std::ostream& os, Term t) {
54
-
55
- if (t == MATERIAL || t == IMBALANCE || t == Term(PAWN) || t == TOTAL)
56
- os << " --- --- | --- --- | ";
57
- else
58
- os << std::setw(5) << scores[t][WHITE][MG] << " "
59
- << std::setw(5) << scores[t][WHITE][EG] << " | "
60
- << std::setw(5) << scores[t][BLACK][MG] << " "
61
- << std::setw(5) << scores[t][BLACK][EG] << " | ";
62
-
63
- os << std::setw(5) << scores[t][WHITE][MG] - scores[t][BLACK][MG] << " "
64
- << std::setw(5) << scores[t][WHITE][EG] - scores[t][BLACK][EG] << " \n";
65
-
66
- return os;
67
- }
68
- }
69
-
70
- using namespace Trace;
71
-
72
- // Struct EvalInfo contains various information computed and collected
73
- // by the evaluation functions.
74
- struct EvalInfo {
75
-
76
- // attackedBy[color][piece type] is a bitboard representing all squares
77
- // attacked by a given color and piece type (can be also ALL_PIECES).
78
- Bitboard attackedBy[COLOR_NB][PIECE_TYPE_NB];
79
-
80
- // attackedBy2[color] are the squares attacked by 2 pieces of a given color,
81
- // possibly via x-ray or by one pawn and one piece. Diagonal x-ray through
82
- // pawn or squares attacked by 2 pawns are not explicitly added.
83
- Bitboard attackedBy2[COLOR_NB];
84
-
85
- // kingRing[color] is the zone around the king which is considered
86
- // by the king safety evaluation. This consists of the squares directly
87
- // adjacent to the king, and the three (or two, for a king on an edge file)
88
- // squares two ranks in front of the king. For instance, if black's king
89
- // is on g8, kingRing[BLACK] is a bitboard containing the squares f8, h8,
90
- // f7, g7, h7, f6, g6 and h6.
91
- Bitboard kingRing[COLOR_NB];
92
-
93
- // kingAttackersCount[color] is the number of pieces of the given color
94
- // which attack a square in the kingRing of the enemy king.
95
- int kingAttackersCount[COLOR_NB];
96
-
97
- // kingAttackersWeight[color] is the sum of the "weights" of the pieces of the
98
- // given color which attack a square in the kingRing of the enemy king. The
99
- // weights of the individual piece types are given by the elements in the
100
- // KingAttackWeights array.
101
- int kingAttackersWeight[COLOR_NB];
102
-
103
- // kingAdjacentZoneAttacksCount[color] is the number of attacks by the given
104
- // color to squares directly adjacent to the enemy king. Pieces which attack
105
- // more than one square are counted multiple times. For instance, if there is
106
- // a white knight on g5 and black's king is on g8, this white knight adds 2
107
- // to kingAdjacentZoneAttacksCount[WHITE].
108
- int kingAdjacentZoneAttacksCount[COLOR_NB];
109
-
110
- Bitboard pinnedPieces[COLOR_NB];
111
- Material::Entry* me;
112
- Pawns::Entry* pi;
113
- };
114
-
115
- #define V(v) Value(v)
116
- #define S(mg, eg) make_score(mg, eg)
117
-
118
- // MobilityBonus[PieceType][attacked] contains bonuses for middle and end
119
- // game, indexed by piece type and number of attacked squares in the MobilityArea.
120
- const Score MobilityBonus[][32] = {
121
- {}, {},
122
- { S(-75,-76), S(-56,-54), S( -9,-26), S( -2,-10), S( 6, 5), S( 15, 11), // Knights
123
- S( 22, 26), S( 30, 28), S( 36, 29) },
124
- { S(-48,-58), S(-21,-19), S( 16, -2), S( 26, 12), S( 37, 22), S( 51, 42), // Bishops
125
- S( 54, 54), S( 63, 58), S( 65, 63), S( 71, 70), S( 79, 74), S( 81, 86),
126
- S( 92, 90), S( 97, 94) },
127
- { S(-56,-78), S(-25,-18), S(-11, 26), S( -5, 55), S( -4, 70), S( -1, 81), // Rooks
128
- S( 8,109), S( 14,120), S( 21,128), S( 23,143), S( 31,154), S( 32,160),
129
- S( 43,165), S( 49,168), S( 59,169) },
130
- { S(-40,-35), S(-25,-12), S( 2, 7), S( 4, 19), S( 14, 37), S( 24, 55), // Queens
131
- S( 25, 62), S( 40, 76), S( 43, 79), S( 47, 87), S( 54, 94), S( 56,102),
132
- S( 60,111), S( 70,116), S( 72,118), S( 73,122), S( 75,128), S( 77,130),
133
- S( 85,133), S( 94,136), S( 99,140), S(108,157), S(112,158), S(113,161),
134
- S(118,174), S(119,177), S(123,191), S(128,199) }
135
- };
136
-
137
- // Outpost[knight/bishop][supported by pawn] contains bonuses for knights and
138
- // bishops outposts, bigger if outpost piece is supported by a pawn.
139
- const Score Outpost[][2] = {
140
- { S(43,11), S(65,20) }, // Knights
141
- { S(20, 3), S(29, 8) } // Bishops
142
- };
143
-
144
- // ReachableOutpost[knight/bishop][supported by pawn] contains bonuses for
145
- // knights and bishops which can reach an outpost square in one move, bigger
146
- // if outpost square is supported by a pawn.
147
- const Score ReachableOutpost[][2] = {
148
- { S(21, 5), S(35, 8) }, // Knights
149
- { S( 8, 0), S(14, 4) } // Bishops
150
- };
151
-
152
- // RookOnFile[semiopen/open] contains bonuses for each rook when there is no
153
- // friendly pawn on the rook file.
154
- const Score RookOnFile[2] = { S(20, 7), S(45, 20) };
155
-
156
- // ThreatBySafePawn[PieceType] contains bonuses according to which piece
157
- // type is attacked by a pawn which is protected or is not attacked.
158
- const Score ThreatBySafePawn[PIECE_TYPE_NB] = {
159
- S(0, 0), S(0, 0), S(176, 139), S(131, 127), S(217, 218), S(203, 215)
160
- };
161
-
162
- // Threat[by minor/by rook][attacked PieceType] contains
163
- // bonuses according to which piece type attacks which one.
164
- // Attacks on lesser pieces which are pawn-defended are not considered.
165
- const Score Threat[][PIECE_TYPE_NB] = {
166
- { S(0, 0), S(0, 33), S(45, 43), S(46, 47), S(72,107), S(48,118) }, // by Minor
167
- { S(0, 0), S(0, 25), S(40, 62), S(40, 59), S( 0, 34), S(35, 48) } // by Rook
168
- };
169
-
170
- // ThreatByKing[on one/on many] contains bonuses for King attacks on
171
- // pawns or pieces which are not pawn-defended.
172
- const Score ThreatByKing[2] = { S(3, 62), S(9, 138) };
173
-
174
- // Passed[mg/eg][Rank] contains midgame and endgame bonuses for passed pawns.
175
- // We don't use a Score because we process the two components independently.
176
- const Value Passed[][RANK_NB] = {
177
- { V(5), V( 5), V(31), V(73), V(166), V(252) },
178
- { V(7), V(14), V(38), V(73), V(166), V(252) }
179
- };
180
-
181
- // PassedFile[File] contains a bonus according to the file of a passed pawn
182
- const Score PassedFile[FILE_NB] = {
183
- S( 9, 10), S( 2, 10), S( 1, -8), S(-20,-12),
184
- S(-20,-12), S( 1, -8), S( 2, 10), S( 9, 10)
185
- };
186
-
187
- // Assorted bonuses and penalties used by evaluation
188
- const Score MinorBehindPawn = S(16, 0);
189
- const Score BishopPawns = S( 8, 12);
190
- const Score RookOnPawn = S( 8, 24);
191
- const Score TrappedRook = S(92, 0);
192
- const Score CloseEnemies = S( 7, 0);
193
- const Score SafeCheck = S(20, 20);
194
- const Score OtherCheck = S(10, 10);
195
- const Score ThreatByHangingPawn = S(71, 61);
196
- const Score LooseEnemies = S( 0, 25);
197
- const Score WeakQueen = S(35, 0);
198
- const Score Hanging = S(48, 27);
199
- const Score ThreatByPawnPush = S(38, 22);
200
- const Score Unstoppable = S( 0, 20);
201
- const Score PawnlessFlank = S(20, 80);
202
- const Score HinderPassedPawn = S( 7, 0);
203
-
204
- // Penalty for a bishop on a1/h1 (a8/h8 for black) which is trapped by
205
- // a friendly pawn on b2/g2 (b7/g7 for black). This can obviously only
206
- // happen in Chess960 games.
207
- const Score TrappedBishopA1H1 = S(50, 50);
208
-
209
- #undef S
210
- #undef V
211
-
212
- // KingAttackWeights[PieceType] contains king attack weights by piece type
213
- const int KingAttackWeights[PIECE_TYPE_NB] = { 0, 0, 78, 56, 45, 11 };
214
-
215
- // Penalties for enemy's safe checks
216
- const int QueenContactCheck = 997;
217
- const int QueenCheck = 695;
218
- const int RookCheck = 638;
219
- const int BishopCheck = 538;
220
- const int KnightCheck = 874;
221
-
222
-
223
- // eval_init() initializes king and attack bitboards for a given color
224
- // adding pawn attacks. To be done at the beginning of the evaluation.
225
-
226
- template<Color Us>
227
- void eval_init(const Position& pos, EvalInfo& ei) {
228
-
229
- const Color Them = (Us == WHITE ? BLACK : WHITE);
230
- const Square Down = (Us == WHITE ? SOUTH : NORTH);
231
-
232
- ei.pinnedPieces[Us] = pos.pinned_pieces(Us);
233
- Bitboard b = ei.attackedBy[Them][KING];
234
- ei.attackedBy[Them][ALL_PIECES] |= b;
235
- ei.attackedBy[Us][ALL_PIECES] |= ei.attackedBy[Us][PAWN] = ei.pi->pawn_attacks(Us);
236
- ei.attackedBy2[Us] = ei.attackedBy[Us][PAWN] & ei.attackedBy[Us][KING];
237
-
238
- // Init king safety tables only if we are going to use them
239
- if (pos.non_pawn_material(Us) >= QueenValueMg)
240
- {
241
- ei.kingRing[Them] = b | shift<Down>(b);
242
- b &= ei.attackedBy[Us][PAWN];
243
- ei.kingAttackersCount[Us] = popcount(b);
244
- ei.kingAdjacentZoneAttacksCount[Us] = ei.kingAttackersWeight[Us] = 0;
245
- }
246
- else
247
- ei.kingRing[Them] = ei.kingAttackersCount[Us] = 0;
248
- }
249
-
250
-
251
- // evaluate_pieces() assigns bonuses and penalties to the pieces of a given
252
- // color and type.
253
-
254
- template<bool DoTrace, Color Us = WHITE, PieceType Pt = KNIGHT>
255
- Score evaluate_pieces(const Position& pos, EvalInfo& ei, Score* mobility,
256
- const Bitboard* mobilityArea) {
257
- Bitboard b, bb;
258
- Square s;
259
- Score score = SCORE_ZERO;
260
-
261
- const PieceType NextPt = (Us == WHITE ? Pt : PieceType(Pt + 1));
262
- const Color Them = (Us == WHITE ? BLACK : WHITE);
263
- const Bitboard OutpostRanks = (Us == WHITE ? Rank4BB | Rank5BB | Rank6BB
264
- : Rank5BB | Rank4BB | Rank3BB);
265
- const Square* pl = pos.squares<Pt>(Us);
266
-
267
- ei.attackedBy[Us][Pt] = 0;
268
-
269
- while ((s = *pl++) != SQ_NONE)
270
- {
271
- // Find attacked squares, including x-ray attacks for bishops and rooks
272
- b = Pt == BISHOP ? attacks_bb<BISHOP>(s, pos.pieces() ^ pos.pieces(Us, QUEEN))
273
- : Pt == ROOK ? attacks_bb< ROOK>(s, pos.pieces() ^ pos.pieces(Us, ROOK, QUEEN))
274
- : pos.attacks_from<Pt>(s);
275
-
276
- if (ei.pinnedPieces[Us] & s)
277
- b &= LineBB[pos.square<KING>(Us)][s];
278
-
279
- ei.attackedBy2[Us] |= ei.attackedBy[Us][ALL_PIECES] & b;
280
- ei.attackedBy[Us][ALL_PIECES] |= ei.attackedBy[Us][Pt] |= b;
281
-
282
- if (b & ei.kingRing[Them])
283
- {
284
- ei.kingAttackersCount[Us]++;
285
- ei.kingAttackersWeight[Us] += KingAttackWeights[Pt];
286
- ei.kingAdjacentZoneAttacksCount[Us] += popcount(b & ei.attackedBy[Them][KING]);
287
- }
288
-
289
- if (Pt == QUEEN)
290
- b &= ~( ei.attackedBy[Them][KNIGHT]
291
- | ei.attackedBy[Them][BISHOP]
292
- | ei.attackedBy[Them][ROOK]);
293
-
294
- int mob = popcount(b & mobilityArea[Us]);
295
-
296
- mobility[Us] += MobilityBonus[Pt][mob];
297
-
298
- if (Pt == BISHOP || Pt == KNIGHT)
299
- {
300
- // Bonus for outpost squares
301
- bb = OutpostRanks & ~ei.pi->pawn_attacks_span(Them);
302
- if (bb & s)
303
- score += Outpost[Pt == BISHOP][!!(ei.attackedBy[Us][PAWN] & s)];
304
- else
305
- {
306
- bb &= b & ~pos.pieces(Us);
307
- if (bb)
308
- score += ReachableOutpost[Pt == BISHOP][!!(ei.attackedBy[Us][PAWN] & bb)];
309
- }
310
-
311
- // Bonus when behind a pawn
312
- if ( relative_rank(Us, s) < RANK_5
313
- && (pos.pieces(PAWN) & (s + pawn_push(Us))))
314
- score += MinorBehindPawn;
315
-
316
- // Penalty for pawns on the same color square as the bishop
317
- if (Pt == BISHOP)
318
- score -= BishopPawns * ei.pi->pawns_on_same_color_squares(Us, s);
319
-
320
- // An important Chess960 pattern: A cornered bishop blocked by a friendly
321
- // pawn diagonally in front of it is a very serious problem, especially
322
- // when that pawn is also blocked.
323
- if ( Pt == BISHOP
324
- && pos.is_chess960()
325
- && (s == relative_square(Us, SQ_A1) || s == relative_square(Us, SQ_H1)))
326
- {
327
- Square d = pawn_push(Us) + (file_of(s) == FILE_A ? EAST : WEST);
328
- if (pos.piece_on(s + d) == make_piece(Us, PAWN))
329
- score -= !pos.empty(s + d + pawn_push(Us)) ? TrappedBishopA1H1 * 4
330
- : pos.piece_on(s + d + d) == make_piece(Us, PAWN) ? TrappedBishopA1H1 * 2
331
- : TrappedBishopA1H1;
332
- }
333
- }
334
-
335
- if (Pt == ROOK)
336
- {
337
- // Bonus for aligning with enemy pawns on the same rank/file
338
- if (relative_rank(Us, s) >= RANK_5)
339
- score += RookOnPawn * popcount(pos.pieces(Them, PAWN) & PseudoAttacks[ROOK][s]);
340
-
341
- // Bonus when on an open or semi-open file
342
- if (ei.pi->semiopen_file(Us, file_of(s)))
343
- score += RookOnFile[!!ei.pi->semiopen_file(Them, file_of(s))];
344
-
345
- // Penalize when trapped by the king, even more if the king cannot castle
346
- else if (mob <= 3)
347
- {
348
- Square ksq = pos.square<KING>(Us);
349
-
350
- if ( ((file_of(ksq) < FILE_E) == (file_of(s) < file_of(ksq)))
351
- && (rank_of(ksq) == rank_of(s) || relative_rank(Us, ksq) == RANK_1)
352
- && !ei.pi->semiopen_side(Us, file_of(ksq), file_of(s) < file_of(ksq)))
353
- score -= (TrappedRook - make_score(mob * 22, 0)) * (1 + !pos.can_castle(Us));
354
- }
355
- }
356
-
357
- if (Pt == QUEEN)
358
- {
359
- // Penalty if any relative pin or discovered attack against the queen
360
- Bitboard pinners;
361
- if (pos.slider_blockers(pos.pieces(Them, ROOK, BISHOP), s, pinners))
362
- score -= WeakQueen;
363
- }
364
- }
365
-
366
- if (DoTrace)
367
- Trace::add(Pt, Us, score);
368
-
369
- // Recursively call evaluate_pieces() of next piece type until KING is excluded
370
- return score - evaluate_pieces<DoTrace, Them, NextPt>(pos, ei, mobility, mobilityArea);
371
- }
372
-
373
- template<>
374
- Score evaluate_pieces<false, WHITE, KING>(const Position&, EvalInfo&, Score*, const Bitboard*) { return SCORE_ZERO; }
375
- template<>
376
- Score evaluate_pieces< true, WHITE, KING>(const Position&, EvalInfo&, Score*, const Bitboard*) { return SCORE_ZERO; }
377
-
378
-
379
- // evaluate_king() assigns bonuses and penalties to a king of a given color
380
-
381
- const Bitboard WhiteCamp = Rank1BB | Rank2BB | Rank3BB | Rank4BB | Rank5BB;
382
- const Bitboard BlackCamp = Rank8BB | Rank7BB | Rank6BB | Rank5BB | Rank4BB;
383
- const Bitboard QueenSide = FileABB | FileBBB | FileCBB | FileDBB;
384
- const Bitboard CenterFiles = FileCBB | FileDBB | FileEBB | FileFBB;
385
- const Bitboard KingSide = FileEBB | FileFBB | FileGBB | FileHBB;
386
-
387
- const Bitboard KingFlank[COLOR_NB][FILE_NB] = {
388
- { QueenSide & WhiteCamp, QueenSide & WhiteCamp, QueenSide & WhiteCamp, CenterFiles & WhiteCamp,
389
- CenterFiles & WhiteCamp, KingSide & WhiteCamp, KingSide & WhiteCamp, KingSide & WhiteCamp },
390
- { QueenSide & BlackCamp, QueenSide & BlackCamp, QueenSide & BlackCamp, CenterFiles & BlackCamp,
391
- CenterFiles & BlackCamp, KingSide & BlackCamp, KingSide & BlackCamp, KingSide & BlackCamp },
392
- };
393
-
394
- template<Color Us, bool DoTrace>
395
- Score evaluate_king(const Position& pos, const EvalInfo& ei) {
396
-
397
- const Color Them = (Us == WHITE ? BLACK : WHITE);
398
- const Square Up = (Us == WHITE ? NORTH : SOUTH);
399
-
400
- Bitboard undefended, b, b1, b2, safe, other;
401
- int kingDanger;
402
- const Square ksq = pos.square<KING>(Us);
403
-
404
- // King shelter and enemy pawns storm
405
- Score score = ei.pi->king_safety<Us>(pos, ksq);
406
-
407
- // Main king safety evaluation
408
- if (ei.kingAttackersCount[Them])
409
- {
410
- // Find the attacked squares which are defended only by the king...
411
- undefended = ei.attackedBy[Them][ALL_PIECES]
412
- & ei.attackedBy[Us][KING]
413
- & ~ei.attackedBy2[Us];
414
-
415
- // ... and those which are not defended at all in the larger king ring
416
- b = ei.attackedBy[Them][ALL_PIECES] & ~ei.attackedBy[Us][ALL_PIECES]
417
- & ei.kingRing[Us] & ~pos.pieces(Them);
418
-
419
- // Initialize the 'kingDanger' variable, which will be transformed
420
- // later into a king danger score. The initial value is based on the
421
- // number and types of the enemy's attacking pieces, the number of
422
- // attacked and undefended squares around our king and the quality of
423
- // the pawn shelter (current 'score' value).
424
- kingDanger = std::min(807, ei.kingAttackersCount[Them] * ei.kingAttackersWeight[Them])
425
- + 101 * ei.kingAdjacentZoneAttacksCount[Them]
426
- + 235 * popcount(undefended)
427
- + 134 * (popcount(b) + !!ei.pinnedPieces[Us])
428
- - 717 * !pos.count<QUEEN>(Them)
429
- - 7 * mg_value(score) / 5 - 5;
430
-
431
- // Analyse the enemy's safe queen contact checks. Firstly, find the
432
- // undefended squares around the king reachable by the enemy queen...
433
- b = undefended & ei.attackedBy[Them][QUEEN] & ~pos.pieces(Them);
434
-
435
- // ...and keep squares supported by another enemy piece
436
- kingDanger += QueenContactCheck * popcount(b & ei.attackedBy2[Them]);
437
-
438
- // Analyse the safe enemy's checks which are possible on next move...
439
- safe = ~(ei.attackedBy[Us][ALL_PIECES] | pos.pieces(Them));
440
-
441
- // ... and some other potential checks, only requiring the square to be
442
- // safe from pawn-attacks, and not being occupied by a blocked pawn.
443
- other = ~( ei.attackedBy[Us][PAWN]
444
- | (pos.pieces(Them, PAWN) & shift<Up>(pos.pieces(PAWN))));
445
-
446
- b1 = pos.attacks_from<ROOK >(ksq);
447
- b2 = pos.attacks_from<BISHOP>(ksq);
448
-
449
- // Enemy queen safe checks
450
- if ((b1 | b2) & ei.attackedBy[Them][QUEEN] & safe)
451
- kingDanger += QueenCheck, score -= SafeCheck;
452
-
453
- // For other pieces, also consider the square safe if attacked twice,
454
- // and only defended by a queen.
455
- safe |= ei.attackedBy2[Them]
456
- & ~(ei.attackedBy2[Us] | pos.pieces(Them))
457
- & ei.attackedBy[Us][QUEEN];
458
-
459
- // Enemy rooks safe and other checks
460
- if (b1 & ei.attackedBy[Them][ROOK] & safe)
461
- kingDanger += RookCheck, score -= SafeCheck;
462
-
463
- else if (b1 & ei.attackedBy[Them][ROOK] & other)
464
- score -= OtherCheck;
465
-
466
- // Enemy bishops safe and other checks
467
- if (b2 & ei.attackedBy[Them][BISHOP] & safe)
468
- kingDanger += BishopCheck, score -= SafeCheck;
469
-
470
- else if (b2 & ei.attackedBy[Them][BISHOP] & other)
471
- score -= OtherCheck;
472
-
473
- // Enemy knights safe and other checks
474
- b = pos.attacks_from<KNIGHT>(ksq) & ei.attackedBy[Them][KNIGHT];
475
- if (b & safe)
476
- kingDanger += KnightCheck, score -= SafeCheck;
477
-
478
- else if (b & other)
479
- score -= OtherCheck;
480
-
481
- // Compute the king danger score and subtract it from the evaluation
482
- if (kingDanger > 0)
483
- score -= make_score(std::min(kingDanger * kingDanger / 4096, 2 * int(BishopValueMg)), 0);
484
- }
485
-
486
- // King tropism: firstly, find squares that opponent attacks in our king flank
487
- File kf = file_of(ksq);
488
- b = ei.attackedBy[Them][ALL_PIECES] & KingFlank[Us][kf];
489
-
490
- assert(((Us == WHITE ? b << 4 : b >> 4) & b) == 0);
491
- assert(popcount(Us == WHITE ? b << 4 : b >> 4) == popcount(b));
492
-
493
- // Secondly, add the squares which are attacked twice in that flank and
494
- // which are not defended by our pawns.
495
- b = (Us == WHITE ? b << 4 : b >> 4)
496
- | (b & ei.attackedBy2[Them] & ~ei.attackedBy[Us][PAWN]);
497
-
498
- score -= CloseEnemies * popcount(b);
499
-
500
- // Penalty when our king is on a pawnless flank
501
- if (!(pos.pieces(PAWN) & (KingFlank[WHITE][kf] | KingFlank[BLACK][kf])))
502
- score -= PawnlessFlank;
503
-
504
- if (DoTrace)
505
- Trace::add(KING, Us, score);
506
-
507
- return score;
508
- }
509
-
510
-
511
- // evaluate_threats() assigns bonuses according to the types of the attacking
512
- // and the attacked pieces.
513
-
514
- template<Color Us, bool DoTrace>
515
- Score evaluate_threats(const Position& pos, const EvalInfo& ei) {
516
-
517
- const Color Them = (Us == WHITE ? BLACK : WHITE);
518
- const Square Up = (Us == WHITE ? NORTH : SOUTH);
519
- const Square Left = (Us == WHITE ? NORTH_WEST : SOUTH_EAST);
520
- const Square Right = (Us == WHITE ? NORTH_EAST : SOUTH_WEST);
521
- const Bitboard TRank2BB = (Us == WHITE ? Rank2BB : Rank7BB);
522
- const Bitboard TRank7BB = (Us == WHITE ? Rank7BB : Rank2BB);
523
-
524
- enum { Minor, Rook };
525
-
526
- Bitboard b, weak, defended, safeThreats;
527
- Score score = SCORE_ZERO;
528
-
529
- // Small bonus if the opponent has loose pawns or pieces
530
- if ( (pos.pieces(Them) ^ pos.pieces(Them, QUEEN, KING))
531
- & ~(ei.attackedBy[Us][ALL_PIECES] | ei.attackedBy[Them][ALL_PIECES]))
532
- score += LooseEnemies;
533
-
534
- // Non-pawn enemies attacked by a pawn
535
- weak = (pos.pieces(Them) ^ pos.pieces(Them, PAWN)) & ei.attackedBy[Us][PAWN];
536
-
537
- if (weak)
538
- {
539
- b = pos.pieces(Us, PAWN) & ( ~ei.attackedBy[Them][ALL_PIECES]
540
- | ei.attackedBy[Us][ALL_PIECES]);
541
-
542
- safeThreats = (shift<Right>(b) | shift<Left>(b)) & weak;
543
-
544
- if (weak ^ safeThreats)
545
- score += ThreatByHangingPawn;
546
-
547
- while (safeThreats)
548
- score += ThreatBySafePawn[type_of(pos.piece_on(pop_lsb(&safeThreats)))];
549
- }
550
-
551
- // Non-pawn enemies defended by a pawn
552
- defended = (pos.pieces(Them) ^ pos.pieces(Them, PAWN)) & ei.attackedBy[Them][PAWN];
553
-
554
- // Enemies not defended by a pawn and under our attack
555
- weak = pos.pieces(Them)
556
- & ~ei.attackedBy[Them][PAWN]
557
- & ei.attackedBy[Us][ALL_PIECES];
558
-
559
- // Add a bonus according to the kind of attacking pieces
560
- if (defended | weak)
561
- {
562
- b = (defended | weak) & (ei.attackedBy[Us][KNIGHT] | ei.attackedBy[Us][BISHOP]);
563
- while (b)
564
- score += Threat[Minor][type_of(pos.piece_on(pop_lsb(&b)))];
565
-
566
- b = (pos.pieces(Them, QUEEN) | weak) & ei.attackedBy[Us][ROOK];
567
- while (b)
568
- score += Threat[Rook ][type_of(pos.piece_on(pop_lsb(&b)))];
569
-
570
- score += Hanging * popcount(weak & ~ei.attackedBy[Them][ALL_PIECES]);
571
-
572
- b = weak & ei.attackedBy[Us][KING];
573
- if (b)
574
- score += ThreatByKing[more_than_one(b)];
575
- }
576
-
577
- // Bonus if some pawns can safely push and attack an enemy piece
578
- b = pos.pieces(Us, PAWN) & ~TRank7BB;
579
- b = shift<Up>(b | (shift<Up>(b & TRank2BB) & ~pos.pieces()));
580
-
581
- b &= ~pos.pieces()
582
- & ~ei.attackedBy[Them][PAWN]
583
- & (ei.attackedBy[Us][ALL_PIECES] | ~ei.attackedBy[Them][ALL_PIECES]);
584
-
585
- b = (shift<Left>(b) | shift<Right>(b))
586
- & pos.pieces(Them)
587
- & ~ei.attackedBy[Us][PAWN];
588
-
589
- score += ThreatByPawnPush * popcount(b);
590
-
591
- if (DoTrace)
592
- Trace::add(THREAT, Us, score);
593
-
594
- return score;
595
- }
596
-
597
-
598
- // evaluate_passed_pawns() evaluates the passed pawns of the given color
599
-
600
- template<Color Us, bool DoTrace>
601
- Score evaluate_passed_pawns(const Position& pos, const EvalInfo& ei) {
602
-
603
- const Color Them = (Us == WHITE ? BLACK : WHITE);
604
-
605
- Bitboard b, bb, squaresToQueen, defendedSquares, unsafeSquares;
606
- Score score = SCORE_ZERO;
607
-
608
- b = ei.pi->passed_pawns(Us);
609
-
610
- while (b)
611
- {
612
- Square s = pop_lsb(&b);
613
-
614
- assert(pos.pawn_passed(Us, s));
615
- assert(!(pos.pieces(PAWN) & forward_bb(Us, s)));
616
-
617
- bb = forward_bb(Us, s) & (ei.attackedBy[Them][ALL_PIECES] | pos.pieces(Them));
618
- score -= HinderPassedPawn * popcount(bb);
619
-
620
- int r = relative_rank(Us, s) - RANK_2;
621
- int rr = r * (r - 1);
622
-
623
- Value mbonus = Passed[MG][r], ebonus = Passed[EG][r];
624
-
625
- if (rr)
626
- {
627
- Square blockSq = s + pawn_push(Us);
628
-
629
- // Adjust bonus based on the king's proximity
630
- ebonus += distance(pos.square<KING>(Them), blockSq) * 5 * rr
631
- - distance(pos.square<KING>(Us ), blockSq) * 2 * rr;
632
-
633
- // If blockSq is not the queening square then consider also a second push
634
- if (relative_rank(Us, blockSq) != RANK_8)
635
- ebonus -= distance(pos.square<KING>(Us), blockSq + pawn_push(Us)) * rr;
636
-
637
- // If the pawn is free to advance, then increase the bonus
638
- if (pos.empty(blockSq))
639
- {
640
- // If there is a rook or queen attacking/defending the pawn from behind,
641
- // consider all the squaresToQueen. Otherwise consider only the squares
642
- // in the pawn's path attacked or occupied by the enemy.
643
- defendedSquares = unsafeSquares = squaresToQueen = forward_bb(Us, s);
644
-
645
- bb = forward_bb(Them, s) & pos.pieces(ROOK, QUEEN) & pos.attacks_from<ROOK>(s);
646
-
647
- if (!(pos.pieces(Us) & bb))
648
- defendedSquares &= ei.attackedBy[Us][ALL_PIECES];
649
-
650
- if (!(pos.pieces(Them) & bb))
651
- unsafeSquares &= ei.attackedBy[Them][ALL_PIECES] | pos.pieces(Them);
652
-
653
- // If there aren't any enemy attacks, assign a big bonus. Otherwise
654
- // assign a smaller bonus if the block square isn't attacked.
655
- int k = !unsafeSquares ? 18 : !(unsafeSquares & blockSq) ? 8 : 0;
656
-
657
- // If the path to the queen is fully defended, assign a big bonus.
658
- // Otherwise assign a smaller bonus if the block square is defended.
659
- if (defendedSquares == squaresToQueen)
660
- k += 6;
661
-
662
- else if (defendedSquares & blockSq)
663
- k += 4;
664
-
665
- mbonus += k * rr, ebonus += k * rr;
666
- }
667
- else if (pos.pieces(Us) & blockSq)
668
- mbonus += rr + r * 2, ebonus += rr + r * 2;
669
- } // rr != 0
670
-
671
- score += make_score(mbonus, ebonus) + PassedFile[file_of(s)];
672
- }
673
-
674
- if (DoTrace)
675
- Trace::add(PASSED, Us, score);
676
-
677
- // Add the scores to the middlegame and endgame eval
678
- return score;
679
- }
680
-
681
-
682
- // evaluate_space() computes the space evaluation for a given side. The
683
- // space evaluation is a simple bonus based on the number of safe squares
684
- // available for minor pieces on the central four files on ranks 2--4. Safe
685
- // squares one, two or three squares behind a friendly pawn are counted
686
- // twice. Finally, the space bonus is multiplied by a weight. The aim is to
687
- // improve play on game opening.
688
- template<Color Us>
689
- Score evaluate_space(const Position& pos, const EvalInfo& ei) {
690
-
691
- const Color Them = (Us == WHITE ? BLACK : WHITE);
692
- const Bitboard SpaceMask =
693
- Us == WHITE ? (FileCBB | FileDBB | FileEBB | FileFBB) & (Rank2BB | Rank3BB | Rank4BB)
694
- : (FileCBB | FileDBB | FileEBB | FileFBB) & (Rank7BB | Rank6BB | Rank5BB);
695
-
696
- // Find the safe squares for our pieces inside the area defined by
697
- // SpaceMask. A square is unsafe if it is attacked by an enemy
698
- // pawn, or if it is undefended and attacked by an enemy piece.
699
- Bitboard safe = SpaceMask
700
- & ~pos.pieces(Us, PAWN)
701
- & ~ei.attackedBy[Them][PAWN]
702
- & (ei.attackedBy[Us][ALL_PIECES] | ~ei.attackedBy[Them][ALL_PIECES]);
703
-
704
- // Find all squares which are at most three squares behind some friendly pawn
705
- Bitboard behind = pos.pieces(Us, PAWN);
706
- behind |= (Us == WHITE ? behind >> 8 : behind << 8);
707
- behind |= (Us == WHITE ? behind >> 16 : behind << 16);
708
-
709
- // Since SpaceMask[Us] is fully on our half of the board...
710
- assert(unsigned(safe >> (Us == WHITE ? 32 : 0)) == 0);
711
-
712
- // ...count safe + (behind & safe) with a single popcount
713
- int bonus = popcount((Us == WHITE ? safe << 32 : safe >> 32) | (behind & safe));
714
- bonus = std::min(16, bonus);
715
- int weight = pos.count<ALL_PIECES>(Us) - 2 * ei.pi->open_files();
716
-
717
- return make_score(bonus * weight * weight / 18, 0);
718
- }
719
-
720
-
721
- // evaluate_initiative() computes the initiative correction value for the
722
- // position, i.e., second order bonus/malus based on the known attacking/defending
723
- // status of the players.
724
- Score evaluate_initiative(const Position& pos, int asymmetry, Value eg) {
725
-
726
- int kingDistance = distance<File>(pos.square<KING>(WHITE), pos.square<KING>(BLACK))
727
- - distance<Rank>(pos.square<KING>(WHITE), pos.square<KING>(BLACK));
728
- int pawns = pos.count<PAWN>(WHITE) + pos.count<PAWN>(BLACK);
729
-
730
- // Compute the initiative bonus for the attacking side
731
- int initiative = 8 * (asymmetry + kingDistance - 15) + 12 * pawns;
732
-
733
- // Now apply the bonus: note that we find the attacking side by extracting
734
- // the sign of the endgame value, and that we carefully cap the bonus so
735
- // that the endgame score will never be divided by more than two.
736
- int value = ((eg > 0) - (eg < 0)) * std::max(initiative, -abs(eg / 2));
737
-
738
- return make_score(0, value);
739
- }
740
-
741
-
742
- // evaluate_scale_factor() computes the scale factor for the winning side
743
- ScaleFactor evaluate_scale_factor(const Position& pos, const EvalInfo& ei, Value eg) {
744
-
745
- Color strongSide = eg > VALUE_DRAW ? WHITE : BLACK;
746
- ScaleFactor sf = ei.me->scale_factor(pos, strongSide);
747
-
748
- // If we don't already have an unusual scale factor, check for certain
749
- // types of endgames, and use a lower scale for those.
750
- if ( ei.me->game_phase() < PHASE_MIDGAME
751
- && (sf == SCALE_FACTOR_NORMAL || sf == SCALE_FACTOR_ONEPAWN))
752
- {
753
- if (pos.opposite_bishops())
754
- {
755
- // Endgame with opposite-colored bishops and no other pieces (ignoring pawns)
756
- // is almost a draw, in case of KBP vs KB, it is even more a draw.
757
- if ( pos.non_pawn_material(WHITE) == BishopValueMg
758
- && pos.non_pawn_material(BLACK) == BishopValueMg)
759
- sf = more_than_one(pos.pieces(PAWN)) ? ScaleFactor(31) : ScaleFactor(9);
760
-
761
- // Endgame with opposite-colored bishops, but also other pieces. Still
762
- // a bit drawish, but not as drawish as with only the two bishops.
763
- else
764
- sf = ScaleFactor(46);
765
- }
766
- // Endings where weaker side can place his king in front of the opponent's
767
- // pawns are drawish.
768
- else if ( abs(eg) <= BishopValueEg
769
- && pos.count<PAWN>(strongSide) <= 2
770
- && !pos.pawn_passed(~strongSide, pos.square<KING>(~strongSide)))
771
- sf = ScaleFactor(37 + 7 * pos.count<PAWN>(strongSide));
772
- }
773
-
774
- return sf;
775
- }
776
-
777
- } // namespace
778
-
779
-
780
- /// evaluate() is the main evaluation function. It returns a static evaluation
781
- /// of the position from the point of view of the side to move.
782
-
783
- template<bool DoTrace>
784
- Value Eval::evaluate(const Position& pos) {
785
-
786
- assert(!pos.checkers());
787
-
788
- Score mobility[COLOR_NB] = { SCORE_ZERO, SCORE_ZERO };
789
- EvalInfo ei;
790
-
791
- // Probe the material hash table
792
- ei.me = Material::probe(pos);
793
-
794
- // If we have a specialized evaluation function for the current material
795
- // configuration, call it and return.
796
- if (ei.me->specialized_eval_exists())
797
- return ei.me->evaluate(pos);
798
-
799
- // Initialize score by reading the incrementally updated scores included in
800
- // the position object (material + piece square tables) and the material
801
- // imbalance. Score is computed internally from the white point of view.
802
- Score score = pos.psq_score() + ei.me->imbalance();
803
-
804
- // Probe the pawn hash table
805
- ei.pi = Pawns::probe(pos);
806
- score += ei.pi->pawns_score();
807
-
808
- // Initialize attack and king safety bitboards
809
- ei.attackedBy[WHITE][ALL_PIECES] = ei.attackedBy[BLACK][ALL_PIECES] = 0;
810
- ei.attackedBy[WHITE][KING] = pos.attacks_from<KING>(pos.square<KING>(WHITE));
811
- ei.attackedBy[BLACK][KING] = pos.attacks_from<KING>(pos.square<KING>(BLACK));
812
- eval_init<WHITE>(pos, ei);
813
- eval_init<BLACK>(pos, ei);
814
-
815
- // Pawns blocked or on ranks 2 and 3 will be excluded from the mobility area
816
- Bitboard blockedPawns[] = {
817
- pos.pieces(WHITE, PAWN) & (shift<SOUTH>(pos.pieces()) | Rank2BB | Rank3BB),
818
- pos.pieces(BLACK, PAWN) & (shift<NORTH>(pos.pieces()) | Rank7BB | Rank6BB)
819
- };
820
-
821
- // Do not include in mobility area squares protected by enemy pawns, or occupied
822
- // by our blocked pawns or king.
823
- Bitboard mobilityArea[] = {
824
- ~(ei.attackedBy[BLACK][PAWN] | blockedPawns[WHITE] | pos.square<KING>(WHITE)),
825
- ~(ei.attackedBy[WHITE][PAWN] | blockedPawns[BLACK] | pos.square<KING>(BLACK))
826
- };
827
-
828
- // Evaluate all pieces but king and pawns
829
- score += evaluate_pieces<DoTrace>(pos, ei, mobility, mobilityArea);
830
- score += mobility[WHITE] - mobility[BLACK];
831
-
832
- // Evaluate kings after all other pieces because we need full attack
833
- // information when computing the king safety evaluation.
834
- score += evaluate_king<WHITE, DoTrace>(pos, ei)
835
- - evaluate_king<BLACK, DoTrace>(pos, ei);
836
-
837
- // Evaluate tactical threats, we need full attack information including king
838
- score += evaluate_threats<WHITE, DoTrace>(pos, ei)
839
- - evaluate_threats<BLACK, DoTrace>(pos, ei);
840
-
841
- // Evaluate passed pawns, we need full attack information including king
842
- score += evaluate_passed_pawns<WHITE, DoTrace>(pos, ei)
843
- - evaluate_passed_pawns<BLACK, DoTrace>(pos, ei);
844
-
845
- // If both sides have only pawns, score for potential unstoppable pawns
846
- if (!pos.non_pawn_material(WHITE) && !pos.non_pawn_material(BLACK))
847
- {
848
- Bitboard b;
849
- if ((b = ei.pi->passed_pawns(WHITE)) != 0)
850
- score += Unstoppable * int(relative_rank(WHITE, frontmost_sq(WHITE, b)));
851
-
852
- if ((b = ei.pi->passed_pawns(BLACK)) != 0)
853
- score -= Unstoppable * int(relative_rank(BLACK, frontmost_sq(BLACK, b)));
854
- }
855
-
856
- // Evaluate space for both sides, only during opening
857
- if (pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK) >= 12222)
858
- score += evaluate_space<WHITE>(pos, ei)
859
- - evaluate_space<BLACK>(pos, ei);
860
-
861
- // Evaluate position potential for the winning side
862
- score += evaluate_initiative(pos, ei.pi->pawn_asymmetry(), eg_value(score));
863
-
864
- // Evaluate scale factor for the winning side
865
- ScaleFactor sf = evaluate_scale_factor(pos, ei, eg_value(score));
866
-
867
- // Interpolate between a middlegame and a (scaled by 'sf') endgame score
868
- Value v = mg_value(score) * int(ei.me->game_phase())
869
- + eg_value(score) * int(PHASE_MIDGAME - ei.me->game_phase()) * sf / SCALE_FACTOR_NORMAL;
870
-
871
- v /= int(PHASE_MIDGAME);
872
-
873
- // In case of tracing add all remaining individual evaluation terms
874
- if (DoTrace)
875
- {
876
- Trace::add(MATERIAL, pos.psq_score());
877
- Trace::add(IMBALANCE, ei.me->imbalance());
878
- Trace::add(PAWN, ei.pi->pawns_score());
879
- Trace::add(MOBILITY, mobility[WHITE], mobility[BLACK]);
880
- Trace::add(SPACE, evaluate_space<WHITE>(pos, ei)
881
- , evaluate_space<BLACK>(pos, ei));
882
- Trace::add(TOTAL, score);
883
- }
884
-
885
- return (pos.side_to_move() == WHITE ? v : -v) + Eval::Tempo; // Side to move point of view
886
- }
887
-
888
- // Explicit template instantiations
889
- template Value Eval::evaluate<true >(const Position&);
890
- template Value Eval::evaluate<false>(const Position&);
891
-
892
-
893
- /// trace() is like evaluate(), but instead of returning a value, it returns
894
- /// a string (suitable for outputting to stdout) that contains the detailed
895
- /// descriptions and values of each evaluation term. Useful for debugging.
896
-
897
- std::string Eval::trace(const Position& pos) {
898
-
899
- std::memset(scores, 0, sizeof(scores));
900
-
901
- Value v = evaluate<true>(pos);
902
- v = pos.side_to_move() == WHITE ? v : -v; // White's point of view
903
-
904
- std::stringstream ss;
905
- ss << std::showpoint << std::noshowpos << std::fixed << std::setprecision(2)
906
- << " Eval term | White | Black | Total \n"
907
- << " | MG EG | MG EG | MG EG \n"
908
- << "----------------+-------------+-------------+-------------\n"
909
- << " Material | " << Term(MATERIAL)
910
- << " Imbalance | " << Term(IMBALANCE)
911
- << " Pawns | " << Term(PAWN)
912
- << " Knights | " << Term(KNIGHT)
913
- << " Bishop | " << Term(BISHOP)
914
- << " Rooks | " << Term(ROOK)
915
- << " Queens | " << Term(QUEEN)
916
- << " Mobility | " << Term(MOBILITY)
917
- << " King safety | " << Term(KING)
918
- << " Threats | " << Term(THREAT)
919
- << " Passed pawns | " << Term(PASSED)
920
- << " Space | " << Term(SPACE)
921
- << "----------------+-------------+-------------+-------------\n"
922
- << " Total | " << Term(TOTAL);
923
-
924
- ss << "\nTotal Evaluation: " << to_cp(v) << " (white side)\n";
925
-
926
- return ss.str();
927
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/evaluate.h DELETED
@@ -1,40 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #ifndef EVALUATE_H_INCLUDED
22
- #define EVALUATE_H_INCLUDED
23
-
24
- #include <string>
25
-
26
- #include "types.h"
27
-
28
- class Position;
29
-
30
- namespace Eval {
31
-
32
- const Value Tempo = Value(20); // Must be visible to search
33
-
34
- std::string trace(const Position& pos);
35
-
36
- template<bool DoTrace = false>
37
- Value evaluate(const Position& pos);
38
- }
39
-
40
- #endif // #ifndef EVALUATE_H_INCLUDED
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/main.cpp DELETED
@@ -1,54 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #include <iostream>
22
-
23
- #include "bitboard.h"
24
- #include "position.h"
25
- #include "search.h"
26
- #include "thread.h"
27
- #include "tt.h"
28
- #include "uci.h"
29
- #include "syzygy/tbprobe.h"
30
-
31
- namespace PSQT {
32
- void init();
33
- }
34
-
35
- int main(int argc, char* argv[]) {
36
-
37
- std::cout << engine_info() << std::endl;
38
-
39
- UCI::init(Options);
40
- PSQT::init();
41
- Bitboards::init();
42
- Position::init();
43
- Bitbases::init();
44
- Search::init();
45
- Pawns::init();
46
- Threads.init();
47
- Tablebases::init(Options["SyzygyPath"]);
48
- TT.resize(Options["Hash"]);
49
-
50
- UCI::loop(argc, argv);
51
-
52
- Threads.exit();
53
- return 0;
54
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/material.cpp DELETED
@@ -1,225 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #include <algorithm> // For std::min
22
- #include <cassert>
23
- #include <cstring> // For std::memset
24
-
25
- #include "material.h"
26
- #include "thread.h"
27
-
28
- using namespace std;
29
-
30
- namespace {
31
-
32
- // Polynomial material imbalance parameters
33
-
34
- const int QuadraticOurs[][PIECE_TYPE_NB] = {
35
- // OUR PIECES
36
- // pair pawn knight bishop rook queen
37
- {1667 }, // Bishop pair
38
- { 40, 2 }, // Pawn
39
- { 32, 255, -3 }, // Knight OUR PIECES
40
- { 0, 104, 4, 0 }, // Bishop
41
- { -26, -2, 47, 105, -149 }, // Rook
42
- {-185, 24, 122, 137, -134, 0 } // Queen
43
- };
44
-
45
- const int QuadraticTheirs[][PIECE_TYPE_NB] = {
46
- // THEIR PIECES
47
- // pair pawn knight bishop rook queen
48
- { 0 }, // Bishop pair
49
- { 36, 0 }, // Pawn
50
- { 9, 63, 0 }, // Knight OUR PIECES
51
- { 59, 65, 42, 0 }, // Bishop
52
- { 46, 39, 24, -24, 0 }, // Rook
53
- { 101, 100, -37, 141, 268, 0 } // Queen
54
- };
55
-
56
- // Endgame evaluation and scaling functions are accessed directly and not through
57
- // the function maps because they correspond to more than one material hash key.
58
- Endgame<KXK> EvaluateKXK[] = { Endgame<KXK>(WHITE), Endgame<KXK>(BLACK) };
59
-
60
- Endgame<KBPsK> ScaleKBPsK[] = { Endgame<KBPsK>(WHITE), Endgame<KBPsK>(BLACK) };
61
- Endgame<KQKRPs> ScaleKQKRPs[] = { Endgame<KQKRPs>(WHITE), Endgame<KQKRPs>(BLACK) };
62
- Endgame<KPsK> ScaleKPsK[] = { Endgame<KPsK>(WHITE), Endgame<KPsK>(BLACK) };
63
- Endgame<KPKP> ScaleKPKP[] = { Endgame<KPKP>(WHITE), Endgame<KPKP>(BLACK) };
64
-
65
- // Helper used to detect a given material distribution
66
- bool is_KXK(const Position& pos, Color us) {
67
- return !more_than_one(pos.pieces(~us))
68
- && pos.non_pawn_material(us) >= RookValueMg;
69
- }
70
-
71
- bool is_KBPsKs(const Position& pos, Color us) {
72
- return pos.non_pawn_material(us) == BishopValueMg
73
- && pos.count<BISHOP>(us) == 1
74
- && pos.count<PAWN >(us) >= 1;
75
- }
76
-
77
- bool is_KQKRPs(const Position& pos, Color us) {
78
- return !pos.count<PAWN>(us)
79
- && pos.non_pawn_material(us) == QueenValueMg
80
- && pos.count<QUEEN>(us) == 1
81
- && pos.count<ROOK>(~us) == 1
82
- && pos.count<PAWN>(~us) >= 1;
83
- }
84
-
85
- /// imbalance() calculates the imbalance by comparing the piece count of each
86
- /// piece type for both colors.
87
- template<Color Us>
88
- int imbalance(const int pieceCount[][PIECE_TYPE_NB]) {
89
-
90
- const Color Them = (Us == WHITE ? BLACK : WHITE);
91
-
92
- int bonus = 0;
93
-
94
- // Second-degree polynomial material imbalance by Tord Romstad
95
- for (int pt1 = NO_PIECE_TYPE; pt1 <= QUEEN; ++pt1)
96
- {
97
- if (!pieceCount[Us][pt1])
98
- continue;
99
-
100
- int v = 0;
101
-
102
- for (int pt2 = NO_PIECE_TYPE; pt2 <= pt1; ++pt2)
103
- v += QuadraticOurs[pt1][pt2] * pieceCount[Us][pt2]
104
- + QuadraticTheirs[pt1][pt2] * pieceCount[Them][pt2];
105
-
106
- bonus += pieceCount[Us][pt1] * v;
107
- }
108
-
109
- return bonus;
110
- }
111
-
112
- } // namespace
113
-
114
- namespace Material {
115
-
116
- /// Material::probe() looks up the current position's material configuration in
117
- /// the material hash table. It returns a pointer to the Entry if the position
118
- /// is found. Otherwise a new Entry is computed and stored there, so we don't
119
- /// have to recompute all when the same material configuration occurs again.
120
-
121
- Entry* probe(const Position& pos) {
122
-
123
- Key key = pos.material_key();
124
- Entry* e = pos.this_thread()->materialTable[key];
125
-
126
- if (e->key == key)
127
- return e;
128
-
129
- std::memset(e, 0, sizeof(Entry));
130
- e->key = key;
131
- e->factor[WHITE] = e->factor[BLACK] = (uint8_t)SCALE_FACTOR_NORMAL;
132
- e->gamePhase = pos.game_phase();
133
-
134
- // Let's look if we have a specialized evaluation function for this particular
135
- // material configuration. Firstly we look for a fixed configuration one, then
136
- // for a generic one if the previous search failed.
137
- if ((e->evaluationFunction = pos.this_thread()->endgames.probe<Value>(key)) != nullptr)
138
- return e;
139
-
140
- for (Color c = WHITE; c <= BLACK; ++c)
141
- if (is_KXK(pos, c))
142
- {
143
- e->evaluationFunction = &EvaluateKXK[c];
144
- return e;
145
- }
146
-
147
- // OK, we didn't find any special evaluation function for the current material
148
- // configuration. Is there a suitable specialized scaling function?
149
- EndgameBase<ScaleFactor>* sf;
150
-
151
- if ((sf = pos.this_thread()->endgames.probe<ScaleFactor>(key)) != nullptr)
152
- {
153
- e->scalingFunction[sf->strong_side()] = sf; // Only strong color assigned
154
- return e;
155
- }
156
-
157
- // We didn't find any specialized scaling function, so fall back on generic
158
- // ones that refer to more than one material distribution. Note that in this
159
- // case we don't return after setting the function.
160
- for (Color c = WHITE; c <= BLACK; ++c)
161
- {
162
- if (is_KBPsKs(pos, c))
163
- e->scalingFunction[c] = &ScaleKBPsK[c];
164
-
165
- else if (is_KQKRPs(pos, c))
166
- e->scalingFunction[c] = &ScaleKQKRPs[c];
167
- }
168
-
169
- Value npm_w = pos.non_pawn_material(WHITE);
170
- Value npm_b = pos.non_pawn_material(BLACK);
171
-
172
- if (npm_w + npm_b == VALUE_ZERO && pos.pieces(PAWN)) // Only pawns on the board
173
- {
174
- if (!pos.count<PAWN>(BLACK))
175
- {
176
- assert(pos.count<PAWN>(WHITE) >= 2);
177
-
178
- e->scalingFunction[WHITE] = &ScaleKPsK[WHITE];
179
- }
180
- else if (!pos.count<PAWN>(WHITE))
181
- {
182
- assert(pos.count<PAWN>(BLACK) >= 2);
183
-
184
- e->scalingFunction[BLACK] = &ScaleKPsK[BLACK];
185
- }
186
- else if (pos.count<PAWN>(WHITE) == 1 && pos.count<PAWN>(BLACK) == 1)
187
- {
188
- // This is a special case because we set scaling functions
189
- // for both colors instead of only one.
190
- e->scalingFunction[WHITE] = &ScaleKPKP[WHITE];
191
- e->scalingFunction[BLACK] = &ScaleKPKP[BLACK];
192
- }
193
- }
194
-
195
- // Zero or just one pawn makes it difficult to win, even with a small material
196
- // advantage. This catches some trivial draws like KK, KBK and KNK and gives a
197
- // drawish scale factor for cases such as KRKBP and KmmKm (except for KBBKN).
198
- if (!pos.count<PAWN>(WHITE) && npm_w - npm_b <= BishopValueMg)
199
- e->factor[WHITE] = uint8_t(npm_w < RookValueMg ? SCALE_FACTOR_DRAW :
200
- npm_b <= BishopValueMg ? 4 : 14);
201
-
202
- if (!pos.count<PAWN>(BLACK) && npm_b - npm_w <= BishopValueMg)
203
- e->factor[BLACK] = uint8_t(npm_b < RookValueMg ? SCALE_FACTOR_DRAW :
204
- npm_w <= BishopValueMg ? 4 : 14);
205
-
206
- if (pos.count<PAWN>(WHITE) == 1 && npm_w - npm_b <= BishopValueMg)
207
- e->factor[WHITE] = (uint8_t) SCALE_FACTOR_ONEPAWN;
208
-
209
- if (pos.count<PAWN>(BLACK) == 1 && npm_b - npm_w <= BishopValueMg)
210
- e->factor[BLACK] = (uint8_t) SCALE_FACTOR_ONEPAWN;
211
-
212
- // Evaluate the material imbalance. We use PIECE_TYPE_NONE as a place holder
213
- // for the bishop pair "extended piece", which allows us to be more flexible
214
- // in defining bishop pair bonuses.
215
- const int PieceCount[COLOR_NB][PIECE_TYPE_NB] = {
216
- { pos.count<BISHOP>(WHITE) > 1, pos.count<PAWN>(WHITE), pos.count<KNIGHT>(WHITE),
217
- pos.count<BISHOP>(WHITE) , pos.count<ROOK>(WHITE), pos.count<QUEEN >(WHITE) },
218
- { pos.count<BISHOP>(BLACK) > 1, pos.count<PAWN>(BLACK), pos.count<KNIGHT>(BLACK),
219
- pos.count<BISHOP>(BLACK) , pos.count<ROOK>(BLACK), pos.count<QUEEN >(BLACK) } };
220
-
221
- e->value = int16_t((imbalance<WHITE>(PieceCount) - imbalance<BLACK>(PieceCount)) / 16);
222
- return e;
223
- }
224
-
225
- } // namespace Material
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/material.h DELETED
@@ -1,73 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #ifndef MATERIAL_H_INCLUDED
22
- #define MATERIAL_H_INCLUDED
23
-
24
- #include "endgame.h"
25
- #include "misc.h"
26
- #include "position.h"
27
- #include "types.h"
28
-
29
- namespace Material {
30
-
31
- /// Material::Entry contains various information about a material configuration.
32
- /// It contains a material imbalance evaluation, a function pointer to a special
33
- /// endgame evaluation function (which in most cases is NULL, meaning that the
34
- /// standard evaluation function will be used), and scale factors.
35
- ///
36
- /// The scale factors are used to scale the evaluation score up or down. For
37
- /// instance, in KRB vs KR endgames, the score is scaled down by a factor of 4,
38
- /// which will result in scores of absolute value less than one pawn.
39
-
40
- struct Entry {
41
-
42
- Score imbalance() const { return make_score(value, value); }
43
- Phase game_phase() const { return gamePhase; }
44
- bool specialized_eval_exists() const { return evaluationFunction != nullptr; }
45
- Value evaluate(const Position& pos) const { return (*evaluationFunction)(pos); }
46
-
47
- // scale_factor takes a position and a color as input and returns a scale factor
48
- // for the given color. We have to provide the position in addition to the color
49
- // because the scale factor may also be a function which should be applied to
50
- // the position. For instance, in KBP vs K endgames, the scaling function looks
51
- // for rook pawns and wrong-colored bishops.
52
- ScaleFactor scale_factor(const Position& pos, Color c) const {
53
- ScaleFactor sf = scalingFunction[c] ? (*scalingFunction[c])(pos)
54
- : SCALE_FACTOR_NONE;
55
- return sf != SCALE_FACTOR_NONE ? sf : ScaleFactor(factor[c]);
56
- }
57
-
58
- Key key;
59
- int16_t value;
60
- uint8_t factor[COLOR_NB];
61
- EndgameBase<Value>* evaluationFunction;
62
- EndgameBase<ScaleFactor>* scalingFunction[COLOR_NB]; // Could be one for each
63
- // side (e.g. KPKP, KBPsKs)
64
- Phase gamePhase;
65
- };
66
-
67
- typedef HashTable<Entry, 8192> Table;
68
-
69
- Entry* probe(const Position& pos);
70
-
71
- } // namespace Material
72
-
73
- #endif // #ifndef MATERIAL_H_INCLUDED
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/misc.cpp DELETED
@@ -1,187 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #include <fstream>
22
- #include <iomanip>
23
- #include <iostream>
24
- #include <sstream>
25
-
26
- #include "misc.h"
27
- #include "thread.h"
28
-
29
- using namespace std;
30
-
31
- namespace {
32
-
33
- /// Version number. If Version is left empty, then compile date in the format
34
- /// DD-MM-YY and show in engine_info.
35
- const string Version = "8";
36
-
37
- /// Our fancy logging facility. The trick here is to replace cin.rdbuf() and
38
- /// cout.rdbuf() with two Tie objects that tie cin and cout to a file stream. We
39
- /// can toggle the logging of std::cout and std:cin at runtime whilst preserving
40
- /// usual I/O functionality, all without changing a single line of code!
41
- /// Idea from http://groups.google.com/group/comp.lang.c++/msg/1d941c0f26ea0d81
42
-
43
- struct Tie: public streambuf { // MSVC requires split streambuf for cin and cout
44
-
45
- Tie(streambuf* b, streambuf* l) : buf(b), logBuf(l) {}
46
-
47
- int sync() { return logBuf->pubsync(), buf->pubsync(); }
48
- int overflow(int c) { return log(buf->sputc((char)c), "<< "); }
49
- int underflow() { return buf->sgetc(); }
50
- int uflow() { return log(buf->sbumpc(), ">> "); }
51
-
52
- streambuf *buf, *logBuf;
53
-
54
- int log(int c, const char* prefix) {
55
-
56
- static int last = '\n'; // Single log file
57
-
58
- if (last == '\n')
59
- logBuf->sputn(prefix, 3);
60
-
61
- return last = logBuf->sputc((char)c);
62
- }
63
- };
64
-
65
- class Logger {
66
-
67
- Logger() : in(cin.rdbuf(), file.rdbuf()), out(cout.rdbuf(), file.rdbuf()) {}
68
- ~Logger() { start(""); }
69
-
70
- ofstream file;
71
- Tie in, out;
72
-
73
- public:
74
- static void start(const std::string& fname) {
75
-
76
- static Logger l;
77
-
78
- if (!fname.empty() && !l.file.is_open())
79
- {
80
- l.file.open(fname, ifstream::out);
81
- cin.rdbuf(&l.in);
82
- cout.rdbuf(&l.out);
83
- }
84
- else if (fname.empty() && l.file.is_open())
85
- {
86
- cout.rdbuf(l.out.buf);
87
- cin.rdbuf(l.in.buf);
88
- l.file.close();
89
- }
90
- }
91
- };
92
-
93
- } // namespace
94
-
95
- /// engine_info() returns the full name of the current Stockfish version. This
96
- /// will be either "Stockfish <Tag> DD-MM-YY" (where DD-MM-YY is the date when
97
- /// the program was compiled) or "Stockfish <Version>", depending on whether
98
- /// Version is empty.
99
-
100
- const string engine_info(bool to_uci) {
101
-
102
- const string months("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec");
103
- string month, day, year;
104
- stringstream ss, date(__DATE__); // From compiler, format is "Sep 21 2008"
105
-
106
- ss << "Stockfish " << Version << setfill('0');
107
-
108
- if (Version.empty())
109
- {
110
- date >> month >> day >> year;
111
- ss << setw(2) << day << setw(2) << (1 + months.find(month) / 4) << year.substr(2);
112
- }
113
-
114
- ss << (Is64Bit ? " 64" : "")
115
- << (HasPext ? " BMI2" : (HasPopCnt ? " POPCNT" : ""))
116
- << (to_uci ? "\nid author ": " by ")
117
- << "T. Romstad, M. Costalba, J. Kiiski, G. Linscott";
118
-
119
- return ss.str();
120
- }
121
-
122
-
123
- /// Debug functions used mainly to collect run-time statistics
124
- static int64_t hits[2], means[2];
125
-
126
- void dbg_hit_on(bool b) { ++hits[0]; if (b) ++hits[1]; }
127
- void dbg_hit_on(bool c, bool b) { if (c) dbg_hit_on(b); }
128
- void dbg_mean_of(int v) { ++means[0]; means[1] += v; }
129
-
130
- void dbg_print() {
131
-
132
- if (hits[0])
133
- cerr << "Total " << hits[0] << " Hits " << hits[1]
134
- << " hit rate (%) " << 100 * hits[1] / hits[0] << endl;
135
-
136
- if (means[0])
137
- cerr << "Total " << means[0] << " Mean "
138
- << (double)means[1] / means[0] << endl;
139
- }
140
-
141
-
142
- /// Used to serialize access to std::cout to avoid multiple threads writing at
143
- /// the same time.
144
-
145
- std::ostream& operator<<(std::ostream& os, SyncCout sc) {
146
-
147
- static Mutex m;
148
-
149
- if (sc == IO_LOCK)
150
- m.lock();
151
-
152
- if (sc == IO_UNLOCK)
153
- m.unlock();
154
-
155
- return os;
156
- }
157
-
158
-
159
- /// Trampoline helper to avoid moving Logger to misc.h
160
- void start_logger(const std::string& fname) { Logger::start(fname); }
161
-
162
-
163
- /// prefetch() preloads the given address in L1/L2 cache. This is a non-blocking
164
- /// function that doesn't stall the CPU waiting for data to be loaded from memory,
165
- /// which can be quite slow.
166
- #ifdef NO_PREFETCH
167
-
168
- void prefetch(void*) {}
169
-
170
- #else
171
-
172
- void prefetch(void* addr) {
173
-
174
- # if defined(__INTEL_COMPILER)
175
- // This hack prevents prefetches from being optimized away by
176
- // Intel compiler. Both MSVC and gcc seem not be affected by this.
177
- __asm__ ("");
178
- # endif
179
-
180
- # if defined(__INTEL_COMPILER) || defined(_MSC_VER)
181
- _mm_prefetch((char*)addr, _MM_HINT_T0);
182
- # else
183
- __builtin_prefetch(addr);
184
- # endif
185
- }
186
-
187
- #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/misc.h DELETED
@@ -1,100 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #ifndef MISC_H_INCLUDED
22
- #define MISC_H_INCLUDED
23
-
24
- #include <cassert>
25
- #include <chrono>
26
- #include <ostream>
27
- #include <string>
28
- #include <vector>
29
-
30
- #include "types.h"
31
-
32
- const std::string engine_info(bool to_uci = false);
33
- void prefetch(void* addr);
34
- void start_logger(const std::string& fname);
35
-
36
- void dbg_hit_on(bool b);
37
- void dbg_hit_on(bool c, bool b);
38
- void dbg_mean_of(int v);
39
- void dbg_print();
40
-
41
- typedef std::chrono::milliseconds::rep TimePoint; // A value in milliseconds
42
-
43
- inline TimePoint now() {
44
- return std::chrono::duration_cast<std::chrono::milliseconds>
45
- (std::chrono::steady_clock::now().time_since_epoch()).count();
46
- }
47
-
48
- template<class Entry, int Size>
49
- struct HashTable {
50
- Entry* operator[](Key key) { return &table[(uint32_t)key & (Size - 1)]; }
51
-
52
- private:
53
- std::vector<Entry> table = std::vector<Entry>(Size);
54
- };
55
-
56
-
57
- enum SyncCout { IO_LOCK, IO_UNLOCK };
58
- std::ostream& operator<<(std::ostream&, SyncCout);
59
-
60
- #define sync_cout std::cout << IO_LOCK
61
- #define sync_endl std::endl << IO_UNLOCK
62
-
63
-
64
- /// xorshift64star Pseudo-Random Number Generator
65
- /// This class is based on original code written and dedicated
66
- /// to the public domain by Sebastiano Vigna (2014).
67
- /// It has the following characteristics:
68
- ///
69
- /// - Outputs 64-bit numbers
70
- /// - Passes Dieharder and SmallCrush test batteries
71
- /// - Does not require warm-up, no zeroland to escape
72
- /// - Internal state is a single 64-bit integer
73
- /// - Period is 2^64 - 1
74
- /// - Speed: 1.60 ns/call (Core i7 @3.40GHz)
75
- ///
76
- /// For further analysis see
77
- /// <http://vigna.di.unimi.it/ftp/papers/xorshift.pdf>
78
-
79
- class PRNG {
80
-
81
- uint64_t s;
82
-
83
- uint64_t rand64() {
84
-
85
- s ^= s >> 12, s ^= s << 25, s ^= s >> 27;
86
- return s * 2685821657736338717LL;
87
- }
88
-
89
- public:
90
- PRNG(uint64_t seed) : s(seed) { assert(seed); }
91
-
92
- template<typename T> T rand() { return T(rand64()); }
93
-
94
- /// Special generator used to fast init magic numbers.
95
- /// Output values only have 1/8th of their bits set on average.
96
- template<typename T> T sparse_rand()
97
- { return T(rand64() & rand64() & rand64()); }
98
- };
99
-
100
- #endif // #ifndef MISC_H_INCLUDED
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/movegen.cpp DELETED
@@ -1,420 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #include <cassert>
22
-
23
- #include "movegen.h"
24
- #include "position.h"
25
-
26
- namespace {
27
-
28
- template<CastlingRight Cr, bool Checks, bool Chess960>
29
- ExtMove* generate_castling(const Position& pos, ExtMove* moveList, Color us) {
30
-
31
- static const bool KingSide = (Cr == WHITE_OO || Cr == BLACK_OO);
32
-
33
- if (pos.castling_impeded(Cr) || !pos.can_castle(Cr))
34
- return moveList;
35
-
36
- // After castling, the rook and king final positions are the same in Chess960
37
- // as they would be in standard chess.
38
- Square kfrom = pos.square<KING>(us);
39
- Square rfrom = pos.castling_rook_square(Cr);
40
- Square kto = relative_square(us, KingSide ? SQ_G1 : SQ_C1);
41
- Bitboard enemies = pos.pieces(~us);
42
-
43
- assert(!pos.checkers());
44
-
45
- const Square K = Chess960 ? kto > kfrom ? WEST : EAST
46
- : KingSide ? WEST : EAST;
47
-
48
- for (Square s = kto; s != kfrom; s += K)
49
- if (pos.attackers_to(s) & enemies)
50
- return moveList;
51
-
52
- // Because we generate only legal castling moves we need to verify that
53
- // when moving the castling rook we do not discover some hidden checker.
54
- // For instance an enemy queen in SQ_A1 when castling rook is in SQ_B1.
55
- if (Chess960 && (attacks_bb<ROOK>(kto, pos.pieces() ^ rfrom) & pos.pieces(~us, ROOK, QUEEN)))
56
- return moveList;
57
-
58
- Move m = make<CASTLING>(kfrom, rfrom);
59
-
60
- if (Checks && !pos.gives_check(m))
61
- return moveList;
62
-
63
- *moveList++ = m;
64
- return moveList;
65
- }
66
-
67
-
68
- template<GenType Type, Square D>
69
- ExtMove* make_promotions(ExtMove* moveList, Square to, Square ksq) {
70
-
71
- if (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS)
72
- *moveList++ = make<PROMOTION>(to - D, to, QUEEN);
73
-
74
- if (Type == QUIETS || Type == EVASIONS || Type == NON_EVASIONS)
75
- {
76
- *moveList++ = make<PROMOTION>(to - D, to, ROOK);
77
- *moveList++ = make<PROMOTION>(to - D, to, BISHOP);
78
- *moveList++ = make<PROMOTION>(to - D, to, KNIGHT);
79
- }
80
-
81
- // Knight promotion is the only promotion that can give a direct check
82
- // that's not already included in the queen promotion.
83
- if (Type == QUIET_CHECKS && (StepAttacksBB[W_KNIGHT][to] & ksq))
84
- *moveList++ = make<PROMOTION>(to - D, to, KNIGHT);
85
- else
86
- (void)ksq; // Silence a warning under MSVC
87
-
88
- return moveList;
89
- }
90
-
91
-
92
- template<Color Us, GenType Type>
93
- ExtMove* generate_pawn_moves(const Position& pos, ExtMove* moveList, Bitboard target) {
94
-
95
- // Compute our parametrized parameters at compile time, named according to
96
- // the point of view of white side.
97
- const Color Them = (Us == WHITE ? BLACK : WHITE);
98
- const Bitboard TRank8BB = (Us == WHITE ? Rank8BB : Rank1BB);
99
- const Bitboard TRank7BB = (Us == WHITE ? Rank7BB : Rank2BB);
100
- const Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB);
101
- const Square Up = (Us == WHITE ? NORTH : SOUTH);
102
- const Square Right = (Us == WHITE ? NORTH_EAST : SOUTH_WEST);
103
- const Square Left = (Us == WHITE ? NORTH_WEST : SOUTH_EAST);
104
-
105
- Bitboard emptySquares;
106
-
107
- Bitboard pawnsOn7 = pos.pieces(Us, PAWN) & TRank7BB;
108
- Bitboard pawnsNotOn7 = pos.pieces(Us, PAWN) & ~TRank7BB;
109
-
110
- Bitboard enemies = (Type == EVASIONS ? pos.pieces(Them) & target:
111
- Type == CAPTURES ? target : pos.pieces(Them));
112
-
113
- // Single and double pawn pushes, no promotions
114
- if (Type != CAPTURES)
115
- {
116
- emptySquares = (Type == QUIETS || Type == QUIET_CHECKS ? target : ~pos.pieces());
117
-
118
- Bitboard b1 = shift<Up>(pawnsNotOn7) & emptySquares;
119
- Bitboard b2 = shift<Up>(b1 & TRank3BB) & emptySquares;
120
-
121
- if (Type == EVASIONS) // Consider only blocking squares
122
- {
123
- b1 &= target;
124
- b2 &= target;
125
- }
126
-
127
- if (Type == QUIET_CHECKS)
128
- {
129
- Square ksq = pos.square<KING>(Them);
130
-
131
- b1 &= pos.attacks_from<PAWN>(ksq, Them);
132
- b2 &= pos.attacks_from<PAWN>(ksq, Them);
133
-
134
- // Add pawn pushes which give discovered check. This is possible only
135
- // if the pawn is not on the same file as the enemy king, because we
136
- // don't generate captures. Note that a possible discovery check
137
- // promotion has been already generated amongst the captures.
138
- Bitboard dcCandidates = pos.discovered_check_candidates();
139
- if (pawnsNotOn7 & dcCandidates)
140
- {
141
- Bitboard dc1 = shift<Up>(pawnsNotOn7 & dcCandidates) & emptySquares & ~file_bb(ksq);
142
- Bitboard dc2 = shift<Up>(dc1 & TRank3BB) & emptySquares;
143
-
144
- b1 |= dc1;
145
- b2 |= dc2;
146
- }
147
- }
148
-
149
- while (b1)
150
- {
151
- Square to = pop_lsb(&b1);
152
- *moveList++ = make_move(to - Up, to);
153
- }
154
-
155
- while (b2)
156
- {
157
- Square to = pop_lsb(&b2);
158
- *moveList++ = make_move(to - Up - Up, to);
159
- }
160
- }
161
-
162
- // Promotions and underpromotions
163
- if (pawnsOn7 && (Type != EVASIONS || (target & TRank8BB)))
164
- {
165
- if (Type == CAPTURES)
166
- emptySquares = ~pos.pieces();
167
-
168
- if (Type == EVASIONS)
169
- emptySquares &= target;
170
-
171
- Bitboard b1 = shift<Right>(pawnsOn7) & enemies;
172
- Bitboard b2 = shift<Left >(pawnsOn7) & enemies;
173
- Bitboard b3 = shift<Up >(pawnsOn7) & emptySquares;
174
-
175
- Square ksq = pos.square<KING>(Them);
176
-
177
- while (b1)
178
- moveList = make_promotions<Type, Right>(moveList, pop_lsb(&b1), ksq);
179
-
180
- while (b2)
181
- moveList = make_promotions<Type, Left >(moveList, pop_lsb(&b2), ksq);
182
-
183
- while (b3)
184
- moveList = make_promotions<Type, Up >(moveList, pop_lsb(&b3), ksq);
185
- }
186
-
187
- // Standard and en-passant captures
188
- if (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS)
189
- {
190
- Bitboard b1 = shift<Right>(pawnsNotOn7) & enemies;
191
- Bitboard b2 = shift<Left >(pawnsNotOn7) & enemies;
192
-
193
- while (b1)
194
- {
195
- Square to = pop_lsb(&b1);
196
- *moveList++ = make_move(to - Right, to);
197
- }
198
-
199
- while (b2)
200
- {
201
- Square to = pop_lsb(&b2);
202
- *moveList++ = make_move(to - Left, to);
203
- }
204
-
205
- if (pos.ep_square() != SQ_NONE)
206
- {
207
- assert(rank_of(pos.ep_square()) == relative_rank(Us, RANK_6));
208
-
209
- // An en passant capture can be an evasion only if the checking piece
210
- // is the double pushed pawn and so is in the target. Otherwise this
211
- // is a discovery check and we are forced to do otherwise.
212
- if (Type == EVASIONS && !(target & (pos.ep_square() - Up)))
213
- return moveList;
214
-
215
- b1 = pawnsNotOn7 & pos.attacks_from<PAWN>(pos.ep_square(), Them);
216
-
217
- assert(b1);
218
-
219
- while (b1)
220
- *moveList++ = make<ENPASSANT>(pop_lsb(&b1), pos.ep_square());
221
- }
222
- }
223
-
224
- return moveList;
225
- }
226
-
227
-
228
- template<PieceType Pt, bool Checks>
229
- ExtMove* generate_moves(const Position& pos, ExtMove* moveList, Color us,
230
- Bitboard target) {
231
-
232
- assert(Pt != KING && Pt != PAWN);
233
-
234
- const Square* pl = pos.squares<Pt>(us);
235
-
236
- for (Square from = *pl; from != SQ_NONE; from = *++pl)
237
- {
238
- if (Checks)
239
- {
240
- if ( (Pt == BISHOP || Pt == ROOK || Pt == QUEEN)
241
- && !(PseudoAttacks[Pt][from] & target & pos.check_squares(Pt)))
242
- continue;
243
-
244
- if (pos.discovered_check_candidates() & from)
245
- continue;
246
- }
247
-
248
- Bitboard b = pos.attacks_from<Pt>(from) & target;
249
-
250
- if (Checks)
251
- b &= pos.check_squares(Pt);
252
-
253
- while (b)
254
- *moveList++ = make_move(from, pop_lsb(&b));
255
- }
256
-
257
- return moveList;
258
- }
259
-
260
-
261
- template<Color Us, GenType Type>
262
- ExtMove* generate_all(const Position& pos, ExtMove* moveList, Bitboard target) {
263
-
264
- const bool Checks = Type == QUIET_CHECKS;
265
-
266
- moveList = generate_pawn_moves<Us, Type>(pos, moveList, target);
267
- moveList = generate_moves<KNIGHT, Checks>(pos, moveList, Us, target);
268
- moveList = generate_moves<BISHOP, Checks>(pos, moveList, Us, target);
269
- moveList = generate_moves< ROOK, Checks>(pos, moveList, Us, target);
270
- moveList = generate_moves< QUEEN, Checks>(pos, moveList, Us, target);
271
-
272
- if (Type != QUIET_CHECKS && Type != EVASIONS)
273
- {
274
- Square ksq = pos.square<KING>(Us);
275
- Bitboard b = pos.attacks_from<KING>(ksq) & target;
276
- while (b)
277
- *moveList++ = make_move(ksq, pop_lsb(&b));
278
- }
279
-
280
- if (Type != CAPTURES && Type != EVASIONS && pos.can_castle(Us))
281
- {
282
- if (pos.is_chess960())
283
- {
284
- moveList = generate_castling<MakeCastling<Us, KING_SIDE>::right, Checks, true>(pos, moveList, Us);
285
- moveList = generate_castling<MakeCastling<Us, QUEEN_SIDE>::right, Checks, true>(pos, moveList, Us);
286
- }
287
- else
288
- {
289
- moveList = generate_castling<MakeCastling<Us, KING_SIDE>::right, Checks, false>(pos, moveList, Us);
290
- moveList = generate_castling<MakeCastling<Us, QUEEN_SIDE>::right, Checks, false>(pos, moveList, Us);
291
- }
292
- }
293
-
294
- return moveList;
295
- }
296
-
297
- } // namespace
298
-
299
-
300
- /// generate<CAPTURES> generates all pseudo-legal captures and queen
301
- /// promotions. Returns a pointer to the end of the move list.
302
- ///
303
- /// generate<QUIETS> generates all pseudo-legal non-captures and
304
- /// underpromotions. Returns a pointer to the end of the move list.
305
- ///
306
- /// generate<NON_EVASIONS> generates all pseudo-legal captures and
307
- /// non-captures. Returns a pointer to the end of the move list.
308
-
309
- template<GenType Type>
310
- ExtMove* generate(const Position& pos, ExtMove* moveList) {
311
-
312
- assert(Type == CAPTURES || Type == QUIETS || Type == NON_EVASIONS);
313
- assert(!pos.checkers());
314
-
315
- Color us = pos.side_to_move();
316
-
317
- Bitboard target = Type == CAPTURES ? pos.pieces(~us)
318
- : Type == QUIETS ? ~pos.pieces()
319
- : Type == NON_EVASIONS ? ~pos.pieces(us) : 0;
320
-
321
- return us == WHITE ? generate_all<WHITE, Type>(pos, moveList, target)
322
- : generate_all<BLACK, Type>(pos, moveList, target);
323
- }
324
-
325
- // Explicit template instantiations
326
- template ExtMove* generate<CAPTURES>(const Position&, ExtMove*);
327
- template ExtMove* generate<QUIETS>(const Position&, ExtMove*);
328
- template ExtMove* generate<NON_EVASIONS>(const Position&, ExtMove*);
329
-
330
-
331
- /// generate<QUIET_CHECKS> generates all pseudo-legal non-captures and knight
332
- /// underpromotions that give check. Returns a pointer to the end of the move list.
333
- template<>
334
- ExtMove* generate<QUIET_CHECKS>(const Position& pos, ExtMove* moveList) {
335
-
336
- assert(!pos.checkers());
337
-
338
- Color us = pos.side_to_move();
339
- Bitboard dc = pos.discovered_check_candidates();
340
-
341
- while (dc)
342
- {
343
- Square from = pop_lsb(&dc);
344
- PieceType pt = type_of(pos.piece_on(from));
345
-
346
- if (pt == PAWN)
347
- continue; // Will be generated together with direct checks
348
-
349
- Bitboard b = pos.attacks_from(Piece(pt), from) & ~pos.pieces();
350
-
351
- if (pt == KING)
352
- b &= ~PseudoAttacks[QUEEN][pos.square<KING>(~us)];
353
-
354
- while (b)
355
- *moveList++ = make_move(from, pop_lsb(&b));
356
- }
357
-
358
- return us == WHITE ? generate_all<WHITE, QUIET_CHECKS>(pos, moveList, ~pos.pieces())
359
- : generate_all<BLACK, QUIET_CHECKS>(pos, moveList, ~pos.pieces());
360
- }
361
-
362
-
363
- /// generate<EVASIONS> generates all pseudo-legal check evasions when the side
364
- /// to move is in check. Returns a pointer to the end of the move list.
365
- template<>
366
- ExtMove* generate<EVASIONS>(const Position& pos, ExtMove* moveList) {
367
-
368
- assert(pos.checkers());
369
-
370
- Color us = pos.side_to_move();
371
- Square ksq = pos.square<KING>(us);
372
- Bitboard sliderAttacks = 0;
373
- Bitboard sliders = pos.checkers() & ~pos.pieces(KNIGHT, PAWN);
374
-
375
- // Find all the squares attacked by slider checkers. We will remove them from
376
- // the king evasions in order to skip known illegal moves, which avoids any
377
- // useless legality checks later on.
378
- while (sliders)
379
- {
380
- Square checksq = pop_lsb(&sliders);
381
- sliderAttacks |= LineBB[checksq][ksq] ^ checksq;
382
- }
383
-
384
- // Generate evasions for king, capture and non capture moves
385
- Bitboard b = pos.attacks_from<KING>(ksq) & ~pos.pieces(us) & ~sliderAttacks;
386
- while (b)
387
- *moveList++ = make_move(ksq, pop_lsb(&b));
388
-
389
- if (more_than_one(pos.checkers()))
390
- return moveList; // Double check, only a king move can save the day
391
-
392
- // Generate blocking evasions or captures of the checking piece
393
- Square checksq = lsb(pos.checkers());
394
- Bitboard target = between_bb(checksq, ksq) | checksq;
395
-
396
- return us == WHITE ? generate_all<WHITE, EVASIONS>(pos, moveList, target)
397
- : generate_all<BLACK, EVASIONS>(pos, moveList, target);
398
- }
399
-
400
-
401
- /// generate<LEGAL> generates all the legal moves in the given position
402
-
403
- template<>
404
- ExtMove* generate<LEGAL>(const Position& pos, ExtMove* moveList) {
405
-
406
- Bitboard pinned = pos.pinned_pieces(pos.side_to_move());
407
- Square ksq = pos.square<KING>(pos.side_to_move());
408
- ExtMove* cur = moveList;
409
-
410
- moveList = pos.checkers() ? generate<EVASIONS >(pos, moveList)
411
- : generate<NON_EVASIONS>(pos, moveList);
412
- while (cur != moveList)
413
- if ( (pinned || from_sq(*cur) == ksq || type_of(*cur) == ENPASSANT)
414
- && !pos.legal(*cur))
415
- *cur = (--moveList)->move;
416
- else
417
- ++cur;
418
-
419
- return moveList;
420
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/movegen.h DELETED
@@ -1,70 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #ifndef MOVEGEN_H_INCLUDED
22
- #define MOVEGEN_H_INCLUDED
23
-
24
- #include "types.h"
25
-
26
- class Position;
27
-
28
- enum GenType {
29
- CAPTURES,
30
- QUIETS,
31
- QUIET_CHECKS,
32
- EVASIONS,
33
- NON_EVASIONS,
34
- LEGAL
35
- };
36
-
37
- struct ExtMove {
38
- Move move;
39
- Value value;
40
-
41
- operator Move() const { return move; }
42
- void operator=(Move m) { move = m; }
43
- };
44
-
45
- inline bool operator<(const ExtMove& f, const ExtMove& s) {
46
- return f.value < s.value;
47
- }
48
-
49
- template<GenType>
50
- ExtMove* generate(const Position& pos, ExtMove* moveList);
51
-
52
- /// The MoveList struct is a simple wrapper around generate(). It sometimes comes
53
- /// in handy to use this class instead of the low level generate() function.
54
- template<GenType T>
55
- struct MoveList {
56
-
57
- explicit MoveList(const Position& pos) : last(generate<T>(pos, moveList)) {}
58
- const ExtMove* begin() const { return moveList; }
59
- const ExtMove* end() const { return last; }
60
- size_t size() const { return last - moveList; }
61
- bool contains(Move move) const {
62
- for (const auto& m : *this) if (m == move) return true;
63
- return false;
64
- }
65
-
66
- private:
67
- ExtMove moveList[MAX_MOVES], *last;
68
- };
69
-
70
- #endif // #ifndef MOVEGEN_H_INCLUDED
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/movepick.cpp DELETED
@@ -1,350 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #include <cassert>
22
-
23
- #include "movepick.h"
24
- #include "thread.h"
25
-
26
- namespace {
27
-
28
- enum Stages {
29
- MAIN_SEARCH, CAPTURES_INIT, GOOD_CAPTURES, KILLERS, COUNTERMOVE, QUIET_INIT, QUIET, BAD_CAPTURES,
30
- EVASION, EVASIONS_INIT, ALL_EVASIONS,
31
- PROBCUT, PROBCUT_INIT, PROBCUT_CAPTURES,
32
- QSEARCH_WITH_CHECKS, QCAPTURES_1_INIT, QCAPTURES_1, QCHECKS,
33
- QSEARCH_NO_CHECKS, QCAPTURES_2_INIT, QCAPTURES_2,
34
- QSEARCH_RECAPTURES, QRECAPTURES
35
- };
36
-
37
- // Our insertion sort, which is guaranteed to be stable, as it should be
38
- void insertion_sort(ExtMove* begin, ExtMove* end)
39
- {
40
- ExtMove tmp, *p, *q;
41
-
42
- for (p = begin + 1; p < end; ++p)
43
- {
44
- tmp = *p;
45
- for (q = p; q != begin && *(q-1) < tmp; --q)
46
- *q = *(q-1);
47
- *q = tmp;
48
- }
49
- }
50
-
51
- // pick_best() finds the best move in the range (begin, end) and moves it to
52
- // the front. It's faster than sorting all the moves in advance when there
53
- // are few moves, e.g., the possible captures.
54
- Move pick_best(ExtMove* begin, ExtMove* end)
55
- {
56
- std::swap(*begin, *std::max_element(begin, end));
57
- return *begin;
58
- }
59
-
60
- } // namespace
61
-
62
-
63
- /// Constructors of the MovePicker class. As arguments we pass information
64
- /// to help it to return the (presumably) good moves first, to decide which
65
- /// moves to return (in the quiescence search, for instance, we only want to
66
- /// search captures, promotions, and some checks) and how important good move
67
- /// ordering is at the current node.
68
-
69
- MovePicker::MovePicker(const Position& p, Move ttm, Depth d, Search::Stack* s)
70
- : pos(p), ss(s), depth(d) {
71
-
72
- assert(d > DEPTH_ZERO);
73
-
74
- Square prevSq = to_sq((ss-1)->currentMove);
75
- countermove = pos.this_thread()->counterMoves[pos.piece_on(prevSq)][prevSq];
76
-
77
- stage = pos.checkers() ? EVASION : MAIN_SEARCH;
78
- ttMove = ttm && pos.pseudo_legal(ttm) ? ttm : MOVE_NONE;
79
- stage += (ttMove == MOVE_NONE);
80
- }
81
-
82
- MovePicker::MovePicker(const Position& p, Move ttm, Depth d, Square s)
83
- : pos(p) {
84
-
85
- assert(d <= DEPTH_ZERO);
86
-
87
- if (pos.checkers())
88
- stage = EVASION;
89
-
90
- else if (d > DEPTH_QS_NO_CHECKS)
91
- stage = QSEARCH_WITH_CHECKS;
92
-
93
- else if (d > DEPTH_QS_RECAPTURES)
94
- stage = QSEARCH_NO_CHECKS;
95
-
96
- else
97
- {
98
- stage = QSEARCH_RECAPTURES;
99
- recaptureSquare = s;
100
- return;
101
- }
102
-
103
- ttMove = ttm && pos.pseudo_legal(ttm) ? ttm : MOVE_NONE;
104
- stage += (ttMove == MOVE_NONE);
105
- }
106
-
107
- MovePicker::MovePicker(const Position& p, Move ttm, Value th)
108
- : pos(p), threshold(th) {
109
-
110
- assert(!pos.checkers());
111
-
112
- stage = PROBCUT;
113
-
114
- // In ProbCut we generate captures with SEE higher than the given threshold
115
- ttMove = ttm
116
- && pos.pseudo_legal(ttm)
117
- && pos.capture(ttm)
118
- && pos.see_ge(ttm, threshold + 1)? ttm : MOVE_NONE;
119
-
120
- stage += (ttMove == MOVE_NONE);
121
- }
122
-
123
-
124
- /// score() assigns a numerical value to each move in a move list. The moves with
125
- /// highest values will be picked first.
126
- template<>
127
- void MovePicker::score<CAPTURES>() {
128
- // Winning and equal captures in the main search are ordered by MVV, preferring
129
- // captures near our home rank. Surprisingly, this appears to perform slightly
130
- // better than SEE-based move ordering: exchanging big pieces before capturing
131
- // a hanging piece probably helps to reduce the subtree size.
132
- // In the main search we want to push captures with negative SEE values to the
133
- // badCaptures[] array, but instead of doing it now we delay until the move
134
- // has been picked up, saving some SEE calls in case we get a cutoff.
135
- for (auto& m : *this)
136
- m.value = PieceValue[MG][pos.piece_on(to_sq(m))]
137
- - Value(200 * relative_rank(pos.side_to_move(), to_sq(m)));
138
- }
139
-
140
- template<>
141
- void MovePicker::score<QUIETS>() {
142
-
143
- const HistoryStats& history = pos.this_thread()->history;
144
- const FromToStats& fromTo = pos.this_thread()->fromTo;
145
-
146
- const CounterMoveStats* cm = (ss-1)->counterMoves;
147
- const CounterMoveStats* fm = (ss-2)->counterMoves;
148
- const CounterMoveStats* f2 = (ss-4)->counterMoves;
149
-
150
- Color c = pos.side_to_move();
151
-
152
- for (auto& m : *this)
153
- m.value = history[pos.moved_piece(m)][to_sq(m)]
154
- + (cm ? (*cm)[pos.moved_piece(m)][to_sq(m)] : VALUE_ZERO)
155
- + (fm ? (*fm)[pos.moved_piece(m)][to_sq(m)] : VALUE_ZERO)
156
- + (f2 ? (*f2)[pos.moved_piece(m)][to_sq(m)] : VALUE_ZERO)
157
- + fromTo.get(c, m);
158
- }
159
-
160
- template<>
161
- void MovePicker::score<EVASIONS>() {
162
- // Try captures ordered by MVV/LVA, then non-captures ordered by history value
163
- const HistoryStats& history = pos.this_thread()->history;
164
- const FromToStats& fromTo = pos.this_thread()->fromTo;
165
- Color c = pos.side_to_move();
166
-
167
- for (auto& m : *this)
168
- if (pos.capture(m))
169
- m.value = PieceValue[MG][pos.piece_on(to_sq(m))]
170
- - Value(type_of(pos.moved_piece(m))) + HistoryStats::Max;
171
- else
172
- m.value = history[pos.moved_piece(m)][to_sq(m)] + fromTo.get(c, m);
173
- }
174
-
175
-
176
- /// next_move() is the most important method of the MovePicker class. It returns
177
- /// a new pseudo legal move every time it is called, until there are no more moves
178
- /// left. It picks the move with the biggest value from a list of generated moves
179
- /// taking care not to return the ttMove if it has already been searched.
180
-
181
- Move MovePicker::next_move() {
182
-
183
- Move move;
184
-
185
- switch (stage) {
186
-
187
- case MAIN_SEARCH: case EVASION: case QSEARCH_WITH_CHECKS:
188
- case QSEARCH_NO_CHECKS: case PROBCUT:
189
- ++stage;
190
- return ttMove;
191
-
192
- case CAPTURES_INIT:
193
- endBadCaptures = cur = moves;
194
- endMoves = generate<CAPTURES>(pos, cur);
195
- score<CAPTURES>();
196
- ++stage;
197
-
198
- case GOOD_CAPTURES:
199
- while (cur < endMoves)
200
- {
201
- move = pick_best(cur++, endMoves);
202
- if (move != ttMove)
203
- {
204
- if (pos.see_ge(move, VALUE_ZERO))
205
- return move;
206
-
207
- // Losing capture, move it to the beginning of the array
208
- *endBadCaptures++ = move;
209
- }
210
- }
211
-
212
- ++stage;
213
- move = ss->killers[0]; // First killer move
214
- if ( move != MOVE_NONE
215
- && move != ttMove
216
- && pos.pseudo_legal(move)
217
- && !pos.capture(move))
218
- return move;
219
-
220
- case KILLERS:
221
- ++stage;
222
- move = ss->killers[1]; // Second killer move
223
- if ( move != MOVE_NONE
224
- && move != ttMove
225
- && pos.pseudo_legal(move)
226
- && !pos.capture(move))
227
- return move;
228
-
229
- case COUNTERMOVE:
230
- ++stage;
231
- move = countermove;
232
- if ( move != MOVE_NONE
233
- && move != ttMove
234
- && move != ss->killers[0]
235
- && move != ss->killers[1]
236
- && pos.pseudo_legal(move)
237
- && !pos.capture(move))
238
- return move;
239
-
240
- case QUIET_INIT:
241
- cur = endBadCaptures;
242
- endMoves = generate<QUIETS>(pos, cur);
243
- score<QUIETS>();
244
- if (depth < 3 * ONE_PLY)
245
- {
246
- ExtMove* goodQuiet = std::partition(cur, endMoves, [](const ExtMove& m)
247
- { return m.value > VALUE_ZERO; });
248
- insertion_sort(cur, goodQuiet);
249
- } else
250
- insertion_sort(cur, endMoves);
251
- ++stage;
252
-
253
- case QUIET:
254
- while (cur < endMoves)
255
- {
256
- move = *cur++;
257
- if ( move != ttMove
258
- && move != ss->killers[0]
259
- && move != ss->killers[1]
260
- && move != countermove)
261
- return move;
262
- }
263
- ++stage;
264
- cur = moves; // Point to beginning of bad captures
265
-
266
- case BAD_CAPTURES:
267
- if (cur < endBadCaptures)
268
- return *cur++;
269
- break;
270
-
271
- case EVASIONS_INIT:
272
- cur = moves;
273
- endMoves = generate<EVASIONS>(pos, cur);
274
- score<EVASIONS>();
275
- ++stage;
276
-
277
- case ALL_EVASIONS:
278
- while (cur < endMoves)
279
- {
280
- move = pick_best(cur++, endMoves);
281
- if (move != ttMove)
282
- return move;
283
- }
284
- break;
285
-
286
- case PROBCUT_INIT:
287
- cur = moves;
288
- endMoves = generate<CAPTURES>(pos, cur);
289
- score<CAPTURES>();
290
- ++stage;
291
-
292
- case PROBCUT_CAPTURES:
293
- while (cur < endMoves)
294
- {
295
- move = pick_best(cur++, endMoves);
296
- if ( move != ttMove
297
- && pos.see_ge(move, threshold + 1))
298
- return move;
299
- }
300
- break;
301
-
302
- case QCAPTURES_1_INIT: case QCAPTURES_2_INIT:
303
- cur = moves;
304
- endMoves = generate<CAPTURES>(pos, cur);
305
- score<CAPTURES>();
306
- ++stage;
307
-
308
- case QCAPTURES_1: case QCAPTURES_2:
309
- while (cur < endMoves)
310
- {
311
- move = pick_best(cur++, endMoves);
312
- if (move != ttMove)
313
- return move;
314
- }
315
- if (stage == QCAPTURES_2)
316
- break;
317
- cur = moves;
318
- endMoves = generate<QUIET_CHECKS>(pos, cur);
319
- ++stage;
320
-
321
- case QCHECKS:
322
- while (cur < endMoves)
323
- {
324
- move = cur++->move;
325
- if (move != ttMove)
326
- return move;
327
- }
328
- break;
329
-
330
- case QSEARCH_RECAPTURES:
331
- cur = moves;
332
- endMoves = generate<CAPTURES>(pos, cur);
333
- score<CAPTURES>();
334
- ++stage;
335
-
336
- case QRECAPTURES:
337
- while (cur < endMoves)
338
- {
339
- move = pick_best(cur++, endMoves);
340
- if (to_sq(move) == recaptureSquare)
341
- return move;
342
- }
343
- break;
344
-
345
- default:
346
- assert(false);
347
- }
348
-
349
- return MOVE_NONE;
350
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/movepick.h DELETED
@@ -1,123 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #ifndef MOVEPICK_H_INCLUDED
22
- #define MOVEPICK_H_INCLUDED
23
-
24
- #include <algorithm> // For std::max
25
- #include <cstring> // For std::memset
26
-
27
- #include "movegen.h"
28
- #include "position.h"
29
- #include "types.h"
30
-
31
-
32
- /// The Stats struct stores moves statistics. According to the template parameter
33
- /// the class can store History and Countermoves. History records how often
34
- /// different moves have been successful or unsuccessful during the current search
35
- /// and is used for reduction and move ordering decisions.
36
- /// Countermoves store the move that refute a previous one. Entries are stored
37
- /// using only the moving piece and destination square, hence two moves with
38
- /// different origin but same destination and piece will be considered identical.
39
- template<typename T, bool CM = false>
40
- struct Stats {
41
-
42
- static const Value Max = Value(1 << 28);
43
-
44
- const T* operator[](Piece pc) const { return table[pc]; }
45
- T* operator[](Piece pc) { return table[pc]; }
46
- void clear() { std::memset(table, 0, sizeof(table)); }
47
- void update(Piece pc, Square to, Move m) { table[pc][to] = m; }
48
- void update(Piece pc, Square to, Value v) {
49
-
50
- if (abs(int(v)) >= 324)
51
- return;
52
-
53
- table[pc][to] -= table[pc][to] * abs(int(v)) / (CM ? 936 : 324);
54
- table[pc][to] += int(v) * 32;
55
- }
56
-
57
- private:
58
- T table[PIECE_NB][SQUARE_NB];
59
- };
60
-
61
- typedef Stats<Move> MoveStats;
62
- typedef Stats<Value, false> HistoryStats;
63
- typedef Stats<Value, true> CounterMoveStats;
64
- typedef Stats<CounterMoveStats> CounterMoveHistoryStats;
65
-
66
- struct FromToStats {
67
-
68
- Value get(Color c, Move m) const { return table[c][from_sq(m)][to_sq(m)]; }
69
- void clear() { std::memset(table, 0, sizeof(table)); }
70
- void update(Color c, Move m, Value v) {
71
-
72
- if (abs(int(v)) >= 324)
73
- return;
74
-
75
- Square from = from_sq(m);
76
- Square to = to_sq(m);
77
-
78
- table[c][from][to] -= table[c][from][to] * abs(int(v)) / 324;
79
- table[c][from][to] += int(v) * 32;
80
- }
81
-
82
- private:
83
- Value table[COLOR_NB][SQUARE_NB][SQUARE_NB];
84
- };
85
-
86
-
87
- /// MovePicker class is used to pick one pseudo legal move at a time from the
88
- /// current position. The most important method is next_move(), which returns a
89
- /// new pseudo legal move each time it is called, until there are no moves left,
90
- /// when MOVE_NONE is returned. In order to improve the efficiency of the alpha
91
- /// beta algorithm, MovePicker attempts to return the moves which are most likely
92
- /// to get a cut-off first.
93
- namespace Search { struct Stack; }
94
-
95
- class MovePicker {
96
- public:
97
- MovePicker(const MovePicker&) = delete;
98
- MovePicker& operator=(const MovePicker&) = delete;
99
-
100
- MovePicker(const Position&, Move, Value);
101
- MovePicker(const Position&, Move, Depth, Square);
102
- MovePicker(const Position&, Move, Depth, Search::Stack*);
103
-
104
- Move next_move();
105
-
106
- private:
107
- template<GenType> void score();
108
- ExtMove* begin() { return cur; }
109
- ExtMove* end() { return endMoves; }
110
-
111
- const Position& pos;
112
- const Search::Stack* ss;
113
- Move countermove;
114
- Depth depth;
115
- Move ttMove;
116
- Square recaptureSquare;
117
- Value threshold;
118
- int stage;
119
- ExtMove *cur, *endMoves, *endBadCaptures;
120
- ExtMove moves[MAX_MOVES];
121
- };
122
-
123
- #endif // #ifndef MOVEPICK_H_INCLUDED
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/pawns.cpp DELETED
@@ -1,291 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #include <algorithm>
22
- #include <cassert>
23
-
24
- #include "bitboard.h"
25
- #include "pawns.h"
26
- #include "position.h"
27
- #include "thread.h"
28
-
29
- namespace {
30
-
31
- #define V Value
32
- #define S(mg, eg) make_score(mg, eg)
33
-
34
- // Isolated pawn penalty by opposed flag
35
- const Score Isolated[2] = { S(45, 40), S(30, 27) };
36
-
37
- // Backward pawn penalty by opposed flag
38
- const Score Backward[2] = { S(56, 33), S(41, 19) };
39
-
40
- // Unsupported pawn penalty for pawns which are neither isolated or backward
41
- const Score Unsupported = S(17, 8);
42
-
43
- // Connected pawn bonus by opposed, phalanx, twice supported and rank
44
- Score Connected[2][2][2][RANK_NB];
45
-
46
- // Doubled pawn penalty
47
- const Score Doubled = S(18,38);
48
-
49
- // Lever bonus by rank
50
- const Score Lever[RANK_NB] = {
51
- S( 0, 0), S( 0, 0), S(0, 0), S(0, 0),
52
- S(17, 16), S(33, 32), S(0, 0), S(0, 0)
53
- };
54
-
55
- // Weakness of our pawn shelter in front of the king by [distance from edge][rank]
56
- const Value ShelterWeakness[][RANK_NB] = {
57
- { V( 97), V(21), V(26), V(51), V(87), V( 89), V( 99) },
58
- { V(120), V( 0), V(28), V(76), V(88), V(103), V(104) },
59
- { V(101), V( 7), V(54), V(78), V(77), V( 92), V(101) },
60
- { V( 80), V(11), V(44), V(68), V(87), V( 90), V(119) }
61
- };
62
-
63
- // Danger of enemy pawns moving toward our king by [type][distance from edge][rank]
64
- const Value StormDanger[][4][RANK_NB] = {
65
- { { V( 0), V( 67), V( 134), V(38), V(32) },
66
- { V( 0), V( 57), V( 139), V(37), V(22) },
67
- { V( 0), V( 43), V( 115), V(43), V(27) },
68
- { V( 0), V( 68), V( 124), V(57), V(32) } },
69
- { { V(20), V( 43), V( 100), V(56), V(20) },
70
- { V(23), V( 20), V( 98), V(40), V(15) },
71
- { V(23), V( 39), V( 103), V(36), V(18) },
72
- { V(28), V( 19), V( 108), V(42), V(26) } },
73
- { { V( 0), V( 0), V( 75), V(14), V( 2) },
74
- { V( 0), V( 0), V( 150), V(30), V( 4) },
75
- { V( 0), V( 0), V( 160), V(22), V( 5) },
76
- { V( 0), V( 0), V( 166), V(24), V(13) } },
77
- { { V( 0), V(-283), V(-281), V(57), V(31) },
78
- { V( 0), V( 58), V( 141), V(39), V(18) },
79
- { V( 0), V( 65), V( 142), V(48), V(32) },
80
- { V( 0), V( 60), V( 126), V(51), V(19) } }
81
- };
82
-
83
- // Max bonus for king safety. Corresponds to start position with all the pawns
84
- // in front of the king and no enemy pawn on the horizon.
85
- const Value MaxSafetyBonus = V(258);
86
-
87
- #undef S
88
- #undef V
89
-
90
- template<Color Us>
91
- Score evaluate(const Position& pos, Pawns::Entry* e) {
92
-
93
- const Color Them = (Us == WHITE ? BLACK : WHITE);
94
- const Square Up = (Us == WHITE ? NORTH : SOUTH);
95
- const Square Right = (Us == WHITE ? NORTH_EAST : SOUTH_WEST);
96
- const Square Left = (Us == WHITE ? NORTH_WEST : SOUTH_EAST);
97
-
98
- Bitboard b, neighbours, stoppers, doubled, supported, phalanx;
99
- Square s;
100
- bool opposed, lever, connected, backward;
101
- Score score = SCORE_ZERO;
102
- const Square* pl = pos.squares<PAWN>(Us);
103
- const Bitboard* pawnAttacksBB = StepAttacksBB[make_piece(Us, PAWN)];
104
-
105
- Bitboard ourPawns = pos.pieces(Us , PAWN);
106
- Bitboard theirPawns = pos.pieces(Them, PAWN);
107
-
108
- e->passedPawns[Us] = e->pawnAttacksSpan[Us] = 0;
109
- e->semiopenFiles[Us] = 0xFF;
110
- e->kingSquares[Us] = SQ_NONE;
111
- e->pawnAttacks[Us] = shift<Right>(ourPawns) | shift<Left>(ourPawns);
112
- e->pawnsOnSquares[Us][BLACK] = popcount(ourPawns & DarkSquares);
113
- e->pawnsOnSquares[Us][WHITE] = pos.count<PAWN>(Us) - e->pawnsOnSquares[Us][BLACK];
114
-
115
- // Loop through all pawns of the current color and score each pawn
116
- while ((s = *pl++) != SQ_NONE)
117
- {
118
- assert(pos.piece_on(s) == make_piece(Us, PAWN));
119
-
120
- File f = file_of(s);
121
-
122
- e->semiopenFiles[Us] &= ~(1 << f);
123
- e->pawnAttacksSpan[Us] |= pawn_attack_span(Us, s);
124
-
125
- // Flag the pawn
126
- opposed = theirPawns & forward_bb(Us, s);
127
- stoppers = theirPawns & passed_pawn_mask(Us, s);
128
- lever = theirPawns & pawnAttacksBB[s];
129
- doubled = ourPawns & (s + Up);
130
- neighbours = ourPawns & adjacent_files_bb(f);
131
- phalanx = neighbours & rank_bb(s);
132
- supported = neighbours & rank_bb(s - Up);
133
- connected = supported | phalanx;
134
-
135
- // A pawn is backward when it is behind all pawns of the same color on the
136
- // adjacent files and cannot be safely advanced.
137
- if (!neighbours || lever || relative_rank(Us, s) >= RANK_5)
138
- backward = false;
139
- else
140
- {
141
- // Find the backmost rank with neighbours or stoppers
142
- b = rank_bb(backmost_sq(Us, neighbours | stoppers));
143
-
144
- // The pawn is backward when it cannot safely progress to that rank:
145
- // either there is a stopper in the way on this rank, or there is a
146
- // stopper on adjacent file which controls the way to that rank.
147
- backward = (b | shift<Up>(b & adjacent_files_bb(f))) & stoppers;
148
-
149
- assert(!backward || !(pawn_attack_span(Them, s + Up) & neighbours));
150
- }
151
-
152
- // Passed pawns will be properly scored in evaluation because we need
153
- // full attack info to evaluate them.
154
- if (!stoppers && !(ourPawns & forward_bb(Us, s)))
155
- e->passedPawns[Us] |= s;
156
-
157
- // Score this pawn
158
- if (!neighbours)
159
- score -= Isolated[opposed];
160
-
161
- else if (backward)
162
- score -= Backward[opposed];
163
-
164
- else if (!supported)
165
- score -= Unsupported;
166
-
167
- if (connected)
168
- score += Connected[opposed][!!phalanx][more_than_one(supported)][relative_rank(Us, s)];
169
-
170
- if (doubled)
171
- score -= Doubled;
172
-
173
- if (lever)
174
- score += Lever[relative_rank(Us, s)];
175
- }
176
-
177
- return score;
178
- }
179
-
180
- } // namespace
181
-
182
- namespace Pawns {
183
-
184
- /// Pawns::init() initializes some tables needed by evaluation. Instead of using
185
- /// hard-coded tables, when makes sense, we prefer to calculate them with a formula
186
- /// to reduce independent parameters and to allow easier tuning and better insight.
187
-
188
- void init() {
189
-
190
- static const int Seed[RANK_NB] = { 0, 8, 19, 13, 71, 94, 169, 324 };
191
-
192
- for (int opposed = 0; opposed <= 1; ++opposed)
193
- for (int phalanx = 0; phalanx <= 1; ++phalanx)
194
- for (int apex = 0; apex <= 1; ++apex)
195
- for (Rank r = RANK_2; r < RANK_8; ++r)
196
- {
197
- int v = (Seed[r] + (phalanx ? (Seed[r + 1] - Seed[r]) / 2 : 0)) >> opposed;
198
- v += (apex ? v / 2 : 0);
199
- Connected[opposed][phalanx][apex][r] = make_score(v, v * 5 / 8);
200
- }
201
- }
202
-
203
-
204
- /// Pawns::probe() looks up the current position's pawns configuration in
205
- /// the pawns hash table. It returns a pointer to the Entry if the position
206
- /// is found. Otherwise a new Entry is computed and stored there, so we don't
207
- /// have to recompute all when the same pawns configuration occurs again.
208
-
209
- Entry* probe(const Position& pos) {
210
-
211
- Key key = pos.pawn_key();
212
- Entry* e = pos.this_thread()->pawnsTable[key];
213
-
214
- if (e->key == key)
215
- return e;
216
-
217
- e->key = key;
218
- e->score = evaluate<WHITE>(pos, e) - evaluate<BLACK>(pos, e);
219
- e->asymmetry = popcount(e->semiopenFiles[WHITE] ^ e->semiopenFiles[BLACK]);
220
- e->openFiles = popcount(e->semiopenFiles[WHITE] & e->semiopenFiles[BLACK]);
221
- return e;
222
- }
223
-
224
-
225
- /// Entry::shelter_storm() calculates shelter and storm penalties for the file
226
- /// the king is on, as well as the two adjacent files.
227
-
228
- template<Color Us>
229
- Value Entry::shelter_storm(const Position& pos, Square ksq) {
230
-
231
- const Color Them = (Us == WHITE ? BLACK : WHITE);
232
-
233
- enum { NoFriendlyPawn, Unblocked, BlockedByPawn, BlockedByKing };
234
-
235
- Bitboard b = pos.pieces(PAWN) & (in_front_bb(Us, rank_of(ksq)) | rank_bb(ksq));
236
- Bitboard ourPawns = b & pos.pieces(Us);
237
- Bitboard theirPawns = b & pos.pieces(Them);
238
- Value safety = MaxSafetyBonus;
239
- File center = std::max(FILE_B, std::min(FILE_G, file_of(ksq)));
240
-
241
- for (File f = center - File(1); f <= center + File(1); ++f)
242
- {
243
- b = ourPawns & file_bb(f);
244
- Rank rkUs = b ? relative_rank(Us, backmost_sq(Us, b)) : RANK_1;
245
-
246
- b = theirPawns & file_bb(f);
247
- Rank rkThem = b ? relative_rank(Us, frontmost_sq(Them, b)) : RANK_1;
248
-
249
- safety -= ShelterWeakness[std::min(f, FILE_H - f)][rkUs]
250
- + StormDanger
251
- [f == file_of(ksq) && rkThem == relative_rank(Us, ksq) + 1 ? BlockedByKing :
252
- rkUs == RANK_1 ? NoFriendlyPawn :
253
- rkThem == rkUs + 1 ? BlockedByPawn : Unblocked]
254
- [std::min(f, FILE_H - f)][rkThem];
255
- }
256
-
257
- return safety;
258
- }
259
-
260
-
261
- /// Entry::do_king_safety() calculates a bonus for king safety. It is called only
262
- /// when king square changes, which is about 20% of total king_safety() calls.
263
-
264
- template<Color Us>
265
- Score Entry::do_king_safety(const Position& pos, Square ksq) {
266
-
267
- kingSquares[Us] = ksq;
268
- castlingRights[Us] = pos.can_castle(Us);
269
- int minKingPawnDistance = 0;
270
-
271
- Bitboard pawns = pos.pieces(Us, PAWN);
272
- if (pawns)
273
- while (!(DistanceRingBB[ksq][minKingPawnDistance++] & pawns)) {}
274
-
275
- Value bonus = shelter_storm<Us>(pos, ksq);
276
-
277
- // If we can castle use the bonus after the castling if it is bigger
278
- if (pos.can_castle(MakeCastling<Us, KING_SIDE>::right))
279
- bonus = std::max(bonus, shelter_storm<Us>(pos, relative_square(Us, SQ_G1)));
280
-
281
- if (pos.can_castle(MakeCastling<Us, QUEEN_SIDE>::right))
282
- bonus = std::max(bonus, shelter_storm<Us>(pos, relative_square(Us, SQ_C1)));
283
-
284
- return make_score(bonus, -16 * minKingPawnDistance);
285
- }
286
-
287
- // Explicit template instantiation
288
- template Score Entry::do_king_safety<WHITE>(const Position& pos, Square ksq);
289
- template Score Entry::do_king_safety<BLACK>(const Position& pos, Square ksq);
290
-
291
- } // namespace Pawns
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/pawns.h DELETED
@@ -1,88 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #ifndef PAWNS_H_INCLUDED
22
- #define PAWNS_H_INCLUDED
23
-
24
- #include "misc.h"
25
- #include "position.h"
26
- #include "types.h"
27
-
28
- namespace Pawns {
29
-
30
- /// Pawns::Entry contains various information about a pawn structure. A lookup
31
- /// to the pawn hash table (performed by calling the probe function) returns a
32
- /// pointer to an Entry object.
33
-
34
- struct Entry {
35
-
36
- Score pawns_score() const { return score; }
37
- Bitboard pawn_attacks(Color c) const { return pawnAttacks[c]; }
38
- Bitboard passed_pawns(Color c) const { return passedPawns[c]; }
39
- Bitboard pawn_attacks_span(Color c) const { return pawnAttacksSpan[c]; }
40
- int pawn_asymmetry() const { return asymmetry; }
41
- int open_files() const { return openFiles; }
42
-
43
- int semiopen_file(Color c, File f) const {
44
- return semiopenFiles[c] & (1 << f);
45
- }
46
-
47
- int semiopen_side(Color c, File f, bool leftSide) const {
48
- return semiopenFiles[c] & (leftSide ? (1 << f) - 1 : ~((1 << (f + 1)) - 1));
49
- }
50
-
51
- int pawns_on_same_color_squares(Color c, Square s) const {
52
- return pawnsOnSquares[c][!!(DarkSquares & s)];
53
- }
54
-
55
- template<Color Us>
56
- Score king_safety(const Position& pos, Square ksq) {
57
- return kingSquares[Us] == ksq && castlingRights[Us] == pos.can_castle(Us)
58
- ? kingSafety[Us] : (kingSafety[Us] = do_king_safety<Us>(pos, ksq));
59
- }
60
-
61
- template<Color Us>
62
- Score do_king_safety(const Position& pos, Square ksq);
63
-
64
- template<Color Us>
65
- Value shelter_storm(const Position& pos, Square ksq);
66
-
67
- Key key;
68
- Score score;
69
- Bitboard passedPawns[COLOR_NB];
70
- Bitboard pawnAttacks[COLOR_NB];
71
- Bitboard pawnAttacksSpan[COLOR_NB];
72
- Square kingSquares[COLOR_NB];
73
- Score kingSafety[COLOR_NB];
74
- int castlingRights[COLOR_NB];
75
- int semiopenFiles[COLOR_NB];
76
- int pawnsOnSquares[COLOR_NB][COLOR_NB]; // [color][light/dark squares]
77
- int asymmetry;
78
- int openFiles;
79
- };
80
-
81
- typedef HashTable<Entry, 16384> Table;
82
-
83
- void init();
84
- Entry* probe(const Position& pos);
85
-
86
- } // namespace Pawns
87
-
88
- #endif // #ifndef PAWNS_H_INCLUDED
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/position.cpp DELETED
@@ -1,1168 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #include <algorithm>
22
- #include <cassert>
23
- #include <cstddef> // For offsetof()
24
- #include <cstring> // For std::memset, std::memcmp
25
- #include <iomanip>
26
- #include <sstream>
27
-
28
- #include "bitboard.h"
29
- #include "misc.h"
30
- #include "movegen.h"
31
- #include "position.h"
32
- #include "thread.h"
33
- #include "tt.h"
34
- #include "uci.h"
35
-
36
- using std::string;
37
-
38
- namespace PSQT {
39
- extern Score psq[PIECE_NB][SQUARE_NB];
40
- }
41
-
42
- namespace Zobrist {
43
-
44
- Key psq[PIECE_NB][SQUARE_NB];
45
- Key enpassant[FILE_NB];
46
- Key castling[CASTLING_RIGHT_NB];
47
- Key side;
48
- }
49
-
50
- namespace {
51
-
52
- const string PieceToChar(" PNBRQK pnbrqk");
53
-
54
- // min_attacker() is a helper function used by see() to locate the least
55
- // valuable attacker for the side to move, remove the attacker we just found
56
- // from the bitboards and scan for new X-ray attacks behind it.
57
-
58
- template<int Pt>
59
- PieceType min_attacker(const Bitboard* bb, Square to, Bitboard stmAttackers,
60
- Bitboard& occupied, Bitboard& attackers) {
61
-
62
- Bitboard b = stmAttackers & bb[Pt];
63
- if (!b)
64
- return min_attacker<Pt+1>(bb, to, stmAttackers, occupied, attackers);
65
-
66
- occupied ^= b & ~(b - 1);
67
-
68
- if (Pt == PAWN || Pt == BISHOP || Pt == QUEEN)
69
- attackers |= attacks_bb<BISHOP>(to, occupied) & (bb[BISHOP] | bb[QUEEN]);
70
-
71
- if (Pt == ROOK || Pt == QUEEN)
72
- attackers |= attacks_bb<ROOK>(to, occupied) & (bb[ROOK] | bb[QUEEN]);
73
-
74
- attackers &= occupied; // After X-ray that may add already processed pieces
75
- return (PieceType)Pt;
76
- }
77
-
78
- template<>
79
- PieceType min_attacker<KING>(const Bitboard*, Square, Bitboard, Bitboard&, Bitboard&) {
80
- return KING; // No need to update bitboards: it is the last cycle
81
- }
82
-
83
- } // namespace
84
-
85
-
86
- /// operator<<(Position) returns an ASCII representation of the position
87
-
88
- std::ostream& operator<<(std::ostream& os, const Position& pos) {
89
-
90
- os << "\n +---+---+---+---+---+---+---+---+\n";
91
-
92
- for (Rank r = RANK_8; r >= RANK_1; --r)
93
- {
94
- for (File f = FILE_A; f <= FILE_H; ++f)
95
- os << " | " << PieceToChar[pos.piece_on(make_square(f, r))];
96
-
97
- os << " |\n +---+---+---+---+---+---+---+---+\n";
98
- }
99
-
100
- os << "\nFen: " << pos.fen() << "\nKey: " << std::hex << std::uppercase
101
- << std::setfill('0') << std::setw(16) << pos.key() << std::dec << "\nCheckers: ";
102
-
103
- for (Bitboard b = pos.checkers(); b; )
104
- os << UCI::square(pop_lsb(&b)) << " ";
105
-
106
- return os;
107
- }
108
-
109
-
110
- /// Position::init() initializes at startup the various arrays used to compute
111
- /// hash keys.
112
-
113
- void Position::init() {
114
-
115
- PRNG rng(1070372);
116
-
117
- for (Piece pc : Pieces)
118
- for (Square s = SQ_A1; s <= SQ_H8; ++s)
119
- Zobrist::psq[pc][s] = rng.rand<Key>();
120
-
121
- for (File f = FILE_A; f <= FILE_H; ++f)
122
- Zobrist::enpassant[f] = rng.rand<Key>();
123
-
124
- for (int cr = NO_CASTLING; cr <= ANY_CASTLING; ++cr)
125
- {
126
- Zobrist::castling[cr] = 0;
127
- Bitboard b = cr;
128
- while (b)
129
- {
130
- Key k = Zobrist::castling[1ULL << pop_lsb(&b)];
131
- Zobrist::castling[cr] ^= k ? k : rng.rand<Key>();
132
- }
133
- }
134
-
135
- Zobrist::side = rng.rand<Key>();
136
- }
137
-
138
-
139
- /// Position::set() initializes the position object with the given FEN string.
140
- /// This function is not very robust - make sure that input FENs are correct,
141
- /// this is assumed to be the responsibility of the GUI.
142
-
143
- Position& Position::set(const string& fenStr, bool isChess960, StateInfo* si, Thread* th) {
144
- /*
145
- A FEN string defines a particular position using only the ASCII character set.
146
-
147
- A FEN string contains six fields separated by a space. The fields are:
148
-
149
- 1) Piece placement (from white's perspective). Each rank is described, starting
150
- with rank 8 and ending with rank 1. Within each rank, the contents of each
151
- square are described from file A through file H. Following the Standard
152
- Algebraic Notation (SAN), each piece is identified by a single letter taken
153
- from the standard English names. White pieces are designated using upper-case
154
- letters ("PNBRQK") whilst Black uses lowercase ("pnbrqk"). Blank squares are
155
- noted using digits 1 through 8 (the number of blank squares), and "/"
156
- separates ranks.
157
-
158
- 2) Active color. "w" means white moves next, "b" means black.
159
-
160
- 3) Castling availability. If neither side can castle, this is "-". Otherwise,
161
- this has one or more letters: "K" (White can castle kingside), "Q" (White
162
- can castle queenside), "k" (Black can castle kingside), and/or "q" (Black
163
- can castle queenside).
164
-
165
- 4) En passant target square (in algebraic notation). If there's no en passant
166
- target square, this is "-". If a pawn has just made a 2-square move, this
167
- is the position "behind" the pawn. This is recorded regardless of whether
168
- there is a pawn in position to make an en passant capture.
169
-
170
- 5) Halfmove clock. This is the number of halfmoves since the last pawn advance
171
- or capture. This is used to determine if a draw can be claimed under the
172
- fifty-move rule.
173
-
174
- 6) Fullmove number. The number of the full move. It starts at 1, and is
175
- incremented after Black's move.
176
- */
177
-
178
- unsigned char col, row, token;
179
- size_t idx;
180
- Square sq = SQ_A8;
181
- std::istringstream ss(fenStr);
182
-
183
- std::memset(this, 0, sizeof(Position));
184
- std::memset(si, 0, sizeof(StateInfo));
185
- std::fill_n(&pieceList[0][0], sizeof(pieceList) / sizeof(Square), SQ_NONE);
186
- st = si;
187
-
188
- ss >> std::noskipws;
189
-
190
- // 1. Piece placement
191
- while ((ss >> token) && !isspace(token))
192
- {
193
- if (isdigit(token))
194
- sq += Square(token - '0'); // Advance the given number of files
195
-
196
- else if (token == '/')
197
- sq -= Square(16);
198
-
199
- else if ((idx = PieceToChar.find(token)) != string::npos)
200
- {
201
- put_piece(Piece(idx), sq);
202
- ++sq;
203
- }
204
- }
205
-
206
- // 2. Active color
207
- ss >> token;
208
- sideToMove = (token == 'w' ? WHITE : BLACK);
209
- ss >> token;
210
-
211
- // 3. Castling availability. Compatible with 3 standards: Normal FEN standard,
212
- // Shredder-FEN that uses the letters of the columns on which the rooks began
213
- // the game instead of KQkq and also X-FEN standard that, in case of Chess960,
214
- // if an inner rook is associated with the castling right, the castling tag is
215
- // replaced by the file letter of the involved rook, as for the Shredder-FEN.
216
- while ((ss >> token) && !isspace(token))
217
- {
218
- Square rsq;
219
- Color c = islower(token) ? BLACK : WHITE;
220
- Piece rook = make_piece(c, ROOK);
221
-
222
- token = char(toupper(token));
223
-
224
- if (token == 'K')
225
- for (rsq = relative_square(c, SQ_H1); piece_on(rsq) != rook; --rsq) {}
226
-
227
- else if (token == 'Q')
228
- for (rsq = relative_square(c, SQ_A1); piece_on(rsq) != rook; ++rsq) {}
229
-
230
- else if (token >= 'A' && token <= 'H')
231
- rsq = make_square(File(token - 'A'), relative_rank(c, RANK_1));
232
-
233
- else
234
- continue;
235
-
236
- set_castling_right(c, rsq);
237
- }
238
-
239
- // 4. En passant square. Ignore if no pawn capture is possible
240
- if ( ((ss >> col) && (col >= 'a' && col <= 'h'))
241
- && ((ss >> row) && (row == '3' || row == '6')))
242
- {
243
- st->epSquare = make_square(File(col - 'a'), Rank(row - '1'));
244
-
245
- if (!(attackers_to(st->epSquare) & pieces(sideToMove, PAWN)))
246
- st->epSquare = SQ_NONE;
247
- }
248
- else
249
- st->epSquare = SQ_NONE;
250
-
251
- // 5-6. Halfmove clock and fullmove number
252
- ss >> std::skipws >> st->rule50 >> gamePly;
253
-
254
- // Convert from fullmove starting from 1 to ply starting from 0,
255
- // handle also common incorrect FEN with fullmove = 0.
256
- gamePly = std::max(2 * (gamePly - 1), 0) + (sideToMove == BLACK);
257
-
258
- chess960 = isChess960;
259
- thisThread = th;
260
- set_state(st);
261
-
262
- assert(pos_is_ok());
263
-
264
- return *this;
265
- }
266
-
267
-
268
- /// Position::set_castling_right() is a helper function used to set castling
269
- /// rights given the corresponding color and the rook starting square.
270
-
271
- void Position::set_castling_right(Color c, Square rfrom) {
272
-
273
- Square kfrom = square<KING>(c);
274
- CastlingSide cs = kfrom < rfrom ? KING_SIDE : QUEEN_SIDE;
275
- CastlingRight cr = (c | cs);
276
-
277
- st->castlingRights |= cr;
278
- castlingRightsMask[kfrom] |= cr;
279
- castlingRightsMask[rfrom] |= cr;
280
- castlingRookSquare[cr] = rfrom;
281
-
282
- Square kto = relative_square(c, cs == KING_SIDE ? SQ_G1 : SQ_C1);
283
- Square rto = relative_square(c, cs == KING_SIDE ? SQ_F1 : SQ_D1);
284
-
285
- for (Square s = std::min(rfrom, rto); s <= std::max(rfrom, rto); ++s)
286
- if (s != kfrom && s != rfrom)
287
- castlingPath[cr] |= s;
288
-
289
- for (Square s = std::min(kfrom, kto); s <= std::max(kfrom, kto); ++s)
290
- if (s != kfrom && s != rfrom)
291
- castlingPath[cr] |= s;
292
- }
293
-
294
-
295
- /// Position::set_check_info() sets king attacks to detect if a move gives check
296
-
297
- void Position::set_check_info(StateInfo* si) const {
298
-
299
- si->blockersForKing[WHITE] = slider_blockers(pieces(BLACK), square<KING>(WHITE), si->pinnersForKing[WHITE]);
300
- si->blockersForKing[BLACK] = slider_blockers(pieces(WHITE), square<KING>(BLACK), si->pinnersForKing[BLACK]);
301
-
302
- Square ksq = square<KING>(~sideToMove);
303
-
304
- si->checkSquares[PAWN] = attacks_from<PAWN>(ksq, ~sideToMove);
305
- si->checkSquares[KNIGHT] = attacks_from<KNIGHT>(ksq);
306
- si->checkSquares[BISHOP] = attacks_from<BISHOP>(ksq);
307
- si->checkSquares[ROOK] = attacks_from<ROOK>(ksq);
308
- si->checkSquares[QUEEN] = si->checkSquares[BISHOP] | si->checkSquares[ROOK];
309
- si->checkSquares[KING] = 0;
310
- }
311
-
312
-
313
- /// Position::set_state() computes the hash keys of the position, and other
314
- /// data that once computed is updated incrementally as moves are made.
315
- /// The function is only used when a new position is set up, and to verify
316
- /// the correctness of the StateInfo data when running in debug mode.
317
-
318
- void Position::set_state(StateInfo* si) const {
319
-
320
- si->key = si->pawnKey = si->materialKey = 0;
321
- si->nonPawnMaterial[WHITE] = si->nonPawnMaterial[BLACK] = VALUE_ZERO;
322
- si->psq = SCORE_ZERO;
323
- si->checkersBB = attackers_to(square<KING>(sideToMove)) & pieces(~sideToMove);
324
-
325
- set_check_info(si);
326
-
327
- for (Bitboard b = pieces(); b; )
328
- {
329
- Square s = pop_lsb(&b);
330
- Piece pc = piece_on(s);
331
- si->key ^= Zobrist::psq[pc][s];
332
- si->psq += PSQT::psq[pc][s];
333
- }
334
-
335
- if (si->epSquare != SQ_NONE)
336
- si->key ^= Zobrist::enpassant[file_of(si->epSquare)];
337
-
338
- if (sideToMove == BLACK)
339
- si->key ^= Zobrist::side;
340
-
341
- si->key ^= Zobrist::castling[si->castlingRights];
342
-
343
- for (Bitboard b = pieces(PAWN); b; )
344
- {
345
- Square s = pop_lsb(&b);
346
- si->pawnKey ^= Zobrist::psq[piece_on(s)][s];
347
- }
348
-
349
- for (Piece pc : Pieces)
350
- {
351
- if (type_of(pc) != PAWN && type_of(pc) != KING)
352
- si->nonPawnMaterial[color_of(pc)] += pieceCount[pc] * PieceValue[MG][pc];
353
-
354
- for (int cnt = 0; cnt < pieceCount[pc]; ++cnt)
355
- si->materialKey ^= Zobrist::psq[pc][cnt];
356
- }
357
- }
358
-
359
-
360
- /// Position::fen() returns a FEN representation of the position. In case of
361
- /// Chess960 the Shredder-FEN notation is used. This is mainly a debugging function.
362
-
363
- const string Position::fen() const {
364
-
365
- int emptyCnt;
366
- std::ostringstream ss;
367
-
368
- for (Rank r = RANK_8; r >= RANK_1; --r)
369
- {
370
- for (File f = FILE_A; f <= FILE_H; ++f)
371
- {
372
- for (emptyCnt = 0; f <= FILE_H && empty(make_square(f, r)); ++f)
373
- ++emptyCnt;
374
-
375
- if (emptyCnt)
376
- ss << emptyCnt;
377
-
378
- if (f <= FILE_H)
379
- ss << PieceToChar[piece_on(make_square(f, r))];
380
- }
381
-
382
- if (r > RANK_1)
383
- ss << '/';
384
- }
385
-
386
- ss << (sideToMove == WHITE ? " w " : " b ");
387
-
388
- if (can_castle(WHITE_OO))
389
- ss << (chess960 ? char('A' + file_of(castling_rook_square(WHITE | KING_SIDE))) : 'K');
390
-
391
- if (can_castle(WHITE_OOO))
392
- ss << (chess960 ? char('A' + file_of(castling_rook_square(WHITE | QUEEN_SIDE))) : 'Q');
393
-
394
- if (can_castle(BLACK_OO))
395
- ss << (chess960 ? char('a' + file_of(castling_rook_square(BLACK | KING_SIDE))) : 'k');
396
-
397
- if (can_castle(BLACK_OOO))
398
- ss << (chess960 ? char('a' + file_of(castling_rook_square(BLACK | QUEEN_SIDE))) : 'q');
399
-
400
- if (!can_castle(WHITE) && !can_castle(BLACK))
401
- ss << '-';
402
-
403
- ss << (ep_square() == SQ_NONE ? " - " : " " + UCI::square(ep_square()) + " ")
404
- << st->rule50 << " " << 1 + (gamePly - (sideToMove == BLACK)) / 2;
405
-
406
- return ss.str();
407
- }
408
-
409
-
410
- /// Position::game_phase() calculates the game phase interpolating total non-pawn
411
- /// material between endgame and midgame limits.
412
-
413
- Phase Position::game_phase() const {
414
-
415
- Value npm = st->nonPawnMaterial[WHITE] + st->nonPawnMaterial[BLACK];
416
-
417
- npm = std::max(EndgameLimit, std::min(npm, MidgameLimit));
418
-
419
- return Phase(((npm - EndgameLimit) * PHASE_MIDGAME) / (MidgameLimit - EndgameLimit));
420
- }
421
-
422
-
423
- /// Position::slider_blockers() returns a bitboard of all the pieces (both colors)
424
- /// that are blocking attacks on the square 's' from 'sliders'. A piece blocks a
425
- /// slider if removing that piece from the board would result in a position where
426
- /// square 's' is attacked. For example, a king-attack blocking piece can be either
427
- /// a pinned or a discovered check piece, according if its color is the opposite
428
- /// or the same of the color of the slider.
429
-
430
- Bitboard Position::slider_blockers(Bitboard sliders, Square s, Bitboard& pinners) const {
431
-
432
- Bitboard result = 0;
433
- pinners = 0;
434
-
435
- // Snipers are sliders that attack 's' when a piece is removed
436
- Bitboard snipers = ( (PseudoAttacks[ROOK ][s] & pieces(QUEEN, ROOK))
437
- | (PseudoAttacks[BISHOP][s] & pieces(QUEEN, BISHOP))) & sliders;
438
-
439
- while (snipers)
440
- {
441
- Square sniperSq = pop_lsb(&snipers);
442
- Bitboard b = between_bb(s, sniperSq) & pieces();
443
-
444
- if (!more_than_one(b))
445
- {
446
- result |= b;
447
- if (b & pieces(color_of(piece_on(s))))
448
- pinners |= sniperSq;
449
- }
450
- }
451
- return result;
452
- }
453
-
454
-
455
- /// Position::attackers_to() computes a bitboard of all pieces which attack a
456
- /// given square. Slider attacks use the occupied bitboard to indicate occupancy.
457
-
458
- Bitboard Position::attackers_to(Square s, Bitboard occupied) const {
459
-
460
- return (attacks_from<PAWN>(s, BLACK) & pieces(WHITE, PAWN))
461
- | (attacks_from<PAWN>(s, WHITE) & pieces(BLACK, PAWN))
462
- | (attacks_from<KNIGHT>(s) & pieces(KNIGHT))
463
- | (attacks_bb<ROOK >(s, occupied) & pieces(ROOK, QUEEN))
464
- | (attacks_bb<BISHOP>(s, occupied) & pieces(BISHOP, QUEEN))
465
- | (attacks_from<KING>(s) & pieces(KING));
466
- }
467
-
468
-
469
- /// Position::legal() tests whether a pseudo-legal move is legal
470
-
471
- bool Position::legal(Move m) const {
472
-
473
- assert(is_ok(m));
474
-
475
- Color us = sideToMove;
476
- Square from = from_sq(m);
477
-
478
- assert(color_of(moved_piece(m)) == us);
479
- assert(piece_on(square<KING>(us)) == make_piece(us, KING));
480
-
481
- // En passant captures are a tricky special case. Because they are rather
482
- // uncommon, we do it simply by testing whether the king is attacked after
483
- // the move is made.
484
- if (type_of(m) == ENPASSANT)
485
- {
486
- Square ksq = square<KING>(us);
487
- Square to = to_sq(m);
488
- Square capsq = to - pawn_push(us);
489
- Bitboard occupied = (pieces() ^ from ^ capsq) | to;
490
-
491
- assert(to == ep_square());
492
- assert(moved_piece(m) == make_piece(us, PAWN));
493
- assert(piece_on(capsq) == make_piece(~us, PAWN));
494
- assert(piece_on(to) == NO_PIECE);
495
-
496
- return !(attacks_bb< ROOK>(ksq, occupied) & pieces(~us, QUEEN, ROOK))
497
- && !(attacks_bb<BISHOP>(ksq, occupied) & pieces(~us, QUEEN, BISHOP));
498
- }
499
-
500
- // If the moving piece is a king, check whether the destination
501
- // square is attacked by the opponent. Castling moves are checked
502
- // for legality during move generation.
503
- if (type_of(piece_on(from)) == KING)
504
- return type_of(m) == CASTLING || !(attackers_to(to_sq(m)) & pieces(~us));
505
-
506
- // A non-king move is legal if and only if it is not pinned or it
507
- // is moving along the ray towards or away from the king.
508
- return !(pinned_pieces(us) & from)
509
- || aligned(from, to_sq(m), square<KING>(us));
510
- }
511
-
512
-
513
- /// Position::pseudo_legal() takes a random move and tests whether the move is
514
- /// pseudo legal. It is used to validate moves from TT that can be corrupted
515
- /// due to SMP concurrent access or hash position key aliasing.
516
-
517
- bool Position::pseudo_legal(const Move m) const {
518
-
519
- Color us = sideToMove;
520
- Square from = from_sq(m);
521
- Square to = to_sq(m);
522
- Piece pc = moved_piece(m);
523
-
524
- // Use a slower but simpler function for uncommon cases
525
- if (type_of(m) != NORMAL)
526
- return MoveList<LEGAL>(*this).contains(m);
527
-
528
- // Is not a promotion, so promotion piece must be empty
529
- if (promotion_type(m) - KNIGHT != NO_PIECE_TYPE)
530
- return false;
531
-
532
- // If the 'from' square is not occupied by a piece belonging to the side to
533
- // move, the move is obviously not legal.
534
- if (pc == NO_PIECE || color_of(pc) != us)
535
- return false;
536
-
537
- // The destination square cannot be occupied by a friendly piece
538
- if (pieces(us) & to)
539
- return false;
540
-
541
- // Handle the special case of a pawn move
542
- if (type_of(pc) == PAWN)
543
- {
544
- // We have already handled promotion moves, so destination
545
- // cannot be on the 8th/1st rank.
546
- if (rank_of(to) == relative_rank(us, RANK_8))
547
- return false;
548
-
549
- if ( !(attacks_from<PAWN>(from, us) & pieces(~us) & to) // Not a capture
550
- && !((from + pawn_push(us) == to) && empty(to)) // Not a single push
551
- && !( (from + 2 * pawn_push(us) == to) // Not a double push
552
- && (rank_of(from) == relative_rank(us, RANK_2))
553
- && empty(to)
554
- && empty(to - pawn_push(us))))
555
- return false;
556
- }
557
- else if (!(attacks_from(pc, from) & to))
558
- return false;
559
-
560
- // Evasions generator already takes care to avoid some kind of illegal moves
561
- // and legal() relies on this. We therefore have to take care that the same
562
- // kind of moves are filtered out here.
563
- if (checkers())
564
- {
565
- if (type_of(pc) != KING)
566
- {
567
- // Double check? In this case a king move is required
568
- if (more_than_one(checkers()))
569
- return false;
570
-
571
- // Our move must be a blocking evasion or a capture of the checking piece
572
- if (!((between_bb(lsb(checkers()), square<KING>(us)) | checkers()) & to))
573
- return false;
574
- }
575
- // In case of king moves under check we have to remove king so as to catch
576
- // invalid moves like b1a1 when opposite queen is on c1.
577
- else if (attackers_to(to, pieces() ^ from) & pieces(~us))
578
- return false;
579
- }
580
-
581
- return true;
582
- }
583
-
584
-
585
- /// Position::gives_check() tests whether a pseudo-legal move gives a check
586
-
587
- bool Position::gives_check(Move m) const {
588
-
589
- assert(is_ok(m));
590
- assert(color_of(moved_piece(m)) == sideToMove);
591
-
592
- Square from = from_sq(m);
593
- Square to = to_sq(m);
594
-
595
- // Is there a direct check?
596
- if (st->checkSquares[type_of(piece_on(from))] & to)
597
- return true;
598
-
599
- // Is there a discovered check?
600
- if ( (discovered_check_candidates() & from)
601
- && !aligned(from, to, square<KING>(~sideToMove)))
602
- return true;
603
-
604
- switch (type_of(m))
605
- {
606
- case NORMAL:
607
- return false;
608
-
609
- case PROMOTION:
610
- return attacks_bb(Piece(promotion_type(m)), to, pieces() ^ from) & square<KING>(~sideToMove);
611
-
612
- // En passant capture with check? We have already handled the case
613
- // of direct checks and ordinary discovered check, so the only case we
614
- // need to handle is the unusual case of a discovered check through
615
- // the captured pawn.
616
- case ENPASSANT:
617
- {
618
- Square capsq = make_square(file_of(to), rank_of(from));
619
- Bitboard b = (pieces() ^ from ^ capsq) | to;
620
-
621
- return (attacks_bb< ROOK>(square<KING>(~sideToMove), b) & pieces(sideToMove, QUEEN, ROOK))
622
- | (attacks_bb<BISHOP>(square<KING>(~sideToMove), b) & pieces(sideToMove, QUEEN, BISHOP));
623
- }
624
- case CASTLING:
625
- {
626
- Square kfrom = from;
627
- Square rfrom = to; // Castling is encoded as 'King captures the rook'
628
- Square kto = relative_square(sideToMove, rfrom > kfrom ? SQ_G1 : SQ_C1);
629
- Square rto = relative_square(sideToMove, rfrom > kfrom ? SQ_F1 : SQ_D1);
630
-
631
- return (PseudoAttacks[ROOK][rto] & square<KING>(~sideToMove))
632
- && (attacks_bb<ROOK>(rto, (pieces() ^ kfrom ^ rfrom) | rto | kto) & square<KING>(~sideToMove));
633
- }
634
- default:
635
- assert(false);
636
- return false;
637
- }
638
- }
639
-
640
-
641
- /// Position::do_move() makes a move, and saves all information necessary
642
- /// to a StateInfo object. The move is assumed to be legal. Pseudo-legal
643
- /// moves should be filtered out before this function is called.
644
-
645
- void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
646
-
647
- assert(is_ok(m));
648
- assert(&newSt != st);
649
-
650
- ++nodes;
651
- Key k = st->key ^ Zobrist::side;
652
-
653
- // Copy some fields of the old state to our new StateInfo object except the
654
- // ones which are going to be recalculated from scratch anyway and then switch
655
- // our state pointer to point to the new (ready to be updated) state.
656
- std::memcpy(&newSt, st, offsetof(StateInfo, key));
657
- newSt.previous = st;
658
- st = &newSt;
659
-
660
- // Increment ply counters. In particular, rule50 will be reset to zero later on
661
- // in case of a capture or a pawn move.
662
- ++gamePly;
663
- ++st->rule50;
664
- ++st->pliesFromNull;
665
-
666
- Color us = sideToMove;
667
- Color them = ~us;
668
- Square from = from_sq(m);
669
- Square to = to_sq(m);
670
- Piece pc = piece_on(from);
671
- Piece captured = type_of(m) == ENPASSANT ? make_piece(them, PAWN) : piece_on(to);
672
-
673
- assert(color_of(pc) == us);
674
- assert(captured == NO_PIECE || color_of(captured) == (type_of(m) != CASTLING ? them : us));
675
- assert(type_of(captured) != KING);
676
-
677
- if (type_of(m) == CASTLING)
678
- {
679
- assert(pc == make_piece(us, KING));
680
- assert(captured == make_piece(us, ROOK));
681
-
682
- Square rfrom, rto;
683
- do_castling<true>(us, from, to, rfrom, rto);
684
-
685
- st->psq += PSQT::psq[captured][rto] - PSQT::psq[captured][rfrom];
686
- k ^= Zobrist::psq[captured][rfrom] ^ Zobrist::psq[captured][rto];
687
- captured = NO_PIECE;
688
- }
689
-
690
- if (captured)
691
- {
692
- Square capsq = to;
693
-
694
- // If the captured piece is a pawn, update pawn hash key, otherwise
695
- // update non-pawn material.
696
- if (type_of(captured) == PAWN)
697
- {
698
- if (type_of(m) == ENPASSANT)
699
- {
700
- capsq -= pawn_push(us);
701
-
702
- assert(pc == make_piece(us, PAWN));
703
- assert(to == st->epSquare);
704
- assert(relative_rank(us, to) == RANK_6);
705
- assert(piece_on(to) == NO_PIECE);
706
- assert(piece_on(capsq) == make_piece(them, PAWN));
707
-
708
- board[capsq] = NO_PIECE; // Not done by remove_piece()
709
- }
710
-
711
- st->pawnKey ^= Zobrist::psq[captured][capsq];
712
- }
713
- else
714
- st->nonPawnMaterial[them] -= PieceValue[MG][captured];
715
-
716
- // Update board and piece lists
717
- remove_piece(captured, capsq);
718
-
719
- // Update material hash key and prefetch access to materialTable
720
- k ^= Zobrist::psq[captured][capsq];
721
- st->materialKey ^= Zobrist::psq[captured][pieceCount[captured]];
722
- prefetch(thisThread->materialTable[st->materialKey]);
723
-
724
- // Update incremental scores
725
- st->psq -= PSQT::psq[captured][capsq];
726
-
727
- // Reset rule 50 counter
728
- st->rule50 = 0;
729
- }
730
-
731
- // Update hash key
732
- k ^= Zobrist::psq[pc][from] ^ Zobrist::psq[pc][to];
733
-
734
- // Reset en passant square
735
- if (st->epSquare != SQ_NONE)
736
- {
737
- k ^= Zobrist::enpassant[file_of(st->epSquare)];
738
- st->epSquare = SQ_NONE;
739
- }
740
-
741
- // Update castling rights if needed
742
- if (st->castlingRights && (castlingRightsMask[from] | castlingRightsMask[to]))
743
- {
744
- int cr = castlingRightsMask[from] | castlingRightsMask[to];
745
- k ^= Zobrist::castling[st->castlingRights & cr];
746
- st->castlingRights &= ~cr;
747
- }
748
-
749
- // Move the piece. The tricky Chess960 castling is handled earlier
750
- if (type_of(m) != CASTLING)
751
- move_piece(pc, from, to);
752
-
753
- // If the moving piece is a pawn do some special extra work
754
- if (type_of(pc) == PAWN)
755
- {
756
- // Set en-passant square if the moved pawn can be captured
757
- if ( (int(to) ^ int(from)) == 16
758
- && (attacks_from<PAWN>(to - pawn_push(us), us) & pieces(them, PAWN)))
759
- {
760
- st->epSquare = (from + to) / 2;
761
- k ^= Zobrist::enpassant[file_of(st->epSquare)];
762
- }
763
-
764
- else if (type_of(m) == PROMOTION)
765
- {
766
- Piece promotion = make_piece(us, promotion_type(m));
767
-
768
- assert(relative_rank(us, to) == RANK_8);
769
- assert(type_of(promotion) >= KNIGHT && type_of(promotion) <= QUEEN);
770
-
771
- remove_piece(pc, to);
772
- put_piece(promotion, to);
773
-
774
- // Update hash keys
775
- k ^= Zobrist::psq[pc][to] ^ Zobrist::psq[promotion][to];
776
- st->pawnKey ^= Zobrist::psq[pc][to];
777
- st->materialKey ^= Zobrist::psq[promotion][pieceCount[promotion]-1]
778
- ^ Zobrist::psq[pc][pieceCount[pc]];
779
-
780
- // Update incremental score
781
- st->psq += PSQT::psq[promotion][to] - PSQT::psq[pc][to];
782
-
783
- // Update material
784
- st->nonPawnMaterial[us] += PieceValue[MG][promotion];
785
- }
786
-
787
- // Update pawn hash key and prefetch access to pawnsTable
788
- st->pawnKey ^= Zobrist::psq[pc][from] ^ Zobrist::psq[pc][to];
789
- prefetch(thisThread->pawnsTable[st->pawnKey]);
790
-
791
- // Reset rule 50 draw counter
792
- st->rule50 = 0;
793
- }
794
-
795
- // Update incremental scores
796
- st->psq += PSQT::psq[pc][to] - PSQT::psq[pc][from];
797
-
798
- // Set capture piece
799
- st->capturedPiece = captured;
800
-
801
- // Update the key with the final value
802
- st->key = k;
803
-
804
- // Calculate checkers bitboard (if move gives check)
805
- st->checkersBB = givesCheck ? attackers_to(square<KING>(them)) & pieces(us) : 0;
806
-
807
- sideToMove = ~sideToMove;
808
-
809
- // Update king attacks used for fast check detection
810
- set_check_info(st);
811
-
812
- assert(pos_is_ok());
813
- }
814
-
815
-
816
- /// Position::undo_move() unmakes a move. When it returns, the position should
817
- /// be restored to exactly the same state as before the move was made.
818
-
819
- void Position::undo_move(Move m) {
820
-
821
- assert(is_ok(m));
822
-
823
- sideToMove = ~sideToMove;
824
-
825
- Color us = sideToMove;
826
- Square from = from_sq(m);
827
- Square to = to_sq(m);
828
- Piece pc = piece_on(to);
829
-
830
- assert(empty(from) || type_of(m) == CASTLING);
831
- assert(type_of(st->capturedPiece) != KING);
832
-
833
- if (type_of(m) == PROMOTION)
834
- {
835
- assert(relative_rank(us, to) == RANK_8);
836
- assert(type_of(pc) == promotion_type(m));
837
- assert(type_of(pc) >= KNIGHT && type_of(pc) <= QUEEN);
838
-
839
- remove_piece(pc, to);
840
- pc = make_piece(us, PAWN);
841
- put_piece(pc, to);
842
- }
843
-
844
- if (type_of(m) == CASTLING)
845
- {
846
- Square rfrom, rto;
847
- do_castling<false>(us, from, to, rfrom, rto);
848
- }
849
- else
850
- {
851
- move_piece(pc, to, from); // Put the piece back at the source square
852
-
853
- if (st->capturedPiece)
854
- {
855
- Square capsq = to;
856
-
857
- if (type_of(m) == ENPASSANT)
858
- {
859
- capsq -= pawn_push(us);
860
-
861
- assert(type_of(pc) == PAWN);
862
- assert(to == st->previous->epSquare);
863
- assert(relative_rank(us, to) == RANK_6);
864
- assert(piece_on(capsq) == NO_PIECE);
865
- assert(st->capturedPiece == make_piece(~us, PAWN));
866
- }
867
-
868
- put_piece(st->capturedPiece, capsq); // Restore the captured piece
869
- }
870
- }
871
-
872
- // Finally point our state pointer back to the previous state
873
- st = st->previous;
874
- --gamePly;
875
-
876
- assert(pos_is_ok());
877
- }
878
-
879
-
880
- /// Position::do_castling() is a helper used to do/undo a castling move. This
881
- /// is a bit tricky in Chess960 where from/to squares can overlap.
882
- template<bool Do>
883
- void Position::do_castling(Color us, Square from, Square& to, Square& rfrom, Square& rto) {
884
-
885
- bool kingSide = to > from;
886
- rfrom = to; // Castling is encoded as "king captures friendly rook"
887
- rto = relative_square(us, kingSide ? SQ_F1 : SQ_D1);
888
- to = relative_square(us, kingSide ? SQ_G1 : SQ_C1);
889
-
890
- // Remove both pieces first since squares could overlap in Chess960
891
- remove_piece(make_piece(us, KING), Do ? from : to);
892
- remove_piece(make_piece(us, ROOK), Do ? rfrom : rto);
893
- board[Do ? from : to] = board[Do ? rfrom : rto] = NO_PIECE; // Since remove_piece doesn't do it for us
894
- put_piece(make_piece(us, KING), Do ? to : from);
895
- put_piece(make_piece(us, ROOK), Do ? rto : rfrom);
896
- }
897
-
898
-
899
- /// Position::do(undo)_null_move() is used to do(undo) a "null move": It flips
900
- /// the side to move without executing any move on the board.
901
-
902
- void Position::do_null_move(StateInfo& newSt) {
903
-
904
- assert(!checkers());
905
- assert(&newSt != st);
906
-
907
- std::memcpy(&newSt, st, sizeof(StateInfo));
908
- newSt.previous = st;
909
- st = &newSt;
910
-
911
- if (st->epSquare != SQ_NONE)
912
- {
913
- st->key ^= Zobrist::enpassant[file_of(st->epSquare)];
914
- st->epSquare = SQ_NONE;
915
- }
916
-
917
- st->key ^= Zobrist::side;
918
- prefetch(TT.first_entry(st->key));
919
-
920
- ++st->rule50;
921
- st->pliesFromNull = 0;
922
-
923
- sideToMove = ~sideToMove;
924
-
925
- set_check_info(st);
926
-
927
- assert(pos_is_ok());
928
- }
929
-
930
- void Position::undo_null_move() {
931
-
932
- assert(!checkers());
933
-
934
- st = st->previous;
935
- sideToMove = ~sideToMove;
936
- }
937
-
938
-
939
- /// Position::key_after() computes the new hash key after the given move. Needed
940
- /// for speculative prefetch. It doesn't recognize special moves like castling,
941
- /// en-passant and promotions.
942
-
943
- Key Position::key_after(Move m) const {
944
-
945
- Square from = from_sq(m);
946
- Square to = to_sq(m);
947
- Piece pc = piece_on(from);
948
- Piece captured = piece_on(to);
949
- Key k = st->key ^ Zobrist::side;
950
-
951
- if (captured)
952
- k ^= Zobrist::psq[captured][to];
953
-
954
- return k ^ Zobrist::psq[pc][to] ^ Zobrist::psq[pc][from];
955
- }
956
-
957
-
958
- /// Position::see_ge (Static Exchange Evaluation Greater or Equal) tests if the
959
- /// SEE value of move is greater or equal to the given value. We'll use an
960
- /// algorithm similar to alpha-beta pruning with a null window.
961
-
962
- bool Position::see_ge(Move m, Value v) const {
963
-
964
- assert(is_ok(m));
965
-
966
- // Castling moves are implemented as king capturing the rook so cannot be
967
- // handled correctly. Simply assume the SEE value is VALUE_ZERO that is always
968
- // correct unless in the rare case the rook ends up under attack.
969
- if (type_of(m) == CASTLING)
970
- return VALUE_ZERO >= v;
971
-
972
- Square from = from_sq(m), to = to_sq(m);
973
- PieceType nextVictim = type_of(piece_on(from));
974
- Color stm = ~color_of(piece_on(from)); // First consider opponent's move
975
- Value balance; // Values of the pieces taken by us minus opponent's ones
976
- Bitboard occupied, stmAttackers;
977
-
978
- if (type_of(m) == ENPASSANT)
979
- {
980
- occupied = SquareBB[to - pawn_push(~stm)]; // Remove the captured pawn
981
- balance = PieceValue[MG][PAWN];
982
- }
983
- else
984
- {
985
- balance = PieceValue[MG][piece_on(to)];
986
- occupied = 0;
987
- }
988
-
989
- if (balance < v)
990
- return false;
991
-
992
- if (nextVictim == KING)
993
- return true;
994
-
995
- balance -= PieceValue[MG][nextVictim];
996
-
997
- if (balance >= v)
998
- return true;
999
-
1000
- bool relativeStm = true; // True if the opponent is to move
1001
- occupied ^= pieces() ^ from ^ to;
1002
-
1003
- // Find all attackers to the destination square, with the moving piece removed,
1004
- // but possibly an X-ray attacker added behind it.
1005
- Bitboard attackers = attackers_to(to, occupied) & occupied;
1006
-
1007
- while (true)
1008
- {
1009
- stmAttackers = attackers & pieces(stm);
1010
-
1011
- // Don't allow pinned pieces to attack pieces except the king as long all
1012
- // pinners are on their original square.
1013
- if (!(st->pinnersForKing[stm] & ~occupied))
1014
- stmAttackers &= ~st->blockersForKing[stm];
1015
-
1016
- if (!stmAttackers)
1017
- return relativeStm;
1018
-
1019
- // Locate and remove the next least valuable attacker
1020
- nextVictim = min_attacker<PAWN>(byTypeBB, to, stmAttackers, occupied, attackers);
1021
-
1022
- if (nextVictim == KING)
1023
- return relativeStm == bool(attackers & pieces(~stm));
1024
-
1025
- balance += relativeStm ? PieceValue[MG][nextVictim]
1026
- : -PieceValue[MG][nextVictim];
1027
-
1028
- relativeStm = !relativeStm;
1029
-
1030
- if (relativeStm == (balance >= v))
1031
- return relativeStm;
1032
-
1033
- stm = ~stm;
1034
- }
1035
- }
1036
-
1037
-
1038
- /// Position::is_draw() tests whether the position is drawn by 50-move rule
1039
- /// or by repetition. It does not detect stalemates.
1040
-
1041
- bool Position::is_draw() const {
1042
-
1043
- if (st->rule50 > 99 && (!checkers() || MoveList<LEGAL>(*this).size()))
1044
- return true;
1045
-
1046
- StateInfo* stp = st;
1047
- for (int i = 2, e = std::min(st->rule50, st->pliesFromNull); i <= e; i += 2)
1048
- {
1049
- stp = stp->previous->previous;
1050
-
1051
- if (stp->key == st->key)
1052
- return true; // Draw at first repetition
1053
- }
1054
-
1055
- return false;
1056
- }
1057
-
1058
-
1059
- /// Position::flip() flips position with the white and black sides reversed. This
1060
- /// is only useful for debugging e.g. for finding evaluation symmetry bugs.
1061
-
1062
- void Position::flip() {
1063
-
1064
- string f, token;
1065
- std::stringstream ss(fen());
1066
-
1067
- for (Rank r = RANK_8; r >= RANK_1; --r) // Piece placement
1068
- {
1069
- std::getline(ss, token, r > RANK_1 ? '/' : ' ');
1070
- f.insert(0, token + (f.empty() ? " " : "/"));
1071
- }
1072
-
1073
- ss >> token; // Active color
1074
- f += (token == "w" ? "B " : "W "); // Will be lowercased later
1075
-
1076
- ss >> token; // Castling availability
1077
- f += token + " ";
1078
-
1079
- std::transform(f.begin(), f.end(), f.begin(),
1080
- [](char c) { return char(islower(c) ? toupper(c) : tolower(c)); });
1081
-
1082
- ss >> token; // En passant square
1083
- f += (token == "-" ? token : token.replace(1, 1, token[1] == '3' ? "6" : "3"));
1084
-
1085
- std::getline(ss, token); // Half and full moves
1086
- f += token;
1087
-
1088
- set(f, is_chess960(), st, this_thread());
1089
-
1090
- assert(pos_is_ok());
1091
- }
1092
-
1093
-
1094
- /// Position::pos_is_ok() performs some consistency checks for the position object.
1095
- /// This is meant to be helpful when debugging.
1096
-
1097
- bool Position::pos_is_ok(int* failedStep) const {
1098
-
1099
- const bool Fast = true; // Quick (default) or full check?
1100
-
1101
- enum { Default, King, Bitboards, State, Lists, Castling };
1102
-
1103
- for (int step = Default; step <= (Fast ? Default : Castling); step++)
1104
- {
1105
- if (failedStep)
1106
- *failedStep = step;
1107
-
1108
- if (step == Default)
1109
- if ( (sideToMove != WHITE && sideToMove != BLACK)
1110
- || piece_on(square<KING>(WHITE)) != W_KING
1111
- || piece_on(square<KING>(BLACK)) != B_KING
1112
- || ( ep_square() != SQ_NONE
1113
- && relative_rank(sideToMove, ep_square()) != RANK_6))
1114
- return false;
1115
-
1116
- if (step == King)
1117
- if ( std::count(board, board + SQUARE_NB, W_KING) != 1
1118
- || std::count(board, board + SQUARE_NB, B_KING) != 1
1119
- || attackers_to(square<KING>(~sideToMove)) & pieces(sideToMove))
1120
- return false;
1121
-
1122
- if (step == Bitboards)
1123
- {
1124
- if ( (pieces(WHITE) & pieces(BLACK))
1125
- ||(pieces(WHITE) | pieces(BLACK)) != pieces())
1126
- return false;
1127
-
1128
- for (PieceType p1 = PAWN; p1 <= KING; ++p1)
1129
- for (PieceType p2 = PAWN; p2 <= KING; ++p2)
1130
- if (p1 != p2 && (pieces(p1) & pieces(p2)))
1131
- return false;
1132
- }
1133
-
1134
- if (step == State)
1135
- {
1136
- StateInfo si = *st;
1137
- set_state(&si);
1138
- if (std::memcmp(&si, st, sizeof(StateInfo)))
1139
- return false;
1140
- }
1141
-
1142
- if (step == Lists)
1143
- for (Piece pc : Pieces)
1144
- {
1145
- if (pieceCount[pc] != popcount(pieces(color_of(pc), type_of(pc))))
1146
- return false;
1147
-
1148
- for (int i = 0; i < pieceCount[pc]; ++i)
1149
- if (board[pieceList[pc][i]] != pc || index[pieceList[pc][i]] != i)
1150
- return false;
1151
- }
1152
-
1153
- if (step == Castling)
1154
- for (Color c = WHITE; c <= BLACK; ++c)
1155
- for (CastlingSide s = KING_SIDE; s <= QUEEN_SIDE; s = CastlingSide(s + 1))
1156
- {
1157
- if (!can_castle(c | s))
1158
- continue;
1159
-
1160
- if ( piece_on(castlingRookSquare[c | s]) != make_piece(c, ROOK)
1161
- || castlingRightsMask[castlingRookSquare[c | s]] != (c | s)
1162
- ||(castlingRightsMask[square<KING>(c)] & (c | s)) != (c | s))
1163
- return false;
1164
- }
1165
- }
1166
-
1167
- return true;
1168
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/position.h DELETED
@@ -1,414 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #ifndef POSITION_H_INCLUDED
22
- #define POSITION_H_INCLUDED
23
-
24
- #include <cassert>
25
- #include <deque>
26
- #include <memory> // For std::unique_ptr
27
- #include <string>
28
-
29
- #include "bitboard.h"
30
- #include "types.h"
31
-
32
-
33
- /// StateInfo struct stores information needed to restore a Position object to
34
- /// its previous state when we retract a move. Whenever a move is made on the
35
- /// board (by calling Position::do_move), a StateInfo object must be passed.
36
-
37
- struct StateInfo {
38
-
39
- // Copied when making a move
40
- Key pawnKey;
41
- Key materialKey;
42
- Value nonPawnMaterial[COLOR_NB];
43
- int castlingRights;
44
- int rule50;
45
- int pliesFromNull;
46
- Score psq;
47
- Square epSquare;
48
-
49
- // Not copied when making a move (will be recomputed anyhow)
50
- Key key;
51
- Bitboard checkersBB;
52
- Piece capturedPiece;
53
- StateInfo* previous;
54
- Bitboard blockersForKing[COLOR_NB];
55
- Bitboard pinnersForKing[COLOR_NB];
56
- Bitboard checkSquares[PIECE_TYPE_NB];
57
- };
58
-
59
- // In a std::deque references to elements are unaffected upon resizing
60
- typedef std::unique_ptr<std::deque<StateInfo>> StateListPtr;
61
-
62
-
63
- /// Position class stores information regarding the board representation as
64
- /// pieces, side to move, hash keys, castling info, etc. Important methods are
65
- /// do_move() and undo_move(), used by the search to update node info when
66
- /// traversing the search tree.
67
- class Thread;
68
-
69
- class Position {
70
- public:
71
- static void init();
72
-
73
- Position() = default;
74
- Position(const Position&) = delete;
75
- Position& operator=(const Position&) = delete;
76
-
77
- // FEN string input/output
78
- Position& set(const std::string& fenStr, bool isChess960, StateInfo* si, Thread* th);
79
- const std::string fen() const;
80
-
81
- // Position representation
82
- Bitboard pieces() const;
83
- Bitboard pieces(PieceType pt) const;
84
- Bitboard pieces(PieceType pt1, PieceType pt2) const;
85
- Bitboard pieces(Color c) const;
86
- Bitboard pieces(Color c, PieceType pt) const;
87
- Bitboard pieces(Color c, PieceType pt1, PieceType pt2) const;
88
- Piece piece_on(Square s) const;
89
- Square ep_square() const;
90
- bool empty(Square s) const;
91
- template<PieceType Pt> int count(Color c) const;
92
- template<PieceType Pt> const Square* squares(Color c) const;
93
- template<PieceType Pt> Square square(Color c) const;
94
-
95
- // Castling
96
- int can_castle(Color c) const;
97
- int can_castle(CastlingRight cr) const;
98
- bool castling_impeded(CastlingRight cr) const;
99
- Square castling_rook_square(CastlingRight cr) const;
100
-
101
- // Checking
102
- Bitboard checkers() const;
103
- Bitboard discovered_check_candidates() const;
104
- Bitboard pinned_pieces(Color c) const;
105
- Bitboard check_squares(PieceType pt) const;
106
-
107
- // Attacks to/from a given square
108
- Bitboard attackers_to(Square s) const;
109
- Bitboard attackers_to(Square s, Bitboard occupied) const;
110
- Bitboard attacks_from(Piece pc, Square s) const;
111
- template<PieceType> Bitboard attacks_from(Square s) const;
112
- template<PieceType> Bitboard attacks_from(Square s, Color c) const;
113
- Bitboard slider_blockers(Bitboard sliders, Square s, Bitboard& pinners) const;
114
-
115
- // Properties of moves
116
- bool legal(Move m) const;
117
- bool pseudo_legal(const Move m) const;
118
- bool capture(Move m) const;
119
- bool capture_or_promotion(Move m) const;
120
- bool gives_check(Move m) const;
121
- bool advanced_pawn_push(Move m) const;
122
- Piece moved_piece(Move m) const;
123
- Piece captured_piece() const;
124
-
125
- // Piece specific
126
- bool pawn_passed(Color c, Square s) const;
127
- bool opposite_bishops() const;
128
-
129
- // Doing and undoing moves
130
- void do_move(Move m, StateInfo& st, bool givesCheck);
131
- void undo_move(Move m);
132
- void do_null_move(StateInfo& st);
133
- void undo_null_move();
134
-
135
- // Static Exchange Evaluation
136
- bool see_ge(Move m, Value value) const;
137
-
138
- // Accessing hash keys
139
- Key key() const;
140
- Key key_after(Move m) const;
141
- Key material_key() const;
142
- Key pawn_key() const;
143
-
144
- // Other properties of the position
145
- Color side_to_move() const;
146
- Phase game_phase() const;
147
- int game_ply() const;
148
- bool is_chess960() const;
149
- Thread* this_thread() const;
150
- uint64_t nodes_searched() const;
151
- bool is_draw() const;
152
- int rule50_count() const;
153
- Score psq_score() const;
154
- Value non_pawn_material(Color c) const;
155
-
156
- // Position consistency check, for debugging
157
- bool pos_is_ok(int* failedStep = nullptr) const;
158
- void flip();
159
-
160
- private:
161
- // Initialization helpers (used while setting up a position)
162
- void set_castling_right(Color c, Square rfrom);
163
- void set_state(StateInfo* si) const;
164
- void set_check_info(StateInfo* si) const;
165
-
166
- // Other helpers
167
- void put_piece(Piece pc, Square s);
168
- void remove_piece(Piece pc, Square s);
169
- void move_piece(Piece pc, Square from, Square to);
170
- template<bool Do>
171
- void do_castling(Color us, Square from, Square& to, Square& rfrom, Square& rto);
172
-
173
- // Data members
174
- Piece board[SQUARE_NB];
175
- Bitboard byTypeBB[PIECE_TYPE_NB];
176
- Bitboard byColorBB[COLOR_NB];
177
- int pieceCount[PIECE_NB];
178
- Square pieceList[PIECE_NB][16];
179
- int index[SQUARE_NB];
180
- int castlingRightsMask[SQUARE_NB];
181
- Square castlingRookSquare[CASTLING_RIGHT_NB];
182
- Bitboard castlingPath[CASTLING_RIGHT_NB];
183
- uint64_t nodes;
184
- int gamePly;
185
- Color sideToMove;
186
- Thread* thisThread;
187
- StateInfo* st;
188
- bool chess960;
189
- };
190
-
191
- extern std::ostream& operator<<(std::ostream& os, const Position& pos);
192
-
193
- inline Color Position::side_to_move() const {
194
- return sideToMove;
195
- }
196
-
197
- inline bool Position::empty(Square s) const {
198
- return board[s] == NO_PIECE;
199
- }
200
-
201
- inline Piece Position::piece_on(Square s) const {
202
- return board[s];
203
- }
204
-
205
- inline Piece Position::moved_piece(Move m) const {
206
- return board[from_sq(m)];
207
- }
208
-
209
- inline Bitboard Position::pieces() const {
210
- return byTypeBB[ALL_PIECES];
211
- }
212
-
213
- inline Bitboard Position::pieces(PieceType pt) const {
214
- return byTypeBB[pt];
215
- }
216
-
217
- inline Bitboard Position::pieces(PieceType pt1, PieceType pt2) const {
218
- return byTypeBB[pt1] | byTypeBB[pt2];
219
- }
220
-
221
- inline Bitboard Position::pieces(Color c) const {
222
- return byColorBB[c];
223
- }
224
-
225
- inline Bitboard Position::pieces(Color c, PieceType pt) const {
226
- return byColorBB[c] & byTypeBB[pt];
227
- }
228
-
229
- inline Bitboard Position::pieces(Color c, PieceType pt1, PieceType pt2) const {
230
- return byColorBB[c] & (byTypeBB[pt1] | byTypeBB[pt2]);
231
- }
232
-
233
- template<PieceType Pt> inline int Position::count(Color c) const {
234
- return pieceCount[make_piece(c, Pt)];
235
- }
236
-
237
- template<PieceType Pt> inline const Square* Position::squares(Color c) const {
238
- return pieceList[make_piece(c, Pt)];
239
- }
240
-
241
- template<PieceType Pt> inline Square Position::square(Color c) const {
242
- assert(pieceCount[make_piece(c, Pt)] == 1);
243
- return pieceList[make_piece(c, Pt)][0];
244
- }
245
-
246
- inline Square Position::ep_square() const {
247
- return st->epSquare;
248
- }
249
-
250
- inline int Position::can_castle(CastlingRight cr) const {
251
- return st->castlingRights & cr;
252
- }
253
-
254
- inline int Position::can_castle(Color c) const {
255
- return st->castlingRights & ((WHITE_OO | WHITE_OOO) << (2 * c));
256
- }
257
-
258
- inline bool Position::castling_impeded(CastlingRight cr) const {
259
- return byTypeBB[ALL_PIECES] & castlingPath[cr];
260
- }
261
-
262
- inline Square Position::castling_rook_square(CastlingRight cr) const {
263
- return castlingRookSquare[cr];
264
- }
265
-
266
- template<PieceType Pt>
267
- inline Bitboard Position::attacks_from(Square s) const {
268
- return Pt == BISHOP || Pt == ROOK ? attacks_bb<Pt>(s, byTypeBB[ALL_PIECES])
269
- : Pt == QUEEN ? attacks_from<ROOK>(s) | attacks_from<BISHOP>(s)
270
- : StepAttacksBB[Pt][s];
271
- }
272
-
273
- template<>
274
- inline Bitboard Position::attacks_from<PAWN>(Square s, Color c) const {
275
- return StepAttacksBB[make_piece(c, PAWN)][s];
276
- }
277
-
278
- inline Bitboard Position::attacks_from(Piece pc, Square s) const {
279
- return attacks_bb(pc, s, byTypeBB[ALL_PIECES]);
280
- }
281
-
282
- inline Bitboard Position::attackers_to(Square s) const {
283
- return attackers_to(s, byTypeBB[ALL_PIECES]);
284
- }
285
-
286
- inline Bitboard Position::checkers() const {
287
- return st->checkersBB;
288
- }
289
-
290
- inline Bitboard Position::discovered_check_candidates() const {
291
- return st->blockersForKing[~sideToMove] & pieces(sideToMove);
292
- }
293
-
294
- inline Bitboard Position::pinned_pieces(Color c) const {
295
- return st->blockersForKing[c] & pieces(c);
296
- }
297
-
298
- inline Bitboard Position::check_squares(PieceType pt) const {
299
- return st->checkSquares[pt];
300
- }
301
-
302
- inline bool Position::pawn_passed(Color c, Square s) const {
303
- return !(pieces(~c, PAWN) & passed_pawn_mask(c, s));
304
- }
305
-
306
- inline bool Position::advanced_pawn_push(Move m) const {
307
- return type_of(moved_piece(m)) == PAWN
308
- && relative_rank(sideToMove, from_sq(m)) > RANK_4;
309
- }
310
-
311
- inline Key Position::key() const {
312
- return st->key;
313
- }
314
-
315
- inline Key Position::pawn_key() const {
316
- return st->pawnKey;
317
- }
318
-
319
- inline Key Position::material_key() const {
320
- return st->materialKey;
321
- }
322
-
323
- inline Score Position::psq_score() const {
324
- return st->psq;
325
- }
326
-
327
- inline Value Position::non_pawn_material(Color c) const {
328
- return st->nonPawnMaterial[c];
329
- }
330
-
331
- inline int Position::game_ply() const {
332
- return gamePly;
333
- }
334
-
335
- inline int Position::rule50_count() const {
336
- return st->rule50;
337
- }
338
-
339
- inline uint64_t Position::nodes_searched() const {
340
- return nodes;
341
- }
342
-
343
- inline bool Position::opposite_bishops() const {
344
- return pieceCount[W_BISHOP] == 1
345
- && pieceCount[B_BISHOP] == 1
346
- && opposite_colors(square<BISHOP>(WHITE), square<BISHOP>(BLACK));
347
- }
348
-
349
- inline bool Position::is_chess960() const {
350
- return chess960;
351
- }
352
-
353
- inline bool Position::capture_or_promotion(Move m) const {
354
- assert(is_ok(m));
355
- return type_of(m) != NORMAL ? type_of(m) != CASTLING : !empty(to_sq(m));
356
- }
357
-
358
- inline bool Position::capture(Move m) const {
359
- assert(is_ok(m));
360
- // Castling is encoded as "king captures rook"
361
- return (!empty(to_sq(m)) && type_of(m) != CASTLING) || type_of(m) == ENPASSANT;
362
- }
363
-
364
- inline Piece Position::captured_piece() const {
365
- return st->capturedPiece;
366
- }
367
-
368
- inline Thread* Position::this_thread() const {
369
- return thisThread;
370
- }
371
-
372
- inline void Position::put_piece(Piece pc, Square s) {
373
-
374
- board[s] = pc;
375
- byTypeBB[ALL_PIECES] |= s;
376
- byTypeBB[type_of(pc)] |= s;
377
- byColorBB[color_of(pc)] |= s;
378
- index[s] = pieceCount[pc]++;
379
- pieceList[pc][index[s]] = s;
380
- pieceCount[make_piece(color_of(pc), ALL_PIECES)]++;
381
- }
382
-
383
- inline void Position::remove_piece(Piece pc, Square s) {
384
-
385
- // WARNING: This is not a reversible operation. If we remove a piece in
386
- // do_move() and then replace it in undo_move() we will put it at the end of
387
- // the list and not in its original place, it means index[] and pieceList[]
388
- // are not invariant to a do_move() + undo_move() sequence.
389
- byTypeBB[ALL_PIECES] ^= s;
390
- byTypeBB[type_of(pc)] ^= s;
391
- byColorBB[color_of(pc)] ^= s;
392
- /* board[s] = NO_PIECE; Not needed, overwritten by the capturing one */
393
- Square lastSquare = pieceList[pc][--pieceCount[pc]];
394
- index[lastSquare] = index[s];
395
- pieceList[pc][index[lastSquare]] = lastSquare;
396
- pieceList[pc][pieceCount[pc]] = SQ_NONE;
397
- pieceCount[make_piece(color_of(pc), ALL_PIECES)]--;
398
- }
399
-
400
- inline void Position::move_piece(Piece pc, Square from, Square to) {
401
-
402
- // index[from] is not updated and becomes stale. This works as long as index[]
403
- // is accessed just by known occupied squares.
404
- Bitboard from_to_bb = SquareBB[from] ^ SquareBB[to];
405
- byTypeBB[ALL_PIECES] ^= from_to_bb;
406
- byTypeBB[type_of(pc)] ^= from_to_bb;
407
- byColorBB[color_of(pc)] ^= from_to_bb;
408
- board[from] = NO_PIECE;
409
- board[to] = pc;
410
- index[to] = index[from];
411
- pieceList[pc][index[to]] = to;
412
- }
413
-
414
- #endif // #ifndef POSITION_H_INCLUDED
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/psqt.cpp DELETED
@@ -1,126 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #include <algorithm>
22
-
23
- #include "types.h"
24
-
25
- Value PieceValue[PHASE_NB][PIECE_NB] = {
26
- { VALUE_ZERO, PawnValueMg, KnightValueMg, BishopValueMg, RookValueMg, QueenValueMg },
27
- { VALUE_ZERO, PawnValueEg, KnightValueEg, BishopValueEg, RookValueEg, QueenValueEg }
28
- };
29
-
30
- namespace PSQT {
31
-
32
- #define S(mg, eg) make_score(mg, eg)
33
-
34
- // Bonus[PieceType][Square / 2] contains Piece-Square scores. For each piece
35
- // type on a given square a (middlegame, endgame) score pair is assigned. Table
36
- // is defined for files A..D and white side: it is symmetric for black side and
37
- // second half of the files.
38
- const Score Bonus[][RANK_NB][int(FILE_NB) / 2] = {
39
- { },
40
- { // Pawn
41
- { S( 0, 0), S( 0, 0), S( 0, 0), S( 0, 0) },
42
- { S(-16, 7), S( 1,-4), S( 7, 8), S( 3,-2) },
43
- { S(-23,-4), S( -7,-5), S( 19, 5), S(24, 4) },
44
- { S(-22, 3), S(-14, 3), S( 20,-8), S(35,-3) },
45
- { S(-11, 8), S( 0, 9), S( 3, 7), S(21,-6) },
46
- { S(-11, 8), S(-13,-5), S( -6, 2), S(-2, 4) },
47
- { S( -9, 3), S( 15,-9), S( -8, 1), S(-4,18) }
48
- },
49
- { // Knight
50
- { S(-143, -97), S(-96,-82), S(-80,-46), S(-73,-14) },
51
- { S( -83, -69), S(-43,-55), S(-21,-17), S(-10, 9) },
52
- { S( -71, -50), S(-22,-39), S( 0, -8), S( 9, 28) },
53
- { S( -25, -41), S( 18,-25), S( 43, 7), S( 47, 38) },
54
- { S( -26, -46), S( 16,-25), S( 38, 2), S( 50, 41) },
55
- { S( -11, -55), S( 37,-38), S( 56, -8), S( 71, 27) },
56
- { S( -62, -64), S(-17,-50), S( 5,-24), S( 14, 13) },
57
- { S(-195,-110), S(-66,-90), S(-42,-50), S(-29,-13) }
58
- },
59
- { // Bishop
60
- { S(-54,-68), S(-23,-40), S(-35,-46), S(-44,-28) },
61
- { S(-30,-43), S( 10,-17), S( 2,-23), S( -9, -5) },
62
- { S(-19,-32), S( 17, -9), S( 11,-13), S( 1, 8) },
63
- { S(-21,-36), S( 18,-13), S( 11,-15), S( 0, 7) },
64
- { S(-21,-36), S( 14,-14), S( 6,-17), S( -1, 3) },
65
- { S(-27,-35), S( 6,-13), S( 2,-10), S( -8, 1) },
66
- { S(-33,-44), S( 7,-21), S( -4,-22), S(-12, -4) },
67
- { S(-45,-65), S(-21,-42), S(-29,-46), S(-39,-27) }
68
- },
69
- { // Rook
70
- { S(-25, 0), S(-16, 0), S(-16, 0), S(-9, 0) },
71
- { S(-21, 0), S( -8, 0), S( -3, 0), S( 0, 0) },
72
- { S(-21, 0), S( -9, 0), S( -4, 0), S( 2, 0) },
73
- { S(-22, 0), S( -6, 0), S( -1, 0), S( 2, 0) },
74
- { S(-22, 0), S( -7, 0), S( 0, 0), S( 1, 0) },
75
- { S(-21, 0), S( -7, 0), S( 0, 0), S( 2, 0) },
76
- { S(-12, 0), S( 4, 0), S( 8, 0), S(12, 0) },
77
- { S(-23, 0), S(-15, 0), S(-11, 0), S(-5, 0) }
78
- },
79
- { // Queen
80
- { S( 0,-70), S(-3,-57), S(-4,-41), S(-1,-29) },
81
- { S(-4,-58), S( 6,-30), S( 9,-21), S( 8, -4) },
82
- { S(-2,-39), S( 6,-17), S( 9, -7), S( 9, 5) },
83
- { S(-1,-29), S( 8, -5), S(10, 9), S( 7, 17) },
84
- { S(-3,-27), S( 9, -5), S( 8, 10), S( 7, 23) },
85
- { S(-2,-40), S( 6,-16), S( 8,-11), S(10, 3) },
86
- { S(-2,-54), S( 7,-30), S( 7,-21), S( 6, -7) },
87
- { S(-1,-75), S(-4,-54), S(-1,-44), S( 0,-30) }
88
- },
89
- { // King
90
- { S(291, 28), S(344, 76), S(294,103), S(219,112) },
91
- { S(289, 70), S(329,119), S(263,170), S(205,159) },
92
- { S(226,109), S(271,164), S(202,195), S(136,191) },
93
- { S(204,131), S(212,194), S(175,194), S(137,204) },
94
- { S(177,132), S(205,187), S(143,224), S( 94,227) },
95
- { S(147,118), S(188,178), S(113,199), S( 70,197) },
96
- { S(116, 72), S(158,121), S( 93,142), S( 48,161) },
97
- { S( 94, 30), S(120, 76), S( 78,101), S( 31,111) }
98
- }
99
- };
100
-
101
- #undef S
102
-
103
- Score psq[PIECE_NB][SQUARE_NB];
104
-
105
- // init() initializes piece-square tables: the white halves of the tables are
106
- // copied from Bonus[] adding the piece value, then the black halves of the
107
- // tables are initialized by flipping and changing the sign of the white scores.
108
- void init() {
109
-
110
- for (Piece pc = W_PAWN; pc <= W_KING; ++pc)
111
- {
112
- PieceValue[MG][~pc] = PieceValue[MG][pc];
113
- PieceValue[EG][~pc] = PieceValue[EG][pc];
114
-
115
- Score v = make_score(PieceValue[MG][pc], PieceValue[EG][pc]);
116
-
117
- for (Square s = SQ_A1; s <= SQ_H8; ++s)
118
- {
119
- File f = std::min(file_of(s), FILE_H - file_of(s));
120
- psq[ pc][ s] = v + Bonus[pc][rank_of(s)][f];
121
- psq[~pc][~s] = -psq[pc][s];
122
- }
123
- }
124
- }
125
-
126
- } // namespace PSQT
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/search.cpp DELETED
@@ -1,1656 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #include <algorithm>
22
- #include <cassert>
23
- #include <cmath>
24
- #include <cstring> // For std::memset
25
- #include <iostream>
26
- #include <sstream>
27
-
28
- #include "evaluate.h"
29
- #include "misc.h"
30
- #include "movegen.h"
31
- #include "movepick.h"
32
- #include "position.h"
33
- #include "search.h"
34
- #include "timeman.h"
35
- #include "thread.h"
36
- #include "tt.h"
37
- #include "uci.h"
38
- #include "syzygy/tbprobe.h"
39
-
40
- namespace Search {
41
-
42
- SignalsType Signals;
43
- LimitsType Limits;
44
- }
45
-
46
- namespace Tablebases {
47
-
48
- int Cardinality;
49
- bool RootInTB;
50
- bool UseRule50;
51
- Depth ProbeDepth;
52
- Value Score;
53
- }
54
-
55
- namespace TB = Tablebases;
56
-
57
- using std::string;
58
- using Eval::evaluate;
59
- using namespace Search;
60
-
61
- namespace {
62
-
63
- // Different node types, used as a template parameter
64
- enum NodeType { NonPV, PV };
65
-
66
- // Razoring and futility margin based on depth
67
- const int razor_margin[4] = { 483, 570, 603, 554 };
68
- Value futility_margin(Depth d) { return Value(150 * d / ONE_PLY); }
69
-
70
- // Futility and reductions lookup tables, initialized at startup
71
- int FutilityMoveCounts[2][16]; // [improving][depth]
72
- int Reductions[2][2][64][64]; // [pv][improving][depth][moveNumber]
73
-
74
- template <bool PvNode> Depth reduction(bool i, Depth d, int mn) {
75
- return Reductions[PvNode][i][std::min(d / ONE_PLY, 63)][std::min(mn, 63)] * ONE_PLY;
76
- }
77
-
78
- // Skill structure is used to implement strength limit
79
- struct Skill {
80
- Skill(int l) : level(l) {}
81
- bool enabled() const { return level < 20; }
82
- bool time_to_pick(Depth depth) const { return depth / ONE_PLY == 1 + level; }
83
- Move best_move(size_t multiPV) { return best ? best : pick_best(multiPV); }
84
- Move pick_best(size_t multiPV);
85
-
86
- int level;
87
- Move best = MOVE_NONE;
88
- };
89
-
90
- // EasyMoveManager structure is used to detect an 'easy move'. When the PV is
91
- // stable across multiple search iterations, we can quickly return the best move.
92
- struct EasyMoveManager {
93
-
94
- void clear() {
95
- stableCnt = 0;
96
- expectedPosKey = 0;
97
- pv[0] = pv[1] = pv[2] = MOVE_NONE;
98
- }
99
-
100
- Move get(Key key) const {
101
- return expectedPosKey == key ? pv[2] : MOVE_NONE;
102
- }
103
-
104
- void update(Position& pos, const std::vector<Move>& newPv) {
105
-
106
- assert(newPv.size() >= 3);
107
-
108
- // Keep track of how many times in a row the 3rd ply remains stable
109
- stableCnt = (newPv[2] == pv[2]) ? stableCnt + 1 : 0;
110
-
111
- if (!std::equal(newPv.begin(), newPv.begin() + 3, pv))
112
- {
113
- std::copy(newPv.begin(), newPv.begin() + 3, pv);
114
-
115
- StateInfo st[2];
116
- pos.do_move(newPv[0], st[0], pos.gives_check(newPv[0]));
117
- pos.do_move(newPv[1], st[1], pos.gives_check(newPv[1]));
118
- expectedPosKey = pos.key();
119
- pos.undo_move(newPv[1]);
120
- pos.undo_move(newPv[0]);
121
- }
122
- }
123
-
124
- int stableCnt;
125
- Key expectedPosKey;
126
- Move pv[3];
127
- };
128
-
129
- // Set of rows with half bits set to 1 and half to 0. It is used to allocate
130
- // the search depths across the threads.
131
- typedef std::vector<int> Row;
132
-
133
- const Row HalfDensity[] = {
134
- {0, 1},
135
- {1, 0},
136
- {0, 0, 1, 1},
137
- {0, 1, 1, 0},
138
- {1, 1, 0, 0},
139
- {1, 0, 0, 1},
140
- {0, 0, 0, 1, 1, 1},
141
- {0, 0, 1, 1, 1, 0},
142
- {0, 1, 1, 1, 0, 0},
143
- {1, 1, 1, 0, 0, 0},
144
- {1, 1, 0, 0, 0, 1},
145
- {1, 0, 0, 0, 1, 1},
146
- {0, 0, 0, 0, 1, 1, 1, 1},
147
- {0, 0, 0, 1, 1, 1, 1, 0},
148
- {0, 0, 1, 1, 1, 1, 0 ,0},
149
- {0, 1, 1, 1, 1, 0, 0 ,0},
150
- {1, 1, 1, 1, 0, 0, 0 ,0},
151
- {1, 1, 1, 0, 0, 0, 0 ,1},
152
- {1, 1, 0, 0, 0, 0, 1 ,1},
153
- {1, 0, 0, 0, 0, 1, 1 ,1},
154
- };
155
-
156
- const size_t HalfDensitySize = std::extent<decltype(HalfDensity)>::value;
157
-
158
- EasyMoveManager EasyMove;
159
- Value DrawValue[COLOR_NB];
160
-
161
- template <NodeType NT>
162
- Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, bool cutNode);
163
-
164
- template <NodeType NT, bool InCheck>
165
- Value qsearch(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth);
166
-
167
- Value value_to_tt(Value v, int ply);
168
- Value value_from_tt(Value v, int ply);
169
- void update_pv(Move* pv, Move move, Move* childPv);
170
- void update_cm_stats(Stack* ss, Piece pc, Square s, Value bonus);
171
- void update_stats(const Position& pos, Stack* ss, Move move, Move* quiets, int quietsCnt, Value bonus);
172
- void check_time();
173
-
174
- } // namespace
175
-
176
-
177
- /// Search::init() is called during startup to initialize various lookup tables
178
-
179
- void Search::init() {
180
-
181
- for (int imp = 0; imp <= 1; ++imp)
182
- for (int d = 1; d < 64; ++d)
183
- for (int mc = 1; mc < 64; ++mc)
184
- {
185
- double r = log(d) * log(mc) / 2;
186
- if (r < 0.80)
187
- continue;
188
-
189
- Reductions[NonPV][imp][d][mc] = int(std::round(r));
190
- Reductions[PV][imp][d][mc] = std::max(Reductions[NonPV][imp][d][mc] - 1, 0);
191
-
192
- // Increase reduction for non-PV nodes when eval is not improving
193
- if (!imp && Reductions[NonPV][imp][d][mc] >= 2)
194
- Reductions[NonPV][imp][d][mc]++;
195
- }
196
-
197
- for (int d = 0; d < 16; ++d)
198
- {
199
- FutilityMoveCounts[0][d] = int(2.4 + 0.773 * pow(d + 0.00, 1.8));
200
- FutilityMoveCounts[1][d] = int(2.9 + 1.045 * pow(d + 0.49, 1.8));
201
- }
202
- }
203
-
204
-
205
- /// Search::clear() resets search state to zero, to obtain reproducible results
206
-
207
- void Search::clear() {
208
-
209
- TT.clear();
210
-
211
- for (Thread* th : Threads)
212
- {
213
- th->history.clear();
214
- th->counterMoves.clear();
215
- th->fromTo.clear();
216
- th->counterMoveHistory.clear();
217
- }
218
-
219
- Threads.main()->previousScore = VALUE_INFINITE;
220
- }
221
-
222
-
223
- /// Search::perft() is our utility to verify move generation. All the leaf nodes
224
- /// up to the given depth are generated and counted, and the sum is returned.
225
- template<bool Root>
226
- uint64_t Search::perft(Position& pos, Depth depth) {
227
-
228
- StateInfo st;
229
- uint64_t cnt, nodes = 0;
230
- const bool leaf = (depth == 2 * ONE_PLY);
231
-
232
- for (const auto& m : MoveList<LEGAL>(pos))
233
- {
234
- if (Root && depth <= ONE_PLY)
235
- cnt = 1, nodes++;
236
- else
237
- {
238
- pos.do_move(m, st, pos.gives_check(m));
239
- cnt = leaf ? MoveList<LEGAL>(pos).size() : perft<false>(pos, depth - ONE_PLY);
240
- nodes += cnt;
241
- pos.undo_move(m);
242
- }
243
- if (Root)
244
- sync_cout << UCI::move(m, pos.is_chess960()) << ": " << cnt << sync_endl;
245
- }
246
- return nodes;
247
- }
248
-
249
- template uint64_t Search::perft<true>(Position&, Depth);
250
-
251
-
252
- /// MainThread::search() is called by the main thread when the program receives
253
- /// the UCI 'go' command. It searches from the root position and outputs the "bestmove".
254
-
255
- void MainThread::search() {
256
-
257
- Color us = rootPos.side_to_move();
258
- Time.init(Limits, us, rootPos.game_ply());
259
-
260
- int contempt = Options["Contempt"] * PawnValueEg / 100; // From centipawns
261
- DrawValue[ us] = VALUE_DRAW - Value(contempt);
262
- DrawValue[~us] = VALUE_DRAW + Value(contempt);
263
-
264
- if (rootMoves.empty())
265
- {
266
- rootMoves.push_back(RootMove(MOVE_NONE));
267
- sync_cout << "info depth 0 score "
268
- << UCI::value(rootPos.checkers() ? -VALUE_MATE : VALUE_DRAW)
269
- << sync_endl;
270
- }
271
- else
272
- {
273
- for (Thread* th : Threads)
274
- if (th != this)
275
- th->start_searching();
276
-
277
- Thread::search(); // Let's start searching!
278
- }
279
-
280
- // When playing in 'nodes as time' mode, subtract the searched nodes from
281
- // the available ones before exiting.
282
- if (Limits.npmsec)
283
- Time.availableNodes += Limits.inc[us] - Threads.nodes_searched();
284
-
285
- // When we reach the maximum depth, we can arrive here without a raise of
286
- // Signals.stop. However, if we are pondering or in an infinite search,
287
- // the UCI protocol states that we shouldn't print the best move before the
288
- // GUI sends a "stop" or "ponderhit" command. We therefore simply wait here
289
- // until the GUI sends one of those commands (which also raises Signals.stop).
290
- if (!Signals.stop && (Limits.ponder || Limits.infinite))
291
- {
292
- Signals.stopOnPonderhit = true;
293
- wait(Signals.stop);
294
- }
295
-
296
- // Stop the threads if not already stopped
297
- Signals.stop = true;
298
-
299
- // Wait until all threads have finished
300
- for (Thread* th : Threads)
301
- if (th != this)
302
- th->wait_for_search_finished();
303
-
304
- // Check if there are threads with a better score than main thread
305
- Thread* bestThread = this;
306
- if ( !this->easyMovePlayed
307
- && Options["MultiPV"] == 1
308
- && !Limits.depth
309
- && !Skill(Options["Skill Level"]).enabled()
310
- && rootMoves[0].pv[0] != MOVE_NONE)
311
- {
312
- for (Thread* th : Threads)
313
- if ( th->completedDepth > bestThread->completedDepth
314
- && th->rootMoves[0].score > bestThread->rootMoves[0].score)
315
- bestThread = th;
316
- }
317
-
318
- previousScore = bestThread->rootMoves[0].score;
319
-
320
- // Send new PV when needed
321
- if (bestThread != this)
322
- sync_cout << UCI::pv(bestThread->rootPos, bestThread->completedDepth, -VALUE_INFINITE, VALUE_INFINITE) << sync_endl;
323
-
324
- sync_cout << "bestmove " << UCI::move(bestThread->rootMoves[0].pv[0], rootPos.is_chess960());
325
-
326
- if (bestThread->rootMoves[0].pv.size() > 1 || bestThread->rootMoves[0].extract_ponder_from_tt(rootPos))
327
- std::cout << " ponder " << UCI::move(bestThread->rootMoves[0].pv[1], rootPos.is_chess960());
328
-
329
- std::cout << sync_endl;
330
- }
331
-
332
-
333
- // Thread::search() is the main iterative deepening loop. It calls search()
334
- // repeatedly with increasing depth until the allocated thinking time has been
335
- // consumed, the user stops the search, or the maximum search depth is reached.
336
-
337
- void Thread::search() {
338
-
339
- Stack stack[MAX_PLY+7], *ss = stack+5; // To allow referencing (ss-5) and (ss+2)
340
- Value bestValue, alpha, beta, delta;
341
- Move easyMove = MOVE_NONE;
342
- MainThread* mainThread = (this == Threads.main() ? Threads.main() : nullptr);
343
-
344
- std::memset(ss-5, 0, 8 * sizeof(Stack));
345
-
346
- bestValue = delta = alpha = -VALUE_INFINITE;
347
- beta = VALUE_INFINITE;
348
- completedDepth = DEPTH_ZERO;
349
-
350
- if (mainThread)
351
- {
352
- easyMove = EasyMove.get(rootPos.key());
353
- EasyMove.clear();
354
- mainThread->easyMovePlayed = mainThread->failedLow = false;
355
- mainThread->bestMoveChanges = 0;
356
- TT.new_search();
357
- }
358
-
359
- size_t multiPV = Options["MultiPV"];
360
- Skill skill(Options["Skill Level"]);
361
-
362
- // When playing with strength handicap enable MultiPV search that we will
363
- // use behind the scenes to retrieve a set of possible moves.
364
- if (skill.enabled())
365
- multiPV = std::max(multiPV, (size_t)4);
366
-
367
- multiPV = std::min(multiPV, rootMoves.size());
368
-
369
- // Iterative deepening loop until requested to stop or the target depth is reached
370
- while ( (rootDepth += ONE_PLY) < DEPTH_MAX
371
- && !Signals.stop
372
- && (!Limits.depth || Threads.main()->rootDepth / ONE_PLY <= Limits.depth))
373
- {
374
- // Set up the new depths for the helper threads skipping on average every
375
- // 2nd ply (using a half-density matrix).
376
- if (!mainThread)
377
- {
378
- const Row& row = HalfDensity[(idx - 1) % HalfDensitySize];
379
- if (row[(rootDepth / ONE_PLY + rootPos.game_ply()) % row.size()])
380
- continue;
381
- }
382
-
383
- // Age out PV variability metric
384
- if (mainThread)
385
- mainThread->bestMoveChanges *= 0.505, mainThread->failedLow = false;
386
-
387
- // Save the last iteration's scores before first PV line is searched and
388
- // all the move scores except the (new) PV are set to -VALUE_INFINITE.
389
- for (RootMove& rm : rootMoves)
390
- rm.previousScore = rm.score;
391
-
392
- // MultiPV loop. We perform a full root search for each PV line
393
- for (PVIdx = 0; PVIdx < multiPV && !Signals.stop; ++PVIdx)
394
- {
395
- // Reset aspiration window starting size
396
- if (rootDepth >= 5 * ONE_PLY)
397
- {
398
- delta = Value(18);
399
- alpha = std::max(rootMoves[PVIdx].previousScore - delta,-VALUE_INFINITE);
400
- beta = std::min(rootMoves[PVIdx].previousScore + delta, VALUE_INFINITE);
401
- }
402
-
403
- // Start with a small aspiration window and, in the case of a fail
404
- // high/low, re-search with a bigger window until we're not failing
405
- // high/low anymore.
406
- while (true)
407
- {
408
- bestValue = ::search<PV>(rootPos, ss, alpha, beta, rootDepth, false);
409
-
410
- // Bring the best move to the front. It is critical that sorting
411
- // is done with a stable algorithm because all the values but the
412
- // first and eventually the new best one are set to -VALUE_INFINITE
413
- // and we want to keep the same order for all the moves except the
414
- // new PV that goes to the front. Note that in case of MultiPV
415
- // search the already searched PV lines are preserved.
416
- std::stable_sort(rootMoves.begin() + PVIdx, rootMoves.end());
417
-
418
- // If search has been stopped, break immediately. Sorting and
419
- // writing PV back to TT is safe because RootMoves is still
420
- // valid, although it refers to the previous iteration.
421
- if (Signals.stop)
422
- break;
423
-
424
- // When failing high/low give some update (without cluttering
425
- // the UI) before a re-search.
426
- if ( mainThread
427
- && multiPV == 1
428
- && (bestValue <= alpha || bestValue >= beta)
429
- && Time.elapsed() > 3000)
430
- sync_cout << UCI::pv(rootPos, rootDepth, alpha, beta) << sync_endl;
431
-
432
- // In case of failing low/high increase aspiration window and
433
- // re-search, otherwise exit the loop.
434
- if (bestValue <= alpha)
435
- {
436
- beta = (alpha + beta) / 2;
437
- alpha = std::max(bestValue - delta, -VALUE_INFINITE);
438
-
439
- if (mainThread)
440
- {
441
- mainThread->failedLow = true;
442
- Signals.stopOnPonderhit = false;
443
- }
444
- }
445
- else if (bestValue >= beta)
446
- {
447
- alpha = (alpha + beta) / 2;
448
- beta = std::min(bestValue + delta, VALUE_INFINITE);
449
- }
450
- else
451
- break;
452
-
453
- delta += delta / 4 + 5;
454
-
455
- assert(alpha >= -VALUE_INFINITE && beta <= VALUE_INFINITE);
456
- }
457
-
458
- // Sort the PV lines searched so far and update the GUI
459
- std::stable_sort(rootMoves.begin(), rootMoves.begin() + PVIdx + 1);
460
-
461
- if (!mainThread)
462
- continue;
463
-
464
- if (Signals.stop || PVIdx + 1 == multiPV || Time.elapsed() > 3000)
465
- sync_cout << UCI::pv(rootPos, rootDepth, alpha, beta) << sync_endl;
466
- }
467
-
468
- if (!Signals.stop)
469
- completedDepth = rootDepth;
470
-
471
- if (!mainThread)
472
- continue;
473
-
474
- // If skill level is enabled and time is up, pick a sub-optimal best move
475
- if (skill.enabled() && skill.time_to_pick(rootDepth))
476
- skill.pick_best(multiPV);
477
-
478
- // Have we found a "mate in x"?
479
- if ( Limits.mate
480
- && bestValue >= VALUE_MATE_IN_MAX_PLY
481
- && VALUE_MATE - bestValue <= 2 * Limits.mate)
482
- Signals.stop = true;
483
-
484
- // Do we have time for the next iteration? Can we stop searching now?
485
- if (Limits.use_time_management())
486
- {
487
- if (!Signals.stop && !Signals.stopOnPonderhit)
488
- {
489
- // Stop the search if only one legal move is available, or if all
490
- // of the available time has been used, or if we matched an easyMove
491
- // from the previous search and just did a fast verification.
492
- const int F[] = { mainThread->failedLow,
493
- bestValue - mainThread->previousScore };
494
-
495
- int improvingFactor = std::max(229, std::min(715, 357 + 119 * F[0] - 6 * F[1]));
496
- double unstablePvFactor = 1 + mainThread->bestMoveChanges;
497
-
498
- bool doEasyMove = rootMoves[0].pv[0] == easyMove
499
- && mainThread->bestMoveChanges < 0.03
500
- && Time.elapsed() > Time.optimum() * 5 / 42;
501
-
502
- if ( rootMoves.size() == 1
503
- || Time.elapsed() > Time.optimum() * unstablePvFactor * improvingFactor / 628
504
- || (mainThread->easyMovePlayed = doEasyMove, doEasyMove))
505
- {
506
- // If we are allowed to ponder do not stop the search now but
507
- // keep pondering until the GUI sends "ponderhit" or "stop".
508
- if (Limits.ponder)
509
- Signals.stopOnPonderhit = true;
510
- else
511
- Signals.stop = true;
512
- }
513
- }
514
-
515
- if (rootMoves[0].pv.size() >= 3)
516
- EasyMove.update(rootPos, rootMoves[0].pv);
517
- else
518
- EasyMove.clear();
519
- }
520
- }
521
-
522
- if (!mainThread)
523
- return;
524
-
525
- // Clear any candidate easy move that wasn't stable for the last search
526
- // iterations; the second condition prevents consecutive fast moves.
527
- if (EasyMove.stableCnt < 6 || mainThread->easyMovePlayed)
528
- EasyMove.clear();
529
-
530
- // If skill level is enabled, swap best PV line with the sub-optimal one
531
- if (skill.enabled())
532
- std::swap(rootMoves[0], *std::find(rootMoves.begin(),
533
- rootMoves.end(), skill.best_move(multiPV)));
534
- }
535
-
536
-
537
- namespace {
538
-
539
- // search<>() is the main search function for both PV and non-PV nodes
540
-
541
- template <NodeType NT>
542
- Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, bool cutNode) {
543
-
544
- const bool PvNode = NT == PV;
545
- const bool rootNode = PvNode && (ss-1)->ply == 0;
546
-
547
- assert(-VALUE_INFINITE <= alpha && alpha < beta && beta <= VALUE_INFINITE);
548
- assert(PvNode || (alpha == beta - 1));
549
- assert(DEPTH_ZERO < depth && depth < DEPTH_MAX);
550
- assert(!(PvNode && cutNode));
551
- assert(depth / ONE_PLY * ONE_PLY == depth);
552
-
553
- Move pv[MAX_PLY+1], quietsSearched[64];
554
- StateInfo st;
555
- TTEntry* tte;
556
- Key posKey;
557
- Move ttMove, move, excludedMove, bestMove;
558
- Depth extension, newDepth;
559
- Value bestValue, value, ttValue, eval, nullValue;
560
- bool ttHit, inCheck, givesCheck, singularExtensionNode, improving;
561
- bool captureOrPromotion, doFullDepthSearch, moveCountPruning;
562
- Piece moved_piece;
563
- int moveCount, quietCount;
564
-
565
- // Step 1. Initialize node
566
- Thread* thisThread = pos.this_thread();
567
- inCheck = pos.checkers();
568
- moveCount = quietCount = ss->moveCount = 0;
569
- ss->history = VALUE_ZERO;
570
- bestValue = -VALUE_INFINITE;
571
- ss->ply = (ss-1)->ply + 1;
572
-
573
- // Check for the available remaining time
574
- if (thisThread->resetCalls.load(std::memory_order_relaxed))
575
- {
576
- thisThread->resetCalls = false;
577
- thisThread->callsCnt = 0;
578
- }
579
- if (++thisThread->callsCnt > 4096)
580
- {
581
- for (Thread* th : Threads)
582
- th->resetCalls = true;
583
-
584
- check_time();
585
- }
586
-
587
- // Used to send selDepth info to GUI
588
- if (PvNode && thisThread->maxPly < ss->ply)
589
- thisThread->maxPly = ss->ply;
590
-
591
- if (!rootNode)
592
- {
593
- // Step 2. Check for aborted search and immediate draw
594
- if (Signals.stop.load(std::memory_order_relaxed) || pos.is_draw() || ss->ply >= MAX_PLY)
595
- return ss->ply >= MAX_PLY && !inCheck ? evaluate(pos)
596
- : DrawValue[pos.side_to_move()];
597
-
598
- // Step 3. Mate distance pruning. Even if we mate at the next move our score
599
- // would be at best mate_in(ss->ply+1), but if alpha is already bigger because
600
- // a shorter mate was found upward in the tree then there is no need to search
601
- // because we will never beat the current alpha. Same logic but with reversed
602
- // signs applies also in the opposite condition of being mated instead of giving
603
- // mate. In this case return a fail-high score.
604
- alpha = std::max(mated_in(ss->ply), alpha);
605
- beta = std::min(mate_in(ss->ply+1), beta);
606
- if (alpha >= beta)
607
- return alpha;
608
- }
609
-
610
- assert(0 <= ss->ply && ss->ply < MAX_PLY);
611
-
612
- ss->currentMove = (ss+1)->excludedMove = bestMove = MOVE_NONE;
613
- ss->counterMoves = nullptr;
614
- (ss+1)->skipEarlyPruning = false;
615
- (ss+2)->killers[0] = (ss+2)->killers[1] = MOVE_NONE;
616
-
617
- // Step 4. Transposition table lookup. We don't want the score of a partial
618
- // search to overwrite a previous full search TT value, so we use a different
619
- // position key in case of an excluded move.
620
- excludedMove = ss->excludedMove;
621
- posKey = pos.key() ^ Key(excludedMove);
622
- tte = TT.probe(posKey, ttHit);
623
- ttValue = ttHit ? value_from_tt(tte->value(), ss->ply) : VALUE_NONE;
624
- ttMove = rootNode ? thisThread->rootMoves[thisThread->PVIdx].pv[0]
625
- : ttHit ? tte->move() : MOVE_NONE;
626
-
627
- // At non-PV nodes we check for an early TT cutoff
628
- if ( !PvNode
629
- && ttHit
630
- && tte->depth() >= depth
631
- && ttValue != VALUE_NONE // Possible in case of TT access race
632
- && (ttValue >= beta ? (tte->bound() & BOUND_LOWER)
633
- : (tte->bound() & BOUND_UPPER)))
634
- {
635
- // If ttMove is quiet, update killers, history, counter move on TT hit
636
- if (ttValue >= beta && ttMove)
637
- {
638
- int d = depth / ONE_PLY;
639
-
640
- if (!pos.capture_or_promotion(ttMove))
641
- {
642
- Value bonus = Value(d * d + 2 * d - 2);
643
- update_stats(pos, ss, ttMove, nullptr, 0, bonus);
644
- }
645
-
646
- // Extra penalty for a quiet TT move in previous ply when it gets refuted
647
- if ((ss-1)->moveCount == 1 && !pos.captured_piece())
648
- {
649
- Value penalty = Value(d * d + 4 * d + 1);
650
- Square prevSq = to_sq((ss-1)->currentMove);
651
- update_cm_stats(ss-1, pos.piece_on(prevSq), prevSq, -penalty);
652
- }
653
- }
654
- return ttValue;
655
- }
656
-
657
- // Step 4a. Tablebase probe
658
- if (!rootNode && TB::Cardinality)
659
- {
660
- int piecesCnt = pos.count<ALL_PIECES>(WHITE) + pos.count<ALL_PIECES>(BLACK);
661
-
662
- if ( piecesCnt <= TB::Cardinality
663
- && (piecesCnt < TB::Cardinality || depth >= TB::ProbeDepth)
664
- && pos.rule50_count() == 0
665
- && !pos.can_castle(ANY_CASTLING))
666
- {
667
- int found, v = Tablebases::probe_wdl(pos, &found);
668
-
669
- if (found)
670
- {
671
- thisThread->tbHits++;
672
-
673
- int drawScore = TB::UseRule50 ? 1 : 0;
674
-
675
- value = v < -drawScore ? -VALUE_MATE + MAX_PLY + ss->ply
676
- : v > drawScore ? VALUE_MATE - MAX_PLY - ss->ply
677
- : VALUE_DRAW + 2 * v * drawScore;
678
-
679
- tte->save(posKey, value_to_tt(value, ss->ply), BOUND_EXACT,
680
- std::min(DEPTH_MAX - ONE_PLY, depth + 6 * ONE_PLY),
681
- MOVE_NONE, VALUE_NONE, TT.generation());
682
-
683
- return value;
684
- }
685
- }
686
- }
687
-
688
- // Step 5. Evaluate the position statically
689
- if (inCheck)
690
- {
691
- ss->staticEval = eval = VALUE_NONE;
692
- goto moves_loop;
693
- }
694
-
695
- else if (ttHit)
696
- {
697
- // Never assume anything on values stored in TT
698
- if ((ss->staticEval = eval = tte->eval()) == VALUE_NONE)
699
- eval = ss->staticEval = evaluate(pos);
700
-
701
- // Can ttValue be used as a better position evaluation?
702
- if (ttValue != VALUE_NONE)
703
- if (tte->bound() & (ttValue > eval ? BOUND_LOWER : BOUND_UPPER))
704
- eval = ttValue;
705
- }
706
- else
707
- {
708
- eval = ss->staticEval =
709
- (ss-1)->currentMove != MOVE_NULL ? evaluate(pos)
710
- : -(ss-1)->staticEval + 2 * Eval::Tempo;
711
-
712
- tte->save(posKey, VALUE_NONE, BOUND_NONE, DEPTH_NONE, MOVE_NONE,
713
- ss->staticEval, TT.generation());
714
- }
715
-
716
- if (ss->skipEarlyPruning)
717
- goto moves_loop;
718
-
719
- // Step 6. Razoring (skipped when in check)
720
- if ( !PvNode
721
- && depth < 4 * ONE_PLY
722
- && ttMove == MOVE_NONE
723
- && eval + razor_margin[depth / ONE_PLY] <= alpha)
724
- {
725
- if (depth <= ONE_PLY)
726
- return qsearch<NonPV, false>(pos, ss, alpha, beta, DEPTH_ZERO);
727
-
728
- Value ralpha = alpha - razor_margin[depth / ONE_PLY];
729
- Value v = qsearch<NonPV, false>(pos, ss, ralpha, ralpha+1, DEPTH_ZERO);
730
- if (v <= ralpha)
731
- return v;
732
- }
733
-
734
- // Step 7. Futility pruning: child node (skipped when in check)
735
- if ( !rootNode
736
- && depth < 7 * ONE_PLY
737
- && eval - futility_margin(depth) >= beta
738
- && eval < VALUE_KNOWN_WIN // Do not return unproven wins
739
- && pos.non_pawn_material(pos.side_to_move()))
740
- return eval;
741
-
742
- // Step 8. Null move search with verification search (is omitted in PV nodes)
743
- if ( !PvNode
744
- && eval >= beta
745
- && (ss->staticEval >= beta - 35 * (depth / ONE_PLY - 6) || depth >= 13 * ONE_PLY)
746
- && pos.non_pawn_material(pos.side_to_move()))
747
- {
748
- ss->currentMove = MOVE_NULL;
749
- ss->counterMoves = nullptr;
750
-
751
- assert(eval - beta >= 0);
752
-
753
- // Null move dynamic reduction based on depth and value
754
- Depth R = ((823 + 67 * depth / ONE_PLY) / 256 + std::min((eval - beta) / PawnValueMg, 3)) * ONE_PLY;
755
-
756
- pos.do_null_move(st);
757
- (ss+1)->skipEarlyPruning = true;
758
- nullValue = depth-R < ONE_PLY ? -qsearch<NonPV, false>(pos, ss+1, -beta, -beta+1, DEPTH_ZERO)
759
- : - search<NonPV>(pos, ss+1, -beta, -beta+1, depth-R, !cutNode);
760
- (ss+1)->skipEarlyPruning = false;
761
- pos.undo_null_move();
762
-
763
- if (nullValue >= beta)
764
- {
765
- // Do not return unproven mate scores
766
- if (nullValue >= VALUE_MATE_IN_MAX_PLY)
767
- nullValue = beta;
768
-
769
- if (depth < 12 * ONE_PLY && abs(beta) < VALUE_KNOWN_WIN)
770
- return nullValue;
771
-
772
- // Do verification search at high depths
773
- ss->skipEarlyPruning = true;
774
- Value v = depth-R < ONE_PLY ? qsearch<NonPV, false>(pos, ss, beta-1, beta, DEPTH_ZERO)
775
- : search<NonPV>(pos, ss, beta-1, beta, depth-R, false);
776
- ss->skipEarlyPruning = false;
777
-
778
- if (v >= beta)
779
- return nullValue;
780
- }
781
- }
782
-
783
- // Step 9. ProbCut (skipped when in check)
784
- // If we have a good enough capture and a reduced search returns a value
785
- // much above beta, we can (almost) safely prune the previous move.
786
- if ( !PvNode
787
- && depth >= 5 * ONE_PLY
788
- && abs(beta) < VALUE_MATE_IN_MAX_PLY)
789
- {
790
- Value rbeta = std::min(beta + 200, VALUE_INFINITE);
791
- Depth rdepth = depth - 4 * ONE_PLY;
792
-
793
- assert(rdepth >= ONE_PLY);
794
- assert((ss-1)->currentMove != MOVE_NONE);
795
- assert((ss-1)->currentMove != MOVE_NULL);
796
-
797
- MovePicker mp(pos, ttMove, rbeta - ss->staticEval);
798
-
799
- while ((move = mp.next_move()) != MOVE_NONE)
800
- if (pos.legal(move))
801
- {
802
- ss->currentMove = move;
803
- ss->counterMoves = &thisThread->counterMoveHistory[pos.moved_piece(move)][to_sq(move)];
804
- pos.do_move(move, st, pos.gives_check(move));
805
- value = -search<NonPV>(pos, ss+1, -rbeta, -rbeta+1, rdepth, !cutNode);
806
- pos.undo_move(move);
807
- if (value >= rbeta)
808
- return value;
809
- }
810
- }
811
-
812
- // Step 10. Internal iterative deepening (skipped when in check)
813
- if ( depth >= 6 * ONE_PLY
814
- && !ttMove
815
- && (PvNode || ss->staticEval + 256 >= beta))
816
- {
817
- Depth d = (3 * depth / (4 * ONE_PLY) - 2) * ONE_PLY;
818
- ss->skipEarlyPruning = true;
819
- search<NT>(pos, ss, alpha, beta, d, cutNode);
820
- ss->skipEarlyPruning = false;
821
-
822
- tte = TT.probe(posKey, ttHit);
823
- ttMove = ttHit ? tte->move() : MOVE_NONE;
824
- }
825
-
826
- moves_loop: // When in check search starts from here
827
-
828
- const CounterMoveStats* cmh = (ss-1)->counterMoves;
829
- const CounterMoveStats* fmh = (ss-2)->counterMoves;
830
- const CounterMoveStats* fmh2 = (ss-4)->counterMoves;
831
-
832
- MovePicker mp(pos, ttMove, depth, ss);
833
- value = bestValue; // Workaround a bogus 'uninitialized' warning under gcc
834
- improving = ss->staticEval >= (ss-2)->staticEval
835
- /* || ss->staticEval == VALUE_NONE Already implicit in the previous condition */
836
- ||(ss-2)->staticEval == VALUE_NONE;
837
-
838
- singularExtensionNode = !rootNode
839
- && depth >= 8 * ONE_PLY
840
- && ttMove != MOVE_NONE
841
- && ttValue != VALUE_NONE
842
- && !excludedMove // Recursive singular search is not allowed
843
- && (tte->bound() & BOUND_LOWER)
844
- && tte->depth() >= depth - 3 * ONE_PLY;
845
-
846
- // Step 11. Loop through moves
847
- // Loop through all pseudo-legal moves until no moves remain or a beta cutoff occurs
848
- while ((move = mp.next_move()) != MOVE_NONE)
849
- {
850
- assert(is_ok(move));
851
-
852
- if (move == excludedMove)
853
- continue;
854
-
855
- // At root obey the "searchmoves" option and skip moves not listed in Root
856
- // Move List. As a consequence any illegal move is also skipped. In MultiPV
857
- // mode we also skip PV moves which have been already searched.
858
- if (rootNode && !std::count(thisThread->rootMoves.begin() + thisThread->PVIdx,
859
- thisThread->rootMoves.end(), move))
860
- continue;
861
-
862
- ss->moveCount = ++moveCount;
863
-
864
- if (rootNode && thisThread == Threads.main() && Time.elapsed() > 3000)
865
- sync_cout << "info depth " << depth / ONE_PLY
866
- << " currmove " << UCI::move(move, pos.is_chess960())
867
- << " currmovenumber " << moveCount + thisThread->PVIdx << sync_endl;
868
-
869
- if (PvNode)
870
- (ss+1)->pv = nullptr;
871
-
872
- extension = DEPTH_ZERO;
873
- captureOrPromotion = pos.capture_or_promotion(move);
874
- moved_piece = pos.moved_piece(move);
875
-
876
- givesCheck = type_of(move) == NORMAL && !pos.discovered_check_candidates()
877
- ? pos.check_squares(type_of(pos.piece_on(from_sq(move)))) & to_sq(move)
878
- : pos.gives_check(move);
879
-
880
- moveCountPruning = depth < 16 * ONE_PLY
881
- && moveCount >= FutilityMoveCounts[improving][depth / ONE_PLY];
882
-
883
- // Step 12. Extend checks
884
- if ( givesCheck
885
- && !moveCountPruning
886
- && pos.see_ge(move, VALUE_ZERO))
887
- extension = ONE_PLY;
888
-
889
- // Singular extension search. If all moves but one fail low on a search of
890
- // (alpha-s, beta-s), and just one fails high on (alpha, beta), then that move
891
- // is singular and should be extended. To verify this we do a reduced search
892
- // on all the other moves but the ttMove and if the result is lower than
893
- // ttValue minus a margin then we extend the ttMove.
894
- if ( singularExtensionNode
895
- && move == ttMove
896
- && !extension
897
- && pos.legal(move))
898
- {
899
- Value rBeta = std::max(ttValue - 2 * depth / ONE_PLY, -VALUE_MATE);
900
- Depth d = (depth / (2 * ONE_PLY)) * ONE_PLY;
901
- ss->excludedMove = move;
902
- ss->skipEarlyPruning = true;
903
- value = search<NonPV>(pos, ss, rBeta - 1, rBeta, d, cutNode);
904
- ss->skipEarlyPruning = false;
905
- ss->excludedMove = MOVE_NONE;
906
-
907
- if (value < rBeta)
908
- extension = ONE_PLY;
909
- }
910
-
911
- // Update the current move (this must be done after singular extension search)
912
- newDepth = depth - ONE_PLY + extension;
913
-
914
- // Step 13. Pruning at shallow depth
915
- if ( !rootNode
916
- && bestValue > VALUE_MATED_IN_MAX_PLY)
917
- {
918
- if ( !captureOrPromotion
919
- && !givesCheck
920
- && !pos.advanced_pawn_push(move))
921
- {
922
- // Move count based pruning
923
- if (moveCountPruning)
924
- continue;
925
-
926
- // Reduced depth of the next LMR search
927
- int lmrDepth = std::max(newDepth - reduction<PvNode>(improving, depth, moveCount), DEPTH_ZERO) / ONE_PLY;
928
-
929
- // Countermoves based pruning
930
- if ( lmrDepth < 3
931
- && (!cmh || (*cmh )[moved_piece][to_sq(move)] < VALUE_ZERO)
932
- && (!fmh || (*fmh )[moved_piece][to_sq(move)] < VALUE_ZERO)
933
- && (!fmh2 || (*fmh2)[moved_piece][to_sq(move)] < VALUE_ZERO || (cmh && fmh)))
934
- continue;
935
-
936
- // Futility pruning: parent node
937
- if ( lmrDepth < 7
938
- && !inCheck
939
- && ss->staticEval + 256 + 200 * lmrDepth <= alpha)
940
- continue;
941
-
942
- // Prune moves with negative SEE
943
- if ( lmrDepth < 8
944
- && !pos.see_ge(move, Value(-35 * lmrDepth * lmrDepth)))
945
- continue;
946
- }
947
- else if ( depth < 7 * ONE_PLY
948
- && !extension
949
- && !pos.see_ge(move, Value(-35 * depth / ONE_PLY * depth / ONE_PLY)))
950
- continue;
951
- }
952
-
953
- // Speculative prefetch as early as possible
954
- prefetch(TT.first_entry(pos.key_after(move)));
955
-
956
- // Check for legality just before making the move
957
- if (!rootNode && !pos.legal(move))
958
- {
959
- ss->moveCount = --moveCount;
960
- continue;
961
- }
962
-
963
- ss->currentMove = move;
964
- ss->counterMoves = &thisThread->counterMoveHistory[moved_piece][to_sq(move)];
965
-
966
- // Step 14. Make the move
967
- pos.do_move(move, st, givesCheck);
968
-
969
- // Step 15. Reduced depth search (LMR). If the move fails high it will be
970
- // re-searched at full depth.
971
- if ( depth >= 3 * ONE_PLY
972
- && moveCount > 1
973
- && (!captureOrPromotion || moveCountPruning))
974
- {
975
- Depth r = reduction<PvNode>(improving, depth, moveCount);
976
-
977
- if (captureOrPromotion)
978
- r -= r ? ONE_PLY : DEPTH_ZERO;
979
- else
980
- {
981
- // Increase reduction for cut nodes
982
- if (cutNode)
983
- r += 2 * ONE_PLY;
984
-
985
- // Decrease reduction for moves that escape a capture. Filter out
986
- // castling moves, because they are coded as "king captures rook" and
987
- // hence break make_move(). Also use see() instead of see_sign(),
988
- // because the destination square is empty.
989
- else if ( type_of(move) == NORMAL
990
- && type_of(pos.piece_on(to_sq(move))) != PAWN
991
- && !pos.see_ge(make_move(to_sq(move), from_sq(move)), VALUE_ZERO))
992
- r -= 2 * ONE_PLY;
993
-
994
- ss->history = thisThread->history[moved_piece][to_sq(move)]
995
- + (cmh ? (*cmh )[moved_piece][to_sq(move)] : VALUE_ZERO)
996
- + (fmh ? (*fmh )[moved_piece][to_sq(move)] : VALUE_ZERO)
997
- + (fmh2 ? (*fmh2)[moved_piece][to_sq(move)] : VALUE_ZERO)
998
- + thisThread->fromTo.get(~pos.side_to_move(), move)
999
- - 8000; // Correction factor
1000
-
1001
- // Decrease/increase reduction by comparing opponent's stat score
1002
- if (ss->history > VALUE_ZERO && (ss-1)->history < VALUE_ZERO)
1003
- r -= ONE_PLY;
1004
-
1005
- else if (ss->history < VALUE_ZERO && (ss-1)->history > VALUE_ZERO)
1006
- r += ONE_PLY;
1007
-
1008
- // Decrease/increase reduction for moves with a good/bad history
1009
- r = std::max(DEPTH_ZERO, (r / ONE_PLY - ss->history / 20000) * ONE_PLY);
1010
- }
1011
-
1012
- Depth d = std::max(newDepth - r, ONE_PLY);
1013
-
1014
- value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, d, true);
1015
-
1016
- doFullDepthSearch = (value > alpha && d != newDepth);
1017
- }
1018
- else
1019
- doFullDepthSearch = !PvNode || moveCount > 1;
1020
-
1021
- // Step 16. Full depth search when LMR is skipped or fails high
1022
- if (doFullDepthSearch)
1023
- value = newDepth < ONE_PLY ?
1024
- givesCheck ? -qsearch<NonPV, true>(pos, ss+1, -(alpha+1), -alpha, DEPTH_ZERO)
1025
- : -qsearch<NonPV, false>(pos, ss+1, -(alpha+1), -alpha, DEPTH_ZERO)
1026
- : - search<NonPV>(pos, ss+1, -(alpha+1), -alpha, newDepth, !cutNode);
1027
-
1028
- // For PV nodes only, do a full PV search on the first move or after a fail
1029
- // high (in the latter case search only if value < beta), otherwise let the
1030
- // parent node fail low with value <= alpha and try another move.
1031
- if (PvNode && (moveCount == 1 || (value > alpha && (rootNode || value < beta))))
1032
- {
1033
- (ss+1)->pv = pv;
1034
- (ss+1)->pv[0] = MOVE_NONE;
1035
-
1036
- value = newDepth < ONE_PLY ?
1037
- givesCheck ? -qsearch<PV, true>(pos, ss+1, -beta, -alpha, DEPTH_ZERO)
1038
- : -qsearch<PV, false>(pos, ss+1, -beta, -alpha, DEPTH_ZERO)
1039
- : - search<PV>(pos, ss+1, -beta, -alpha, newDepth, false);
1040
- }
1041
-
1042
- // Step 17. Undo move
1043
- pos.undo_move(move);
1044
-
1045
- assert(value > -VALUE_INFINITE && value < VALUE_INFINITE);
1046
-
1047
- // Step 18. Check for a new best move
1048
- // Finished searching the move. If a stop occurred, the return value of
1049
- // the search cannot be trusted, and we return immediately without
1050
- // updating best move, PV and TT.
1051
- if (Signals.stop.load(std::memory_order_relaxed))
1052
- return VALUE_ZERO;
1053
-
1054
- if (rootNode)
1055
- {
1056
- RootMove& rm = *std::find(thisThread->rootMoves.begin(),
1057
- thisThread->rootMoves.end(), move);
1058
-
1059
- // PV move or new best move ?
1060
- if (moveCount == 1 || value > alpha)
1061
- {
1062
- rm.score = value;
1063
- rm.pv.resize(1);
1064
-
1065
- assert((ss+1)->pv);
1066
-
1067
- for (Move* m = (ss+1)->pv; *m != MOVE_NONE; ++m)
1068
- rm.pv.push_back(*m);
1069
-
1070
- // We record how often the best move has been changed in each
1071
- // iteration. This information is used for time management: When
1072
- // the best move changes frequently, we allocate some more time.
1073
- if (moveCount > 1 && thisThread == Threads.main())
1074
- ++static_cast<MainThread*>(thisThread)->bestMoveChanges;
1075
- }
1076
- else
1077
- // All other moves but the PV are set to the lowest value: this is
1078
- // not a problem when sorting because the sort is stable and the
1079
- // move position in the list is preserved - just the PV is pushed up.
1080
- rm.score = -VALUE_INFINITE;
1081
- }
1082
-
1083
- if (value > bestValue)
1084
- {
1085
- bestValue = value;
1086
-
1087
- if (value > alpha)
1088
- {
1089
- // If there is an easy move for this position, clear it if unstable
1090
- if ( PvNode
1091
- && thisThread == Threads.main()
1092
- && EasyMove.get(pos.key())
1093
- && (move != EasyMove.get(pos.key()) || moveCount > 1))
1094
- EasyMove.clear();
1095
-
1096
- bestMove = move;
1097
-
1098
- if (PvNode && !rootNode) // Update pv even in fail-high case
1099
- update_pv(ss->pv, move, (ss+1)->pv);
1100
-
1101
- if (PvNode && value < beta) // Update alpha! Always alpha < beta
1102
- alpha = value;
1103
- else
1104
- {
1105
- assert(value >= beta); // Fail high
1106
- break;
1107
- }
1108
- }
1109
- }
1110
-
1111
- if (!captureOrPromotion && move != bestMove && quietCount < 64)
1112
- quietsSearched[quietCount++] = move;
1113
- }
1114
-
1115
- // The following condition would detect a stop only after move loop has been
1116
- // completed. But in this case bestValue is valid because we have fully
1117
- // searched our subtree, and we can anyhow save the result in TT.
1118
- /*
1119
- if (Signals.stop)
1120
- return VALUE_DRAW;
1121
- */
1122
-
1123
- // Step 20. Check for mate and stalemate
1124
- // All legal moves have been searched and if there are no legal moves, it
1125
- // must be a mate or a stalemate. If we are in a singular extension search then
1126
- // return a fail low score.
1127
-
1128
- assert(moveCount || !inCheck || excludedMove || !MoveList<LEGAL>(pos).size());
1129
-
1130
- if (!moveCount)
1131
- bestValue = excludedMove ? alpha
1132
- : inCheck ? mated_in(ss->ply) : DrawValue[pos.side_to_move()];
1133
- else if (bestMove)
1134
- {
1135
- int d = depth / ONE_PLY;
1136
-
1137
- // Quiet best move: update killers, history and countermoves
1138
- if (!pos.capture_or_promotion(bestMove))
1139
- {
1140
- Value bonus = Value(d * d + 2 * d - 2);
1141
- update_stats(pos, ss, bestMove, quietsSearched, quietCount, bonus);
1142
- }
1143
-
1144
- // Extra penalty for a quiet TT move in previous ply when it gets refuted
1145
- if ((ss-1)->moveCount == 1 && !pos.captured_piece())
1146
- {
1147
- Value penalty = Value(d * d + 4 * d + 1);
1148
- Square prevSq = to_sq((ss-1)->currentMove);
1149
- update_cm_stats(ss-1, pos.piece_on(prevSq), prevSq, -penalty);
1150
- }
1151
- }
1152
- // Bonus for prior countermove that caused the fail low
1153
- else if ( depth >= 3 * ONE_PLY
1154
- && !pos.captured_piece()
1155
- && is_ok((ss-1)->currentMove))
1156
- {
1157
- int d = depth / ONE_PLY;
1158
- Value bonus = Value(d * d + 2 * d - 2);
1159
- Square prevSq = to_sq((ss-1)->currentMove);
1160
- update_cm_stats(ss-1, pos.piece_on(prevSq), prevSq, bonus);
1161
- }
1162
-
1163
- tte->save(posKey, value_to_tt(bestValue, ss->ply),
1164
- bestValue >= beta ? BOUND_LOWER :
1165
- PvNode && bestMove ? BOUND_EXACT : BOUND_UPPER,
1166
- depth, bestMove, ss->staticEval, TT.generation());
1167
-
1168
- assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE);
1169
-
1170
- return bestValue;
1171
- }
1172
-
1173
-
1174
- // qsearch() is the quiescence search function, which is called by the main
1175
- // search function when the remaining depth is zero (or, to be more precise,
1176
- // less than ONE_PLY).
1177
-
1178
- template <NodeType NT, bool InCheck>
1179
- Value qsearch(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth) {
1180
-
1181
- const bool PvNode = NT == PV;
1182
-
1183
- assert(InCheck == !!pos.checkers());
1184
- assert(alpha >= -VALUE_INFINITE && alpha < beta && beta <= VALUE_INFINITE);
1185
- assert(PvNode || (alpha == beta - 1));
1186
- assert(depth <= DEPTH_ZERO);
1187
- assert(depth / ONE_PLY * ONE_PLY == depth);
1188
-
1189
- Move pv[MAX_PLY+1];
1190
- StateInfo st;
1191
- TTEntry* tte;
1192
- Key posKey;
1193
- Move ttMove, move, bestMove;
1194
- Value bestValue, value, ttValue, futilityValue, futilityBase, oldAlpha;
1195
- bool ttHit, givesCheck, evasionPrunable;
1196
- Depth ttDepth;
1197
-
1198
- if (PvNode)
1199
- {
1200
- oldAlpha = alpha; // To flag BOUND_EXACT when eval above alpha and no available moves
1201
- (ss+1)->pv = pv;
1202
- ss->pv[0] = MOVE_NONE;
1203
- }
1204
-
1205
- ss->currentMove = bestMove = MOVE_NONE;
1206
- ss->ply = (ss-1)->ply + 1;
1207
-
1208
- // Check for an instant draw or if the maximum ply has been reached
1209
- if (pos.is_draw() || ss->ply >= MAX_PLY)
1210
- return ss->ply >= MAX_PLY && !InCheck ? evaluate(pos)
1211
- : DrawValue[pos.side_to_move()];
1212
-
1213
- assert(0 <= ss->ply && ss->ply < MAX_PLY);
1214
-
1215
- // Decide whether or not to include checks: this fixes also the type of
1216
- // TT entry depth that we are going to use. Note that in qsearch we use
1217
- // only two types of depth in TT: DEPTH_QS_CHECKS or DEPTH_QS_NO_CHECKS.
1218
- ttDepth = InCheck || depth >= DEPTH_QS_CHECKS ? DEPTH_QS_CHECKS
1219
- : DEPTH_QS_NO_CHECKS;
1220
-
1221
- // Transposition table lookup
1222
- posKey = pos.key();
1223
- tte = TT.probe(posKey, ttHit);
1224
- ttMove = ttHit ? tte->move() : MOVE_NONE;
1225
- ttValue = ttHit ? value_from_tt(tte->value(), ss->ply) : VALUE_NONE;
1226
-
1227
- if ( !PvNode
1228
- && ttHit
1229
- && tte->depth() >= ttDepth
1230
- && ttValue != VALUE_NONE // Only in case of TT access race
1231
- && (ttValue >= beta ? (tte->bound() & BOUND_LOWER)
1232
- : (tte->bound() & BOUND_UPPER)))
1233
- return ttValue;
1234
-
1235
- // Evaluate the position statically
1236
- if (InCheck)
1237
- {
1238
- ss->staticEval = VALUE_NONE;
1239
- bestValue = futilityBase = -VALUE_INFINITE;
1240
- }
1241
- else
1242
- {
1243
- if (ttHit)
1244
- {
1245
- // Never assume anything on values stored in TT
1246
- if ((ss->staticEval = bestValue = tte->eval()) == VALUE_NONE)
1247
- ss->staticEval = bestValue = evaluate(pos);
1248
-
1249
- // Can ttValue be used as a better position evaluation?
1250
- if (ttValue != VALUE_NONE)
1251
- if (tte->bound() & (ttValue > bestValue ? BOUND_LOWER : BOUND_UPPER))
1252
- bestValue = ttValue;
1253
- }
1254
- else
1255
- ss->staticEval = bestValue =
1256
- (ss-1)->currentMove != MOVE_NULL ? evaluate(pos)
1257
- : -(ss-1)->staticEval + 2 * Eval::Tempo;
1258
-
1259
- // Stand pat. Return immediately if static value is at least beta
1260
- if (bestValue >= beta)
1261
- {
1262
- if (!ttHit)
1263
- tte->save(pos.key(), value_to_tt(bestValue, ss->ply), BOUND_LOWER,
1264
- DEPTH_NONE, MOVE_NONE, ss->staticEval, TT.generation());
1265
-
1266
- return bestValue;
1267
- }
1268
-
1269
- if (PvNode && bestValue > alpha)
1270
- alpha = bestValue;
1271
-
1272
- futilityBase = bestValue + 128;
1273
- }
1274
-
1275
- // Initialize a MovePicker object for the current position, and prepare
1276
- // to search the moves. Because the depth is <= 0 here, only captures,
1277
- // queen promotions and checks (only if depth >= DEPTH_QS_CHECKS) will
1278
- // be generated.
1279
- MovePicker mp(pos, ttMove, depth, to_sq((ss-1)->currentMove));
1280
-
1281
- // Loop through the moves until no moves remain or a beta cutoff occurs
1282
- while ((move = mp.next_move()) != MOVE_NONE)
1283
- {
1284
- assert(is_ok(move));
1285
-
1286
- givesCheck = type_of(move) == NORMAL && !pos.discovered_check_candidates()
1287
- ? pos.check_squares(type_of(pos.piece_on(from_sq(move)))) & to_sq(move)
1288
- : pos.gives_check(move);
1289
-
1290
- // Futility pruning
1291
- if ( !InCheck
1292
- && !givesCheck
1293
- && futilityBase > -VALUE_KNOWN_WIN
1294
- && !pos.advanced_pawn_push(move))
1295
- {
1296
- assert(type_of(move) != ENPASSANT); // Due to !pos.advanced_pawn_push
1297
-
1298
- futilityValue = futilityBase + PieceValue[EG][pos.piece_on(to_sq(move))];
1299
-
1300
- if (futilityValue <= alpha)
1301
- {
1302
- bestValue = std::max(bestValue, futilityValue);
1303
- continue;
1304
- }
1305
-
1306
- if (futilityBase <= alpha && !pos.see_ge(move, VALUE_ZERO + 1))
1307
- {
1308
- bestValue = std::max(bestValue, futilityBase);
1309
- continue;
1310
- }
1311
- }
1312
-
1313
- // Detect non-capture evasions that are candidates to be pruned
1314
- evasionPrunable = InCheck
1315
- && bestValue > VALUE_MATED_IN_MAX_PLY
1316
- && !pos.capture(move);
1317
-
1318
- // Don't search moves with negative SEE values
1319
- if ( (!InCheck || evasionPrunable)
1320
- && type_of(move) != PROMOTION
1321
- && !pos.see_ge(move, VALUE_ZERO))
1322
- continue;
1323
-
1324
- // Speculative prefetch as early as possible
1325
- prefetch(TT.first_entry(pos.key_after(move)));
1326
-
1327
- // Check for legality just before making the move
1328
- if (!pos.legal(move))
1329
- continue;
1330
-
1331
- ss->currentMove = move;
1332
-
1333
- // Make and search the move
1334
- pos.do_move(move, st, givesCheck);
1335
- value = givesCheck ? -qsearch<NT, true>(pos, ss+1, -beta, -alpha, depth - ONE_PLY)
1336
- : -qsearch<NT, false>(pos, ss+1, -beta, -alpha, depth - ONE_PLY);
1337
- pos.undo_move(move);
1338
-
1339
- assert(value > -VALUE_INFINITE && value < VALUE_INFINITE);
1340
-
1341
- // Check for a new best move
1342
- if (value > bestValue)
1343
- {
1344
- bestValue = value;
1345
-
1346
- if (value > alpha)
1347
- {
1348
- if (PvNode) // Update pv even in fail-high case
1349
- update_pv(ss->pv, move, (ss+1)->pv);
1350
-
1351
- if (PvNode && value < beta) // Update alpha here!
1352
- {
1353
- alpha = value;
1354
- bestMove = move;
1355
- }
1356
- else // Fail high
1357
- {
1358
- tte->save(posKey, value_to_tt(value, ss->ply), BOUND_LOWER,
1359
- ttDepth, move, ss->staticEval, TT.generation());
1360
-
1361
- return value;
1362
- }
1363
- }
1364
- }
1365
- }
1366
-
1367
- // All legal moves have been searched. A special case: If we're in check
1368
- // and no legal moves were found, it is checkmate.
1369
- if (InCheck && bestValue == -VALUE_INFINITE)
1370
- return mated_in(ss->ply); // Plies to mate from the root
1371
-
1372
- tte->save(posKey, value_to_tt(bestValue, ss->ply),
1373
- PvNode && bestValue > oldAlpha ? BOUND_EXACT : BOUND_UPPER,
1374
- ttDepth, bestMove, ss->staticEval, TT.generation());
1375
-
1376
- assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE);
1377
-
1378
- return bestValue;
1379
- }
1380
-
1381
-
1382
- // value_to_tt() adjusts a mate score from "plies to mate from the root" to
1383
- // "plies to mate from the current position". Non-mate scores are unchanged.
1384
- // The function is called before storing a value in the transposition table.
1385
-
1386
- Value value_to_tt(Value v, int ply) {
1387
-
1388
- assert(v != VALUE_NONE);
1389
-
1390
- return v >= VALUE_MATE_IN_MAX_PLY ? v + ply
1391
- : v <= VALUE_MATED_IN_MAX_PLY ? v - ply : v;
1392
- }
1393
-
1394
-
1395
- // value_from_tt() is the inverse of value_to_tt(): It adjusts a mate score
1396
- // from the transposition table (which refers to the plies to mate/be mated
1397
- // from current position) to "plies to mate/be mated from the root".
1398
-
1399
- Value value_from_tt(Value v, int ply) {
1400
-
1401
- return v == VALUE_NONE ? VALUE_NONE
1402
- : v >= VALUE_MATE_IN_MAX_PLY ? v - ply
1403
- : v <= VALUE_MATED_IN_MAX_PLY ? v + ply : v;
1404
- }
1405
-
1406
-
1407
- // update_pv() adds current move and appends child pv[]
1408
-
1409
- void update_pv(Move* pv, Move move, Move* childPv) {
1410
-
1411
- for (*pv++ = move; childPv && *childPv != MOVE_NONE; )
1412
- *pv++ = *childPv++;
1413
- *pv = MOVE_NONE;
1414
- }
1415
-
1416
-
1417
- // update_cm_stats() updates countermove and follow-up move history
1418
-
1419
- void update_cm_stats(Stack* ss, Piece pc, Square s, Value bonus) {
1420
-
1421
- CounterMoveStats* cmh = (ss-1)->counterMoves;
1422
- CounterMoveStats* fmh1 = (ss-2)->counterMoves;
1423
- CounterMoveStats* fmh2 = (ss-4)->counterMoves;
1424
-
1425
- if (cmh)
1426
- cmh->update(pc, s, bonus);
1427
-
1428
- if (fmh1)
1429
- fmh1->update(pc, s, bonus);
1430
-
1431
- if (fmh2)
1432
- fmh2->update(pc, s, bonus);
1433
- }
1434
-
1435
-
1436
- // update_stats() updates killers, history, countermove and countermove plus
1437
- // follow-up move history when a new quiet best move is found.
1438
-
1439
- void update_stats(const Position& pos, Stack* ss, Move move,
1440
- Move* quiets, int quietsCnt, Value bonus) {
1441
-
1442
- if (ss->killers[0] != move)
1443
- {
1444
- ss->killers[1] = ss->killers[0];
1445
- ss->killers[0] = move;
1446
- }
1447
-
1448
- Color c = pos.side_to_move();
1449
- Thread* thisThread = pos.this_thread();
1450
- thisThread->fromTo.update(c, move, bonus);
1451
- thisThread->history.update(pos.moved_piece(move), to_sq(move), bonus);
1452
- update_cm_stats(ss, pos.moved_piece(move), to_sq(move), bonus);
1453
-
1454
- if ((ss-1)->counterMoves)
1455
- {
1456
- Square prevSq = to_sq((ss-1)->currentMove);
1457
- thisThread->counterMoves.update(pos.piece_on(prevSq), prevSq, move);
1458
- }
1459
-
1460
- // Decrease all the other played quiet moves
1461
- for (int i = 0; i < quietsCnt; ++i)
1462
- {
1463
- thisThread->fromTo.update(c, quiets[i], -bonus);
1464
- thisThread->history.update(pos.moved_piece(quiets[i]), to_sq(quiets[i]), -bonus);
1465
- update_cm_stats(ss, pos.moved_piece(quiets[i]), to_sq(quiets[i]), -bonus);
1466
- }
1467
- }
1468
-
1469
-
1470
- // When playing with strength handicap, choose best move among a set of RootMoves
1471
- // using a statistical rule dependent on 'level'. Idea by Heinz van Saanen.
1472
-
1473
- Move Skill::pick_best(size_t multiPV) {
1474
-
1475
- const RootMoves& rootMoves = Threads.main()->rootMoves;
1476
- static PRNG rng(now()); // PRNG sequence should be non-deterministic
1477
-
1478
- // RootMoves are already sorted by score in descending order
1479
- Value topScore = rootMoves[0].score;
1480
- int delta = std::min(topScore - rootMoves[multiPV - 1].score, PawnValueMg);
1481
- int weakness = 120 - 2 * level;
1482
- int maxScore = -VALUE_INFINITE;
1483
-
1484
- // Choose best move. For each move score we add two terms, both dependent on
1485
- // weakness. One is deterministic and bigger for weaker levels, and one is
1486
- // random. Then we choose the move with the resulting highest score.
1487
- for (size_t i = 0; i < multiPV; ++i)
1488
- {
1489
- // This is our magic formula
1490
- int push = ( weakness * int(topScore - rootMoves[i].score)
1491
- + delta * (rng.rand<unsigned>() % weakness)) / 128;
1492
-
1493
- if (rootMoves[i].score + push > maxScore)
1494
- {
1495
- maxScore = rootMoves[i].score + push;
1496
- best = rootMoves[i].pv[0];
1497
- }
1498
- }
1499
-
1500
- return best;
1501
- }
1502
-
1503
-
1504
- // check_time() is used to print debug info and, more importantly, to detect
1505
- // when we are out of available time and thus stop the search.
1506
-
1507
- void check_time() {
1508
-
1509
- static TimePoint lastInfoTime = now();
1510
-
1511
- int elapsed = Time.elapsed();
1512
- TimePoint tick = Limits.startTime + elapsed;
1513
-
1514
- if (tick - lastInfoTime >= 1000)
1515
- {
1516
- lastInfoTime = tick;
1517
- dbg_print();
1518
- }
1519
-
1520
- // An engine may not stop pondering until told so by the GUI
1521
- if (Limits.ponder)
1522
- return;
1523
-
1524
- if ( (Limits.use_time_management() && elapsed > Time.maximum() - 10)
1525
- || (Limits.movetime && elapsed >= Limits.movetime)
1526
- || (Limits.nodes && Threads.nodes_searched() >= (uint64_t)Limits.nodes))
1527
- Signals.stop = true;
1528
- }
1529
-
1530
- } // namespace
1531
-
1532
-
1533
- /// UCI::pv() formats PV information according to the UCI protocol. UCI requires
1534
- /// that all (if any) unsearched PV lines are sent using a previous search score.
1535
-
1536
- string UCI::pv(const Position& pos, Depth depth, Value alpha, Value beta) {
1537
-
1538
- std::stringstream ss;
1539
- int elapsed = Time.elapsed() + 1;
1540
- const RootMoves& rootMoves = pos.this_thread()->rootMoves;
1541
- size_t PVIdx = pos.this_thread()->PVIdx;
1542
- size_t multiPV = std::min((size_t)Options["MultiPV"], rootMoves.size());
1543
- uint64_t nodesSearched = Threads.nodes_searched();
1544
- uint64_t tbHits = Threads.tb_hits() + (TB::RootInTB ? rootMoves.size() : 0);
1545
-
1546
- for (size_t i = 0; i < multiPV; ++i)
1547
- {
1548
- bool updated = (i <= PVIdx);
1549
-
1550
- if (depth == ONE_PLY && !updated)
1551
- continue;
1552
-
1553
- Depth d = updated ? depth : depth - ONE_PLY;
1554
- Value v = updated ? rootMoves[i].score : rootMoves[i].previousScore;
1555
-
1556
- bool tb = TB::RootInTB && abs(v) < VALUE_MATE - MAX_PLY;
1557
- v = tb ? TB::Score : v;
1558
-
1559
- if (ss.rdbuf()->in_avail()) // Not at first line
1560
- ss << "\n";
1561
-
1562
- ss << "info"
1563
- << " depth " << d / ONE_PLY
1564
- << " seldepth " << pos.this_thread()->maxPly
1565
- << " multipv " << i + 1
1566
- << " score " << UCI::value(v);
1567
-
1568
- if (!tb && i == PVIdx)
1569
- ss << (v >= beta ? " lowerbound" : v <= alpha ? " upperbound" : "");
1570
-
1571
- ss << " nodes " << nodesSearched
1572
- << " nps " << nodesSearched * 1000 / elapsed;
1573
-
1574
- if (elapsed > 1000) // Earlier makes little sense
1575
- ss << " hashfull " << TT.hashfull();
1576
-
1577
- ss << " tbhits " << tbHits
1578
- << " time " << elapsed
1579
- << " pv";
1580
-
1581
- for (Move m : rootMoves[i].pv)
1582
- ss << " " << UCI::move(m, pos.is_chess960());
1583
- }
1584
-
1585
- return ss.str();
1586
- }
1587
-
1588
-
1589
- /// RootMove::extract_ponder_from_tt() is called in case we have no ponder move
1590
- /// before exiting the search, for instance, in case we stop the search during a
1591
- /// fail high at root. We try hard to have a ponder move to return to the GUI,
1592
- /// otherwise in case of 'ponder on' we have nothing to think on.
1593
-
1594
- bool RootMove::extract_ponder_from_tt(Position& pos) {
1595
-
1596
- StateInfo st;
1597
- bool ttHit;
1598
-
1599
- assert(pv.size() == 1);
1600
-
1601
- if (!pv[0])
1602
- return false;
1603
-
1604
- pos.do_move(pv[0], st, pos.gives_check(pv[0]));
1605
- TTEntry* tte = TT.probe(pos.key(), ttHit);
1606
-
1607
- if (ttHit)
1608
- {
1609
- Move m = tte->move(); // Local copy to be SMP safe
1610
- if (MoveList<LEGAL>(pos).contains(m))
1611
- pv.push_back(m);
1612
- }
1613
-
1614
- pos.undo_move(pv[0]);
1615
- return pv.size() > 1;
1616
- }
1617
-
1618
- void Tablebases::filter_root_moves(Position& pos, Search::RootMoves& rootMoves) {
1619
-
1620
- RootInTB = false;
1621
- UseRule50 = Options["Syzygy50MoveRule"];
1622
- ProbeDepth = Options["SyzygyProbeDepth"] * ONE_PLY;
1623
- Cardinality = Options["SyzygyProbeLimit"];
1624
-
1625
- // Skip TB probing when no TB found: !TBLargest -> !TB::Cardinality
1626
- if (Cardinality > MaxCardinality)
1627
- {
1628
- Cardinality = MaxCardinality;
1629
- ProbeDepth = DEPTH_ZERO;
1630
- }
1631
-
1632
- if (Cardinality < popcount(pos.pieces()) || pos.can_castle(ANY_CASTLING))
1633
- return;
1634
-
1635
- // If the current root position is in the tablebases, then RootMoves
1636
- // contains only moves that preserve the draw or the win.
1637
- RootInTB = root_probe(pos, rootMoves, TB::Score);
1638
-
1639
- if (RootInTB)
1640
- Cardinality = 0; // Do not probe tablebases during the search
1641
-
1642
- else // If DTZ tables are missing, use WDL tables as a fallback
1643
- {
1644
- // Filter out moves that do not preserve the draw or the win.
1645
- RootInTB = root_probe_wdl(pos, rootMoves, TB::Score);
1646
-
1647
- // Only probe during search if winning
1648
- if (RootInTB && TB::Score <= VALUE_DRAW)
1649
- Cardinality = 0;
1650
- }
1651
-
1652
- if (RootInTB && !UseRule50)
1653
- TB::Score = TB::Score > VALUE_DRAW ? VALUE_MATE - MAX_PLY - 1
1654
- : TB::Score < VALUE_DRAW ? -VALUE_MATE + MAX_PLY + 1
1655
- : VALUE_DRAW;
1656
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/search.h DELETED
@@ -1,111 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #ifndef SEARCH_H_INCLUDED
22
- #define SEARCH_H_INCLUDED
23
-
24
- #include <atomic>
25
- #include <vector>
26
-
27
- #include "misc.h"
28
- #include "movepick.h"
29
- #include "types.h"
30
-
31
- class Position;
32
-
33
- namespace Search {
34
-
35
- /// Stack struct keeps track of the information we need to remember from nodes
36
- /// shallower and deeper in the tree during the search. Each search thread has
37
- /// its own array of Stack objects, indexed by the current ply.
38
-
39
- struct Stack {
40
- Move* pv;
41
- int ply;
42
- Move currentMove;
43
- Move excludedMove;
44
- Move killers[2];
45
- Value staticEval;
46
- Value history;
47
- bool skipEarlyPruning;
48
- int moveCount;
49
- CounterMoveStats* counterMoves;
50
- };
51
-
52
-
53
- /// RootMove struct is used for moves at the root of the tree. For each root move
54
- /// we store a score and a PV (really a refutation in the case of moves which
55
- /// fail low). Score is normally set at -VALUE_INFINITE for all non-pv moves.
56
-
57
- struct RootMove {
58
-
59
- explicit RootMove(Move m) : pv(1, m) {}
60
-
61
- bool operator<(const RootMove& m) const { return m.score < score; } // Descending sort
62
- bool operator==(const Move& m) const { return pv[0] == m; }
63
- bool extract_ponder_from_tt(Position& pos);
64
-
65
- Value score = -VALUE_INFINITE;
66
- Value previousScore = -VALUE_INFINITE;
67
- std::vector<Move> pv;
68
- };
69
-
70
- typedef std::vector<RootMove> RootMoves;
71
-
72
-
73
- /// LimitsType struct stores information sent by GUI about available time to
74
- /// search the current move, maximum depth/time, if we are in analysis mode or
75
- /// if we have to ponder while it's our opponent's turn to move.
76
-
77
- struct LimitsType {
78
-
79
- LimitsType() { // Init explicitly due to broken value-initialization of non POD in MSVC
80
- nodes = time[WHITE] = time[BLACK] = inc[WHITE] = inc[BLACK] =
81
- npmsec = movestogo = depth = movetime = mate = infinite = ponder = 0;
82
- }
83
-
84
- bool use_time_management() const {
85
- return !(mate | movetime | depth | nodes | infinite);
86
- }
87
-
88
- std::vector<Move> searchmoves;
89
- int time[COLOR_NB], inc[COLOR_NB], npmsec, movestogo, depth, movetime, mate, infinite, ponder;
90
- int64_t nodes;
91
- TimePoint startTime;
92
- };
93
-
94
-
95
- /// SignalsType struct stores atomic flags updated during the search, typically
96
- /// in an async fashion e.g. to stop the search by the GUI.
97
-
98
- struct SignalsType {
99
- std::atomic_bool stop, stopOnPonderhit;
100
- };
101
-
102
- extern SignalsType Signals;
103
- extern LimitsType Limits;
104
-
105
- void init();
106
- void clear();
107
- template<bool Root = true> uint64_t perft(Position& pos, Depth depth);
108
-
109
- } // namespace Search
110
-
111
- #endif // #ifndef SEARCH_H_INCLUDED
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/syzygy/tbcore.cpp DELETED
@@ -1,1378 +0,0 @@
1
- /*
2
- Copyright (c) 2011-2013 Ronald de Man
3
- This file may be redistributed and/or modified without restrictions.
4
-
5
- tbcore.c contains engine-independent routines of the tablebase probing code.
6
- This file should not need too much adaptation to add tablebase probing to
7
- a particular engine, provided the engine is written in C or C++.
8
- */
9
-
10
- #include <stdio.h>
11
- #include <stdint.h>
12
- #include <stdlib.h>
13
- #include <string.h>
14
- #include <sys/stat.h>
15
- #include <fcntl.h>
16
- #ifndef _WIN32
17
- #include <unistd.h>
18
- #include <sys/mman.h>
19
- #endif
20
- #include "tbcore.h"
21
-
22
- #define TBMAX_PIECE 254
23
- #define TBMAX_PAWN 256
24
- #define HSHMAX 5
25
-
26
- #define Swap(a,b) {int tmp=a;a=b;b=tmp;}
27
-
28
- #define TB_PAWN 1
29
- #define TB_KNIGHT 2
30
- #define TB_BISHOP 3
31
- #define TB_ROOK 4
32
- #define TB_QUEEN 5
33
- #define TB_KING 6
34
-
35
- #define TB_WPAWN TB_PAWN
36
- #define TB_BPAWN (TB_PAWN | 8)
37
-
38
- static LOCK_T TB_mutex;
39
-
40
- static bool initialized = false;
41
- static int num_paths = 0;
42
- static char *path_string = NULL;
43
- static char **paths = NULL;
44
-
45
- static int TBnum_piece, TBnum_pawn;
46
- static struct TBEntry_piece TB_piece[TBMAX_PIECE];
47
- static struct TBEntry_pawn TB_pawn[TBMAX_PAWN];
48
-
49
- static struct TBHashEntry TB_hash[1 << TBHASHBITS][HSHMAX];
50
-
51
- #define DTZ_ENTRIES 64
52
-
53
- static struct DTZTableEntry DTZ_table[DTZ_ENTRIES];
54
-
55
- static void init_indices(void);
56
- static uint64 calc_key_from_pcs(int *pcs, int mirror);
57
- static void free_wdl_entry(struct TBEntry *entry);
58
- static void free_dtz_entry(struct TBEntry *entry);
59
-
60
- static FD open_tb(const char *str, const char *suffix)
61
- {
62
- int i;
63
- FD fd;
64
- char file[256];
65
-
66
- for (i = 0; i < num_paths; i++) {
67
- strcpy(file, paths[i]);
68
- strcat(file, "/");
69
- strcat(file, str);
70
- strcat(file, suffix);
71
- #ifndef _WIN32
72
- fd = open(file, O_RDONLY);
73
- #else
74
- fd = CreateFile(file, GENERIC_READ, FILE_SHARE_READ, NULL,
75
- OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
76
- #endif
77
- if (fd != FD_ERR) return fd;
78
- }
79
- return FD_ERR;
80
- }
81
-
82
- static void close_tb(FD fd)
83
- {
84
- #ifndef _WIN32
85
- close(fd);
86
- #else
87
- CloseHandle(fd);
88
- #endif
89
- }
90
-
91
- static char *map_file(const char *name, const char *suffix, uint64 *mapping)
92
- {
93
- FD fd = open_tb(name, suffix);
94
- if (fd == FD_ERR)
95
- return NULL;
96
- #ifndef _WIN32
97
- struct stat statbuf;
98
- fstat(fd, &statbuf);
99
- *mapping = statbuf.st_size;
100
- char *data = (char *)mmap(NULL, statbuf.st_size, PROT_READ,
101
- MAP_SHARED, fd, 0);
102
- if (data == (char *)(-1)) {
103
- printf("Could not mmap() %s.\n", name);
104
- exit(1);
105
- }
106
- #else
107
- DWORD size_low, size_high;
108
- size_low = GetFileSize(fd, &size_high);
109
- // *size = ((uint64)size_high) << 32 | ((uint64)size_low);
110
- HANDLE map = CreateFileMapping(fd, NULL, PAGE_READONLY, size_high, size_low,
111
- NULL);
112
- if (map == NULL) {
113
- printf("CreateFileMapping() failed.\n");
114
- exit(1);
115
- }
116
- *mapping = (uint64)map;
117
- char *data = (char *)MapViewOfFile(map, FILE_MAP_READ, 0, 0, 0);
118
- if (data == NULL) {
119
- printf("MapViewOfFile() failed, name = %s%s, error = %lu.\n", name, suffix, GetLastError());
120
- exit(1);
121
- }
122
- #endif
123
- close_tb(fd);
124
- return data;
125
- }
126
-
127
- #ifndef _WIN32
128
- static void unmap_file(char *data, uint64 size)
129
- {
130
- if (!data) return;
131
- munmap(data, size);
132
- }
133
- #else
134
- static void unmap_file(char *data, uint64 mapping)
135
- {
136
- if (!data) return;
137
- UnmapViewOfFile(data);
138
- CloseHandle((HANDLE)mapping);
139
- }
140
- #endif
141
-
142
- static void add_to_hash(struct TBEntry *ptr, uint64 key)
143
- {
144
- int i, hshidx;
145
-
146
- hshidx = key >> (64 - TBHASHBITS);
147
- i = 0;
148
- while (i < HSHMAX && TB_hash[hshidx][i].ptr)
149
- i++;
150
- if (i == HSHMAX) {
151
- printf("HSHMAX too low!\n");
152
- exit(1);
153
- } else {
154
- TB_hash[hshidx][i].key = key;
155
- TB_hash[hshidx][i].ptr = ptr;
156
- }
157
- }
158
-
159
- static char pchr[] = {'K', 'Q', 'R', 'B', 'N', 'P'};
160
-
161
- static void init_tb(char *str)
162
- {
163
- FD fd;
164
- struct TBEntry *entry;
165
- int i, j, pcs[16];
166
- uint64 key, key2;
167
- int color;
168
- char *s;
169
-
170
- fd = open_tb(str, WDLSUFFIX);
171
- if (fd == FD_ERR) return;
172
- close_tb(fd);
173
-
174
- for (i = 0; i < 16; i++)
175
- pcs[i] = 0;
176
- color = 0;
177
- for (s = str; *s; s++)
178
- switch (*s) {
179
- case 'P':
180
- pcs[TB_PAWN | color]++;
181
- break;
182
- case 'N':
183
- pcs[TB_KNIGHT | color]++;
184
- break;
185
- case 'B':
186
- pcs[TB_BISHOP | color]++;
187
- break;
188
- case 'R':
189
- pcs[TB_ROOK | color]++;
190
- break;
191
- case 'Q':
192
- pcs[TB_QUEEN | color]++;
193
- break;
194
- case 'K':
195
- pcs[TB_KING | color]++;
196
- break;
197
- case 'v':
198
- color = 0x08;
199
- break;
200
- }
201
- for (i = 0; i < 8; i++)
202
- if (pcs[i] != pcs[i+8])
203
- break;
204
- key = calc_key_from_pcs(pcs, 0);
205
- key2 = calc_key_from_pcs(pcs, 1);
206
- if (pcs[TB_WPAWN] + pcs[TB_BPAWN] == 0) {
207
- if (TBnum_piece == TBMAX_PIECE) {
208
- printf("TBMAX_PIECE limit too low!\n");
209
- exit(1);
210
- }
211
- entry = (struct TBEntry *)&TB_piece[TBnum_piece++];
212
- } else {
213
- if (TBnum_pawn == TBMAX_PAWN) {
214
- printf("TBMAX_PAWN limit too low!\n");
215
- exit(1);
216
- }
217
- entry = (struct TBEntry *)&TB_pawn[TBnum_pawn++];
218
- }
219
- entry->key = key;
220
- entry->ready = 0;
221
- entry->num = 0;
222
- for (i = 0; i < 16; i++)
223
- entry->num += (ubyte)pcs[i];
224
- entry->symmetric = (key == key2);
225
- entry->has_pawns = (pcs[TB_WPAWN] + pcs[TB_BPAWN] > 0);
226
- if (entry->num > Tablebases::MaxCardinality)
227
- Tablebases::MaxCardinality = entry->num;
228
-
229
- if (entry->has_pawns) {
230
- struct TBEntry_pawn *ptr = (struct TBEntry_pawn *)entry;
231
- ptr->pawns[0] = (ubyte)pcs[TB_WPAWN];
232
- ptr->pawns[1] = (ubyte)pcs[TB_BPAWN];
233
- if (pcs[TB_BPAWN] > 0
234
- && (pcs[TB_WPAWN] == 0 || pcs[TB_BPAWN] < pcs[TB_WPAWN])) {
235
- ptr->pawns[0] = (ubyte)pcs[TB_BPAWN];
236
- ptr->pawns[1] = (ubyte)pcs[TB_WPAWN];
237
- }
238
- } else {
239
- struct TBEntry_piece *ptr = (struct TBEntry_piece *)entry;
240
- for (i = 0, j = 0; i < 16; i++)
241
- if (pcs[i] == 1) j++;
242
- if (j >= 3) ptr->enc_type = 0;
243
- else if (j == 2) ptr->enc_type = 2;
244
- else { /* only for suicide */
245
- j = 16;
246
- for (i = 0; i < 16; i++) {
247
- if (pcs[i] < j && pcs[i] > 1) j = pcs[i];
248
- ptr->enc_type = ubyte(1 + j);
249
- }
250
- }
251
- }
252
- add_to_hash(entry, key);
253
- if (key2 != key) add_to_hash(entry, key2);
254
- }
255
-
256
- void Tablebases::init(const std::string& path)
257
- {
258
- char str[16];
259
- int i, j, k, l;
260
-
261
- if (initialized) {
262
- free(path_string);
263
- free(paths);
264
- struct TBEntry *entry;
265
- for (i = 0; i < TBnum_piece; i++) {
266
- entry = (struct TBEntry *)&TB_piece[i];
267
- free_wdl_entry(entry);
268
- }
269
- for (i = 0; i < TBnum_pawn; i++) {
270
- entry = (struct TBEntry *)&TB_pawn[i];
271
- free_wdl_entry(entry);
272
- }
273
- for (i = 0; i < DTZ_ENTRIES; i++)
274
- if (DTZ_table[i].entry)
275
- free_dtz_entry(DTZ_table[i].entry);
276
- } else {
277
- init_indices();
278
- initialized = true;
279
- }
280
-
281
- const char *p = path.c_str();
282
- if (strlen(p) == 0 || !strcmp(p, "<empty>")) return;
283
- path_string = (char *)malloc(strlen(p) + 1);
284
- strcpy(path_string, p);
285
- num_paths = 0;
286
- for (i = 0;; i++) {
287
- if (path_string[i] != SEP_CHAR)
288
- num_paths++;
289
- while (path_string[i] && path_string[i] != SEP_CHAR)
290
- i++;
291
- if (!path_string[i]) break;
292
- path_string[i] = 0;
293
- }
294
- paths = (char **)malloc(num_paths * sizeof(char *));
295
- for (i = j = 0; i < num_paths; i++) {
296
- while (!path_string[j]) j++;
297
- paths[i] = &path_string[j];
298
- while (path_string[j]) j++;
299
- }
300
-
301
- LOCK_INIT(TB_mutex);
302
-
303
- TBnum_piece = TBnum_pawn = 0;
304
- MaxCardinality = 0;
305
-
306
- for (i = 0; i < (1 << TBHASHBITS); i++)
307
- for (j = 0; j < HSHMAX; j++) {
308
- TB_hash[i][j].key = 0ULL;
309
- TB_hash[i][j].ptr = NULL;
310
- }
311
-
312
- for (i = 0; i < DTZ_ENTRIES; i++)
313
- DTZ_table[i].entry = NULL;
314
-
315
- for (i = 1; i < 6; i++) {
316
- sprintf(str, "K%cvK", pchr[i]);
317
- init_tb(str);
318
- }
319
-
320
- for (i = 1; i < 6; i++)
321
- for (j = i; j < 6; j++) {
322
- sprintf(str, "K%cvK%c", pchr[i], pchr[j]);
323
- init_tb(str);
324
- }
325
-
326
- for (i = 1; i < 6; i++)
327
- for (j = i; j < 6; j++) {
328
- sprintf(str, "K%c%cvK", pchr[i], pchr[j]);
329
- init_tb(str);
330
- }
331
-
332
- for (i = 1; i < 6; i++)
333
- for (j = i; j < 6; j++)
334
- for (k = 1; k < 6; k++) {
335
- sprintf(str, "K%c%cvK%c", pchr[i], pchr[j], pchr[k]);
336
- init_tb(str);
337
- }
338
-
339
- for (i = 1; i < 6; i++)
340
- for (j = i; j < 6; j++)
341
- for (k = j; k < 6; k++) {
342
- sprintf(str, "K%c%c%cvK", pchr[i], pchr[j], pchr[k]);
343
- init_tb(str);
344
- }
345
-
346
- for (i = 1; i < 6; i++)
347
- for (j = i; j < 6; j++)
348
- for (k = i; k < 6; k++)
349
- for (l = (i == k) ? j : k; l < 6; l++) {
350
- sprintf(str, "K%c%cvK%c%c", pchr[i], pchr[j], pchr[k], pchr[l]);
351
- init_tb(str);
352
- }
353
-
354
- for (i = 1; i < 6; i++)
355
- for (j = i; j < 6; j++)
356
- for (k = j; k < 6; k++)
357
- for (l = 1; l < 6; l++) {
358
- sprintf(str, "K%c%c%cvK%c", pchr[i], pchr[j], pchr[k], pchr[l]);
359
- init_tb(str);
360
- }
361
-
362
- for (i = 1; i < 6; i++)
363
- for (j = i; j < 6; j++)
364
- for (k = j; k < 6; k++)
365
- for (l = k; l < 6; l++) {
366
- sprintf(str, "K%c%c%c%cvK", pchr[i], pchr[j], pchr[k], pchr[l]);
367
- init_tb(str);
368
- }
369
-
370
- printf("info string Found %d tablebases.\n", TBnum_piece + TBnum_pawn);
371
- }
372
-
373
- static const signed char offdiag[] = {
374
- 0,-1,-1,-1,-1,-1,-1,-1,
375
- 1, 0,-1,-1,-1,-1,-1,-1,
376
- 1, 1, 0,-1,-1,-1,-1,-1,
377
- 1, 1, 1, 0,-1,-1,-1,-1,
378
- 1, 1, 1, 1, 0,-1,-1,-1,
379
- 1, 1, 1, 1, 1, 0,-1,-1,
380
- 1, 1, 1, 1, 1, 1, 0,-1,
381
- 1, 1, 1, 1, 1, 1, 1, 0
382
- };
383
-
384
- static const ubyte triangle[] = {
385
- 6, 0, 1, 2, 2, 1, 0, 6,
386
- 0, 7, 3, 4, 4, 3, 7, 0,
387
- 1, 3, 8, 5, 5, 8, 3, 1,
388
- 2, 4, 5, 9, 9, 5, 4, 2,
389
- 2, 4, 5, 9, 9, 5, 4, 2,
390
- 1, 3, 8, 5, 5, 8, 3, 1,
391
- 0, 7, 3, 4, 4, 3, 7, 0,
392
- 6, 0, 1, 2, 2, 1, 0, 6
393
- };
394
-
395
- static const ubyte invtriangle[] = {
396
- 1, 2, 3, 10, 11, 19, 0, 9, 18, 27
397
- };
398
-
399
- static const ubyte invdiag[] = {
400
- 0, 9, 18, 27, 36, 45, 54, 63,
401
- 7, 14, 21, 28, 35, 42, 49, 56
402
- };
403
-
404
- static const ubyte flipdiag[] = {
405
- 0, 8, 16, 24, 32, 40, 48, 56,
406
- 1, 9, 17, 25, 33, 41, 49, 57,
407
- 2, 10, 18, 26, 34, 42, 50, 58,
408
- 3, 11, 19, 27, 35, 43, 51, 59,
409
- 4, 12, 20, 28, 36, 44, 52, 60,
410
- 5, 13, 21, 29, 37, 45, 53, 61,
411
- 6, 14, 22, 30, 38, 46, 54, 62,
412
- 7, 15, 23, 31, 39, 47, 55, 63
413
- };
414
-
415
- static const ubyte lower[] = {
416
- 28, 0, 1, 2, 3, 4, 5, 6,
417
- 0, 29, 7, 8, 9, 10, 11, 12,
418
- 1, 7, 30, 13, 14, 15, 16, 17,
419
- 2, 8, 13, 31, 18, 19, 20, 21,
420
- 3, 9, 14, 18, 32, 22, 23, 24,
421
- 4, 10, 15, 19, 22, 33, 25, 26,
422
- 5, 11, 16, 20, 23, 25, 34, 27,
423
- 6, 12, 17, 21, 24, 26, 27, 35
424
- };
425
-
426
- static const ubyte diag[] = {
427
- 0, 0, 0, 0, 0, 0, 0, 8,
428
- 0, 1, 0, 0, 0, 0, 9, 0,
429
- 0, 0, 2, 0, 0, 10, 0, 0,
430
- 0, 0, 0, 3, 11, 0, 0, 0,
431
- 0, 0, 0, 12, 4, 0, 0, 0,
432
- 0, 0, 13, 0, 0, 5, 0, 0,
433
- 0, 14, 0, 0, 0, 0, 6, 0,
434
- 15, 0, 0, 0, 0, 0, 0, 7
435
- };
436
-
437
- static const ubyte flap[] = {
438
- 0, 0, 0, 0, 0, 0, 0, 0,
439
- 0, 6, 12, 18, 18, 12, 6, 0,
440
- 1, 7, 13, 19, 19, 13, 7, 1,
441
- 2, 8, 14, 20, 20, 14, 8, 2,
442
- 3, 9, 15, 21, 21, 15, 9, 3,
443
- 4, 10, 16, 22, 22, 16, 10, 4,
444
- 5, 11, 17, 23, 23, 17, 11, 5,
445
- 0, 0, 0, 0, 0, 0, 0, 0
446
- };
447
-
448
- static const ubyte ptwist[] = {
449
- 0, 0, 0, 0, 0, 0, 0, 0,
450
- 47, 35, 23, 11, 10, 22, 34, 46,
451
- 45, 33, 21, 9, 8, 20, 32, 44,
452
- 43, 31, 19, 7, 6, 18, 30, 42,
453
- 41, 29, 17, 5, 4, 16, 28, 40,
454
- 39, 27, 15, 3, 2, 14, 26, 38,
455
- 37, 25, 13, 1, 0, 12, 24, 36,
456
- 0, 0, 0, 0, 0, 0, 0, 0
457
- };
458
-
459
- static const ubyte invflap[] = {
460
- 8, 16, 24, 32, 40, 48,
461
- 9, 17, 25, 33, 41, 49,
462
- 10, 18, 26, 34, 42, 50,
463
- 11, 19, 27, 35, 43, 51
464
- };
465
-
466
- static const ubyte invptwist[] = {
467
- 52, 51, 44, 43, 36, 35, 28, 27, 20, 19, 12, 11,
468
- 53, 50, 45, 42, 37, 34, 29, 26, 21, 18, 13, 10,
469
- 54, 49, 46, 41, 38, 33, 30, 25, 22, 17, 14, 9,
470
- 55, 48, 47, 40, 39, 32, 31, 24, 23, 16, 15, 8
471
- };
472
-
473
- static const ubyte file_to_file[] = {
474
- 0, 1, 2, 3, 3, 2, 1, 0
475
- };
476
-
477
- static const short KK_idx[10][64] = {
478
- { -1, -1, -1, 0, 1, 2, 3, 4,
479
- -1, -1, -1, 5, 6, 7, 8, 9,
480
- 10, 11, 12, 13, 14, 15, 16, 17,
481
- 18, 19, 20, 21, 22, 23, 24, 25,
482
- 26, 27, 28, 29, 30, 31, 32, 33,
483
- 34, 35, 36, 37, 38, 39, 40, 41,
484
- 42, 43, 44, 45, 46, 47, 48, 49,
485
- 50, 51, 52, 53, 54, 55, 56, 57 },
486
- { 58, -1, -1, -1, 59, 60, 61, 62,
487
- 63, -1, -1, -1, 64, 65, 66, 67,
488
- 68, 69, 70, 71, 72, 73, 74, 75,
489
- 76, 77, 78, 79, 80, 81, 82, 83,
490
- 84, 85, 86, 87, 88, 89, 90, 91,
491
- 92, 93, 94, 95, 96, 97, 98, 99,
492
- 100,101,102,103,104,105,106,107,
493
- 108,109,110,111,112,113,114,115},
494
- {116,117, -1, -1, -1,118,119,120,
495
- 121,122, -1, -1, -1,123,124,125,
496
- 126,127,128,129,130,131,132,133,
497
- 134,135,136,137,138,139,140,141,
498
- 142,143,144,145,146,147,148,149,
499
- 150,151,152,153,154,155,156,157,
500
- 158,159,160,161,162,163,164,165,
501
- 166,167,168,169,170,171,172,173 },
502
- {174, -1, -1, -1,175,176,177,178,
503
- 179, -1, -1, -1,180,181,182,183,
504
- 184, -1, -1, -1,185,186,187,188,
505
- 189,190,191,192,193,194,195,196,
506
- 197,198,199,200,201,202,203,204,
507
- 205,206,207,208,209,210,211,212,
508
- 213,214,215,216,217,218,219,220,
509
- 221,222,223,224,225,226,227,228 },
510
- {229,230, -1, -1, -1,231,232,233,
511
- 234,235, -1, -1, -1,236,237,238,
512
- 239,240, -1, -1, -1,241,242,243,
513
- 244,245,246,247,248,249,250,251,
514
- 252,253,254,255,256,257,258,259,
515
- 260,261,262,263,264,265,266,267,
516
- 268,269,270,271,272,273,274,275,
517
- 276,277,278,279,280,281,282,283 },
518
- {284,285,286,287,288,289,290,291,
519
- 292,293, -1, -1, -1,294,295,296,
520
- 297,298, -1, -1, -1,299,300,301,
521
- 302,303, -1, -1, -1,304,305,306,
522
- 307,308,309,310,311,312,313,314,
523
- 315,316,317,318,319,320,321,322,
524
- 323,324,325,326,327,328,329,330,
525
- 331,332,333,334,335,336,337,338 },
526
- { -1, -1,339,340,341,342,343,344,
527
- -1, -1,345,346,347,348,349,350,
528
- -1, -1,441,351,352,353,354,355,
529
- -1, -1, -1,442,356,357,358,359,
530
- -1, -1, -1, -1,443,360,361,362,
531
- -1, -1, -1, -1, -1,444,363,364,
532
- -1, -1, -1, -1, -1, -1,445,365,
533
- -1, -1, -1, -1, -1, -1, -1,446 },
534
- { -1, -1, -1,366,367,368,369,370,
535
- -1, -1, -1,371,372,373,374,375,
536
- -1, -1, -1,376,377,378,379,380,
537
- -1, -1, -1,447,381,382,383,384,
538
- -1, -1, -1, -1,448,385,386,387,
539
- -1, -1, -1, -1, -1,449,388,389,
540
- -1, -1, -1, -1, -1, -1,450,390,
541
- -1, -1, -1, -1, -1, -1, -1,451 },
542
- {452,391,392,393,394,395,396,397,
543
- -1, -1, -1, -1,398,399,400,401,
544
- -1, -1, -1, -1,402,403,404,405,
545
- -1, -1, -1, -1,406,407,408,409,
546
- -1, -1, -1, -1,453,410,411,412,
547
- -1, -1, -1, -1, -1,454,413,414,
548
- -1, -1, -1, -1, -1, -1,455,415,
549
- -1, -1, -1, -1, -1, -1, -1,456 },
550
- {457,416,417,418,419,420,421,422,
551
- -1,458,423,424,425,426,427,428,
552
- -1, -1, -1, -1, -1,429,430,431,
553
- -1, -1, -1, -1, -1,432,433,434,
554
- -1, -1, -1, -1, -1,435,436,437,
555
- -1, -1, -1, -1, -1,459,438,439,
556
- -1, -1, -1, -1, -1, -1,460,440,
557
- -1, -1, -1, -1, -1, -1, -1,461 }
558
- };
559
-
560
- static int binomial[5][64];
561
- static int pawnidx[5][24];
562
- static int pfactor[5][4];
563
-
564
- static void init_indices(void)
565
- {
566
- int i, j, k;
567
-
568
- // binomial[k-1][n] = Bin(n, k)
569
- for (i = 0; i < 5; i++)
570
- for (j = 0; j < 64; j++) {
571
- int f = j;
572
- int l = 1;
573
- for (k = 1; k <= i; k++) {
574
- f *= (j - k);
575
- l *= (k + 1);
576
- }
577
- binomial[i][j] = f / l;
578
- }
579
-
580
- for (i = 0; i < 5; i++) {
581
- int s = 0;
582
- for (j = 0; j < 6; j++) {
583
- pawnidx[i][j] = s;
584
- s += (i == 0) ? 1 : binomial[i - 1][ptwist[invflap[j]]];
585
- }
586
- pfactor[i][0] = s;
587
- s = 0;
588
- for (; j < 12; j++) {
589
- pawnidx[i][j] = s;
590
- s += (i == 0) ? 1 : binomial[i - 1][ptwist[invflap[j]]];
591
- }
592
- pfactor[i][1] = s;
593
- s = 0;
594
- for (; j < 18; j++) {
595
- pawnidx[i][j] = s;
596
- s += (i == 0) ? 1 : binomial[i - 1][ptwist[invflap[j]]];
597
- }
598
- pfactor[i][2] = s;
599
- s = 0;
600
- for (; j < 24; j++) {
601
- pawnidx[i][j] = s;
602
- s += (i == 0) ? 1 : binomial[i - 1][ptwist[invflap[j]]];
603
- }
604
- pfactor[i][3] = s;
605
- }
606
- }
607
-
608
- static uint64 encode_piece(struct TBEntry_piece *ptr, ubyte *norm, int *pos, int *factor)
609
- {
610
- uint64 idx;
611
- int i, j, k, m, l, p;
612
- int n = ptr->num;
613
-
614
- if (pos[0] & 0x04) {
615
- for (i = 0; i < n; i++)
616
- pos[i] ^= 0x07;
617
- }
618
- if (pos[0] & 0x20) {
619
- for (i = 0; i < n; i++)
620
- pos[i] ^= 0x38;
621
- }
622
-
623
- for (i = 0; i < n; i++)
624
- if (offdiag[pos[i]]) break;
625
- if (i < (ptr->enc_type == 0 ? 3 : 2) && offdiag[pos[i]] > 0)
626
- for (i = 0; i < n; i++)
627
- pos[i] = flipdiag[pos[i]];
628
-
629
- switch (ptr->enc_type) {
630
-
631
- case 0: /* 111 */
632
- i = (pos[1] > pos[0]);
633
- j = (pos[2] > pos[0]) + (pos[2] > pos[1]);
634
-
635
- if (offdiag[pos[0]])
636
- idx = triangle[pos[0]] * 63*62 + (pos[1] - i) * 62 + (pos[2] - j);
637
- else if (offdiag[pos[1]])
638
- idx = 6*63*62 + diag[pos[0]] * 28*62 + lower[pos[1]] * 62 + pos[2] - j;
639
- else if (offdiag[pos[2]])
640
- idx = 6*63*62 + 4*28*62 + (diag[pos[0]]) * 7*28 + (diag[pos[1]] - i) * 28 + lower[pos[2]];
641
- else
642
- idx = 6*63*62 + 4*28*62 + 4*7*28 + (diag[pos[0]] * 7*6) + (diag[pos[1]] - i) * 6 + (diag[pos[2]] - j);
643
- i = 3;
644
- break;
645
-
646
- case 1: /* K3 */
647
- j = (pos[2] > pos[0]) + (pos[2] > pos[1]);
648
-
649
- idx = KK_idx[triangle[pos[0]]][pos[1]];
650
- if (idx < 441)
651
- idx = idx + 441 * (pos[2] - j);
652
- else {
653
- idx = 441*62 + (idx - 441) + 21 * lower[pos[2]];
654
- if (!offdiag[pos[2]])
655
- idx -= j * 21;
656
- }
657
- i = 3;
658
- break;
659
-
660
- default: /* K2 */
661
- idx = KK_idx[triangle[pos[0]]][pos[1]];
662
- i = 2;
663
- break;
664
- }
665
- idx *= factor[0];
666
-
667
- for (; i < n;) {
668
- int t = norm[i];
669
- for (j = i; j < i + t; j++)
670
- for (k = j + 1; k < i + t; k++)
671
- if (pos[j] > pos[k]) Swap(pos[j], pos[k]);
672
- int s = 0;
673
- for (m = i; m < i + t; m++) {
674
- p = pos[m];
675
- for (l = 0, j = 0; l < i; l++)
676
- j += (p > pos[l]);
677
- s += binomial[m - i][p - j];
678
- }
679
- idx += ((uint64)s) * ((uint64)factor[i]);
680
- i += t;
681
- }
682
-
683
- return idx;
684
- }
685
-
686
- // determine file of leftmost pawn and sort pawns
687
- static int pawn_file(struct TBEntry_pawn *ptr, int *pos)
688
- {
689
- int i;
690
-
691
- for (i = 1; i < ptr->pawns[0]; i++)
692
- if (flap[pos[0]] > flap[pos[i]])
693
- Swap(pos[0], pos[i]);
694
-
695
- return file_to_file[pos[0] & 0x07];
696
- }
697
-
698
- static uint64 encode_pawn(struct TBEntry_pawn *ptr, ubyte *norm, int *pos, int *factor)
699
- {
700
- uint64 idx;
701
- int i, j, k, m, s, t;
702
- int n = ptr->num;
703
-
704
- if (pos[0] & 0x04)
705
- for (i = 0; i < n; i++)
706
- pos[i] ^= 0x07;
707
-
708
- for (i = 1; i < ptr->pawns[0]; i++)
709
- for (j = i + 1; j < ptr->pawns[0]; j++)
710
- if (ptwist[pos[i]] < ptwist[pos[j]])
711
- Swap(pos[i], pos[j]);
712
-
713
- t = ptr->pawns[0] - 1;
714
- idx = pawnidx[t][flap[pos[0]]];
715
- for (i = t; i > 0; i--)
716
- idx += binomial[t - i][ptwist[pos[i]]];
717
- idx *= factor[0];
718
-
719
- // remaining pawns
720
- i = ptr->pawns[0];
721
- t = i + ptr->pawns[1];
722
- if (t > i) {
723
- for (j = i; j < t; j++)
724
- for (k = j + 1; k < t; k++)
725
- if (pos[j] > pos[k]) Swap(pos[j], pos[k]);
726
- s = 0;
727
- for (m = i; m < t; m++) {
728
- int p = pos[m];
729
- for (k = 0, j = 0; k < i; k++)
730
- j += (p > pos[k]);
731
- s += binomial[m - i][p - j - 8];
732
- }
733
- idx += ((uint64)s) * ((uint64)factor[i]);
734
- i = t;
735
- }
736
-
737
- for (; i < n;) {
738
- t = norm[i];
739
- for (j = i; j < i + t; j++)
740
- for (k = j + 1; k < i + t; k++)
741
- if (pos[j] > pos[k]) Swap(pos[j], pos[k]);
742
- s = 0;
743
- for (m = i; m < i + t; m++) {
744
- int p = pos[m];
745
- for (k = 0, j = 0; k < i; k++)
746
- j += (p > pos[k]);
747
- s += binomial[m - i][p - j];
748
- }
749
- idx += ((uint64)s) * ((uint64)factor[i]);
750
- i += t;
751
- }
752
-
753
- return idx;
754
- }
755
-
756
- // place k like pieces on n squares
757
- static int subfactor(int k, int n)
758
- {
759
- int i, f, l;
760
-
761
- f = n;
762
- l = 1;
763
- for (i = 1; i < k; i++) {
764
- f *= n - i;
765
- l *= i + 1;
766
- }
767
-
768
- return f / l;
769
- }
770
-
771
- static uint64 calc_factors_piece(int *factor, int num, int order, ubyte *norm, ubyte enc_type)
772
- {
773
- int i, k, n;
774
- uint64 f;
775
- static int pivfac[] = { 31332, 28056, 462 };
776
-
777
- n = 64 - norm[0];
778
-
779
- f = 1;
780
- for (i = norm[0], k = 0; i < num || k == order; k++) {
781
- if (k == order) {
782
- factor[0] = static_cast<int>(f);
783
- f *= pivfac[enc_type];
784
- } else {
785
- factor[i] = static_cast<int>(f);
786
- f *= subfactor(norm[i], n);
787
- n -= norm[i];
788
- i += norm[i];
789
- }
790
- }
791
-
792
- return f;
793
- }
794
-
795
- static uint64 calc_factors_pawn(int *factor, int num, int order, int order2, ubyte *norm, int file)
796
- {
797
- int i, k, n;
798
- uint64 f;
799
-
800
- i = norm[0];
801
- if (order2 < 0x0f) i += norm[i];
802
- n = 64 - i;
803
-
804
- f = 1;
805
- for (k = 0; i < num || k == order || k == order2; k++) {
806
- if (k == order) {
807
- factor[0] = static_cast<int>(f);
808
- f *= pfactor[norm[0] - 1][file];
809
- } else if (k == order2) {
810
- factor[norm[0]] = static_cast<int>(f);
811
- f *= subfactor(norm[norm[0]], 48 - norm[0]);
812
- } else {
813
- factor[i] = static_cast<int>(f);
814
- f *= subfactor(norm[i], n);
815
- n -= norm[i];
816
- i += norm[i];
817
- }
818
- }
819
-
820
- return f;
821
- }
822
-
823
- static void set_norm_piece(struct TBEntry_piece *ptr, ubyte *norm, ubyte *pieces)
824
- {
825
- int i, j;
826
-
827
- for (i = 0; i < ptr->num; i++)
828
- norm[i] = 0;
829
-
830
- switch (ptr->enc_type) {
831
- case 0:
832
- norm[0] = 3;
833
- break;
834
- case 2:
835
- norm[0] = 2;
836
- break;
837
- default:
838
- norm[0] = ubyte(ptr->enc_type - 1);
839
- break;
840
- }
841
-
842
- for (i = norm[0]; i < ptr->num; i += norm[i])
843
- for (j = i; j < ptr->num && pieces[j] == pieces[i]; j++)
844
- norm[i]++;
845
- }
846
-
847
- static void set_norm_pawn(struct TBEntry_pawn *ptr, ubyte *norm, ubyte *pieces)
848
- {
849
- int i, j;
850
-
851
- for (i = 0; i < ptr->num; i++)
852
- norm[i] = 0;
853
-
854
- norm[0] = ptr->pawns[0];
855
- if (ptr->pawns[1]) norm[ptr->pawns[0]] = ptr->pawns[1];
856
-
857
- for (i = ptr->pawns[0] + ptr->pawns[1]; i < ptr->num; i += norm[i])
858
- for (j = i; j < ptr->num && pieces[j] == pieces[i]; j++)
859
- norm[i]++;
860
- }
861
-
862
- static void setup_pieces_piece(struct TBEntry_piece *ptr, unsigned char *data, uint64 *tb_size)
863
- {
864
- int i;
865
- int order;
866
-
867
- for (i = 0; i < ptr->num; i++)
868
- ptr->pieces[0][i] = ubyte(data[i + 1] & 0x0f);
869
- order = data[0] & 0x0f;
870
- set_norm_piece(ptr, ptr->norm[0], ptr->pieces[0]);
871
- tb_size[0] = calc_factors_piece(ptr->factor[0], ptr->num, order, ptr->norm[0], ptr->enc_type);
872
-
873
- for (i = 0; i < ptr->num; i++)
874
- ptr->pieces[1][i] = ubyte(data[i + 1] >> 4);
875
- order = data[0] >> 4;
876
- set_norm_piece(ptr, ptr->norm[1], ptr->pieces[1]);
877
- tb_size[1] = calc_factors_piece(ptr->factor[1], ptr->num, order, ptr->norm[1], ptr->enc_type);
878
- }
879
-
880
- static void setup_pieces_piece_dtz(struct DTZEntry_piece *ptr, unsigned char *data, uint64 *tb_size)
881
- {
882
- int i;
883
- int order;
884
-
885
- for (i = 0; i < ptr->num; i++)
886
- ptr->pieces[i] = ubyte(data[i + 1] & 0x0f);
887
- order = data[0] & 0x0f;
888
- set_norm_piece((struct TBEntry_piece *)ptr, ptr->norm, ptr->pieces);
889
- tb_size[0] = calc_factors_piece(ptr->factor, ptr->num, order, ptr->norm, ptr->enc_type);
890
- }
891
-
892
- static void setup_pieces_pawn(struct TBEntry_pawn *ptr, unsigned char *data, uint64 *tb_size, int f)
893
- {
894
- int i, j;
895
- int order, order2;
896
-
897
- j = 1 + (ptr->pawns[1] > 0);
898
- order = data[0] & 0x0f;
899
- order2 = ptr->pawns[1] ? (data[1] & 0x0f) : 0x0f;
900
- for (i = 0; i < ptr->num; i++)
901
- ptr->file[f].pieces[0][i] = ubyte(data[i + j] & 0x0f);
902
- set_norm_pawn(ptr, ptr->file[f].norm[0], ptr->file[f].pieces[0]);
903
- tb_size[0] = calc_factors_pawn(ptr->file[f].factor[0], ptr->num, order, order2, ptr->file[f].norm[0], f);
904
-
905
- order = data[0] >> 4;
906
- order2 = ptr->pawns[1] ? (data[1] >> 4) : 0x0f;
907
- for (i = 0; i < ptr->num; i++)
908
- ptr->file[f].pieces[1][i] = ubyte(data[i + j] >> 4);
909
- set_norm_pawn(ptr, ptr->file[f].norm[1], ptr->file[f].pieces[1]);
910
- tb_size[1] = calc_factors_pawn(ptr->file[f].factor[1], ptr->num, order, order2, ptr->file[f].norm[1], f);
911
- }
912
-
913
- static void setup_pieces_pawn_dtz(struct DTZEntry_pawn *ptr, unsigned char *data, uint64 *tb_size, int f)
914
- {
915
- int i, j;
916
- int order, order2;
917
-
918
- j = 1 + (ptr->pawns[1] > 0);
919
- order = data[0] & 0x0f;
920
- order2 = ptr->pawns[1] ? (data[1] & 0x0f) : 0x0f;
921
- for (i = 0; i < ptr->num; i++)
922
- ptr->file[f].pieces[i] = ubyte(data[i + j] & 0x0f);
923
- set_norm_pawn((struct TBEntry_pawn *)ptr, ptr->file[f].norm, ptr->file[f].pieces);
924
- tb_size[0] = calc_factors_pawn(ptr->file[f].factor, ptr->num, order, order2, ptr->file[f].norm, f);
925
- }
926
-
927
- static void calc_symlen(struct PairsData *d, int s, char *tmp)
928
- {
929
- int s1, s2;
930
-
931
- ubyte* w = d->sympat + 3 * s;
932
- s2 = (w[2] << 4) | (w[1] >> 4);
933
- if (s2 == 0x0fff)
934
- d->symlen[s] = 0;
935
- else {
936
- s1 = ((w[1] & 0xf) << 8) | w[0];
937
- if (!tmp[s1]) calc_symlen(d, s1, tmp);
938
- if (!tmp[s2]) calc_symlen(d, s2, tmp);
939
- d->symlen[s] = ubyte(d->symlen[s1] + d->symlen[s2] + 1);
940
- }
941
- tmp[s] = 1;
942
- }
943
-
944
- ushort ReadUshort(ubyte* d) {
945
- return ushort(d[0] | (d[1] << 8));
946
- }
947
-
948
- uint32 ReadUint32(ubyte* d) {
949
- return d[0] | (d[1] << 8) | (d[2] << 16) | (d[3] << 24);
950
- }
951
-
952
- static struct PairsData *setup_pairs(unsigned char *data, uint64 tb_size, uint64 *size, unsigned char **next, ubyte *flags, int wdl)
953
- {
954
- struct PairsData *d;
955
- int i;
956
-
957
- *flags = data[0];
958
- if (data[0] & 0x80) {
959
- d = (struct PairsData *)malloc(sizeof(struct PairsData));
960
- d->idxbits = 0;
961
- if (wdl)
962
- d->min_len = data[1];
963
- else
964
- d->min_len = 0;
965
- *next = data + 2;
966
- size[0] = size[1] = size[2] = 0;
967
- return d;
968
- }
969
-
970
- int blocksize = data[1];
971
- int idxbits = data[2];
972
- int real_num_blocks = ReadUint32(&data[4]);
973
- int num_blocks = real_num_blocks + *(ubyte *)(&data[3]);
974
- int max_len = data[8];
975
- int min_len = data[9];
976
- int h = max_len - min_len + 1;
977
- int num_syms = ReadUshort(&data[10 + 2 * h]);
978
- d = (struct PairsData *)malloc(sizeof(struct PairsData) + (h - 1) * sizeof(base_t) + num_syms);
979
- d->blocksize = blocksize;
980
- d->idxbits = idxbits;
981
- d->offset = (ushort*)(&data[10]);
982
- d->symlen = ((ubyte *)d) + sizeof(struct PairsData) + (h - 1) * sizeof(base_t);
983
- d->sympat = &data[12 + 2 * h];
984
- d->min_len = min_len;
985
- *next = &data[12 + 2 * h + 3 * num_syms + (num_syms & 1)];
986
-
987
- uint64 num_indices = (tb_size + (1ULL << idxbits) - 1) >> idxbits;
988
- size[0] = 6ULL * num_indices;
989
- size[1] = 2ULL * num_blocks;
990
- size[2] = (1ULL << blocksize) * real_num_blocks;
991
-
992
- // char tmp[num_syms];
993
- char tmp[4096];
994
- for (i = 0; i < num_syms; i++)
995
- tmp[i] = 0;
996
- for (i = 0; i < num_syms; i++)
997
- if (!tmp[i])
998
- calc_symlen(d, i, tmp);
999
-
1000
- d->base[h - 1] = 0;
1001
- for (i = h - 2; i >= 0; i--)
1002
- d->base[i] = (d->base[i + 1] + ReadUshort((ubyte*)(d->offset + i)) - ReadUshort((ubyte*)(d->offset + i + 1))) / 2;
1003
- for (i = 0; i < h; i++)
1004
- d->base[i] <<= 64 - (min_len + i);
1005
-
1006
- d->offset -= d->min_len;
1007
-
1008
- return d;
1009
- }
1010
-
1011
- static int init_table_wdl(struct TBEntry *entry, char *str)
1012
- {
1013
- ubyte *next;
1014
- int f, s;
1015
- uint64 tb_size[8];
1016
- uint64 size[8 * 3];
1017
- ubyte flags;
1018
-
1019
- // first mmap the table into memory
1020
-
1021
- entry->data = map_file(str, WDLSUFFIX, &entry->mapping);
1022
- if (!entry->data) {
1023
- printf("Could not find %s" WDLSUFFIX, str);
1024
- return 0;
1025
- }
1026
-
1027
- ubyte *data = (ubyte *)entry->data;
1028
- if (data[0] != WDL_MAGIC[0] ||
1029
- data[1] != WDL_MAGIC[1] ||
1030
- data[2] != WDL_MAGIC[2] ||
1031
- data[3] != WDL_MAGIC[3]) {
1032
- printf("Corrupted table.\n");
1033
- unmap_file(entry->data, entry->mapping);
1034
- entry->data = 0;
1035
- return 0;
1036
- }
1037
-
1038
- int split = data[4] & 0x01;
1039
- int files = data[4] & 0x02 ? 4 : 1;
1040
-
1041
- data += 5;
1042
-
1043
- if (!entry->has_pawns) {
1044
- struct TBEntry_piece *ptr = (struct TBEntry_piece *)entry;
1045
- setup_pieces_piece(ptr, data, &tb_size[0]);
1046
- data += ptr->num + 1;
1047
- data += ((uintptr_t)data) & 0x01;
1048
-
1049
- ptr->precomp[0] = setup_pairs(data, tb_size[0], &size[0], &next, &flags, 1);
1050
- data = next;
1051
- if (split) {
1052
- ptr->precomp[1] = setup_pairs(data, tb_size[1], &size[3], &next, &flags, 1);
1053
- data = next;
1054
- } else
1055
- ptr->precomp[1] = NULL;
1056
-
1057
- ptr->precomp[0]->indextable = (char *)data;
1058
- data += size[0];
1059
- if (split) {
1060
- ptr->precomp[1]->indextable = (char *)data;
1061
- data += size[3];
1062
- }
1063
-
1064
- ptr->precomp[0]->sizetable = (ushort *)data;
1065
- data += size[1];
1066
- if (split) {
1067
- ptr->precomp[1]->sizetable = (ushort *)data;
1068
- data += size[4];
1069
- }
1070
-
1071
- data = (ubyte *)((((uintptr_t)data) + 0x3f) & ~0x3f);
1072
- ptr->precomp[0]->data = data;
1073
- data += size[2];
1074
- if (split) {
1075
- data = (ubyte *)((((uintptr_t)data) + 0x3f) & ~0x3f);
1076
- ptr->precomp[1]->data = data;
1077
- }
1078
- } else {
1079
- struct TBEntry_pawn *ptr = (struct TBEntry_pawn *)entry;
1080
- s = 1 + (ptr->pawns[1] > 0);
1081
- for (f = 0; f < 4; f++) {
1082
- setup_pieces_pawn((struct TBEntry_pawn *)ptr, data, &tb_size[2 * f], f);
1083
- data += ptr->num + s;
1084
- }
1085
- data += ((uintptr_t)data) & 0x01;
1086
-
1087
- for (f = 0; f < files; f++) {
1088
- ptr->file[f].precomp[0] = setup_pairs(data, tb_size[2 * f], &size[6 * f], &next, &flags, 1);
1089
- data = next;
1090
- if (split) {
1091
- ptr->file[f].precomp[1] = setup_pairs(data, tb_size[2 * f + 1], &size[6 * f + 3], &next, &flags, 1);
1092
- data = next;
1093
- } else
1094
- ptr->file[f].precomp[1] = NULL;
1095
- }
1096
-
1097
- for (f = 0; f < files; f++) {
1098
- ptr->file[f].precomp[0]->indextable = (char *)data;
1099
- data += size[6 * f];
1100
- if (split) {
1101
- ptr->file[f].precomp[1]->indextable = (char *)data;
1102
- data += size[6 * f + 3];
1103
- }
1104
- }
1105
-
1106
- for (f = 0; f < files; f++) {
1107
- ptr->file[f].precomp[0]->sizetable = (ushort *)data;
1108
- data += size[6 * f + 1];
1109
- if (split) {
1110
- ptr->file[f].precomp[1]->sizetable = (ushort *)data;
1111
- data += size[6 * f + 4];
1112
- }
1113
- }
1114
-
1115
- for (f = 0; f < files; f++) {
1116
- data = (ubyte *)((((uintptr_t)data) + 0x3f) & ~0x3f);
1117
- ptr->file[f].precomp[0]->data = data;
1118
- data += size[6 * f + 2];
1119
- if (split) {
1120
- data = (ubyte *)((((uintptr_t)data) + 0x3f) & ~0x3f);
1121
- ptr->file[f].precomp[1]->data = data;
1122
- data += size[6 * f + 5];
1123
- }
1124
- }
1125
- }
1126
-
1127
- return 1;
1128
- }
1129
-
1130
- static int init_table_dtz(struct TBEntry *entry)
1131
- {
1132
- ubyte *data = (ubyte *)entry->data;
1133
- ubyte *next;
1134
- int f, s;
1135
- uint64 tb_size[4];
1136
- uint64 size[4 * 3];
1137
-
1138
- if (!data)
1139
- return 0;
1140
-
1141
- if (data[0] != DTZ_MAGIC[0] ||
1142
- data[1] != DTZ_MAGIC[1] ||
1143
- data[2] != DTZ_MAGIC[2] ||
1144
- data[3] != DTZ_MAGIC[3]) {
1145
- printf("Corrupted table.\n");
1146
- return 0;
1147
- }
1148
-
1149
- int files = data[4] & 0x02 ? 4 : 1;
1150
-
1151
- data += 5;
1152
-
1153
- if (!entry->has_pawns) {
1154
- struct DTZEntry_piece *ptr = (struct DTZEntry_piece *)entry;
1155
- setup_pieces_piece_dtz(ptr, data, &tb_size[0]);
1156
- data += ptr->num + 1;
1157
- data += ((uintptr_t)data) & 0x01;
1158
-
1159
- ptr->precomp = setup_pairs(data, tb_size[0], &size[0], &next, &(ptr->flags), 0);
1160
- data = next;
1161
-
1162
- ptr->map = data;
1163
- if (ptr->flags & 2) {
1164
- int i;
1165
- for (i = 0; i < 4; i++) {
1166
- ptr->map_idx[i] = static_cast<ushort>(data + 1 - ptr->map);
1167
- data += 1 + data[0];
1168
- }
1169
- data += ((uintptr_t)data) & 0x01;
1170
- }
1171
-
1172
- ptr->precomp->indextable = (char *)data;
1173
- data += size[0];
1174
-
1175
- ptr->precomp->sizetable = (ushort *)data;
1176
- data += size[1];
1177
-
1178
- data = (ubyte *)((((uintptr_t)data) + 0x3f) & ~0x3f);
1179
- ptr->precomp->data = data;
1180
- data += size[2];
1181
- } else {
1182
- struct DTZEntry_pawn *ptr = (struct DTZEntry_pawn *)entry;
1183
- s = 1 + (ptr->pawns[1] > 0);
1184
- for (f = 0; f < 4; f++) {
1185
- setup_pieces_pawn_dtz(ptr, data, &tb_size[f], f);
1186
- data += ptr->num + s;
1187
- }
1188
- data += ((uintptr_t)data) & 0x01;
1189
-
1190
- for (f = 0; f < files; f++) {
1191
- ptr->file[f].precomp = setup_pairs(data, tb_size[f], &size[3 * f], &next, &(ptr->flags[f]), 0);
1192
- data = next;
1193
- }
1194
-
1195
- ptr->map = data;
1196
- for (f = 0; f < files; f++) {
1197
- if (ptr->flags[f] & 2) {
1198
- int i;
1199
- for (i = 0; i < 4; i++) {
1200
- ptr->map_idx[f][i] = static_cast<ushort>(data + 1 - ptr->map);
1201
- data += 1 + data[0];
1202
- }
1203
- }
1204
- }
1205
- data += ((uintptr_t)data) & 0x01;
1206
-
1207
- for (f = 0; f < files; f++) {
1208
- ptr->file[f].precomp->indextable = (char *)data;
1209
- data += size[3 * f];
1210
- }
1211
-
1212
- for (f = 0; f < files; f++) {
1213
- ptr->file[f].precomp->sizetable = (ushort *)data;
1214
- data += size[3 * f + 1];
1215
- }
1216
-
1217
- for (f = 0; f < files; f++) {
1218
- data = (ubyte *)((((uintptr_t)data) + 0x3f) & ~0x3f);
1219
- ptr->file[f].precomp->data = data;
1220
- data += size[3 * f + 2];
1221
- }
1222
- }
1223
-
1224
- return 1;
1225
- }
1226
-
1227
- template<bool LittleEndian>
1228
- static ubyte decompress_pairs(struct PairsData *d, uint64 idx)
1229
- {
1230
- if (!d->idxbits)
1231
- return ubyte(d->min_len);
1232
-
1233
- uint32 mainidx = static_cast<uint32>(idx >> d->idxbits);
1234
- int litidx = (idx & ((1ULL << d->idxbits) - 1)) - (1ULL << (d->idxbits - 1));
1235
- uint32 block = *(uint32 *)(d->indextable + 6 * mainidx);
1236
- if (!LittleEndian)
1237
- block = BSWAP32(block);
1238
-
1239
- ushort idxOffset = *(ushort *)(d->indextable + 6 * mainidx + 4);
1240
- if (!LittleEndian)
1241
- idxOffset = ushort((idxOffset << 8) | (idxOffset >> 8));
1242
- litidx += idxOffset;
1243
-
1244
- if (litidx < 0) {
1245
- do {
1246
- litidx += d->sizetable[--block] + 1;
1247
- } while (litidx < 0);
1248
- } else {
1249
- while (litidx > d->sizetable[block])
1250
- litidx -= d->sizetable[block++] + 1;
1251
- }
1252
-
1253
- uint32 *ptr = (uint32 *)(d->data + (block << d->blocksize));
1254
-
1255
- int m = d->min_len;
1256
- ushort *offset = d->offset;
1257
- base_t *base = d->base - m;
1258
- ubyte *symlen = d->symlen;
1259
- int sym, bitcnt;
1260
-
1261
- uint64 code = *((uint64 *)ptr);
1262
- if (LittleEndian)
1263
- code = BSWAP64(code);
1264
-
1265
- ptr += 2;
1266
- bitcnt = 0; // number of "empty bits" in code
1267
- for (;;) {
1268
- int l = m;
1269
- while (code < base[l]) l++;
1270
- sym = offset[l];
1271
- if (!LittleEndian)
1272
- sym = ((sym & 0xff) << 8) | (sym >> 8);
1273
- sym += static_cast<int>((code - base[l]) >> (64 - l));
1274
- if (litidx < (int)symlen[sym] + 1) break;
1275
- litidx -= (int)symlen[sym] + 1;
1276
- code <<= l;
1277
- bitcnt += l;
1278
- if (bitcnt >= 32) {
1279
- bitcnt -= 32;
1280
- uint32 tmp = *ptr++;
1281
- if (LittleEndian)
1282
- tmp = BSWAP32(tmp);
1283
- code |= ((uint64)tmp) << bitcnt;
1284
- }
1285
- }
1286
-
1287
- ubyte *sympat = d->sympat;
1288
- while (symlen[sym] != 0) {
1289
- ubyte* w = sympat + (3 * sym);
1290
- int s1 = ((w[1] & 0xf) << 8) | w[0];
1291
- if (litidx < (int)symlen[s1] + 1)
1292
- sym = s1;
1293
- else {
1294
- litidx -= (int)symlen[s1] + 1;
1295
- sym = (w[2] << 4) | (w[1] >> 4);
1296
- }
1297
- }
1298
-
1299
- return sympat[3 * sym];
1300
- }
1301
-
1302
- void load_dtz_table(char *str, uint64 key1, uint64 key2)
1303
- {
1304
- int i;
1305
- struct TBEntry *ptr, *ptr3;
1306
- struct TBHashEntry *ptr2;
1307
-
1308
- DTZ_table[0].key1 = key1;
1309
- DTZ_table[0].key2 = key2;
1310
- DTZ_table[0].entry = NULL;
1311
-
1312
- // find corresponding WDL entry
1313
- ptr2 = TB_hash[key1 >> (64 - TBHASHBITS)];
1314
- for (i = 0; i < HSHMAX; i++)
1315
- if (ptr2[i].key == key1) break;
1316
- if (i == HSHMAX) return;
1317
- ptr = ptr2[i].ptr;
1318
-
1319
- ptr3 = (struct TBEntry *)malloc(ptr->has_pawns
1320
- ? sizeof(struct DTZEntry_pawn)
1321
- : sizeof(struct DTZEntry_piece));
1322
-
1323
- ptr3->data = map_file(str, DTZSUFFIX, &ptr3->mapping);
1324
- ptr3->key = ptr->key;
1325
- ptr3->num = ptr->num;
1326
- ptr3->symmetric = ptr->symmetric;
1327
- ptr3->has_pawns = ptr->has_pawns;
1328
- if (ptr3->has_pawns) {
1329
- struct DTZEntry_pawn *entry = (struct DTZEntry_pawn *)ptr3;
1330
- entry->pawns[0] = ((struct TBEntry_pawn *)ptr)->pawns[0];
1331
- entry->pawns[1] = ((struct TBEntry_pawn *)ptr)->pawns[1];
1332
- } else {
1333
- struct DTZEntry_piece *entry = (struct DTZEntry_piece *)ptr3;
1334
- entry->enc_type = ((struct TBEntry_piece *)ptr)->enc_type;
1335
- }
1336
- if (!init_table_dtz(ptr3))
1337
- free(ptr3);
1338
- else
1339
- DTZ_table[0].entry = ptr3;
1340
- }
1341
-
1342
- static void free_wdl_entry(struct TBEntry *entry)
1343
- {
1344
- unmap_file(entry->data, entry->mapping);
1345
- if (!entry->has_pawns) {
1346
- struct TBEntry_piece *ptr = (struct TBEntry_piece *)entry;
1347
- free(ptr->precomp[0]);
1348
- if (ptr->precomp[1])
1349
- free(ptr->precomp[1]);
1350
- } else {
1351
- struct TBEntry_pawn *ptr = (struct TBEntry_pawn *)entry;
1352
- int f;
1353
- for (f = 0; f < 4; f++) {
1354
- free(ptr->file[f].precomp[0]);
1355
- if (ptr->file[f].precomp[1])
1356
- free(ptr->file[f].precomp[1]);
1357
- }
1358
- }
1359
- }
1360
-
1361
- static void free_dtz_entry(struct TBEntry *entry)
1362
- {
1363
- unmap_file(entry->data, entry->mapping);
1364
- if (!entry->has_pawns) {
1365
- struct DTZEntry_piece *ptr = (struct DTZEntry_piece *)entry;
1366
- free(ptr->precomp);
1367
- } else {
1368
- struct DTZEntry_pawn *ptr = (struct DTZEntry_pawn *)entry;
1369
- int f;
1370
- for (f = 0; f < 4; f++)
1371
- free(ptr->file[f].precomp);
1372
- }
1373
- free(entry);
1374
- }
1375
-
1376
- static int wdl_to_map[5] = { 1, 3, 0, 2, 0 };
1377
- static ubyte pa_flags[5] = { 8, 0, 0, 0, 4 };
1378
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/syzygy/tbcore.h DELETED
@@ -1,169 +0,0 @@
1
- /*
2
- Copyright (c) 2011-2013 Ronald de Man
3
- */
4
-
5
- #ifndef TBCORE_H
6
- #define TBCORE_H
7
-
8
- #ifndef _WIN32
9
- #include <pthread.h>
10
- #define SEP_CHAR ':'
11
- #define FD int
12
- #define FD_ERR -1
13
- #else
14
- #include <windows.h>
15
- #define SEP_CHAR ';'
16
- #define FD HANDLE
17
- #define FD_ERR INVALID_HANDLE_VALUE
18
- #endif
19
-
20
- #ifndef _WIN32
21
- #define LOCK_T pthread_mutex_t
22
- #define LOCK_INIT(x) pthread_mutex_init(&(x), NULL)
23
- #define LOCK(x) pthread_mutex_lock(&(x))
24
- #define UNLOCK(x) pthread_mutex_unlock(&(x))
25
- #else
26
- #define LOCK_T HANDLE
27
- #define LOCK_INIT(x) do { x = CreateMutex(NULL, FALSE, NULL); } while (0)
28
- #define LOCK(x) WaitForSingleObject(x, INFINITE)
29
- #define UNLOCK(x) ReleaseMutex(x)
30
- #endif
31
-
32
- #ifndef _MSC_VER
33
- #define BSWAP32(v) __builtin_bswap32(v)
34
- #define BSWAP64(v) __builtin_bswap64(v)
35
- #else
36
- #define BSWAP32(v) _byteswap_ulong(v)
37
- #define BSWAP64(v) _byteswap_uint64(v)
38
- #endif
39
-
40
- #define WDLSUFFIX ".rtbw"
41
- #define DTZSUFFIX ".rtbz"
42
- #define WDLDIR "RTBWDIR"
43
- #define DTZDIR "RTBZDIR"
44
- #define TBPIECES 6
45
-
46
- typedef unsigned long long uint64;
47
- typedef unsigned int uint32;
48
- typedef unsigned char ubyte;
49
- typedef unsigned short ushort;
50
-
51
- const ubyte WDL_MAGIC[4] = { 0x71, 0xe8, 0x23, 0x5d };
52
- const ubyte DTZ_MAGIC[4] = { 0xd7, 0x66, 0x0c, 0xa5 };
53
-
54
- #define TBHASHBITS 10
55
-
56
- struct TBHashEntry;
57
-
58
- typedef uint64 base_t;
59
-
60
- struct PairsData {
61
- char *indextable;
62
- ushort *sizetable;
63
- ubyte *data;
64
- ushort *offset;
65
- ubyte *symlen;
66
- ubyte *sympat;
67
- int blocksize;
68
- int idxbits;
69
- int min_len;
70
- base_t base[1]; // C++ complains about base[]...
71
- };
72
-
73
- struct TBEntry {
74
- char *data;
75
- uint64 key;
76
- uint64 mapping;
77
- ubyte ready;
78
- ubyte num;
79
- ubyte symmetric;
80
- ubyte has_pawns;
81
- }
82
- #ifndef _WIN32
83
- __attribute__((__may_alias__))
84
- #endif
85
- ;
86
-
87
- struct TBEntry_piece {
88
- char *data;
89
- uint64 key;
90
- uint64 mapping;
91
- ubyte ready;
92
- ubyte num;
93
- ubyte symmetric;
94
- ubyte has_pawns;
95
- ubyte enc_type;
96
- struct PairsData *precomp[2];
97
- int factor[2][TBPIECES];
98
- ubyte pieces[2][TBPIECES];
99
- ubyte norm[2][TBPIECES];
100
- };
101
-
102
- struct TBEntry_pawn {
103
- char *data;
104
- uint64 key;
105
- uint64 mapping;
106
- ubyte ready;
107
- ubyte num;
108
- ubyte symmetric;
109
- ubyte has_pawns;
110
- ubyte pawns[2];
111
- struct {
112
- struct PairsData *precomp[2];
113
- int factor[2][TBPIECES];
114
- ubyte pieces[2][TBPIECES];
115
- ubyte norm[2][TBPIECES];
116
- } file[4];
117
- };
118
-
119
- struct DTZEntry_piece {
120
- char *data;
121
- uint64 key;
122
- uint64 mapping;
123
- ubyte ready;
124
- ubyte num;
125
- ubyte symmetric;
126
- ubyte has_pawns;
127
- ubyte enc_type;
128
- struct PairsData *precomp;
129
- int factor[TBPIECES];
130
- ubyte pieces[TBPIECES];
131
- ubyte norm[TBPIECES];
132
- ubyte flags; // accurate, mapped, side
133
- ushort map_idx[4];
134
- ubyte *map;
135
- };
136
-
137
- struct DTZEntry_pawn {
138
- char *data;
139
- uint64 key;
140
- uint64 mapping;
141
- ubyte ready;
142
- ubyte num;
143
- ubyte symmetric;
144
- ubyte has_pawns;
145
- ubyte pawns[2];
146
- struct {
147
- struct PairsData *precomp;
148
- int factor[TBPIECES];
149
- ubyte pieces[TBPIECES];
150
- ubyte norm[TBPIECES];
151
- } file[4];
152
- ubyte flags[4];
153
- ushort map_idx[4][4];
154
- ubyte *map;
155
- };
156
-
157
- struct TBHashEntry {
158
- uint64 key;
159
- struct TBEntry *ptr;
160
- };
161
-
162
- struct DTZTableEntry {
163
- uint64 key1;
164
- uint64 key2;
165
- struct TBEntry *entry;
166
- };
167
-
168
- #endif
169
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/syzygy/tbprobe.cpp DELETED
@@ -1,824 +0,0 @@
1
- /*
2
- Copyright (c) 2013 Ronald de Man
3
- This file may be redistributed and/or modified without restrictions.
4
-
5
- tbprobe.cpp contains the Stockfish-specific routines of the
6
- tablebase probing code. It should be relatively easy to adapt
7
- this code to other chess engines.
8
- */
9
-
10
- #define NOMINMAX
11
-
12
- #include <algorithm>
13
-
14
- #include "../position.h"
15
- #include "../movegen.h"
16
- #include "../bitboard.h"
17
- #include "../search.h"
18
-
19
- #include "tbprobe.h"
20
- #include "tbcore.h"
21
-
22
- #include "tbcore.cpp"
23
-
24
- namespace Zobrist {
25
- extern Key psq[PIECE_NB][SQUARE_NB];
26
- }
27
-
28
- int Tablebases::MaxCardinality = 0;
29
-
30
- // Given a position with 6 or fewer pieces, produce a text string
31
- // of the form KQPvKRP, where "KQP" represents the white pieces if
32
- // mirror == 0 and the black pieces if mirror == 1.
33
- static void prt_str(Position& pos, char *str, int mirror)
34
- {
35
- Color color;
36
- PieceType pt;
37
- int i;
38
-
39
- color = !mirror ? WHITE : BLACK;
40
- for (pt = KING; pt >= PAWN; --pt)
41
- for (i = popcount(pos.pieces(color, pt)); i > 0; i--)
42
- *str++ = pchr[6 - pt];
43
- *str++ = 'v';
44
- color = ~color;
45
- for (pt = KING; pt >= PAWN; --pt)
46
- for (i = popcount(pos.pieces(color, pt)); i > 0; i--)
47
- *str++ = pchr[6 - pt];
48
- *str++ = 0;
49
- }
50
-
51
- // Given a position, produce a 64-bit material signature key.
52
- // If the engine supports such a key, it should equal the engine's key.
53
- static uint64 calc_key(Position& pos, int mirror)
54
- {
55
- Color color;
56
- PieceType pt;
57
- int i;
58
- uint64 key = 0;
59
-
60
- color = !mirror ? WHITE : BLACK;
61
- for (pt = PAWN; pt <= KING; ++pt)
62
- for (i = popcount(pos.pieces(color, pt)); i > 0; i--)
63
- key ^= Zobrist::psq[make_piece(WHITE, pt)][i - 1];
64
- color = ~color;
65
- for (pt = PAWN; pt <= KING; ++pt)
66
- for (i = popcount(pos.pieces(color, pt)); i > 0; i--)
67
- key ^= Zobrist::psq[make_piece(BLACK, pt)][i - 1];
68
-
69
- return key;
70
- }
71
-
72
- // Produce a 64-bit material key corresponding to the material combination
73
- // defined by pcs[16], where pcs[1], ..., pcs[6] is the number of white
74
- // pawns, ..., kings and pcs[9], ..., pcs[14] is the number of black
75
- // pawns, ..., kings.
76
- static uint64 calc_key_from_pcs(int *pcs, int mirror)
77
- {
78
- int color;
79
- PieceType pt;
80
- int i;
81
- uint64 key = 0;
82
-
83
- color = !mirror ? 0 : 8;
84
- for (pt = PAWN; pt <= KING; ++pt)
85
- for (i = 0; i < pcs[color + pt]; i++)
86
- key ^= Zobrist::psq[make_piece(WHITE, pt)][i];
87
- color ^= 8;
88
- for (pt = PAWN; pt <= KING; ++pt)
89
- for (i = 0; i < pcs[color + pt]; i++)
90
- key ^= Zobrist::psq[make_piece(BLACK, pt)][i];
91
-
92
- return key;
93
- }
94
-
95
- bool is_little_endian() {
96
- union {
97
- int i;
98
- char c[sizeof(int)];
99
- } x;
100
- x.i = 1;
101
- return x.c[0] == 1;
102
- }
103
-
104
- static ubyte decompress_pairs(struct PairsData *d, uint64 idx)
105
- {
106
- static const bool isLittleEndian = is_little_endian();
107
- return isLittleEndian ? decompress_pairs<true >(d, idx)
108
- : decompress_pairs<false>(d, idx);
109
- }
110
-
111
- // probe_wdl_table and probe_dtz_table require similar adaptations.
112
- static int probe_wdl_table(Position& pos, int *success)
113
- {
114
- struct TBEntry *ptr;
115
- struct TBHashEntry *ptr2;
116
- uint64 idx;
117
- uint64 key;
118
- int i;
119
- ubyte res;
120
- int p[TBPIECES];
121
-
122
- // Obtain the position's material signature key.
123
- key = pos.material_key();
124
-
125
- // Test for KvK.
126
- if (key == (Zobrist::psq[W_KING][0] ^ Zobrist::psq[B_KING][0]))
127
- return 0;
128
-
129
- ptr2 = TB_hash[key >> (64 - TBHASHBITS)];
130
- for (i = 0; i < HSHMAX; i++)
131
- if (ptr2[i].key == key) break;
132
- if (i == HSHMAX) {
133
- *success = 0;
134
- return 0;
135
- }
136
-
137
- ptr = ptr2[i].ptr;
138
- if (!ptr->ready) {
139
- LOCK(TB_mutex);
140
- if (!ptr->ready) {
141
- char str[16];
142
- prt_str(pos, str, ptr->key != key);
143
- if (!init_table_wdl(ptr, str)) {
144
- ptr2[i].key = 0ULL;
145
- *success = 0;
146
- UNLOCK(TB_mutex);
147
- return 0;
148
- }
149
- // Memory barrier to ensure ptr->ready = 1 is not reordered.
150
- #ifdef _MSC_VER
151
- _ReadWriteBarrier();
152
- #else
153
- __asm__ __volatile__ ("" ::: "memory");
154
- #endif
155
- ptr->ready = 1;
156
- }
157
- UNLOCK(TB_mutex);
158
- }
159
-
160
- int bside, mirror, cmirror;
161
- if (!ptr->symmetric) {
162
- if (key != ptr->key) {
163
- cmirror = 8;
164
- mirror = 0x38;
165
- bside = (pos.side_to_move() == WHITE);
166
- } else {
167
- cmirror = mirror = 0;
168
- bside = !(pos.side_to_move() == WHITE);
169
- }
170
- } else {
171
- cmirror = pos.side_to_move() == WHITE ? 0 : 8;
172
- mirror = pos.side_to_move() == WHITE ? 0 : 0x38;
173
- bside = 0;
174
- }
175
-
176
- // p[i] is to contain the square 0-63 (A1-H8) for a piece of type
177
- // pc[i] ^ cmirror, where 1 = white pawn, ..., 14 = black king.
178
- // Pieces of the same type are guaranteed to be consecutive.
179
- if (!ptr->has_pawns) {
180
- struct TBEntry_piece *entry = (struct TBEntry_piece *)ptr;
181
- ubyte *pc = entry->pieces[bside];
182
- for (i = 0; i < entry->num;) {
183
- Bitboard bb = pos.pieces((Color)((pc[i] ^ cmirror) >> 3),
184
- (PieceType)(pc[i] & 0x07));
185
- do {
186
- p[i++] = pop_lsb(&bb);
187
- } while (bb);
188
- }
189
- idx = encode_piece(entry, entry->norm[bside], p, entry->factor[bside]);
190
- res = decompress_pairs(entry->precomp[bside], idx);
191
- } else {
192
- struct TBEntry_pawn *entry = (struct TBEntry_pawn *)ptr;
193
- int k = entry->file[0].pieces[0][0] ^ cmirror;
194
- Bitboard bb = pos.pieces((Color)(k >> 3), (PieceType)(k & 0x07));
195
- i = 0;
196
- do {
197
- p[i++] = pop_lsb(&bb) ^ mirror;
198
- } while (bb);
199
- int f = pawn_file(entry, p);
200
- ubyte *pc = entry->file[f].pieces[bside];
201
- for (; i < entry->num;) {
202
- bb = pos.pieces((Color)((pc[i] ^ cmirror) >> 3),
203
- (PieceType)(pc[i] & 0x07));
204
- do {
205
- p[i++] = pop_lsb(&bb) ^ mirror;
206
- } while (bb);
207
- }
208
- idx = encode_pawn(entry, entry->file[f].norm[bside], p, entry->file[f].factor[bside]);
209
- res = decompress_pairs(entry->file[f].precomp[bside], idx);
210
- }
211
-
212
- return ((int)res) - 2;
213
- }
214
-
215
- static int probe_dtz_table(Position& pos, int wdl, int *success)
216
- {
217
- struct TBEntry *ptr;
218
- uint64 idx;
219
- int i, res;
220
- int p[TBPIECES];
221
-
222
- // Obtain the position's material signature key.
223
- uint64 key = pos.material_key();
224
-
225
- if (DTZ_table[0].key1 != key && DTZ_table[0].key2 != key) {
226
- for (i = 1; i < DTZ_ENTRIES; i++)
227
- if (DTZ_table[i].key1 == key) break;
228
- if (i < DTZ_ENTRIES) {
229
- struct DTZTableEntry table_entry = DTZ_table[i];
230
- for (; i > 0; i--)
231
- DTZ_table[i] = DTZ_table[i - 1];
232
- DTZ_table[0] = table_entry;
233
- } else {
234
- struct TBHashEntry *ptr2 = TB_hash[key >> (64 - TBHASHBITS)];
235
- for (i = 0; i < HSHMAX; i++)
236
- if (ptr2[i].key == key) break;
237
- if (i == HSHMAX) {
238
- *success = 0;
239
- return 0;
240
- }
241
- ptr = ptr2[i].ptr;
242
- char str[16];
243
- int mirror = (ptr->key != key);
244
- prt_str(pos, str, mirror);
245
- if (DTZ_table[DTZ_ENTRIES - 1].entry)
246
- free_dtz_entry(DTZ_table[DTZ_ENTRIES-1].entry);
247
- for (i = DTZ_ENTRIES - 1; i > 0; i--)
248
- DTZ_table[i] = DTZ_table[i - 1];
249
- load_dtz_table(str, calc_key(pos, mirror), calc_key(pos, !mirror));
250
- }
251
- }
252
-
253
- ptr = DTZ_table[0].entry;
254
- if (!ptr) {
255
- *success = 0;
256
- return 0;
257
- }
258
-
259
- int bside, mirror, cmirror;
260
- if (!ptr->symmetric) {
261
- if (key != ptr->key) {
262
- cmirror = 8;
263
- mirror = 0x38;
264
- bside = (pos.side_to_move() == WHITE);
265
- } else {
266
- cmirror = mirror = 0;
267
- bside = !(pos.side_to_move() == WHITE);
268
- }
269
- } else {
270
- cmirror = pos.side_to_move() == WHITE ? 0 : 8;
271
- mirror = pos.side_to_move() == WHITE ? 0 : 0x38;
272
- bside = 0;
273
- }
274
-
275
- if (!ptr->has_pawns) {
276
- struct DTZEntry_piece *entry = (struct DTZEntry_piece *)ptr;
277
- if ((entry->flags & 1) != bside && !entry->symmetric) {
278
- *success = -1;
279
- return 0;
280
- }
281
- ubyte *pc = entry->pieces;
282
- for (i = 0; i < entry->num;) {
283
- Bitboard bb = pos.pieces((Color)((pc[i] ^ cmirror) >> 3),
284
- (PieceType)(pc[i] & 0x07));
285
- do {
286
- p[i++] = pop_lsb(&bb);
287
- } while (bb);
288
- }
289
- idx = encode_piece((struct TBEntry_piece *)entry, entry->norm, p, entry->factor);
290
- res = decompress_pairs(entry->precomp, idx);
291
-
292
- if (entry->flags & 2)
293
- res = entry->map[entry->map_idx[wdl_to_map[wdl + 2]] + res];
294
-
295
- if (!(entry->flags & pa_flags[wdl + 2]) || (wdl & 1))
296
- res *= 2;
297
- } else {
298
- struct DTZEntry_pawn *entry = (struct DTZEntry_pawn *)ptr;
299
- int k = entry->file[0].pieces[0] ^ cmirror;
300
- Bitboard bb = pos.pieces((Color)(k >> 3), (PieceType)(k & 0x07));
301
- i = 0;
302
- do {
303
- p[i++] = pop_lsb(&bb) ^ mirror;
304
- } while (bb);
305
- int f = pawn_file((struct TBEntry_pawn *)entry, p);
306
- if ((entry->flags[f] & 1) != bside) {
307
- *success = -1;
308
- return 0;
309
- }
310
- ubyte *pc = entry->file[f].pieces;
311
- for (; i < entry->num;) {
312
- bb = pos.pieces((Color)((pc[i] ^ cmirror) >> 3),
313
- (PieceType)(pc[i] & 0x07));
314
- do {
315
- p[i++] = pop_lsb(&bb) ^ mirror;
316
- } while (bb);
317
- }
318
- idx = encode_pawn((struct TBEntry_pawn *)entry, entry->file[f].norm, p, entry->file[f].factor);
319
- res = decompress_pairs(entry->file[f].precomp, idx);
320
-
321
- if (entry->flags[f] & 2)
322
- res = entry->map[entry->map_idx[f][wdl_to_map[wdl + 2]] + res];
323
-
324
- if (!(entry->flags[f] & pa_flags[wdl + 2]) || (wdl & 1))
325
- res *= 2;
326
- }
327
-
328
- return res;
329
- }
330
-
331
- // Add underpromotion captures to list of captures.
332
- static ExtMove *add_underprom_caps(Position& pos, ExtMove *stack, ExtMove *end)
333
- {
334
- ExtMove *moves, *extra = end;
335
-
336
- for (moves = stack; moves < end; moves++) {
337
- Move move = moves->move;
338
- if (type_of(move) == PROMOTION && !pos.empty(to_sq(move))) {
339
- (*extra++).move = (Move)(move - (1 << 12));
340
- (*extra++).move = (Move)(move - (2 << 12));
341
- (*extra++).move = (Move)(move - (3 << 12));
342
- }
343
- }
344
-
345
- return extra;
346
- }
347
-
348
- static int probe_ab(Position& pos, int alpha, int beta, int *success)
349
- {
350
- int v;
351
- ExtMove stack[64];
352
- ExtMove *moves, *end;
353
- StateInfo st;
354
-
355
- // Generate (at least) all legal non-ep captures including (under)promotions.
356
- // It is OK to generate more, as long as they are filtered out below.
357
- if (!pos.checkers()) {
358
- end = generate<CAPTURES>(pos, stack);
359
- // Since underpromotion captures are not included, we need to add them.
360
- end = add_underprom_caps(pos, stack, end);
361
- } else
362
- end = generate<EVASIONS>(pos, stack);
363
-
364
- for (moves = stack; moves < end; moves++) {
365
- Move capture = moves->move;
366
- if (!pos.capture(capture) || type_of(capture) == ENPASSANT
367
- || !pos.legal(capture))
368
- continue;
369
- pos.do_move(capture, st, pos.gives_check(capture));
370
- v = -probe_ab(pos, -beta, -alpha, success);
371
- pos.undo_move(capture);
372
- if (*success == 0) return 0;
373
- if (v > alpha) {
374
- if (v >= beta) {
375
- *success = 2;
376
- return v;
377
- }
378
- alpha = v;
379
- }
380
- }
381
-
382
- v = probe_wdl_table(pos, success);
383
- if (*success == 0) return 0;
384
- if (alpha >= v) {
385
- *success = 1 + (alpha > 0);
386
- return alpha;
387
- } else {
388
- *success = 1;
389
- return v;
390
- }
391
- }
392
-
393
- // Probe the WDL table for a particular position.
394
- // If *success != 0, the probe was successful.
395
- // The return value is from the point of view of the side to move:
396
- // -2 : loss
397
- // -1 : loss, but draw under 50-move rule
398
- // 0 : draw
399
- // 1 : win, but draw under 50-move rule
400
- // 2 : win
401
- int Tablebases::probe_wdl(Position& pos, int *success)
402
- {
403
- int v;
404
-
405
- *success = 1;
406
- v = probe_ab(pos, -2, 2, success);
407
-
408
- // If en passant is not possible, we are done.
409
- if (pos.ep_square() == SQ_NONE)
410
- return v;
411
- if (!(*success)) return 0;
412
-
413
- // Now handle en passant.
414
- int v1 = -3;
415
- // Generate (at least) all legal en passant captures.
416
- ExtMove stack[192];
417
- ExtMove *moves, *end;
418
- StateInfo st;
419
-
420
- if (!pos.checkers())
421
- end = generate<CAPTURES>(pos, stack);
422
- else
423
- end = generate<EVASIONS>(pos, stack);
424
-
425
- for (moves = stack; moves < end; moves++) {
426
- Move capture = moves->move;
427
- if (type_of(capture) != ENPASSANT
428
- || !pos.legal(capture))
429
- continue;
430
- pos.do_move(capture, st, pos.gives_check(capture));
431
- int v0 = -probe_ab(pos, -2, 2, success);
432
- pos.undo_move(capture);
433
- if (*success == 0) return 0;
434
- if (v0 > v1) v1 = v0;
435
- }
436
- if (v1 > -3) {
437
- if (v1 >= v) v = v1;
438
- else if (v == 0) {
439
- // Check whether there is at least one legal non-ep move.
440
- for (moves = stack; moves < end; moves++) {
441
- Move capture = moves->move;
442
- if (type_of(capture) == ENPASSANT) continue;
443
- if (pos.legal(capture)) break;
444
- }
445
- if (moves == end && !pos.checkers()) {
446
- end = generate<QUIETS>(pos, end);
447
- for (; moves < end; moves++) {
448
- Move move = moves->move;
449
- if (pos.legal(move))
450
- break;
451
- }
452
- }
453
- // If not, then we are forced to play the losing ep capture.
454
- if (moves == end)
455
- v = v1;
456
- }
457
- }
458
-
459
- return v;
460
- }
461
-
462
- // This routine treats a position with en passant captures as one without.
463
- static int probe_dtz_no_ep(Position& pos, int *success)
464
- {
465
- int wdl, dtz;
466
-
467
- wdl = probe_ab(pos, -2, 2, success);
468
- if (*success == 0) return 0;
469
-
470
- if (wdl == 0) return 0;
471
-
472
- if (*success == 2)
473
- return wdl == 2 ? 1 : 101;
474
-
475
- ExtMove stack[192];
476
- ExtMove *moves, *end = NULL;
477
- StateInfo st;
478
-
479
- if (wdl > 0) {
480
- // Generate at least all legal non-capturing pawn moves
481
- // including non-capturing promotions.
482
- if (!pos.checkers())
483
- end = generate<NON_EVASIONS>(pos, stack);
484
- else
485
- end = generate<EVASIONS>(pos, stack);
486
-
487
- for (moves = stack; moves < end; moves++) {
488
- Move move = moves->move;
489
- if (type_of(pos.moved_piece(move)) != PAWN || pos.capture(move)
490
- || !pos.legal(move))
491
- continue;
492
- pos.do_move(move, st, pos.gives_check(move));
493
- int v = -Tablebases::probe_wdl(pos, success);
494
- pos.undo_move(move);
495
- if (*success == 0) return 0;
496
- if (v == wdl)
497
- return v == 2 ? 1 : 101;
498
- }
499
- }
500
-
501
- dtz = 1 + probe_dtz_table(pos, wdl, success);
502
- if (*success >= 0) {
503
- if (wdl & 1) dtz += 100;
504
- return wdl >= 0 ? dtz : -dtz;
505
- }
506
-
507
- if (wdl > 0) {
508
- int best = 0xffff;
509
- for (moves = stack; moves < end; moves++) {
510
- Move move = moves->move;
511
- if (pos.capture(move) || type_of(pos.moved_piece(move)) == PAWN
512
- || !pos.legal(move))
513
- continue;
514
- pos.do_move(move, st, pos.gives_check(move));
515
- int v = -Tablebases::probe_dtz(pos, success);
516
- pos.undo_move(move);
517
- if (*success == 0) return 0;
518
- if (v > 0 && v + 1 < best)
519
- best = v + 1;
520
- }
521
- return best;
522
- } else {
523
- int best = -1;
524
- if (!pos.checkers())
525
- end = generate<NON_EVASIONS>(pos, stack);
526
- else
527
- end = generate<EVASIONS>(pos, stack);
528
- for (moves = stack; moves < end; moves++) {
529
- int v;
530
- Move move = moves->move;
531
- if (!pos.legal(move))
532
- continue;
533
- pos.do_move(move, st, pos.gives_check(move));
534
- if (st.rule50 == 0) {
535
- if (wdl == -2) v = -1;
536
- else {
537
- v = probe_ab(pos, 1, 2, success);
538
- v = (v == 2) ? 0 : -101;
539
- }
540
- } else {
541
- v = -Tablebases::probe_dtz(pos, success) - 1;
542
- }
543
- pos.undo_move(move);
544
- if (*success == 0) return 0;
545
- if (v < best)
546
- best = v;
547
- }
548
- return best;
549
- }
550
- }
551
-
552
- static int wdl_to_dtz[] = {
553
- -1, -101, 0, 101, 1
554
- };
555
-
556
- // Probe the DTZ table for a particular position.
557
- // If *success != 0, the probe was successful.
558
- // The return value is from the point of view of the side to move:
559
- // n < -100 : loss, but draw under 50-move rule
560
- // -100 <= n < -1 : loss in n ply (assuming 50-move counter == 0)
561
- // 0 : draw
562
- // 1 < n <= 100 : win in n ply (assuming 50-move counter == 0)
563
- // 100 < n : win, but draw under 50-move rule
564
- //
565
- // The return value n can be off by 1: a return value -n can mean a loss
566
- // in n+1 ply and a return value +n can mean a win in n+1 ply. This
567
- // cannot happen for tables with positions exactly on the "edge" of
568
- // the 50-move rule.
569
- //
570
- // This implies that if dtz > 0 is returned, the position is certainly
571
- // a win if dtz + 50-move-counter <= 99. Care must be taken that the engine
572
- // picks moves that preserve dtz + 50-move-counter <= 99.
573
- //
574
- // If n = 100 immediately after a capture or pawn move, then the position
575
- // is also certainly a win, and during the whole phase until the next
576
- // capture or pawn move, the inequality to be preserved is
577
- // dtz + 50-movecounter <= 100.
578
- //
579
- // In short, if a move is available resulting in dtz + 50-move-counter <= 99,
580
- // then do not accept moves leading to dtz + 50-move-counter == 100.
581
- //
582
- int Tablebases::probe_dtz(Position& pos, int *success)
583
- {
584
- *success = 1;
585
- int v = probe_dtz_no_ep(pos, success);
586
-
587
- if (pos.ep_square() == SQ_NONE)
588
- return v;
589
- if (*success == 0) return 0;
590
-
591
- // Now handle en passant.
592
- int v1 = -3;
593
-
594
- ExtMove stack[192];
595
- ExtMove *moves, *end;
596
- StateInfo st;
597
-
598
- if (!pos.checkers())
599
- end = generate<CAPTURES>(pos, stack);
600
- else
601
- end = generate<EVASIONS>(pos, stack);
602
-
603
- for (moves = stack; moves < end; moves++) {
604
- Move capture = moves->move;
605
- if (type_of(capture) != ENPASSANT
606
- || !pos.legal(capture))
607
- continue;
608
- pos.do_move(capture, st, pos.gives_check(capture));
609
- int v0 = -probe_ab(pos, -2, 2, success);
610
- pos.undo_move(capture);
611
- if (*success == 0) return 0;
612
- if (v0 > v1) v1 = v0;
613
- }
614
- if (v1 > -3) {
615
- v1 = wdl_to_dtz[v1 + 2];
616
- if (v < -100) {
617
- if (v1 >= 0)
618
- v = v1;
619
- } else if (v < 0) {
620
- if (v1 >= 0 || v1 < -100)
621
- v = v1;
622
- } else if (v > 100) {
623
- if (v1 > 0)
624
- v = v1;
625
- } else if (v > 0) {
626
- if (v1 == 1)
627
- v = v1;
628
- } else if (v1 >= 0) {
629
- v = v1;
630
- } else {
631
- for (moves = stack; moves < end; moves++) {
632
- Move move = moves->move;
633
- if (type_of(move) == ENPASSANT) continue;
634
- if (pos.legal(move)) break;
635
- }
636
- if (moves == end && !pos.checkers()) {
637
- end = generate<QUIETS>(pos, end);
638
- for (; moves < end; moves++) {
639
- Move move = moves->move;
640
- if (pos.legal(move))
641
- break;
642
- }
643
- }
644
- if (moves == end)
645
- v = v1;
646
- }
647
- }
648
-
649
- return v;
650
- }
651
-
652
- // Check whether there has been at least one repetition of positions
653
- // since the last capture or pawn move.
654
- static int has_repeated(StateInfo *st)
655
- {
656
- while (1) {
657
- int i = 4, e = std::min(st->rule50, st->pliesFromNull);
658
- if (e < i)
659
- return 0;
660
- StateInfo *stp = st->previous->previous;
661
- do {
662
- stp = stp->previous->previous;
663
- if (stp->key == st->key)
664
- return 1;
665
- i += 2;
666
- } while (i <= e);
667
- st = st->previous;
668
- }
669
- }
670
-
671
- static Value wdl_to_Value[5] = {
672
- -VALUE_MATE + MAX_PLY + 1,
673
- VALUE_DRAW - 2,
674
- VALUE_DRAW,
675
- VALUE_DRAW + 2,
676
- VALUE_MATE - MAX_PLY - 1
677
- };
678
-
679
- // Use the DTZ tables to filter out moves that don't preserve the win or draw.
680
- // If the position is lost, but DTZ is fairly high, only keep moves that
681
- // maximise DTZ.
682
- //
683
- // A return value false indicates that not all probes were successful and that
684
- // no moves were filtered out.
685
- bool Tablebases::root_probe(Position& pos, Search::RootMoves& rootMoves, Value& score)
686
- {
687
- int success;
688
-
689
- int dtz = probe_dtz(pos, &success);
690
- if (!success) return false;
691
-
692
- StateInfo st;
693
-
694
- // Probe each move.
695
- for (size_t i = 0; i < rootMoves.size(); i++) {
696
- Move move = rootMoves[i].pv[0];
697
- pos.do_move(move, st, pos.gives_check(move));
698
- int v = 0;
699
- if (pos.checkers() && dtz > 0) {
700
- ExtMove s[192];
701
- if (generate<LEGAL>(pos, s) == s)
702
- v = 1;
703
- }
704
- if (!v) {
705
- if (st.rule50 != 0) {
706
- v = -Tablebases::probe_dtz(pos, &success);
707
- if (v > 0) v++;
708
- else if (v < 0) v--;
709
- } else {
710
- v = -Tablebases::probe_wdl(pos, &success);
711
- v = wdl_to_dtz[v + 2];
712
- }
713
- }
714
- pos.undo_move(move);
715
- if (!success) return false;
716
- rootMoves[i].score = (Value)v;
717
- }
718
-
719
- // Obtain 50-move counter for the root position.
720
- // In Stockfish there seems to be no clean way, so we do it like this:
721
- int cnt50 = st.previous->rule50;
722
-
723
- // Use 50-move counter to determine whether the root position is
724
- // won, lost or drawn.
725
- int wdl = 0;
726
- if (dtz > 0)
727
- wdl = (dtz + cnt50 <= 100) ? 2 : 1;
728
- else if (dtz < 0)
729
- wdl = (-dtz + cnt50 <= 100) ? -2 : -1;
730
-
731
- // Determine the score to report to the user.
732
- score = wdl_to_Value[wdl + 2];
733
- // If the position is winning or losing, but too few moves left, adjust the
734
- // score to show how close it is to winning or losing.
735
- // NOTE: int(PawnValueEg) is used as scaling factor in score_to_uci().
736
- if (wdl == 1 && dtz <= 100)
737
- score = (Value)(((200 - dtz - cnt50) * int(PawnValueEg)) / 200);
738
- else if (wdl == -1 && dtz >= -100)
739
- score = -(Value)(((200 + dtz - cnt50) * int(PawnValueEg)) / 200);
740
-
741
- // Now be a bit smart about filtering out moves.
742
- size_t j = 0;
743
- if (dtz > 0) { // winning (or 50-move rule draw)
744
- int best = 0xffff;
745
- for (size_t i = 0; i < rootMoves.size(); i++) {
746
- int v = rootMoves[i].score;
747
- if (v > 0 && v < best)
748
- best = v;
749
- }
750
- int max = best;
751
- // If the current phase has not seen repetitions, then try all moves
752
- // that stay safely within the 50-move budget, if there are any.
753
- if (!has_repeated(st.previous) && best + cnt50 <= 99)
754
- max = 99 - cnt50;
755
- for (size_t i = 0; i < rootMoves.size(); i++) {
756
- int v = rootMoves[i].score;
757
- if (v > 0 && v <= max)
758
- rootMoves[j++] = rootMoves[i];
759
- }
760
- } else if (dtz < 0) { // losing (or 50-move rule draw)
761
- int best = 0;
762
- for (size_t i = 0; i < rootMoves.size(); i++) {
763
- int v = rootMoves[i].score;
764
- if (v < best)
765
- best = v;
766
- }
767
- // Try all moves, unless we approach or have a 50-move rule draw.
768
- if (-best * 2 + cnt50 < 100)
769
- return true;
770
- for (size_t i = 0; i < rootMoves.size(); i++) {
771
- if (rootMoves[i].score == best)
772
- rootMoves[j++] = rootMoves[i];
773
- }
774
- } else { // drawing
775
- // Try all moves that preserve the draw.
776
- for (size_t i = 0; i < rootMoves.size(); i++) {
777
- if (rootMoves[i].score == 0)
778
- rootMoves[j++] = rootMoves[i];
779
- }
780
- }
781
- rootMoves.resize(j, Search::RootMove(MOVE_NONE));
782
-
783
- return true;
784
- }
785
-
786
- // Use the WDL tables to filter out moves that don't preserve the win or draw.
787
- // This is a fallback for the case that some or all DTZ tables are missing.
788
- //
789
- // A return value false indicates that not all probes were successful and that
790
- // no moves were filtered out.
791
- bool Tablebases::root_probe_wdl(Position& pos, Search::RootMoves& rootMoves, Value& score)
792
- {
793
- int success;
794
-
795
- int wdl = Tablebases::probe_wdl(pos, &success);
796
- if (!success) return false;
797
- score = wdl_to_Value[wdl + 2];
798
-
799
- StateInfo st;
800
-
801
- int best = -2;
802
-
803
- // Probe each move.
804
- for (size_t i = 0; i < rootMoves.size(); i++) {
805
- Move move = rootMoves[i].pv[0];
806
- pos.do_move(move, st, pos.gives_check(move));
807
- int v = -Tablebases::probe_wdl(pos, &success);
808
- pos.undo_move(move);
809
- if (!success) return false;
810
- rootMoves[i].score = (Value)v;
811
- if (v > best)
812
- best = v;
813
- }
814
-
815
- size_t j = 0;
816
- for (size_t i = 0; i < rootMoves.size(); i++) {
817
- if (rootMoves[i].score == best)
818
- rootMoves[j++] = rootMoves[i];
819
- }
820
- rootMoves.resize(j, Search::RootMove(MOVE_NONE));
821
-
822
- return true;
823
- }
824
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/syzygy/tbprobe.h DELETED
@@ -1,19 +0,0 @@
1
- #ifndef TBPROBE_H
2
- #define TBPROBE_H
3
-
4
- #include "../search.h"
5
-
6
- namespace Tablebases {
7
-
8
- extern int MaxCardinality;
9
-
10
- void init(const std::string& path);
11
- int probe_wdl(Position& pos, int *success);
12
- int probe_dtz(Position& pos, int *success);
13
- bool root_probe(Position& pos, Search::RootMoves& rootMoves, Value& score);
14
- bool root_probe_wdl(Position& pos, Search::RootMoves& rootMoves, Value& score);
15
- void filter_root_moves(Position& pos, Search::RootMoves& rootMoves);
16
-
17
- }
18
-
19
- #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/thread.cpp DELETED
@@ -1,223 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #include <algorithm> // For std::count
22
- #include <cassert>
23
-
24
- #include "movegen.h"
25
- #include "search.h"
26
- #include "thread.h"
27
- #include "uci.h"
28
- #include "syzygy/tbprobe.h"
29
-
30
- ThreadPool Threads; // Global object
31
-
32
- /// Thread constructor launches the thread and then waits until it goes to sleep
33
- /// in idle_loop().
34
-
35
- Thread::Thread() {
36
-
37
- resetCalls = exit = false;
38
- maxPly = callsCnt = 0;
39
- tbHits = 0;
40
- history.clear();
41
- counterMoves.clear();
42
- idx = Threads.size(); // Start from 0
43
-
44
- std::unique_lock<Mutex> lk(mutex);
45
- searching = true;
46
- nativeThread = std::thread(&Thread::idle_loop, this);
47
- sleepCondition.wait(lk, [&]{ return !searching; });
48
- }
49
-
50
-
51
- /// Thread destructor waits for thread termination before returning
52
-
53
- Thread::~Thread() {
54
-
55
- mutex.lock();
56
- exit = true;
57
- sleepCondition.notify_one();
58
- mutex.unlock();
59
- nativeThread.join();
60
- }
61
-
62
-
63
- /// Thread::wait_for_search_finished() waits on sleep condition
64
- /// until not searching
65
-
66
- void Thread::wait_for_search_finished() {
67
-
68
- std::unique_lock<Mutex> lk(mutex);
69
- sleepCondition.wait(lk, [&]{ return !searching; });
70
- }
71
-
72
-
73
- /// Thread::wait() waits on sleep condition until condition is true
74
-
75
- void Thread::wait(std::atomic_bool& condition) {
76
-
77
- std::unique_lock<Mutex> lk(mutex);
78
- sleepCondition.wait(lk, [&]{ return bool(condition); });
79
- }
80
-
81
-
82
- /// Thread::start_searching() wakes up the thread that will start the search
83
-
84
- void Thread::start_searching(bool resume) {
85
-
86
- std::unique_lock<Mutex> lk(mutex);
87
-
88
- if (!resume)
89
- searching = true;
90
-
91
- sleepCondition.notify_one();
92
- }
93
-
94
-
95
- /// Thread::idle_loop() is where the thread is parked when it has no work to do
96
-
97
- void Thread::idle_loop() {
98
-
99
- while (!exit)
100
- {
101
- std::unique_lock<Mutex> lk(mutex);
102
-
103
- searching = false;
104
-
105
- while (!searching && !exit)
106
- {
107
- sleepCondition.notify_one(); // Wake up any waiting thread
108
- sleepCondition.wait(lk);
109
- }
110
-
111
- lk.unlock();
112
-
113
- if (!exit)
114
- search();
115
- }
116
- }
117
-
118
-
119
- /// ThreadPool::init() creates and launches requested threads that will go
120
- /// immediately to sleep. We cannot use a constructor because Threads is a
121
- /// static object and we need a fully initialized engine at this point due to
122
- /// allocation of Endgames in the Thread constructor.
123
-
124
- void ThreadPool::init() {
125
-
126
- push_back(new MainThread);
127
- read_uci_options();
128
- }
129
-
130
-
131
- /// ThreadPool::exit() terminates threads before the program exits. Cannot be
132
- /// done in destructor because threads must be terminated before deleting any
133
- /// static objects while still in main().
134
-
135
- void ThreadPool::exit() {
136
-
137
- while (size())
138
- delete back(), pop_back();
139
- }
140
-
141
-
142
- /// ThreadPool::read_uci_options() updates internal threads parameters from the
143
- /// corresponding UCI options and creates/destroys threads to match requested
144
- /// number. Thread objects are dynamically allocated.
145
-
146
- void ThreadPool::read_uci_options() {
147
-
148
- size_t requested = Options["Threads"];
149
-
150
- assert(requested > 0);
151
-
152
- while (size() < requested)
153
- push_back(new Thread);
154
-
155
- while (size() > requested)
156
- delete back(), pop_back();
157
- }
158
-
159
-
160
- /// ThreadPool::nodes_searched() returns the number of nodes searched
161
-
162
- uint64_t ThreadPool::nodes_searched() const {
163
-
164
- uint64_t nodes = 0;
165
- for (Thread* th : *this)
166
- nodes += th->rootPos.nodes_searched();
167
- return nodes;
168
- }
169
-
170
-
171
- /// ThreadPool::tb_hits() returns the number of TB hits
172
-
173
- uint64_t ThreadPool::tb_hits() const {
174
-
175
- uint64_t hits = 0;
176
- for (Thread* th : *this)
177
- hits += th->tbHits;
178
- return hits;
179
- }
180
-
181
-
182
- /// ThreadPool::start_thinking() wakes up the main thread sleeping in idle_loop()
183
- /// and starts a new search, then returns immediately.
184
-
185
- void ThreadPool::start_thinking(Position& pos, StateListPtr& states,
186
- const Search::LimitsType& limits) {
187
-
188
- main()->wait_for_search_finished();
189
-
190
- Search::Signals.stopOnPonderhit = Search::Signals.stop = false;
191
- Search::Limits = limits;
192
- Search::RootMoves rootMoves;
193
-
194
- for (const auto& m : MoveList<LEGAL>(pos))
195
- if ( limits.searchmoves.empty()
196
- || std::count(limits.searchmoves.begin(), limits.searchmoves.end(), m))
197
- rootMoves.push_back(Search::RootMove(m));
198
-
199
- if (!rootMoves.empty())
200
- Tablebases::filter_root_moves(pos, rootMoves);
201
-
202
- // After ownership transfer 'states' becomes empty, so if we stop the search
203
- // and call 'go' again without setting a new position states.get() == NULL.
204
- assert(states.get() || setupStates.get());
205
-
206
- if (states.get())
207
- setupStates = std::move(states); // Ownership transfer, states is now empty
208
-
209
- StateInfo tmp = setupStates->back();
210
-
211
- for (Thread* th : Threads)
212
- {
213
- th->maxPly = 0;
214
- th->tbHits = 0;
215
- th->rootDepth = DEPTH_ZERO;
216
- th->rootMoves = rootMoves;
217
- th->rootPos.set(pos.fen(), pos.is_chess960(), &setupStates->back(), th);
218
- }
219
-
220
- setupStates->back() = tmp; // Restore st->previous, cleared by Position::set()
221
-
222
- main()->start_searching();
223
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/thread.h DELETED
@@ -1,111 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #ifndef THREAD_H_INCLUDED
22
- #define THREAD_H_INCLUDED
23
-
24
- #include <atomic>
25
- #include <bitset>
26
- #include <condition_variable>
27
- #include <mutex>
28
- #include <thread>
29
- #include <vector>
30
-
31
- #include "material.h"
32
- #include "movepick.h"
33
- #include "pawns.h"
34
- #include "position.h"
35
- #include "search.h"
36
- #include "thread_win32.h"
37
-
38
-
39
- /// Thread struct keeps together all the thread-related stuff. We also use
40
- /// per-thread pawn and material hash tables so that once we get a pointer to an
41
- /// entry its life time is unlimited and we don't have to care about someone
42
- /// changing the entry under our feet.
43
-
44
- class Thread {
45
-
46
- std::thread nativeThread;
47
- Mutex mutex;
48
- ConditionVariable sleepCondition;
49
- bool exit, searching;
50
-
51
- public:
52
- Thread();
53
- virtual ~Thread();
54
- virtual void search();
55
- void idle_loop();
56
- void start_searching(bool resume = false);
57
- void wait_for_search_finished();
58
- void wait(std::atomic_bool& b);
59
-
60
- Pawns::Table pawnsTable;
61
- Material::Table materialTable;
62
- Endgames endgames;
63
- size_t idx, PVIdx;
64
- int maxPly, callsCnt;
65
- uint64_t tbHits;
66
-
67
- Position rootPos;
68
- Search::RootMoves rootMoves;
69
- Depth rootDepth;
70
- Depth completedDepth;
71
- std::atomic_bool resetCalls;
72
- HistoryStats history;
73
- MoveStats counterMoves;
74
- FromToStats fromTo;
75
- CounterMoveHistoryStats counterMoveHistory;
76
- };
77
-
78
-
79
- /// MainThread is a derived class with a specific overload for the main thread
80
-
81
- struct MainThread : public Thread {
82
- virtual void search();
83
-
84
- bool easyMovePlayed, failedLow;
85
- double bestMoveChanges;
86
- Value previousScore;
87
- };
88
-
89
-
90
- /// ThreadPool struct handles all the threads-related stuff like init, starting,
91
- /// parking and, most importantly, launching a thread. All the access to threads
92
- /// data is done through this class.
93
-
94
- struct ThreadPool : public std::vector<Thread*> {
95
-
96
- void init(); // No constructor and destructor, threads rely on globals that should
97
- void exit(); // be initialized and valid during the whole thread lifetime.
98
-
99
- MainThread* main() { return static_cast<MainThread*>(at(0)); }
100
- void start_thinking(Position&, StateListPtr&, const Search::LimitsType&);
101
- void read_uci_options();
102
- uint64_t nodes_searched() const;
103
- uint64_t tb_hits() const;
104
-
105
- private:
106
- StateListPtr setupStates;
107
- };
108
-
109
- extern ThreadPool Threads;
110
-
111
- #endif // #ifndef THREAD_H_INCLUDED
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/thread_win32.h DELETED
@@ -1,70 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #ifndef THREAD_WIN32_H_INCLUDED
22
- #define THREAD_WIN32_H_INCLUDED
23
-
24
- /// STL thread library used by mingw and gcc when cross compiling for Windows
25
- /// relies on libwinpthread. Currently libwinpthread implements mutexes directly
26
- /// on top of Windows semaphores. Semaphores, being kernel objects, require kernel
27
- /// mode transition in order to lock or unlock, which is very slow compared to
28
- /// interlocked operations (about 30% slower on bench test). To work around this
29
- /// issue, we define our wrappers to the low level Win32 calls. We use critical
30
- /// sections to support Windows XP and older versions. Unfortunately, cond_wait()
31
- /// is racy between unlock() and WaitForSingleObject() but they have the same
32
- /// speed performance as the SRW locks.
33
-
34
- #include <condition_variable>
35
- #include <mutex>
36
-
37
- #if defined(_WIN32) && !defined(_MSC_VER)
38
-
39
- #ifndef NOMINMAX
40
- # define NOMINMAX // Disable macros min() and max()
41
- #endif
42
-
43
- #define WIN32_LEAN_AND_MEAN
44
- #include <windows.h>
45
- #undef WIN32_LEAN_AND_MEAN
46
- #undef NOMINMAX
47
-
48
- /// Mutex and ConditionVariable struct are wrappers of the low level locking
49
- /// machinery and are modeled after the corresponding C++11 classes.
50
-
51
- struct Mutex {
52
- Mutex() { InitializeCriticalSection(&cs); }
53
- ~Mutex() { DeleteCriticalSection(&cs); }
54
- void lock() { EnterCriticalSection(&cs); }
55
- void unlock() { LeaveCriticalSection(&cs); }
56
-
57
- private:
58
- CRITICAL_SECTION cs;
59
- };
60
-
61
- typedef std::condition_variable_any ConditionVariable;
62
-
63
- #else // Default case: use STL classes
64
-
65
- typedef std::mutex Mutex;
66
- typedef std::condition_variable ConditionVariable;
67
-
68
- #endif
69
-
70
- #endif // #ifndef THREAD_WIN32_H_INCLUDED
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/timeman.cpp DELETED
@@ -1,132 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #include <algorithm>
22
- #include <cfloat>
23
- #include <cmath>
24
-
25
- #include "search.h"
26
- #include "timeman.h"
27
- #include "uci.h"
28
-
29
- TimeManagement Time; // Our global time management object
30
-
31
- namespace {
32
-
33
- enum TimeType { OptimumTime, MaxTime };
34
-
35
- const int MoveHorizon = 50; // Plan time management at most this many moves ahead
36
- const double MaxRatio = 7.09; // When in trouble, we can step over reserved time with this ratio
37
- const double StealRatio = 0.35; // However we must not steal time from remaining moves over this ratio
38
-
39
-
40
- // move_importance() is a skew-logistic function based on naive statistical
41
- // analysis of "how many games are still undecided after n half-moves". Game
42
- // is considered "undecided" as long as neither side has >275cp advantage.
43
- // Data was extracted from the CCRL game database with some simple filtering criteria.
44
-
45
- double move_importance(int ply) {
46
-
47
- const double XScale = 7.64;
48
- const double XShift = 58.4;
49
- const double Skew = 0.183;
50
-
51
- return pow((1 + exp((ply - XShift) / XScale)), -Skew) + DBL_MIN; // Ensure non-zero
52
- }
53
-
54
- template<TimeType T>
55
- int remaining(int myTime, int movesToGo, int ply, int slowMover) {
56
-
57
- const double TMaxRatio = (T == OptimumTime ? 1 : MaxRatio);
58
- const double TStealRatio = (T == OptimumTime ? 0 : StealRatio);
59
-
60
- double moveImportance = (move_importance(ply) * slowMover) / 100;
61
- double otherMovesImportance = 0;
62
-
63
- for (int i = 1; i < movesToGo; ++i)
64
- otherMovesImportance += move_importance(ply + 2 * i);
65
-
66
- double ratio1 = (TMaxRatio * moveImportance) / (TMaxRatio * moveImportance + otherMovesImportance);
67
- double ratio2 = (moveImportance + TStealRatio * otherMovesImportance) / (moveImportance + otherMovesImportance);
68
-
69
- return int(myTime * std::min(ratio1, ratio2)); // Intel C++ asks for an explicit cast
70
- }
71
-
72
- } // namespace
73
-
74
-
75
- /// init() is called at the beginning of the search and calculates the allowed
76
- /// thinking time out of the time control and current game ply. We support four
77
- /// different kinds of time controls, passed in 'limits':
78
- ///
79
- /// inc == 0 && movestogo == 0 means: x basetime [sudden death!]
80
- /// inc == 0 && movestogo != 0 means: x moves in y minutes
81
- /// inc > 0 && movestogo == 0 means: x basetime + z increment
82
- /// inc > 0 && movestogo != 0 means: x moves in y minutes + z increment
83
-
84
- void TimeManagement::init(Search::LimitsType& limits, Color us, int ply) {
85
-
86
- int minThinkingTime = Options["Minimum Thinking Time"];
87
- int moveOverhead = Options["Move Overhead"];
88
- int slowMover = Options["Slow Mover"];
89
- int npmsec = Options["nodestime"];
90
-
91
- // If we have to play in 'nodes as time' mode, then convert from time
92
- // to nodes, and use resulting values in time management formulas.
93
- // WARNING: Given npms (nodes per millisecond) must be much lower then
94
- // the real engine speed to avoid time losses.
95
- if (npmsec)
96
- {
97
- if (!availableNodes) // Only once at game start
98
- availableNodes = npmsec * limits.time[us]; // Time is in msec
99
-
100
- // Convert from millisecs to nodes
101
- limits.time[us] = (int)availableNodes;
102
- limits.inc[us] *= npmsec;
103
- limits.npmsec = npmsec;
104
- }
105
-
106
- startTime = limits.startTime;
107
- optimumTime = maximumTime = std::max(limits.time[us], minThinkingTime);
108
-
109
- const int MaxMTG = limits.movestogo ? std::min(limits.movestogo, MoveHorizon) : MoveHorizon;
110
-
111
- // We calculate optimum time usage for different hypothetical "moves to go"-values
112
- // and choose the minimum of calculated search time values. Usually the greatest
113
- // hypMTG gives the minimum values.
114
- for (int hypMTG = 1; hypMTG <= MaxMTG; ++hypMTG)
115
- {
116
- // Calculate thinking time for hypothetical "moves to go"-value
117
- int hypMyTime = limits.time[us]
118
- + limits.inc[us] * (hypMTG - 1)
119
- - moveOverhead * (2 + std::min(hypMTG, 40));
120
-
121
- hypMyTime = std::max(hypMyTime, 0);
122
-
123
- int t1 = minThinkingTime + remaining<OptimumTime>(hypMyTime, hypMTG, ply, slowMover);
124
- int t2 = minThinkingTime + remaining<MaxTime >(hypMyTime, hypMTG, ply, slowMover);
125
-
126
- optimumTime = std::min(t1, optimumTime);
127
- maximumTime = std::min(t2, maximumTime);
128
- }
129
-
130
- if (Options["Ponder"])
131
- optimumTime += optimumTime / 4;
132
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/timeman.h DELETED
@@ -1,48 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #ifndef TIMEMAN_H_INCLUDED
22
- #define TIMEMAN_H_INCLUDED
23
-
24
- #include "misc.h"
25
- #include "search.h"
26
- #include "thread.h"
27
-
28
- /// The TimeManagement class computes the optimal time to think depending on
29
- /// the maximum available time, the game move number and other parameters.
30
-
31
- class TimeManagement {
32
- public:
33
- void init(Search::LimitsType& limits, Color us, int ply);
34
- int optimum() const { return optimumTime; }
35
- int maximum() const { return maximumTime; }
36
- int elapsed() const { return int(Search::Limits.npmsec ? Threads.nodes_searched() : now() - startTime); }
37
-
38
- int64_t availableNodes; // When in 'nodes as time' mode
39
-
40
- private:
41
- TimePoint startTime;
42
- int optimumTime;
43
- int maximumTime;
44
- };
45
-
46
- extern TimeManagement Time;
47
-
48
- #endif // #ifndef TIMEMAN_H_INCLUDED
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/tt.cpp DELETED
@@ -1,117 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #include <cstring> // For std::memset
22
- #include <iostream>
23
-
24
- #include "bitboard.h"
25
- #include "tt.h"
26
-
27
- TranspositionTable TT; // Our global transposition table
28
-
29
-
30
- /// TranspositionTable::resize() sets the size of the transposition table,
31
- /// measured in megabytes. Transposition table consists of a power of 2 number
32
- /// of clusters and each cluster consists of ClusterSize number of TTEntry.
33
-
34
- void TranspositionTable::resize(size_t mbSize) {
35
-
36
- size_t newClusterCount = size_t(1) << msb((mbSize * 1024 * 1024) / sizeof(Cluster));
37
-
38
- if (newClusterCount == clusterCount)
39
- return;
40
-
41
- clusterCount = newClusterCount;
42
-
43
- free(mem);
44
- mem = calloc(clusterCount * sizeof(Cluster) + CacheLineSize - 1, 1);
45
-
46
- if (!mem)
47
- {
48
- std::cerr << "Failed to allocate " << mbSize
49
- << "MB for transposition table." << std::endl;
50
- exit(EXIT_FAILURE);
51
- }
52
-
53
- table = (Cluster*)((uintptr_t(mem) + CacheLineSize - 1) & ~(CacheLineSize - 1));
54
- }
55
-
56
-
57
- /// TranspositionTable::clear() overwrites the entire transposition table
58
- /// with zeros. It is called whenever the table is resized, or when the
59
- /// user asks the program to clear the table (from the UCI interface).
60
-
61
- void TranspositionTable::clear() {
62
-
63
- std::memset(table, 0, clusterCount * sizeof(Cluster));
64
- }
65
-
66
-
67
- /// TranspositionTable::probe() looks up the current position in the transposition
68
- /// table. It returns true and a pointer to the TTEntry if the position is found.
69
- /// Otherwise, it returns false and a pointer to an empty or least valuable TTEntry
70
- /// to be replaced later. The replace value of an entry is calculated as its depth
71
- /// minus 8 times its relative age. TTEntry t1 is considered more valuable than
72
- /// TTEntry t2 if its replace value is greater than that of t2.
73
-
74
- TTEntry* TranspositionTable::probe(const Key key, bool& found) const {
75
-
76
- TTEntry* const tte = first_entry(key);
77
- const uint16_t key16 = key >> 48; // Use the high 16 bits as key inside the cluster
78
-
79
- for (int i = 0; i < ClusterSize; ++i)
80
- if (!tte[i].key16 || tte[i].key16 == key16)
81
- {
82
- if ((tte[i].genBound8 & 0xFC) != generation8 && tte[i].key16)
83
- tte[i].genBound8 = uint8_t(generation8 | tte[i].bound()); // Refresh
84
-
85
- return found = (bool)tte[i].key16, &tte[i];
86
- }
87
-
88
- // Find an entry to be replaced according to the replacement strategy
89
- TTEntry* replace = tte;
90
- for (int i = 1; i < ClusterSize; ++i)
91
- // Due to our packed storage format for generation and its cyclic
92
- // nature we add 259 (256 is the modulus plus 3 to keep the lowest
93
- // two bound bits from affecting the result) to calculate the entry
94
- // age correctly even after generation8 overflows into the next cycle.
95
- if ( replace->depth8 - ((259 + generation8 - replace->genBound8) & 0xFC) * 2
96
- > tte[i].depth8 - ((259 + generation8 - tte[i].genBound8) & 0xFC) * 2)
97
- replace = &tte[i];
98
-
99
- return found = false, replace;
100
- }
101
-
102
-
103
- /// TranspositionTable::hashfull() returns an approximation of the hashtable
104
- /// occupation during a search. The hash is x permill full, as per UCI protocol.
105
-
106
- int TranspositionTable::hashfull() const {
107
-
108
- int cnt = 0;
109
- for (int i = 0; i < 1000 / ClusterSize; i++)
110
- {
111
- const TTEntry* tte = &table[i].entry[0];
112
- for (int j = 0; j < ClusterSize; j++)
113
- if ((tte[j].genBound8 & 0xFC) == generation8)
114
- cnt++;
115
- }
116
- return cnt;
117
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/tt.h DELETED
@@ -1,121 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #ifndef TT_H_INCLUDED
22
- #define TT_H_INCLUDED
23
-
24
- #include "misc.h"
25
- #include "types.h"
26
-
27
- /// TTEntry struct is the 10 bytes transposition table entry, defined as below:
28
- ///
29
- /// key 16 bit
30
- /// move 16 bit
31
- /// value 16 bit
32
- /// eval value 16 bit
33
- /// generation 6 bit
34
- /// bound type 2 bit
35
- /// depth 8 bit
36
-
37
- struct TTEntry {
38
-
39
- Move move() const { return (Move )move16; }
40
- Value value() const { return (Value)value16; }
41
- Value eval() const { return (Value)eval16; }
42
- Depth depth() const { return (Depth)(depth8 * int(ONE_PLY)); }
43
- Bound bound() const { return (Bound)(genBound8 & 0x3); }
44
-
45
- void save(Key k, Value v, Bound b, Depth d, Move m, Value ev, uint8_t g) {
46
-
47
- assert(d / ONE_PLY * ONE_PLY == d);
48
-
49
- // Preserve any existing move for the same position
50
- if (m || (k >> 48) != key16)
51
- move16 = (uint16_t)m;
52
-
53
- // Don't overwrite more valuable entries
54
- if ( (k >> 48) != key16
55
- || d / ONE_PLY > depth8 - 4
56
- /* || g != (genBound8 & 0xFC) // Matching non-zero keys are already refreshed by probe() */
57
- || b == BOUND_EXACT)
58
- {
59
- key16 = (uint16_t)(k >> 48);
60
- value16 = (int16_t)v;
61
- eval16 = (int16_t)ev;
62
- genBound8 = (uint8_t)(g | b);
63
- depth8 = (int8_t)(d / ONE_PLY);
64
- }
65
- }
66
-
67
- private:
68
- friend class TranspositionTable;
69
-
70
- uint16_t key16;
71
- uint16_t move16;
72
- int16_t value16;
73
- int16_t eval16;
74
- uint8_t genBound8;
75
- int8_t depth8;
76
- };
77
-
78
-
79
- /// A TranspositionTable consists of a power of 2 number of clusters and each
80
- /// cluster consists of ClusterSize number of TTEntry. Each non-empty entry
81
- /// contains information of exactly one position. The size of a cluster should
82
- /// divide the size of a cache line size, to ensure that clusters never cross
83
- /// cache lines. This ensures best cache performance, as the cacheline is
84
- /// prefetched, as soon as possible.
85
-
86
- class TranspositionTable {
87
-
88
- static const int CacheLineSize = 64;
89
- static const int ClusterSize = 3;
90
-
91
- struct Cluster {
92
- TTEntry entry[ClusterSize];
93
- char padding[2]; // Align to a divisor of the cache line size
94
- };
95
-
96
- static_assert(CacheLineSize % sizeof(Cluster) == 0, "Cluster size incorrect");
97
-
98
- public:
99
- ~TranspositionTable() { free(mem); }
100
- void new_search() { generation8 += 4; } // Lower 2 bits are used by Bound
101
- uint8_t generation() const { return generation8; }
102
- TTEntry* probe(const Key key, bool& found) const;
103
- int hashfull() const;
104
- void resize(size_t mbSize);
105
- void clear();
106
-
107
- // The lowest order bits of the key are used to get the index of the cluster
108
- TTEntry* first_entry(const Key key) const {
109
- return &table[(size_t)key & (clusterCount - 1)].entry[0];
110
- }
111
-
112
- private:
113
- size_t clusterCount;
114
- Cluster* table;
115
- void* mem;
116
- uint8_t generation8; // Size must be not bigger than TTEntry::genBound8
117
- };
118
-
119
- extern TranspositionTable TT;
120
-
121
- #endif // #ifndef TT_H_INCLUDED
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/types.h DELETED
@@ -1,435 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #ifndef TYPES_H_INCLUDED
22
- #define TYPES_H_INCLUDED
23
-
24
- /// When compiling with provided Makefile (e.g. for Linux and OSX), configuration
25
- /// is done automatically. To get started type 'make help'.
26
- ///
27
- /// When Makefile is not used (e.g. with Microsoft Visual Studio) some switches
28
- /// need to be set manually:
29
- ///
30
- /// -DNDEBUG | Disable debugging mode. Always use this for release.
31
- ///
32
- /// -DNO_PREFETCH | Disable use of prefetch asm-instruction. You may need this to
33
- /// | run on some very old machines.
34
- ///
35
- /// -DUSE_POPCNT | Add runtime support for use of popcnt asm-instruction. Works
36
- /// | only in 64-bit mode and requires hardware with popcnt support.
37
- ///
38
- /// -DUSE_PEXT | Add runtime support for use of pext asm-instruction. Works
39
- /// | only in 64-bit mode and requires hardware with pext support.
40
-
41
- #include <cassert>
42
- #include <cctype>
43
- #include <climits>
44
- #include <cstdint>
45
- #include <cstdlib>
46
-
47
- #if defined(_MSC_VER)
48
- // Disable some silly and noisy warning from MSVC compiler
49
- #pragma warning(disable: 4127) // Conditional expression is constant
50
- #pragma warning(disable: 4146) // Unary minus operator applied to unsigned type
51
- #pragma warning(disable: 4800) // Forcing value to bool 'true' or 'false'
52
- #endif
53
-
54
- /// Predefined macros hell:
55
- ///
56
- /// __GNUC__ Compiler is gcc, Clang or Intel on Linux
57
- /// __INTEL_COMPILER Compiler is Intel
58
- /// _MSC_VER Compiler is MSVC or Intel on Windows
59
- /// _WIN32 Building on Windows (any)
60
- /// _WIN64 Building on Windows 64 bit
61
-
62
- #if defined(_WIN64) && defined(_MSC_VER) // No Makefile used
63
- # include <intrin.h> // Microsoft header for _BitScanForward64()
64
- # define IS_64BIT
65
- #endif
66
-
67
- #if defined(USE_POPCNT) && (defined(__INTEL_COMPILER) || defined(_MSC_VER))
68
- # include <nmmintrin.h> // Intel and Microsoft header for _mm_popcnt_u64()
69
- #endif
70
-
71
- #if !defined(NO_PREFETCH) && (defined(__INTEL_COMPILER) || defined(_MSC_VER))
72
- # include <xmmintrin.h> // Intel and Microsoft header for _mm_prefetch()
73
- #endif
74
-
75
- #if defined(USE_PEXT)
76
- # include <immintrin.h> // Header for _pext_u64() intrinsic
77
- # define pext(b, m) _pext_u64(b, m)
78
- #else
79
- # define pext(b, m) (0)
80
- #endif
81
-
82
- #ifdef USE_POPCNT
83
- const bool HasPopCnt = true;
84
- #else
85
- const bool HasPopCnt = false;
86
- #endif
87
-
88
- #ifdef USE_PEXT
89
- const bool HasPext = true;
90
- #else
91
- const bool HasPext = false;
92
- #endif
93
-
94
- #ifdef IS_64BIT
95
- const bool Is64Bit = true;
96
- #else
97
- const bool Is64Bit = false;
98
- #endif
99
-
100
- typedef uint64_t Key;
101
- typedef uint64_t Bitboard;
102
-
103
- const int MAX_MOVES = 256;
104
- const int MAX_PLY = 128;
105
-
106
- /// A move needs 16 bits to be stored
107
- ///
108
- /// bit 0- 5: destination square (from 0 to 63)
109
- /// bit 6-11: origin square (from 0 to 63)
110
- /// bit 12-13: promotion piece type - 2 (from KNIGHT-2 to QUEEN-2)
111
- /// bit 14-15: special move flag: promotion (1), en passant (2), castling (3)
112
- /// NOTE: EN-PASSANT bit is set only when a pawn can be captured
113
- ///
114
- /// Special cases are MOVE_NONE and MOVE_NULL. We can sneak these in because in
115
- /// any normal move destination square is always different from origin square
116
- /// while MOVE_NONE and MOVE_NULL have the same origin and destination square.
117
-
118
- enum Move : int {
119
- MOVE_NONE,
120
- MOVE_NULL = 65
121
- };
122
-
123
- enum MoveType {
124
- NORMAL,
125
- PROMOTION = 1 << 14,
126
- ENPASSANT = 2 << 14,
127
- CASTLING = 3 << 14
128
- };
129
-
130
- enum Color {
131
- WHITE, BLACK, NO_COLOR, COLOR_NB = 2
132
- };
133
-
134
- enum CastlingSide {
135
- KING_SIDE, QUEEN_SIDE, CASTLING_SIDE_NB = 2
136
- };
137
-
138
- enum CastlingRight {
139
- NO_CASTLING,
140
- WHITE_OO,
141
- WHITE_OOO = WHITE_OO << 1,
142
- BLACK_OO = WHITE_OO << 2,
143
- BLACK_OOO = WHITE_OO << 3,
144
- ANY_CASTLING = WHITE_OO | WHITE_OOO | BLACK_OO | BLACK_OOO,
145
- CASTLING_RIGHT_NB = 16
146
- };
147
-
148
- template<Color C, CastlingSide S> struct MakeCastling {
149
- static const CastlingRight
150
- right = C == WHITE ? S == QUEEN_SIDE ? WHITE_OOO : WHITE_OO
151
- : S == QUEEN_SIDE ? BLACK_OOO : BLACK_OO;
152
- };
153
-
154
- enum Phase {
155
- PHASE_ENDGAME,
156
- PHASE_MIDGAME = 128,
157
- MG = 0, EG = 1, PHASE_NB = 2
158
- };
159
-
160
- enum ScaleFactor {
161
- SCALE_FACTOR_DRAW = 0,
162
- SCALE_FACTOR_ONEPAWN = 48,
163
- SCALE_FACTOR_NORMAL = 64,
164
- SCALE_FACTOR_MAX = 128,
165
- SCALE_FACTOR_NONE = 255
166
- };
167
-
168
- enum Bound {
169
- BOUND_NONE,
170
- BOUND_UPPER,
171
- BOUND_LOWER,
172
- BOUND_EXACT = BOUND_UPPER | BOUND_LOWER
173
- };
174
-
175
- enum Value : int {
176
- VALUE_ZERO = 0,
177
- VALUE_DRAW = 0,
178
- VALUE_KNOWN_WIN = 10000,
179
- VALUE_MATE = 32000,
180
- VALUE_INFINITE = 32001,
181
- VALUE_NONE = 32002,
182
-
183
- VALUE_MATE_IN_MAX_PLY = VALUE_MATE - 2 * MAX_PLY,
184
- VALUE_MATED_IN_MAX_PLY = -VALUE_MATE + 2 * MAX_PLY,
185
-
186
- PawnValueMg = 188, PawnValueEg = 248,
187
- KnightValueMg = 753, KnightValueEg = 832,
188
- BishopValueMg = 826, BishopValueEg = 897,
189
- RookValueMg = 1285, RookValueEg = 1371,
190
- QueenValueMg = 2513, QueenValueEg = 2650,
191
-
192
- MidgameLimit = 15258, EndgameLimit = 3915
193
- };
194
-
195
- enum PieceType {
196
- NO_PIECE_TYPE, PAWN, KNIGHT, BISHOP, ROOK, QUEEN, KING,
197
- ALL_PIECES = 0,
198
- PIECE_TYPE_NB = 8
199
- };
200
-
201
- enum Piece {
202
- NO_PIECE,
203
- W_PAWN = 1, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING,
204
- B_PAWN = 9, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING,
205
- PIECE_NB = 16
206
- };
207
-
208
- const Piece Pieces[] = { W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING,
209
- B_PAWN, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING };
210
- extern Value PieceValue[PHASE_NB][PIECE_NB];
211
-
212
- enum Depth {
213
-
214
- ONE_PLY = 1,
215
-
216
- DEPTH_ZERO = 0 * ONE_PLY,
217
- DEPTH_QS_CHECKS = 0 * ONE_PLY,
218
- DEPTH_QS_NO_CHECKS = -1 * ONE_PLY,
219
- DEPTH_QS_RECAPTURES = -5 * ONE_PLY,
220
-
221
- DEPTH_NONE = -6 * ONE_PLY,
222
- DEPTH_MAX = MAX_PLY * ONE_PLY
223
- };
224
-
225
- static_assert(!(ONE_PLY & (ONE_PLY - 1)), "ONE_PLY is not a power of 2");
226
-
227
- enum Square {
228
- SQ_A1, SQ_B1, SQ_C1, SQ_D1, SQ_E1, SQ_F1, SQ_G1, SQ_H1,
229
- SQ_A2, SQ_B2, SQ_C2, SQ_D2, SQ_E2, SQ_F2, SQ_G2, SQ_H2,
230
- SQ_A3, SQ_B3, SQ_C3, SQ_D3, SQ_E3, SQ_F3, SQ_G3, SQ_H3,
231
- SQ_A4, SQ_B4, SQ_C4, SQ_D4, SQ_E4, SQ_F4, SQ_G4, SQ_H4,
232
- SQ_A5, SQ_B5, SQ_C5, SQ_D5, SQ_E5, SQ_F5, SQ_G5, SQ_H5,
233
- SQ_A6, SQ_B6, SQ_C6, SQ_D6, SQ_E6, SQ_F6, SQ_G6, SQ_H6,
234
- SQ_A7, SQ_B7, SQ_C7, SQ_D7, SQ_E7, SQ_F7, SQ_G7, SQ_H7,
235
- SQ_A8, SQ_B8, SQ_C8, SQ_D8, SQ_E8, SQ_F8, SQ_G8, SQ_H8,
236
- SQ_NONE,
237
-
238
- SQUARE_NB = 64,
239
-
240
- NORTH = 8,
241
- EAST = 1,
242
- SOUTH = -8,
243
- WEST = -1,
244
-
245
- NORTH_EAST = NORTH + EAST,
246
- SOUTH_EAST = SOUTH + EAST,
247
- SOUTH_WEST = SOUTH + WEST,
248
- NORTH_WEST = NORTH + WEST
249
- };
250
-
251
- enum File : int {
252
- FILE_A, FILE_B, FILE_C, FILE_D, FILE_E, FILE_F, FILE_G, FILE_H, FILE_NB
253
- };
254
-
255
- enum Rank : int {
256
- RANK_1, RANK_2, RANK_3, RANK_4, RANK_5, RANK_6, RANK_7, RANK_8, RANK_NB
257
- };
258
-
259
-
260
- /// Score enum stores a middlegame and an endgame value in a single integer
261
- /// (enum). The least significant 16 bits are used to store the endgame value
262
- /// and the upper 16 bits are used to store the middlegame value. Take some
263
- /// care to avoid left-shifting a signed int to avoid undefined behavior.
264
- enum Score : int { SCORE_ZERO };
265
-
266
- inline Score make_score(int mg, int eg) {
267
- return Score((int)((unsigned int)eg << 16) + mg);
268
- }
269
-
270
- /// Extracting the signed lower and upper 16 bits is not so trivial because
271
- /// according to the standard a simple cast to short is implementation defined
272
- /// and so is a right shift of a signed integer.
273
- inline Value eg_value(Score s) {
274
-
275
- union { uint16_t u; int16_t s; } eg = { uint16_t(unsigned(s + 0x8000) >> 16) };
276
- return Value(eg.s);
277
- }
278
-
279
- inline Value mg_value(Score s) {
280
-
281
- union { uint16_t u; int16_t s; } mg = { uint16_t(unsigned(s)) };
282
- return Value(mg.s);
283
- }
284
-
285
- #define ENABLE_BASE_OPERATORS_ON(T) \
286
- inline T operator+(T d1, T d2) { return T(int(d1) + int(d2)); } \
287
- inline T operator-(T d1, T d2) { return T(int(d1) - int(d2)); } \
288
- inline T operator*(int i, T d) { return T(i * int(d)); } \
289
- inline T operator*(T d, int i) { return T(int(d) * i); } \
290
- inline T operator-(T d) { return T(-int(d)); } \
291
- inline T& operator+=(T& d1, T d2) { return d1 = d1 + d2; } \
292
- inline T& operator-=(T& d1, T d2) { return d1 = d1 - d2; } \
293
- inline T& operator*=(T& d, int i) { return d = T(int(d) * i); }
294
-
295
- #define ENABLE_FULL_OPERATORS_ON(T) \
296
- ENABLE_BASE_OPERATORS_ON(T) \
297
- inline T& operator++(T& d) { return d = T(int(d) + 1); } \
298
- inline T& operator--(T& d) { return d = T(int(d) - 1); } \
299
- inline T operator/(T d, int i) { return T(int(d) / i); } \
300
- inline int operator/(T d1, T d2) { return int(d1) / int(d2); } \
301
- inline T& operator/=(T& d, int i) { return d = T(int(d) / i); }
302
-
303
- ENABLE_FULL_OPERATORS_ON(Value)
304
- ENABLE_FULL_OPERATORS_ON(PieceType)
305
- ENABLE_FULL_OPERATORS_ON(Piece)
306
- ENABLE_FULL_OPERATORS_ON(Color)
307
- ENABLE_FULL_OPERATORS_ON(Depth)
308
- ENABLE_FULL_OPERATORS_ON(Square)
309
- ENABLE_FULL_OPERATORS_ON(File)
310
- ENABLE_FULL_OPERATORS_ON(Rank)
311
-
312
- ENABLE_BASE_OPERATORS_ON(Score)
313
-
314
- #undef ENABLE_FULL_OPERATORS_ON
315
- #undef ENABLE_BASE_OPERATORS_ON
316
-
317
- /// Additional operators to add integers to a Value
318
- inline Value operator+(Value v, int i) { return Value(int(v) + i); }
319
- inline Value operator-(Value v, int i) { return Value(int(v) - i); }
320
- inline Value& operator+=(Value& v, int i) { return v = v + i; }
321
- inline Value& operator-=(Value& v, int i) { return v = v - i; }
322
-
323
- /// Only declared but not defined. We don't want to multiply two scores due to
324
- /// a very high risk of overflow. So user should explicitly convert to integer.
325
- inline Score operator*(Score s1, Score s2);
326
-
327
- /// Division of a Score must be handled separately for each term
328
- inline Score operator/(Score s, int i) {
329
- return make_score(mg_value(s) / i, eg_value(s) / i);
330
- }
331
-
332
- inline Color operator~(Color c) {
333
- return Color(c ^ BLACK); // Toggle color
334
- }
335
-
336
- inline Square operator~(Square s) {
337
- return Square(s ^ SQ_A8); // Vertical flip SQ_A1 -> SQ_A8
338
- }
339
-
340
- inline Piece operator~(Piece pc) {
341
- return Piece(pc ^ 8); // Swap color of piece B_KNIGHT -> W_KNIGHT
342
- }
343
-
344
- inline CastlingRight operator|(Color c, CastlingSide s) {
345
- return CastlingRight(WHITE_OO << ((s == QUEEN_SIDE) + 2 * c));
346
- }
347
-
348
- inline Value mate_in(int ply) {
349
- return VALUE_MATE - ply;
350
- }
351
-
352
- inline Value mated_in(int ply) {
353
- return -VALUE_MATE + ply;
354
- }
355
-
356
- inline Square make_square(File f, Rank r) {
357
- return Square((r << 3) + f);
358
- }
359
-
360
- inline Piece make_piece(Color c, PieceType pt) {
361
- return Piece((c << 3) + pt);
362
- }
363
-
364
- inline PieceType type_of(Piece pc) {
365
- return PieceType(pc & 7);
366
- }
367
-
368
- inline Color color_of(Piece pc) {
369
- assert(pc != NO_PIECE);
370
- return Color(pc >> 3);
371
- }
372
-
373
- inline bool is_ok(Square s) {
374
- return s >= SQ_A1 && s <= SQ_H8;
375
- }
376
-
377
- inline File file_of(Square s) {
378
- return File(s & 7);
379
- }
380
-
381
- inline Rank rank_of(Square s) {
382
- return Rank(s >> 3);
383
- }
384
-
385
- inline Square relative_square(Color c, Square s) {
386
- return Square(s ^ (c * 56));
387
- }
388
-
389
- inline Rank relative_rank(Color c, Rank r) {
390
- return Rank(r ^ (c * 7));
391
- }
392
-
393
- inline Rank relative_rank(Color c, Square s) {
394
- return relative_rank(c, rank_of(s));
395
- }
396
-
397
- inline bool opposite_colors(Square s1, Square s2) {
398
- int s = int(s1) ^ int(s2);
399
- return ((s >> 3) ^ s) & 1;
400
- }
401
-
402
- inline Square pawn_push(Color c) {
403
- return c == WHITE ? NORTH : SOUTH;
404
- }
405
-
406
- inline Square from_sq(Move m) {
407
- return Square((m >> 6) & 0x3F);
408
- }
409
-
410
- inline Square to_sq(Move m) {
411
- return Square(m & 0x3F);
412
- }
413
-
414
- inline MoveType type_of(Move m) {
415
- return MoveType(m & (3 << 14));
416
- }
417
-
418
- inline PieceType promotion_type(Move m) {
419
- return PieceType(((m >> 12) & 3) + KNIGHT);
420
- }
421
-
422
- inline Move make_move(Square from, Square to) {
423
- return Move((from << 6) + to);
424
- }
425
-
426
- template<MoveType T>
427
- inline Move make(Square from, Square to, PieceType pt = KNIGHT) {
428
- return Move(T + ((pt - KNIGHT) << 12) + (from << 6) + to);
429
- }
430
-
431
- inline bool is_ok(Move m) {
432
- return from_sq(m) != to_sq(m); // Catch MOVE_NULL and MOVE_NONE
433
- }
434
-
435
- #endif // #ifndef TYPES_H_INCLUDED
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/uci.cpp DELETED
@@ -1,289 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #include <iostream>
22
- #include <sstream>
23
- #include <string>
24
-
25
- #include "evaluate.h"
26
- #include "movegen.h"
27
- #include "position.h"
28
- #include "search.h"
29
- #include "thread.h"
30
- #include "timeman.h"
31
- #include "uci.h"
32
-
33
- using namespace std;
34
-
35
- extern void benchmark(const Position& pos, istream& is);
36
-
37
- namespace {
38
-
39
- // FEN string of the initial position, normal chess
40
- const char* StartFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
41
-
42
- // A list to keep track of the position states along the setup moves (from the
43
- // start position to the position just before the search starts). Needed by
44
- // 'draw by repetition' detection.
45
- StateListPtr States(new std::deque<StateInfo>(1));
46
-
47
-
48
- // position() is called when engine receives the "position" UCI command.
49
- // The function sets up the position described in the given FEN string ("fen")
50
- // or the starting position ("startpos") and then makes the moves given in the
51
- // following move list ("moves").
52
-
53
- void position(Position& pos, istringstream& is) {
54
-
55
- Move m;
56
- string token, fen;
57
-
58
- is >> token;
59
-
60
- if (token == "startpos")
61
- {
62
- fen = StartFEN;
63
- is >> token; // Consume "moves" token if any
64
- }
65
- else if (token == "fen")
66
- while (is >> token && token != "moves")
67
- fen += token + " ";
68
- else
69
- return;
70
-
71
- States = StateListPtr(new std::deque<StateInfo>(1));
72
- pos.set(fen, Options["UCI_Chess960"], &States->back(), Threads.main());
73
-
74
- // Parse move list (if any)
75
- while (is >> token && (m = UCI::to_move(pos, token)) != MOVE_NONE)
76
- {
77
- States->push_back(StateInfo());
78
- pos.do_move(m, States->back(), pos.gives_check(m));
79
- }
80
- }
81
-
82
-
83
- // setoption() is called when engine receives the "setoption" UCI command. The
84
- // function updates the UCI option ("name") to the given value ("value").
85
-
86
- void setoption(istringstream& is) {
87
-
88
- string token, name, value;
89
-
90
- is >> token; // Consume "name" token
91
-
92
- // Read option name (can contain spaces)
93
- while (is >> token && token != "value")
94
- name += string(" ", name.empty() ? 0 : 1) + token;
95
-
96
- // Read option value (can contain spaces)
97
- while (is >> token)
98
- value += string(" ", value.empty() ? 0 : 1) + token;
99
-
100
- if (Options.count(name))
101
- Options[name] = value;
102
- else
103
- sync_cout << "No such option: " << name << sync_endl;
104
- }
105
-
106
-
107
- // go() is called when engine receives the "go" UCI command. The function sets
108
- // the thinking time and other parameters from the input string, then starts
109
- // the search.
110
-
111
- void go(Position& pos, istringstream& is) {
112
-
113
- Search::LimitsType limits;
114
- string token;
115
-
116
- limits.startTime = now(); // As early as possible!
117
-
118
- while (is >> token)
119
- if (token == "searchmoves")
120
- while (is >> token)
121
- limits.searchmoves.push_back(UCI::to_move(pos, token));
122
-
123
- else if (token == "wtime") is >> limits.time[WHITE];
124
- else if (token == "btime") is >> limits.time[BLACK];
125
- else if (token == "winc") is >> limits.inc[WHITE];
126
- else if (token == "binc") is >> limits.inc[BLACK];
127
- else if (token == "movestogo") is >> limits.movestogo;
128
- else if (token == "depth") is >> limits.depth;
129
- else if (token == "nodes") is >> limits.nodes;
130
- else if (token == "movetime") is >> limits.movetime;
131
- else if (token == "mate") is >> limits.mate;
132
- else if (token == "infinite") limits.infinite = 1;
133
- else if (token == "ponder") limits.ponder = 1;
134
-
135
- Threads.start_thinking(pos, States, limits);
136
- }
137
-
138
- } // namespace
139
-
140
-
141
- /// UCI::loop() waits for a command from stdin, parses it and calls the appropriate
142
- /// function. Also intercepts EOF from stdin to ensure gracefully exiting if the
143
- /// GUI dies unexpectedly. When called with some command line arguments, e.g. to
144
- /// run 'bench', once the command is executed the function returns immediately.
145
- /// In addition to the UCI ones, also some additional debug commands are supported.
146
-
147
- void UCI::loop(int argc, char* argv[]) {
148
-
149
- Position pos;
150
- string token, cmd;
151
-
152
- pos.set(StartFEN, false, &States->back(), Threads.main());
153
-
154
- for (int i = 1; i < argc; ++i)
155
- cmd += std::string(argv[i]) + " ";
156
-
157
- do {
158
- if (argc == 1 && !getline(cin, cmd)) // Block here waiting for input or EOF
159
- cmd = "quit";
160
-
161
- istringstream is(cmd);
162
-
163
- token.clear(); // getline() could return empty or blank line
164
- is >> skipws >> token;
165
-
166
- // The GUI sends 'ponderhit' to tell us to ponder on the same move the
167
- // opponent has played. In case Signals.stopOnPonderhit is set we are
168
- // waiting for 'ponderhit' to stop the search (for instance because we
169
- // already ran out of time), otherwise we should continue searching but
170
- // switching from pondering to normal search.
171
- if ( token == "quit"
172
- || token == "stop"
173
- || (token == "ponderhit" && Search::Signals.stopOnPonderhit))
174
- {
175
- Search::Signals.stop = true;
176
- Threads.main()->start_searching(true); // Could be sleeping
177
- }
178
- else if (token == "ponderhit")
179
- Search::Limits.ponder = 0; // Switch to normal search
180
-
181
- else if (token == "uci")
182
- sync_cout << "id name " << engine_info(true)
183
- << "\n" << Options
184
- << "\nuciok" << sync_endl;
185
-
186
- else if (token == "ucinewgame")
187
- {
188
- Search::clear();
189
- Time.availableNodes = 0;
190
- }
191
- else if (token == "isready") sync_cout << "readyok" << sync_endl;
192
- else if (token == "go") go(pos, is);
193
- else if (token == "position") position(pos, is);
194
- else if (token == "setoption") setoption(is);
195
-
196
- // Additional custom non-UCI commands, useful for debugging
197
- else if (token == "flip") pos.flip();
198
- else if (token == "bench") benchmark(pos, is);
199
- else if (token == "d") sync_cout << pos << sync_endl;
200
- else if (token == "eval") sync_cout << Eval::trace(pos) << sync_endl;
201
- else if (token == "perft")
202
- {
203
- int depth;
204
- stringstream ss;
205
-
206
- is >> depth;
207
- ss << Options["Hash"] << " "
208
- << Options["Threads"] << " " << depth << " current perft";
209
-
210
- benchmark(pos, ss);
211
- }
212
- else
213
- sync_cout << "Unknown command: " << cmd << sync_endl;
214
-
215
- } while (token != "quit" && argc == 1); // Passed args have one-shot behaviour
216
-
217
- Threads.main()->wait_for_search_finished();
218
- }
219
-
220
-
221
- /// UCI::value() converts a Value to a string suitable for use with the UCI
222
- /// protocol specification:
223
- ///
224
- /// cp <x> The score from the engine's point of view in centipawns.
225
- /// mate <y> Mate in y moves, not plies. If the engine is getting mated
226
- /// use negative values for y.
227
-
228
- string UCI::value(Value v) {
229
-
230
- stringstream ss;
231
-
232
- if (abs(v) < VALUE_MATE - MAX_PLY)
233
- ss << "cp " << v * 100 / PawnValueEg;
234
- else
235
- ss << "mate " << (v > 0 ? VALUE_MATE - v + 1 : -VALUE_MATE - v) / 2;
236
-
237
- return ss.str();
238
- }
239
-
240
-
241
- /// UCI::square() converts a Square to a string in algebraic notation (g1, a7, etc.)
242
-
243
- std::string UCI::square(Square s) {
244
- return std::string{ char('a' + file_of(s)), char('1' + rank_of(s)) };
245
- }
246
-
247
-
248
- /// UCI::move() converts a Move to a string in coordinate notation (g1f3, a7a8q).
249
- /// The only special case is castling, where we print in the e1g1 notation in
250
- /// normal chess mode, and in e1h1 notation in chess960 mode. Internally all
251
- /// castling moves are always encoded as 'king captures rook'.
252
-
253
- string UCI::move(Move m, bool chess960) {
254
-
255
- Square from = from_sq(m);
256
- Square to = to_sq(m);
257
-
258
- if (m == MOVE_NONE)
259
- return "(none)";
260
-
261
- if (m == MOVE_NULL)
262
- return "0000";
263
-
264
- if (type_of(m) == CASTLING && !chess960)
265
- to = make_square(to > from ? FILE_G : FILE_C, rank_of(from));
266
-
267
- string move = UCI::square(from) + UCI::square(to);
268
-
269
- if (type_of(m) == PROMOTION)
270
- move += " pnbrqk"[promotion_type(m)];
271
-
272
- return move;
273
- }
274
-
275
-
276
- /// UCI::to_move() converts a string representing a move in coordinate notation
277
- /// (g1f3, a7a8q) to the corresponding legal Move, if any.
278
-
279
- Move UCI::to_move(const Position& pos, string& str) {
280
-
281
- if (str.length() == 5) // Junior could send promotion piece in uppercase
282
- str[4] = char(tolower(str[4]));
283
-
284
- for (const auto& m : MoveList<LEGAL>(pos))
285
- if (str == UCI::move(m, pos.is_chess960()))
286
- return m;
287
-
288
- return MOVE_NONE;
289
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/uci.h DELETED
@@ -1,80 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #ifndef UCI_H_INCLUDED
22
- #define UCI_H_INCLUDED
23
-
24
- #include <map>
25
- #include <string>
26
-
27
- #include "types.h"
28
-
29
- class Position;
30
-
31
- namespace UCI {
32
-
33
- class Option;
34
-
35
- /// Custom comparator because UCI options should be case insensitive
36
- struct CaseInsensitiveLess {
37
- bool operator() (const std::string&, const std::string&) const;
38
- };
39
-
40
- /// Our options container is actually a std::map
41
- typedef std::map<std::string, Option, CaseInsensitiveLess> OptionsMap;
42
-
43
- /// Option class implements an option as defined by UCI protocol
44
- class Option {
45
-
46
- typedef void (*OnChange)(const Option&);
47
-
48
- public:
49
- Option(OnChange = nullptr);
50
- Option(bool v, OnChange = nullptr);
51
- Option(const char* v, OnChange = nullptr);
52
- Option(int v, int min, int max, OnChange = nullptr);
53
-
54
- Option& operator=(const std::string&);
55
- void operator<<(const Option&);
56
- operator int() const;
57
- operator std::string() const;
58
-
59
- private:
60
- friend std::ostream& operator<<(std::ostream&, const OptionsMap&);
61
-
62
- std::string defaultValue, currentValue, type;
63
- int min, max;
64
- size_t idx;
65
- OnChange on_change;
66
- };
67
-
68
- void init(OptionsMap&);
69
- void loop(int argc, char* argv[]);
70
- std::string value(Value v);
71
- std::string square(Square s);
72
- std::string move(Move m, bool chess960);
73
- std::string pv(const Position& pos, Depth depth, Value alpha, Value beta);
74
- Move to_move(const Position& pos, std::string& str);
75
-
76
- } // namespace UCI
77
-
78
- extern UCI::OptionsMap Options;
79
-
80
- #endif // #ifndef UCI_H_INCLUDED
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stockfish-8-linux/src/ucioption.cpp DELETED
@@ -1,163 +0,0 @@
1
- /*
2
- Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4
- Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
- Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
6
-
7
- Stockfish is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- Stockfish is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
- #include <algorithm>
22
- #include <cassert>
23
- #include <ostream>
24
-
25
- #include "misc.h"
26
- #include "search.h"
27
- #include "thread.h"
28
- #include "tt.h"
29
- #include "uci.h"
30
- #include "syzygy/tbprobe.h"
31
-
32
- using std::string;
33
-
34
- UCI::OptionsMap Options; // Global object
35
-
36
- namespace UCI {
37
-
38
- /// 'On change' actions, triggered by an option's value change
39
- void on_clear_hash(const Option&) { Search::clear(); }
40
- void on_hash_size(const Option& o) { TT.resize(o); }
41
- void on_logger(const Option& o) { start_logger(o); }
42
- void on_threads(const Option&) { Threads.read_uci_options(); }
43
- void on_tb_path(const Option& o) { Tablebases::init(o); }
44
-
45
-
46
- /// Our case insensitive less() function as required by UCI protocol
47
- bool CaseInsensitiveLess::operator() (const string& s1, const string& s2) const {
48
-
49
- return std::lexicographical_compare(s1.begin(), s1.end(), s2.begin(), s2.end(),
50
- [](char c1, char c2) { return tolower(c1) < tolower(c2); });
51
- }
52
-
53
-
54
- /// init() initializes the UCI options to their hard-coded default values
55
-
56
- void init(OptionsMap& o) {
57
-
58
- const int MaxHashMB = Is64Bit ? 1024 * 1024 : 2048;
59
-
60
- o["Debug Log File"] << Option("", on_logger);
61
- o["Contempt"] << Option(0, -100, 100);
62
- o["Threads"] << Option(1, 1, 128, on_threads);
63
- o["Hash"] << Option(16, 1, MaxHashMB, on_hash_size);
64
- o["Clear Hash"] << Option(on_clear_hash);
65
- o["Ponder"] << Option(false);
66
- o["MultiPV"] << Option(1, 1, 500);
67
- o["Skill Level"] << Option(20, 0, 20);
68
- o["Move Overhead"] << Option(30, 0, 5000);
69
- o["Minimum Thinking Time"] << Option(20, 0, 5000);
70
- o["Slow Mover"] << Option(89, 10, 1000);
71
- o["nodestime"] << Option(0, 0, 10000);
72
- o["UCI_Chess960"] << Option(false);
73
- o["SyzygyPath"] << Option("<empty>", on_tb_path);
74
- o["SyzygyProbeDepth"] << Option(1, 1, 100);
75
- o["Syzygy50MoveRule"] << Option(true);
76
- o["SyzygyProbeLimit"] << Option(6, 0, 6);
77
- }
78
-
79
-
80
- /// operator<<() is used to print all the options default values in chronological
81
- /// insertion order (the idx field) and in the format defined by the UCI protocol.
82
-
83
- std::ostream& operator<<(std::ostream& os, const OptionsMap& om) {
84
-
85
- for (size_t idx = 0; idx < om.size(); ++idx)
86
- for (const auto& it : om)
87
- if (it.second.idx == idx)
88
- {
89
- const Option& o = it.second;
90
- os << "\noption name " << it.first << " type " << o.type;
91
-
92
- if (o.type != "button")
93
- os << " default " << o.defaultValue;
94
-
95
- if (o.type == "spin")
96
- os << " min " << o.min << " max " << o.max;
97
-
98
- break;
99
- }
100
-
101
- return os;
102
- }
103
-
104
-
105
- /// Option class constructors and conversion operators
106
-
107
- Option::Option(const char* v, OnChange f) : type("string"), min(0), max(0), on_change(f)
108
- { defaultValue = currentValue = v; }
109
-
110
- Option::Option(bool v, OnChange f) : type("check"), min(0), max(0), on_change(f)
111
- { defaultValue = currentValue = (v ? "true" : "false"); }
112
-
113
- Option::Option(OnChange f) : type("button"), min(0), max(0), on_change(f)
114
- {}
115
-
116
- Option::Option(int v, int minv, int maxv, OnChange f) : type("spin"), min(minv), max(maxv), on_change(f)
117
- { defaultValue = currentValue = std::to_string(v); }
118
-
119
- Option::operator int() const {
120
- assert(type == "check" || type == "spin");
121
- return (type == "spin" ? stoi(currentValue) : currentValue == "true");
122
- }
123
-
124
- Option::operator std::string() const {
125
- assert(type == "string");
126
- return currentValue;
127
- }
128
-
129
-
130
- /// operator<<() inits options and assigns idx in the correct printing order
131
-
132
- void Option::operator<<(const Option& o) {
133
-
134
- static size_t insert_order = 0;
135
-
136
- *this = o;
137
- idx = insert_order++;
138
- }
139
-
140
-
141
- /// operator=() updates currentValue and triggers on_change() action. It's up to
142
- /// the GUI to check for option's limits, but we could receive the new value from
143
- /// the user by console window, so let's check the bounds anyway.
144
-
145
- Option& Option::operator=(const string& v) {
146
-
147
- assert(!type.empty());
148
-
149
- if ( (type != "button" && v.empty())
150
- || (type == "check" && v != "true" && v != "false")
151
- || (type == "spin" && (stoi(v) < min || stoi(v) > max)))
152
- return *this;
153
-
154
- if (type != "button")
155
- currentValue = v;
156
-
157
- if (on_change)
158
- on_change(*this);
159
-
160
- return *this;
161
- }
162
-
163
- } // namespace UCI