From: Marco Costalba Date: Mon, 27 Jun 2011 15:06:15 +0000 (+0100) Subject: Greatly simplify castling rights handling X-Git-Url: https://git.sesse.net/?p=stockfish;a=commitdiff_plain;h=c2a4856f9e9aad8122f2386acdacf7aa385cfc1b Greatly simplify castling rights handling No functional change. Signed-off-by: Marco Costalba --- diff --git a/src/book.cpp b/src/book.cpp index 8944b31b..ed5cba4b 100644 --- a/src/book.cpp +++ b/src/book.cpp @@ -322,16 +322,16 @@ namespace { result ^= ZobPiece[PieceOfs[pos.piece_on(s)] + s]; } - if (pos.can_castle_kingside(WHITE)) + if (pos.can_castle(WHITE_OO)) result ^= ZobCastle[0]; - if (pos.can_castle_queenside(WHITE)) + if (pos.can_castle(WHITE_OOO)) result ^= ZobCastle[1]; - if (pos.can_castle_kingside(BLACK)) + if (pos.can_castle(BLACK_OO)) result ^= ZobCastle[2]; - if (pos.can_castle_queenside(BLACK)) + if (pos.can_castle(BLACK_OOO)) result ^= ZobCastle[3]; if (pos.ep_square() != SQ_NONE) diff --git a/src/movegen.cpp b/src/movegen.cpp index d821f0fa..3d736b25 100644 --- a/src/movegen.cpp +++ b/src/movegen.cpp @@ -178,12 +178,12 @@ MoveStack* generate(const Position& pos, MoveStack* mlist) { mlist = generate_piece_moves(pos, mlist, us, target); mlist = generate_piece_moves(pos, mlist, us, target); - if (Type != MV_CAPTURE) + if (Type != MV_CAPTURE && pos.can_castle(us)) { - if (pos.can_castle_kingside(us)) + if (pos.can_castle(us == WHITE ? WHITE_OO : BLACK_OO)) mlist = generate_castle_moves(pos, mlist, us); - if (pos.can_castle_queenside(us)) + if (pos.can_castle(us == WHITE ? WHITE_OOO : BLACK_OOO)) mlist = generate_castle_moves(pos, mlist, us); } @@ -503,10 +503,11 @@ namespace { Color them = opposite_color(us); Square ksq = pos.king_square(us); + CastleRight f = CastleRight((Side == KING_SIDE ? WHITE_OO : WHITE_OOO) << us); assert(pos.piece_on(ksq) == make_piece(us, KING)); - Square rsq = (Side == KING_SIDE ? pos.initial_kr_square(us) : pos.initial_qr_square(us)); + Square rsq = pos.castle_rook_square(f); Square s1 = relative_square(us, Side == KING_SIDE ? SQ_G1 : SQ_C1); Square s2 = relative_square(us, Side == KING_SIDE ? SQ_F1 : SQ_D1); Square s; diff --git a/src/position.cpp b/src/position.cpp index 0dbbbddf..f9fd0b73 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -211,13 +211,6 @@ void Position::from_fen(const string& fen, bool isChess960) { ss >> st->rule50 >> fullMoves; // Various initialisations - castleRightsMask[make_square(initialKFile, RANK_1)] ^= WHITE_OO | WHITE_OOO; - castleRightsMask[make_square(initialKFile, RANK_8)] ^= BLACK_OO | BLACK_OOO; - castleRightsMask[make_square(initialKRFile, RANK_1)] ^= WHITE_OO; - castleRightsMask[make_square(initialKRFile, RANK_8)] ^= BLACK_OO; - castleRightsMask[make_square(initialQRFile, RANK_1)] ^= WHITE_OOO; - castleRightsMask[make_square(initialQRFile, RANK_8)] ^= BLACK_OOO; - chess960 = isChess960; find_checkers(); @@ -230,6 +223,18 @@ void Position::from_fen(const string& fen, bool isChess960) { } +/// Position::set_castle() is an helper function used to set +/// correct castling related flags. + +void Position::set_castle(int f, Square ksq, Square rsq) { + + st->castleRights |= f; + castleRightsMask[ksq] ^= f; + castleRightsMask[rsq] ^= f; + castleRookSquare[f] = rsq; +} + + /// Position::set_castling_rights() sets castling parameters castling avaiability. /// This function is compatible with 3 standards: Normal FEN standard, Shredder-FEN /// that uses the letters of the columns on which the rooks began the game instead @@ -244,42 +249,26 @@ void Position::set_castling_rights(char token) { Square sqA = relative_square(c, SQ_A1); Square sqH = relative_square(c, SQ_H1); - initialKFile = square_file(king_square(c)); + Square rsq, ksq = king_square(c); if (toupper(token) == 'K') { - for (Square sq = sqH; sq >= sqA; sq--) - if (piece_on(sq) == make_piece(c, ROOK)) - { - set_castle_kingside(c); - initialKRFile = square_file(sq); - break; - } + for (rsq = sqH; piece_on(rsq) != make_piece(c, ROOK); rsq--) {} + set_castle(WHITE_OO << c, ksq, rsq); } else if (toupper(token) == 'Q') { - for (Square sq = sqA; sq <= sqH; sq++) - if (piece_on(sq) == make_piece(c, ROOK)) - { - set_castle_queenside(c); - initialQRFile = square_file(sq); - break; - } + for (rsq = sqA; piece_on(rsq) != make_piece(c, ROOK); rsq++) {} + set_castle(WHITE_OOO << c, ksq, rsq); } else if (toupper(token) >= 'A' && toupper(token) <= 'H') { - File rookFile = File(toupper(token) - 'A'); + Square rsq = make_square(File(toupper(token) - 'A'), RANK_1); - if (rookFile < initialKFile) - { - set_castle_queenside(c); - initialQRFile = rookFile; - } + if (square_file(rsq) < square_file(ksq)) + set_castle(WHITE_OOO << c, ksq, rsq); else - { - set_castle_kingside(c); - initialKRFile = rookFile; - } + set_castle(WHITE_OO << c, ksq, rsq); } } @@ -321,17 +310,17 @@ const string Position::to_fen() const { if (st->castleRights != CASTLES_NONE) { - if (can_castle_kingside(WHITE)) - fen += chess960 ? char(toupper(file_to_char(initialKRFile))) : 'K'; + if (can_castle(WHITE_OO)) + fen += chess960 ? char(toupper(file_to_char(square_file(castle_rook_square(WHITE_OO))))) : 'K'; - if (can_castle_queenside(WHITE)) - fen += chess960 ? char(toupper(file_to_char(initialQRFile))) : 'Q'; + if (can_castle(WHITE_OOO)) + fen += chess960 ? char(toupper(file_to_char(square_file(castle_rook_square(WHITE_OOO))))) : 'Q'; - if (can_castle_kingside(BLACK)) - fen += chess960 ? file_to_char(initialKRFile) : 'k'; + if (can_castle(BLACK_OO)) + fen += chess960 ? file_to_char(square_file(castle_rook_square(BLACK_OO))) : 'k'; - if (can_castle_queenside(BLACK)) - fen += chess960 ? file_to_char(initialQRFile) : 'q'; + if (can_castle(BLACK_OOO)) + fen += chess960 ? file_to_char(square_file(castle_rook_square(BLACK_OOO))) : 'q'; } else fen += '-'; @@ -1595,9 +1584,6 @@ void Position::clear() { castleRightsMask[sq] = ALL_CASTLES; sideToMove = WHITE; - initialKFile = FILE_E; - initialKRFile = FILE_H; - initialQRFile = FILE_A; } @@ -1819,21 +1805,14 @@ void Position::flip() { sideToMove = opposite_color(pos.side_to_move()); // Castling rights - if (pos.can_castle_kingside(WHITE)) set_castle_kingside(BLACK); - if (pos.can_castle_queenside(WHITE)) set_castle_queenside(BLACK); - if (pos.can_castle_kingside(BLACK)) set_castle_kingside(WHITE); - if (pos.can_castle_queenside(BLACK)) set_castle_queenside(WHITE); - - initialKFile = pos.initialKFile; - initialKRFile = pos.initialKRFile; - initialQRFile = pos.initialQRFile; - - castleRightsMask[make_square(initialKFile, RANK_1)] ^= (WHITE_OO | WHITE_OOO); - castleRightsMask[make_square(initialKFile, RANK_8)] ^= (BLACK_OO | BLACK_OOO); - castleRightsMask[make_square(initialKRFile, RANK_1)] ^= WHITE_OO; - castleRightsMask[make_square(initialKRFile, RANK_8)] ^= BLACK_OO; - castleRightsMask[make_square(initialQRFile, RANK_1)] ^= WHITE_OOO; - castleRightsMask[make_square(initialQRFile, RANK_8)] ^= BLACK_OOO; + if (pos.can_castle(WHITE_OO)) + set_castle(BLACK_OO, king_square(BLACK), flip_square(pos.castle_rook_square(WHITE_OO))); + if (pos.can_castle(WHITE_OOO)) + set_castle(BLACK_OOO, king_square(BLACK), flip_square(pos.castle_rook_square(WHITE_OOO))); + if (pos.can_castle(BLACK_OO)) + set_castle(WHITE_OO, king_square(WHITE), flip_square(pos.castle_rook_square(BLACK_OO))); + if (pos.can_castle(BLACK_OOO)) + set_castle(WHITE_OOO, king_square(WHITE), flip_square(pos.castle_rook_square(BLACK_OOO))); // En passant square if (pos.st->epSquare != SQ_NONE) @@ -1894,14 +1873,6 @@ bool Position::is_ok(int* failedStep) const { if (piece_on(king_square(BLACK)) != BK) return false; - // Castle files OK? - if (failedStep) (*failedStep)++; - if (!square_is_ok(make_square(initialKRFile, RANK_1))) - return false; - - if (!square_is_ok(make_square(initialQRFile, RANK_1))) - return false; - // Do both sides have exactly one king? if (failedStep) (*failedStep)++; if (debugKingCount) @@ -2015,24 +1986,17 @@ bool Position::is_ok(int* failedStep) const { if (failedStep) (*failedStep)++; if (debugCastleSquares) - { - for (Color c = WHITE; c <= BLACK; c++) + for (CastleRight f = WHITE_OO; f <= BLACK_OOO; f = CastleRight(f << 1)) { - if (can_castle_kingside(c) && piece_on(initial_kr_square(c)) != make_piece(c, ROOK)) - return false; + if (!can_castle(f)) + continue; - if (can_castle_queenside(c) && piece_on(initial_qr_square(c)) != make_piece(c, ROOK)) + Piece rook = (f & (WHITE_OO | WHITE_OOO) ? WR : BR); + + if ( castleRightsMask[castleRookSquare[f]] != (ALL_CASTLES ^ f) + || piece_on(castleRookSquare[f]) != rook) return false; } - if (castleRightsMask[initial_kr_square(WHITE)] != (ALL_CASTLES ^ WHITE_OO)) - return false; - if (castleRightsMask[initial_qr_square(WHITE)] != (ALL_CASTLES ^ WHITE_OOO)) - return false; - if (castleRightsMask[initial_kr_square(BLACK)] != (ALL_CASTLES ^ BLACK_OO)) - return false; - if (castleRightsMask[initial_qr_square(BLACK)] != (ALL_CASTLES ^ BLACK_OOO)) - return false; - } if (failedStep) *failedStep = 0; return true; diff --git a/src/position.h b/src/position.h index d822260d..406dca5a 100644 --- a/src/position.h +++ b/src/position.h @@ -47,7 +47,7 @@ struct CheckInfo { /// Castle rights, encoded as bit fields -enum CastleRights { +enum CastleRight { CASTLES_NONE = 0, WHITE_OO = 1, BLACK_OO = 2, @@ -154,11 +154,9 @@ public: Square king_square(Color c) const; // Castling rights - bool can_castle_kingside(Color c) const; - bool can_castle_queenside(Color c) const; + bool can_castle(CastleRight f) const; bool can_castle(Color c) const; - Square initial_kr_square(Color c) const; - Square initial_qr_square(Color c) const; + Square castle_rook_square(CastleRight f) const; // Bitboards for pinned pieces and discovered check candidates Bitboard discovered_check_candidates(Color c) const; @@ -251,8 +249,7 @@ private: void clear(); void detach(); void put_piece(Piece p, Square s); - void set_castle_kingside(Color c); - void set_castle_queenside(Color c); + void set_castle(int f, Square ksq, Square rsq); void set_castling_rights(char token); bool move_is_pl_slow(const Move m) const; @@ -292,8 +289,8 @@ private: Color sideToMove; Key history[MaxGameLength]; int castleRightsMask[64]; + Square castleRookSquare[16]; // [CastleRights] StateInfo startState; - File initialKFile, initialKRFile, initialQRFile; bool chess960; int fullMoves; int threadID; @@ -381,32 +378,16 @@ inline Square Position::king_square(Color c) const { return pieceList[c][KING][0]; } -inline bool Position::can_castle_kingside(Color c) const { - return st->castleRights & (WHITE_OO << c); -} - -inline bool Position::can_castle_queenside(Color c) const { - return st->castleRights & (WHITE_OOO << c); +inline bool Position::can_castle(CastleRight f) const { + return st->castleRights & f; } inline bool Position::can_castle(Color c) const { return st->castleRights & ((WHITE_OO | WHITE_OOO) << c); } -inline void Position::set_castle_kingside(Color c) { - st->castleRights |= (WHITE_OO << c); -} - -inline void Position::set_castle_queenside(Color c) { - st->castleRights |= (WHITE_OOO << c); -} - -inline Square Position::initial_kr_square(Color c) const { - return relative_square(c, make_square(initialKRFile, RANK_1)); -} - -inline Square Position::initial_qr_square(Color c) const { - return relative_square(c, make_square(initialQRFile, RANK_1)); +inline Square Position::castle_rook_square(CastleRight f) const { + return castleRookSquare[f]; } template<>