]> git.sesse.net Git - stockfish/blobdiff - src/position.cpp
Revert hidden checkers rework
[stockfish] / src / position.cpp
index 81208ac2262b87b3a7113d1297ade6218e12c268..67680b1fbac52c46360109abdabbd6bcf585863a 100644 (file)
@@ -207,7 +207,6 @@ void Position::from_fen(const std::string& fen) {
   castleRightsMask[make_square(initialQRFile, RANK_8)] ^= BLACK_OOO;
 
   find_checkers();
-  find_hidden_checks();
 
   st->key = compute_key();
   st->pawnKey = compute_pawn_key();
@@ -321,6 +320,29 @@ 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 p;
+  Square ksq = king_square(c);
+  return hidden_checks<ROOK, true>(c, ksq, p) | hidden_checks<BISHOP, true>(c, ksq, p);
+}
+
+
+/// 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 p;
+  Square ksq = king_square(opposite_color(c));
+  return hidden_checks<ROOK, false>(c, ksq, p) | hidden_checks<BISHOP, false>(c, ksq, p);
+}
+
+
 /// 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
@@ -446,34 +468,19 @@ void Position::find_checkers() {
   st->checkersBB = attacks_to(king_square(us), opposite_color(us));
 }
 
-/// Position:find_hidden_checks() computes the pinned, pinners and dcCandidates
-/// bitboards. There are two versions of this function. One takes a color and
-/// computes bitboards relative to that color only, the other computes both
-/// colors. Bitboard checkersBB must be already updated.
-
-void Position::find_hidden_checks(Color us) {
 
-  Bitboard p1, p2;
-  Color them = opposite_color(us);
-  Square ksq = king_square(them);
-  st->pinned[them] = hidden_checks<ROOK, true>(them, ksq, p1) | hidden_checks<BISHOP, true>(them, ksq, p2);
-  st->pinners[them] = p1 | p2;
-  st->dcCandidates[us] = hidden_checks<ROOK, false>(us, ksq, p1) | hidden_checks<BISHOP, false>(us, ksq, p2);
-}
+/// Position::pl_move_is_legal() tests whether a pseudo-legal move is legal
 
-void Position::find_hidden_checks() {
+bool Position::pl_move_is_legal(Move m) const {
 
-  for (Color c = WHITE; c <= BLACK; c++)
-      find_hidden_checks(c);
+  return pl_move_is_legal(m, pinned_pieces(side_to_move()));
 }
 
-
-/// Position::pl_move_is_legal() tests whether a pseudo-legal move is legal
-
-bool Position::pl_move_is_legal(Move m) const {
+bool Position::pl_move_is_legal(Move m, Bitboard pinned) const {
 
   assert(is_ok());
   assert(move_is_ok(m));
+  assert(pinned == pinned_pieces(side_to_move()));
 
   // If we're in check, all pseudo-legal moves are legal, because our
   // check evasion generator only generates true legal moves.
@@ -521,7 +528,7 @@ bool Position::pl_move_is_legal(Move m) const {
 
   // A non-king move is legal if and only if it is not pinned or it
   // is moving along the ray towards or away from the king.
-  return (   !bit_is_set(pinned_pieces(us), from)
+  return (   !bit_is_set(pinned, from)
           || (direction_between_squares(from, ksq) == direction_between_squares(move_to(m), ksq)));
 }
 
@@ -530,15 +537,21 @@ bool Position::pl_move_is_legal(Move m) const {
 
 bool Position::move_is_check(Move m) const {
 
+  Bitboard dc = discovered_check_candidates(side_to_move());
+  return move_is_check(m, dc);
+}
+
+bool Position::move_is_check(Move m, Bitboard dcCandidates) const {
+
   assert(is_ok());
   assert(move_is_ok(m));
+  assert(dcCandidates == discovered_check_candidates(side_to_move()));
 
   Color us = side_to_move();
   Color them = opposite_color(us);
   Square from = move_from(m);
   Square to = move_to(m);
   Square ksq = king_square(them);
-  Bitboard dcCandidates = discovered_check_candidates(us);
 
   assert(color_of_piece_on(from) == us);
   assert(piece_on(ksq) == piece_of_color_and_type(them, KING));
@@ -680,63 +693,20 @@ inline void Position::update_checkers(Bitboard* pCheckersBB, Square ksq, Square
 }
 
 
-/// Position::update_hidden_checks() udpates pinned, pinners and dcCandidates
-/// bitboards incrementally, given the move. It is called in do_move and is
-/// faster then find_hidden_checks().
-
-void Position::update_hidden_checks(Square from, Square to) {
-
-  Color us = sideToMove;
-  Color them = opposite_color(us);
-  Square ksq = king_square(opposite_color(us));
-
-  Bitboard moveSquares = EmptyBoardBB;
-  set_bit(&moveSquares, from);
-  set_bit(&moveSquares, to);
-
-  // Our moving piece could have been a possible pinner or hidden checker behind a dcCandidates?
-  bool checkerMoved = (st->dcCandidates[us] | st->pinners[them]) && (moveSquares & sliders());
-
-  // If we are moving from/to an opponent king attack direction and we was a possible hidden checker
-  // or there exsist some possible hidden checker on that line then recalculate the position
-  // otherwise skip because our dcCandidates and opponent pinned pieces are not changed.
-  if (   (moveSquares & RookPseudoAttacks[ksq])   && (checkerMoved || (rooks_and_queens(us)   & RookPseudoAttacks[ksq]))
-      || (moveSquares & BishopPseudoAttacks[ksq]) && (checkerMoved || (bishops_and_queens(us) & BishopPseudoAttacks[ksq])))
-      find_hidden_checks(us);
-
-  ksq = king_square(us);
-
-  if (ksq == to)
-  {
-      find_hidden_checks(them);
-      return;
-  }
-
-  // It is possible that we have captured an opponent hidden checker?
-  Bitboard checkerCaptured = st->capture && (st->dcCandidates[them] || bit_is_set(st->pinners[us], to));
-
-  // If we are moving from/to an our king attack direction and there was/is some possible
-  // opponent hidden checker then calculate the position otherwise skip because opponent
-  // dcCandidates and our pinned pieces are not changed.
-  if (   (moveSquares & RookPseudoAttacks[ksq])   && (checkerCaptured || (rooks_and_queens(them)   & RookPseudoAttacks[ksq]))
-      || (moveSquares & BishopPseudoAttacks[ksq]) && (checkerCaptured || (bishops_and_queens(them) & BishopPseudoAttacks[ksq])))
-      find_hidden_checks(them);
-}
-
-
 /// Position::do_move() makes a move, and saves all information necessary
 /// to a StateInfo object. The move is assumed to be legal.
 /// Pseudo-legal moves should be filtered out before this function is called.
 
 void Position::do_move(Move m, StateInfo& newSt) {
 
+  do_move(m, newSt, discovered_check_candidates(side_to_move()));
+}
+
+void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) {
+
   assert(is_ok());
   assert(move_is_ok(m));
 
-  // Get now the current (before to move) dc candidates that we will use
-  // in update_checkers().
-  Bitboard oldDcCandidates = discovered_check_candidates(side_to_move());
-
   // Copy some fields of old state to our new StateInfo object (except the
   // captured piece, which is taken care of later) and switch state pointer
   // to point to the new, ready to be updated, state.
@@ -842,16 +812,14 @@ void Position::do_move(Move m, StateInfo& newSt) {
     Square ksq = king_square(them);
     switch (piece)
     {
-    case PAWN:   update_checkers<PAWN>(&st->checkersBB, ksq, from, to, oldDcCandidates);   break;
-    case KNIGHT: update_checkers<KNIGHT>(&st->checkersBB, ksq, from, to, oldDcCandidates); break;
-    case BISHOP: update_checkers<BISHOP>(&st->checkersBB, ksq, from, to, oldDcCandidates); break;
-    case ROOK:   update_checkers<ROOK>(&st->checkersBB, ksq, from, to, oldDcCandidates);   break;
-    case QUEEN:  update_checkers<QUEEN>(&st->checkersBB, ksq, from, to, oldDcCandidates);  break;
-    case KING:   update_checkers<KING>(&st->checkersBB, ksq, from, to, oldDcCandidates);   break;
+    case PAWN:   update_checkers<PAWN>(&(st->checkersBB), ksq, from, to, dcCandidates);   break;
+    case KNIGHT: update_checkers<KNIGHT>(&(st->checkersBB), ksq, from, to, dcCandidates); break;
+    case BISHOP: update_checkers<BISHOP>(&(st->checkersBB), ksq, from, to, dcCandidates); break;
+    case ROOK:   update_checkers<ROOK>(&(st->checkersBB), ksq, from, to, dcCandidates);   break;
+    case QUEEN:  update_checkers<QUEEN>(&(st->checkersBB), ksq, from, to, dcCandidates);  break;
+    case KING:   update_checkers<KING>(&(st->checkersBB), ksq, from, to, dcCandidates);   break;
     default: assert(false); break;
     }
-
-    update_hidden_checks(from, to);
   }
 
   // Finish
@@ -1003,9 +971,6 @@ void Position::do_castle_move(Move m) {
 
   // Update checkers BB
   st->checkersBB = attacks_to(king_square(them), us);
-
-  // Update hidden checks
-  find_hidden_checks();
 }
 
 
@@ -1096,9 +1061,6 @@ void Position::do_promotion_move(Move m) {
 
   // Update checkers BB
   st->checkersBB = attacks_to(king_square(them), us);
-
-  // Update hidden checks
-  find_hidden_checks();
 }
 
 
@@ -1181,9 +1143,6 @@ void Position::do_ep_move(Move m) {
 
   // Update checkers BB
   st->checkersBB = attacks_to(king_square(them), us);
-
-  // Update hidden checks
-  find_hidden_checks();
 }
 
 
@@ -1568,11 +1527,6 @@ int Position::see(Square from, Square to) const {
   Color us = (from != SQ_NONE ? color_of_piece_on(from) : opposite_color(color_of_piece_on(to)));
   Color them = opposite_color(us);
 
-  // Initialize pinned and pinners bitboards
-  Bitboard pinned[2], pinners[2];
-  pinned[us] = pinned_pieces(us, pinners[us]);
-  pinned[them] = pinned_pieces(them, pinners[them]);
-
   // Initialize pieces
   Piece piece = piece_on(from);
   Piece capture = piece_on(to);
@@ -1605,17 +1559,6 @@ int Position::see(Square from, Square to) const {
                  | (pawn_attacks(WHITE, to)    & pawns(BLACK))
                  | (pawn_attacks(BLACK, to)    & pawns(WHITE));
 
-      // Remove our pinned pieces from attacks if the captured piece is not
-      // a pinner, otherwise we could remove a valid "capture the pinner" attack.
-      if (pinned[us] != EmptyBoardBB && !bit_is_set(pinners[us], to))
-          attackers &= ~pinned[us];
-
-      // Remove opponent pinned pieces from attacks if the moving piece is not
-      // a pinner, otherwise we could remove a piece that is no more pinned
-      // due to our pinner piece is moving away.
-      if (pinned[them] != EmptyBoardBB && !bit_is_set(pinners[them], from))
-          attackers &= ~pinned[them];
-
       if (from != SQ_NONE)
           break;
 
@@ -1678,12 +1621,6 @@ int Position::see(Square from, Square to) const {
       lastCapturingPieceValue = seeValues[pt];
       c = opposite_color(c);
 
-      // Remove pinned pieces from attackers
-      if (    pinned[c] != EmptyBoardBB
-          && !bit_is_set(pinners[c], to)
-          && !(pinners[c] & attackers))
-          attackers &= ~pinned[c];
-
       // Stop after a king capture
       if (pt == KING && (attackers & pieces_of_color(c)))
       {