"Fossies" - the Fresh Open Source Software Archive

Member "stockfish-11-linux/src/position.cpp" (18 Jan 2020, 40878 Bytes) of package /linux/privat/stockfish-11-linux.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "position.cpp": 9-linux_vs_10-linux.

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