├── Copying.txt
├── README.md
├── pgn
├── GM_games.pgn
├── ambiguous.pgn
├── bali02.pgn
├── chessdoctor.pgn
├── d00_chess_informant.pgn
├── electronic_campfire.pgn
├── europe_echecs.pgn
├── exeter_lessons_from_tal.pgn
├── famous_games.pgn
├── great_masters.pgn
├── hartwig.pgn
├── hayes.pgn
├── human_computer.pgn
├── immortal_games.pgn
├── kramnik.pgn
├── middleg.pgn
├── moscow64.pgn
├── newyork1924.pgn
├── perle.pgn
├── polgar.pgn
├── pon_korch.pgn
├── romero.pgn
├── russian_chess.pgn
├── scarborough_2001.pgn
├── scca.pgn
├── schiller.pgn
└── semicomm.pgn
└── src
├── Makefile
├── benchmark.cpp
├── bitbase.cpp
├── bitboard.cpp
├── bitboard.h
├── endgame.cpp
├── endgame.h
├── evaluate.cpp
├── evaluate.h
├── json.hpp
├── main.cpp
├── material.cpp
├── material.h
├── misc.cpp
├── misc.h
├── movegen.h
├── movepick.cpp
├── movepick.h
├── parser.cpp
├── pawns.cpp
├── pawns.h
├── position.cpp
├── position.h
├── psqt.cpp
├── scout.cpp
├── scoutfish.py
├── search.cpp
├── search.h
├── syzygy
├── tbprobe.cpp
└── tbprobe.h
├── test.py
├── thread.cpp
├── thread.h
├── thread_win32.h
├── timeman.cpp
├── timeman.h
├── tt.cpp
├── tt.h
├── types.h
├── uci.cpp
├── uci.h
└── ucioption.cpp
/README.md:
--------------------------------------------------------------------------------
1 | ## Overview
2 |
3 | Run powerful and flexible queries on **very big chessdatabases** and with **very high speed**.
4 |
5 | Start building an index out of a [PGN](https://en.wikipedia.org/wiki/Portable_Game_Notation) file:
6 |
7 | ./scoutfish make my_big_db.pgn
8 |
9 | Scoutfish will create a file called _my_big_db.scout_ with the needed bits to make
10 | the queries lightning fast. Queries are written in [JSON](https://en.wikipedia.org/wiki/JSON)
11 | format that is human-readable, well supported in most languages and very simple.
12 | Search result will be in JSON too.
13 |
14 | You can run Scoutfish from the command line:
15 |
16 | ./scoutfish scout my_big_db.scout { "sub-fen": "8/8/p7/8/8/1B3N2/8/8" }
17 |
18 | To find all the games that match the given **sub-fen** condition, i.e. all the
19 | games with at least one position with a black pawn in _a6_, a white bishop in
20 | _b3_ and a white knight in _f3_. Output will be like:
21 |
22 | ~~~~
23 | {
24 | "moves": 14922,
25 | "match count": 8,
26 | "moves/second": 3730500,
27 | "processing time (ms)": 4,
28 | "matches":
29 | [
30 | { "ofs": 75129, "ply": [11] },
31 | { "ofs": 80890, "ply": [11] },
32 | { "ofs": 342346, "ply": [13] },
33 | { "ofs": 346059, "ply": [13] },
34 | { "ofs": 375551, "ply": [21] },
35 | { "ofs": 484182, "ply": [29] },
36 | { "ofs": 486999, "ply": [29] },
37 | { "ofs": 536474, "ply": [13] }
38 | ]
39 | }
40 | ~~~~
41 |
42 | After some header, there is a list of matches, each match reports an offset
43 | (in bytes) in the original _my_big_db.pgn_ file, pointing at the beginning of
44 | the matching game and the ply number: this is the number of (half) moves before
45 | reaching the first position in the game that satisfies the given condition.
46 |
47 | In case you call Scoutfish from a higher level tool, like a GUI or a web interface,
48 | it is better to run in interactive mode:
49 |
50 | ~~~~
51 | ./scoutfish
52 | setoption name threads value 8
53 | scout my_big_db.scout { "sub-fen": "8/8/8/8/1k6/8/8/8", "material": "KBNKP" }
54 | scout my_big_db.scout { "white-move": "O-O-O" }
55 | quit
56 | ~~~~
57 |
58 | Scoutfish is strictly derived from [Stockfish](https://stockfishchess.org/) so,
59 | yes, it understands [UCI commands](http://wbec-ridderkerk.nl/html/UCIProtocol.html),
60 | like _setoption_, that we use to increase thread number according to our hardware:
61 | the search speed will increase accordingly!
62 |
63 | Above examples show how to look for a specific **material distribution** and **move**
64 | and how to compose a **multi-rule condition**: a position should satisfy all the rules
65 | to match the condition.
66 |
67 | You are not limited to search for a single _sub-fen_, the following condition:
68 |
69 | { "sub-fen": ["8/8/8/q7/8/8/8/8", "8/8/8/r7/8/8/8/8"] }
70 |
71 | Will find all the positions with a black queen **or** a black rook in a5. There
72 | is no limit to the size of the _sub-fen_ list, enabling to compose very powerful
73 | requests.
74 |
75 | The position **full FEN** is just a special _sub-fen_, so:
76 |
77 | { "sub-fen": ["rnbqkbnr/pp1p1ppp/2p5/4p3/3PP3/8/PPP2PPP/RNBQKBNR",
78 | "rnbqkbnr/pp1ppppp/8/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R"] }
79 |
80 | Will search for all the games with a _Caro-Kann_ or a _Sicilian_ opening.
81 |
82 |
83 | ## Rules
84 |
85 | Rules allow to look for very specific occurrences in the game. We have already
86 | seen some of them, like _sub-fen_, but there are many more.
87 |
88 |
89 | ##### result
90 |
91 | Find all games with a given result in PGN notation, like "1-0" or "1/2-1/2".
92 | Support lists.
93 |
94 | { "sub-fen": "8/pp1p1ppp/2p5/4p3/3PP3/8/PPP2PPP/8", "result": "1-0" }
95 | { "result": ["1-0", "0-1"] }
96 |
97 | To find all white winning games with given sub-fen or all the decided games.
98 |
99 |
100 | ##### result-type
101 |
102 | Find all games with a given result type that can be "mate" or "stalemate".
103 |
104 | { "result": "0-1", "result-type": "mate" }
105 |
106 | To find all games won by black by giving mate.
107 |
108 |
109 | ##### material
110 |
111 | Find all games with a given material distribution, i.e. the given pieces,
112 | no matter where placed. Support lists.
113 |
114 | { "material": ["KBNKNN", "KBNPKNN"] }
115 |
116 | To find all end-games with white Knight and Bishop plus one optional pawn
117 | against two black Knights.
118 |
119 |
120 | ##### imbalance
121 |
122 | Find all games with a given material imbalance. Support lists.
123 |
124 | { "imbalance": ["PPPv", "PPv"] }
125 | { "imbalance": "PPvN" }
126 |
127 |
128 | To find all games with 3 or 2 pawns advantage for white and all games
129 | where white is above 2 pawns but down of a knight.
130 |
131 |
132 | ##### sub-fen
133 |
134 | Find all games with a position matching the sub-fen pattern given in
135 | PGN notation. Support lists.
136 |
137 | { "sub-fen": "1n2k1n1/8/8/8/8/8/8/2B1K1N1", "material": "KBNKNN" }
138 |
139 | To find all games with given sub-fen **and** given material distribution.
140 | Note that the sub-fen is matched by the start position and without the
141 | added rule on material, any game would match. A condition composed by
142 | sub-fen + material, can be used to find an **exact fen**.
143 |
144 |
145 | ##### white-move / black-move
146 |
147 | Find all games with a given move in PGN notation. Support lists.
148 |
149 | {"white-move": "e8=Q"}
150 | {"black-move": ["O-O-O", "O-O"]}
151 | {"black-move": "Rac1"}
152 |
153 | To find all games with white's queen promotion in _e8_ and all games
154 | with a black castling, no matter if long or short. Rule supports
155 | SAN notation with a disambiguation, like _Rac1_.
156 |
157 |
158 | ##### moved / captured
159 |
160 | Find all games with a given moved and/or captured piece. Pieces are listed
161 | in a single string.
162 |
163 | {"moved": "KP", "captured": "Q" }
164 | {"captured": "" }
165 |
166 | To find all games with a queen captured by a king or a pawn and all games
167 | with a quiet move (eventually to be used in a multi-rule condition).
168 |
169 |
170 | ##### stm
171 |
172 | This rule matches the given side to move, that can be "white" or "black"
173 | Usually it is used in a multi-rule condition.
174 |
175 | {"stm": "black", "captured": "QR" }
176 |
177 | To find all games where black side captures a queen or a rook.
178 |
179 |
180 | ##### pass
181 |
182 | This rule matches any position. It is used mainly for debugging purposes or
183 | as a part of a more complex condition (see streaks).
184 |
185 | {"pass": "" }
186 |
187 | To find the number of games in the DB, because it will match any game.
188 |
189 |
190 | ## Sequences
191 |
192 | A _sequence_ is a powerful feature of Scoutfish to look for games that satisfy
193 | more than one condition at *different times in game*. This is very useful in
194 | looking for a piece path from a position. Typical tournament player questions
195 | are: how does one maneuver the bishop in this opening, should we go f1-d3-c2 or
196 | f1-b5-a4. When should we select which maneuver?
197 |
198 | { "sequence": [ { "sub-fen": "r1bqkb1r/pppp1ppp/2n2n2/1B2p3/4P3/2N2N2/PPPP1PPP/R1BQK2R", "result": "1-0" },
199 | { "sub-fen": "8/8/8/8/2B5/8/8/8" },
200 | { "sub-fen": "8/8/8/8/8/5B2/8/8" } ] }
201 |
202 | The above _sequence_ will find all the games won by white, with _Four Knights
203 | Spanish Variation_ opening and with bishop maneuvering to b5-c4-f3.
204 |
205 | A _sequence_ is mainly a list of conditions: a game should match first condition,
206 | then the second one (eventually later in the game) and so on for all the list,
207 | that can be arbitrary long. Output of the search will be like:
208 |
209 | ~~~~
210 | {
211 | "moves": 28796,
212 | "match count": 2,
213 | "moves/second": 5759200,
214 | "processing time (ms)": 5,
215 | "matches":
216 | [
217 | { "ofs": 19054, "ply": [7, 15, 17] },
218 | { "ofs": 20653, "ply": [7, 15, 17] }
219 | ]
220 | }
221 | ~~~~
222 |
223 | Where _ply_ list will show the matching ply for each condition in the sequence.
224 |
225 |
226 | ## Streaks
227 |
228 | A _streak_ is a special kind of sequence. It is defined like a sequence and has
229 | all the sequence properties, but it is different in two key points:
230 |
231 | - Conditions in a streak should be satisfied in consecutive (half) moves
232 | - A streak can appear nested in a bigger, outer sequence
233 |
234 | Mainly a streak is like a sequence but with the added constrain that the conditions
235 | should be satisfied one-by-one along consecutive moves. You may want to use a
236 | streak to look for a white's pawn-down imbalance that should persist for at least
237 | few moves to be sure we are not in the middle of a capture-recapture combination:
238 |
239 | ~~~~
240 | { "streak": [ { "imbalance": "vP" }, { "imbalance": "vP" }, { "imbalance": "vP" } ] }
241 | ~~~~
242 |
243 | From chess perspective, say you want to find games with a clearance sacrifice in
244 | the Benoni for white. Plan of e5, dxe5, followed by f5 and then Ne4 for white.
245 | The first three moves are in a streak, but the last move might be delayed by a
246 | move (but is also played immediately):
247 |
248 | ~~~~
249 | { "sequence": [ { "sub-fen": "rnbqkb1r/pp1p1ppp/4pn2/2pP4/2P5/2N5/PP2PPPP/R1BQKBNR"},
250 | { "streak": [ { "white-move": "e5"}, { "black-move": "dxe5"}, { "white-move": "f5"} ] },
251 | { "white-move": "Ne4"} ] }
252 | ~~~~
253 |
254 | The above sequence, first checks for Benoni opening, then checks for the
255 | **consecutives** e5, dxe5, f5 then finally by the (possibly delayed) Ne4.
256 |
257 | Some rules like _captured_ are very suitable to be used in a streak:
258 |
259 | ~~~~
260 | { "streak": [ { "captured": "" }, { "stm": "white", "captured": "Q" }, { "captured": "" } ] }
261 | { "streak": [ { "white-move": "e5"}, { "pass": "" }, { "white-move": "f5" } ] }
262 | ~~~~
263 |
264 | To find all games where white captures a net queen, i.e. not in a capture-recapture
265 | combination. The second streak uses 'pass' rule to find all games with white _e5_
266 | followed by _f5_, independently from the black reply.
267 |
268 |
269 | ## Python wrapper
270 |
271 | As a typical UCI chess engine, also Scoutfish is not intended to be exposed to the
272 | user directly, eventually a GUI or a web interface will handle the user interaction,
273 | composing the query and later presenting the results in a graphical form, ensuring
274 | a user friendly experience.
275 |
276 | To easy integration with higher level tools, a Python wrapper is provided through
277 | **scoutfish.py** file:
278 |
279 | ~~~~python
280 | from scoutfish import Scoutfish
281 |
282 | p = Scoutfish()
283 | p.setoption('threads', 4) # Will use 4 threads for searching
284 | p.open('my_big.pgn')
285 |
286 | q = {'white-move': 'O-O-O'} # Our query, defined as a simple dict
287 | result = p.scout(q)
288 |
289 | num = result['match count']
290 | print('Found ' + str(num) + ' games')
291 |
292 | # Run again the query but limiting output to max 10 games and skipping
293 | # the first 50 results. This is useful for pagination.
294 | q = {'skip': 50, 'limit': 10, 'white-move': 'O-O-O'}
295 |
296 | result = p.scout(q)
297 | games = p.get_games(result['matches']) # Load the pgn games from my_big.pgn
298 |
299 | for g in games:
300 | print(g['pgn'])
301 |
302 | p.close()
303 | ~~~~
304 |
--------------------------------------------------------------------------------
/pgn/ambiguous.pgn:
--------------------------------------------------------------------------------
1 | [Event "?"]
2 | [White "Spassky"]
3 | [Black "Petrosian"]
4 | [Date "1969.??.??"]
5 | [Result "1-0"]
6 |
7 | {Queen's Gambit Declined (by transposition), 30 moves. Spassky plays an excellent opening and emerges with an advantage. Petrosian, under pressure, allows Spassky to obtain a passed d pawn which decides the game. Petrosian was world champion from 1963-1969; Spassky from 1969-1972.}
8 | 1. c4 {The English opening. White takes possession of d5.}
9 | 1... Nf6 {Developing and attacking the center.}
10 | 2. Nc3 {A natural move.}
11 | 2... e6 {Preparing to play 3... d5. Also playable is 2... e5.}
12 | 3. Nf3
13 | 3... d5
14 | 4. d4 {This position can also arise from the Queen's gambit as follows: 1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3.}
15 | 4... c5 {This variation is called the Semi-Tarrasch Defense.}
16 | 5. cxd5 {If 5... exd5 then Black will end up with an isolated queen pawn.}
17 | 5... Nxd5 {The usual next move for White when this game was played was 6. e3}
18 | 6. e4 $1 {Spassky will demonstrate the strength of the pawn center.}
19 | 6... Nxc3
20 | 7. bxc3
21 | 7... cxd4
22 | 8. cxd4 {White now occupies the center. The question is whether he will be able to use it to advantage or spend all his energy protecting it.}
23 | 8... Bb4+ {The side with less space should strive to exchange pieces.}
24 | 9. Bd2
25 | 9... Bxd2+
26 | 10. Qxd2
27 | 10... 0-0
28 | 11. Bc4 {A natural developing move.}
29 | 11... Nc6 {Developing and beginning to put pressure on White's center.}
30 | 12. 0-0
31 | 12... b6 {The bishop is better placed on b7 then d7.}
32 | 13. Rd1
33 | 13... Bb7
34 | 14. Rfe1 {Developing the last piece.}
35 | 14... Rc8 {Placing the rook on the open file.}
36 | 15. d5 $1 {If here 15... Na5 then Spassky planned 15. Bd3 exd5 16. e5 with a strong attack. White's bishop, knight, and queen all are ready for a kingside attack while Black's pieces are on the other wing.}
37 | 15... exd5
38 | 16. Bxd5 {White's pieces are now very active and it is difficult for Black to find a good defense.}
39 | 16... Na5? {The knight ends up being out of the game. Either 16... Qe7 or 16... Qc7 is better.}
40 | 17. Qf4 $1 {The queen is well placed here, exerting pressure on f7. The threat is Bxf7+ winning the queen.}
41 | 17... Qc7
42 | 18. Qf5 {threatening Ng5. If now 18... h6 then 19. Bxb7 Qxb7 20. Rd7 Rc7 21. Red1 and White's rook on the seventh rank gives him a distinct advantage.}
43 | 18... Bxd5 {This gives White a very strong passed d pawn.}
44 | 19. exd5
45 | 19... Qc2 {White would have a good game after 20. Qxc2 Rxc2 21. Re7 Rxa2 22. Rxa7}
46 | 20. Qf4 {White wants to force a win in the middle game rather than play out a long end game.}
47 | 20... Qxa2
48 | 21. d6 {Nimzovich often spoke of a past pawn's lust to expand.}
49 | 21... Rcd8 {Covering the pawn's queening square.}
50 | 22. d7
51 | 22... Qc4
52 | 23. Qf5 {White threatens 24. Ng5 as well as 24. Rc1 followd by 25. Rc7}
53 | 23... h6
54 | 24. Rdc1 {Now the rook will get to the seventh rank.}
55 | 24... Qa6
56 | 25. Rc7
57 | 25... b5 {Giving the queen a better chance to defend.}
58 | 26. Nd4
59 | 26... Qb6
60 | 27. Rc8 $1 {Black cannot play 27... Qxd4 because of 28. Rxd8 Rxd8 29. Re8+ Rxe8 30. dxe8=Q#. White threatens 28. Re8 Qxd4 29. Rxf8+ Rxf8 29. Rxf8 Kxf8 30. Qc5+ Qxc5 31. d8=Q#.}
61 | 27... Nb7 {Guarding the rook on d8.}
62 | 28. Nc6 $1
63 | 28... Nd6
64 | 29. Nxd8 $1 {A decisive finish.}
65 | 29... Nxf5
66 | 30. Nc6 {Black resigned since White is threatening both 31. Rxf8+ Kxf8 32. Re8# and 31. Rxf8+ Kxf8 32. d8=Q+ Qxd8 33. Nxd8}
67 | 1-0
68 |
69 |
70 | [Event "1st/2nd Prize Corus"]
71 | [Site "?"]
72 | [Date "2008.??.??"]
73 | [Round "?"]
74 | [White "Bazlov, Y. (wh)"]
75 | [Black "[+4146.21c6f6 (bl)"]
76 | [Result "1-0"]
77 | [SetUp "1"]
78 | [FEN "2n1n3/3Qp1RP/2Kb1k1P/8/3q4/6B1/8/8 w - - 0 1"]
79 |
80 | 1. Bh4+ Qxh4 2. Rf7+ Kxf7 3. Qf5+ Qf6 4. Qxf6+ exf6 5. h8=Q Bf8 6. h7 Ne7+
81 | 7. Kd7 Ng7 8. Qg8+ Nxg8 9. h8=N# 1-0
82 |
83 | [Event "IPCCC Paderborn"]
84 | [Date "2006.12.27"]
85 | [White "Ikarus V0.40a"]
86 | [Black "Jonny 2.90"]
87 | [Round "2"]
88 | [Result "0-1"]
89 |
90 | 1.d4 Nf6{(g8f6 tb=0/0)} 2.c4{00:08.078} e6{(e7e6 tb=0/0)} 3.Nf3{00:06.156}
91 | b6{(b7b6 tb=0/0)} 4.g3{00:06.485} Ba6{(c8a6 tb=0/0)} 5.Nbd2{00:06.094}
92 | d5{(d7d5 tb=0/0)} 6.Bg2{00:06.188} Be7{(f8e7 tb=0/0)} 7.O-O{00:07.656}
93 | O-O{(e8g8 tb=0/0)} 8.b3{00:05.985} c5{(c7c5 c1b2 b8c6 d4c5 e7c5 e2e3
94 | tb=0/0) 0.27/15 01:45.094} 9.dxc5{00:08.984} Bxc5{(e7c5 c1b2 b8c6 e2e3
95 | a8c8 d1c2 c8c7 f1d1 c6b4 c2b1 tb=0/0) 0.25/15 00:53.594} 10.Bb2{00:08.172}
96 | Nc6{(b8c6 d1c2 a8c8 e2e3 f6g4 tb=0/0) 0.13/15 03:04.281} 11.Rc1{04:36.468}
97 | Rc8{(a8c8 a2a3 c5e7 c4d5 f6d5 d2e4 d8d7 d1d2 f7f6 f1d1 c6a5 f3d4 e6e5
98 | d4f5 d7f5 d2d5 g8h8 tb=0/0) 0.17/15 02:58.671} 12.a3{11:18.844} Be7 13.cxd5{02:56.969}
99 | Nxd5{(f6d5 d2c4 d5f6 f3g5 d8d1 f1d1 f8d8 d1d8 c6d8 e2e3 f6e8 g5e4 b6b5
100 | c4e5 c8c1 b2c1 f7f6 e5d3 a6b7 c1b2 e6e5 tb=0/0) 0.13/17 02:24.437} 14.b4{04:16.141}
101 | Bf6{(e7f6 b2f6 d8f6 d1a4 a6b7 d2e4 f6e7 e2e3 f7f5 e4d2 e6e5 f1d1 e5e4 a4b3
102 | c6b4 c1c8 f8c8 f3d4 c8c3 d4f5 e7f8 tb=0/0) 0.16/15 02:47.359} 15.Bxf6{01:02.516}
103 | Qxf6{(d8f6 d1a4 a6b7 d2e4 f6e7 e2e3 tb=0/0) 0.10/16 00:27.781} 16.Qa4{03:26.047}
104 | Bb7{(a6b7 d2e4 f6e7 f1d1 f8d8 e2e3 a7a5 b4b5 c6a7 a4b3 c8c1 d1c1 d5f4 e3f4
105 | b7e4 tb=0/0) 0.06/17 00:29.610} 17.Ne4{03:48.172} Qe7{(f6e7 f1d1 f8d8
106 | e2e3 f7f5 e4d2 e7f6 d2c4 d5c3 d1d8 c8d8 a4c2 c3e4 b4b5 c6e7 c1d1 e7g6 d1d8
107 | f6d8 tb=0/0) 0.11/17 00:07.109} 18.Qb3{02:30.703} Nf6{(d5f6 e4f6 e7f6
108 | f1d1 f8d8 b3a4 tb=0/0) 0.09/16 03:30.641} 19.Nxf6{01:29.938} Qxf6{(e7f6
109 | f1d1 f8d8 b3a4 a7a6 d1d8 f6d8 a4d1 d8d1 c1d1 c6b8 f3e1 b7g2 g1g2 g8f8 e2e4
110 | f8e7 f2f4 f7f6 g2f3 tb=0/0) 0.00/17 00:19.312} 20.Rfd1{02:03.813} Rfd8
111 | 21.b5{02:10.078} Na5{(c6a5 c1c8 d8c8 b3d3 f6e7 h2h4 f7f6 g2h3 f6f5 f3e5
112 | e7c5 e5f3 c5c7 f3g5 c7e7 g5e6 e7e6 h3f5 e6e8 f5c8 e8c8 tb=0/0) 0.07/18
113 | 02:45.047} 22.Rxc8{03:30.359} Rxc8 23.Qd3{01:23.157} Qe7{(f6e7 f3e5
114 | b7g2 g1g2 f7f6 e5f3 a5c4 d1c1 e7c5 g2g1 c5d5 f3d4 c4d6 c1c8 d6c8 e2e4 d5a2
115 | f2f4 g8f7 d4c6 tb=0/0) 0.03/18 01:03.781} 24.h4{05:22.891} f6{(f7f6 g2h3
116 | b7d5 e2e4 d5c4 d3d7 c8c7 d7e7 c7e7 f3d4 g8f7 d1c1 e7e8 g1g2 e6e5 d4c6 c4b5
117 | c6a7 b5c4 a7c6 c4b3 c6a5 b6a5 tb=0/0) 0.16/17 01:03.906} 25.Bh3{01:47.359}
118 | Bd5 26.e4{02:17.562} Bc4 27.Qd7{01:31.610} Rc7{(c8c7 d7e7 c7e7 f3d4
119 | e7d7 h3g4 g8f7 g1g2 d7c7 d1c1 c7c5 c1d1 f7e7 tb=0/0) 0.40/19 01:26.312}
120 | 28.Qxe7{01:26.797} Rxe7{(c7e7 f3d4 e7d7 h3g4 g8f7 f2f4 a5b7 e4e5 b7c5
121 | d4c6 d7c7 c6d8 f7g6 d1d6 c4b5 h4h5 g6h6 e5f6 tb=0/0) 0.47/20 00:40.344}
122 | 29.Nd4{03:57.594} Rd7 30.Bg4{04:58.703} Kf7{00:00.016} 31.a4{01:50.937}
123 | Rd6{(d7d6 f2f4 e6e5 f4e5 f6e5 d4f5 d6d1 g4d1 c4e6 g3g4 g7g6 f5e3 a5b3
124 | g1f2 b3d2 d1c2 f7e7 f2e2 d2b3 c2d1 e7d6 h4h5 tb=0/0) 0.75/19 00:58.469}
125 | 32.f4{00:33.891} e5{(e6e5 f4e5 f6e5 d4f5 d6d1 g4d1 c4e6 g3g4 g7g6 f5e3
126 | a5b3 g1f2 b3c5 f2f3 f7e7 h4h5 e7d6 h5g6 h7g6 e3f1 d6c7 tb=0/0) 0.75/20
127 | 00:43.890} 33.fxe5{02:11.844} fxe5 34.Nf5{05:07.594} Rxd1 35.Bxd1{00:07.031}
128 | g6{(g7g6 f5e3 c4d3 d1c2 d3c2 e3c2 f7e6 c2e3 e6d6 g1f2 d6c5 e3g4 a5c4 g4f6
129 | c5d4 f6h7 d4e4 h7f8 e4f5 f8d7 e5e4 d7b8 f5g4 tb=2/180) 1.05/24 04:12.500}
130 | 36.Nd6{00:51.312} Ke7{(f7e7 d6c8 e7d7 c8a7 c4d3 g1f2 d3e4 f2e3 e4f5 tb=0/46)
131 | 1.04/22 01:06.078} 37.Nxc4{06:39.813} Nxc4{(a5c4 d1b3 c4d2 b3g8 d2e4
132 | g8h7 e7f6 h4h5 e4g3 h5g6 g3e2 g1f2 e2f4 g6g7 f6g7 h7c2 g7f6 f2e3 f4e6 e3e4
133 | e6d4 c2d3 f6e6 tb=83/1699) 1.31/24 00:55.156} 38.Bb3{00:44.406} Nd2{(c4d2
134 | b3g8 d2e4 g8h7 e7f6 h4h5 e4g3 h5g6 g3e2 g1f2 e2f4 g6g7 f6g7 h7c2 f4e6 f2e3
135 | e6c5 e3d2 g7f6 d2c3 e5e4 c3d4 f6f5 tb=297/5465) 1.42/24 00:37.343} 39.Bg8{01:43.922}
136 | Nxe4 40.Bxh7{01:40.906} Kf6{(e7f6 h4h5 e4g3 h5g6 g3h5 g1f2 h5f4 f2e3 f4g6
137 | h7g8 g6f4 tb=6847/118788) 1.50/26 01:44.750} 41.h5{01:19.797} Nxg3{(e4g3
138 | h7g6 f6g5 g6f7 g3h5 g1f2 h5f6 f2e3 g5f5 f7b3 e5e4 e3d4 f5f4 b3d1 e4e3 d4d3
139 | tb=31062/1523303) 1.83/27 02:40.875} 42.Bxg6{02:30.735} Kg5{(f6g5 g6f7
140 | g3h5 g1f2 h5f6 f2e3 g5f5 f7c4 e5e4 c4b3 f6g4 e3e2 f5f4 b3c2 e4e3 e2f1 tb=31443/572368)
141 | 2.05/27 00:05.312} 43.Kf2{00:22.750} Nxh5{(g3h5 g6e4 g5f4 tb=17572/395628)
142 | 2.30/26 01:58.766} 44.Bf7{00:43.047} Nf6{(h5f6 f2f3 g5f5 f7a2 tb=4635/75796)
143 | 2.42/24 00:47.078} 45.Ke3{01:05.422} Kf5{(g5f5 f7c4 e5e4 c4a2 f5e5 tb=5514/84196)
144 | 2.71/24 00:56.922} 46.Bc4{02:05.907} e4{(e5e4 c4b3 f5e5 tb=29093/437627)
145 | 2.93/25 02:15.218} 47.Ke2{01:13.954} Ke5{(f5e5 c4a2 e5d4 a2b3 tb=14097/268343)
146 | 3.37/23 00:57.609} 48.Kd2{00:47.703} Nd5{(f6d5 c4b3 e5d4 b3c2 d5e3 c2b3
147 | e3c4 d2e2 c4b2 b3c2 e4e3 c2b3 b2d3 b3c2 d3f4 e2d1 tb=14100/212997) 3.41/23
148 | 01:25.500} 49.Bb3{00:32.875} Kd4{(e5d4 b3c2 d5e3 c2b3 e3c4 d2e2 c4b2
149 | b3c2 tb=30403/361794) 3.41/24 01:15.188} 50.Bd1{00:47.812} e3{(e4e3 d2e1
150 | d4d3 d1g4 d3e4 tb=21892/263876) 3.63/24 01:34.687} 51.Ke1{02:43.969}
151 | Nf4{(d5f4 d1g4 d4c3 tb=85865/1117783) 3.88/24 02:13.937} 52.Bc2{01:47.922}
152 | Kc3{(d4c3 c2e4 c3b3 e4b7 b3c2 b7c8 c2d3 c8f5 d3c4 f5d7 c4b4 tb=67090/749863)
153 | 3.97/25 05:16.907} 53.Be4{00:20.468} Kb3{(c3b3 e4b7 b3a4 tb=32182/425409)
154 | 4.97/24 06:00.625} 54.Bc6{01:04.359} Kxa4{(b3a4 c6e8 a4b4 e8d7 b4c3 d7g4
155 | e3e2 g4f5 tb=3639/67429) 5.70/20 00:40.344} 55.Bd7{00:08.922} Kb4{(a4b4
156 | e1d1 b4c3 d7f5 e3e2 d1e1 c3c4 e1d2 c4b5 f5d7 b5b4 d7e8 tb=7192/158536)
157 | 5.59/19 02:43.656} 56.Kd1{04:32.282} Kc3{00:41.578} 57.Bf5{01:11.859}
158 | e2{(e3e2 d1e1 c3c4 f5h7 c4b5 e1d2 a7a5 h7g8 a5a4 d2e1 b5b4 tb=13624/221488)
159 | 7.15/19 02:12.312} 58.Ke1{00:19.594} Kc4{(c3c4 f5h7 c4b5 tb=20578/289546)
160 | 7.40/19 01:54.078} 59.Kd2{02:27.266} Kxb5{(c4b5 f5d7 b5c5 tb=5528/84512)
161 | 10.66/19 04:32.297} 0-1
162 |
--------------------------------------------------------------------------------
/pgn/d00_chess_informant.pgn:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcostalba/scoutfish/00cec1339f97114a32c30080dbad5e3a500634f2/pgn/d00_chess_informant.pgn
--------------------------------------------------------------------------------
/pgn/exeter_lessons_from_tal.pgn:
--------------------------------------------------------------------------------
1 | [Event "Olympic games"]
2 | [Site "Munchen"]
3 | [Date "1958"]
4 | [White "Walther"]
5 | [Black "Tal,M"]
6 | [Result "0-1"]
7 | [Source "Exeter Chess Club"]
8 | [Annotator "DrDave"]
9 |
10 | {Natural moves in the opening}
11 | 1. e4 c5 2. Ne2 Nf6 3. d3 Nc6 4. Nd2
12 | {
13 | So many words have been written about Tal that my own observations are perhaps rather superfluous. The brilliance of his play and the dramatic way his wins are often achieved are apparent to all.
14 | For tonight's session, and with their instructional content in mind, I would just like to add that it was interesting to me how some of his most striking wins are introduced by apprently simple means - not striving for complications but building up with classically good moves. This may be partly a reflection of how familiar the GM play of the 1950s is to a club player of the 1990s - the Modern Benoni was by no means a staple when Tal played it - but nonetheless you feel that Capablanca would have chosen many of Tal's moves, even if he would have tried to reach a decision by different means.
15 | Most curious. It is not unusual to develop one or other Knight to the second rank, but both at once, and before developing either Bishop, is very odd. Any advantage Walther saw in getting Tal out of the books is outweighed by the unnatural formation and the need to get his pieces untangled. Tal does not strike immediately, but develops quietly, waiting for a suitable moment to arise.
16 | }
17 | 4... d5 5. c3 dxe4 6. dxe4 g6 7. Qc2 Bg7 8. a4 $2 O-O 9. Nc4 $2 Na5 10. Nf4
18 | {
19 | White is trying to get sorted but is a long way from castling. Tal gives White's formation a sharp push, and after some wobbling, it collapses.
20 | }
21 | 10... e5 $1 11. Nd5 Nxe4 12. Qxe4 Nb3 13. Ra3 Bf5 14. Qe3 Nxc1 15. Qxc5 Re8 16. Qe3
22 | {
23 | On "body count" Black is a bare Pawn up, but as Bill Hartston says, its the pieces on the board that count, and White's are horribly uncoordinated.
24 | }
25 | 16... Bf8 17. Nb4 a5 18. Nxa5 Qxa5 19. Qxc1 Bxb4 20. cxb4 Qxb4+ 21. Rc3 Qe4+ 22. Be2 Rxa4 23. f3 Qb4 24. g4 e4 $1
26 | {
27 | Properly opening up lines against White's uncastled King.
28 | }
29 | 25. f4 Ra2 $1 26. gxf5 Rxb2 27. O-O $1
30 | {
31 | At last! But Black's nicely centralised and active forces are still in control.
32 | }
33 | 27... Rxe2 28. Rc8 Qb6+ 29. Kh1 Rxc8 30. Qxc8+ Kg7 31. fxg6 hxg6 32. f5 Qf6 33. Qxb7 Qe5
34 | 0-1
35 |
36 | [Event "ch-SU"]
37 | [Site "Riga"]
38 | [Date "1958"]
39 | [White "Averbakh"]
40 | [Black "Tal,M"]
41 | [Result "0-1"]
42 | [Source "Exeter Chess Club"]
43 | [Annotator "DrDave"]
44 |
45 | {Trying to refute an opponent's opening}
46 | 1. d4 Nf6 2. c4 e6 3. Nc3 c5 4. d5 exd5 5. cxd5 d6 6. e4 g6 7. Be2 Bg7 8. Nf3 O-O 9. O-O Re8
47 | {
48 | So far, so typical of the Modern Benoni. At the time this formation was still considered rather suspect (and maybe it still is in some circles), so Averbakh adopts a very active plan to 'punish' this cheeky opening, targeting d6.
49 | }
50 | 10. Qc2 Na6 11. Bf4 Nb4 12. Qb1
51 | {
52 | White's formation is just for the moment in need of a few moves for perfect comfort. Tal decides the time to strike is now!
53 | }
54 | 12... Nxe4 13. Nxe4 Bf5 14. Nfd2 Nxd5
55 | {
56 | This sacrifice of a Knight for central Pawns is seen repeatedly in Tal's play, and his practical results have been excellent.
57 | }
58 | 15. Bxd6?!
59 | (15. Bg3 {e.g.} 15... Qe7 16. Bf3 Rad8)
60 | 15... Nf6 16. Bf3 Nxe4 17. Nxe4 Bxe4 18. Bxe4 Qxd6
61 | {
62 | The scrapping has led to a winning position for Black. Opposite coloured Bishops only draw if they are the only things on the board!
63 | }
64 | 19. Qc2 Re7 20. Bf3 Rae8 21. Rad1 Bd4 22. a4 b6 23. b3 Re5 24. Rd2 h5 25. Re2 Rxe2 26. Bxe2 h4 27. Kh1 Qf4 28. g3 Qf6 29. Qd1 Rd8 30. Bg4 Bxf2 31. Qe2 Rd2 32. Qe8+ Kh7 33. gxh4 Qd4 34. Bh3 Qd3 35. Bg2 Rd1
65 | 0-1
66 |
67 | [Event ""]
68 | [Site "Riga"]
69 | [Date "1954"]
70 | [White "Saigin"]
71 | [Black "Tal,M"]
72 | [Result "0-1"]
73 | [Source "Exeter Chess Club"]
74 | [Annotator "DrDave"]
75 |
76 | {Natural moves in the middlegame}
77 | 1. d4 Nf6 2. c4 c5 3. Nf3 e6 4. g3 cxd4 5. Nxd4 d5 6. Bg2 e5 7. Nf3 d4 8. O-O Nc6 9. e3 $5 Be7 10. exd4 exd4 11. Nbd2 Be6
78 | {
79 | White has allowed Black a passed Pawn, hoping that it will become weak.
80 | }
81 | 12. Re1 O-O 13. b3 Qd7 14. Bb2 Rad8 15. a3 a5 16. Ne5 Nxe5 17. Rxe5 b6 18. Nf3 Bc5 19. Qd2 Ng4 20. Ree1 d3 21. Rf1
82 | {
83 | Black has a nice position, but what to do next?
84 | }
85 | 21... Qd6
86 | {
87 | "Such quiet and apparently non-constructive moves are among the finest and most difficult to find in a game of chess." - Clarke.
88 | }
89 | 22. Qc3
90 | (22. b4 axb4 23. axb4 Bxb4)(22. h3 Nxf2 23. Rxf2 Qxg3)
91 | 22... f6 23. Rad1 Rfe8 24. Rd2 Bf5 25. Ng5
92 | {
93 | Surely Black's position has reached its peak of potential. All we need now is a way of translating the good position into a decisive tactical blow - and of that art Tal has always been a master.
94 | }
95 | 25... Ne3 $3 26. fxe3
96 | (26. Re1 Nxg2 27. Rxe8+ Rxe8 28. Kxg2 Qc6+ 29. f3
97 | (29. Nf3 Be4)
98 | 29... Re1)
99 | 26... Bxe3+ 27. Kh1
100 | (27. Rff2 Bxf2+ 28. Kxf2 Qc5+ 29. Kf1 Re1+ 30. Kxe1 Qg1+ 31. Bf1 Re8+)(27. Rdf2 Bxf2+ 28. Rxf2
101 | (28. Kxf2 Qc5+)
102 | 28... d2 29. Bd5+ Qxd5 30. cxd5 d1=Q+)
103 | 27... Bxd2 28. Qxd2 Re2 29. Qc3 Rxg2
104 | (29... Rxg2 30. Kxg2 d2 31. Rd1 Bg4 32. Nf3 Qd3)
105 | 0-1
106 |
107 | [Event "23rd USSR ch"]
108 | [Site ""]
109 | [Date "1956"]
110 | [White "Tal,M"]
111 | [Black "Simagin"]
112 | [Result "1-0"]
113 | [Source "Exeter Chess Club"]
114 | [Annotator "DrDave"]
115 |
116 | {A real sacrifice}
117 | 1. e4 c6 2. d4 d6 3. Nc3 Nf6 4. f4 Qb6 5. Nf3 Bg4 6. Be2 Nbd7 7. e5 Nd5 8. O-O Nxc3 9. bxc3
118 | 9... e6
119 | (9... Bxf3 10. Bxf3 dxe5 11. fxe5 Nxe5 12. Ba3)
120 | 10. Ng5 Bxe2 11. Qxe2 h6
121 | 12. Nxf7
122 | {
123 | Easy to see, hard to play! Simagin undoubtedly expected this move and was deliberately inviting it, judging that Tal was bluffing. Bravery from both players, then!
124 | Spielmann calls this type of move a 'real' sacrifice as opposed to those sacrificial combinations where the hoped-for gain is clear and short- term. We have seen already a Tal sacrifice in the game against Averbakh where the omens may have been good but the precise justification was not obvious.
125 | }
126 | 12... Kxf7 13. f5 dxe5 14. fxe6+ Kxe6 15. Rb1 Qxb1 16. Qc4+ Kd6 17. Ba3+ Kc7 18. Rxb1 Bxa3 19. Qb3 Be7 20. Qxb7+ Kd6
127 | 21. dxe5+ (21. Rd1 $1 $18) Nxe5 22. Rd1+ Ke6 23. Qb3+ Kf5 24. Rf1+
128 | 24... Ke4
129 | (24... Kg6 25. Qe6+ Bf6 26. Qf5+ Kf7 27. Qxe5)
130 | 25. Re1+ Kf5 26. g4+ Kf6 27. Rf1+ Kg6 28. Qe6+ Kh7 29. Qxe5 Rhe8 30. Rf7 Bf8 31. Qf5+ Kg8 32. Kf2 Bc5+ 33. Kg3 Re3+ 34. Kh4 Rae8 35. Rxg7+ Kxg7 36. Qxc5 R8e6 37. Qxa7+ Kg6 38. Qa8 Kf6 39. a4 Ke5 40. a5 Kd5 41. Qd8+ Ke4 42. a6 Kf3 43. a7 Re2 44. Qd3+ R6e3 45. Qxe3+
131 | 1-0
132 |
133 | [Event "ch-SU"]
134 | [Site "Moskva"]
135 | [Date "1957"]
136 | [White "Aronson"]
137 | [Black "Tal,M"]
138 | [Result "0-1"]
139 | [Source "Exeter Chess Club"]
140 | [Annotator "DrDave"]
141 |
142 | {Mixing it}
143 | 1. d4 e6 2. c4 f5 3. Nf3 Nf6 4. Nc3 Be7 5. g3 O-O 6. Bg2 d6 7. O-O Qe8 8. Re1 Qg6 9. e4 fxe4 10. Nxe4 Nxe4 11. Rxe4 Nc6 12. Qe2 Bf6 13. Bd2 e5 14. dxe5 dxe5 15. Bc3 Bf5 16. Nh4 Bxh4 17. Rxh4 Rae8
144 | {
145 | Tal's position looks OK but White's position also has virtues. The game now enters a scrappy phase where Tal's formidable powers of imagination and calculation shine.
146 | }
147 | 18. Qe3 h6 19. b4 $1 Qf6 20. b5 Nd8 21. Bd5+ Kh8 22. f4 $2 exf4 $1 23. Qd2
148 | {
149 | Just when White might have thought he was getting somewhere...
150 | }
151 | 23... Qb6+ $1 24. Bd4 Qg6 25. Qxf4
152 | (25. Rxf4 Ne6 26. Bxe6 Bxe6)
153 | 25... Kh7 $1 26. Qxc7
154 | (26. Qd2)
155 | 26... Bb1 27. Be5 Ne6 28. Qd6 Qf5 29. Bf4 Ng5 30. Qb4 Be4 31. Bxe4 Rxe4 32. Rf1 Re2 33. Qd6 Rxa2 34. Qd5 Qc2 35. c5 Rd8! 36. Bd6 Re8 $1
156 | (36... Re8 37. Qf5+ Qxf5 38. Rxf5 Re1+ 39. Rf1 Nf3+)
157 | {time}
158 | 0-1
159 |
160 | [Event "sf-ch-SU"]
161 | [Site "Tbilisi"]
162 | [Date "1956"]
163 | [White "Tal,M"]
164 | [Black "Yukhtman"]
165 | [Result "1-0"]
166 | [Source "Exeter Chess Club"]
167 | [Annotator "DrDave"]
168 |
169 | {Outside passed Pawn}
170 | 1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 a6 6. Bg5 Nbd7 7. Bc4 h6 8. Bxf6 Nxf6 9. Qe2 e6 10. a3 Be7 11. Bb3 Bd7 12. O-O Qa5 13. Rad1 Qh5 14. Qe1
171 | 14... g5 $2 15. e5 $1 Ng4 16. Nf3 Bc6 17. Bd5 $1 Nxe5 18. Nxe5 exd5 19. Nxd5 $1 Bxd5 20. Rxd5 dxe5 21. Rxe5 O-O 22. Rxe7
172 | {
173 | Peter Clarke remarks that drawing chances in major piece endings depend on (1) exposed opponent's King, (2) possession of an advanced or passed Pawn, and (3) weak enemy Pawns. Black has none of these!
174 | }
175 | 22... Rac8 23. Qe4 b5 24. Re1 Rcd8 25. c4 $1 bxc4 26. Qxc4 Qg6 27. Ra7 Rfe8 28. Rxe8+ Rxe8 29. g3 Re6 30. Kg2 Rf6 31. Ra8+ Kh7 32. Rd8 $1
176 | {
177 | Deliberately inviting...
178 | }
179 | 32... Rxf2+ 33. Kxf2 Qf6+ 34. Ke3 Qxd8 35. Qd3+ Qxd3+ 36. Kxd3
180 | {
181 | Tal had of course had foreseen this simple win: the outside passed Pawn wins.
182 | }
183 | 36... Kg6 37. Ke4 Kf6 38. g4 $1 Ke6 39. b4 h5 40. gxh5 f5+ 41. Kd4 Kf6 42. a4 g4 43. b5
184 | 1-0
185 |
186 | [Event ""]
187 | [Site ""]
188 | [Date "1956"]
189 | [White "Tal,M"]
190 | [Black "Lisitsin"]
191 | [Result "1-0"]
192 | [Source "Exeter Chess Club"]
193 | [Annotator "DrDave"]
194 |
195 | {Active King in the Ending}
196 | 1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 g6 6. f4 Nc6 7. Nxc6 bxc6 8. e5 Nd7 9. exd6 exd6 10. Be3 Be7 11. Qf3 d5 12. O-O-O Bf6 13. Bd4 O-O 14. h4 Rb8 15. Qf2 Rb4 16. Bxf6 Nxf6 17. a3 Qb6 18. Qxb6 Rxb6 19. Na4 Rb7 20. Bd3 Nh5 21. Rhf1 Re7
197 | {
198 | How to save the f-pawn?
199 | }
200 | 22. f5 $1
201 | {
202 | Can't be done, but Tal gives it up for a high price - scrambled pawns.
203 | }
204 | 22... gxf5 23. Rfe1 Rfe8 24.Rxe7 Rxe7 25. Kd2
205 | {
206 | In Exeter we say "KUFTE!" (King Up For The Endgame!)
207 | }
208 | 25... Ng3 26. Kc3 f4 27. Kd4 Bf5
209 | {
210 | And there it is, nicely posted in the middle of a lot of weak Black pawns.
211 | }
212 | 28. Rd2 Re6 29. Nc5 Rh6 30. Ke5 $1 Bxd3 31. cxd3 Rxh4 32. Kd6 Rh6+ 33. Kc7 Nf5 34. Kb7 Nd4 35. Rf2 a5 36. Rxf4 Ne6 37. Rg4+ Kf8
213 | {
214 | The game is decided all in the position of the two Kings.
215 | }
216 | 38. Kxc6 $1 38... Nxc5+ 39. Kxc5 Re6 40. Kxd5 Rb6 41. b4 axb4 42. axb4 Ke7
217 | {
218 | Too late
219 | }
220 | 43. Kc5 Rf6 44. Rd4 Rf5+ 45. Kb6 Rf6+ 46. Kc7 Rf5 47. Re4+ Kf6 48. Kc6 Rf2 49. g4 h5 50. gxh5 Kg5 51. b5 f5 52. Rb4 f4 53. b6 f3 54. b7
221 | (54. b7 Rc2+ 55. Kd5 f2 56. b8=Q f1=Q 57. Qg3+ Kf6 58. Qe5+ Kf7 59. Rb7+ Rc7 60. Rxc7+ Kf8 61. Qh8#)
222 | 1-0
223 |
224 | [Event "WM"]
225 | [Site "Varna tt stud"]
226 | [Date "1958"]
227 | [White "Tal,M"]
228 | [Black "Djurasevic"]
229 | [Result "1-0"]
230 | [Source "Exeter Chess Club"]
231 | [Annotator "DrDave"]
232 |
233 | {Activity of the pieces}
234 | 1. e4 c5 2. Nf3 Nc6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 d6 6. Bg5 e6 7. Qd2 a6 8. O-O-O h6 9. Bf4 Bd7 10. Nxc6 Bxc6 11. f3 Qb6 12. Bc4 O-O-O 13. Be3 Qc7 14. Qf2 Nd7 15. f4 b5 16. Be2 Qb7 17. a3 $1 Be7 $2
235 | {
236 | This apparently safe developing move is not to the point.
237 | }
238 | (17... Nf6)
239 | 18. Bf3 Nf6 19. e5 Ne4 20. Nxe4 Bxe4 21. Bxe4 Qxe4
240 | 22. Bb6 $1 Rd7 23. Rhe1 Qb7 24. exd6 Rxd6 25. Rxd6 Bxd6 26. Qd4 Bc7
241 | {
242 | White can grab the pawn on g7, but... Purdy talks about 'contempt for Pawns' - what is more important is to keep active.
243 | }
244 | 27. Bxc7 $1
245 | {
246 | "The most important feature of each phase of the game is the activity of the pieces." - Stean.
247 | }
248 | (27. Qxg7 Bxf4+ 28. Kb1 Re8 29. g3 {when Black's active pieces have counterplay.})
249 | 27... Qxc7 28. Rd1 Rd8
250 | {
251 | Biting the bullet!
252 | }
253 | (28... Qc4 29. Qxc4+ bxc4 30. Rd4)(28... f6 29. Qd6)(28... Rg8 29. Rd3 Kb8 30. Rc3 Qd8 31. Qc5 Qd7 32. Qb6+ Qb7 33. Qd6+ Ka8 34. Rc6)(28... Kb8 29. Rd3 Rc8 30. Rc3 Qb7 31. Rxc8+ Qxc8 32. Qxg7)
254 | 29. Qxd8+ Qxd8 30. Rxd8+ Kxd8 31. Kd2 Kd7 32. Kd3 Kd6
255 | {
256 | The exchanges have led to a position in which Tal again has a Queen's-side majority, but this is by no means a simple win because of the "outside" candidate. The reason this position is won is because the White Queen's-side majority is 3:2 as opposed to 4:3. This simpler formation can yield a passed Pawn more quickly.
257 | }
258 | 33. c4 bxc4+
259 | (33... Kc6 {passive defence} 34. Kd4 bxc4 35. Kxc4 Kd6 36. b4 Kc6 37. a4 Kb6 38. b5 axb5+ 39. axb5 g5 40. fxg5 hxg5 41. h3 f6 42. g3 f5 43. Kd3 Kxb5 44. h4)(33... e5 {counterattack} 34. fxe5+ Kxe5 35. cxb5 axb5 36. b3 Kd5 37. a4 bxa4 38. bxa4 Kc5 39. Ke4 Kb4 40. Ke5 Kxa4 41. Kd6 Kb5 42. Ke7)
260 | 34. Kxc4 e5 35. fxe5+ Kxe5 36. b4 f5 37. b5 axb5+ 38. Kxb5
261 | 38... f4 39. a4 g5 40. a5 g4
262 | (40... Kd6 41. Kc4 Kc6 42. Kd4 Kb5 43. Ke4 Kxa5 44. Kf5 Kb5 45. h3)
263 | 41. Kc4 $1
264 | (41. Kc4 $1 Ke4
265 | (41... f3 42. gxf3 gxf3 43. Kd3)(41... Kd6 42. Kd4)
266 | 42. a6 f3 43. a7 f2 44. a8=Q+)
267 | 1-0
268 |
269 |
--------------------------------------------------------------------------------
/pgn/hartwig.pgn:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcostalba/scoutfish/00cec1339f97114a32c30080dbad5e3a500634f2/pgn/hartwig.pgn
--------------------------------------------------------------------------------
/pgn/human_computer.pgn:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcostalba/scoutfish/00cec1339f97114a32c30080dbad5e3a500634f2/pgn/human_computer.pgn
--------------------------------------------------------------------------------
/pgn/perle.pgn:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcostalba/scoutfish/00cec1339f97114a32c30080dbad5e3a500634f2/pgn/perle.pgn
--------------------------------------------------------------------------------
/pgn/romero.pgn:
--------------------------------------------------------------------------------
1 | [Event "FIDE Wch KO"]
2 | [Site "Moscow"]
3 | [Date "2001.12.05"]
4 | [Round "4.4"]
5 | [White "Ponomariov, R."]
6 | [Black "Morozevich, A."]
7 | [Result "1-0"]
8 | [ECO "C78"]
9 | [WhiteElo "2684"]
10 | [BlackElo "2742"]
11 | [Annotator "GM Alfonso Romero Holmes"]
12 | [PlyCount "88"]
13 | [EventDate "2001.11.27"]
14 | [Source "Mikhail Golubev"]
15 | [SourceDate "2002.01.08"]
16 |
17 | 1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Bc5 6. c3 b5 7. Bb3 d6 8. a4
18 | Bg4 (8... Rb8 9. axb5 axb5 10. d4 Bb6 11. Na3 Bg4 12. Nxb5 O-O) 9. h3 Bxf3 10.
19 | Qxf3 O-O 11. a5 $1 (11. d3 Na5 12. Bc2 b4 13. Nd2 Rb8) 11... Rb8 12. d3 Nd7 13.
20 | Nd2 (13. Be3 Kh8 14. Nd2 14... Ne7 {Kasparov-Anand, Wijk aan Zee 2001}) 13...
21 | Kh8 14. Kh1 Ne7 15. Qe2 { } 15... h6 (15... f5 16. Nf3 (16. exf5 Nxf5 17. Ne4))
22 | 16. f4 Ng6 (16... exf4 17. d4 Ba7 18. Rxf4) 17. f5 Nf4 18. Qf3 18... Nf6 { }
23 | 19. Bc2 (19. Nb1 b4 (19... g5 20. fxg6 fxg6 21. d4 (21. g3 $5) 21... Ba7 22. g3
24 | ) 20. Bc4 d5 21. exd5 bxc3 22. bxc3) 19... g5 20. fxg6 fxg6 21. Nb3 21... Nd7 {
25 | } 22. Bxf4 $1 22... Rxf4 23. Qe2 Ba7 (23... Qh4 24. Rxf4 exf4 (24... Qxf4 25.
26 | Rf1 Qh4 26. Rf7) 25. d4 $1 (25. Nxc5 dxc5 26. Rf1 Nf6) 25... Ba7 26. Rf1 c6 27.
27 | Qf3 g5 28. e5 $1) 24. Rxf4 exf4 25. Qg4 g5 26. d4 $16 { } 26... Nf6 27. Qe6 Qf8
28 | 28. e5 Nh5 29. exd6 29... Qxd6 { } (29... cxd6 30. Qd7) 30. Qxd6 (30. Re1)
29 | 30... cxd6 31. Re1 Rf8 32. Re7 Bb8 33. Nd2 Ng7 (33... Nf6 34. Rb7 Re8 35. Nf3
30 | Nd5 36. Rh7+ Kg8 37. Rxh6 Re2 38. Rg6+ Kf8 39. Bb3 Ne7 40. Rf6+) 34. Nf3 Re8
31 | 35. Rb7 d5 36. Rb6 { } 36... h5 37. Bg6 Rc8 38. Nxg5 f3 39. gxf3 Bf4 40. h4 Bc1
32 | 41. Rxa6 Bxb2 42. Bf7 Ne8 (42... Nf5 43. Ra7 (43. Be6 Rf8 44. Ra7 Ng7) 43...
33 | Ng7 44. Bxd5 Bxc3 45. Nf7+ Kh7 46. Be4+ Kg8 47. Nd6) 43. Rg6 Nc7 44. Rc6 Ra8
34 | 1-0
35 |
36 | [Event "FIDE Wch KO"]
37 | [Site "Moscow"]
38 | [Date "2001.??.??"]
39 | [Round "5.5"]
40 | [White "Ivanchuk, V."]
41 | [Black "Lautier, J."]
42 | [Result "1-0"]
43 | [ECO "E15"]
44 | [WhiteElo "2730"]
45 | [BlackElo "2650"]
46 | [Annotator "GM Alfonso Romero Holmes"]
47 | [PlyCount "103"]
48 | [EventDate "2001.11.27"]
49 | [Source "Mikhail Golubev"]
50 | [SourceDate "2002.01.08"]
51 |
52 | 1. d4 Nf6 2. c4 e6 3. Nf3 b6 4. g3 Ba6 5. b3 Bb4+ 6. Bd2 Be7 7. Nc3 O-O 8. Qc2
53 | (8. Bg2 8... c6 $1) 8... d5 9. cxd5 9... exd5 { } (9... Nxd5 10. Bg2 Nd7 11.
54 | O-O c5 12. Rfd1 Rc8 13. Qb2 Bb7 14. e4 $1 {
55 | Ivanchuk-Ehlvest, Tallinn rpd 2000; Topalov-Karpov, Monaco rpd 2001}) 10. Bh3
56 | $5 10... c5 11. O-O Nc6 12. Be3 Re8 13. Rfd1 h6 14. Rac1 c4 15. Ne5 Na5 16.
57 | bxc4 16... Nxc4 { } 17. Qa4 $6 (17. Bf4 $1 17... Bd6 (17... b5 18. e4 $5) 18.
58 | Qa4 Bc8 19. Bg2 Nxe5 20. dxe5 Bd7 21. Qa6 $5 (21. Qd4 Bc5 22. Qd3)) 17... Nxe3
59 | 18. fxe3 Bb7 19. Nb5 19... Bd6 { } 20. Nd7 $5 (20. Nxd6 Qxd6 21. Rf1 Re7 22.
60 | Bf5 Rc7) 20... Qe7 21. Rd3 (21. Nxf6+ Qxf6 22. Nc7 Qe7 (22... Bxc7 $5 23. Rxc7
61 | Re7) 23. Nxa8 Qxe3+ 24. Kh1 24... Bxa8 $44) (21. Nxd6 Qxd6 22. Nxf6+ Qxf6 23.
62 | Rc7 Re7 24. Bd7 $5 { } 24... Qg5 $1 25. Rf1 Bc8 26. Qc6 Rxd7 27. Rxd7 Qxe3+ 28.
63 | Rf2 Bxd7 29. Qxa8+ Kh7 30. Qxd5 Bh3) 21... Nxd7 $6 (21... Ne4 22. Nxd6 Qxd6 23.
64 | Qa3 Bc8 24. Qxd6 Nxd6 25. Rc6 Nc4 26. Rc3 Bxd7 27. Bxd7 Re7 28. Bf5 g6 29. Bd3
65 | Nxe3 30. h3 $11) 22. Nxd6 Qxd6 23. Qxd7 Qxd7 24. Bxd7 Re7 25. Bb5 { } 25... Rd8
66 | $2 (25... a6 26. Ba4 b5 27. Bb3 b4 28. Rc5 Rd8 29. Kf2 Rd6 30. Ba4 $14 (30. Rd2
67 | Rf6+ 31. Ke1 Rxe3 32. Bxd5 Bxd5 33. Rxd5 $11)) 26. Rdc3 Rd6 27. Rc7 27... Rde6
68 | { } 28. Bd7 Rd6 29. Bf5 Rxc7 30. Rxc7 g6 (30... Ba6 31. Rxa7 g6 32. Bxg6 fxg6
69 | 33. Rxa6 $18) 31. Bd3 $1 31... Bc6 32. Rxa7 Bd7 33. Kf2 Kg7 34. Ke1 Bh3 35. Kd2
70 | Rf6 36. Rb7 h5 37. a4 g5 38. e4 dxe4 39. Bxe4 $18 39... h4 40. gxh4 gxh4 41.
71 | Bf3 Kg6 42. Ke3 Bf5 43. Rc7 Re6+ 44. Kd2 Be4 45. Bxe4+ Rxe4 46. Kd3 Rg4 47.
72 | Rc6+ Kg5 48. Rxb6 Rg2 49. a5 Rxh2 50. a6 Rh3+ 51. e3 Rh2 52. Rb5+ {( 53.Ra5)}
73 | 1-0
74 |
75 | [Event "FIDE Wch KO"]
76 | [Site "Moscow"]
77 | [Date "2001.12.11"]
78 | [Round "6.3"]
79 | [White "Svidler, P."]
80 | [Black "Ponomariov, R."]
81 | [Result "0-1"]
82 | [ECO "C43"]
83 | [WhiteElo "2686"]
84 | [BlackElo "2684"]
85 | [Annotator "GM Alfonso Romero Holmes"]
86 | [PlyCount "88"]
87 | [EventDate "2001.11.27"]
88 | [Source "Mikhail Golubev"]
89 | [SourceDate "2002.01.08"]
90 |
91 | 1. e4 e5 2. Nf3 Nf6 3. d4 Nxe4 4. Bd3 d5 5. Nxe5 Nd7 6. Nxd7 Bxd7 7. O-O Bd6 8.
92 | c4 c6 9. cxd5 cxd5 10. Nc3 Nxc3 11. bxc3 O-O 12. Qh5 f5 (12... g6 13. Qxd5 Qc7
93 | 14. Qf3 $5 14... Bxh2+ 15. Kh1 Bd6 16. c4 {Rublevsky-Vallejo, Ech 2001}) 13.
94 | Re1 (13. Qf3 13... Kh8 $1 14. Bf4 Qc7 15. Bxd6 Qxd6 16. Rfe1 16... Rfe8 $11)
95 | 13... Qc7 14. Bd2 Rae8 15. Bc2 g6 16. Qf3 { } (16. Qh4) 16... Re4 $1 17. g3 (
96 | 17. Bxe4 fxe4 18. Qe2 Bxh2+ 19. Kh1 Rf5) 17... Bb5 18. Bf4 { } (18. Bxe4 fxe4
97 | 19. Qg4 Rf5 (19... Bd7 $2 20. Qd1 Qc8 21. Qb3)) 18... Bxf4 19. gxf4 Qd6 20.
98 | Bxe4 fxe4 21. Qg3 Rxf4 22. Rab1 Bd7 23. f3 b6 (23... exf3 24. Kf2) 24. Re3
99 | 24... Qf6 { } (24... exf3 25. Kf2 Bf5 26. Re8+ Kg7 27. Rbe1 Be4 28. c4) 25. Rf1
100 | $2 (25. Rbe1 h5) (25. Rb2 25... h5 (25... exf3 26. Kf2) 26. Rf2 h4 27. Qg2 Bf5
101 | 28. h3 (28. Rf1 h3 29. Qe2 29... Qg5+ $1) 28... b5 29. fxe4 Bxe4 30. Rxf4 Qxf4
102 | 31. Qf2 Qg5+ 32. Kh2) 25... Bg4 26. Qxg4 Rxg4+ 27. fxg4 Qg5 28. Rg3 28... b5 {
103 | } 29. Rf2 Kg7 30. Kg2 a5 31. Rb2 b4 32. cxb4 axb4 33. h3 Qc1 34. Rgb3 34... Kh6
104 | $1 35. Rxb4 Qd1 36. Kf2 Kg5 37. Re2 { } 37... Kf4 $19 38. Rb3 Qxd4+ 39. Kg2 Qc4
105 | 40. Rf2+ Kg5 41. Rf7 d4 42. h4+ Kxh4 43. Rxh7+ Kxg4 44. Rg3+ Kf5 0-1
106 |
107 | [Event "FIDE Wch KO"]
108 | [Site "Moscow"]
109 | [Date "2001.12.13"]
110 | [Round "6.4"]
111 | [White "Anand, V."]
112 | [Black "Ivanchuk, V."]
113 | [Result "0-1"]
114 | [ECO "B30"]
115 | [WhiteElo "2770"]
116 | [BlackElo "2731"]
117 | [Annotator "GM Alfonso Romero Holmes"]
118 | [PlyCount "84"]
119 | [EventDate "2001.11.27"]
120 | [Source "Mikhail Golubev"]
121 | [SourceDate "2002.01.08"]
122 |
123 | 1. e4 c5 2. Nf3 Nc6 3. Nc3 e5 4. Bc4 d6 5. d3 5... Be7 { } 6. Nd2 $5 6... Nf6
124 | 7. Nf1 7... Nd7 $5 (7... Be6 8. Ne3 O-O (8... Bxc4 $6 9. dxc4 $14) 9. O-O Nd4
125 | 10. a4 a6 11. Ncd5 Nxd5 (11... b5 $2 12. axb5 axb5 13. Rxa8 Qxa8 14. Nxe7+ $18)
126 | 12. Bxd5 Rb8 13. g3 (13. c3 Nc6 14. g3 $14) 13... Bh3 14. Ng2 Qd7 (14... Ne6
127 | 15. f4 exf4 16. gxf4 Nc7 17. Ba2 d5) 15. c3 Ne6 16. f4 exf4 17. gxf4 Nc7 18.
128 | Ba2 Qg4 (18... d5 19. Qf3 Rbd8) 19. Qxg4 Bxg4 20. Rf2 Be6 21. f5 $1 21... Bxa2
129 | 22. Rxa2 b5 23. Bf4 b4 24. f6 $5 24... Bxf6 (24... gxf6 $6 25. Ne3 $14 {x f5})
130 | 25. Bxd6 Rfc8 (25... bxc3 $2 26. e5 $1 26... cxb2 27. Rfxb2 Rxb2 28. Rxb2 $18)
131 | 26. e5 Bd8 27. e6 $6 (27. Ne3 $14) 27... Bf6 28. exf7+ Kxf7 29. Ne3 bxc3 30.
132 | bxc3 Rb1+ 31. Kg2 Ne8 32. Bg3 Kg6 33. Ng4 33... Rd8 {
133 | - Gelfand,B-Kramnik,V FIDE Sanghi Nagar (2) 1994}) 8. Nd5 (8. Ne3 Bg5) 8...
134 | Nb6 9. Nxb6 (9. Bb3 Nd4) 9... axb6 10. c3 O-O 11. Ne3 (11. Ng3 $5 11... Be6 (
135 | 11... Bg5 12. Bxg5 Qxg5 13. O-O) 12. O-O d5 13. exd5 Bxd5 14. Qg4) 11... Bg5
136 | 12. O-O Kh8 13. Bd2 (13. Nd5 Bxc1 14. Qxc1 Ne7 15. f4 15... Be6 $1) 13... Bxe3
137 | 14. fxe3 14... Qe7 { } 15. Bd5 Be6 16. Qb3 (16. c4 f5) 16... Na5 17. Qc2 (17.
138 | Qxb6 Ra6 18. Qb5 18... Bd7 $19) 17... Qc7 (17... b5 18. c4 bxc4 19. dxc4) (
139 | 17... f5 $6 18. Bxe6 Qxe6 19. exf5 Rxf5 20. Rxf5 Qxf5 21. Rf1 Qe6 22. c4) 18.
140 | h3 (18. c4 Nc6 19. a3 Ne7) 18... h6 19. c4 Nc6 20. Qd1 { } 20... Bxd5 $1 21.
141 | exd5 Ne7 22. a4 (22. e4 22... f5 $1 23. Qh5 Qd7) 22... f5 23. Bc3 23... Rf7 { }
142 | 24. Qb3 $2 (24. Qh5 Rf6 25. b3 $1 (25. Rf2 b5) 25... Qd7 26. Rf2) 24... Ng6 25.
143 | Rf2 Raf8 26. Raf1 { } 26... f4 $1 27. Bd2 27... f3 $1 28. Rxf3 (28. g3 Rf5 (
144 | 28... Qd7 29. Kh2 Rf5 30. Qb5 Qc8 31. g4 R5f6) 29. e4 Rh5 30. Rxf3 (30. h4 Nxh4
145 | 31. gxh4 Qc8 32. Rh2 Qg4+ 33. Kh1 Rxh4 34. Rff2 Rxh2+ 35. Kxh2 Qh4+ 36. Kg1
146 | 36... Rf6 $19) 30... Rxf3 31. Rxf3 Rxh3 32. Kg2 Rh5 33. Be3 33... Qd7 $40)
147 | 28... Rxf3 29. gxf3 (29. Rxf3 Rxf3 30. gxf3 Qd7 31. Kh2 Qf5 32. f4 (32. Qxb6
148 | Qxf3) 32... Nh4 (32... Qh5 $1) 33. Kg3 33... g5 $1 (33... Qg6+ 34. Kxh4 Qg2 35.
149 | Qxb6 Kh7 36. Qc7 $11) 34. Bc1 $1 34... Qg6 (34... Kh7 35. Qd1) 35. fxg5 (35.
150 | fxe5 35... Qf5 $1) 35... Qxg5+ 36. Kf2 Qg2+ 37. Ke1 Nf3+ 38. Kd1 Qf1+ 39. Kc2
151 | Ne1+ 40. Kd2 Kg7 41. Qxb6 $11) 29... Qc8 30. Kh2 { } 30... Rf5 31. f4 Rh5 32.
152 | f5 (32. Rf3 Qg4 33. Rg3 Qe2+ 34. Rg2 Qf3) 32... Rxf5 33. Qd1 33... Qf8 { } 34.
153 | Rxf5 $2 (34. Kg1 Nh4 35. e4 Rxf1+ (35... Rf3 36. Bc1 Qf7 37. Rxf3 Nxf3+ 38. Kg2
154 | Nh4+ 39. Kg3 39... g5 $15) 36. Qxf1 { } 36... Qf3 $1 37. Be1 Qe3+ 38. Bf2 Qg5+
155 | 39. Kh1 Ng6 40. Qd1 (40. Bg1 Kh7) 40... Nf4 41. Qf3 Qf6) 34... Qxf5 35. Qe2
156 | 35... e4 $1 36. Qg4 Qxg4 37. hxg4 Ne5 38. Kg3 exd3 39. b3 39... g6 $19 { } 40.
157 | e4 h5 41. gxh5 gxh5 42. Kf2 h4 0-1
158 |
159 |
--------------------------------------------------------------------------------
/src/benchmark.cpp:
--------------------------------------------------------------------------------
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 .
19 | */
20 |
21 | #include
22 | #include
23 | #include
24 | #include
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 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 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 = stoll(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(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 | }
184 |
--------------------------------------------------------------------------------
/src/bitbase.cpp:
--------------------------------------------------------------------------------
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 .
19 | */
20 |
21 | #include
22 | #include
23 | #include
24 | #include
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& db)
64 | { return us == WHITE ? classify(db) : classify(db); }
65 |
66 | template Result classify(const std::vector& 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 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
143 | Result KPKPosition::classify(const std::vector& 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
181 |
--------------------------------------------------------------------------------
/src/bitboard.cpp:
--------------------------------------------------------------------------------
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 .
19 | */
20 |
21 | #include
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(s1, s2), distance(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);
212 | init_magics(BishopTable, BishopAttacks, BishopMagics, BishopMasks, BishopShifts, BishopDeltas, magic_index);
213 |
214 | for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
215 | {
216 | PseudoAttacks[QUEEN][s1] = PseudoAttacks[BISHOP][s1] = attacks_bb(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();
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 | }
334 |
--------------------------------------------------------------------------------
/src/bitboard.h:
--------------------------------------------------------------------------------
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 .
19 | */
20 |
21 | #ifndef BITBOARD_H_INCLUDED
22 | #define BITBOARD_H_INCLUDED
23 |
24 | #include
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
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 inline int distance(T x, T y) { return x < y ? y - x : x - y; }
205 | template<> inline int distance(Square x, Square y) { return SquareDistance[x][y]; }
206 |
207 | template inline int distance(T2 x, T2 y);
208 | template<> inline int distance(Square x, Square y) { return distance(file_of(x), file_of(y)); }
209 | template<> inline int distance(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
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
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(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(s, occupied);
254 | case ROOK : return attacks_bb(s, occupied);
255 | case QUEEN : return attacks_bb(s, occupied) | attacks_bb(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
339 |
--------------------------------------------------------------------------------
/src/endgame.h:
--------------------------------------------------------------------------------
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 .
19 | */
20 |
21 | #ifndef ENDGAME_H_INCLUDED
22 | #define ENDGAME_H_INCLUDED
23 |
24 | #include