]> git.sesse.net Git - stockfish/blobdiff - src/position.cpp
Small codestyle touches
[stockfish] / src / position.cpp
index c8132d5e513d2a1b2d4aa6a711f96e1440b0b5f7..74cb1f4eefef8c920ce7b1da55a70153fe9c08ca 100644 (file)
@@ -46,7 +46,7 @@ using std::endl;
 
 static inline bool isZero(char c) { return c == '0'; }
 
-struct PieceLetters : std::map<char, Piece> {
+struct PieceLetters : public std::map<char, Piece> {
 
     PieceLetters() {
 
@@ -71,10 +71,16 @@ struct PieceLetters : std::map<char, Piece> {
     }
 };
 
+
 ////
-//// Variables
+//// Constants and variables
 ////
 
+/// Bonus for having the side to move (modified by Joona Kiiski)
+
+static const Score TempoValue = make_score(48, 22);
+
+
 Key Position::zobrist[2][8][64];
 Key Position::zobEp[64];
 Key Position::zobCastle[16];
@@ -85,6 +91,12 @@ Score Position::PieceSquareTable[16][64];
 
 static PieceLetters pieceLetters;
 
+// Material values used by SEE, indexed by PieceType
+const Value Position::seeValues[] = {
+  VALUE_ZERO, PawnValueMidgame, KnightValueMidgame, BishopValueMidgame,
+  RookValueMidgame, QueenValueMidgame, QueenValueMidgame*10
+};
+
 
 /// Constructors
 
@@ -182,7 +194,7 @@ void Position::from_fen(const string& fen) {
   {
       if (isdigit(token))
       {
-          file += token - '0'; // Skip the given number of files
+          file += File(token - '0'); // Skip the given number of files
           continue;
       }
       else if (token == '/')
@@ -240,6 +252,10 @@ void Position::from_fen(const string& fen) {
   castleRightsMask[make_square(initialQRFile, RANK_1)] ^= WHITE_OOO;
   castleRightsMask[make_square(initialQRFile, RANK_8)] ^= BLACK_OOO;
 
+  isChess960 =   initialKFile  != FILE_E
+              || initialQRFile != FILE_A
+              || initialKRFile != FILE_H;
+
   find_checkers();
 
   st->key = compute_key();
@@ -346,21 +362,17 @@ const string Position::to_fen() const {
 
   if (st->castleRights != CASTLES_NONE)
   {
-      const bool Chess960 =   initialKFile  != FILE_E
-                           || initialQRFile != FILE_A
-                           || initialKRFile != FILE_H;
-
       if (can_castle_kingside(WHITE))
-          fen += Chess960 ? char(toupper(file_to_char(initialKRFile))) : 'K';
+          fen += isChess960 ? char(toupper(file_to_char(initialKRFile))) : 'K';
 
       if (can_castle_queenside(WHITE))
-          fen += Chess960 ? char(toupper(file_to_char(initialQRFile))) : 'Q';
+          fen += isChess960 ? char(toupper(file_to_char(initialQRFile))) : 'Q';
 
       if (can_castle_kingside(BLACK))
-          fen += Chess960 ? file_to_char(initialKRFile) : 'k';
+          fen += isChess960 ? file_to_char(initialKRFile) : 'k';
 
       if (can_castle_queenside(BLACK))
-          fen += Chess960 ? file_to_char(initialQRFile) : 'q';
+          fen += isChess960 ? file_to_char(initialQRFile) : 'q';
   } else
       fen += '-';
 
@@ -370,7 +382,7 @@ const string Position::to_fen() const {
 
 
 /// Position::print() prints an ASCII representation of the position to
-/// the standard output. If a move is given then also the san is print.
+/// the standard output. If a move is given then also the san is printed.
 
 void Position::print(Move move) const {
 
@@ -839,8 +851,9 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
       // Reset rule 50 draw counter
       st->rule50 = 0;
 
-      // Update pawn hash key
+      // Update pawn hash key and prefetch in L1/L2 cache
       st->pawnKey ^= zobrist[us][PAWN][from] ^ zobrist[us][PAWN][to];
+      prefetchPawn(st->pawnKey, threadID);
 
       // Set en passant square, only if moved pawn can be captured
       if ((to ^ from) == 16)
@@ -889,7 +902,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
           st->value += pst(us, promotion, to);
 
           // Update material
-          st->npMaterial[us] += piece_value_midgame(promotion);
+          st->npMaterial[us] += PieceValueMidgame[promotion];
       }
   }
 
@@ -962,7 +975,7 @@ void Position::do_capture_move(Key& key, PieceType capture, Color them, Square t
         st->pawnKey ^= zobrist[them][PAWN][capsq];
     }
     else
-        st->npMaterial[them] -= piece_value_midgame(capture);
+        st->npMaterial[them] -= PieceValueMidgame[capture];
 
     // Remove captured piece
     clear_bit(&(byColorBB[them]), capsq);
@@ -1332,12 +1345,6 @@ void Position::undo_null_move() {
 /// move, and one which takes a 'from' and a 'to' square. The function does
 /// not yet understand promotions captures.
 
-int Position::see(Square to) const {
-
-  assert(square_is_ok(to));
-  return see(SQ_NONE, to);
-}
-
 int Position::see(Move m) const {
 
   assert(move_is_ok(m));
@@ -1362,82 +1369,50 @@ int Position::see_sign(Move m) const {
 
 int Position::see(Square from, Square to) const {
 
-  // Material values
-  static const int seeValues[18] = {
-    0, PawnValueMidgame, KnightValueMidgame, BishopValueMidgame,
-       RookValueMidgame, QueenValueMidgame, QueenValueMidgame*10, 0,
-    0, PawnValueMidgame, KnightValueMidgame, BishopValueMidgame,
-       RookValueMidgame, QueenValueMidgame, QueenValueMidgame*10, 0,
-    0, 0
-  };
-
-  Bitboard attackers, stmAttackers, b;
+  Bitboard occ, attackers, stmAttackers, b;
+  int swapList[32], slIndex = 1;
+  PieceType capturedType, pt;
+  Color stm;
 
-  assert(square_is_ok(from) || from == SQ_NONE);
+  assert(square_is_ok(from));
   assert(square_is_ok(to));
 
-  // Initialize colors
-  Color us = (from != SQ_NONE ? color_of_piece_on(from) : opposite_color(color_of_piece_on(to)));
-  Color them = opposite_color(us);
-
-  // Initialize pieces
-  Piece piece = piece_on(from);
-  Piece capture = piece_on(to);
-  Bitboard occ = occupied_squares();
+  capturedType = type_of_piece_on(to);
 
   // King cannot be recaptured
-  if (type_of_piece(piece) == KING)
-      return seeValues[capture];
+  if (capturedType == KING)
+      return seeValues[capturedType];
+
+  occ = occupied_squares();
 
   // Handle en passant moves
   if (st->epSquare == to && type_of_piece_on(from) == PAWN)
   {
-      assert(capture == PIECE_NONE);
+      Square capQq = (side_to_move() == WHITE) ? (to - DELTA_N) : (to - DELTA_S);
 
-      Square capQq = (side_to_move() == WHITE)? (to - DELTA_N) : (to - DELTA_S);
-      capture = piece_on(capQq);
+      assert(capturedType == PIECE_TYPE_NONE);
       assert(type_of_piece_on(capQq) == PAWN);
 
       // Remove the captured pawn
       clear_bit(&occ, capQq);
+      capturedType = PAWN;
   }
 
-  while (true)
-  {
-      // Find all attackers to the destination square, with the moving piece
-      // removed, but possibly an X-ray attacker added behind it.
-      clear_bit(&occ, from);
-      attackers =  (rook_attacks_bb(to, occ)      & pieces(ROOK, QUEEN))
-                 | (bishop_attacks_bb(to, occ)    & pieces(BISHOP, QUEEN))
-                 | (attacks_from<KNIGHT>(to)      & pieces(KNIGHT))
-                 | (attacks_from<KING>(to)        & pieces(KING))
-                 | (attacks_from<PAWN>(to, WHITE) & pieces(PAWN, BLACK))
-                 | (attacks_from<PAWN>(to, BLACK) & pieces(PAWN, WHITE));
-
-      if (from != SQ_NONE)
-          break;
-
-      // If we don't have any attacker we are finished
-      if ((attackers & pieces_of_color(us)) == EmptyBoardBB)
-          return 0;
-
-      // Locate the least valuable attacker to the destination square
-      // and use it to initialize from square.
-      stmAttackers = attackers & pieces_of_color(us);
-      PieceType pt;
-      for (pt = PAWN; !(stmAttackers & pieces(pt)); pt++)
-          assert(pt < KING);
-
-      from = first_1(stmAttackers & pieces(pt));
-      piece = piece_on(from);
-  }
+  // Find all attackers to the destination square, with the moving piece
+  // removed, but possibly an X-ray attacker added behind it.
+  clear_bit(&occ, from);
+  attackers =  (rook_attacks_bb(to, occ)      & pieces(ROOK, QUEEN))
+             | (bishop_attacks_bb(to, occ)    & pieces(BISHOP, QUEEN))
+             | (attacks_from<KNIGHT>(to)      & pieces(KNIGHT))
+             | (attacks_from<KING>(to)        & pieces(KING))
+             | (attacks_from<PAWN>(to, WHITE) & pieces(PAWN, BLACK))
+             | (attacks_from<PAWN>(to, BLACK) & pieces(PAWN, WHITE));
 
   // If the opponent has no attackers we are finished
-  stmAttackers = attackers & pieces_of_color(them);
+  stm = opposite_color(color_of_piece_on(from));
+  stmAttackers = attackers & pieces_of_color(stm);
   if (!stmAttackers)
-      return seeValues[capture];
-
-  attackers &= occ; // Remove the moving piece
+      return seeValues[capturedType];
 
   // The destination square is defended, which makes things rather more
   // difficult to compute. We proceed by building up a "swap list" containing
@@ -1445,12 +1420,8 @@ int Position::see(Square from, Square to) const {
   // destination square, where the sides alternately capture, and always
   // capture with the least valuable piece. After each capture, we look for
   // new X-ray attacks from behind the capturing piece.
-  int lastCapturingPieceValue = seeValues[piece];
-  int swapList[32], n = 1;
-  Color c = them;
-  PieceType pt;
-
-  swapList[0] = seeValues[capture];
+  swapList[0] = seeValues[capturedType];
+  capturedType = type_of_piece_on(from);
 
   do {
       // Locate the least valuable attacker for the side to move. The loop
@@ -1463,35 +1434,35 @@ int Position::see(Square from, Square to) const {
       // and scan for new X-ray attacks behind the attacker.
       b = stmAttackers & pieces(pt);
       occ ^= (b & (~b + 1));
-      attackers |=  (rook_attacks_bb(to, occ)  pieces(ROOK, QUEEN))
+      attackers |=  (rook_attacks_bb(to, occ)   & pieces(ROOK, QUEEN))
                   | (bishop_attacks_bb(to, occ) & pieces(BISHOP, QUEEN));
 
-      attackers &= occ;
+      attackers &= occ; // Cut out pieces we've already done
 
       // Add the new entry to the swap list
-      assert(n < 32);
-      swapList[n] = -swapList[n - 1] + lastCapturingPieceValue;
-      n++;
+      assert(slIndex < 32);
+      swapList[slIndex] = -swapList[slIndex - 1] + seeValues[capturedType];
+      slIndex++;
 
       // Remember the value of the capturing piece, and change the side to move
       // before beginning the next iteration
-      lastCapturingPieceValue = seeValues[pt];
-      c = opposite_color(c);
-      stmAttackers = attackers & pieces_of_color(c);
+      capturedType = pt;
+      stm = opposite_color(stm);
+      stmAttackers = attackers & pieces_of_color(stm);
 
       // Stop after a king capture
       if (pt == KING && stmAttackers)
       {
-          assert(n < 32);
-          swapList[n++] = QueenValueMidgame*10;
+          assert(slIndex < 32);
+          swapList[slIndex++] = QueenValueMidgame*10;
           break;
       }
   } while (stmAttackers);
 
   // Having built the swap list, we negamax through it to find the best
   // achievable score from the point of view of the side to move
-  while (--n)
-      swapList[n-1] = Min(-swapList[n], swapList[n-1]);
+  while (--slIndex)
+      swapList[slIndex-1] = Min(-swapList[slIndex], swapList[slIndex-1]);
 
   return swapList[0];
 }
@@ -1590,7 +1561,7 @@ void Position::allow_ooo(Color c) {
 
 Key Position::compute_key() const {
 
-  Key result = Key(0ULL);
+  Key result = 0;
 
   for (Square s = SQ_A1; s <= SQ_H8; s++)
       if (square_is_occupied(s))
@@ -1615,7 +1586,7 @@ Key Position::compute_key() const {
 
 Key Position::compute_pawn_key() const {
 
-  Key result = Key(0ULL);
+  Key result = 0;
   Bitboard b;
   Square s;
 
@@ -1640,7 +1611,7 @@ Key Position::compute_pawn_key() const {
 
 Key Position::compute_material_key() const {
 
-  Key result = Key(0ULL);
+  Key result = 0;
   for (Color c = WHITE; c <= BLACK; c++)
       for (PieceType pt = PAWN; pt <= QUEEN; pt++)
       {
@@ -1658,7 +1629,7 @@ Key Position::compute_material_key() const {
 /// updated by do_move and undo_move when the program is running in debug mode.
 Score Position::compute_value() const {
 
-  Score result = make_score(0, 0);
+  Score result = SCORE_ZERO;
   Bitboard b;
   Square s;
 
@@ -1686,7 +1657,7 @@ Score Position::compute_value() const {
 
 Value Position::compute_non_pawn_material(Color c) const {
 
-  Value result = Value(0);
+  Value result = VALUE_ZERO;
 
   for (PieceType pt = KNIGHT; pt <= QUEEN; pt++)
   {
@@ -1694,8 +1665,9 @@ Value Position::compute_non_pawn_material(Color c) const {
       while (b)
       {
           assert(piece_on(first_1(b)) == piece_of_color_and_type(c, pt));
+
           pop_1st_bit(&b);
-          result += piece_value_midgame(pt);
+          result += PieceValueMidgame[pt];
       }
   }
   return result;
@@ -1705,7 +1677,6 @@ Value Position::compute_non_pawn_material(Color c) const {
 /// Position::is_draw() tests whether the position is drawn by material,
 /// repetition, or the 50 moves rule. It does not detect stalemates, this
 /// must be done by the search.
-// FIXME: Currently we are not handling 50 move rule correctly when in check
 
 bool Position::is_draw() const {
 
@@ -1715,7 +1686,7 @@ bool Position::is_draw() const {
       return true;
 
   // Draw by the 50 moves rule?
-  if (st->rule50 > 100 || (st->rule50 == 100 && !is_check()))
+  if (st->rule50 > 99 && (st->rule50 > 100 || !is_mate()))
       return true;
 
   // Draw by repetition?
@@ -1732,7 +1703,7 @@ bool Position::is_draw() const {
 
 bool Position::is_mate() const {
 
-  MoveStack moves[256];
+  MoveStack moves[MOVES_MAX];
   return is_check() && (generate_moves(*this, moves) == moves);
 }
 
@@ -1742,7 +1713,7 @@ bool Position::is_mate() const {
 
 bool Position::has_mate_threat() {
 
-  MoveStack mlist[256], *last, *cur;
+  MoveStack mlist[MOVES_MAX], *last, *cur;
   StateInfo st1, st2;
   bool mateFound = false;
 
@@ -1946,7 +1917,7 @@ bool Position::is_ok(int* failedStep) const {
 
   // Is there more than 2 checkers?
   if (failedStep) (*failedStep)++;
-  if (debugCheckerCount && count_1s(st->checkersBB) > 2)
+  if (debugCheckerCount && count_1s<CNT32>(st->checkersBB) > 2)
       return false;
 
   // Bitboards OK?
@@ -2015,7 +1986,7 @@ bool Position::is_ok(int* failedStep) const {
   if (debugPieceCounts)
       for (Color c = WHITE; c <= BLACK; c++)
           for (PieceType pt = PAWN; pt <= KING; pt++)
-              if (pieceCount[c][pt] != count_1s(pieces(pt, c)))
+              if (pieceCount[c][pt] != count_1s<CNT32>(pieces(pt, c)))
                   return false;
 
   if (failedStep) (*failedStep)++;