]> git.sesse.net Git - stockfish/blobdiff - src/position.cpp
Pinned aware SEE
[stockfish] / src / position.cpp
index eeedbbb22d1fd8d332ed25deb83acdeb07dda9d3..e51c1ba70296a7149460da078c1032b1582a3b88 100644 (file)
@@ -109,10 +109,9 @@ void Position::init() {
 
   PRNG rng(1070372);
 
-  for (Color c = WHITE; c <= BLACK; ++c)
-      for (PieceType pt = PAWN; pt <= KING; ++pt)
-          for (Square s = SQ_A1; s <= SQ_H8; ++s)
-              Zobrist::psq[make_piece(c, pt)][s] = rng.rand<Key>();
+  for (Piece pc : Pieces)
+      for (Square s = SQ_A1; s <= SQ_H8; ++s)
+          Zobrist::psq[pc][s] = rng.rand<Key>();
 
   for (File f = FILE_A; f <= FILE_H; ++f)
       Zobrist::enpassant[f] = rng.rand<Key>();
@@ -292,8 +291,8 @@ void Position::set_castling_right(Color c, Square rfrom) {
 
 void Position::set_check_info(StateInfo* si) const {
 
-  si->blockersForKing[WHITE] = slider_blockers(pieces(BLACK), square<KING>(WHITE));
-  si->blockersForKing[BLACK] = slider_blockers(pieces(WHITE), square<KING>(BLACK));
+  si->blockersForKing[WHITE] = slider_blockers(pieces(BLACK), square<KING>(WHITE), si->pinnersForKing[WHITE]);
+  si->blockersForKing[BLACK] = slider_blockers(pieces(WHITE), square<KING>(BLACK), si->pinnersForKing[BLACK]);
 
   Square ksq = square<KING>(~sideToMove);
 
@@ -342,14 +341,14 @@ void Position::set_state(StateInfo* si) const {
       si->pawnKey ^= Zobrist::psq[piece_on(s)][s];
   }
 
-  for (Color c = WHITE; c <= BLACK; ++c)
-      for (PieceType pt = PAWN; pt <= KING; ++pt)
-          for (int cnt = 0; cnt < pieceCount[make_piece(c, pt)]; ++cnt)
-              si->materialKey ^= Zobrist::psq[make_piece(c, pt)][cnt];
+  for (Piece pc : Pieces)
+  {
+      if (type_of(pc) != PAWN && type_of(pc) != KING)
+          si->nonPawnMaterial[color_of(pc)] += pieceCount[pc] * PieceValue[MG][pc];
 
-  for (Color c = WHITE; c <= BLACK; ++c)
-      for (PieceType pt = KNIGHT; pt <= QUEEN; ++pt)
-          si->nonPawnMaterial[c] += pieceCount[make_piece(c, pt)] * PieceValue[MG][pt];
+      for (int cnt = 0; cnt < pieceCount[pc]; ++cnt)
+          si->materialKey ^= Zobrist::psq[pc][cnt];
+  }
 }
 
 
@@ -416,24 +415,25 @@ Phase Position::game_phase() const {
 }
 
 
-/// Position::slider_blockers() returns a bitboard of all the pieces (both colors) that
-/// are blocking attacks on the square 's' from 'sliders'. A piece blocks a slider
-/// if removing that piece from the board would result in a position where square 's'
-/// is attacked. For example, a king-attack blocking piece can be either a pinned or
-/// a discovered check piece, according if its color is the opposite or the same of
-/// the color of the slider.
+/// Position::slider_blockers() returns a bitboard of all the pieces (both colors)
+/// that are blocking attacks on the square 's' from 'sliders'. A piece blocks a
+/// slider if removing that piece from the board would result in a position where
+/// square 's' is attacked. For example, a king-attack blocking piece can be either
+/// a pinned or a discovered check piece, according if its color is the opposite
+/// or the same of the color of the slider. The pinners bitboard get filled with
+/// real and potential pinners.
 
-Bitboard Position::slider_blockers(Bitboard sliders, Square s) const {
+Bitboard Position::slider_blockers(Bitboard sliders, Square s, Bitboard& pinners) const {
 
-  Bitboard b, pinners, result = 0;
+  Bitboard b, p, result = 0;
 
   // Pinners are sliders that attack 's' when a pinned piece is removed
-  pinners = (  (PseudoAttacks[ROOK  ][s] & pieces(QUEEN, ROOK))
-             | (PseudoAttacks[BISHOP][s] & pieces(QUEEN, BISHOP))) & sliders;
+  pinners = p = (  (PseudoAttacks[ROOK  ][s] & pieces(QUEEN, ROOK))
+                 | (PseudoAttacks[BISHOP][s] & pieces(QUEEN, BISHOP))) & sliders;
 
-  while (pinners)
+  while (p)
   {
-      b = between_bb(s, pop_lsb(&pinners)) & pieces();
+      b = between_bb(s, pop_lsb(&p)) & pieces();
 
       if (!more_than_one(b))
           result |= b;
@@ -1000,6 +1000,18 @@ Value Position::see(Move m) const {
   if (!stmAttackers)
       return swapList[0];
 
+  // Don't allow pinned pieces to attack as long all pinners (this includes also
+  // potential ones) are on their original square. When a pinner moves to the
+  // exchange-square or get captured on it, we fall back to standard SEE behaviour.
+  else if (   (stmAttackers & st->blockersForKing[stm])
+           && ((st->pinnersForKing[stm] & (occupied ^ (occupied & to))) == st->pinnersForKing[stm]))
+  {
+      // Pinned pieces can't attack so remove them from attackers
+      stmAttackers ^= (stmAttackers & st->blockersForKing[stm]);
+      if (!stmAttackers)
+          return swapList[0];
+  }
+
   // The destination square is defended, which makes things rather more
   // difficult to compute. We proceed by building up a "swap list" containing
   // the material gain or loss at each stop in a sequence of captures to the
@@ -1018,6 +1030,11 @@ Value Position::see(Move m) const {
       captured = min_attacker<PAWN>(byTypeBB, to, stmAttackers, occupied, attackers);
       stm = ~stm;
       stmAttackers = attackers & pieces(stm);
+      if (    stmAttackers
+          && (stmAttackers & st->blockersForKing[stm])
+          && ((st->pinnersForKing[stm] & (occupied ^ (occupied & to))) == st->pinnersForKing[stm]))
+          stmAttackers ^= (stmAttackers & st->blockersForKing[stm]);
+
       ++slIndex;
 
   } while (stmAttackers && (captured != KING || (--slIndex, false))); // Stop before a king capture
@@ -1136,18 +1153,15 @@ bool Position::pos_is_ok(int* failedStep) const {
       }
 
       if (step == Lists)
-          for (Color c = WHITE; c <= BLACK; ++c)
-              for (PieceType pt = PAWN; pt <= KING; ++pt)
-              {
-                  Piece pc = make_piece(c, pt);
+          for (Piece pc : Pieces)
+          {
+              if (pieceCount[pc] != popcount(pieces(color_of(pc), type_of(pc))))
+                  return false;
 
-                  if (pieceCount[pc] != popcount(pieces(c, pt)))
+              for (int i = 0; i < pieceCount[pc]; ++i)
+                  if (board[pieceList[pc][i]] != pc || index[pieceList[pc][i]] != i)
                       return false;
-
-                  for (int i = 0; i < pieceCount[pc]; ++i)
-                      if (board[pieceList[pc][i]] != pc || index[pieceList[pc][i]] != i)
-                          return false;
-              }
+          }
 
       if (step == Castling)
           for (Color c = WHITE; c <= BLACK; ++c)