Greatly simplify castling rights handling
authorMarco Costalba <mcostalba@gmail.com>
Mon, 27 Jun 2011 15:06:15 +0000 (16:06 +0100)
committerMarco Costalba <mcostalba@gmail.com>
Mon, 27 Jun 2011 18:26:30 +0000 (19:26 +0100)
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
src/book.cpp
src/movegen.cpp
src/position.cpp
src/position.h

index 8944b31bdb3d8d63bd19e9da206b196af7ababed..ed5cba4b0eb208b7b3ae3eff52226fe0013c5c3b 100644 (file)
@@ -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)
index d821f0fad2e0ce56ccf6e03e6d22850b02ddb0b5..3d736b255952537f26515f97b5118116b9b1fce9 100644 (file)
@@ -178,12 +178,12 @@ MoveStack* generate(const Position& pos, MoveStack* mlist) {
   mlist = generate_piece_moves<QUEEN>(pos, mlist, us, target);
   mlist = generate_piece_moves<KING>(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<KING_SIDE>(pos, mlist, us);
 
-      if (pos.can_castle_queenside(us))
+      if (pos.can_castle(us == WHITE ? WHITE_OOO : BLACK_OOO))
           mlist = generate_castle_moves<QUEEN_SIDE>(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;
index 0dbbbddf81449b399386e7ae8e87585ffb4f90ca..f9fd0b73e51363068eaef1ab35deeaca200b125e 100644 (file)
@@ -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;
index d822260dd768fb6eca1776435d80fb39cb7ad318..406dca5aa82b5da3b91014f7860a093df8c91389 100644 (file)
@@ -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<>