Rev 169 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 169 | Rev 185 | ||
---|---|---|---|
Line 4... | Line 4... | ||
4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad |
4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad |
5 | Copyright (C) 2015- |
5 | Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad |
6 | 6 | ||
7 | Stockfish is free software: you can redistribute it and/or modify |
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 |
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 |
9 | the Free Software Foundation, either version 3 of the License, or |
10 | (at your option) any later version. |
10 | (at your option) any later version. |
Line 33... | Line 33... | ||
33 | #include "tt.h" |
33 | #include "tt.h" |
34 | #include "uci.h" |
34 | #include "uci.h" |
35 | #include "syzygy/tbprobe.h" |
35 | #include "syzygy/tbprobe.h" |
36 | 36 | ||
37 | using std::string; |
37 | using std::string; |
38 | - | ||
39 | namespace PSQT { |
- | |
40 | extern Score psq[PIECE_NB][SQUARE_NB]; |
- | |
41 | } |
- | |
42 | 38 | ||
43 | namespace Zobrist { |
39 | namespace Zobrist { |
44 | 40 | ||
45 | Key psq[PIECE_NB][SQUARE_NB]; |
41 | Key psq[PIECE_NB][SQUARE_NB]; |
46 | Key enpassant[FILE_NB]; |
42 | Key enpassant[FILE_NB]; |
Line 50... | Line 46... | ||
50 | 46 | ||
51 | namespace { |
47 | namespace { |
52 | 48 | ||
53 | const string PieceToChar(" PNBRQK pnbrqk"); |
49 | const string PieceToChar(" PNBRQK pnbrqk"); |
54 | 50 | ||
55 |
|
51 | constexpr Piece Pieces[] = { W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING, |
56 | B_PAWN, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING }; |
52 | B_PAWN, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING }; |
57 | 53 | ||
58 | // min_attacker() is a helper function used by see_ge() to locate the least |
54 | // min_attacker() is a helper function used by see_ge() to locate the least |
59 | // valuable attacker for the side to move, remove the attacker we just found |
55 | // valuable attacker for the side to move, remove the attacker we just found |
60 | // from the bitboards and scan for new X-ray attacks behind it. |
56 | // from the bitboards and scan for new X-ray attacks behind it. |
61 | 57 | ||
62 | template<int Pt> |
58 | template<int Pt> |
63 | PieceType min_attacker(const Bitboard* |
59 | PieceType min_attacker(const Bitboard* byTypeBB, Square to, Bitboard stmAttackers, |
64 | Bitboard& occupied, Bitboard& attackers) { |
60 | Bitboard& occupied, Bitboard& attackers) { |
65 | 61 | ||
66 | Bitboard b = stmAttackers & |
62 | Bitboard b = stmAttackers & byTypeBB[Pt]; |
67 | if (!b) |
63 | if (!b) |
68 | return min_attacker<Pt + 1>( |
64 | return min_attacker<Pt + 1>(byTypeBB, to, stmAttackers, occupied, attackers); |
69 | 65 | ||
70 | occupied ^= |
66 | occupied ^= lsb(b); // Remove the attacker from occupied |
71 | 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. |
|
72 | if (Pt == PAWN || Pt == BISHOP || Pt == QUEEN) |
71 | if (Pt == PAWN || Pt == BISHOP || Pt == QUEEN) |
73 | attackers |= attacks_bb<BISHOP>(to, occupied) & ( |
72 | attackers |= attacks_bb<BISHOP>(to, occupied) & (byTypeBB[BISHOP] | byTypeBB[QUEEN]); |
74 | 73 | ||
75 | if (Pt == ROOK || Pt == QUEEN) |
74 | if (Pt == ROOK || Pt == QUEEN) |
76 | attackers |= attacks_bb<ROOK>(to, occupied) & ( |
75 | attackers |= attacks_bb<ROOK>(to, occupied) & (byTypeBB[ROOK] | byTypeBB[QUEEN]); |
77 | 76 | ||
- | 77 | // X-ray may add already processed pieces because byTypeBB[] is constant: in |
|
78 |
|
78 | // the rook example, now attackers contains _again_ rook in a7, so remove it. |
- | 79 | attackers &= occupied; |
|
79 | return (PieceType)Pt; |
80 | return (PieceType)Pt; |
80 | } |
81 | } |
81 | 82 | ||
82 | template<> |
83 | template<> |
83 | PieceType min_attacker<KING>(const Bitboard*, Square, Bitboard, Bitboard&, Bitboard&) { |
84 | PieceType min_attacker<KING>(const Bitboard*, Square, Bitboard, Bitboard&, Bitboard&) { |
Line 121... | Line 122... | ||
121 | << "\nTablebases DTZ: " << std::setw(4) << dtz << " (" << s2 << ")"; |
122 | << "\nTablebases DTZ: " << std::setw(4) << dtz << " (" << s2 << ")"; |
122 | } |
123 | } |
123 | 124 | ||
124 | return os; |
125 | return os; |
125 | } |
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]; |
|
126 | 140 | ||
127 | 141 | ||
128 | /// Position::init() initializes at startup the various arrays used to compute |
142 | /// Position::init() initializes at startup the various arrays used to compute |
129 | /// hash keys. |
143 | /// hash keys. |
130 | 144 | ||
Line 150... | Line 164... | ||
150 | } |
164 | } |
151 | } |
165 | } |
152 | 166 | ||
153 | Zobrist::side = rng.rand<Key>(); |
167 | Zobrist::side = rng.rand<Key>(); |
154 | Zobrist::noPawns = 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 == 0) // 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); |
|
155 | } |
193 | } |
156 | 194 | ||
157 | 195 | ||
158 | /// Position::set() initializes the position object with the given FEN string. |
196 | /// Position::set() initializes the position object with the given FEN string. |
159 | /// This function is not very robust - make sure that input FENs are correct, |
197 | /// This function is not very robust - make sure that input FENs are correct, |
Line 315... | Line 353... | ||
315 | 353 | ||
316 | /// Position::set_check_info() sets king attacks to detect if a move gives check |
354 | /// Position::set_check_info() sets king attacks to detect if a move gives check |
317 | 355 | ||
318 | void Position::set_check_info(StateInfo* si) const { |
356 | void Position::set_check_info(StateInfo* si) const { |
319 | 357 | ||
320 | si->blockersForKing[WHITE] = slider_blockers(pieces(BLACK), square<KING>(WHITE), si-> |
358 | si->blockersForKing[WHITE] = slider_blockers(pieces(BLACK), square<KING>(WHITE), si->pinners[BLACK]); |
321 | si->blockersForKing[BLACK] = slider_blockers(pieces(WHITE), square<KING>(BLACK), si-> |
359 | si->blockersForKing[BLACK] = slider_blockers(pieces(WHITE), square<KING>(BLACK), si->pinners[WHITE]); |
322 | 360 | ||
323 | Square ksq = square<KING>(~sideToMove); |
361 | Square ksq = square<KING>(~sideToMove); |
324 | 362 | ||
325 | si->checkSquares[PAWN] = attacks_from<PAWN>(ksq, ~sideToMove); |
363 | si->checkSquares[PAWN] = attacks_from<PAWN>(ksq, ~sideToMove); |
326 | si->checkSquares[KNIGHT] = attacks_from<KNIGHT>(ksq); |
364 | si->checkSquares[KNIGHT] = attacks_from<KNIGHT>(ksq); |
Line 339... | Line 377... | ||
339 | void Position::set_state(StateInfo* si) const { |
377 | void Position::set_state(StateInfo* si) const { |
340 | 378 | ||
341 | si->key = si->materialKey = 0; |
379 | si->key = si->materialKey = 0; |
342 | si->pawnKey = Zobrist::noPawns; |
380 | si->pawnKey = Zobrist::noPawns; |
343 | si->nonPawnMaterial[WHITE] = si->nonPawnMaterial[BLACK] = VALUE_ZERO; |
381 | si->nonPawnMaterial[WHITE] = si->nonPawnMaterial[BLACK] = VALUE_ZERO; |
344 | si->psq = SCORE_ZERO; |
- | |
345 | si->checkersBB = attackers_to(square<KING>(sideToMove)) & pieces(~sideToMove); |
382 | si->checkersBB = attackers_to(square<KING>(sideToMove)) & pieces(~sideToMove); |
346 | 383 | ||
347 | set_check_info(si); |
384 | set_check_info(si); |
348 | 385 | ||
349 | for (Bitboard b = pieces(); b; ) |
386 | for (Bitboard b = pieces(); b; ) |
350 | { |
387 | { |
351 | Square s = pop_lsb(&b); |
388 | Square s = pop_lsb(&b); |
352 | Piece pc = piece_on(s); |
389 | Piece pc = piece_on(s); |
353 | si->key ^= Zobrist::psq[pc][s]; |
390 | si->key ^= Zobrist::psq[pc][s]; |
354 | si->psq += PSQT::psq[pc][s]; |
- | |
355 | } |
391 | } |
356 | 392 | ||
357 | if (si->epSquare != SQ_NONE) |
393 | if (si->epSquare != SQ_NONE) |
358 | si->key ^= Zobrist::enpassant[file_of(si->epSquare)]; |
394 | si->key ^= Zobrist::enpassant[file_of(si->epSquare)]; |
359 | 395 | ||
Line 457... | Line 493... | ||
457 | /// a pinned or a discovered check piece, according if its color is the opposite |
493 | /// a pinned or a discovered check piece, according if its color is the opposite |
458 | /// or the same of the color of the slider. |
494 | /// or the same of the color of the slider. |
459 | 495 | ||
460 | Bitboard Position::slider_blockers(Bitboard sliders, Square s, Bitboard& pinners) const { |
496 | Bitboard Position::slider_blockers(Bitboard sliders, Square s, Bitboard& pinners) const { |
461 | 497 | ||
462 | Bitboard |
498 | Bitboard blockers = 0; |
463 | pinners = 0; |
499 | pinners = 0; |
464 | 500 | ||
465 | // Snipers are sliders that attack 's' when a piece is removed |
501 | // Snipers are sliders that attack 's' when a piece is removed |
466 | Bitboard snipers = ( (PseudoAttacks[ ROOK][s] & pieces(QUEEN, ROOK)) |
502 | Bitboard snipers = ( (PseudoAttacks[ ROOK][s] & pieces(QUEEN, ROOK)) |
467 | | (PseudoAttacks[BISHOP][s] & pieces(QUEEN, BISHOP))) & sliders; |
503 | | (PseudoAttacks[BISHOP][s] & pieces(QUEEN, BISHOP))) & sliders; |
Line 469... | Line 505... | ||
469 | while (snipers) |
505 | while (snipers) |
470 | { |
506 | { |
471 | Square sniperSq = pop_lsb(&snipers); |
507 | Square sniperSq = pop_lsb(&snipers); |
472 | Bitboard b = between_bb(s, sniperSq) & pieces(); |
508 | Bitboard b = between_bb(s, sniperSq) & pieces(); |
473 | 509 | ||
474 | if (!more_than_one(b)) |
510 | if (b && !more_than_one(b)) |
475 | { |
511 | { |
476 |
|
512 | blockers |= b; |
477 | if (b & pieces(color_of(piece_on(s)))) |
513 | if (b & pieces(color_of(piece_on(s)))) |
478 | pinners |= sniperSq; |
514 | pinners |= sniperSq; |
479 | } |
515 | } |
480 | } |
516 | } |
481 | return |
517 | return blockers; |
482 | } |
518 | } |
483 | 519 | ||
484 | 520 | ||
485 | /// Position::attackers_to() computes a bitboard of all pieces which attack a |
521 | /// Position::attackers_to() computes a bitboard of all pieces which attack a |
486 | /// given square. Slider attacks use the occupied bitboard to indicate occupancy. |
522 | /// given square. Slider attacks use the occupied bitboard to indicate occupancy. |
Line 533... | Line 569... | ||
533 | if (type_of(piece_on(from)) == KING) |
569 | if (type_of(piece_on(from)) == KING) |
534 | return type_of(m) == CASTLING || !(attackers_to(to_sq(m)) & pieces(~us)); |
570 | return type_of(m) == CASTLING || !(attackers_to(to_sq(m)) & pieces(~us)); |
535 | 571 | ||
536 | // A non-king move is legal if and only if it is not pinned or it |
572 | // A non-king move is legal if and only if it is not pinned or it |
537 | // is moving along the ray towards or away from the king. |
573 | // is moving along the ray towards or away from the king. |
538 | return !( |
574 | return !(blockers_for_king(us) & from) |
539 | || aligned(from, to_sq(m), square<KING>(us)); |
575 | || aligned(from, to_sq(m), square<KING>(us)); |
540 | } |
576 | } |
541 | 577 | ||
542 | 578 | ||
543 | /// Position::pseudo_legal() takes a random move and tests whether the move is |
579 | /// Position::pseudo_legal() takes a random move and tests whether the move is |
Line 625... | Line 661... | ||
625 | // Is there a direct check? |
661 | // Is there a direct check? |
626 | if (st->checkSquares[type_of(piece_on(from))] & to) |
662 | if (st->checkSquares[type_of(piece_on(from))] & to) |
627 | return true; |
663 | return true; |
628 | 664 | ||
629 | // Is there a discovered check? |
665 | // Is there a discovered check? |
630 | if ( ( |
666 | if ( (st->blockersForKing[~sideToMove] & from) |
631 | && !aligned(from, to, square<KING>(~sideToMove))) |
667 | && !aligned(from, to, square<KING>(~sideToMove))) |
632 | return true; |
668 | return true; |
633 | 669 | ||
634 | switch (type_of(m)) |
670 | switch (type_of(m)) |
635 | { |
671 | { |
Line 710... | Line 746... | ||
710 | assert(captured == make_piece(us, ROOK)); |
746 | assert(captured == make_piece(us, ROOK)); |
711 | 747 | ||
712 | Square rfrom, rto; |
748 | Square rfrom, rto; |
713 | do_castling<true>(us, from, to, rfrom, rto); |
749 | do_castling<true>(us, from, to, rfrom, rto); |
714 | 750 | ||
715 | st->psq += PSQT::psq[captured][rto] - PSQT::psq[captured][rfrom]; |
- | |
716 | k ^= Zobrist::psq[captured][rfrom] ^ Zobrist::psq[captured][rto]; |
751 | k ^= Zobrist::psq[captured][rfrom] ^ Zobrist::psq[captured][rto]; |
717 | captured = NO_PIECE; |
752 | captured = NO_PIECE; |
718 | } |
753 | } |
719 | 754 | ||
720 | if (captured) |
755 | if (captured) |
Line 748... | Line 783... | ||
748 | 783 | ||
749 | // Update material hash key and prefetch access to materialTable |
784 | // Update material hash key and prefetch access to materialTable |
750 | k ^= Zobrist::psq[captured][capsq]; |
785 | k ^= Zobrist::psq[captured][capsq]; |
751 | st->materialKey ^= Zobrist::psq[captured][pieceCount[captured]]; |
786 | st->materialKey ^= Zobrist::psq[captured][pieceCount[captured]]; |
752 | prefetch(thisThread->materialTable[st->materialKey]); |
787 | prefetch(thisThread->materialTable[st->materialKey]); |
753 | - | ||
754 | // Update incremental scores |
- | |
755 | st->psq -= PSQT::psq[captured][capsq]; |
- | |
756 | 788 | ||
757 | // Reset rule 50 counter |
789 | // Reset rule 50 counter |
758 | st->rule50 = 0; |
790 | st->rule50 = 0; |
759 | } |
791 | } |
760 | 792 | ||
Line 804... | Line 836... | ||
804 | // Update hash keys |
836 | // Update hash keys |
805 | k ^= Zobrist::psq[pc][to] ^ Zobrist::psq[promotion][to]; |
837 | k ^= Zobrist::psq[pc][to] ^ Zobrist::psq[promotion][to]; |
806 | st->pawnKey ^= Zobrist::psq[pc][to]; |
838 | st->pawnKey ^= Zobrist::psq[pc][to]; |
807 | st->materialKey ^= Zobrist::psq[promotion][pieceCount[promotion]-1] |
839 | st->materialKey ^= Zobrist::psq[promotion][pieceCount[promotion]-1] |
808 | ^ Zobrist::psq[pc][pieceCount[pc]]; |
840 | ^ Zobrist::psq[pc][pieceCount[pc]]; |
809 | - | ||
810 | // Update incremental score |
- | |
811 | st->psq += PSQT::psq[promotion][to] - PSQT::psq[pc][to]; |
- | |
812 | 841 | ||
813 | // Update material |
842 | // Update material |
814 | st->nonPawnMaterial[us] += PieceValue[MG][promotion]; |
843 | st->nonPawnMaterial[us] += PieceValue[MG][promotion]; |
815 | } |
844 | } |
816 | 845 | ||
Line 819... | Line 848... | ||
819 | prefetch2(thisThread->pawnsTable[st->pawnKey]); |
848 | prefetch2(thisThread->pawnsTable[st->pawnKey]); |
820 | 849 | ||
821 | // Reset rule 50 draw counter |
850 | // Reset rule 50 draw counter |
822 | st->rule50 = 0; |
851 | st->rule50 = 0; |
823 | } |
852 | } |
824 | - | ||
825 | // Update incremental scores |
- | |
826 | st->psq += PSQT::psq[pc][to] - PSQT::psq[pc][from]; |
- | |
827 | 853 | ||
828 | // Set capture piece |
854 | // Set capture piece |
829 | st->capturedPiece = captured; |
855 | st->capturedPiece = captured; |
830 | 856 | ||
831 | // Update the key with the final value |
857 | // Update the key with the final value |
Line 995... | Line 1021... | ||
995 | 1021 | ||
996 | // Only deal with normal moves, assume others pass a simple see |
1022 | // Only deal with normal moves, assume others pass a simple see |
997 | if (type_of(m) != NORMAL) |
1023 | if (type_of(m) != NORMAL) |
998 | return VALUE_ZERO >= threshold; |
1024 | return VALUE_ZERO >= threshold; |
999 | 1025 | ||
- | 1026 | Bitboard stmAttackers; |
|
1000 | Square from = from_sq(m), to = to_sq(m); |
1027 | Square from = from_sq(m), to = to_sq(m); |
1001 | PieceType nextVictim = type_of(piece_on(from)); |
1028 | PieceType nextVictim = type_of(piece_on(from)); |
- | 1029 | Color us = color_of(piece_on(from)); |
|
1002 | Color stm = |
1030 | Color stm = ~us; // First consider opponent's move |
1003 | Value balance; // Values of the pieces taken by us minus opponent's ones |
1031 | Value balance; // Values of the pieces taken by us minus opponent's ones |
1004 | Bitboard occupied, stmAttackers; |
- | |
1005 | 1032 | ||
1006 | // The opponent may be able to recapture so this is the best result |
1033 | // The opponent may be able to recapture so this is the best result |
1007 | // we can hope for. |
1034 | // we can hope for. |
1008 | balance = PieceValue[MG][piece_on(to)] - threshold; |
1035 | balance = PieceValue[MG][piece_on(to)] - threshold; |
1009 | 1036 | ||
Line 1012... | Line 1039... | ||
1012 | 1039 | ||
1013 | // Now assume the worst possible result: that the opponent can |
1040 | // Now assume the worst possible result: that the opponent can |
1014 | // capture our piece for free. |
1041 | // capture our piece for free. |
1015 | balance -= PieceValue[MG][nextVictim]; |
1042 | balance -= PieceValue[MG][nextVictim]; |
1016 | 1043 | ||
- | 1044 | // If it is enough (like in PxQ) then return immediately. Note that |
|
1017 |
|
1045 | // in case nextVictim == KING we always return here, this is ok |
- | 1046 | // if the given move is legal. |
|
- | 1047 | if (balance >= VALUE_ZERO) |
|
1018 | return true; |
1048 | return true; |
1019 | 1049 | ||
1020 | bool opponentToMove = true; |
- | |
1021 | occupied = pieces() ^ from ^ to; |
- | |
1022 | - | ||
1023 | // Find all attackers to the destination square, with the moving piece |
1050 | // Find all attackers to the destination square, with the moving piece |
1024 | // but possibly an X-ray attacker added behind it. |
1051 | // removed, but possibly an X-ray attacker added behind it. |
- | 1052 | Bitboard occupied = pieces() ^ from ^ to; |
|
1025 | Bitboard attackers = attackers_to(to, occupied) & occupied; |
1053 | Bitboard attackers = attackers_to(to, occupied) & occupied; |
1026 | 1054 | ||
1027 | while (true) |
1055 | while (true) |
1028 | { |
1056 | { |
1029 | // The balance is negative only because we assumed we could win |
- | |
1030 | // the last piece for free. We are truly winning only if we can |
- | |
1031 | // win the last piece _cheaply enough_. Test if we can actually |
- | |
1032 | // do this otherwise "give up". |
- | |
1033 | assert(balance < VALUE_ZERO); |
- | |
1034 | - | ||
1035 | stmAttackers = attackers & pieces(stm); |
1057 | stmAttackers = attackers & pieces(stm); |
1036 | 1058 | ||
1037 | // Don't allow pinned pieces to attack |
1059 | // Don't allow pinned pieces to attack (except the king) as long as |
1038 | // pinners are on their original square. |
1060 | // all pinners are on their original square. |
1039 | if (!(st-> |
1061 | if (!(st->pinners[~stm] & ~occupied)) |
1040 | stmAttackers &= ~st->blockersForKing[stm]; |
1062 | stmAttackers &= ~st->blockersForKing[stm]; |
1041 | 1063 | ||
1042 | // If |
1064 | // If stm has no more attackers then give up: stm loses |
1043 | if (!stmAttackers) |
1065 | if (!stmAttackers) |
1044 | break; |
1066 | break; |
1045 | 1067 | ||
1046 | // Locate and remove the next least valuable |
1068 | // Locate and remove the next least valuable attacker, and add to |
- | 1069 | // the bitboard 'attackers' the possibly X-ray attackers behind it. |
|
1047 | nextVictim = min_attacker<PAWN>(byTypeBB, to, stmAttackers, occupied, attackers); |
1070 | nextVictim = min_attacker<PAWN>(byTypeBB, to, stmAttackers, occupied, attackers); |
1048 | 1071 | ||
1049 | if (nextVictim == KING) |
- | |
1050 | { |
- | |
1051 | // Our only attacker is the king. If the opponent still has |
- | |
1052 | // attackers we must give up. Otherwise we make the move and |
- | |
1053 | // (having no more attackers) the opponent must give up. |
- | |
1054 |
|
1072 | stm = ~stm; // Switch side to move |
1055 | opponentToMove = !opponentToMove; |
- | |
1056 | break; |
- | |
1057 | } |
- | |
1058 | 1073 | ||
1059 | // |
1074 | // Negamax the balance with alpha = balance, beta = balance+1 and |
- | 1075 | // add nextVictim's value. |
|
- | 1076 | // |
|
1060 |
|
1077 | // (balance, balance+1) -> (-balance-1, -balance) |
- | 1078 | // |
|
1061 |
|
1079 | assert(balance < VALUE_ZERO); |
1062 | 1080 | ||
1063 |
|
1081 | balance = -balance - 1 - PieceValue[MG][nextVictim]; |
1064 | if (balance < VALUE_ZERO) |
- | |
1065 | break; |
- | |
1066 | 1082 | ||
1067 | // |
1083 | // If balance is still non-negative after giving away nextVictim then we |
1068 | // |
1084 | // win. The only thing to be careful about it is that we should revert |
1069 | // |
1085 | // stm if we captured with the king when the opponent still has attackers. |
1070 |
|
1086 | if (balance >= VALUE_ZERO) |
- | 1087 | { |
|
- | 1088 | if (nextVictim == KING && (attackers & pieces(stm))) |
|
1071 | stm = ~stm; |
1089 | stm = ~stm; |
- | 1090 | break; |
|
- | 1091 | } |
|
- | 1092 | assert(nextVictim != KING); |
|
1072 | } |
1093 | } |
1073 | - | ||
1074 | // |
1094 | return us != stm; // We break the above loop when stm loses |
1075 | return opponentToMove; |
- | |
1076 | } |
1095 | } |
1077 | 1096 | ||
1078 | 1097 | ||
1079 | /// Position::is_draw() tests whether the position is drawn by 50-move rule |
1098 | /// Position::is_draw() tests whether the position is drawn by 50-move rule |
1080 | /// or by repetition. It does not detect stalemates. |
1099 | /// or by repetition. It does not detect stalemates. |
Line 1101... | Line 1120... | ||
1101 | if ( stp->key == st->key |
1120 | if ( stp->key == st->key |
1102 | && ++cnt + (ply > i) == 2) |
1121 | && ++cnt + (ply > i) == 2) |
1103 | return true; |
1122 | return true; |
1104 | } |
1123 | } |
1105 | 1124 | ||
- | 1125 | return false; |
|
- | 1126 | } |
|
- | 1127 | ||
- | 1128 | ||
- | 1129 | // Position::has_repeated() tests whether there has been at least one repetition |
|
- | 1130 | // of positions since the last capture or pawn move. |
|
- | 1131 | ||
- | 1132 | bool Position::has_repeated() const { |
|
- | 1133 | ||
- | 1134 | StateInfo* stc = st; |
|
- | 1135 | while (true) |
|
- | 1136 | { |
|
- | 1137 | int i = 4, end = std::min(stc->rule50, stc->pliesFromNull); |
|
- | 1138 | ||
- | 1139 | if (end < i) |
|
- | 1140 | return false; |
|
- | 1141 | ||
- | 1142 | StateInfo* stp = stc->previous->previous; |
|
- | 1143 | ||
- | 1144 | do { |
|
- | 1145 | stp = stp->previous->previous; |
|
- | 1146 | ||
- | 1147 | if (stp->key == stc->key) |
|
- | 1148 | return true; |
|
- | 1149 | ||
- | 1150 | i += 2; |
|
- | 1151 | } while (i <= end); |
|
- | 1152 | ||
- | 1153 | stc = stc->previous; |
|
- | 1154 | } |
|
- | 1155 | } |
|
- | 1156 | ||
- | 1157 | ||
- | 1158 | /// Position::has_game_cycle() tests if the position has a move which draws by repetition, |
|
- | 1159 | /// or an earlier position has a move that directly reaches the current position. |
|
- | 1160 | ||
- | 1161 | bool Position::has_game_cycle(int ply) const { |
|
- | 1162 | ||
- | 1163 | int j; |
|
- | 1164 | ||
- | 1165 | int end = std::min(st->rule50, st->pliesFromNull); |
|
- | 1166 | ||
- | 1167 | if (end < 3) |
|
- | 1168 | return false; |
|
- | 1169 | ||
- | 1170 | Key originalKey = st->key; |
|
- | 1171 | StateInfo* stp = st->previous; |
|
- | 1172 | ||
- | 1173 | for (int i = 3; i <= end; i += 2) |
|
- | 1174 | { |
|
- | 1175 | stp = stp->previous->previous; |
|
- | 1176 | ||
- | 1177 | Key moveKey = originalKey ^ stp->key; |
|
- | 1178 | if ( (j = H1(moveKey), cuckoo[j] == moveKey) |
|
- | 1179 | || (j = H2(moveKey), cuckoo[j] == moveKey)) |
|
- | 1180 | { |
|
- | 1181 | Move move = cuckooMove[j]; |
|
- | 1182 | Square s1 = from_sq(move); |
|
- | 1183 | Square s2 = to_sq(move); |
|
- | 1184 | ||
- | 1185 | if (!(between_bb(s1, s2) & pieces())) |
|
- | 1186 | { |
|
- | 1187 | // In the cuckoo table, both moves Rc1c5 and Rc5c1 are stored in the same |
|
- | 1188 | // location. We select the legal one by reversing the move variable if necessary. |
|
- | 1189 | if (empty(s1)) |
|
- | 1190 | move = make_move(s2, s1); |
|
- | 1191 | ||
- | 1192 | if (ply > i) |
|
- | 1193 | return true; |
|
- | 1194 | ||
- | 1195 | // For repetitions before or at the root, require one more |
|
- | 1196 | StateInfo* next_stp = stp; |
|
- | 1197 | for (int k = i + 2; k <= end; k += 2) |
|
- | 1198 | { |
|
- | 1199 | next_stp = next_stp->previous->previous; |
|
- | 1200 | if (next_stp->key == stp->key) |
|
- | 1201 | return true; |
|
- | 1202 | } |
|
- | 1203 | } |
|
- | 1204 | } |
|
- | 1205 | } |
|
1106 | return false; |
1206 | return false; |
1107 | } |
1207 | } |
1108 | 1208 | ||
1109 | 1209 | ||
1110 | /// Position::flip() flips position with the white and black sides reversed. This |
1210 | /// Position::flip() flips position with the white and black sides reversed. This |
Line 1146... | Line 1246... | ||
1146 | /// position object and raises an asserts if something wrong is detected. |
1246 | /// position object and raises an asserts if something wrong is detected. |
1147 | /// This is meant to be helpful when debugging. |
1247 | /// This is meant to be helpful when debugging. |
1148 | 1248 | ||
1149 | bool Position::pos_is_ok() const { |
1249 | bool Position::pos_is_ok() const { |
1150 | 1250 | ||
1151 |
|
1251 | constexpr bool Fast = true; // Quick (default) or full check? |
1152 | 1252 | ||
1153 | if ( (sideToMove != WHITE && sideToMove != BLACK) |
1253 | if ( (sideToMove != WHITE && sideToMove != BLACK) |
1154 | || piece_on(square<KING>(WHITE)) != W_KING |
1254 | || piece_on(square<KING>(WHITE)) != W_KING |
1155 | || piece_on(square<KING>(BLACK)) != B_KING |
1255 | || piece_on(square<KING>(BLACK)) != B_KING |
1156 | || ( ep_square() != SQ_NONE |
1256 | || ( ep_square() != SQ_NONE |