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