X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fposition.cpp;h=6e6bf38b3dda159a5703386f3d7e1fe192d693ab;hp=1c1ceed2199eb73c2d4ab4b2620cb34938cbf10d;hb=3376c68f4bb83dc9fd874eb9d710dab09609ae54;hpb=980124c6094f90741a250a40c160efb593244ffb diff --git a/src/position.cpp b/src/position.cpp index 1c1ceed2..6e6bf38b 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -27,6 +27,7 @@ #include #include +#include "bitcount.h" #include "mersenne.h" #include "movegen.h" #include "movepick.h" @@ -35,6 +36,8 @@ #include "san.h" #include "ucioption.h" +using std::string; + //// //// Variables @@ -63,7 +66,7 @@ Position::Position(const Position& pos) { copy(pos); } -Position::Position(const std::string& fen) { +Position::Position(const string& fen) { from_fen(fen); } @@ -72,9 +75,9 @@ Position::Position(const std::string& 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). -void Position::from_fen(const std::string& fen) { +void Position::from_fen(const string& fen) { - static const std::string pieceLetters = "KQRBNPkqrbnp"; + static const string pieceLetters = "KQRBNPkqrbnp"; static const Piece pieces[] = { WK, WQ, WR, WB, WN, WP, BK, BQ, BR, BB, BN, BP }; clear(); @@ -98,7 +101,7 @@ void Position::from_fen(const std::string& fen) { continue; } size_t idx = pieceLetters.find(fen[i]); - if (idx == std::string::npos) + if (idx == string::npos) { std::cout << "Error in FEN at character " << i << std::endl; return; @@ -211,18 +214,18 @@ void Position::from_fen(const std::string& fen) { st->materialKey = compute_material_key(); st->mgValue = compute_value(); st->egValue = compute_value(); - npMaterial[WHITE] = compute_non_pawn_material(WHITE); - npMaterial[BLACK] = compute_non_pawn_material(BLACK); + st->npMaterial[WHITE] = compute_non_pawn_material(WHITE); + st->npMaterial[BLACK] = compute_non_pawn_material(BLACK); } /// Position::to_fen() converts the position object to a FEN string. This is /// probably only useful for debugging. -const std::string Position::to_fen() const { +const string Position::to_fen() const { - static const std::string pieceLetters = " PNBRQK pnbrqk"; - std::string fen; + static const string pieceLetters = " PNBRQK pnbrqk"; + string fen; int skip; for (Rank rank = RANK_8; rank >= RANK_1; rank--) @@ -272,7 +275,7 @@ const std::string Position::to_fen() const { void Position::print(Move m) const { - static const std::string pieceLetters = " PNBRQK PNBRQK ."; + static const string pieceLetters = " PNBRQK PNBRQK ."; // Check for reentrancy, as example when called from inside // MovePicker that is used also here in move_to_san() @@ -284,7 +287,7 @@ void Position::print(Move m) const { std::cout << std::endl; if (m != MOVE_NONE) { - std::string col = (color_of_piece_on(move_from(m)) == BLACK ? ".." : ""); + string col = (color_of_piece_on(move_from(m)) == BLACK ? ".." : ""); std::cout << "Move is: " << col << move_to_san(*this, m) << std::endl; } for (Rank rank = RANK_8; rank >= RANK_1; rank--) @@ -375,9 +378,7 @@ Bitboard Position::discovered_check_candidates(Color c) const { } /// Position::attacks_to() computes a bitboard containing all pieces which -/// attacks a given square. There are two versions of this function: One -/// which finds attackers of both colors, and one which only finds the -/// attackers for one side. +/// attacks a given square. Bitboard Position::attacks_to(Square s) const { @@ -656,6 +657,7 @@ inline void Position::update_checkers(Bitboard* pCheckersBB, Square ksq, Square const bool Rook = (Piece == QUEEN || Piece == ROOK); const bool Slider = Bishop || Rook; + // Direct checks if ( ( (Bishop && bit_is_set(BishopPseudoAttacks[ksq], to)) || (Rook && bit_is_set(RookPseudoAttacks[ksq], to))) && bit_is_set(piece_attacks(ksq), to)) // slow, try to early skip @@ -666,6 +668,7 @@ inline void Position::update_checkers(Bitboard* pCheckersBB, Square ksq, Square && bit_is_set(piece_attacks(ksq), to)) set_bit(pCheckersBB, to); + // Discovery checks if (Piece != QUEEN && bit_is_set(dcCandidates, from)) { if (Piece != ROOK) @@ -699,6 +702,7 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) { int castleRights, rule50; Square epSquare; Value mgValue, egValue; + Value npMaterial[2]; }; memcpy(&newSt, st, sizeof(ReducedStateInfo)); @@ -738,12 +742,11 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) { do_capture_move(st->capture, them, to); // Move the piece - clear_bit(&(byColorBB[us]), from); - clear_bit(&(byTypeBB[piece]), from); - clear_bit(&(byTypeBB[0]), from); // HACK: byTypeBB[0] == occupied squares - set_bit(&(byColorBB[us]), to); - set_bit(&(byTypeBB[piece]), to); - set_bit(&(byTypeBB[0]), to); // HACK: byTypeBB[0] == occupied squares + Bitboard move_bb = make_move_bb(from, to); + do_move_bb(&(byColorBB[us]), move_bb); + do_move_bb(&(byTypeBB[piece]), move_bb); + do_move_bb(&(byTypeBB[0]), move_bb); // HACK: byTypeBB[0] == occupied squares + board[to] = board[from]; board[from] = EMPTY; @@ -835,6 +838,7 @@ void Position::do_capture_move(PieceType capture, Color them, Square to) { // Remove captured piece clear_bit(&(byColorBB[them]), to); clear_bit(&(byTypeBB[capture]), to); + clear_bit(&(byTypeBB[0]), to); // Update hash key st->key ^= zobrist[them][capture][to]; @@ -849,7 +853,7 @@ void Position::do_capture_move(PieceType capture, Color them, Square to) { // Update material if (capture != PAWN) - npMaterial[them] -= piece_value_midgame(capture); + st->npMaterial[them] -= piece_value_midgame(capture); // Update material hash key st->materialKey ^= zobMaterial[them][capture][pieceCount[them][capture]]; @@ -988,7 +992,7 @@ void Position::do_promotion_move(Move m) { st->capture = type_of_piece_on(to); if (st->capture) - do_capture_move(st->capture, them, to); + do_capture_move(st->capture, them, to); // Remove pawn clear_bit(&(byColorBB[us]), from); @@ -1031,7 +1035,7 @@ void Position::do_promotion_move(Move m) { st->egValue += pst(us, promotion, to); // Update material - npMaterial[us] += piece_value_midgame(promotion); + st->npMaterial[us] += piece_value_midgame(promotion); // Clear the en passant square if (st->epSquare != SQ_NONE) @@ -1077,21 +1081,17 @@ void Position::do_ep_move(Move m) { assert(piece_on(from) == piece_of_color_and_type(us, PAWN)); assert(piece_on(capsq) == piece_of_color_and_type(them, PAWN)); - // Remove captured piece + // 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; - // Remove moving piece from source square - clear_bit(&(byColorBB[us]), from); - clear_bit(&(byTypeBB[PAWN]), from); - clear_bit(&(byTypeBB[0]), from); // HACK: byTypeBB[0] == occupied squares - - // Put moving piece on destination square - set_bit(&(byColorBB[us]), to); - set_bit(&(byTypeBB[PAWN]), to); - set_bit(&(byTypeBB[0]), to); // HACK: byTypeBB[0] == occupied squares + // 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; @@ -1167,17 +1167,13 @@ void Position::undo_move(Move m) { assert(color_of_piece_on(to) == us); // Put the piece back at the source square + Bitboard move_bb = make_move_bb(to, from); piece = type_of_piece_on(to); - set_bit(&(byColorBB[us]), from); - set_bit(&(byTypeBB[piece]), from); - set_bit(&(byTypeBB[0]), from); // HACK: byTypeBB[0] == occupied squares + do_move_bb(&(byColorBB[us]), move_bb); + do_move_bb(&(byTypeBB[piece]), move_bb); + do_move_bb(&(byTypeBB[0]), move_bb); // HACK: byTypeBB[0] == occupied squares board[from] = piece_of_color_and_type(us, piece); - // Clear the destination square - clear_bit(&(byColorBB[us]), to); - clear_bit(&(byTypeBB[piece]), to); - clear_bit(&(byTypeBB[0]), to); // HACK: byTypeBB[0] == occupied squares - // If the moving piece was a king, update the king square if (piece == KING) kingSquare[us] = from; @@ -1190,16 +1186,12 @@ void Position::undo_move(Move m) { { assert(st->capture != KING); - // Replace the captured piece + // Restore the captured piece set_bit(&(byColorBB[them]), to); set_bit(&(byTypeBB[st->capture]), to); set_bit(&(byTypeBB[0]), to); board[to] = piece_of_color_and_type(them, st->capture); - // Update material - if (st->capture != PAWN) - npMaterial[them] += piece_value_midgame(st->capture); - // Update piece list pieceList[them][st->capture][pieceCount[them][st->capture]] = to; index[to] = pieceCount[them][st->capture]; @@ -1321,9 +1313,6 @@ void Position::undo_promotion_move(Move m) { set_bit(&(byTypeBB[0]), from); // HACK: byTypeBB[0] == occupied squares board[from] = piece_of_color_and_type(us, PAWN); - // Update material - npMaterial[us] -= piece_value_midgame(promotion); - // Update piece list pieceList[us][PAWN][pieceCount[us][PAWN]] = from; index[from] = pieceCount[us][PAWN]; @@ -1345,11 +1334,6 @@ void Position::undo_promotion_move(Move m) { set_bit(&(byTypeBB[0]), to); // HACK: byTypeBB[0] == occupied squares board[to] = piece_of_color_and_type(them, st->capture); - // Update material. Because the move is a promotion move, we know - // that the captured piece cannot be a pawn. - assert(st->capture != PAWN); - npMaterial[them] += piece_value_midgame(st->capture); - // Update piece list pieceList[them][st->capture][pieceCount[them][st->capture]] = to; index[to] = pieceCount[them][st->capture]; @@ -1384,31 +1368,27 @@ void Position::undo_ep_move(Move m) { assert(piece_on(from) == EMPTY); assert(piece_on(capsq) == EMPTY); - // Replace captured piece + // Restore captured pawn set_bit(&(byColorBB[them]), capsq); set_bit(&(byTypeBB[PAWN]), capsq); set_bit(&(byTypeBB[0]), capsq); board[capsq] = piece_of_color_and_type(them, PAWN); - // Remove moving piece from destination square - clear_bit(&(byColorBB[us]), to); - clear_bit(&(byTypeBB[PAWN]), to); - clear_bit(&(byTypeBB[0]), to); + // Move capturing pawn back to source square + Bitboard move_bb = make_move_bb(to, from); + do_move_bb(&(byColorBB[us]), move_bb); + do_move_bb(&(byTypeBB[PAWN]), move_bb); + do_move_bb(&(byTypeBB[0]), move_bb); board[to] = EMPTY; - - // Replace moving piece at source square - set_bit(&(byColorBB[us]), from); - set_bit(&(byTypeBB[PAWN]), from); - set_bit(&(byTypeBB[0]), from); board[from] = piece_of_color_and_type(us, PAWN); - // Update piece list: + // Update piece list pieceList[us][PAWN][index[to]] = from; index[from] = index[to]; pieceList[them][PAWN][pieceCount[them][PAWN]] = capsq; index[capsq] = pieceCount[them][PAWN]; - // Update piece count: + // Update piece count pieceCount[them][PAWN]++; } @@ -1422,12 +1402,13 @@ void Position::do_null_move(StateInfo& backupSt) { assert(!is_check()); // Back up the information necessary to undo the null move to the supplied - // StateInfo object. In the case of a null move, the only thing we need to - // remember is the last move made and the en passant square. + // 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.lastMove = st->lastMove; backupSt.epSquare = st->epSquare; + backupSt.key = st->key; + backupSt.mgValue = st->mgValue; + backupSt.egValue = st->egValue; backupSt.previous = st->previous; st->previous = &backupSt; @@ -1460,21 +1441,16 @@ void Position::undo_null_move() { assert(!is_check()); // Restore information from the our backup StateInfo object - st->lastMove = st->previous->lastMove; st->epSquare = st->previous->epSquare; + st->key = st->previous->key; + st->mgValue = st->previous->mgValue; + st->egValue = st->previous->egValue; st->previous = st->previous->previous; - if (st->epSquare != SQ_NONE) - st->key ^= zobEp[st->epSquare]; - // Update the necessary information sideToMove = opposite_color(sideToMove); st->rule50--; gamePly--; - st->key ^= zobSideToMove; - - st->mgValue += (sideToMove == WHITE)? TempoValueMidgame : -TempoValueMidgame; - st->egValue += (sideToMove == WHITE)? TempoValueEndgame : -TempoValueEndgame; assert(is_ok()); } @@ -2041,8 +2017,8 @@ void Position::flipped_copy(const Position &pos) { st->egValue = compute_value(); // Material - npMaterial[WHITE] = compute_non_pawn_material(WHITE); - npMaterial[BLACK] = compute_non_pawn_material(BLACK); + st->npMaterial[WHITE] = compute_non_pawn_material(WHITE); + st->npMaterial[BLACK] = compute_non_pawn_material(BLACK); assert(is_ok()); } @@ -2115,7 +2091,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(st->checkersBB) > 2) return false; // Bitboards OK? @@ -2178,10 +2154,10 @@ bool Position::is_ok(int* failedStep) const { if (failedStep) (*failedStep)++; if (debugNonPawnMaterial) { - if (npMaterial[WHITE] != compute_non_pawn_material(WHITE)) + if (st->npMaterial[WHITE] != compute_non_pawn_material(WHITE)) return false; - if (npMaterial[BLACK] != compute_non_pawn_material(BLACK)) + if (st->npMaterial[BLACK] != compute_non_pawn_material(BLACK)) return false; } @@ -2190,7 +2166,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_of_color_and_type(c, pt))) + if (pieceCount[c][pt] != count_1s(pieces_of_color_and_type(c, pt))) return false; if (failedStep) (*failedStep)++;