X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fposition.cpp;h=5e1ebfeb486880de58081900499f67cd2b4f55b3;hp=abac6efc1ef56e4b57a22734558c5d1c3564348a;hb=c97104e8540b72ee2c6c9c13d3773d2c0f9ec32f;hpb=08265aef81d63b1ccf22e1e1818d0edb64e0528e diff --git a/src/position.cpp b/src/position.cpp index abac6efc..5e1ebfeb 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -52,6 +52,7 @@ Key Position::zobSideToMove; Value Position::MgPieceSquareTable[16][64]; Value Position::EgPieceSquareTable[16][64]; +static bool RequestPending = false; //// //// Functions @@ -272,6 +273,13 @@ void Position::print(Move m) const { static const std::string pieceLetters = " PNBRQK PNBRQK ."; + // Check for reentrancy, as example when called from inside + // MovePicker that is used also here in move_to_san() + if (RequestPending) + return; + + RequestPending = true; + std::cout << std::endl; if (m != MOVE_NONE) { @@ -296,6 +304,8 @@ void Position::print(Move m) const { std::cout << "+---+---+---+---+---+---+---+---+" << std::endl << "Fen is: " << to_fen() << std::endl << "Key is: " << key << std::endl; + + RequestPending = false; } @@ -665,10 +675,12 @@ bool Position::move_is_check(Move m, Bitboard dcCandidates) const { /// Position::move_is_capture() tests whether a move from the current -/// position is a capture. +/// position is a capture. Move must not be MOVE_NONE. bool Position::move_is_capture(Move m) const { + assert(m != MOVE_NONE); + return ( !square_is_empty(move_to(m)) && (color_of_piece_on(move_to(m)) == opposite_color(side_to_move())) ) @@ -1570,10 +1582,16 @@ void Position::undo_null_move(const UndoInfo &u) { /// Position::see() is a static exchange evaluator: It tries to estimate the -/// material gain or loss resulting from a move. There are two versions of -/// this function: One which takes a move as input, and one which takes a -/// 'from' and a 'to' square. The function does not yet understand promotions -/// or en passant captures. +/// 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 or en passant captures. + +int Position::see(Square to) const { + + assert(square_is_ok(to)); + return see(SQ_NONE, to); +} int Position::see(Move m) const { @@ -1583,18 +1601,22 @@ int Position::see(Move m) const { int Position::see(Square from, Square to) const { - // Approximate material values, with pawn = 1 + // Material values static const int seeValues[18] = { - 0, 1, 3, 3, 5, 10, 100, 0, 0, 1, 3, 3, 5, 10, 100, 0, 0, 0 + 0, PawnValueMidgame, KnightValueMidgame, BishopValueMidgame, + RookValueMidgame, QueenValueMidgame, QueenValueMidgame*10, 0, + 0, PawnValueMidgame, KnightValueMidgame, BishopValueMidgame, + RookValueMidgame, QueenValueMidgame, QueenValueMidgame*10, 0, + 0, 0 }; Bitboard attackers, occ, b; - assert(square_is_ok(from)); + assert(square_is_ok(from) || from == SQ_NONE); assert(square_is_ok(to)); // Initialize colors - Color us = color_of_piece_on(from); + Color us = (from != SQ_NONE ? color_of_piece_on(from) : opposite_color(color_of_piece_on(to))); Color them = opposite_color(us); // Initialize pieces @@ -1604,15 +1626,49 @@ int Position::see(Square from, Square to) const { // Find all attackers to the destination square, with the moving piece // removed, but possibly an X-ray attacker added behind it. occ = occupied_squares(); - clear_bit(&occ, from); - attackers = (rook_attacks_bb(to, occ) & rooks_and_queens()) - | (bishop_attacks_bb(to, occ) & bishops_and_queens()) - | (piece_attacks(to) & knights()) - | (piece_attacks(to) & kings()) - | (pawn_attacks(WHITE, to) & pawns(BLACK)) - | (pawn_attacks(BLACK, to) & pawns(WHITE)); - - // If the opponent has no attackers, we are finished + + // Handle enpassant moves + if (ep_square() == to && type_of_piece_on(from) == PAWN) + { + assert(capture == EMPTY); + + Square capQq = (side_to_move() == WHITE)? (to - DELTA_N) : (to - DELTA_S); + capture = piece_on(capQq); + + assert(type_of_piece_on(capQq) == PAWN); + + // Remove the captured pawn + clear_bit(&occ, capQq); + } + + while (true) + { + clear_bit(&occ, from); + attackers = (rook_attacks_bb(to, occ) & rooks_and_queens()) + | (bishop_attacks_bb(to, occ) & bishops_and_queens()) + | (piece_attacks(to) & knights()) + | (piece_attacks(to) & kings()) + | (pawn_attacks(WHITE, to) & pawns(BLACK)) + | (pawn_attacks(BLACK, to) & pawns(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. + PieceType pt; + for (pt = PAWN; !(attackers & pieces_of_color_and_type(us, pt)); pt++) + assert(pt < KING); + + from = first_1(attackers & pieces_of_color_and_type(us, pt)); + piece = piece_on(from); + } + + // If the opponent has no attackers we are finished if ((attackers & pieces_of_color(them)) == EmptyBoardBB) return seeValues[capture];