]> git.sesse.net Git - stockfish/blobdiff - src/position.cpp
Unify pinned and discovery checks code
[stockfish] / src / position.cpp
index ff93e532d999c3012e4774a35ea98a1e07c4417b..111f5cead6808b623c6641d38c77066b86eb9869 100644 (file)
@@ -298,71 +298,64 @@ void Position::copy(const Position &pos) {
 
 /// Position:pinned_pieces() returns a bitboard of all pinned (against the
 /// king) pieces for the given color.
-
 Bitboard Position::pinned_pieces(Color c) const {
-  Bitboard b1, b2, pinned, pinners, sliders;
-  Square ksq = king_square(c), s;
-  Color them = opposite_color(c);
-
-  pinned = EmptyBoardBB;
-  b1 = occupied_squares();
-
-  sliders = rooks_and_queens(them) & ~checkers();
-  if(sliders & RookPseudoAttacks[ksq]) {
-    b2 = piece_attacks<ROOK>(ksq) & pieces_of_color(c);
-    pinners = rook_attacks_bb(ksq, b1 ^ b2) & sliders;
-    while(pinners) {
-      s = pop_1st_bit(&pinners);
-      pinned |= (squares_between(s, ksq) & b2);
-    }
-  }
 
-  sliders = bishops_and_queens(them) & ~checkers();
-  if(sliders & BishopPseudoAttacks[ksq]) {
-    b2 = piece_attacks<BISHOP>(ksq) & pieces_of_color(c);
-    pinners = bishop_attacks_bb(ksq, b1 ^ b2) & sliders;
-    while(pinners) {
-      s = pop_1st_bit(&pinners);
-      pinned |= (squares_between(s, ksq) & b2);
-    }
-  }
-
-  return pinned;
+  Square ksq = king_square(c);
+  return hidden_checks<ROOK, true>(c, ksq) | hidden_checks<BISHOP, true>(c, ksq);
 }
 
+
 /// Position:discovered_check_candidates() returns a bitboard containing all
 /// pieces for the given side which are candidates for giving a discovered
 /// check.  The code is almost the same as the function for finding pinned
 /// pieces.
 
 Bitboard Position::discovered_check_candidates(Color c) const {
-  Bitboard b1, b2, dc, checkers, sliders;
-  Square ksq = king_square(opposite_color(c)), s;
-
-  dc = EmptyBoardBB;
-  b1 = occupied_squares();
-
-  sliders = rooks_and_queens(c);
-  if(sliders & RookPseudoAttacks[ksq]) {
-    b2 = piece_attacks<ROOK>(ksq) & pieces_of_color(c);
-    checkers = rook_attacks_bb(ksq, b1 ^ b2) & sliders;
-    while(checkers) {
-      s = pop_1st_bit(&checkers);
-      dc |= (squares_between(s, ksq) & b2);
-    }
-  }
 
-  sliders = bishops_and_queens(c);
-  if(sliders & BishopPseudoAttacks[ksq]) {
-    b2 = piece_attacks<BISHOP>(ksq) & pieces_of_color(c);
-    checkers = bishop_attacks_bb(ksq, b1 ^ b2) & sliders;
-    while(checkers) {
-      s = pop_1st_bit(&checkers);
-      dc |= (squares_between(s, ksq) & b2);
-    }
-  }
+  Square ksq = king_square(opposite_color(c));
+  return hidden_checks<ROOK, false>(c, ksq) | hidden_checks<BISHOP, false>(c, ksq);
+}
+
+
+/// Position:hidden_checks<>() returns a bitboard of all pinned (against the
+/// king) pieces for the given color and for the given pinner type. Or, when
+/// template parameter FindPinned is false, the pinned pieces of opposite color
+/// that are, indeed, the pieces candidate for a discovery check.
+template<PieceType Piece, bool FindPinned>
+Bitboard Position::hidden_checks(Color c, Square ksq) const {
 
-  return dc;
+  Square s;
+  Bitboard sliders, result = EmptyBoardBB;
+  
+  if (Piece == ROOK) // Resolved at compile time
+      sliders = rooks_and_queens(FindPinned ? opposite_color(c) : c) & RookPseudoAttacks[ksq];
+  else
+      sliders = bishops_and_queens(FindPinned ? opposite_color(c) : c) & BishopPseudoAttacks[ksq];
+
+  if (sliders && (!FindPinned || (sliders & ~checkersBB)))
+  {
+       // King blockers are candidate pinned pieces
+      Bitboard candidate_pinned = piece_attacks<Piece>(ksq) & pieces_of_color(c);
+
+      // Pinners are sliders, not checkers, that give check when 
+      // candidate pinned are removed.
+      Bitboard pinners = (FindPinned ? sliders & ~checkersBB : sliders);
+
+      if (Piece == ROOK)
+          pinners &= rook_attacks_bb(ksq, occupied_squares() ^ candidate_pinned);
+      else
+          pinners &= bishop_attacks_bb(ksq, occupied_squares() ^ candidate_pinned);
+
+
+      // Finally for each pinner find the corresponding pinned piece (if same color of king)
+      // or discovery checker (if opposite color) among the candidates.
+      while (pinners)
+      {
+          s = pop_1st_bit(&pinners);
+          result |= (squares_between(s, ksq) & candidate_pinned);
+      }
+  }
+  return result;
 }