X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fposition.cpp;h=605cc1ae63f3e63c0f4bd0f13cc68b40b0b979cb;hb=bc76c62c6302a445860e1deef5f55c2aabb7377d;hp=4935a2c643ed965992944a4563695619b7ac9b70;hpb=e896368496d4156f3f8c1dda5a95686804088e73;p=stockfish diff --git a/src/position.cpp b/src/position.cpp index 4935a2c6..605cc1ae 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -781,11 +781,66 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI assert(color_of(piece_on(from)) == us); assert(color_of(piece_on(to)) == them || square_is_empty(to)); - assert(!(ep || pm) || piece == make_piece(us, PAWN)); - assert(!pm || relative_rank(us, to) == RANK_8); + assert(capture != KING); if (capture) - do_capture_move(key, capture, them, to, ep); + { + Square capsq = to; + + // If the captured piece was a pawn, update pawn hash key, otherwise + // update non-pawn material. + if (capture == PAWN) + { + if (ep) // En passant? + { + capsq += pawn_push(them); + + assert(pt == PAWN); + assert(to == st->epSquare); + assert(relative_rank(us, to) == RANK_6); + assert(piece_on(to) == PIECE_NONE); + assert(piece_on(capsq) == make_piece(them, PAWN)); + + board[capsq] = PIECE_NONE; + } + + st->pawnKey ^= zobrist[them][PAWN][capsq]; + } + else + st->npMaterial[them] -= PieceValueMidgame[capture]; + + // Remove captured piece + clear_bit(&byColorBB[them], capsq); + clear_bit(&byTypeBB[capture], capsq); + clear_bit(&occupied, capsq); + + // Update hash key + key ^= zobrist[them][capture][capsq]; + + // Update incremental scores + st->value -= pst(make_piece(them, capture), capsq); + + // Update piece count + pieceCount[them][capture]--; + + // Update material hash key + st->materialKey ^= zobrist[them][capture][pieceCount[them][capture]]; + + // Update piece list, move the last piece at index[capsq] position + // + // WARNING: This is a not perfectly revresible operation. When we + // will reinsert the captured piece in undo_move() we will put it + // at the end of the list and not in its original place, it means + // index[] and pieceList[] are not guaranteed to be invariant to a + // do_move() + undo_move() sequence. + Square lastPieceSquare = pieceList[them][capture][pieceCount[them][capture]]; + index[lastPieceSquare] = index[capsq]; + pieceList[them][capture][index[lastPieceSquare]] = lastPieceSquare; + pieceList[them][capture][pieceCount[them][capture]] = SQ_NONE; + + // Reset rule 50 counter + st->rule50 = 0; + } // Update hash key key ^= zobrist[us][pt][from] ^ zobrist[us][pt][to]; @@ -813,7 +868,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI Bitboard move_bb = make_move_bb(from, to); do_move_bb(&byColorBB[us], move_bb); do_move_bb(&byTypeBB[pt], move_bb); - do_move_bb(&byTypeBB[0], move_bb); // HACK: byTypeBB[0] == occupied squares + do_move_bb(&occupied, move_bb); board[to] = board[from]; board[from] = PIECE_NONE; @@ -930,69 +985,6 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI } -/// 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(Key& key, PieceType capture, Color them, Square to, bool ep) { - - assert(capture != KING); - - Square capsq = to; - - // If the captured piece was a pawn, update pawn hash key, - // otherwise update non-pawn material. - if (capture == PAWN) - { - if (ep) // en passant ? - { - capsq = to + pawn_push(them); - - assert(to == st->epSquare); - assert(relative_rank(flip(them), to) == RANK_6); - assert(piece_on(to) == PIECE_NONE); - assert(piece_on(capsq) == make_piece(them, PAWN)); - - board[capsq] = PIECE_NONE; - } - st->pawnKey ^= zobrist[them][PAWN][capsq]; - } - else - st->npMaterial[them] -= PieceValueMidgame[capture]; - - // Remove captured piece - clear_bit(&byColorBB[them], capsq); - clear_bit(&byTypeBB[capture], capsq); - clear_bit(&byTypeBB[0], capsq); - - // Update hash key - key ^= zobrist[them][capture][capsq]; - - // Update incremental scores - st->value -= pst(make_piece(them, capture), capsq); - - // Update piece count - pieceCount[them][capture]--; - - // Update material hash key - st->materialKey ^= zobrist[them][capture][pieceCount[them][capture]]; - - // Update piece list, move the last piece at index[capsq] position - // - // WARNING: This is a not perfectly revresible operation. When we - // will reinsert the captured piece in undo_move() we will put it - // at the end of the list and not in its original place, it means - // index[] and pieceList[] are not guaranteed to be invariant to a - // do_move() + undo_move() sequence. - Square lastPieceSquare = pieceList[them][capture][pieceCount[them][capture]]; - index[lastPieceSquare] = index[capsq]; - pieceList[them][capture][index[lastPieceSquare]] = lastPieceSquare; - pieceList[them][capture][pieceCount[them][capture]] = SQ_NONE; - - // Reset rule 50 counter - st->rule50 = 0; -} - - /// Position::do_castle_move() is a private method used to do/undo a castling /// move. Note that castling moves are encoded as "king captures friendly rook" /// moves, for instance white short castling in a non-Chess960 game is encoded @@ -1033,18 +1025,18 @@ void Position::do_castle_move(Move m) { // Remove pieces from source squares clear_bit(&byColorBB[us], kfrom); clear_bit(&byTypeBB[KING], kfrom); - clear_bit(&byTypeBB[0], kfrom); + clear_bit(&occupied, kfrom); clear_bit(&byColorBB[us], rfrom); clear_bit(&byTypeBB[ROOK], rfrom); - clear_bit(&byTypeBB[0], rfrom); + clear_bit(&occupied, rfrom); // Put pieces on destination squares set_bit(&byColorBB[us], kto); set_bit(&byTypeBB[KING], kto); - set_bit(&byTypeBB[0], kto); + set_bit(&occupied, kto); set_bit(&byColorBB[us], rto); set_bit(&byTypeBB[ROOK], rto); - set_bit(&byTypeBB[0], rto); + set_bit(&occupied, rto); // Update board Piece king = make_piece(us, KING); @@ -1163,7 +1155,7 @@ void Position::undo_move(Move m) { Bitboard move_bb = make_move_bb(to, from); do_move_bb(&byColorBB[us], move_bb); do_move_bb(&byTypeBB[pt], move_bb); - do_move_bb(&byTypeBB[0], move_bb); // HACK: byTypeBB[0] == occupied squares + do_move_bb(&occupied, move_bb); board[from] = make_piece(us, pt); board[to] = PIECE_NONE; @@ -1185,7 +1177,7 @@ void Position::undo_move(Move m) { // Restore the captured piece set_bit(&byColorBB[them], capsq); set_bit(&byTypeBB[st->capturedType], capsq); - set_bit(&byTypeBB[0], capsq); + set_bit(&occupied, capsq); board[capsq] = make_piece(them, st->capturedType); @@ -1204,62 +1196,49 @@ void Position::undo_move(Move m) { } -/// Position::do_null_move makes() a "null move": It switches the side to move -/// and updates the hash key without executing any move on the board. - +/// Position::do_null_move() is used to do/undo a "null move": It flips the side +/// to move and updates the hash key without executing any move on the board. +template void Position::do_null_move(StateInfo& backupSt) { assert(!in_check()); // Back up the information necessary to undo the null move to the supplied - // StateInfo object. - // Note that differently from normal case here backupSt is actually used as - // a backup storage not as a new state to be used. - backupSt.key = st->key; - backupSt.epSquare = st->epSquare; - backupSt.value = st->value; - backupSt.previous = st->previous; - backupSt.pliesFromNull = st->pliesFromNull; - st->previous = &backupSt; - - // Update the necessary information - if (st->epSquare != SQ_NONE) - st->key ^= zobEp[st->epSquare]; - - st->key ^= zobSideToMove; - prefetch((char*)TT.first_entry(st->key)); + // StateInfo object. Note that differently from normal case here backupSt + // is actually used as a backup storage not as the new state. This reduces + // the number of fields to be copied. + StateInfo* src = Do ? st : &backupSt; + StateInfo* dst = Do ? &backupSt : st; + + dst->key = src->key; + dst->epSquare = src->epSquare; + dst->value = src->value; + dst->rule50 = src->rule50; + dst->pliesFromNull = src->pliesFromNull; sideToMove = flip(sideToMove); - st->epSquare = SQ_NONE; - st->rule50++; - st->pliesFromNull = 0; - st->value += (sideToMove == WHITE) ? TempoValue : -TempoValue; - assert(pos_is_ok()); -} - - -/// Position::undo_null_move() unmakes a "null move". - -void Position::undo_null_move() { - - assert(!in_check()); + if (Do) + { + if (st->epSquare != SQ_NONE) + st->key ^= zobEp[st->epSquare]; - // Restore information from the our backup StateInfo object - StateInfo* backupSt = st->previous; - st->key = backupSt->key; - st->epSquare = backupSt->epSquare; - st->value = backupSt->value; - st->previous = backupSt->previous; - st->pliesFromNull = backupSt->pliesFromNull; + st->key ^= zobSideToMove; + prefetch((char*)TT.first_entry(st->key)); - // Update the necessary information - sideToMove = flip(sideToMove); - st->rule50--; + st->epSquare = SQ_NONE; + st->rule50++; + st->pliesFromNull = 0; + st->value += (sideToMove == WHITE) ? TempoValue : -TempoValue; + } assert(pos_is_ok()); } +// Explicit template instantiations +template void Position::do_null_move(StateInfo& backupSt); +template void Position::do_null_move(StateInfo& backupSt); + /// Position::see() is a static exchange evaluator: It tries to estimate the /// material gain or loss resulting from a move. There are three versions of @@ -1286,7 +1265,7 @@ int Position::see_sign(Move m) const { int Position::see(Move m) const { Square from, to; - Bitboard occupied, attackers, stmAttackers, b; + Bitboard occ, attackers, stmAttackers, b; int swapList[32], slIndex = 1; PieceType capturedType, pt; Color stm; @@ -1302,7 +1281,7 @@ int Position::see(Move m) const { from = move_from(m); to = move_to(m); capturedType = type_of(piece_on(to)); - occupied = occupied_squares(); + occ = occupied_squares(); // Handle en passant moves if (st->epSquare == to && type_of(piece_on(from)) == PAWN) @@ -1313,14 +1292,14 @@ int Position::see(Move m) const { assert(type_of(piece_on(capQq)) == PAWN); // Remove the captured pawn - clear_bit(&occupied, capQq); + clear_bit(&occ, capQq); capturedType = PAWN; } // Find all attackers to the destination square, with the moving piece // removed, but possibly an X-ray attacker added behind it. - clear_bit(&occupied, from); - attackers = attackers_to(to, occupied); + clear_bit(&occ, from); + attackers = attackers_to(to, occ); // If the opponent has no attackers we are finished stm = flip(color_of(piece_on(from))); @@ -1347,11 +1326,11 @@ int Position::see(Move m) const { // Remove the attacker we just found from the 'occupied' bitboard, // and scan for new X-ray attacks behind the attacker. b = stmAttackers & pieces(pt); - occupied ^= (b & (~b + 1)); - attackers |= (rook_attacks_bb(to, occupied) & pieces(ROOK, QUEEN)) - | (bishop_attacks_bb(to, occupied) & pieces(BISHOP, QUEEN)); + occ ^= (b & (~b + 1)); + attackers |= (rook_attacks_bb(to, occ) & pieces(ROOK, QUEEN)) + | (bishop_attacks_bb(to, occ) & pieces(BISHOP, QUEEN)); - attackers &= occupied; // Cut out pieces we've already done + attackers &= occ; // Cut out pieces we've already done // Add the new entry to the swap list assert(slIndex < 32); @@ -1407,6 +1386,7 @@ void Position::clear() { } sideToMove = WHITE; nodes = 0; + occupied = 0; } @@ -1424,7 +1404,7 @@ void Position::put_piece(Piece p, Square s) { set_bit(&byTypeBB[pt], s); set_bit(&byColorBB[c], s); - set_bit(&byTypeBB[0], s); // HACK: byTypeBB[0] contains all occupied squares. + set_bit(&occupied, s); }