]> git.sesse.net Git - stockfish/commitdiff
Revert hidden checkers rework
authorMarco Costalba <mcostalba@gmail.com>
Mon, 2 Mar 2009 15:20:00 +0000 (16:20 +0100)
committerMarco Costalba <mcostalba@gmail.com>
Mon, 2 Mar 2009 15:20:00 +0000 (16:20 +0100)
It is slower the previous uglier but faster code.

So completely restore old one for now :-(

Just leave in the rework of status backup/restore in do_move().

We will cherry pick bits of previous work once we are sure
we have fixed the performance regression.

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

index 37e66724e5decd81e25a8eaecd552264f200e2c1..258f9c710616a208339b055599f999c0817b382a 100644 (file)
@@ -166,14 +166,13 @@ int generate_noncaptures(const Position& pos, MoveStack* mlist) {
 /// generate_checks() generates all pseudo-legal non-capturing, non-promoting
 /// checks. It returns the number of generated moves.
 
 /// generate_checks() generates all pseudo-legal non-capturing, non-promoting
 /// checks. It returns the number of generated moves.
 
-int generate_checks(const Position& pos, MoveStack* mlist) {
+int generate_checks(const Position& pos, MoveStack* mlist, Bitboard dc) {
 
   assert(pos.is_ok());
   assert(!pos.is_check());
 
   Color us = pos.side_to_move();
   Square ksq = pos.king_square(opposite_color(us));
 
   assert(pos.is_ok());
   assert(!pos.is_check());
 
   Color us = pos.side_to_move();
   Square ksq = pos.king_square(opposite_color(us));
-  Bitboard dc = pos.discovered_check_candidates(us);
   MoveStack* mlist_start = mlist;
 
   assert(pos.piece_on(ksq) == piece_of_color_and_type(opposite_color(us), KING));
   MoveStack* mlist_start = mlist;
 
   assert(pos.piece_on(ksq) == piece_of_color_and_type(opposite_color(us), KING));
@@ -205,7 +204,7 @@ int generate_checks(const Position& pos, MoveStack* mlist) {
 /// in check. Unlike the other move generation functions, this one generates
 /// only legal moves. It returns the number of generated moves.
 
 /// in check. Unlike the other move generation functions, this one generates
 /// only legal moves. It returns the number of generated moves.
 
-int generate_evasions(const Position& pos, MoveStack* mlist) {
+int generate_evasions(const Position& pos, MoveStack* mlist, Bitboard pinned) {
 
   assert(pos.is_ok());
   assert(pos.is_check());
 
   assert(pos.is_ok());
   assert(pos.is_check());
@@ -259,7 +258,6 @@ int generate_evasions(const Position& pos, MoveStack* mlist) {
   if (!(checkers & (checkers - 1))) // Only one bit set?
   {
       Square checksq = first_1(checkers);
   if (!(checkers & (checkers - 1))) // Only one bit set?
   {
       Square checksq = first_1(checkers);
-      Bitboard pinned = pos.pinned_pieces(us);
 
       assert(pos.color_of_piece_on(checksq) == them);
 
 
       assert(pos.color_of_piece_on(checksq) == them);
 
@@ -349,8 +347,10 @@ int generate_legal_moves(const Position& pos, MoveStack* mlist) {
 
   assert(pos.is_ok());
 
 
   assert(pos.is_ok());
 
+  Bitboard pinned = pos.pinned_pieces(pos.side_to_move());
+
   if (pos.is_check())
   if (pos.is_check())
-      return generate_evasions(pos, mlist);
+      return generate_evasions(pos, mlist, pinned);
 
   // Generate pseudo-legal moves
   int n = generate_captures(pos, mlist);
 
   // Generate pseudo-legal moves
   int n = generate_captures(pos, mlist);
@@ -358,7 +358,7 @@ int generate_legal_moves(const Position& pos, MoveStack* mlist) {
 
   // Remove illegal moves from the list
   for (int i = 0; i < n; i++)
 
   // Remove illegal moves from the list
   for (int i = 0; i < n; i++)
-      if (!pos.pl_move_is_legal(mlist[i].move))
+      if (!pos.pl_move_is_legal(mlist[i].move, pinned))
           mlist[i--].move = mlist[--n].move;
 
   return n;
           mlist[i--].move = mlist[--n].move;
 
   return n;
@@ -371,11 +371,12 @@ int generate_legal_moves(const Position& pos, MoveStack* mlist) {
 /// returned. If not, the function returns false.  This function must
 /// only be used when the side to move is not in check.
 
 /// returned. If not, the function returns false.  This function must
 /// only be used when the side to move is not in check.
 
-bool move_is_legal(const Position& pos, const Move m) {
+bool move_is_legal(const Position& pos, const Move m, Bitboard pinned) {
 
   assert(pos.is_ok());
   assert(!pos.is_check());
   assert(move_is_ok(m));
 
   assert(pos.is_ok());
   assert(!pos.is_check());
   assert(move_is_ok(m));
+  assert(pinned == pos.pinned_pieces(pos.side_to_move()));
 
   Color us = pos.side_to_move();
   Color them = opposite_color(us);
 
   Color us = pos.side_to_move();
   Color them = opposite_color(us);
@@ -402,7 +403,7 @@ bool move_is_legal(const Position& pos, const Move m) {
       assert(pos.piece_on(to - pawn_push(us)) == piece_of_color_and_type(them, PAWN));
 
       // The move is pseudo-legal, check if it is also legal
       assert(pos.piece_on(to - pawn_push(us)) == piece_of_color_and_type(them, PAWN));
 
       // The move is pseudo-legal, check if it is also legal
-      return pos.pl_move_is_legal(m);
+      return pos.pl_move_is_legal(m, pinned);
   }
 
   // Castling moves
   }
 
   // Castling moves
@@ -534,12 +535,12 @@ bool move_is_legal(const Position& pos, const Move m) {
           return false;
       }
       // The move is pseudo-legal, check if it is also legal
           return false;
       }
       // The move is pseudo-legal, check if it is also legal
-      return pos.pl_move_is_legal(m);
+      return pos.pl_move_is_legal(m, pinned);
   }
 
   // Luckly we can handle all the other pieces in one go
   return (   pos.piece_attacks_square(pos.piece_on(from), from, to)
   }
 
   // Luckly we can handle all the other pieces in one go
   return (   pos.piece_attacks_square(pos.piece_on(from), from, to)
-          && pos.pl_move_is_legal(m)
+          && pos.pl_move_is_legal(m, pinned)
           && !move_promotion(m));
 }
 
           && !move_promotion(m));
 }
 
index bdb7df48d52e3fab30278b7581d877439c4f4841..48e0dec032ca848ec00118c82d9719fd7c1a8968 100644 (file)
 
 extern int generate_captures(const Position &pos, MoveStack *mlist);
 extern int generate_noncaptures(const Position &pos, MoveStack *mlist);
 
 extern int generate_captures(const Position &pos, MoveStack *mlist);
 extern int generate_noncaptures(const Position &pos, MoveStack *mlist);
-extern int generate_checks(const Position &pos, MoveStack *mlist);
-extern int generate_evasions(const Position &pos, MoveStack *mlist);
+extern int generate_checks(const Position &pos, MoveStack *mlist, Bitboard dc);
+extern int generate_evasions(const Position &pos, MoveStack *mlist, Bitboard pinned);
 extern int generate_legal_moves(const Position &pos, MoveStack *mlist);
 extern int generate_legal_moves(const Position &pos, MoveStack *mlist);
-extern bool move_is_legal(const Position &pos, const Move m);
+extern bool move_is_legal(const Position &pos, const Move m, Bitboard pinned);
 
 
 #endif // !defined(MOVEGEN_H_INCLUDED)
 
 
 #endif // !defined(MOVEGEN_H_INCLUDED)
index 59b134532e4ec5318884c9b2810d902d0af337cb..d9fe8d2cf329c2cf4fe109efec6f0225f329611d 100644 (file)
@@ -96,6 +96,9 @@ MovePicker::MovePicker(const Position& p, bool pv, Move ttm,
   else
       phaseIndex = (noCaptures ? NoMovesPhaseIndex : QsearchWithoutChecksPhaseIndex);
 
   else
       phaseIndex = (noCaptures ? NoMovesPhaseIndex : QsearchWithoutChecksPhaseIndex);
 
+  dc = p.discovered_check_candidates(us);
+  pinned = p.pinned_pieces(us);
+
   finished = false;
 }
 
   finished = false;
 }
 
@@ -127,7 +130,7 @@ Move MovePicker::get_next_move() {
         if (ttMove != MOVE_NONE)
         {
             assert(move_is_ok(ttMove));
         if (ttMove != MOVE_NONE)
         {
             assert(move_is_ok(ttMove));
-            if (move_is_legal(pos, ttMove))
+            if (move_is_legal(pos, ttMove, pinned))
                 return ttMove;
         }
         break;
                 return ttMove;
         }
         break;
@@ -136,7 +139,7 @@ Move MovePicker::get_next_move() {
         if (mateKiller != MOVE_NONE)
         {
             assert(move_is_ok(mateKiller));
         if (mateKiller != MOVE_NONE)
         {
             assert(move_is_ok(mateKiller));
-            if (move_is_legal(pos, mateKiller))
+            if (move_is_legal(pos, mateKiller, pinned))
                 return mateKiller;
        }
        break;
                 return mateKiller;
        }
        break;
@@ -159,7 +162,7 @@ Move MovePicker::get_next_move() {
 
     case PH_EVASIONS:
         assert(pos.is_check());
 
     case PH_EVASIONS:
         assert(pos.is_check());
-        numOfMoves = generate_evasions(pos, moves);
+        numOfMoves = generate_evasions(pos, moves, pinned);
         score_evasions();
         movesPicked = 0;
         break;
         score_evasions();
         movesPicked = 0;
         break;
@@ -171,7 +174,7 @@ Move MovePicker::get_next_move() {
         break;
 
     case PH_QCHECKS:
         break;
 
     case PH_QCHECKS:
-        numOfMoves = generate_checks(pos, moves);
+        numOfMoves = generate_checks(pos, moves, dc);
         movesPicked = 0;
         break;
 
         movesPicked = 0;
         break;
 
@@ -391,7 +394,7 @@ Move MovePicker::pick_move_from_list() {
           moves[bestIndex] = moves[movesPicked++];
           if (   move != ttMove
               && move != mateKiller
           moves[bestIndex] = moves[movesPicked++];
           if (   move != ttMove
               && move != mateKiller
-              && pos.pl_move_is_legal(move))
+              && pos.pl_move_is_legal(move, pinned))
               return move;
       }
       break;
               return move;
       }
       break;
@@ -411,7 +414,7 @@ Move MovePicker::pick_move_from_list() {
           moves[bestIndex] = moves[movesPicked++];
           if (   move != ttMove
               && move != mateKiller
           moves[bestIndex] = moves[movesPicked++];
           if (   move != ttMove
               && move != mateKiller
-              && pos.pl_move_is_legal(move))
+              && pos.pl_move_is_legal(move, pinned))
               return move;
       }
       break;
               return move;
       }
       break;
@@ -439,7 +442,7 @@ Move MovePicker::pick_move_from_list() {
           move = badCaptures[movesPicked++].move;
           if (   move != ttMove
               && move != mateKiller
           move = badCaptures[movesPicked++].move;
           if (   move != ttMove
               && move != mateKiller
-              && pos.pl_move_is_legal(move))
+              && pos.pl_move_is_legal(move, pinned))
               return move;
       }
       break;
               return move;
       }
       break;
@@ -454,7 +457,7 @@ Move MovePicker::pick_move_from_list() {
           moves[bestIndex] = moves[movesPicked++];
           // Remember to change the line below if we decide to hash the qsearch!
           // Maybe also postpone the legality check until after futility pruning?
           moves[bestIndex] = moves[movesPicked++];
           // Remember to change the line below if we decide to hash the qsearch!
           // Maybe also postpone the legality check until after futility pruning?
-          if (/* move != ttMove && */ pos.pl_move_is_legal(move))
+          if (/* move != ttMove && */ pos.pl_move_is_legal(move, pinned))
               return move;
       }
       break;
               return move;
       }
       break;
@@ -468,7 +471,7 @@ Move MovePicker::pick_move_from_list() {
       {
           move = moves[movesPicked++].move;
           // Remember to change the line below if we decide to hash the qsearch!
       {
           move = moves[movesPicked++].move;
           // Remember to change the line below if we decide to hash the qsearch!
-          if (/* move != ttMove && */ pos.pl_move_is_legal(move))
+          if (/* move != ttMove && */ pos.pl_move_is_legal(move, pinned))
               return move;
       }
       break;
               return move;
       }
       break;
index e0d6ca53ca1b091e875e5b5ac88da0cc153c1f92..2c861c71db873377800dca30e2e3d82096739dd2 100644 (file)
@@ -69,6 +69,7 @@ public:
   int number_of_moves() const;
   int current_move_score() const;
   MovegenPhase current_move_type() const;
   int number_of_moves() const;
   int current_move_score() const;
   MovegenPhase current_move_type() const;
+  Bitboard discovered_check_candidates() const;
 
   static void init_phase_table();
 
 
   static void init_phase_table();
 
@@ -83,6 +84,7 @@ private:
 
   const Position& pos;
   Move ttMove, mateKiller, killer1, killer2;
 
   const Position& pos;
   Move ttMove, mateKiller, killer1, killer2;
+  Bitboard pinned, dc;
   MoveStack moves[256], badCaptures[64];
   bool pvNode;
   Depth depth;
   MoveStack moves[256], badCaptures[64];
   bool pvNode;
   Depth depth;
@@ -107,4 +109,12 @@ inline int MovePicker::number_of_moves() const {
   return numOfMoves;
 }
 
   return numOfMoves;
 }
 
+/// MovePicker::discovered_check_candidates() returns a bitboard containing
+/// all pieces which can possibly give discovered check.  This bitboard is
+/// computed by the constructor function.
+
+inline Bitboard MovePicker::discovered_check_candidates() const {
+  return dc;
+}
+
 #endif // !defined(MOVEPICK_H_INCLUDED)
 #endif // !defined(MOVEPICK_H_INCLUDED)
index e6125ec7c2c756816bc098014d132fa04900ae03..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();
   castleRightsMask[make_square(initialQRFile, RANK_8)] ^= BLACK_OOO;
 
   find_checkers();
-  find_hidden_checks();
 
   st->key = compute_key();
   st->pawnKey = compute_pawn_key();
 
   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
 /// 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,38 +468,19 @@ void Position::find_checkers() {
   st->checkersBB = attacks_to(king_square(us), opposite_color(us));
 }
 
   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, unsigned int types) {
 
 
-  Bitboard p1, p2;
-  Color them = opposite_color(us);
-  Square ksq = king_square(them);
-  if (types & Pinned)
-  {
-      st->pinned[them] = hidden_checks<ROOK, true>(them, ksq, p1) | hidden_checks<BISHOP, true>(them, ksq, p2);
-      st->pinners[them] = p1 | p2;
-  }
-  if (types & DcCandidates)
-      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, Pinned | DcCandidates);
+  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(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.
 
   // If we're in check, all pseudo-legal moves are legal, because our
   // check evasion generator only generates true legal moves.
@@ -525,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.
 
   // 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)));
 }
 
           || (direction_between_squares(from, ksq) == direction_between_squares(move_to(m), ksq)));
 }
 
@@ -534,15 +537,21 @@ bool Position::pl_move_is_legal(Move m) const {
 
 bool Position::move_is_check(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(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);
 
   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));
 
   assert(color_of_piece_on(from) == us);
   assert(piece_on(ksq) == piece_of_color_and_type(them, KING));
@@ -684,88 +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] || bit_is_set(st->pinners[them], from)) && (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])))
-    {
-        // If the move gives direct check and we don't have pinners/dc cadidates
-        // then we can be sure that we won't have them also after the move if
-        // we are not moving from a possible king attack direction.
-        bool outsideChecker = false;
-
-        if (   bit_is_set(st->checkersBB, to)
-            && !(bit_is_set(RookPseudoAttacks[ksq],   from) && (checkerMoved || (rooks_and_queens(us)   & RookPseudoAttacks[ksq])))
-            && !(bit_is_set(BishopPseudoAttacks[ksq], from) && (checkerMoved || (bishops_and_queens(us) & BishopPseudoAttacks[ksq]))))
-            outsideChecker = true;
-
-        if (!outsideChecker || st->pinned[them])
-            find_hidden_checks(us, Pinned);
-
-        if (!outsideChecker || st->dcCandidates[us] || bit_is_set(st->pinned[them], to))
-            find_hidden_checks(us, DcCandidates);
-  }
-
-  ksq = king_square(us);
-
-  if (ksq == to)
-  {
-      find_hidden_checks(them, Pinned | DcCandidates);
-      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, Pinned);
-
-      // If we don't have opponent dc candidates and we are moving in the
-      // attack line then won't be any dc candidates also after the move.
-      if (   st->dcCandidates[them]
-          || (bit_is_set(RookPseudoAttacks[ksq], from) && (rooks_and_queens(them) & RookPseudoAttacks[ksq]))
-          || (bit_is_set(BishopPseudoAttacks[ksq], from) && (bishops_and_queens(them) & BishopPseudoAttacks[ksq])))
-          find_hidden_checks(them, DcCandidates);
-  }
-}
-
-
 /// 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) {
 
 /// 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));
 
   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.
   // 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.
@@ -871,16 +812,14 @@ void Position::do_move(Move m, StateInfo& newSt) {
     Square ksq = king_square(them);
     switch (piece)
     {
     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;
     }
     default: assert(false); break;
     }
-
-    update_hidden_checks(from, to);
   }
 
   // Finish
   }
 
   // Finish
@@ -1032,9 +971,6 @@ void Position::do_castle_move(Move m) {
 
   // Update checkers BB
   st->checkersBB = attacks_to(king_square(them), us);
 
   // Update checkers BB
   st->checkersBB = attacks_to(king_square(them), us);
-
-  // Update hidden checks
-  find_hidden_checks();
 }
 
 
 }
 
 
@@ -1125,9 +1061,6 @@ void Position::do_promotion_move(Move m) {
 
   // Update checkers BB
   st->checkersBB = attacks_to(king_square(them), us);
 
   // Update checkers BB
   st->checkersBB = attacks_to(king_square(them), us);
-
-  // Update hidden checks
-  find_hidden_checks();
 }
 
 
 }
 
 
@@ -1210,9 +1143,6 @@ void Position::do_ep_move(Move m) {
 
   // Update checkers BB
   st->checkersBB = attacks_to(king_square(them), us);
 
   // Update checkers BB
   st->checkersBB = attacks_to(king_square(them), us);
-
-  // Update hidden checks
-  find_hidden_checks();
 }
 
 
 }
 
 
@@ -1597,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);
 
   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);
   // Initialize pieces
   Piece piece = piece_on(from);
   Piece capture = piece_on(to);
@@ -1634,17 +1559,6 @@ int Position::see(Square from, Square to) const {
                  | (pawn_attacks(WHITE, to)    & pawns(BLACK))
                  | (pawn_attacks(BLACK, to)    & pawns(WHITE));
 
                  | (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;
 
       if (from != SQ_NONE)
           break;
 
@@ -1707,12 +1621,6 @@ int Position::see(Square from, Square to) const {
       lastCapturingPieceValue = seeValues[pt];
       c = opposite_color(c);
 
       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)))
       {
       // Stop after a king capture
       if (pt == KING && (attackers & pieces_of_color(c)))
       {
index 4f18e67feeb37381c97534ec8abc0d7719167ebd..bd59b5c959d624c90c66a63f943a04f33d19fd0b 100644 (file)
@@ -79,7 +79,7 @@ enum CastleRights {
 /// must be passed as a parameter.
 
 struct StateInfo {
 /// must be passed as a parameter.
 
 struct StateInfo {
-  Bitboard pinners[2], pinned[2], dcCandidates[2], checkersBB;
+  Bitboard checkersBB;
   Key key, pawnKey, materialKey;
   int castleRights, rule50;
   Square epSquare;
   Key key, pawnKey, materialKey;
   int castleRights, rule50;
   Square epSquare;
@@ -219,7 +219,9 @@ public:
 
   // Properties of moves
   bool pl_move_is_legal(Move m) const;
 
   // Properties of moves
   bool pl_move_is_legal(Move m) const;
+  bool pl_move_is_legal(Move m, Bitboard pinned) const;
   bool move_is_check(Move m) const;
   bool move_is_check(Move m) const;
+  bool move_is_check(Move m, Bitboard dcCandidates) const;
   bool move_is_capture(Move m) const;
   bool move_is_deep_pawn_push(Move m) const;
   bool move_is_pawn_push_to_7th(Move m) const;
   bool move_is_capture(Move m) const;
   bool move_is_deep_pawn_push(Move m) const;
   bool move_is_pawn_push_to_7th(Move m) const;
@@ -242,6 +244,7 @@ public:
   // Doing and undoing moves
   void setStartState(const StateInfo& st);
   void do_move(Move m, StateInfo& st);
   // Doing and undoing moves
   void setStartState(const StateInfo& st);
   void do_move(Move m, StateInfo& st);
+  void do_move(Move m, StateInfo& st, Bitboard dcCandidates);
   void undo_move(Move m);
   void do_null_move(StateInfo& st);
   void undo_null_move();
   void undo_move(Move m);
   void do_null_move(StateInfo& st);
   void undo_null_move();
@@ -289,11 +292,6 @@ public:
 
 private:
 
 
 private:
 
-  enum {
-      Pinned       = 1,
-      DcCandidates = 2
-  };
-
   // Initialization helper functions (used while setting up a position)
   void clear();
   void put_piece(Piece p, Square s);
   // Initialization helper functions (used while setting up a position)
   void clear();
   void put_piece(Piece p, Square s);
@@ -309,9 +307,6 @@ private:
   void undo_promotion_move(Move m);
   void undo_ep_move(Move m);
   void find_checkers();
   void undo_promotion_move(Move m);
   void undo_ep_move(Move m);
   void find_checkers();
-  void find_hidden_checks(Color us, unsigned int types);
-  void find_hidden_checks();
-  void update_hidden_checks(Square from, Square to);
 
   template<PieceType Piece>
   void update_checkers(Bitboard* pCheckersBB, Square ksq, Square from, Square to, Bitboard dcCandidates);
 
   template<PieceType Piece>
   void update_checkers(Bitboard* pCheckersBB, Square ksq, Square from, Square to, Bitboard dcCandidates);
@@ -566,19 +561,6 @@ inline Bitboard Position::piece_attacks<KING>(Square s) const {
   return StepAttackBB[KING][s];
 }
 
   return StepAttackBB[KING][s];
 }
 
-inline Bitboard Position::pinned_pieces(Color c) const {
-  return st->pinned[c];
-}
-
-inline Bitboard Position::pinned_pieces(Color c, Bitboard& p) const {
-  p = st->pinners[c];
-  return st->pinned[c];
-}
-
-inline Bitboard Position::discovered_check_candidates(Color c) const {
-  return st->dcCandidates[c];
-}
-
 inline Bitboard Position::checkers() const {
   return st->checkersBB;
 }
 inline Bitboard Position::checkers() const {
   return st->checkersBB;
 }
index 2b41ec448da40db166b8a107e7a529ddc0a491e1..ba80ccdfde93ba1ab4ec97ed68d74e69fe929613 100644 (file)
@@ -290,8 +290,8 @@ namespace {
   bool thread_is_available(int slave, int master);
   bool idle_thread_exists(int master);
   bool split(const Position &pos, SearchStack *ss, int ply,
   bool thread_is_available(int slave, int master);
   bool idle_thread_exists(int master);
   bool split(const Position &pos, SearchStack *ss, int ply,
-             Value *alpha, Value *beta, Value *bestValue, Depth depth,
-             int *moves, MovePicker *mp, int master, bool pvNode);
+             Value *alpha, Value *beta, Value *bestValue, Depth depth, int *moves,
+             MovePicker *mp, Bitboard dcCandidates, int master, bool pvNode);
   void wake_sleeping_threads();
 
 #if !defined(_MSC_VER)
   void wake_sleeping_threads();
 
 #if !defined(_MSC_VER)
@@ -775,6 +775,7 @@ namespace {
 
     Value alpha = -VALUE_INFINITE;
     Value beta = VALUE_INFINITE, value;
 
     Value alpha = -VALUE_INFINITE;
     Value beta = VALUE_INFINITE, value;
+    Bitboard dcCandidates = pos.discovered_check_candidates(pos.side_to_move());
 
     // Loop through all the moves in the root move list
     for (int i = 0; i <  rml.move_count() && !AbortSearch; i++)
 
     // Loop through all the moves in the root move list
     for (int i = 0; i <  rml.move_count() && !AbortSearch; i++)
@@ -807,7 +808,7 @@ namespace {
         newDepth = (Iteration - 2) * OnePly + ext + InitialDepth;
 
         // Make the move, and search it
         newDepth = (Iteration - 2) * OnePly + ext + InitialDepth;
 
         // Make the move, and search it
-        pos.do_move(move, st);
+        pos.do_move(move, st, dcCandidates);
 
         if (i < MultiPV)
         {
 
         if (i < MultiPV)
         {
@@ -981,6 +982,7 @@ namespace {
     Move move, movesSearched[256];
     int moveCount = 0;
     Value value, bestValue = -VALUE_INFINITE;
     Move move, movesSearched[256];
     int moveCount = 0;
     Value value, bestValue = -VALUE_INFINITE;
+    Bitboard dcCandidates = mp.discovered_check_candidates();
     Color us = pos.side_to_move();
     bool isCheck = pos.is_check();
     bool mateThreat = pos.has_mate_threat(opposite_color(us));
     Color us = pos.side_to_move();
     bool isCheck = pos.is_check();
     bool mateThreat = pos.has_mate_threat(opposite_color(us));
@@ -994,7 +996,7 @@ namespace {
       assert(move_is_ok(move));
 
       bool singleReply = (isCheck && mp.number_of_moves() == 1);
       assert(move_is_ok(move));
 
       bool singleReply = (isCheck && mp.number_of_moves() == 1);
-      bool moveIsCheck = pos.move_is_check(move);
+      bool moveIsCheck = pos.move_is_check(move, dcCandidates);
       bool moveIsCapture = pos.move_is_capture(move);
 
       movesSearched[moveCount++] = ss[ply].currentMove = move;
       bool moveIsCapture = pos.move_is_capture(move);
 
       movesSearched[moveCount++] = ss[ply].currentMove = move;
@@ -1012,7 +1014,7 @@ namespace {
 
       // Make and search the move
       StateInfo st;
 
       // Make and search the move
       StateInfo st;
-      pos.do_move(move, st);
+      pos.do_move(move, st, dcCandidates);
 
       if (moveCount == 1) // The first move in list is the PV
           value = -search_pv(pos, ss, -beta, -alpha, newDepth, ply+1, threadID);
 
       if (moveCount == 1) // The first move in list is the PV
           value = -search_pv(pos, ss, -beta, -alpha, newDepth, ply+1, threadID);
@@ -1087,7 +1089,7 @@ namespace {
           && !AbortSearch
           && !thread_should_stop(threadID)
           && split(pos, ss, ply, &alpha, &beta, &bestValue, depth,
           && !AbortSearch
           && !thread_should_stop(threadID)
           && split(pos, ss, ply, &alpha, &beta, &bestValue, depth,
-                   &moveCount, &mp, threadID, true))
+                   &moveCount, &mp, dcCandidates, threadID, true))
           break;
     }
 
           break;
     }
 
@@ -1281,6 +1283,7 @@ namespace {
     Move move, movesSearched[256];
     int moveCount = 0;
     Value value, bestValue = -VALUE_INFINITE;
     Move move, movesSearched[256];
     int moveCount = 0;
     Value value, bestValue = -VALUE_INFINITE;
+    Bitboard dcCandidates = mp.discovered_check_candidates();
     Value futilityValue = VALUE_NONE;
     bool useFutilityPruning =   UseFutilityPruning
                              && depth < SelectiveDepth
     Value futilityValue = VALUE_NONE;
     bool useFutilityPruning =   UseFutilityPruning
                              && depth < SelectiveDepth
@@ -1295,7 +1298,7 @@ namespace {
       assert(move_is_ok(move));
 
       bool singleReply = (isCheck && mp.number_of_moves() == 1);
       assert(move_is_ok(move));
 
       bool singleReply = (isCheck && mp.number_of_moves() == 1);
-      bool moveIsCheck = pos.move_is_check(move);
+      bool moveIsCheck = pos.move_is_check(move, dcCandidates);
       bool moveIsCapture = pos.move_is_capture(move);
 
       movesSearched[moveCount++] = ss[ply].currentMove = move;
       bool moveIsCapture = pos.move_is_capture(move);
 
       movesSearched[moveCount++] = ss[ply].currentMove = move;
@@ -1335,7 +1338,7 @@ namespace {
 
       // Make and search the move
       StateInfo st;
 
       // Make and search the move
       StateInfo st;
-      pos.do_move(move, st);
+      pos.do_move(move, st, dcCandidates);
 
       // Try to reduce non-pv search depth by one ply if move seems not problematic,
       // if the move fails high will be re-searched at full depth.
 
       // Try to reduce non-pv search depth by one ply if move seems not problematic,
       // if the move fails high will be re-searched at full depth.
@@ -1382,7 +1385,7 @@ namespace {
           && !AbortSearch
           && !thread_should_stop(threadID)
           && split(pos, ss, ply, &beta, &beta, &bestValue, depth, &moveCount,
           && !AbortSearch
           && !thread_should_stop(threadID)
           && split(pos, ss, ply, &beta, &beta, &bestValue, depth, &moveCount,
-                   &mp, threadID, false))
+                   &mp, dcCandidates, threadID, false))
         break;
     }
 
         break;
     }
 
@@ -1467,6 +1470,7 @@ namespace {
     MovePicker mp = MovePicker(pos, pvNode, MOVE_NONE, EmptySearchStack, depth, isCheck ? NULL : &ei);
     Move move;
     int moveCount = 0;
     MovePicker mp = MovePicker(pos, pvNode, MOVE_NONE, EmptySearchStack, depth, isCheck ? NULL : &ei);
     Move move;
     int moveCount = 0;
+    Bitboard dcCandidates = mp.discovered_check_candidates();
     Color us = pos.side_to_move();
     bool enoughMaterial = pos.non_pawn_material(us) > RookValueMidgame;
 
     Color us = pos.side_to_move();
     bool enoughMaterial = pos.non_pawn_material(us) > RookValueMidgame;
 
@@ -1486,7 +1490,7 @@ namespace {
           && !isCheck
           && !pvNode
           && !move_promotion(move)
           && !isCheck
           && !pvNode
           && !move_promotion(move)
-          && !pos.move_is_check(move)
+          && !pos.move_is_check(move, dcCandidates)
           && !pos.move_is_passed_pawn_push(move))
       {
           Value futilityValue = staticValue
           && !pos.move_is_passed_pawn_push(move))
       {
           Value futilityValue = staticValue
@@ -1514,7 +1518,7 @@ namespace {
 
       // Make and search the move.
       StateInfo st;
 
       // Make and search the move.
       StateInfo st;
-      pos.do_move(move, st);
+      pos.do_move(move, st, dcCandidates);
       Value value = -qsearch(pos, ss, -beta, -alpha, depth-OnePly, ply+1, threadID);
       pos.undo_move(move);
 
       Value value = -qsearch(pos, ss, -beta, -alpha, depth-OnePly, ply+1, threadID);
       pos.undo_move(move);
 
@@ -1581,7 +1585,7 @@ namespace {
     {
       assert(move_is_ok(move));
 
     {
       assert(move_is_ok(move));
 
-      bool moveIsCheck = pos.move_is_check(move);
+      bool moveIsCheck = pos.move_is_check(move, sp->dcCandidates);
       bool moveIsCapture = pos.move_is_capture(move);
 
       lock_grab(&(sp->lock));
       bool moveIsCapture = pos.move_is_capture(move);
 
       lock_grab(&(sp->lock));
@@ -1606,7 +1610,7 @@ namespace {
 
       // Make and search the move.
       StateInfo st;
 
       // Make and search the move.
       StateInfo st;
-      pos.do_move(move, st);
+      pos.do_move(move, st, sp->dcCandidates);
 
       // Try to reduce non-pv search depth by one ply if move seems not problematic,
       // if the move fails high will be re-searched at full depth.
 
       // Try to reduce non-pv search depth by one ply if move seems not problematic,
       // if the move fails high will be re-searched at full depth.
@@ -1691,7 +1695,7 @@ namespace {
            && !thread_should_stop(threadID)
            && (move = sp->mp->get_next_move(sp->lock)) != MOVE_NONE)
     {
            && !thread_should_stop(threadID)
            && (move = sp->mp->get_next_move(sp->lock)) != MOVE_NONE)
     {
-      bool moveIsCheck = pos.move_is_check(move);
+      bool moveIsCheck = pos.move_is_check(move, sp->dcCandidates);
       bool moveIsCapture = pos.move_is_capture(move);
 
       assert(move_is_ok(move));
       bool moveIsCapture = pos.move_is_capture(move);
 
       assert(move_is_ok(move));
@@ -1715,7 +1719,7 @@ namespace {
 
       // Make and search the move.
       StateInfo st;
 
       // Make and search the move.
       StateInfo st;
-      pos.do_move(move, st);
+      pos.do_move(move, st, sp->dcCandidates);
 
       // Try to reduce non-pv search depth by one ply if move seems not problematic,
       // if the move fails high will be re-searched at full depth.
 
       // Try to reduce non-pv search depth by one ply if move seems not problematic,
       // if the move fails high will be re-searched at full depth.
@@ -2671,8 +2675,9 @@ namespace {
   // splitPoint->cpus becomes 0), split() returns true.
 
   bool split(const Position &p, SearchStack *sstck, int ply,
   // splitPoint->cpus becomes 0), split() returns true.
 
   bool split(const Position &p, SearchStack *sstck, int ply,
-             Value *alpha, Value *beta, Value *bestValue,
-             Depth depth, int *moves, MovePicker *mp, int master, bool pvNode) {
+             Value *alpha, Value *beta, Value *bestValue, Depth depth, int *moves,
+             MovePicker *mp, Bitboard dcCandidates, int master, bool pvNode) {
+
     assert(p.is_ok());
     assert(sstck != NULL);
     assert(ply >= 0 && ply < PLY_MAX);
     assert(p.is_ok());
     assert(sstck != NULL);
     assert(ply >= 0 && ply < PLY_MAX);
@@ -2708,6 +2713,7 @@ namespace {
     splitPoint->alpha = pvNode? *alpha : (*beta - 1);
     splitPoint->beta = *beta;
     splitPoint->pvNode = pvNode;
     splitPoint->alpha = pvNode? *alpha : (*beta - 1);
     splitPoint->beta = *beta;
     splitPoint->pvNode = pvNode;
+    splitPoint->dcCandidates = dcCandidates;
     splitPoint->bestValue = *bestValue;
     splitPoint->master = master;
     splitPoint->mp = mp;
     splitPoint->bestValue = *bestValue;
     splitPoint->master = master;
     splitPoint->mp = mp;