]> git.sesse.net Git - stockfish/blobdiff - src/position.cpp
Don't reparent if a cutoff is pending
[stockfish] / src / position.cpp
index 8b043af83b4a0826c0d0fe52000bce970cce9c79..e5e0ab06d6eff97946b800ae8ff7bbf159cfa198 100644 (file)
@@ -62,15 +62,8 @@ const Value PieceValueEndgame[17] = {
   RookValueEndgame, QueenValueEndgame
 };
 
-
-namespace {
-
-  // Bonus for having the side to move (modified by Joona Kiiski)
-  const Score Tempo = make_score(48, 22);
-
-  // To convert a Piece to and from a FEN char
-  const string PieceToChar(" PNBRQK  pnbrqk  .");
-}
+// To convert a Piece to and from a FEN char
+static const string PieceToChar(" PNBRQK  pnbrqk  .");
 
 
 /// CheckInfo c'tor
@@ -830,7 +823,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
   prefetch((char*)TT.first_entry(k));
 
   // Move the piece
-  Bitboard from_to_bb = SquareBB[from] | SquareBB[to];
+  Bitboard from_to_bb = SquareBB[from] ^ SquareBB[to];
   byTypeBB[ALL_PIECES] ^= from_to_bb;
   byTypeBB[pt] ^= from_to_bb;
   byColorBB[us] ^= from_to_bb;
@@ -934,9 +927,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
       }
   }
 
-  // Finish
   sideToMove = ~sideToMove;
-  st->psqScore += (sideToMove == WHITE ?  Tempo : -Tempo);
 
   assert(pos_is_ok());
 }
@@ -995,7 +986,7 @@ void Position::undo_move(Move m) {
   }
 
   // Put the piece back at the source square
-  Bitboard from_to_bb = SquareBB[from] | SquareBB[to];
+  Bitboard from_to_bb = SquareBB[from] ^ SquareBB[to];
   byTypeBB[ALL_PIECES] ^= from_to_bb;
   byTypeBB[pt] ^= from_to_bb;
   byColorBB[us] ^= from_to_bb;
@@ -1078,21 +1069,13 @@ void Position::do_castle_move(Move m) {
   assert(piece_on(kfrom) == make_piece(us, KING));
   assert(piece_on(rfrom) == make_piece(us, ROOK));
 
-  // Remove pieces from source squares
-  byTypeBB[ALL_PIECES] ^= kfrom;
-  byTypeBB[KING] ^= kfrom;
-  byColorBB[us] ^= kfrom;
-  byTypeBB[ALL_PIECES] ^= rfrom;
-  byTypeBB[ROOK] ^= rfrom;
-  byColorBB[us] ^= rfrom;
-
-  // Put pieces on destination squares
-  byTypeBB[ALL_PIECES] |= kto;
-  byTypeBB[KING] |= kto;
-  byColorBB[us] |= kto;
-  byTypeBB[ALL_PIECES] |= rto;
-  byTypeBB[ROOK] |= rto;
-  byColorBB[us] |= rto;
+  // Move the pieces, with some care; in chess960 could be kto == rfrom
+  Bitboard k_from_to_bb = SquareBB[kfrom] ^ SquareBB[kto];
+  Bitboard r_from_to_bb = SquareBB[rfrom] ^ SquareBB[rto];
+  byTypeBB[KING] ^= k_from_to_bb;
+  byTypeBB[ROOK] ^= r_from_to_bb;
+  byTypeBB[ALL_PIECES] ^= k_from_to_bb ^ r_from_to_bb;
+  byColorBB[us] ^= k_from_to_bb ^ r_from_to_bb;
 
   // Update board
   Piece king = make_piece(us, KING);
@@ -1135,9 +1118,7 @@ void Position::do_castle_move(Move m) {
       // Update checkers BB
       st->checkersBB = attackers_to(king_square(~us)) & pieces(us);
 
-      // Finish
       sideToMove = ~sideToMove;
-      st->psqScore += (sideToMove == WHITE ?  Tempo : -Tempo);
   }
   else
       // Undo: point our state pointer back to the previous state
@@ -1180,7 +1161,6 @@ void Position::do_null_move(StateInfo& backupSt) {
       st->epSquare = SQ_NONE;
       st->rule50++;
       st->pliesFromNull = 0;
-      st->psqScore += (sideToMove == WHITE ?  Tempo : -Tempo);
   }
 
   assert(pos_is_ok());
@@ -1352,19 +1332,21 @@ void Position::put_piece(Piece p, Square s) {
 
 Key Position::compute_key() const {
 
-  Key result = zobCastle[st->castleRights];
+  Key k = zobCastle[st->castleRights];
 
-  for (Square s = SQ_A1; s <= SQ_H8; s++)
-      if (!square_empty(s))
-          result ^= zobrist[color_of(piece_on(s))][type_of(piece_on(s))][s];
+  for (Bitboard b = pieces(); b; )
+  {
+      Square s = pop_1st_bit(&b);
+      k ^= zobrist[color_of(piece_on(s))][type_of(piece_on(s))][s];
+  }
 
   if (ep_square() != SQ_NONE)
-      result ^= zobEp[file_of(ep_square())];
+      k ^= zobEp[file_of(ep_square())];
 
   if (sideToMove == BLACK)
-      result ^= zobSideToMove;
+      k ^= zobSideToMove;
 
-  return result;
+  return k;
 }
 
 
@@ -1376,16 +1358,15 @@ Key Position::compute_key() const {
 
 Key Position::compute_pawn_key() const {
 
-  Bitboard b;
-  Key result = 0;
+  Key k = 0;
 
-  for (Color c = WHITE; c <= BLACK; c++)
+  for (Bitboard b = pieces(PAWN); b; )
   {
-      b = pieces(PAWN, c);
-      while (b)
-          result ^= zobrist[c][PAWN][pop_1st_bit(&b)];
+      Square s = pop_1st_bit(&b);
+      k ^= zobrist[color_of(piece_on(s))][PAWN][s];
   }
-  return result;
+
+  return k;
 }
 
 
@@ -1397,14 +1378,14 @@ Key Position::compute_pawn_key() const {
 
 Key Position::compute_material_key() const {
 
-  Key result = 0;
+  Key k = 0;
 
   for (Color c = WHITE; c <= BLACK; c++)
       for (PieceType pt = PAWN; pt <= QUEEN; pt++)
-          for (int i = 0; i < piece_count(c, pt); i++)
-              result ^= zobrist[c][pt][i];
+          for (int cnt = 0; cnt < piece_count(c, pt); cnt++)
+              k ^= zobrist[c][pt][cnt];
 
-  return result;
+  return k;
 }
 
 
@@ -1414,19 +1395,15 @@ Key Position::compute_material_key() const {
 /// updated by do_move and undo_move when the program is running in debug mode.
 Score Position::compute_psq_score() const {
 
-  Bitboard b;
-  Score result = SCORE_ZERO;
+  Score score = SCORE_ZERO;
 
-  for (Color c = WHITE; c <= BLACK; c++)
-      for (PieceType pt = PAWN; pt <= KING; pt++)
-      {
-          b = pieces(pt, c);
-          while (b)
-              result += pieceSquareTable[make_piece(c, pt)][pop_1st_bit(&b)];
-      }
+  for (Bitboard b = pieces(); b; )
+  {
+      Square s = pop_1st_bit(&b);
+      score += pieceSquareTable[piece_on(s)][s];
+  }
 
-  result += (sideToMove == WHITE ? Tempo / 2 : -Tempo / 2);
-  return result;
+  return score;
 }
 
 
@@ -1437,12 +1414,12 @@ Score Position::compute_psq_score() const {
 
 Value Position::compute_non_pawn_material(Color c) const {
 
-  Value result = VALUE_ZERO;
+  Value value = VALUE_ZERO;
 
   for (PieceType pt = KNIGHT; pt <= QUEEN; pt++)
-      result += piece_count(c, pt) * PieceValueMidgame[pt];
+      value += piece_count(c, pt) * PieceValueMidgame[pt];
 
-  return result;
+  return value;
 }
 
 
@@ -1521,14 +1498,14 @@ void Position::init() {
   zobSideToMove = rk.rand<Key>();
   zobExclusion  = rk.rand<Key>();
 
-  for (Piece p = W_PAWN; p <= W_KING; p++)
+  for (PieceType pt = PAWN; pt <= KING; pt++)
   {
-      Score ps = make_score(PieceValueMidgame[p], PieceValueEndgame[p]);
+      Score v = make_score(PieceValueMidgame[pt], PieceValueEndgame[pt]);
 
       for (Square s = SQ_A1; s <= SQ_H8; s++)
       {
-          pieceSquareTable[p][s] = ps + PSQT[p][s];
-          pieceSquareTable[p+8][~s] = -pieceSquareTable[p][s];
+          pieceSquareTable[make_piece(WHITE, pt)][ s] =  (v + PSQT[pt][s]);
+          pieceSquareTable[make_piece(BLACK, pt)][~s] = -(v + PSQT[pt][s]);
       }
   }
 }
@@ -1565,11 +1542,12 @@ void Position::flip() {
   if (pos.st->epSquare != SQ_NONE)
       st->epSquare = ~pos.st->epSquare;
 
+  st->checkersBB = attackers_to(king_square(sideToMove)) & pieces(~sideToMove);
+
   st->key = compute_key();
   st->pawnKey = compute_pawn_key();
   st->materialKey = compute_material_key();
   st->psqScore = compute_psq_score();
-  st->checkersBB = attackers_to(king_square(sideToMove)) & pieces(~sideToMove);
   st->npMaterial[WHITE] = compute_non_pawn_material(WHITE);
   st->npMaterial[BLACK] = compute_non_pawn_material(BLACK);
 
@@ -1582,42 +1560,39 @@ void Position::flip() {
 
 bool Position::pos_is_ok(int* failedStep) const {
 
+  int dummy, *step = failedStep ? failedStep : &dummy;
+
   // What features of the position should be verified?
-  const bool debugAll = false;
-
-  const bool debugBitboards       = debugAll || false;
-  const bool debugKingCount       = debugAll || false;
-  const bool debugKingCapture     = debugAll || false;
-  const bool debugCheckerCount    = debugAll || false;
-  const bool debugKey             = debugAll || false;
-  const bool debugMaterialKey     = debugAll || false;
-  const bool debugPawnKey         = debugAll || false;
-  const bool debugIncrementalEval = debugAll || false;
-  const bool debugNonPawnMaterial = debugAll || false;
-  const bool debugPieceCounts     = debugAll || false;
-  const bool debugPieceList       = debugAll || false;
-  const bool debugCastleSquares   = debugAll || false;
-
-  if (failedStep) *failedStep = 1;
-
-  // Side to move OK?
+  const bool all = false;
+
+  const bool debugBitboards       = all || false;
+  const bool debugKingCount       = all || false;
+  const bool debugKingCapture     = all || false;
+  const bool debugCheckerCount    = all || false;
+  const bool debugKey             = all || false;
+  const bool debugMaterialKey     = all || false;
+  const bool debugPawnKey         = all || false;
+  const bool debugIncrementalEval = all || false;
+  const bool debugNonPawnMaterial = all || false;
+  const bool debugPieceCounts     = all || false;
+  const bool debugPieceList       = all || false;
+  const bool debugCastleSquares   = all || false;
+
+  *step = 1;
+
   if (sideToMove != WHITE && sideToMove != BLACK)
       return false;
 
-  // Are the king squares in the position correct?
-  if (failedStep) (*failedStep)++;
-  if (piece_on(king_square(WHITE)) != W_KING)
+  if ((*step)++, piece_on(king_square(WHITE)) != W_KING)
       return false;
 
-  if (failedStep) (*failedStep)++;
-  if (piece_on(king_square(BLACK)) != B_KING)
+  if ((*step)++, piece_on(king_square(BLACK)) != B_KING)
       return false;
 
-  // Do both sides have exactly one king?
-  if (failedStep) (*failedStep)++;
-  if (debugKingCount)
+  if ((*step)++, debugKingCount)
   {
-      int kingCount[2] = {0, 0};
+      int kingCount[2] = {};
+
       for (Square s = SQ_A1; s <= SQ_H8; s++)
           if (type_of(piece_on(s)) == KING)
               kingCount[color_of(piece_on(s))]++;
@@ -1626,25 +1601,14 @@ bool Position::pos_is_ok(int* failedStep) const {
           return false;
   }
 
-  // Can the side to move capture the opponent's king?
-  if (failedStep) (*failedStep)++;
-  if (debugKingCapture)
-  {
-      Color us = sideToMove;
-      Color them = ~us;
-      Square ksq = king_square(them);
-      if (attackers_to(ksq) & pieces(us))
+  if ((*step)++, debugKingCapture)
+      if (attackers_to(king_square(~sideToMove)) & pieces(sideToMove))
           return false;
-  }
 
-  // Is there more than 2 checkers?
-  if (failedStep) (*failedStep)++;
-  if (debugCheckerCount && popcount<Full>(st->checkersBB) > 2)
+  if ((*step)++, debugCheckerCount && popcount<Full>(st->checkersBB) > 2)
       return false;
 
-  // Bitboards OK?
-  if (failedStep) (*failedStep)++;
-  if (debugBitboards)
+  if ((*step)++, debugBitboards)
   {
       // The intersection of the white and black pieces must be empty
       if (pieces(WHITE) & pieces(BLACK))
@@ -1662,57 +1626,35 @@ bool Position::pos_is_ok(int* failedStep) const {
                   return false;
   }
 
-  // En passant square OK?
-  if (failedStep) (*failedStep)++;
-  if (ep_square() != SQ_NONE)
-  {
-      // The en passant square must be on rank 6, from the point of view of the
-      // side to move.
-      if (relative_rank(sideToMove, ep_square()) != RANK_6)
-          return false;
-  }
+  if ((*step)++, ep_square() != SQ_NONE && relative_rank(sideToMove, ep_square()) != RANK_6)
+      return false;
 
-  // Hash key OK?
-  if (failedStep) (*failedStep)++;
-  if (debugKey && st->key != compute_key())
+  if ((*step)++, debugKey && st->key != compute_key())
       return false;
 
-  // Pawn hash key OK?
-  if (failedStep) (*failedStep)++;
-  if (debugPawnKey && st->pawnKey != compute_pawn_key())
+  if ((*step)++, debugPawnKey && st->pawnKey != compute_pawn_key())
       return false;
 
-  // Material hash key OK?
-  if (failedStep) (*failedStep)++;
-  if (debugMaterialKey && st->materialKey != compute_material_key())
+  if ((*step)++, debugMaterialKey && st->materialKey != compute_material_key())
       return false;
 
-  // Incremental eval OK?
-  if (failedStep) (*failedStep)++;
-  if (debugIncrementalEval && st->psqScore != compute_psq_score())
+  if ((*step)++, debugIncrementalEval && st->psqScore != compute_psq_score())
       return false;
 
-  // Non-pawn material OK?
-  if (failedStep) (*failedStep)++;
-  if (debugNonPawnMaterial)
+  if ((*step)++, debugNonPawnMaterial)
   {
-      if (st->npMaterial[WHITE] != compute_non_pawn_material(WHITE))
-          return false;
-
-      if (st->npMaterial[BLACK] != compute_non_pawn_material(BLACK))
+      if (   st->npMaterial[WHITE] != compute_non_pawn_material(WHITE)
+          || st->npMaterial[BLACK] != compute_non_pawn_material(BLACK))
           return false;
   }
 
-  // Piece counts OK?
-  if (failedStep) (*failedStep)++;
-  if (debugPieceCounts)
+  if ((*step)++, debugPieceCounts)
       for (Color c = WHITE; c <= BLACK; c++)
           for (PieceType pt = PAWN; pt <= KING; pt++)
               if (pieceCount[c][pt] != popcount<Full>(pieces(pt, c)))
                   return false;
 
-  if (failedStep) (*failedStep)++;
-  if (debugPieceList)
+  if ((*step)++, debugPieceList)
       for (Color c = WHITE; c <= BLACK; c++)
           for (PieceType pt = PAWN; pt <= KING; pt++)
               for (int i = 0; i < pieceCount[c][pt]; i++)
@@ -1724,19 +1666,23 @@ bool Position::pos_is_ok(int* failedStep) const {
                       return false;
               }
 
-  if (failedStep) (*failedStep)++;
-  if (debugCastleSquares)
+  if ((*step)++, debugCastleSquares)
       for (Color c = WHITE; c <= BLACK; c++)
           for (CastlingSide s = KING_SIDE; s <= QUEEN_SIDE; s = CastlingSide(s + 1))
           {
-              if (!can_castle(make_castle_right(c, s)))
+              CastleRight cr = make_castle_right(c, s);
+
+              if (!can_castle(cr))
                   continue;
 
+              if ((castleRightsMask[king_square(c)] & cr) != cr)
+                  return false;
+
               if (   piece_on(castleRookSquare[c][s]) != make_piece(c, ROOK)
-                  || castleRightsMask[castleRookSquare[c][s]] != make_castle_right(c, s))
+                  || castleRightsMask[castleRookSquare[c][s]] != cr)
                   return false;
           }
 
-  if (failedStep) *failedStep = 0;
+  *step = 0;
   return true;
 }