X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fposition.cpp;h=0a275b5ee3bdc4e7dfb48fe3b8e8d2f835cced48;hp=0a7ebadda7f3b5614668781f715f6c067cc7ad3f;hb=962216440c186d067d8946112acab847ccb7249f;hpb=0bf45823da3d76d25d0e3cfdf131bf8823ecb58e diff --git a/src/position.cpp b/src/position.cpp index 0a7ebadd..0a275b5e 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -23,8 +23,9 @@ //// #include -#include +#include #include +#include #include "mersenne.h" #include "movegen.h" @@ -676,6 +677,25 @@ inline void Position::update_checkers(Bitboard* pCheckersBB, Square ksq, Square } +/// Position::init_new_state() copies from the current state the fields +/// that will be updated incrementally, skips the fields, like bitboards +/// that will be recalculated form scratch anyway. + +void Position::init_new_state(StateInfo& newSt) { + + newSt.key = st->key; + newSt.pawnKey = st->pawnKey; + newSt.materialKey = st->materialKey; + newSt.castleRights = st->castleRights; + newSt.rule50 = st->rule50; + newSt.epSquare = st->epSquare; + newSt.mgValue = st->mgValue; + newSt.egValue = st->egValue; + newSt.capture = NO_PIECE_TYPE; + newSt.previous = st; +} + + /// Position::do_move() makes a move, and saves all information necessary /// to a StateInfo object. The move is assumed to be legal. /// Pseudo-legal moves should be filtered out before this function is called. @@ -685,17 +705,14 @@ void Position::do_move(Move m, StateInfo& newSt) { assert(is_ok()); assert(move_is_ok(m)); - // Get now the current (pre-move) dc candidates that we will use + // Get now the current (before to move) dc candidates that we will use // in update_checkers(). Bitboard oldDcCandidates = discovered_check_candidates(side_to_move()); - // Copy the old state to our new StateInfo object (except the - // captured piece, which is taken care of later. - // TODO do not copy pinners and checkersBB because are recalculated - // anyway. - newSt = *st; - newSt.capture = NO_PIECE_TYPE; - newSt.previous = st; + // Copy some fields of old state to our new StateInfo object (except the + // captured piece, which is taken care of later) and switch state pointer + // to point to the new, ready to be updated, state. + init_new_state(newSt); st = &newSt; // Save the current key to the history[] array, in order to be able to @@ -1474,7 +1491,7 @@ void Position::undo_null_move() { /// 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 +/// material gain or loss resulting from a move. There are three versions of /// this function: One which takes a destination square as input, one takes a /// move, and one which takes a 'from' and a 'to' square. The function does /// not yet understand promotions captures. @@ -1511,6 +1528,11 @@ int Position::see(Square from, Square to) const { Color us = (from != SQ_NONE ? color_of_piece_on(from) : opposite_color(color_of_piece_on(to))); Color them = opposite_color(us); + // Initialize pinned and pinners bitboards + Bitboard pinned[2], pinners[2]; + pinned[us] = pinned_pieces(us, pinners[us]); + pinned[them] = pinned_pieces(them, pinners[them]); + // Initialize pieces Piece piece = piece_on(from); Piece capture = piece_on(to); @@ -1543,6 +1565,17 @@ int Position::see(Square from, Square to) const { | (pawn_attacks(WHITE, to) & pawns(BLACK)) | (pawn_attacks(BLACK, to) & pawns(WHITE)); + // Remove our pinned pieces from attacks if the captured piece is not + // a pinner, otherwise we could remove a valid "capture the pinner" attack. + if (pinned[us] != EmptyBoardBB && !bit_is_set(pinners[us], to)) + attackers &= ~pinned[us]; + + // Remove opponent pinned pieces from attacks if the moving piece is not + // a pinner, otherwise we could remove a piece that is no more pinned + // due to our pinner piece is moving away. + if (pinned[them] != EmptyBoardBB && !bit_is_set(pinners[them], from)) + attackers &= ~pinned[them]; + if (from != SQ_NONE) break; @@ -1580,7 +1613,7 @@ int Position::see(Square from, Square to) const { swapList[0] = seeValues[capture]; do { - // Locate the least valuable attacker for the side to move. The loop + // Locate the least valuable attacker for the side to move. The loop // below looks like it is potentially infinite, but it isn't. We know // that the side to move still has at least one attacker left. for (pt = PAWN; !(attackers & pieces_of_color_and_type(c, pt)); pt++) @@ -1605,6 +1638,12 @@ int Position::see(Square from, Square to) const { lastCapturingPieceValue = seeValues[pt]; c = opposite_color(c); + // Remove pinned pieces from attackers + if ( pinned[c] != EmptyBoardBB + && !bit_is_set(pinners[c], to) + && !(pinners[c] & attackers)) + attackers &= ~pinned[c]; + // Stop after a king capture if (pt == KING && (attackers & pieces_of_color(c))) { @@ -1629,16 +1668,14 @@ int Position::see(Square from, Square to) const { void Position::clear() { st = &startState; - st->previous = NULL; // We should never dereference this + memset(st, 0, sizeof(StateInfo)); + st->epSquare = SQ_NONE; + + memset(index, 0, sizeof(int) * 64); + memset(byColorBB, 0, sizeof(Bitboard) * 2); for (int i = 0; i < 64; i++) - { board[i] = EMPTY; - index[i] = 0; - } - - for (int i = 0; i < 2; i++) - byColorBB[i] = EmptyBoardBB; for (int i = 0; i < 7; i++) { @@ -1648,21 +1685,11 @@ void Position::clear() { pieceList[0][i][j] = pieceList[1][i][j] = SQ_NONE; } - st->checkersBB = EmptyBoardBB; - for (Color c = WHITE; c <= BLACK; c++) - st->pinners[c] = st->pinned[c] = st->dcCandidates[c] = ~EmptyBoardBB; - sideToMove = WHITE; gamePly = 0; initialKFile = FILE_E; initialKRFile = FILE_H; initialQRFile = FILE_A; - - st->lastMove = MOVE_NONE; - st->castleRights = NO_CASTLES; - st->epSquare = SQ_NONE; - st->rule50 = 0; - st->previous = NULL; }