]> git.sesse.net Git - stockfish/blobdiff - src/position.cpp
Unify do_promotion_move()
[stockfish] / src / position.cpp
index 874c7545bf4dc31b1745a920ba6f7bcbef2106d6..795b633a9f90da27c6b3ca62f8f3312b21ea0a97 100644 (file)
@@ -72,14 +72,6 @@ Position::Position(const string& fen) {
 }
 
 
-/// Position::setTranspositionTable() is used by search functions to pass
-/// the pointer to the used TT so that do_move() will prefetch TT access.
-
-void Position::setTranspositionTable(TranspositionTable* tt) {
-  TT = tt;
-}
-
-
 /// Position::from_fen() initializes the position object with the given FEN
 /// string. This function is not very robust - make sure that input FENs are
 /// correct (this is assumed to be the responsibility of the GUI).
@@ -728,33 +720,35 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) {
   // case of non-reversible moves is taken care of later.
   st->rule50++;
 
+  // Update side to move
+  st->key ^= zobSideToMove;
+
   if (move_is_castle(m))
       do_castle_move(m);
-  else if (move_is_promotion(m))
-      do_promotion_move(m);
-  else if (move_is_ep(m))
-      do_ep_move(m);
   else
   {
     Color us = side_to_move();
     Color them = opposite_color(us);
     Square from = move_from(m);
     Square to = move_to(m);
-
-    assert(color_of_piece_on(from) == us);
-    assert(color_of_piece_on(to) == them || piece_on(to) == EMPTY);
+    bool ep = move_is_ep(m);
+    bool pm = move_is_promotion(m);
 
     Piece piece = piece_on(from);
     PieceType pt = type_of_piece(piece);
 
+    assert(color_of_piece_on(from) == us);
+    assert(color_of_piece_on(to) == them || square_is_empty(to));
+    assert(!(ep || pm) || piece == piece_of_color_and_type(us, PAWN));
+    assert(!pm || relative_rank(us, to) == RANK_8);
+
     st->capture = type_of_piece_on(to);
 
-    if (st->capture)
-      do_capture_move(st->capture, them, to);
+    if (st->capture || ep)
+        do_capture_move(st->capture, them, to, ep);
 
     // Update hash key
     st->key ^= zobrist[us][pt][from] ^ zobrist[us][pt][to];
-    st->key ^= zobSideToMove;
 
     // Reset en passant square
     if (st->epSquare != SQ_NONE)
@@ -772,11 +766,8 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) {
         st->key ^= zobCastle[st->castleRights];
     }
 
-    bool checkEpSquare = (pt == PAWN && abs(int(to) - int(from)) == 16);
-
     // Prefetch TT access as soon as we know key is updated
-    if (!checkEpSquare && TT)
-        TT->prefetch(st->key);
+    TT.prefetch(st->key);
 
     // Move the piece
     Bitboard move_bb = make_move_bb(from, to);
@@ -797,7 +788,7 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) {
         st->pawnKey ^= zobrist[us][PAWN][from] ^ zobrist[us][PAWN][to];
 
         // Set en passant square, only if moved pawn can be captured
-        if (checkEpSquare)
+        if (abs(int(to) - int(from)) == 16)
         {
             if (   (us == WHITE && (pawn_attacks(WHITE, from + DELTA_N) & pawns(BLACK)))
                 || (us == BLACK && (pawn_attacks(BLACK, from + DELTA_S) & pawns(WHITE))))
@@ -808,10 +799,6 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) {
         }
     }
 
-    // Prefetch only here in the few cases we needed zobEp[] to update the key
-    if (checkEpSquare && TT)
-        TT->prefetch(st->key);
-
     // Update incremental scores
     st->mgValue += pst_delta<MidGame>(piece, from, to);
     st->egValue += pst_delta<EndGame>(piece, from, to);
@@ -824,18 +811,62 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) {
     pieceList[us][pt][index[from]] = to;
     index[to] = index[from];
 
+    if (pm)
+    {
+        PieceType promotion = move_promotion_piece(m);
+
+        assert(promotion >= KNIGHT && promotion <= QUEEN);
+
+        // Insert promoted piece instead of pawn
+        clear_bit(&(byTypeBB[PAWN]), to);
+        set_bit(&(byTypeBB[promotion]), to);
+        board[to] = piece_of_color_and_type(us, promotion);
+
+        // Partially revert hash keys update
+        st->key ^= zobrist[us][PAWN][to] ^ zobrist[us][promotion][to];
+        st->pawnKey ^= zobrist[us][PAWN][to];
+
+        // Update material key
+        st->materialKey ^= zobMaterial[us][PAWN][pieceCount[us][PAWN]];
+        st->materialKey ^= zobMaterial[us][promotion][pieceCount[us][promotion]+1];
+
+        // Update piece counts
+        pieceCount[us][PAWN]--;
+        pieceCount[us][promotion]++;
+
+        // Update piece lists
+        pieceList[us][PAWN][index[from]] = pieceList[us][PAWN][pieceCount[us][PAWN]];
+        index[pieceList[us][PAWN][index[from]]] = index[from];
+        pieceList[us][promotion][pieceCount[us][promotion] - 1] = to;
+        index[to] = pieceCount[us][promotion] - 1;
+
+        // Partially revert and update incremental scores
+        st->mgValue -= pst<MidGame>(us, PAWN, to);
+        st->mgValue += pst<MidGame>(us, promotion, to);
+        st->egValue -= pst<EndGame>(us, PAWN, to);
+        st->egValue += pst<EndGame>(us, promotion, to);
+
+        // Update material
+        st->npMaterial[us] += piece_value_midgame(promotion);
+    }
+
     // Update checkers bitboard, piece must be already moved
-    st->checkersBB = EmptyBoardBB;
-    Square ksq = king_square(them);
-    switch (pt)
+    if (ep || pm)
+        st->checkersBB = attacks_to(king_square(them), 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;
+        st->checkersBB = EmptyBoardBB; // FIXME EP ?
+        Square ksq = king_square(them);
+        switch (pt)
+        {
+        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;
+        }
     }
   }
 
@@ -853,25 +884,41 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) {
 /// Position::do_capture_move() is a private method used to update captured
 /// piece info. It is called from the main Position::do_move function.
 
-void Position::do_capture_move(PieceType capture, Color them, Square to) {
+void Position::do_capture_move(PieceType capture, Color them, Square to, bool ep) {
 
     assert(capture != KING);
 
+    Square capsq = to;
+
+    if (ep)
+    {
+        capture = PAWN;
+        capsq = (them == BLACK)? (to - DELTA_N) : (to - DELTA_S);
+
+        assert(to == st->epSquare);
+        assert(relative_rank(opposite_color(them), to) == RANK_6);
+        assert(piece_on(to) == EMPTY);
+        //assert(piece_on(from) == piece_of_color_and_type(us, PAWN));
+        assert(piece_on(capsq) == piece_of_color_and_type(them, PAWN));
+
+        board[capsq] = EMPTY;
+    }
+
     // Remove captured piece
-    clear_bit(&(byColorBB[them]), to);
-    clear_bit(&(byTypeBB[capture]), to);
-    clear_bit(&(byTypeBB[0]), to);
+    clear_bit(&(byColorBB[them]), capsq);
+    clear_bit(&(byTypeBB[capture]), capsq);
+    clear_bit(&(byTypeBB[0]), capsq); // HACK: byTypeBB[0] == occupied squares
 
     // Update hash key
-    st->key ^= zobrist[them][capture][to];
+    st->key ^= zobrist[them][capture][capsq];
 
     // If the captured piece was a pawn, update pawn hash key
     if (capture == PAWN)
-        st->pawnKey ^= zobrist[them][PAWN][to];
+        st->pawnKey ^= zobrist[them][PAWN][capsq];
 
     // Update incremental scores
-    st->mgValue -= pst<MidGame>(them, capture, to);
-    st->egValue -= pst<EndGame>(them, capture, to);
+    st->mgValue -= pst<MidGame>(them, capture, capsq);
+    st->egValue -= pst<EndGame>(them, capture, capsq);
 
     // Update material
     if (capture != PAWN)
@@ -884,8 +931,8 @@ void Position::do_capture_move(PieceType capture, Color them, Square to) {
     pieceCount[them][capture]--;
 
     // Update piece list
-    pieceList[them][capture][index[to]] = pieceList[them][capture][pieceCount[them][capture]];
-    index[pieceList[them][capture][index[to]]] = index[to];
+    pieceList[them][capture][index[capsq]] = pieceList[them][capture][pieceCount[them][capture]];
+    index[pieceList[them][capture][index[capsq]]] = index[capsq];
 
     // Reset rule 50 counter
     st->rule50 = 0;
@@ -979,179 +1026,6 @@ void Position::do_castle_move(Move m) {
 
   // Update checkers BB
   st->checkersBB = attacks_to(king_square(them), us);
-
-  st->key ^= zobSideToMove;
-}
-
-
-/// Position::do_promotion_move() is a private method used to make a promotion
-/// move. It is called from the main Position::do_move function.
-
-void Position::do_promotion_move(Move m) {
-
-  Color us, them;
-  Square from, to;
-  PieceType promotion;
-
-  assert(is_ok());
-  assert(move_is_ok(m));
-  assert(move_is_promotion(m));
-
-  us = side_to_move();
-  them = opposite_color(us);
-  from = move_from(m);
-  to = move_to(m);
-
-  assert(relative_rank(us, to) == RANK_8);
-  assert(piece_on(from) == piece_of_color_and_type(us, PAWN));
-  assert(color_of_piece_on(to) == them || square_is_empty(to));
-
-  st->capture = type_of_piece_on(to);
-
-  if (st->capture)
-      do_capture_move(st->capture, them, to);
-
-  // Remove pawn
-  clear_bit(&(byColorBB[us]), from);
-  clear_bit(&(byTypeBB[PAWN]), from);
-  clear_bit(&(byTypeBB[0]), from); // HACK: byTypeBB[0] == occupied squares
-  board[from] = EMPTY;
-
-  // Insert promoted piece
-  promotion = move_promotion_piece(m);
-  assert(promotion >= KNIGHT && promotion <= QUEEN);
-  set_bit(&(byColorBB[us]), to);
-  set_bit(&(byTypeBB[promotion]), to);
-  set_bit(&(byTypeBB[0]), to); // HACK: byTypeBB[0] == occupied squares
-  board[to] = piece_of_color_and_type(us, promotion);
-
-  // Update hash key
-  st->key ^= zobrist[us][PAWN][from] ^ zobrist[us][promotion][to];
-
-  // Update pawn hash key
-  st->pawnKey ^= zobrist[us][PAWN][from];
-
-  // Update material key
-  st->materialKey ^= zobMaterial[us][PAWN][pieceCount[us][PAWN]];
-  st->materialKey ^= zobMaterial[us][promotion][pieceCount[us][promotion]+1];
-
-  // Update piece counts
-  pieceCount[us][PAWN]--;
-  pieceCount[us][promotion]++;
-
-  // Update piece lists
-  pieceList[us][PAWN][index[from]] = pieceList[us][PAWN][pieceCount[us][PAWN]];
-  index[pieceList[us][PAWN][index[from]]] = index[from];
-  pieceList[us][promotion][pieceCount[us][promotion] - 1] = to;
-  index[to] = pieceCount[us][promotion] - 1;
-
-  // Update incremental scores
-  st->mgValue -= pst<MidGame>(us, PAWN, from);
-  st->mgValue += pst<MidGame>(us, promotion, to);
-  st->egValue -= pst<EndGame>(us, PAWN, from);
-  st->egValue += pst<EndGame>(us, promotion, to);
-
-  // Update material
-  st->npMaterial[us] += piece_value_midgame(promotion);
-
-  // Clear the en passant square
-  if (st->epSquare != SQ_NONE)
-  {
-      st->key ^= zobEp[st->epSquare];
-      st->epSquare = SQ_NONE;
-  }
-
-  // Update castle rights
-  st->key ^= zobCastle[st->castleRights];
-  st->castleRights &= castleRightsMask[to];
-  st->key ^= zobCastle[st->castleRights];
-
-  // Reset rule 50 counter
-  st->rule50 = 0;
-
-  // Update checkers BB
-  st->checkersBB = attacks_to(king_square(them), us);
-
-  st->key ^= zobSideToMove;
-}
-
-
-/// Position::do_ep_move() is a private method used to make an en passant
-/// capture. It is called from the main Position::do_move function.
-
-void Position::do_ep_move(Move m) {
-
-  Color us, them;
-  Square from, to, capsq;
-
-  assert(is_ok());
-  assert(move_is_ok(m));
-  assert(move_is_ep(m));
-
-  us = side_to_move();
-  them = opposite_color(us);
-  from = move_from(m);
-  to = move_to(m);
-  capsq = (us == WHITE)? (to - DELTA_N) : (to - DELTA_S);
-
-  assert(to == st->epSquare);
-  assert(relative_rank(us, to) == RANK_6);
-  assert(piece_on(to) == EMPTY);
-  assert(piece_on(from) == piece_of_color_and_type(us, PAWN));
-  assert(piece_on(capsq) == piece_of_color_and_type(them, PAWN));
-
-  // Remove captured pawn
-  clear_bit(&(byColorBB[them]), capsq);
-  clear_bit(&(byTypeBB[PAWN]), capsq);
-  clear_bit(&(byTypeBB[0]), capsq); // HACK: byTypeBB[0] == occupied squares
-  board[capsq] = EMPTY;
-
-  // Move capturing pawn
-  Bitboard move_bb = make_move_bb(from, to);
-  do_move_bb(&(byColorBB[us]), move_bb);
-  do_move_bb(&(byTypeBB[PAWN]), move_bb);
-  do_move_bb(&(byTypeBB[0]), move_bb); // HACK: byTypeBB[0] == occupied squares
-  board[to] = board[from];
-  board[from] = EMPTY;
-
-  // Update material hash key
-  st->materialKey ^= zobMaterial[them][PAWN][pieceCount[them][PAWN]];
-
-  // Update piece count
-  pieceCount[them][PAWN]--;
-
-  // Update piece list
-  pieceList[us][PAWN][index[from]] = to;
-  index[to] = index[from];
-  pieceList[them][PAWN][index[capsq]] = pieceList[them][PAWN][pieceCount[them][PAWN]];
-  index[pieceList[them][PAWN][index[capsq]]] = index[capsq];
-
-  // Update hash key
-  st->key ^= zobrist[us][PAWN][from] ^ zobrist[us][PAWN][to];
-  st->key ^= zobrist[them][PAWN][capsq];
-  st->key ^= zobEp[st->epSquare];
-
-  // Update pawn hash key
-  st->pawnKey ^= zobrist[us][PAWN][from] ^ zobrist[us][PAWN][to];
-  st->pawnKey ^= zobrist[them][PAWN][capsq];
-
-  // Update incremental scores
-  Piece pawn = piece_of_color_and_type(us, PAWN);
-  st->mgValue += pst_delta<MidGame>(pawn, from, to);
-  st->egValue += pst_delta<EndGame>(pawn, from, to);
-  st->mgValue -= pst<MidGame>(them, PAWN, capsq);
-  st->egValue -= pst<EndGame>(them, PAWN, capsq);
-
-  // Reset en passant square
-  st->epSquare = SQ_NONE;
-
-  // Reset rule 50 counter
-  st->rule50 = 0;
-
-  // Update checkers BB
-  st->checkersBB = attacks_to(king_square(them), us);
-
-  st->key ^= zobSideToMove;
 }
 
 
@@ -1436,7 +1310,7 @@ void Position::do_null_move(StateInfo& backupSt) {
       st->key ^= zobEp[st->epSquare];
 
   st->key ^= zobSideToMove;
-  TT->prefetch(st->key);
+  TT.prefetch(st->key);
   sideToMove = opposite_color(sideToMove);
   st->epSquare = SQ_NONE;
   st->rule50++;
@@ -1680,7 +1554,6 @@ void Position::clear() {
   initialKFile = FILE_E;
   initialKRFile = FILE_H;
   initialQRFile = FILE_A;
-  TT = NULL;
 }