]> git.sesse.net Git - stockfish/blobdiff - src/position.cpp
Order check moves used in qsearch
[stockfish] / src / position.cpp
index 366d61f309ed9706b0bec3d3af5797b9b8fdf48f..fb17f209e3e4d24adeb9a45542f77f0b4fa8a3ba 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];
 
@@ -203,11 +204,16 @@ void Position::from_fen(const string& fen) {
   while (fen[i] == ' ')
       i++;
 
-  // En passant square
+  // En passant square -- ignore if no capture is possible
   if (    i <= fen.length() - 2
       && (fen[i] >= 'a' && fen[i] <= 'h')
       && (fen[i+1] == '3' || fen[i+1] == '6'))
-      st->epSquare = square_from_string(fen.substr(i, 2));
+  {
+      Square fenEpSquare = square_from_string(fen.substr(i, 2));
+      Color them = opposite_color(sideToMove);
+      if (attacks_from<PAWN>(fenEpSquare, them) & this->pieces(PAWN, sideToMove))
+          st->epSquare = square_from_string(fen.substr(i, 2));
+  }
 
   // Various initialisation
   for (Square sq = SQ_A1; sq <= SQ_H8; sq++)
@@ -338,21 +344,20 @@ void Position::copy(const Position& pos) {
 /// king) pieces for the given color and for the given pinner type. Or, when
 /// template parameter FindPinned is false, the pieces of the given color
 /// candidate for a discovery check against the enemy king.
-/// Note that checkersBB bitboard must be already updated.
+/// Bitboard checkersBB must be already updated when looking for pinners.
 
 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;
@@ -373,7 +378,8 @@ Bitboard Position::hidden_checkers(Color c) const {
 
 
 /// Position:pinned_pieces() returns a bitboard of all pinned (against the
-/// king) pieces for the given color.
+/// king) pieces for the given color. Note that checkersBB bitboard must
+/// be already updated.
 
 Bitboard Position::pinned_pieces(Color c) const {
 
@@ -383,7 +389,8 @@ Bitboard Position::pinned_pieces(Color c) const {
 
 /// Position:discovered_check_candidates() returns a bitboard containing all
 /// pieces for the given side which are candidates for giving a discovered
-/// check.
+/// check. Contrary to pinned_pieces() here there is no need of checkersBB
+/// to be already updated.
 
 Bitboard Position::discovered_check_candidates(Color c) const {
 
@@ -647,49 +654,17 @@ bool Position::move_is_check(Move m, const CheckInfo& ci) const {
 }
 
 
-/// 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;
-
-  assert(*pCheckersBB == EmptyBoardBB);
-
-  // Direct checks
-  if (  (   !Slider // try to early skip slide piece attacks
-         || (Bishop && bit_is_set(BishopPseudoAttacks[ksq], to))
-         || (Rook   && bit_is_set(RookPseudoAttacks[ksq], to)))
-      && bit_is_set(Piece == PAWN ? attacks_from<PAWN>(ksq, opposite_color(sideToMove)) : attacks_from<Piece>(ksq) , to))
-  {
-      *pCheckersBB = SetMaskBB[to];
-  }
-  // Discovery checks
-  if (Piece != QUEEN && dcCandidates && bit_is_set(dcCandidates, from))
-  {
-      if (Piece != ROOK)
-          (*pCheckersBB) |= (attacks_from<ROOK>(ksq) & pieces(ROOK, QUEEN, side_to_move()));
-
-      if (Piece != BISHOP)
-          (*pCheckersBB) |= (attacks_from<BISHOP>(ksq) & pieces(BISHOP, QUEEN, side_to_move()));
-  }
-}
-
-
 /// 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()));
+  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));
@@ -703,7 +678,7 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) {
     Key pawnKey, materialKey;
     int castleRights, rule50, pliesFromNull;
     Square epSquare;
-    Value value;
+    Score value;
     Value npMaterial[2];
   };
 
@@ -858,21 +833,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));
+          }
       }
   }
 
@@ -995,7 +976,7 @@ void Position::do_castle_move(Move m) {
   set_bit(&(byColorBB[us]), rto);
   set_bit(&(byTypeBB[ROOK]), rto);
   set_bit(&(byTypeBB[0]), rto); // HACK: byTypeBB[0] == occupied squares
-  
+
   // Update board array
   Piece king = piece_of_color_and_type(us, KING);
   Piece rook = piece_of_color_and_type(us, ROOK);
@@ -1180,7 +1161,7 @@ void Position::undo_castle_move(Move m) {
 
   assert(piece_on(kto) == piece_of_color_and_type(us, KING));
   assert(piece_on(rto) == piece_of_color_and_type(us, ROOK));
-  
+
   // Remove pieces from destination squares:
   clear_bit(&(byColorBB[us]), kto);
   clear_bit(&(byTypeBB[KING]), kto);
@@ -1188,7 +1169,7 @@ void Position::undo_castle_move(Move m) {
   clear_bit(&(byColorBB[us]), rto);
   clear_bit(&(byTypeBB[ROOK]), rto);
   clear_bit(&(byTypeBB[0]), rto); // HACK: byTypeBB[0] == occupied squares
+
   // Put pieces on source squares:
   set_bit(&(byColorBB[us]), kfrom);
   set_bit(&(byTypeBB[KING]), kfrom);
@@ -1763,6 +1744,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();
 }