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