]> git.sesse.net Git - stockfish/blob - src/position.cpp
Fix compilation after recent merge.
[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();
286
287   return *this;
288 }
289
290
291 /// Position::set_castling_right() is a helper function used to set castling
292 /// rights given the corresponding color and the rook starting square.
293
294 void Position::set_castling_right(Color c, Square rfrom) {
295
296   Square kfrom = square<KING>(c);
297   CastlingRights cr = c & (kfrom < rfrom ? KING_SIDE: QUEEN_SIDE);
298
299   st->castlingRights |= cr;
300   castlingRightsMask[kfrom] |= cr;
301   castlingRightsMask[rfrom] |= cr;
302   castlingRookSquare[cr] = rfrom;
303
304   Square kto = relative_square(c, cr & KING_SIDE ? SQ_G1 : SQ_C1);
305   Square rto = relative_square(c, cr & KING_SIDE ? SQ_F1 : SQ_D1);
306
307   castlingPath[cr] =   (between_bb(rfrom, rto) | between_bb(kfrom, kto))
308                     & ~(kfrom | rfrom);
309 }
310
311
312 /// Position::set_check_info() sets king attacks to detect if a move gives check
313
314 void Position::set_check_info() const {
315
316   st->blockersForKing[WHITE] = slider_blockers(pieces(BLACK), square<KING>(WHITE), st->pinners[BLACK]);
317   st->blockersForKing[BLACK] = slider_blockers(pieces(WHITE), square<KING>(BLACK), st->pinners[WHITE]);
318
319   Square ksq = square<KING>(~sideToMove);
320
321   st->checkSquares[PAWN]   = pawn_attacks_bb(~sideToMove, ksq);
322   st->checkSquares[KNIGHT] = attacks_bb<KNIGHT>(ksq);
323   st->checkSquares[BISHOP] = attacks_bb<BISHOP>(ksq, pieces());
324   st->checkSquares[ROOK]   = attacks_bb<ROOK>(ksq, pieces());
325   st->checkSquares[QUEEN]  = st->checkSquares[BISHOP] | st->checkSquares[ROOK];
326   st->checkSquares[KING]   = 0;
327 }
328
329
330 /// Position::set_state() computes the hash keys of the position, and other
331 /// data that once computed is updated incrementally as moves are made.
332 /// The function is only used when a new position is set up, and to verify
333 /// the correctness of the StateInfo data when running in debug mode.
334
335 void Position::set_state() const {
336
337   st->key = st->materialKey = 0;
338   st->pawnKey = Zobrist::noPawns;
339   st->nonPawnMaterial[WHITE] = st->nonPawnMaterial[BLACK] = VALUE_ZERO;
340   st->checkersBB = attackers_to(square<KING>(sideToMove)) & pieces(~sideToMove);
341
342   set_check_info();
343
344   for (Bitboard b = pieces(); b; )
345   {
346       Square s = pop_lsb(b);
347       Piece pc = piece_on(s);
348       st->key ^= Zobrist::psq[pc][s];
349
350       if (type_of(pc) == PAWN)
351           st->pawnKey ^= Zobrist::psq[pc][s];
352
353       else if (type_of(pc) != KING)
354           st->nonPawnMaterial[color_of(pc)] += PieceValue[MG][pc];
355   }
356
357   if (st->epSquare != SQ_NONE)
358       st->key ^= Zobrist::enpassant[file_of(st->epSquare)];
359
360   if (sideToMove == BLACK)
361       st->key ^= Zobrist::side;
362
363   st->key ^= Zobrist::castling[st->castlingRights];
364
365   for (Piece pc : Pieces)
366       for (int cnt = 0; cnt < pieceCount[pc]; ++cnt)
367           st->materialKey ^= Zobrist::psq[pc][cnt];
368 }
369
370
371 /// Position::set() is an overload to initialize the position object with
372 /// the given endgame code string like "KBPKN". It is mainly a helper to
373 /// get the material key out of an endgame code.
374
375 Position& Position::set(const string& code, Color c, StateInfo* si) {
376
377   assert(code[0] == 'K');
378
379   string sides[] = { code.substr(code.find('K', 1)),      // Weak
380                      code.substr(0, std::min(code.find('v'), code.find('K', 1))) }; // Strong
381
382   assert(sides[0].length() > 0 && sides[0].length() < 8);
383   assert(sides[1].length() > 0 && sides[1].length() < 8);
384
385   std::transform(sides[c].begin(), sides[c].end(), sides[c].begin(), tolower);
386
387   string fenStr = "8/" + sides[0] + char(8 - sides[0].length() + '0') + "/8/8/8/8/"
388                        + sides[1] + char(8 - sides[1].length() + '0') + "/8 w - - 0 10";
389
390   return set(fenStr, false, si, nullptr);
391 }
392
393
394 /// Position::fen() returns a FEN representation of the position. In case of
395 /// Chess960 the Shredder-FEN notation is used. This is mainly a debugging function.
396
397 string Position::fen() const {
398
399   int emptyCnt;
400   std::ostringstream ss;
401
402   for (Rank r = RANK_8; r >= RANK_1; --r)
403   {
404       for (File f = FILE_A; f <= FILE_H; ++f)
405       {
406           for (emptyCnt = 0; f <= FILE_H && empty(make_square(f, r)); ++f)
407               ++emptyCnt;
408
409           if (emptyCnt)
410               ss << emptyCnt;
411
412           if (f <= FILE_H)
413               ss << PieceToChar[piece_on(make_square(f, r))];
414       }
415
416       if (r > RANK_1)
417           ss << '/';
418   }
419
420   ss << (sideToMove == WHITE ? " w " : " b ");
421
422   if (can_castle(WHITE_OO))
423       ss << (chess960 ? char('A' + file_of(castling_rook_square(WHITE_OO ))) : 'K');
424
425   if (can_castle(WHITE_OOO))
426       ss << (chess960 ? char('A' + file_of(castling_rook_square(WHITE_OOO))) : 'Q');
427
428   if (can_castle(BLACK_OO))
429       ss << (chess960 ? char('a' + file_of(castling_rook_square(BLACK_OO ))) : 'k');
430
431   if (can_castle(BLACK_OOO))
432       ss << (chess960 ? char('a' + file_of(castling_rook_square(BLACK_OOO))) : 'q');
433
434   if (!can_castle(ANY_CASTLING))
435       ss << '-';
436
437   ss << (ep_square() == SQ_NONE ? " - " : " " + UCI::square(ep_square()) + " ")
438      << st->rule50 << " " << 1 + (gamePly - (sideToMove == BLACK)) / 2;
439
440   return ss.str();
441 }
442
443
444 /// Position::slider_blockers() returns a bitboard of all the pieces (both colors)
445 /// that are blocking attacks on the square 's' from 'sliders'. A piece blocks a
446 /// slider if removing that piece from the board would result in a position where
447 /// square 's' is attacked. For example, a king-attack blocking piece can be either
448 /// a pinned or a discovered check piece, according if its color is the opposite
449 /// or the same of the color of the slider.
450
451 Bitboard Position::slider_blockers(Bitboard sliders, Square s, Bitboard& pinners) const {
452
453   Bitboard blockers = 0;
454   pinners = 0;
455
456   // Snipers are sliders that attack 's' when a piece and other snipers are removed
457   Bitboard snipers = (  (attacks_bb<  ROOK>(s) & pieces(QUEEN, ROOK))
458                       | (attacks_bb<BISHOP>(s) & pieces(QUEEN, BISHOP))) & sliders;
459   Bitboard occupancy = pieces() ^ snipers;
460
461   while (snipers)
462   {
463     Square sniperSq = pop_lsb(snipers);
464     Bitboard b = between_bb(s, sniperSq) & occupancy;
465
466     if (b && !more_than_one(b))
467     {
468         blockers |= b;
469         if (b & pieces(color_of(piece_on(s))))
470             pinners |= sniperSq;
471     }
472   }
473   return blockers;
474 }
475
476
477 /// Position::attackers_to() computes a bitboard of all pieces which attack a
478 /// given square. Slider attacks use the occupied bitboard to indicate occupancy.
479
480 Bitboard Position::attackers_to(Square s, Bitboard occupied) const {
481
482   return  (pawn_attacks_bb(BLACK, s)       & pieces(WHITE, PAWN))
483         | (pawn_attacks_bb(WHITE, s)       & pieces(BLACK, PAWN))
484         | (attacks_bb<KNIGHT>(s)           & pieces(KNIGHT))
485         | (attacks_bb<  ROOK>(s, occupied) & pieces(  ROOK, QUEEN))
486         | (attacks_bb<BISHOP>(s, occupied) & pieces(BISHOP, QUEEN))
487         | (attacks_bb<KING>(s)             & pieces(KING));
488 }
489
490
491 /// Position::legal() tests whether a pseudo-legal move is legal
492
493 bool Position::legal(Move m) const {
494
495   assert(is_ok(m));
496
497   Color us = sideToMove;
498   Square from = from_sq(m);
499   Square to = to_sq(m);
500
501   assert(color_of(moved_piece(m)) == us);
502   assert(piece_on(square<KING>(us)) == make_piece(us, KING));
503
504   // En passant captures are a tricky special case. Because they are rather
505   // uncommon, we do it simply by testing whether the king is attacked after
506   // the move is made.
507   if (type_of(m) == EN_PASSANT)
508   {
509       Square ksq = square<KING>(us);
510       Square capsq = to - pawn_push(us);
511       Bitboard occupied = (pieces() ^ from ^ capsq) | to;
512
513       assert(to == ep_square());
514       assert(moved_piece(m) == make_piece(us, PAWN));
515       assert(piece_on(capsq) == make_piece(~us, PAWN));
516       assert(piece_on(to) == NO_PIECE);
517
518       return   !(attacks_bb<  ROOK>(ksq, occupied) & pieces(~us, QUEEN, ROOK))
519             && !(attacks_bb<BISHOP>(ksq, occupied) & pieces(~us, QUEEN, BISHOP));
520   }
521
522   // Castling moves generation does not check if the castling path is clear of
523   // enemy attacks, it is delayed at a later time: now!
524   if (type_of(m) == CASTLING)
525   {
526       // After castling, the rook and king final positions are the same in
527       // Chess960 as they would be in standard chess.
528       to = relative_square(us, to > from ? SQ_G1 : SQ_C1);
529       Direction step = to > from ? WEST : EAST;
530
531       for (Square s = to; s != from; s += step)
532           if (attackers_to(s) & pieces(~us))
533               return false;
534
535       // In case of Chess960, verify if the Rook blocks some checks
536       // For instance an enemy queen in SQ_A1 when castling rook is in SQ_B1.
537       return !chess960 || !(blockers_for_king(us) & to_sq(m));
538   }
539
540   // If the moving piece is a king, check whether the destination square is
541   // attacked by the opponent.
542   if (type_of(piece_on(from)) == KING)
543       return !(attackers_to(to, pieces() ^ from) & pieces(~us));
544
545   // A non-king move is legal if and only if it is not pinned or it
546   // is moving along the ray towards or away from the king.
547   return !(blockers_for_king(us) & from)
548       || aligned(from, to, square<KING>(us));
549 }
550
551
552 /// Position::pseudo_legal() takes a random move and tests whether the move is
553 /// pseudo legal. It is used to validate moves from TT that can be corrupted
554 /// due to SMP concurrent access or hash position key aliasing.
555
556 bool Position::pseudo_legal(const Move m) const {
557
558   Color us = sideToMove;
559   Square from = from_sq(m);
560   Square to = to_sq(m);
561   Piece pc = moved_piece(m);
562
563   // Use a slower but simpler function for uncommon cases
564   // yet we skip the legality check of MoveList<LEGAL>().
565   if (type_of(m) != NORMAL)
566       return checkers() ? MoveList<    EVASIONS>(*this).contains(m)
567                         : MoveList<NON_EVASIONS>(*this).contains(m);
568
569   // Is not a promotion, so promotion piece must be empty
570   assert(promotion_type(m) - KNIGHT == NO_PIECE_TYPE);
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 (   !(pawn_attacks_bb(us, from) & 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                && (relative_rank(us, from) == RANK_2)
593                && empty(to)
594                && empty(to - pawn_push(us))))
595           return false;
596   }
597   else if (!(attacks_bb(type_of(pc), from, pieces()) & 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 interposition or a capture of the checking piece
612           if (!(between_bb(square<KING>(us), lsb(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 (check_squares(type_of(piece_on(from))) & to)
637       return true;
638
639   // Is there a discovered check?
640   if (   (blockers_for_king(~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 EN_PASSANT:
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   default: //CASTLING
665   {
666       // Castling is encoded as 'king captures the rook'
667       Square ksq = square<KING>(~sideToMove);
668       Square rto = relative_square(sideToMove, to > from ? SQ_F1 : SQ_D1);
669
670       return   (attacks_bb<ROOK>(rto) & ksq)
671             && (attacks_bb<ROOK>(rto, pieces() ^ from ^ to) & ksq);
672   }
673   }
674 }
675
676
677 /// Position::do_move() makes a move, and saves all information necessary
678 /// to a StateInfo object. The move is assumed to be legal. Pseudo-legal
679 /// moves should be filtered out before this function is called.
680
681 void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
682
683   assert(is_ok(m));
684   assert(&newSt != st);
685
686   thisThread->nodes.fetch_add(1, std::memory_order_relaxed);
687   Key k = st->key ^ Zobrist::side;
688
689   // Copy some fields of the old state to our new StateInfo object except the
690   // ones which are going to be recalculated from scratch anyway and then switch
691   // our state pointer to point to the new (ready to be updated) state.
692   std::memcpy(&newSt, st, offsetof(StateInfo, key));
693   newSt.previous = st;
694   st = &newSt;
695
696   // Increment ply counters. In particular, rule50 will be reset to zero later on
697   // in case of a capture or a pawn move.
698   ++gamePly;
699   ++st->rule50;
700   ++st->pliesFromNull;
701
702   // Used by NNUE
703   st->accumulator.computed[WHITE] = false;
704   st->accumulator.computed[BLACK] = false;
705   auto& dp = st->dirtyPiece;
706   dp.dirty_num = 1;
707
708   Color us = sideToMove;
709   Color them = ~us;
710   Square from = from_sq(m);
711   Square to = to_sq(m);
712   Piece pc = piece_on(from);
713   Piece captured = type_of(m) == EN_PASSANT ? make_piece(them, PAWN) : piece_on(to);
714
715   assert(color_of(pc) == us);
716   assert(captured == NO_PIECE || color_of(captured) == (type_of(m) != CASTLING ? them : us));
717   assert(type_of(captured) != KING);
718
719   if (type_of(m) == CASTLING)
720   {
721       assert(pc == make_piece(us, KING));
722       assert(captured == make_piece(us, ROOK));
723
724       Square rfrom, rto;
725       do_castling<true>(us, from, to, rfrom, rto);
726
727       k ^= Zobrist::psq[captured][rfrom] ^ Zobrist::psq[captured][rto];
728       captured = NO_PIECE;
729   }
730
731   if (captured)
732   {
733       Square capsq = to;
734
735       // If the captured piece is a pawn, update pawn hash key, otherwise
736       // update non-pawn material.
737       if (type_of(captured) == PAWN)
738       {
739           if (type_of(m) == EN_PASSANT)
740           {
741               capsq -= pawn_push(us);
742
743               assert(pc == make_piece(us, PAWN));
744               assert(to == st->epSquare);
745               assert(relative_rank(us, to) == RANK_6);
746               assert(piece_on(to) == NO_PIECE);
747               assert(piece_on(capsq) == make_piece(them, PAWN));
748           }
749
750           st->pawnKey ^= Zobrist::psq[captured][capsq];
751       }
752       else
753           st->nonPawnMaterial[them] -= PieceValue[MG][captured];
754
755       if (Eval::useNNUE)
756       {
757           dp.dirty_num = 2;  // 1 piece moved, 1 piece captured
758           dp.piece[1] = captured;
759           dp.from[1] = capsq;
760           dp.to[1] = SQ_NONE;
761       }
762
763       // Update board and piece lists
764       remove_piece(capsq);
765
766       // Update material hash key and prefetch access to materialTable
767       k ^= Zobrist::psq[captured][capsq];
768       st->materialKey ^= Zobrist::psq[captured][pieceCount[captured]];
769       prefetch(thisThread->materialTable[st->materialKey]);
770
771       // Reset rule 50 counter
772       st->rule50 = 0;
773   }
774
775   // Update hash key
776   k ^= Zobrist::psq[pc][from] ^ Zobrist::psq[pc][to];
777
778   // Reset en passant square
779   if (st->epSquare != SQ_NONE)
780   {
781       k ^= Zobrist::enpassant[file_of(st->epSquare)];
782       st->epSquare = SQ_NONE;
783   }
784
785   // Update castling rights if needed
786   if (st->castlingRights && (castlingRightsMask[from] | castlingRightsMask[to]))
787   {
788       k ^= Zobrist::castling[st->castlingRights];
789       st->castlingRights &= ~(castlingRightsMask[from] | castlingRightsMask[to]);
790       k ^= Zobrist::castling[st->castlingRights];
791   }
792
793   // Move the piece. The tricky Chess960 castling is handled earlier
794   if (type_of(m) != CASTLING)
795   {
796       if (Eval::useNNUE)
797       {
798           dp.piece[0] = pc;
799           dp.from[0] = from;
800           dp.to[0] = to;
801       }
802
803       move_piece(from, to);
804   }
805
806   // If the moving piece is a pawn do some special extra work
807   if (type_of(pc) == PAWN)
808   {
809       // Set en passant square if the moved pawn can be captured
810       if (   (int(to) ^ int(from)) == 16
811           && (pawn_attacks_bb(us, to - pawn_push(us)) & pieces(them, PAWN)))
812       {
813           st->epSquare = to - pawn_push(us);
814           k ^= Zobrist::enpassant[file_of(st->epSquare)];
815       }
816
817       else if (type_of(m) == PROMOTION)
818       {
819           Piece promotion = make_piece(us, promotion_type(m));
820
821           assert(relative_rank(us, to) == RANK_8);
822           assert(type_of(promotion) >= KNIGHT && type_of(promotion) <= QUEEN);
823
824           remove_piece(to);
825           put_piece(promotion, to);
826
827           if (Eval::useNNUE)
828           {
829               // Promoting pawn to SQ_NONE, promoted piece from SQ_NONE
830               dp.to[0] = SQ_NONE;
831               dp.piece[dp.dirty_num] = promotion;
832               dp.from[dp.dirty_num] = SQ_NONE;
833               dp.to[dp.dirty_num] = to;
834               dp.dirty_num++;
835           }
836
837           // Update hash keys
838           k ^= Zobrist::psq[pc][to] ^ Zobrist::psq[promotion][to];
839           st->pawnKey ^= Zobrist::psq[pc][to];
840           st->materialKey ^=  Zobrist::psq[promotion][pieceCount[promotion]-1]
841                             ^ Zobrist::psq[pc][pieceCount[pc]];
842
843           // Update material
844           st->nonPawnMaterial[us] += PieceValue[MG][promotion];
845       }
846
847       // Update pawn hash key
848       st->pawnKey ^= Zobrist::psq[pc][from] ^ Zobrist::psq[pc][to];
849
850       // Reset rule 50 draw counter
851       st->rule50 = 0;
852   }
853
854   // Set capture piece
855   st->capturedPiece = captured;
856
857   // Update the key with the final value
858   st->key = k;
859
860   // Calculate checkers bitboard (if move gives check)
861   st->checkersBB = givesCheck ? attackers_to(square<KING>(them)) & pieces(us) : 0;
862
863   sideToMove = ~sideToMove;
864
865   // Update king attacks used for fast check detection
866   set_check_info();
867
868   // Calculate the repetition info. It is the ply distance from the previous
869   // occurrence of the same position, negative in the 3-fold case, or zero
870   // if the position was not repeated.
871   st->repetition = 0;
872   int end = std::min(st->rule50, st->pliesFromNull);
873   if (end >= 4)
874   {
875       StateInfo* stp = st->previous->previous;
876       for (int i = 4; i <= end; i += 2)
877       {
878           stp = stp->previous->previous;
879           if (stp->key == st->key)
880           {
881               st->repetition = stp->repetition ? -i : i;
882               break;
883           }
884       }
885   }
886
887   assert(pos_is_ok());
888 }
889
890
891 /// Position::undo_move() unmakes a move. When it returns, the position should
892 /// be restored to exactly the same state as before the move was made.
893
894 void Position::undo_move(Move m) {
895
896   assert(is_ok(m));
897
898   sideToMove = ~sideToMove;
899
900   Color us = sideToMove;
901   Square from = from_sq(m);
902   Square to = to_sq(m);
903   Piece pc = piece_on(to);
904
905   assert(empty(from) || type_of(m) == CASTLING);
906   assert(type_of(st->capturedPiece) != KING);
907
908   if (type_of(m) == PROMOTION)
909   {
910       assert(relative_rank(us, to) == RANK_8);
911       assert(type_of(pc) == promotion_type(m));
912       assert(type_of(pc) >= KNIGHT && type_of(pc) <= QUEEN);
913
914       remove_piece(to);
915       pc = make_piece(us, PAWN);
916       put_piece(pc, to);
917   }
918
919   if (type_of(m) == CASTLING)
920   {
921       Square rfrom, rto;
922       do_castling<false>(us, from, to, rfrom, rto);
923   }
924   else
925   {
926       move_piece(to, from); // Put the piece back at the source square
927
928       if (st->capturedPiece)
929       {
930           Square capsq = to;
931
932           if (type_of(m) == EN_PASSANT)
933           {
934               capsq -= pawn_push(us);
935
936               assert(type_of(pc) == PAWN);
937               assert(to == st->previous->epSquare);
938               assert(relative_rank(us, to) == RANK_6);
939               assert(piece_on(capsq) == NO_PIECE);
940               assert(st->capturedPiece == make_piece(~us, PAWN));
941           }
942
943           put_piece(st->capturedPiece, capsq); // Restore the captured piece
944       }
945   }
946
947   // Finally point our state pointer back to the previous state
948   st = st->previous;
949   --gamePly;
950
951   assert(pos_is_ok());
952 }
953
954
955 /// Position::do_castling() is a helper used to do/undo a castling move. This
956 /// is a bit tricky in Chess960 where from/to squares can overlap.
957 template<bool Do>
958 void Position::do_castling(Color us, Square from, Square& to, Square& rfrom, Square& rto) {
959
960   bool kingSide = to > from;
961   rfrom = to; // Castling is encoded as "king captures friendly rook"
962   rto = relative_square(us, kingSide ? SQ_F1 : SQ_D1);
963   to = relative_square(us, kingSide ? SQ_G1 : SQ_C1);
964
965   if (Do && Eval::useNNUE)
966   {
967       auto& dp = st->dirtyPiece;
968       dp.piece[0] = make_piece(us, KING);
969       dp.from[0] = from;
970       dp.to[0] = to;
971       dp.piece[1] = make_piece(us, ROOK);
972       dp.from[1] = rfrom;
973       dp.to[1] = rto;
974       dp.dirty_num = 2;
975   }
976
977   // Remove both pieces first since squares could overlap in Chess960
978   remove_piece(Do ? from : to);
979   remove_piece(Do ? rfrom : rto);
980   board[Do ? from : to] = board[Do ? rfrom : rto] = NO_PIECE; // Since remove_piece doesn't do this for us
981   put_piece(make_piece(us, KING), Do ? to : from);
982   put_piece(make_piece(us, ROOK), Do ? rto : rfrom);
983 }
984
985
986 /// Position::do_null_move() is used to do a "null move": it flips
987 /// the side to move without executing any move on the board.
988
989 void Position::do_null_move(StateInfo& newSt) {
990
991   assert(!checkers());
992   assert(&newSt != st);
993
994   std::memcpy(&newSt, st, offsetof(StateInfo, accumulator));
995
996   newSt.previous = st;
997   st = &newSt;
998
999   st->dirtyPiece.dirty_num = 0;
1000   st->dirtyPiece.piece[0] = NO_PIECE; // Avoid checks in UpdateAccumulator()
1001   st->accumulator.computed[WHITE] = false;
1002   st->accumulator.computed[BLACK] = false;
1003
1004   if (st->epSquare != SQ_NONE)
1005   {
1006       st->key ^= Zobrist::enpassant[file_of(st->epSquare)];
1007       st->epSquare = SQ_NONE;
1008   }
1009
1010   st->key ^= Zobrist::side;
1011   ++st->rule50;
1012   prefetch(TT.first_entry(key()));
1013
1014   st->pliesFromNull = 0;
1015
1016   sideToMove = ~sideToMove;
1017
1018   set_check_info();
1019
1020   st->repetition = 0;
1021
1022   assert(pos_is_ok());
1023 }
1024
1025
1026 /// Position::undo_null_move() must be used to undo a "null move"
1027
1028 void Position::undo_null_move() {
1029
1030   assert(!checkers());
1031
1032   st = st->previous;
1033   sideToMove = ~sideToMove;
1034 }
1035
1036
1037 /// Position::key_after() computes the new hash key after the given move. Needed
1038 /// for speculative prefetch. It doesn't recognize special moves like castling,
1039 /// en passant and promotions.
1040
1041 Key Position::key_after(Move m) const {
1042
1043   Square from = from_sq(m);
1044   Square to = to_sq(m);
1045   Piece pc = piece_on(from);
1046   Piece captured = piece_on(to);
1047   Key k = st->key ^ Zobrist::side;
1048
1049   if (captured)
1050       k ^= Zobrist::psq[captured][to];
1051
1052   k ^= Zobrist::psq[pc][to] ^ Zobrist::psq[pc][from];
1053
1054   return (captured || type_of(pc) == PAWN)
1055       ? k : adjust_key50<true>(k);
1056 }
1057
1058
1059 /// Position::see_ge (Static Exchange Evaluation Greater or Equal) tests if the
1060 /// SEE value of move is greater or equal to the given threshold. We'll use an
1061 /// algorithm similar to alpha-beta pruning with a null window.
1062
1063 bool Position::see_ge(Move m, Bitboard& occupied, Value threshold) const {
1064
1065   assert(is_ok(m));
1066
1067   // Only deal with normal moves, assume others pass a simple SEE
1068   if (type_of(m) != NORMAL)
1069       return VALUE_ZERO >= threshold;
1070
1071   Square from = from_sq(m), to = to_sq(m);
1072
1073   int swap = PieceValue[MG][piece_on(to)] - threshold;
1074   if (swap < 0)
1075       return false;
1076
1077   swap = PieceValue[MG][piece_on(from)] - swap;
1078   if (swap <= 0)
1079       return true;
1080
1081   assert(color_of(piece_on(from)) == sideToMove);
1082   occupied = pieces() ^ from ^ to; // xoring to is important for pinned piece logic
1083   Color stm = sideToMove;
1084   Bitboard attackers = attackers_to(to, occupied);
1085   Bitboard stmAttackers, bb;
1086   int res = 1;
1087
1088   while (true)
1089   {
1090       stm = ~stm;
1091       attackers &= occupied;
1092
1093       // If stm has no more attackers then give up: stm loses
1094       if (!(stmAttackers = attackers & pieces(stm)))
1095           break;
1096
1097       // Don't allow pinned pieces to attack as long as there are
1098       // pinners on their original square.
1099       if (pinners(~stm) & occupied)
1100       {
1101           stmAttackers &= ~blockers_for_king(stm);
1102
1103           if (!stmAttackers)
1104               break;
1105       }
1106
1107       res ^= 1;
1108
1109       // Locate and remove the next least valuable attacker, and add to
1110       // the bitboard 'attackers' any X-ray attackers behind it.
1111       if ((bb = stmAttackers & pieces(PAWN)))
1112       {
1113           occupied ^= least_significant_square_bb(bb);
1114           if ((swap = PawnValueMg - swap) < res)
1115               break;
1116
1117           attackers |= attacks_bb<BISHOP>(to, occupied) & pieces(BISHOP, QUEEN);
1118       }
1119
1120       else if ((bb = stmAttackers & pieces(KNIGHT)))
1121       {
1122           occupied ^= least_significant_square_bb(bb);
1123           if ((swap = KnightValueMg - swap) < res)
1124               break;
1125       }
1126
1127       else if ((bb = stmAttackers & pieces(BISHOP)))
1128       {
1129           occupied ^= least_significant_square_bb(bb);
1130           if ((swap = BishopValueMg - swap) < res)
1131               break;
1132
1133           attackers |= attacks_bb<BISHOP>(to, occupied) & pieces(BISHOP, QUEEN);
1134       }
1135
1136       else if ((bb = stmAttackers & pieces(ROOK)))
1137       {
1138           occupied ^= least_significant_square_bb(bb);
1139           if ((swap = RookValueMg - swap) < res)
1140               break;
1141
1142           attackers |= attacks_bb<ROOK>(to, occupied) & pieces(ROOK, QUEEN);
1143       }
1144
1145       else if ((bb = stmAttackers & pieces(QUEEN)))
1146       {
1147           occupied ^= least_significant_square_bb(bb);
1148           if ((swap = QueenValueMg - swap) < res)
1149               break;
1150
1151           attackers |=  (attacks_bb<BISHOP>(to, occupied) & pieces(BISHOP, QUEEN))
1152                       | (attacks_bb<ROOK  >(to, occupied) & pieces(ROOK  , QUEEN));
1153       }
1154
1155       else // KING
1156            // If we "capture" with the king but opponent still has attackers,
1157            // reverse the result.
1158           return (attackers & ~pieces(stm)) ? res ^ 1 : res;
1159   }
1160
1161   return bool(res);
1162 }
1163
1164 bool Position::see_ge(Move m, Value threshold) const {
1165     Bitboard occupied;
1166     return see_ge(m, occupied, threshold);
1167 }
1168
1169
1170 /// Position::is_draw() tests whether the position is drawn by 50-move rule
1171 /// or by repetition. It does not detect stalemates.
1172
1173 bool Position::is_draw(int ply) const {
1174
1175   if (st->rule50 > 99 && (!checkers() || MoveList<LEGAL>(*this).size()))
1176       return true;
1177
1178   // Return a draw score if a position repeats once earlier but strictly
1179   // after the root, or repeats twice before or at the root.
1180   return st->repetition && st->repetition < ply;
1181 }
1182
1183
1184 // Position::has_repeated() tests whether there has been at least one repetition
1185 // of positions since the last capture or pawn move.
1186
1187 bool Position::has_repeated() const {
1188
1189     StateInfo* stc = st;
1190     int end = std::min(st->rule50, st->pliesFromNull);
1191     while (end-- >= 4)
1192     {
1193         if (stc->repetition)
1194             return true;
1195
1196         stc = stc->previous;
1197     }
1198     return false;
1199 }
1200
1201
1202 /// Position::has_game_cycle() tests if the position has a move which draws by repetition,
1203 /// or an earlier position has a move that directly reaches the current position.
1204
1205 bool Position::has_game_cycle(int ply) const {
1206
1207   int j;
1208
1209   int end = std::min(st->rule50, st->pliesFromNull);
1210
1211   if (end < 3)
1212     return false;
1213
1214   Key originalKey = st->key;
1215   StateInfo* stp = st->previous;
1216
1217   for (int i = 3; i <= end; i += 2)
1218   {
1219       stp = stp->previous->previous;
1220
1221       Key moveKey = originalKey ^ stp->key;
1222       if (   (j = H1(moveKey), cuckoo[j] == moveKey)
1223           || (j = H2(moveKey), cuckoo[j] == moveKey))
1224       {
1225           Move move = cuckooMove[j];
1226           Square s1 = from_sq(move);
1227           Square s2 = to_sq(move);
1228
1229           if (!((between_bb(s1, s2) ^ s2) & pieces()))
1230           {
1231               if (ply > i)
1232                   return true;
1233
1234               // For nodes before or at the root, check that the move is a
1235               // repetition rather than a move to the current position.
1236               // In the cuckoo table, both moves Rc1c5 and Rc5c1 are stored in
1237               // the same location, so we have to select which square to check.
1238               if (color_of(piece_on(empty(s1) ? s2 : s1)) != side_to_move())
1239                   continue;
1240
1241               // For repetitions before or at the root, require one more
1242               if (stp->repetition)
1243                   return true;
1244           }
1245       }
1246   }
1247   return false;
1248 }
1249
1250
1251 /// Position::flip() flips position with the white and black sides reversed. This
1252 /// is only useful for debugging e.g. for finding evaluation symmetry bugs.
1253
1254 void Position::flip() {
1255
1256   string f, token;
1257   std::stringstream ss(fen());
1258
1259   for (Rank r = RANK_8; r >= RANK_1; --r) // Piece placement
1260   {
1261       std::getline(ss, token, r > RANK_1 ? '/' : ' ');
1262       f.insert(0, token + (f.empty() ? " " : "/"));
1263   }
1264
1265   ss >> token; // Active color
1266   f += (token == "w" ? "B " : "W "); // Will be lowercased later
1267
1268   ss >> token; // Castling availability
1269   f += token + " ";
1270
1271   std::transform(f.begin(), f.end(), f.begin(),
1272                  [](char c) { return char(islower(c) ? toupper(c) : tolower(c)); });
1273
1274   ss >> token; // En passant square
1275   f += (token == "-" ? token : token.replace(1, 1, token[1] == '3' ? "6" : "3"));
1276
1277   std::getline(ss, token); // Half and full moves
1278   f += token;
1279
1280   set(f, is_chess960(), st, this_thread());
1281
1282   assert(pos_is_ok());
1283 }
1284
1285
1286 /// Position::pos_is_ok() performs some consistency checks for the
1287 /// position object and raises an asserts if something wrong is detected.
1288 /// This is meant to be helpful when debugging.
1289
1290 bool Position::pos_is_ok() const {
1291
1292   constexpr bool Fast = true; // Quick (default) or full check?
1293
1294   if (   (sideToMove != WHITE && sideToMove != BLACK)
1295       || piece_on(square<KING>(WHITE)) != W_KING
1296       || piece_on(square<KING>(BLACK)) != B_KING
1297       || (   ep_square() != SQ_NONE
1298           && relative_rank(sideToMove, ep_square()) != RANK_6))
1299       assert(0 && "pos_is_ok: Default");
1300
1301   if (Fast)
1302       return true;
1303
1304   if (   pieceCount[W_KING] != 1
1305       || pieceCount[B_KING] != 1
1306       || attackers_to(square<KING>(~sideToMove)) & pieces(sideToMove))
1307       assert(0 && "pos_is_ok: Kings");
1308
1309   if (   (pieces(PAWN) & (Rank1BB | Rank8BB))
1310       || pieceCount[W_PAWN] > 8
1311       || pieceCount[B_PAWN] > 8)
1312       assert(0 && "pos_is_ok: Pawns");
1313
1314   if (   (pieces(WHITE) & pieces(BLACK))
1315       || (pieces(WHITE) | pieces(BLACK)) != pieces()
1316       || popcount(pieces(WHITE)) > 16
1317       || popcount(pieces(BLACK)) > 16)
1318       assert(0 && "pos_is_ok: Bitboards");
1319
1320   for (PieceType p1 = PAWN; p1 <= KING; ++p1)
1321       for (PieceType p2 = PAWN; p2 <= KING; ++p2)
1322           if (p1 != p2 && (pieces(p1) & pieces(p2)))
1323               assert(0 && "pos_is_ok: Bitboards");
1324
1325
1326   for (Piece pc : Pieces)
1327       if (   pieceCount[pc] != popcount(pieces(color_of(pc), type_of(pc)))
1328           || pieceCount[pc] != std::count(board, board + SQUARE_NB, pc))
1329           assert(0 && "pos_is_ok: Pieces");
1330
1331   for (Color c : { WHITE, BLACK })
1332       for (CastlingRights cr : {c & KING_SIDE, c & QUEEN_SIDE})
1333       {
1334           if (!can_castle(cr))
1335               continue;
1336
1337           if (   piece_on(castlingRookSquare[cr]) != make_piece(c, ROOK)
1338               || castlingRightsMask[castlingRookSquare[cr]] != cr
1339               || (castlingRightsMask[square<KING>(c)] & cr) != cr)
1340               assert(0 && "pos_is_ok: Castling");
1341       }
1342
1343   return true;
1344 }
1345
1346 } // namespace Stockfish