]> git.sesse.net Git - stockfish/blobdiff - src/position.cpp
Adjust SingleReplyMargin 0x64 -> 0x20
[stockfish] / src / position.cpp
index 8ab712b46d1f81a0fe6cd25865f39a1ea57e3c93..7de4ae826c246c0705019f2ccab936ff1afd33d6 100644 (file)
@@ -51,6 +51,7 @@ Key Position::zobEp[64];
 Key Position::zobCastle[16];
 Key Position::zobMaterial[2][8][16];
 Key Position::zobSideToMove;
+Key Position::zobExclusion;
 
 Score Position::PieceSquareTable[16][64];
 
@@ -65,7 +66,7 @@ CheckInfo::CheckInfo(const Position& pos) {
   Color them = opposite_color(us);
 
   ksq = pos.king_square(them);
-  dc = pos.discovered_check_candidates(us);
+  dcCandidates = pos.discovered_check_candidates(us);
 
   checkSq[PAWN] = pos.attacks_from<PAWN>(ksq, them);
   checkSq[KNIGHT] = pos.attacks_from<KNIGHT>(ksq);
@@ -343,16 +344,15 @@ void Position::copy(const Position& pos) {
 template<bool FindPinned>
 Bitboard Position::hidden_checkers(Color c) const {
 
-  Bitboard pinners, result = EmptyBoardBB;
+  Bitboard result = EmptyBoardBB;
+  Bitboard pinners = pieces_of_color(FindPinned ? opposite_color(c) : c);
 
   // Pinned pieces protect our king, dicovery checks attack
   // the enemy king.
   Square ksq = king_square(FindPinned ? c : opposite_color(c));
 
-  // Pinners are sliders, not checkers, that give check when
-  // candidate pinned is removed.
-  pinners =  (pieces(ROOK, QUEEN, FindPinned ? opposite_color(c) : c) & RookPseudoAttacks[ksq])
-           | (pieces(BISHOP, QUEEN, FindPinned ? opposite_color(c) : c) & BishopPseudoAttacks[ksq]);
+  // Pinners are sliders, not checkers, that give check when candidate pinned is removed
+  pinners &= (pieces(ROOK, QUEEN) & RookPseudoAttacks[ksq]) | (pieces(BISHOP, QUEEN) & BishopPseudoAttacks[ksq]);
 
   if (FindPinned && pinners)
       pinners &= ~st->checkersBB;
@@ -552,162 +552,98 @@ bool Position::pl_move_is_evasion(Move m, Bitboard pinned) const
 
 bool Position::move_is_check(Move m) const {
 
-  Bitboard dc = discovered_check_candidates(side_to_move());
-  return move_is_check(m, dc);
+  return move_is_check(m, CheckInfo(*this));
 }
 
-bool Position::move_is_check(Move m, Bitboard dcCandidates) const {
+bool Position::move_is_check(Move m, const CheckInfo& ci) const {
 
   assert(is_ok());
   assert(move_is_ok(m));
-  assert(dcCandidates == discovered_check_candidates(side_to_move()));
+  assert(ci.dcCandidates == discovered_check_candidates(side_to_move()));
+  assert(color_of_piece_on(move_from(m)) == side_to_move());
+  assert(piece_on(ci.ksq) == piece_of_color_and_type(opposite_color(side_to_move()), KING));
 
-  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);
+  PieceType pt = type_of_piece_on(from);
 
-  assert(color_of_piece_on(from) == us);
-  assert(piece_on(ksq) == piece_of_color_and_type(them, KING));
+  // Direct check ?
+  if (bit_is_set(ci.checkSq[pt], to))
+      return true;
 
-  // Proceed according to the type of the moving piece
-  switch (type_of_piece_on(from))
+  // Discovery check ?
+  if (ci.dcCandidates && bit_is_set(ci.dcCandidates, from))
   {
-  case PAWN:
-
-      if (bit_is_set(attacks_from<PAWN>(ksq, them), to)) // Normal check?
-          return true;
-
-      if (   dcCandidates // Discovered check?
-          && bit_is_set(dcCandidates, from)
-          && (direction_between_squares(from, ksq) != direction_between_squares(to, ksq)))
+      // For pawn and king moves we need to verify also direction
+      if (  (pt != PAWN && pt != KING)
+          ||(direction_between_squares(from, ci.ksq) != direction_between_squares(to, ci.ksq)))
           return true;
+  }
 
-      if (move_is_promotion(m)) // Promotion with check?
-      {
-          Bitboard b = occupied_squares();
-          clear_bit(&b, from);
-
-          switch (move_promotion_piece(m))
-          {
-          case KNIGHT:
-              return bit_is_set(attacks_from<KNIGHT>(to), ksq);
-          case BISHOP:
-              return bit_is_set(bishop_attacks_bb(to, b), ksq);
-          case ROOK:
-              return bit_is_set(rook_attacks_bb(to, b), ksq);
-          case QUEEN:
-              return bit_is_set(queen_attacks_bb(to, b), ksq);
-          default:
-              assert(false);
-          }
-      }
-      // En passant capture with check?  We have already handled the case
-      // of direct checks and ordinary discovered check, the only case we
-      // need to handle is the unusual case of a discovered check through the
-      // captured pawn.
-      else if (move_is_ep(m))
-      {
-          Square capsq = make_square(square_file(to), square_rank(from));
-          Bitboard b = occupied_squares();
-          clear_bit(&b, from);
-          clear_bit(&b, capsq);
-          set_bit(&b, to);
-          return  (rook_attacks_bb(ksq, b) & pieces(ROOK, QUEEN, us))
-                ||(bishop_attacks_bb(ksq, b) & pieces(BISHOP, QUEEN, us));
-      }
+  // Can we skip the ugly special cases ?
+  if (!move_is_special(m))
       return false;
 
-  // Test discovered check and normal check according to piece type
-  case KNIGHT:
-    return   (dcCandidates && bit_is_set(dcCandidates, from))
-          || bit_is_set(attacks_from<KNIGHT>(ksq), to);
-
-  case BISHOP:
-    return   (dcCandidates && bit_is_set(dcCandidates, from))
-          || (direction_is_diagonal(ksq, to) && bit_is_set(attacks_from<BISHOP>(ksq), to));
-
-  case ROOK:
-    return   (dcCandidates && bit_is_set(dcCandidates, from))
-          || (direction_is_straight(ksq, to) && bit_is_set(attacks_from<ROOK>(ksq), to));
-
-  case QUEEN:
-      // Discovered checks are impossible!
-      assert(!bit_is_set(dcCandidates, from));
-      return (   (direction_is_straight(ksq, to) && bit_is_set(attacks_from<ROOK>(ksq), to))
-              || (direction_is_diagonal(ksq, to) && bit_is_set(attacks_from<BISHOP>(ksq), to)));
-
-  case KING:
-      // Discovered check?
-      if (   bit_is_set(dcCandidates, from)
-          && (direction_between_squares(from, ksq) != direction_between_squares(to, ksq)))
-          return true;
+  Color us = side_to_move();
+  Bitboard b = occupied_squares();
 
-      // Castling with check?
-      if (move_is_castle(m))
-      {
-          Square kfrom, kto, rfrom, rto;
-          Bitboard b = occupied_squares();
-          kfrom = from;
-          rfrom = to;
+  // Promotion with check ?
+  if (move_is_promotion(m))
+  {
+      clear_bit(&b, from);
 
-          if (rfrom > kfrom)
-          {
-              kto = relative_square(us, SQ_G1);
-              rto = relative_square(us, SQ_F1);
-          } else {
-              kto = relative_square(us, SQ_C1);
-              rto = relative_square(us, SQ_D1);
-          }
-          clear_bit(&b, kfrom);
-          clear_bit(&b, rfrom);
-          set_bit(&b, rto);
-          set_bit(&b, kto);
-          return bit_is_set(rook_attacks_bb(rto, b), ksq);
+      switch (move_promotion_piece(m))
+      {
+      case KNIGHT:
+          return bit_is_set(attacks_from<KNIGHT>(to), ci.ksq);
+      case BISHOP:
+          return bit_is_set(bishop_attacks_bb(to, b), ci.ksq);
+      case ROOK:
+          return bit_is_set(rook_attacks_bb(to, b), ci.ksq);
+      case QUEEN:
+          return bit_is_set(queen_attacks_bb(to, b), ci.ksq);
+      default:
+          assert(false);
       }
-      return false;
-
-  default: // NO_PIECE_TYPE
-      break;
   }
-  assert(false);
-  return false;
-}
-
-
-/// Position::update_checkers() udpates chekers info given the move. It is called
-/// in do_move() and is faster then find_checkers().
-
-template<PieceType Piece>
-inline void Position::update_checkers(Bitboard* pCheckersBB, Square ksq, Square from,
-                                      Square to, Bitboard dcCandidates) {
 
-  const bool Bishop = (Piece == QUEEN || Piece == BISHOP);
-  const bool Rook   = (Piece == QUEEN || Piece == ROOK);
-  const bool Slider = Bishop || Rook;
-
-  // Direct checks
-  if (  (   (Bishop && bit_is_set(BishopPseudoAttacks[ksq], to))
-         || (Rook   && bit_is_set(RookPseudoAttacks[ksq], to)))
-      && bit_is_set(attacks_from<Piece>(ksq), to)) // slow, try to early skip
-      set_bit(pCheckersBB, to);
-
-  else if (   Piece != KING
-           && !Slider
-           && bit_is_set(Piece == PAWN ? attacks_from<PAWN>(ksq, opposite_color(sideToMove))
-                                       : attacks_from<Piece>(ksq), to))
-      set_bit(pCheckersBB, to);
+  // En passant capture with check?  We have already handled the case
+  // of direct checks and ordinary discovered check, the only case we
+  // need to handle is the unusual case of a discovered check through the
+  // captured pawn.
+  if (move_is_ep(m))
+  {
+      Square capsq = make_square(square_file(to), square_rank(from));
+      clear_bit(&b, from);
+      clear_bit(&b, capsq);
+      set_bit(&b, to);
+      return  (rook_attacks_bb(ci.ksq, b) & pieces(ROOK, QUEEN, us))
+            ||(bishop_attacks_bb(ci.ksq, b) & pieces(BISHOP, QUEEN, us));
+  }
 
-  // Discovery checks
-  if (Piece != QUEEN && bit_is_set(dcCandidates, from))
+  // Castling with check ?
+  if (move_is_castle(m))
   {
-      if (Piece != ROOK)
-          (*pCheckersBB) |= (attacks_from<ROOK>(ksq) & pieces(ROOK, QUEEN, side_to_move()));
+      Square kfrom, kto, rfrom, rto;
+      kfrom = from;
+      rfrom = to;
 
-      if (Piece != BISHOP)
-          (*pCheckersBB) |= (attacks_from<BISHOP>(ksq) & pieces(BISHOP, QUEEN, side_to_move()));
+      if (rfrom > kfrom)
+      {
+          kto = relative_square(us, SQ_G1);
+          rto = relative_square(us, SQ_F1);
+      } else {
+          kto = relative_square(us, SQ_C1);
+          rto = relative_square(us, SQ_D1);
+      }
+      clear_bit(&b, kfrom);
+      clear_bit(&b, rfrom);
+      set_bit(&b, rto);
+      set_bit(&b, kto);
+      return bit_is_set(rook_attacks_bb(rto, b), ci.ksq);
   }
+
+  return false;
 }
 
 
@@ -717,10 +653,11 @@ inline void Position::update_checkers(Bitboard* pCheckersBB, Square ksq, Square
 
 void Position::do_move(Move m, StateInfo& newSt) {
 
-  do_move(m, newSt, discovered_check_candidates(side_to_move()));
+  CheckInfo ci(*this);
+  do_move(m, newSt, ci, move_is_check(m, ci));
 }
 
-void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) {
+void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveIsCheck) {
 
   assert(is_ok());
   assert(move_is_ok(m));
@@ -889,21 +826,27 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) {
   st->key = key;
 
   // Update checkers bitboard, piece must be already moved
-  if (ep | pm)
-      st->checkersBB = attackers_to(king_square(them)) & pieces_of_color(us);
-  else
+  st->checkersBB = EmptyBoardBB;
+
+  if (moveIsCheck)
   {
-      st->checkersBB = EmptyBoardBB;
-      Square ksq = king_square(them);
-      switch (pt)
+      if (ep | pm)
+          st->checkersBB = attackers_to(king_square(them)) & pieces_of_color(us);
+      else
       {
-      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;
+          // Direct checks
+          if (bit_is_set(ci.checkSq[pt], to))
+              st->checkersBB = SetMaskBB[to];
+
+          // Discovery checks
+          if (ci.dcCandidates && bit_is_set(ci.dcCandidates, from))
+          {
+              if (pt != ROOK)
+                  st->checkersBB |= (attacks_from<ROOK>(ci.ksq) & pieces(ROOK, QUEEN, us));
+
+              if (pt != BISHOP)
+                  st->checkersBB |= (attacks_from<BISHOP>(ci.ksq) & pieces(BISHOP, QUEEN, us));
+          }
       }
   }
 
@@ -1794,6 +1737,8 @@ void Position::init_zobrist() {
 
   for (int i = 0; i < 16; i++)
       zobMaterial[0][KING][i] = zobMaterial[1][KING][i] = Key(0ULL);
+
+  zobExclusion = genrand_int64();
 }