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-2019 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 | #include "syzygy/tbprobe.h" |
36 | |
37 | using std::string; |
38 | |
39 | namespace Zobrist { |
40 | |
41 | Key psq[PIECE_NB][SQUARE_NB]; |
42 | Key enpassant[FILE_NB]; |
43 | Key castling[CASTLING_RIGHT_NB]; |
44 | Key side, noPawns; |
45 | } |
46 | |
47 | namespace { |
48 | |
49 | const string PieceToChar(" PNBRQK pnbrqk" ); |
50 | |
51 | constexpr Piece Pieces[] = { W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING, |
52 | B_PAWN, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING }; |
53 | |
54 | // min_attacker() is a helper function used by see_ge() 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<PieceType Pt> |
59 | PieceType min_attacker(const Bitboard* byTypeBB, Square to, Bitboard stmAttackers, |
60 | Bitboard& occupied, Bitboard& attackers) { |
61 | |
62 | Bitboard b = stmAttackers & byTypeBB[Pt]; |
63 | if (!b) |
64 | return min_attacker<PieceType(Pt + 1)>(byTypeBB, to, stmAttackers, occupied, attackers); |
65 | |
66 | occupied ^= lsb(b); // Remove the attacker from occupied |
67 | |
68 | // Add any X-ray attack behind the just removed piece. For instance with |
69 | // rooks in a8 and a7 attacking a1, after removing a7 we add rook in a8. |
70 | // Note that new added attackers can be of any color. |
71 | if (Pt == PAWN || Pt == BISHOP || Pt == QUEEN) |
72 | attackers |= attacks_bb<BISHOP>(to, occupied) & (byTypeBB[BISHOP] | byTypeBB[QUEEN]); |
73 | |
74 | if (Pt == ROOK || Pt == QUEEN) |
75 | attackers |= attacks_bb<ROOK>(to, occupied) & (byTypeBB[ROOK] | byTypeBB[QUEEN]); |
76 | |
77 | // X-ray may add already processed pieces because byTypeBB[] is constant: in |
78 | // the rook example, now attackers contains _again_ rook in a7, so remove it. |
79 | attackers &= occupied; |
80 | return Pt; |
81 | } |
82 | |
83 | template<> |
84 | PieceType min_attacker<KING>(const Bitboard*, Square, Bitboard, Bitboard&, Bitboard&) { |
85 | return KING; // No need to update bitboards: it is the last cycle |
86 | } |
87 | |
88 | } // namespace |
89 | |
90 | |
91 | /// operator<<(Position) returns an ASCII representation of the position |
92 | |
93 | std::ostream& operator<<(std::ostream& os, const Position& pos) { |
94 | |
95 | os << "\n +---+---+---+---+---+---+---+---+\n" ; |
96 | |
97 | for (Rank r = RANK_8; r >= RANK_1; --r) |
98 | { |
99 | for (File f = FILE_A; f <= FILE_H; ++f) |
100 | os << " | " << PieceToChar[pos.piece_on(make_square(f, r))]; |
101 | |
102 | os << " |\n +---+---+---+---+---+---+---+---+\n" ; |
103 | } |
104 | |
105 | os << "\nFen: " << pos.fen() << "\nKey: " << std::hex << std::uppercase |
106 | << std::setfill('0') << std::setw(16) << pos.key() |
107 | << std::setfill(' ') << std::dec << "\nCheckers: " ; |
108 | |
109 | for (Bitboard b = pos.checkers(); b; ) |
110 | os << UCI::square(pop_lsb(&b)) << " " ; |
111 | |
112 | if ( int(Tablebases::MaxCardinality) >= popcount(pos.pieces()) |
113 | && !pos.can_castle(ANY_CASTLING)) |
114 | { |
115 | StateInfo st; |
116 | Position p; |
117 | p.set(pos.fen(), pos.is_chess960(), &st, pos.this_thread()); |
118 | Tablebases::ProbeState s1, s2; |
119 | Tablebases::WDLScore wdl = Tablebases::probe_wdl(p, &s1); |
120 | int dtz = Tablebases::probe_dtz(p, &s2); |
121 | os << "\nTablebases WDL: " << std::setw(4) << wdl << " (" << s1 << ")" |
122 | << "\nTablebases DTZ: " << std::setw(4) << dtz << " (" << s2 << ")" ; |
123 | } |
124 | |
125 | return os; |
126 | } |
127 | |
128 | |
129 | // Marcel van Kervinck's cuckoo algorithm for fast detection of "upcoming repetition" |
130 | // situations. Description of the algorithm in the following paper: |
131 | // https://marcelk.net/2013-04-06/paper/upcoming-rep-v2.pdf |
132 | |
133 | // First and second hash functions for indexing the cuckoo tables |
134 | inline int H1(Key h) { return h & 0x1fff; } |
135 | inline int H2(Key h) { return (h >> 16) & 0x1fff; } |
136 | |
137 | // Cuckoo tables with Zobrist hashes of valid reversible moves, and the moves themselves |
138 | Key cuckoo[8192]; |
139 | Move cuckooMove[8192]; |
140 | |
141 | |
142 | /// Position::init() initializes at startup the various arrays used to compute |
143 | /// hash keys. |
144 | |
145 | void Position::init() { |
146 | |
147 | PRNG rng(1070372); |
148 | |
149 | for (Piece pc : Pieces) |
150 | for (Square s = SQ_A1; s <= SQ_H8; ++s) |
151 | Zobrist::psq[pc][s] = rng.rand<Key>(); |
152 | |
153 | for (File f = FILE_A; f <= FILE_H; ++f) |
154 | Zobrist::enpassant[f] = rng.rand<Key>(); |
155 | |
156 | for (int cr = NO_CASTLING; cr <= ANY_CASTLING; ++cr) |
157 | { |
158 | Zobrist::castling[cr] = 0; |
159 | Bitboard b = cr; |
160 | while (b) |
161 | { |
162 | Key k = Zobrist::castling[1ULL << pop_lsb(&b)]; |
163 | Zobrist::castling[cr] ^= k ? k : rng.rand<Key>(); |
164 | } |
165 | } |
166 | |
167 | Zobrist::side = rng.rand<Key>(); |
168 | Zobrist::noPawns = rng.rand<Key>(); |
169 | |
170 | // Prepare the cuckoo tables |
171 | std::memset(cuckoo, 0, sizeof(cuckoo)); |
172 | std::memset(cuckooMove, 0, sizeof(cuckooMove)); |
173 | int count = 0; |
174 | for (Piece pc : Pieces) |
175 | for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1) |
176 | for (Square s2 = Square(s1 + 1); s2 <= SQ_H8; ++s2) |
177 | if (PseudoAttacks[type_of(pc)][s1] & s2) |
178 | { |
179 | Move move = make_move(s1, s2); |
180 | Key key = Zobrist::psq[pc][s1] ^ Zobrist::psq[pc][s2] ^ Zobrist::side; |
181 | int i = H1(key); |
182 | while (true) |
183 | { |
184 | std::swap(cuckoo[i], key); |
185 | std::swap(cuckooMove[i], move); |
186 | if (move == MOVE_NONE) // Arrived at empty slot? |
187 | break; |
188 | i = (i == H1(key)) ? H2(key) : H1(key); // Push victim to alternative slot |
189 | } |
190 | count++; |
191 | } |
192 | assert(count == 3668); |
193 | } |
194 | |
195 | |
196 | /// Position::set() initializes the position object with the given FEN string. |
197 | /// This function is not very robust - make sure that input FENs are correct, |
198 | /// this is assumed to be the responsibility of the GUI. |
199 | |
200 | Position& Position::set(const string& fenStr, bool isChess960, StateInfo* si, Thread* th) { |
201 | /* |
202 | A FEN string defines a particular position using only the ASCII character set. |
203 | |
204 | A FEN string contains six fields separated by a space. The fields are: |
205 | |
206 | 1) Piece placement (from white's perspective). Each rank is described, starting |
207 | with rank 8 and ending with rank 1. Within each rank, the contents of each |
208 | square are described from file A through file H. Following the Standard |
209 | Algebraic Notation (SAN), each piece is identified by a single letter taken |
210 | from the standard English names. White pieces are designated using upper-case |
211 | letters ("PNBRQK") whilst Black uses lowercase ("pnbrqk"). Blank squares are |
212 | noted using digits 1 through 8 (the number of blank squares), and "/" |
213 | separates ranks. |
214 | |
215 | 2) Active color. "w" means white moves next, "b" means black. |
216 | |
217 | 3) Castling availability. If neither side can castle, this is "-". Otherwise, |
218 | this has one or more letters: "K" (White can castle kingside), "Q" (White |
219 | can castle queenside), "k" (Black can castle kingside), and/or "q" (Black |
220 | can castle queenside). |
221 | |
222 | 4) En passant target square (in algebraic notation). If there's no en passant |
223 | target square, this is "-". If a pawn has just made a 2-square move, this |
224 | is the position "behind" the pawn. This is recorded only if there is a pawn |
225 | in position to make an en passant capture, and if there really is a pawn |
226 | that might have advanced two squares. |
227 | |
228 | 5) Halfmove clock. This is the number of halfmoves since the last pawn advance |
229 | or capture. This is used to determine if a draw can be claimed under the |
230 | fifty-move rule. |
231 | |
232 | 6) Fullmove number. The number of the full move. It starts at 1, and is |
233 | incremented after Black's move. |
234 | */ |
235 | |
236 | unsigned char col, row, token; |
237 | size_t idx; |
238 | Square sq = SQ_A8; |
239 | std::istringstream ss(fenStr); |
240 | |
241 | std::memset(this, 0, sizeof(Position)); |
242 | std::memset(si, 0, sizeof(StateInfo)); |
243 | std::fill_n(&pieceList[0][0], sizeof(pieceList) / sizeof(Square), SQ_NONE); |
244 | st = si; |
245 | |
246 | ss >> std::noskipws; |
247 | |
248 | // 1. Piece placement |
249 | while ((ss >> token) && !isspace(token)) |
250 | { |
251 | if (isdigit(token)) |
252 | sq += (token - '0') * EAST; // Advance the given number of files |
253 | |
254 | else if (token == '/') |
255 | sq += 2 * SOUTH; |
256 | |
257 | else if ((idx = PieceToChar.find(token)) != string::npos) |
258 | { |
259 | put_piece(Piece(idx), sq); |
260 | ++sq; |
261 | } |
262 | } |
263 | |
264 | // 2. Active color |
265 | ss >> token; |
266 | sideToMove = (token == 'w' ? WHITE : BLACK); |
267 | ss >> token; |
268 | |
269 | // 3. Castling availability. Compatible with 3 standards: Normal FEN standard, |
270 | // Shredder-FEN that uses the letters of the columns on which the rooks began |
271 | // the game instead of KQkq and also X-FEN standard that, in case of Chess960, |
272 | // if an inner rook is associated with the castling right, the castling tag is |
273 | // replaced by the file letter of the involved rook, as for the Shredder-FEN. |
274 | while ((ss >> token) && !isspace(token)) |
275 | { |
276 | Square rsq; |
277 | Color c = islower(token) ? BLACK : WHITE; |
278 | Piece rook = make_piece(c, ROOK); |
279 | |
280 | token = char(toupper(token)); |
281 | |
282 | if (token == 'K') |
283 | for (rsq = relative_square(c, SQ_H1); piece_on(rsq) != rook; --rsq) {} |
284 | |
285 | else if (token == 'Q') |
286 | for (rsq = relative_square(c, SQ_A1); piece_on(rsq) != rook; ++rsq) {} |
287 | |
288 | else if (token >= 'A' && token <= 'H') |
289 | rsq = make_square(File(token - 'A'), relative_rank(c, RANK_1)); |
290 | |
291 | else |
292 | continue; |
293 | |
294 | set_castling_right(c, rsq); |
295 | } |
296 | |
297 | // 4. En passant square. Ignore if no pawn capture is possible |
298 | if ( ((ss >> col) && (col >= 'a' && col <= 'h')) |
299 | && ((ss >> row) && (row == '3' || row == '6'))) |
300 | { |
301 | st->epSquare = make_square(File(col - 'a'), Rank(row - '1')); |
302 | |
303 | if ( !(attackers_to(st->epSquare) & pieces(sideToMove, PAWN)) |
304 | || !(pieces(~sideToMove, PAWN) & (st->epSquare + pawn_push(~sideToMove)))) |
305 | st->epSquare = SQ_NONE; |
306 | } |
307 | else |
308 | st->epSquare = SQ_NONE; |
309 | |
310 | // 5-6. Halfmove clock and fullmove number |
311 | ss >> std::skipws >> st->rule50 >> gamePly; |
312 | |
313 | // Convert from fullmove starting from 1 to gamePly starting from 0, |
314 | // handle also common incorrect FEN with fullmove = 0. |
315 | gamePly = std::max(2 * (gamePly - 1), 0) + (sideToMove == BLACK); |
316 | |
317 | chess960 = isChess960; |
318 | thisThread = th; |
319 | set_state(st); |
320 | |
321 | assert(pos_is_ok()); |
322 | |
323 | return *this; |
324 | } |
325 | |
326 | |
327 | /// Position::set_castling_right() is a helper function used to set castling |
328 | /// rights given the corresponding color and the rook starting square. |
329 | |
330 | void Position::set_castling_right(Color c, Square rfrom) { |
331 | |
332 | Square kfrom = square<KING>(c); |
333 | CastlingSide cs = kfrom < rfrom ? KING_SIDE : QUEEN_SIDE; |
334 | CastlingRight cr = (c | cs); |
335 | |
336 | st->castlingRights |= cr; |
337 | castlingRightsMask[kfrom] |= cr; |
338 | castlingRightsMask[rfrom] |= cr; |
339 | castlingRookSquare[cr] = rfrom; |
340 | |
341 | Square kto = relative_square(c, cs == KING_SIDE ? SQ_G1 : SQ_C1); |
342 | Square rto = relative_square(c, cs == KING_SIDE ? SQ_F1 : SQ_D1); |
343 | |
344 | castlingPath[cr] = (between_bb(rfrom, rto) | between_bb(kfrom, kto) | rto | kto) |
345 | & ~(square_bb(kfrom) | rfrom); |
346 | } |
347 | |
348 | |
349 | /// Position::set_check_info() sets king attacks to detect if a move gives check |
350 | |
351 | void Position::set_check_info(StateInfo* si) const { |
352 | |
353 | si->blockersForKing[WHITE] = slider_blockers(pieces(BLACK), square<KING>(WHITE), si->pinners[BLACK]); |
354 | si->blockersForKing[BLACK] = slider_blockers(pieces(WHITE), square<KING>(BLACK), si->pinners[WHITE]); |
355 | |
356 | Square ksq = square<KING>(~sideToMove); |
357 | |
358 | si->checkSquares[PAWN] = attacks_from<PAWN>(ksq, ~sideToMove); |
359 | si->checkSquares[KNIGHT] = attacks_from<KNIGHT>(ksq); |
360 | si->checkSquares[BISHOP] = attacks_from<BISHOP>(ksq); |
361 | si->checkSquares[ROOK] = attacks_from<ROOK>(ksq); |
362 | si->checkSquares[QUEEN] = si->checkSquares[BISHOP] | si->checkSquares[ROOK]; |
363 | si->checkSquares[KING] = 0; |
364 | } |
365 | |
366 | |
367 | /// Position::set_state() computes the hash keys of the position, and other |
368 | /// data that once computed is updated incrementally as moves are made. |
369 | /// The function is only used when a new position is set up, and to verify |
370 | /// the correctness of the StateInfo data when running in debug mode. |
371 | |
372 | void Position::set_state(StateInfo* si) const { |
373 | |
374 | si->key = si->materialKey = 0; |
375 | si->pawnKey = Zobrist::noPawns; |
376 | si->nonPawnMaterial[WHITE] = si->nonPawnMaterial[BLACK] = VALUE_ZERO; |
377 | si->checkersBB = attackers_to(square<KING>(sideToMove)) & pieces(~sideToMove); |
378 | |
379 | set_check_info(si); |
380 | |
381 | for (Bitboard b = pieces(); b; ) |
382 | { |
383 | Square s = pop_lsb(&b); |
384 | Piece pc = piece_on(s); |
385 | si->key ^= Zobrist::psq[pc][s]; |
386 | |
387 | if (type_of(pc) == PAWN) |
388 | si->pawnKey ^= Zobrist::psq[pc][s]; |
389 | |
390 | else if (type_of(pc) != KING) |
391 | si->nonPawnMaterial[color_of(pc)] += PieceValue[MG][pc]; |
392 | } |
393 | |
394 | if (si->epSquare != SQ_NONE) |
395 | si->key ^= Zobrist::enpassant[file_of(si->epSquare)]; |
396 | |
397 | if (sideToMove == BLACK) |
398 | si->key ^= Zobrist::side; |
399 | |
400 | si->key ^= Zobrist::castling[si->castlingRights]; |
401 | |
402 | for (Piece pc : Pieces) |
403 | for (int cnt = 0; cnt < pieceCount[pc]; ++cnt) |
404 | si->materialKey ^= Zobrist::psq[pc][cnt]; |
405 | } |
406 | |
407 | |
408 | /// Position::set() is an overload to initialize the position object with |
409 | /// the given endgame code string like "KBPKN". It is mainly a helper to |
410 | /// get the material key out of an endgame code. |
411 | |
412 | Position& Position::set(const string& code, Color c, StateInfo* si) { |
413 | |
414 | assert(code.length() > 0 && code.length() < 8); |
415 | assert(code[0] == 'K'); |
416 | |
417 | string sides[] = { code.substr(code.find('K', 1)), // Weak |
418 | code.substr(0, code.find('K', 1)) }; // Strong |
419 | |
420 | std::transform(sides[c].begin(), sides[c].end(), sides[c].begin(), tolower); |
421 | |
422 | string fenStr = "8/" + sides[0] + char(8 - sides[0].length() + '0') + "/8/8/8/8/" |
423 | + sides[1] + char(8 - sides[1].length() + '0') + "/8 w - - 0 10" ; |
424 | |
425 | return set(fenStr, false, si, nullptr); |
426 | } |
427 | |
428 | |
429 | /// Position::fen() returns a FEN representation of the position. In case of |
430 | /// Chess960 the Shredder-FEN notation is used. This is mainly a debugging function. |
431 | |
432 | const string Position::fen() const { |
433 | |
434 | int emptyCnt; |
435 | std::ostringstream ss; |
436 | |
437 | for (Rank r = RANK_8; r >= RANK_1; --r) |
438 | { |
439 | for (File f = FILE_A; f <= FILE_H; ++f) |
440 | { |
441 | for (emptyCnt = 0; f <= FILE_H && empty(make_square(f, r)); ++f) |
442 | ++emptyCnt; |
443 | |
444 | if (emptyCnt) |
445 | ss << emptyCnt; |
446 | |
447 | if (f <= FILE_H) |
448 | ss << PieceToChar[piece_on(make_square(f, r))]; |
449 | } |
450 | |
451 | if (r > RANK_1) |
452 | ss << '/'; |
453 | } |
454 | |
455 | ss << (sideToMove == WHITE ? " w " : " b " ); |
456 | |
457 | if (can_castle(WHITE_OO)) |
458 | ss << (chess960 ? char('A' + file_of(castling_rook_square(WHITE_OO ))) : 'K'); |
459 | |
460 | if (can_castle(WHITE_OOO)) |
461 | ss << (chess960 ? char('A' + file_of(castling_rook_square(WHITE_OOO))) : 'Q'); |
462 | |
463 | if (can_castle(BLACK_OO)) |
464 | ss << (chess960 ? char('a' + file_of(castling_rook_square(BLACK_OO ))) : 'k'); |
465 | |
466 | if (can_castle(BLACK_OOO)) |
467 | ss << (chess960 ? char('a' + file_of(castling_rook_square(BLACK_OOO))) : 'q'); |
468 | |
469 | if (!can_castle(ANY_CASTLING)) |
470 | ss << '-'; |
471 | |
472 | ss << (ep_square() == SQ_NONE ? " - " : " " + UCI::square(ep_square()) + " " ) |
473 | << st->rule50 << " " << 1 + (gamePly - (sideToMove == BLACK)) / 2; |
474 | |
475 | return ss.str(); |
476 | } |
477 | |
478 | |
479 | /// Position::slider_blockers() returns a bitboard of all the pieces (both colors) |
480 | /// that are blocking attacks on the square 's' from 'sliders'. A piece blocks a |
481 | /// slider if removing that piece from the board would result in a position where |
482 | /// square 's' is attacked. For example, a king-attack blocking piece can be either |
483 | /// a pinned or a discovered check piece, according if its color is the opposite |
484 | /// or the same of the color of the slider. |
485 | |
486 | Bitboard Position::slider_blockers(Bitboard sliders, Square s, Bitboard& pinners) const { |
487 | |
488 | Bitboard blockers = 0; |
489 | pinners = 0; |
490 | |
491 | // Snipers are sliders that attack 's' when a piece and other snipers are removed |
492 | Bitboard snipers = ( (PseudoAttacks[ ROOK][s] & pieces(QUEEN, ROOK)) |
493 | | (PseudoAttacks[BISHOP][s] & pieces(QUEEN, BISHOP))) & sliders; |
494 | Bitboard occupancy = pieces() ^ snipers; |
495 | |
496 | while (snipers) |
497 | { |
498 | Square sniperSq = pop_lsb(&snipers); |
499 | Bitboard b = between_bb(s, sniperSq) & occupancy; |
500 | |
501 | if (b && !more_than_one(b)) |
502 | { |
503 | blockers |= b; |
504 | if (b & pieces(color_of(piece_on(s)))) |
505 | pinners |= sniperSq; |
506 | } |
507 | } |
508 | return blockers; |
509 | } |
510 | |
511 | |
512 | /// Position::attackers_to() computes a bitboard of all pieces which attack a |
513 | /// given square. Slider attacks use the occupied bitboard to indicate occupancy. |
514 | |
515 | Bitboard Position::attackers_to(Square s, Bitboard occupied) const { |
516 | |
517 | return (attacks_from<PAWN>(s, BLACK) & pieces(WHITE, PAWN)) |
518 | | (attacks_from<PAWN>(s, WHITE) & pieces(BLACK, PAWN)) |
519 | | (attacks_from<KNIGHT>(s) & pieces(KNIGHT)) |
520 | | (attacks_bb< ROOK>(s, occupied) & pieces( ROOK, QUEEN)) |
521 | | (attacks_bb<BISHOP>(s, occupied) & pieces(BISHOP, QUEEN)) |
522 | | (attacks_from<KING>(s) & pieces(KING)); |
523 | } |
524 | |
525 | |
526 | /// Position::legal() tests whether a pseudo-legal move is legal |
527 | |
528 | bool Position::legal(Move m) const { |
529 | |
530 | assert(is_ok(m)); |
531 | |
532 | Color us = sideToMove; |
533 | Square from = from_sq(m); |
534 | Square to = to_sq(m); |
535 | |
536 | assert(color_of(moved_piece(m)) == us); |
537 | assert(piece_on(square<KING>(us)) == make_piece(us, KING)); |
538 | |
539 | // En passant captures are a tricky special case. Because they are rather |
540 | // uncommon, we do it simply by testing whether the king is attacked after |
541 | // the move is made. |
542 | if (type_of(m) == ENPASSANT) |
543 | { |
544 | Square ksq = square<KING>(us); |
545 | Square capsq = to - pawn_push(us); |
546 | Bitboard occupied = (pieces() ^ from ^ capsq) | to; |
547 | |
548 | assert(to == ep_square()); |
549 | assert(moved_piece(m) == make_piece(us, PAWN)); |
550 | assert(piece_on(capsq) == make_piece(~us, PAWN)); |
551 | assert(piece_on(to) == NO_PIECE); |
552 | |
553 | return !(attacks_bb< ROOK>(ksq, occupied) & pieces(~us, QUEEN, ROOK)) |
554 | && !(attacks_bb<BISHOP>(ksq, occupied) & pieces(~us, QUEEN, BISHOP)); |
555 | } |
556 | |
557 | // Castling moves generation does not check if the castling path is clear of |
558 | // enemy attacks, it is delayed at a later time: now! |
559 | if (type_of(m) == CASTLING) |
560 | { |
561 | // After castling, the rook and king final positions are the same in |
562 | // Chess960 as they would be in standard chess. |
563 | to = relative_square(us, to > from ? SQ_G1 : SQ_C1); |
564 | Direction step = to > from ? WEST : EAST; |
565 | |
566 | for (Square s = to; s != from; s += step) |
567 | if (attackers_to(s) & pieces(~us)) |
568 | return false; |
569 | |
570 | // In case of Chess960, verify that when moving the castling rook we do |
571 | // not discover some hidden checker. |
572 | // For instance an enemy queen in SQ_A1 when castling rook is in SQ_B1. |
573 | return !chess960 |
574 | || !(attacks_bb<ROOK>(to, pieces() ^ to_sq(m)) & pieces(~us, ROOK, QUEEN)); |
575 | } |
576 | |
577 | // If the moving piece is a king, check whether the destination square is |
578 | // attacked by the opponent. |
579 | if (type_of(piece_on(from)) == KING) |
580 | return !(attackers_to(to) & pieces(~us)); |
581 | |
582 | // A non-king move is legal if and only if it is not pinned or it |
583 | // is moving along the ray towards or away from the king. |
584 | return !(blockers_for_king(us) & from) |
585 | || aligned(from, to, square<KING>(us)); |
586 | } |
587 | |
588 | |
589 | /// Position::pseudo_legal() takes a random move and tests whether the move is |
590 | /// pseudo legal. It is used to validate moves from TT that can be corrupted |
591 | /// due to SMP concurrent access or hash position key aliasing. |
592 | |
593 | bool Position::pseudo_legal(const Move m) const { |
594 | |
595 | Color us = sideToMove; |
596 | Square from = from_sq(m); |
597 | Square to = to_sq(m); |
598 | Piece pc = moved_piece(m); |
599 | |
600 | // Use a slower but simpler function for uncommon cases |
601 | if (type_of(m) != NORMAL) |
602 | return MoveList<LEGAL>(*this).contains(m); |
603 | |
604 | // Is not a promotion, so promotion piece must be empty |
605 | if (promotion_type(m) - KNIGHT != NO_PIECE_TYPE) |
606 | return false; |
607 | |
608 | // If the 'from' square is not occupied by a piece belonging to the side to |
609 | // move, the move is obviously not legal. |
610 | if (pc == NO_PIECE || color_of(pc) != us) |
611 | return false; |
612 | |
613 | // The destination square cannot be occupied by a friendly piece |
614 | if (pieces(us) & to) |
615 | return false; |
616 | |
617 | // Handle the special case of a pawn move |
618 | if (type_of(pc) == PAWN) |
619 | { |
620 | // We have already handled promotion moves, so destination |
621 | // cannot be on the 8th/1st rank. |
622 | if ((Rank8BB | Rank1BB) & to) |
623 | return false; |
624 | |
625 | if ( !(attacks_from<PAWN>(from, us) & pieces(~us) & to) // Not a capture |
626 | && !((from + pawn_push(us) == to) && empty(to)) // Not a single push |
627 | && !( (from + 2 * pawn_push(us) == to) // Not a double push |
628 | && (rank_of(from) == relative_rank(us, RANK_2)) |
629 | && empty(to) |
630 | && empty(to - pawn_push(us)))) |
631 | return false; |
632 | } |
633 | else if (!(attacks_from(type_of(pc), from) & to)) |
634 | return false; |
635 | |
636 | // Evasions generator already takes care to avoid some kind of illegal moves |
637 | // and legal() relies on this. We therefore have to take care that the same |
638 | // kind of moves are filtered out here. |
639 | if (checkers()) |
640 | { |
641 | if (type_of(pc) != KING) |
642 | { |
643 | // Double check? In this case a king move is required |
644 | if (more_than_one(checkers())) |
645 | return false; |
646 | |
647 | // Our move must be a blocking evasion or a capture of the checking piece |
648 | if (!((between_bb(lsb(checkers()), square<KING>(us)) | checkers()) & to)) |
649 | return false; |
650 | } |
651 | // In case of king moves under check we have to remove king so as to catch |
652 | // invalid moves like b1a1 when opposite queen is on c1. |
653 | else if (attackers_to(to, pieces() ^ from) & pieces(~us)) |
654 | return false; |
655 | } |
656 | |
657 | return true; |
658 | } |
659 | |
660 | |
661 | /// Position::gives_check() tests whether a pseudo-legal move gives a check |
662 | |
663 | bool Position::gives_check(Move m) const { |
664 | |
665 | assert(is_ok(m)); |
666 | assert(color_of(moved_piece(m)) == sideToMove); |
667 | |
668 | Square from = from_sq(m); |
669 | Square to = to_sq(m); |
670 | |
671 | // Is there a direct check? |
672 | if (st->checkSquares[type_of(piece_on(from))] & to) |
673 | return true; |
674 | |
675 | // Is there a discovered check? |
676 | if ( (st->blockersForKing[~sideToMove] & from) |
677 | && !aligned(from, to, square<KING>(~sideToMove))) |
678 | return true; |
679 | |
680 | switch (type_of(m)) |
681 | { |
682 | case NORMAL: |
683 | return false; |
684 | |
685 | case PROMOTION: |
686 | return attacks_bb(promotion_type(m), to, pieces() ^ from) & square<KING>(~sideToMove); |
687 | |
688 | // En passant capture with check? We have already handled the case |
689 | // of direct checks and ordinary discovered check, so the only case we |
690 | // need to handle is the unusual case of a discovered check through |
691 | // the captured pawn. |
692 | case ENPASSANT: |
693 | { |
694 | Square capsq = make_square(file_of(to), rank_of(from)); |
695 | Bitboard b = (pieces() ^ from ^ capsq) | to; |
696 | |
697 | return (attacks_bb< ROOK>(square<KING>(~sideToMove), b) & pieces(sideToMove, QUEEN, ROOK)) |
698 | | (attacks_bb<BISHOP>(square<KING>(~sideToMove), b) & pieces(sideToMove, QUEEN, BISHOP)); |
699 | } |
700 | case CASTLING: |
701 | { |
702 | Square kfrom = from; |
703 | Square rfrom = to; // Castling is encoded as 'King captures the rook' |
704 | Square kto = relative_square(sideToMove, rfrom > kfrom ? SQ_G1 : SQ_C1); |
705 | Square rto = relative_square(sideToMove, rfrom > kfrom ? SQ_F1 : SQ_D1); |
706 | |
707 | return (PseudoAttacks[ROOK][rto] & square<KING>(~sideToMove)) |
708 | && (attacks_bb<ROOK>(rto, (pieces() ^ kfrom ^ rfrom) | rto | kto) & square<KING>(~sideToMove)); |
709 | } |
710 | default: |
711 | assert(false); |
712 | return false; |
713 | } |
714 | } |
715 | |
716 | |
717 | /// Position::do_move() makes a move, and saves all information necessary |
718 | /// to a StateInfo object. The move is assumed to be legal. Pseudo-legal |
719 | /// moves should be filtered out before this function is called. |
720 | |
721 | void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) { |
722 | |
723 | assert(is_ok(m)); |
724 | assert(&newSt != st); |
725 | |
726 | thisThread->nodes.fetch_add(1, std::memory_order_relaxed); |
727 | Key k = st->key ^ Zobrist::side; |
728 | |
729 | // Copy some fields of the old state to our new StateInfo object except the |
730 | // ones which are going to be recalculated from scratch anyway and then switch |
731 | // our state pointer to point to the new (ready to be updated) state. |
732 | std::memcpy(&newSt, st, offsetof(StateInfo, key)); |
733 | newSt.previous = st; |
734 | st = &newSt; |
735 | |
736 | // Increment ply counters. In particular, rule50 will be reset to zero later on |
737 | // in case of a capture or a pawn move. |
738 | ++gamePly; |
739 | ++st->rule50; |
740 | ++st->pliesFromNull; |
741 | |
742 | Color us = sideToMove; |
743 | Color them = ~us; |
744 | Square from = from_sq(m); |
745 | Square to = to_sq(m); |
746 | Piece pc = piece_on(from); |
747 | Piece captured = type_of(m) == ENPASSANT ? make_piece(them, PAWN) : piece_on(to); |
748 | |
749 | assert(color_of(pc) == us); |
750 | assert(captured == NO_PIECE || color_of(captured) == (type_of(m) != CASTLING ? them : us)); |
751 | assert(type_of(captured) != KING); |
752 | |
753 | if (type_of(m) == CASTLING) |
754 | { |
755 | assert(pc == make_piece(us, KING)); |
756 | assert(captured == make_piece(us, ROOK)); |
757 | |
758 | Square rfrom, rto; |
759 | do_castling<true>(us, from, to, rfrom, rto); |
760 | |
761 | k ^= Zobrist::psq[captured][rfrom] ^ Zobrist::psq[captured][rto]; |
762 | captured = NO_PIECE; |
763 | } |
764 | |
765 | if (captured) |
766 | { |
767 | Square capsq = to; |
768 | |
769 | // If the captured piece is a pawn, update pawn hash key, otherwise |
770 | // update non-pawn material. |
771 | if (type_of(captured) == PAWN) |
772 | { |
773 | if (type_of(m) == ENPASSANT) |
774 | { |
775 | capsq -= pawn_push(us); |
776 | |
777 | assert(pc == make_piece(us, PAWN)); |
778 | assert(to == st->epSquare); |
779 | assert(relative_rank(us, to) == RANK_6); |
780 | assert(piece_on(to) == NO_PIECE); |
781 | assert(piece_on(capsq) == make_piece(them, PAWN)); |
782 | |
783 | board[capsq] = NO_PIECE; // Not done by remove_piece() |
784 | } |
785 | |
786 | st->pawnKey ^= Zobrist::psq[captured][capsq]; |
787 | } |
788 | else |
789 | st->nonPawnMaterial[them] -= PieceValue[MG][captured]; |
790 | |
791 | // Update board and piece lists |
792 | remove_piece(captured, capsq); |
793 | |
794 | // Update material hash key and prefetch access to materialTable |
795 | k ^= Zobrist::psq[captured][capsq]; |
796 | st->materialKey ^= Zobrist::psq[captured][pieceCount[captured]]; |
797 | prefetch(thisThread->materialTable[st->materialKey]); |
798 | |
799 | // Reset rule 50 counter |
800 | st->rule50 = 0; |
801 | } |
802 | |
803 | // Update hash key |
804 | k ^= Zobrist::psq[pc][from] ^ Zobrist::psq[pc][to]; |
805 | |
806 | // Reset en passant square |
807 | if (st->epSquare != SQ_NONE) |
808 | { |
809 | k ^= Zobrist::enpassant[file_of(st->epSquare)]; |
810 | st->epSquare = SQ_NONE; |
811 | } |
812 | |
813 | // Update castling rights if needed |
814 | if (st->castlingRights && (castlingRightsMask[from] | castlingRightsMask[to])) |
815 | { |
816 | int cr = castlingRightsMask[from] | castlingRightsMask[to]; |
817 | k ^= Zobrist::castling[st->castlingRights & cr]; |
818 | st->castlingRights &= ~cr; |
819 | } |
820 | |
821 | // Move the piece. The tricky Chess960 castling is handled earlier |
822 | if (type_of(m) != CASTLING) |
823 | move_piece(pc, from, to); |
824 | |
825 | // If the moving piece is a pawn do some special extra work |
826 | if (type_of(pc) == PAWN) |
827 | { |
828 | // Set en-passant square if the moved pawn can be captured |
829 | if ( (int(to) ^ int(from)) == 16 |
830 | && (attacks_from<PAWN>(to - pawn_push(us), us) & pieces(them, PAWN))) |
831 | { |
832 | st->epSquare = to - pawn_push(us); |
833 | k ^= Zobrist::enpassant[file_of(st->epSquare)]; |
834 | } |
835 | |
836 | else if (type_of(m) == PROMOTION) |
837 | { |
838 | Piece promotion = make_piece(us, promotion_type(m)); |
839 | |
840 | assert(relative_rank(us, to) == RANK_8); |
841 | assert(type_of(promotion) >= KNIGHT && type_of(promotion) <= QUEEN); |
842 | |
843 | remove_piece(pc, to); |
844 | put_piece(promotion, to); |
845 | |
846 | // Update hash keys |
847 | k ^= Zobrist::psq[pc][to] ^ Zobrist::psq[promotion][to]; |
848 | st->pawnKey ^= Zobrist::psq[pc][to]; |
849 | st->materialKey ^= Zobrist::psq[promotion][pieceCount[promotion]-1] |
850 | ^ Zobrist::psq[pc][pieceCount[pc]]; |
851 | |
852 | // Update material |
853 | st->nonPawnMaterial[us] += PieceValue[MG][promotion]; |
854 | } |
855 | |
856 | // Update pawn hash key and prefetch access to pawnsTable |
857 | st->pawnKey ^= Zobrist::psq[pc][from] ^ Zobrist::psq[pc][to]; |
858 | |
859 | // Reset rule 50 draw counter |
860 | st->rule50 = 0; |
861 | } |
862 | |
863 | // Set capture piece |
864 | st->capturedPiece = captured; |
865 | |
866 | // Update the key with the final value |
867 | st->key = k; |
868 | |
869 | // Calculate checkers bitboard (if move gives check) |
870 | st->checkersBB = givesCheck ? attackers_to(square<KING>(them)) & pieces(us) : 0; |
871 | |
872 | sideToMove = ~sideToMove; |
873 | |
874 | // Update king attacks used for fast check detection |
875 | set_check_info(st); |
876 | |
877 | // Calculate the repetition info. It is the ply distance from the previous |
878 | // occurrence of the same position, negative in the 3-fold case, or zero |
879 | // if the position was not repeated. |
880 | st->repetition = 0; |
881 | int end = std::min(st->rule50, st->pliesFromNull); |
882 | if (end >= 4) |
883 | { |
884 | StateInfo* stp = st->previous->previous; |
885 | for (int i = 4; i <= end; i += 2) |
886 | { |
887 | stp = stp->previous->previous; |
888 | if (stp->key == st->key) |
889 | { |
890 | st->repetition = stp->repetition ? -i : i; |
891 | break; |
892 | } |
893 | } |
894 | } |
895 | |
896 | assert(pos_is_ok()); |
897 | } |
898 | |
899 | |
900 | /// Position::undo_move() unmakes a move. When it returns, the position should |
901 | /// be restored to exactly the same state as before the move was made. |
902 | |
903 | void Position::undo_move(Move m) { |
904 | |
905 | assert(is_ok(m)); |
906 | |
907 | sideToMove = ~sideToMove; |
908 | |
909 | Color us = sideToMove; |
910 | Square from = from_sq(m); |
911 | Square to = to_sq(m); |
912 | Piece pc = piece_on(to); |
913 | |
914 | assert(empty(from) || type_of(m) == CASTLING); |
915 | assert(type_of(st->capturedPiece) != KING); |
916 | |
917 | if (type_of(m) == PROMOTION) |
918 | { |
919 | assert(relative_rank(us, to) == RANK_8); |
920 | assert(type_of(pc) == promotion_type(m)); |
921 | assert(type_of(pc) >= KNIGHT && type_of(pc) <= QUEEN); |
922 | |
923 | remove_piece(pc, to); |
924 | pc = make_piece(us, PAWN); |
925 | put_piece(pc, to); |
926 | } |
927 | |
928 | if (type_of(m) == CASTLING) |
929 | { |
930 | Square rfrom, rto; |
931 | do_castling<false>(us, from, to, rfrom, rto); |
932 | } |
933 | else |
934 | { |
935 | move_piece(pc, to, from); // Put the piece back at the source square |
936 | |
937 | if (st->capturedPiece) |
938 | { |
939 | Square capsq = to; |
940 | |
941 | if (type_of(m) == ENPASSANT) |
942 | { |
943 | capsq -= pawn_push(us); |
944 | |
945 | assert(type_of(pc) == PAWN); |
946 | assert(to == st->previous->epSquare); |
947 | assert(relative_rank(us, to) == RANK_6); |
948 | assert(piece_on(capsq) == NO_PIECE); |
949 | assert(st->capturedPiece == make_piece(~us, PAWN)); |
950 | } |
951 | |
952 | put_piece(st->capturedPiece, capsq); // Restore the captured piece |
953 | } |
954 | } |
955 | |
956 | // Finally point our state pointer back to the previous state |
957 | st = st->previous; |
958 | --gamePly; |
959 | |
960 | assert(pos_is_ok()); |
961 | } |
962 | |
963 | |
964 | /// Position::do_castling() is a helper used to do/undo a castling move. This |
965 | /// is a bit tricky in Chess960 where from/to squares can overlap. |
966 | template<bool Do> |
967 | void Position::do_castling(Color us, Square from, Square& to, Square& rfrom, Square& rto) { |
968 | |
969 | bool kingSide = to > from; |
970 | rfrom = to; // Castling is encoded as "king captures friendly rook" |
971 | rto = relative_square(us, kingSide ? SQ_F1 : SQ_D1); |
972 | to = relative_square(us, kingSide ? SQ_G1 : SQ_C1); |
973 | |
974 | // Remove both pieces first since squares could overlap in Chess960 |
975 | remove_piece(make_piece(us, KING), Do ? from : to); |
976 | remove_piece(make_piece(us, ROOK), Do ? rfrom : rto); |
977 | board[Do ? from : to] = board[Do ? rfrom : rto] = NO_PIECE; // Since remove_piece doesn't do it for us |
978 | put_piece(make_piece(us, KING), Do ? to : from); |
979 | put_piece(make_piece(us, ROOK), Do ? rto : rfrom); |
980 | } |
981 | |
982 | |
983 | /// Position::do(undo)_null_move() is used to do(undo) a "null move": It flips |
984 | /// the side to move without executing any move on the board. |
985 | |
986 | void Position::do_null_move(StateInfo& newSt) { |
987 | |
988 | assert(!checkers()); |
989 | assert(&newSt != st); |
990 | |
991 | std::memcpy(&newSt, st, sizeof(StateInfo)); |
992 | newSt.previous = st; |
993 | st = &newSt; |
994 | |
995 | if (st->epSquare != SQ_NONE) |
996 | { |
997 | st->key ^= Zobrist::enpassant[file_of(st->epSquare)]; |
998 | st->epSquare = SQ_NONE; |
999 | } |
1000 | |
1001 | st->key ^= Zobrist::side; |
1002 | prefetch(TT.first_entry(st->key)); |
1003 | |
1004 | ++st->rule50; |
1005 | st->pliesFromNull = 0; |
1006 | |
1007 | sideToMove = ~sideToMove; |
1008 | |
1009 | set_check_info(st); |
1010 | |
1011 | st->repetition = 0; |
1012 | |
1013 | assert(pos_is_ok()); |
1014 | } |
1015 | |
1016 | void Position::undo_null_move() { |
1017 | |
1018 | assert(!checkers()); |
1019 | |
1020 | st = st->previous; |
1021 | sideToMove = ~sideToMove; |
1022 | } |
1023 | |
1024 | |
1025 | /// Position::key_after() computes the new hash key after the given move. Needed |
1026 | /// for speculative prefetch. It doesn't recognize special moves like castling, |
1027 | /// en-passant and promotions. |
1028 | |
1029 | Key Position::key_after(Move m) const { |
1030 | |
1031 | Square from = from_sq(m); |
1032 | Square to = to_sq(m); |
1033 | Piece pc = piece_on(from); |
1034 | Piece captured = piece_on(to); |
1035 | Key k = st->key ^ Zobrist::side; |
1036 | |
1037 | if (captured) |
1038 | k ^= Zobrist::psq[captured][to]; |
1039 | |
1040 | return k ^ Zobrist::psq[pc][to] ^ Zobrist::psq[pc][from]; |
1041 | } |
1042 | |
1043 | |
1044 | /// Position::see_ge (Static Exchange Evaluation Greater or Equal) tests if the |
1045 | /// SEE value of move is greater or equal to the given threshold. We'll use an |
1046 | /// algorithm similar to alpha-beta pruning with a null window. |
1047 | |
1048 | bool Position::see_ge(Move m, Value threshold) const { |
1049 | |
1050 | assert(is_ok(m)); |
1051 | |
1052 | // Only deal with normal moves, assume others pass a simple see |
1053 | if (type_of(m) != NORMAL) |
1054 | return VALUE_ZERO >= threshold; |
1055 | |
1056 | Bitboard stmAttackers; |
1057 | Square from = from_sq(m), to = to_sq(m); |
1058 | PieceType nextVictim = type_of(piece_on(from)); |
1059 | Color us = color_of(piece_on(from)); |
1060 | Color stm = ~us; // First consider opponent's move |
1061 | Value balance; // Values of the pieces taken by us minus opponent's ones |
1062 | |
1063 | // The opponent may be able to recapture so this is the best result |
1064 | // we can hope for. |
1065 | balance = PieceValue[MG][piece_on(to)] - threshold; |
1066 | |
1067 | if (balance < VALUE_ZERO) |
1068 | return false; |
1069 | |
1070 | // Now assume the worst possible result: that the opponent can |
1071 | // capture our piece for free. |
1072 | balance -= PieceValue[MG][nextVictim]; |
1073 | |
1074 | // If it is enough (like in PxQ) then return immediately. Note that |
1075 | // in case nextVictim == KING we always return here, this is ok |
1076 | // if the given move is legal. |
1077 | if (balance >= VALUE_ZERO) |
1078 | return true; |
1079 | |
1080 | // Find all attackers to the destination square, with the moving piece |
1081 | // removed, but possibly an X-ray attacker added behind it. |
1082 | Bitboard occupied = pieces() ^ from ^ to; |
1083 | Bitboard attackers = attackers_to(to, occupied) & occupied; |
1084 | |
1085 | while (true) |
1086 | { |
1087 | stmAttackers = attackers & pieces(stm); |
1088 | |
1089 | // Don't allow pinned pieces to attack (except the king) as long as |
1090 | // any pinners are on their original square. |
1091 | if (st->pinners[~stm] & occupied) |
1092 | stmAttackers &= ~st->blockersForKing[stm]; |
1093 | |
1094 | // If stm has no more attackers then give up: stm loses |
1095 | if (!stmAttackers) |
1096 | break; |
1097 | |
1098 | // Locate and remove the next least valuable attacker, and add to |
1099 | // the bitboard 'attackers' the possibly X-ray attackers behind it. |
1100 | nextVictim = min_attacker<PAWN>(byTypeBB, to, stmAttackers, occupied, attackers); |
1101 | |
1102 | stm = ~stm; // Switch side to move |
1103 | |
1104 | // Negamax the balance with alpha = balance, beta = balance+1 and |
1105 | // add nextVictim's value. |
1106 | // |
1107 | // (balance, balance+1) -> (-balance-1, -balance) |
1108 | // |
1109 | assert(balance < VALUE_ZERO); |
1110 | |
1111 | balance = -balance - 1 - PieceValue[MG][nextVictim]; |
1112 | |
1113 | // If balance is still non-negative after giving away nextVictim then we |
1114 | // win. The only thing to be careful about it is that we should revert |
1115 | // stm if we captured with the king when the opponent still has attackers. |
1116 | if (balance >= VALUE_ZERO) |
1117 | { |
1118 | if (nextVictim == KING && (attackers & pieces(stm))) |
1119 | stm = ~stm; |
1120 | break; |
1121 | } |
1122 | assert(nextVictim != KING); |
1123 | } |
1124 | return us != stm; // We break the above loop when stm loses |
1125 | } |
1126 | |
1127 | |
1128 | /// Position::is_draw() tests whether the position is drawn by 50-move rule |
1129 | /// or by repetition. It does not detect stalemates. |
1130 | |
1131 | bool Position::is_draw(int ply) const { |
1132 | |
1133 | if (st->rule50 > 99 && (!checkers() || MoveList<LEGAL>(*this).size())) |
1134 | return true; |
1135 | |
1136 | // Return a draw score if a position repeats once earlier but strictly |
1137 | // after the root, or repeats twice before or at the root. |
1138 | if (st->repetition && st->repetition < ply) |
1139 | return true; |
1140 | |
1141 | return false; |
1142 | } |
1143 | |
1144 | |
1145 | // Position::has_repeated() tests whether there has been at least one repetition |
1146 | // of positions since the last capture or pawn move. |
1147 | |
1148 | bool Position::has_repeated() const { |
1149 | |
1150 | StateInfo* stc = st; |
1151 | int end = std::min(st->rule50, st->pliesFromNull); |
1152 | while (end-- >= 4) |
1153 | { |
1154 | if (stc->repetition) |
1155 | return true; |
1156 | |
1157 | stc = stc->previous; |
1158 | } |
1159 | return false; |
1160 | } |
1161 | |
1162 | |
1163 | /// Position::has_game_cycle() tests if the position has a move which draws by repetition, |
1164 | /// or an earlier position has a move that directly reaches the current position. |
1165 | |
1166 | bool Position::has_game_cycle(int ply) const { |
1167 | |
1168 | int j; |
1169 | |
1170 | int end = std::min(st->rule50, st->pliesFromNull); |
1171 | |
1172 | if (end < 3) |
1173 | return false; |
1174 | |
1175 | Key originalKey = st->key; |
1176 | StateInfo* stp = st->previous; |
1177 | |
1178 | for (int i = 3; i <= end; i += 2) |
1179 | { |
1180 | stp = stp->previous->previous; |
1181 | |
1182 | Key moveKey = originalKey ^ stp->key; |
1183 | if ( (j = H1(moveKey), cuckoo[j] == moveKey) |
1184 | || (j = H2(moveKey), cuckoo[j] == moveKey)) |
1185 | { |
1186 | Move move = cuckooMove[j]; |
1187 | Square s1 = from_sq(move); |
1188 | Square s2 = to_sq(move); |
1189 | |
1190 | if (!(between_bb(s1, s2) & pieces())) |
1191 | { |
1192 | if (ply > i) |
1193 | return true; |
1194 | |
1195 | // For nodes before or at the root, check that the move is a |
1196 | // repetition rather than a move to the current position. |
1197 | // In the cuckoo table, both moves Rc1c5 and Rc5c1 are stored in |
1198 | // the same location, so we have to select which square to check. |
1199 | if (color_of(piece_on(empty(s1) ? s2 : s1)) != side_to_move()) |
1200 | continue; |
1201 | |
1202 | // For repetitions before or at the root, require one more |
1203 | if (stp->repetition) |
1204 | return true; |
1205 | } |
1206 | } |
1207 | } |
1208 | return false; |
1209 | } |
1210 | |
1211 | |
1212 | /// Position::flip() flips position with the white and black sides reversed. This |
1213 | /// is only useful for debugging e.g. for finding evaluation symmetry bugs. |
1214 | |
1215 | void Position::flip() { |
1216 | |
1217 | string f, token; |
1218 | std::stringstream ss(fen()); |
1219 | |
1220 | for (Rank r = RANK_8; r >= RANK_1; --r) // Piece placement |
1221 | { |
1222 | std::getline(ss, token, r > RANK_1 ? '/' : ' '); |
1223 | f.insert(0, token + (f.empty() ? " " : "/" )); |
1224 | } |
1225 | |
1226 | ss >> token; // Active color |
1227 | f += (token == "w" ? "B " : "W " ); // Will be lowercased later |
1228 | |
1229 | ss >> token; // Castling availability |
1230 | f += token + " " ; |
1231 | |
1232 | std::transform(f.begin(), f.end(), f.begin(), |
1233 | [](char c) { return char(islower(c) ? toupper(c) : tolower(c)); }); |
1234 | |
1235 | ss >> token; // En passant square |
1236 | f += (token == "-" ? token : token.replace(1, 1, token[1] == '3' ? "6" : "3" )); |
1237 | |
1238 | std::getline(ss, token); // Half and full moves |
1239 | f += token; |
1240 | |
1241 | set(f, is_chess960(), st, this_thread()); |
1242 | |
1243 | assert(pos_is_ok()); |
1244 | } |
1245 | |
1246 | |
1247 | /// Position::pos_is_ok() performs some consistency checks for the |
1248 | /// position object and raises an asserts if something wrong is detected. |
1249 | /// This is meant to be helpful when debugging. |
1250 | |
1251 | bool Position::pos_is_ok() const { |
1252 | |
1253 | constexpr bool Fast = true; // Quick (default) or full check? |
1254 | |
1255 | if ( (sideToMove != WHITE && sideToMove != BLACK) |
1256 | || piece_on(square<KING>(WHITE)) != W_KING |
1257 | || piece_on(square<KING>(BLACK)) != B_KING |
1258 | || ( ep_square() != SQ_NONE |
1259 | && relative_rank(sideToMove, ep_square()) != RANK_6)) |
1260 | assert(0 && "pos_is_ok: Default" ); |
1261 | |
1262 | if (Fast) |
1263 | return true; |
1264 | |
1265 | if ( pieceCount[W_KING] != 1 |
1266 | || pieceCount[B_KING] != 1 |
1267 | || attackers_to(square<KING>(~sideToMove)) & pieces(sideToMove)) |
1268 | assert(0 && "pos_is_ok: Kings" ); |
1269 | |
1270 | if ( (pieces(PAWN) & (Rank1BB | Rank8BB)) |
1271 | || pieceCount[W_PAWN] > 8 |
1272 | || pieceCount[B_PAWN] > 8) |
1273 | assert(0 && "pos_is_ok: Pawns" ); |
1274 | |
1275 | if ( (pieces(WHITE) & pieces(BLACK)) |
1276 | || (pieces(WHITE) | pieces(BLACK)) != pieces() |
1277 | || popcount(pieces(WHITE)) > 16 |
1278 | || popcount(pieces(BLACK)) > 16) |
1279 | assert(0 && "pos_is_ok: Bitboards" ); |
1280 | |
1281 | for (PieceType p1 = PAWN; p1 <= KING; ++p1) |
1282 | for (PieceType p2 = PAWN; p2 <= KING; ++p2) |
1283 | if (p1 != p2 && (pieces(p1) & pieces(p2))) |
1284 | assert(0 && "pos_is_ok: Bitboards" ); |
1285 | |
1286 | StateInfo si = *st; |
1287 | set_state(&si); |
1288 | if (std::memcmp(&si, st, sizeof(StateInfo))) |
1289 | assert(0 && "pos_is_ok: State" ); |
1290 | |
1291 | for (Piece pc : Pieces) |
1292 | { |
1293 | if ( pieceCount[pc] != popcount(pieces(color_of(pc), type_of(pc))) |
1294 | || pieceCount[pc] != std::count(board, board + SQUARE_NB, pc)) |
1295 | assert(0 && "pos_is_ok: Pieces" ); |
1296 | |
1297 | for (int i = 0; i < pieceCount[pc]; ++i) |
1298 | if (board[pieceList[pc][i]] != pc || index[pieceList[pc][i]] != i) |
1299 | assert(0 && "pos_is_ok: Index" ); |
1300 | } |
1301 | |
1302 | for (Color c : { WHITE, BLACK }) |
1303 | for (CastlingSide s : {KING_SIDE, QUEEN_SIDE}) |
1304 | { |
1305 | if (!can_castle(c | s)) |
1306 | continue; |
1307 | |
1308 | if ( piece_on(castlingRookSquare[c | s]) != make_piece(c, ROOK) |
1309 | || castlingRightsMask[castlingRookSquare[c | s]] != (c | s) |
1310 | || (castlingRightsMask[square<KING>(c)] & (c | s)) != (c | s)) |
1311 | assert(0 && "pos_is_ok: Castling" ); |
1312 | } |
1313 | |
1314 | return true; |
1315 | } |
1316 | |