X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fposition.cpp;h=71a3074608ee75fda8996486ddba03762dc4b603;hp=f0d15d734aa0c2625dacaa3210c9480835911fc8;hb=038235ba3541087e2db969a0a4bdfd5fc2a42b44;hpb=4397e6c03e72881a0a477c61c7d17c040c6fdb92 diff --git a/src/position.cpp b/src/position.cpp index f0d15d73..71a30746 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -235,7 +235,7 @@ const std::string Position::to_fen() const { fen += (char)skip + '0'; skip = 0; } - fen += pieceLetters[piece_on(sq)]; + fen += pieceLetters[piece_on(sq)]; } if (skip > 0) fen += (char)skip + '0'; @@ -327,7 +327,7 @@ Bitboard Position::hidden_checks(Color c, Square ksq) const { Square s; Bitboard sliders, result = EmptyBoardBB; - + if (Piece == ROOK) // Resolved at compile time sliders = rooks_and_queens(FindPinned ? opposite_color(c) : c) & RookPseudoAttacks[ksq]; else @@ -338,7 +338,7 @@ Bitboard Position::hidden_checks(Color c, Square ksq) const { // King blockers are candidate pinned pieces Bitboard candidate_pinned = piece_attacks(ksq) & pieces_of_color(c); - // Pinners are sliders, not checkers, that give check when + // Pinners are sliders, not checkers, that give check when // candidate pinned are removed. Bitboard pinners = (FindPinned ? sliders & ~checkersBB : sliders); @@ -410,7 +410,6 @@ bool Position::piece_attacks_square(Square f, Square t) const { case WR: case BR: return piece_attacks_square(f, t); case WQ: case BQ: return piece_attacks_square(f, t); case WK: case BK: return piece_attacks_square(f, t); - default: return false; } return false; } @@ -438,7 +437,6 @@ bool Position::move_attacks_square(Move m, Square s) const { case WR: case BR: return piece_attacks_square(t, s); case WQ: case BQ: return piece_attacks_square(t, s); case WK: case BK: return piece_attacks_square(t, s); - default: assert(false); } return false; } @@ -447,12 +445,13 @@ bool Position::move_attacks_square(Move m, Square s) const { /// Position::find_checkers() computes the checkersBB bitboard, which /// contains a nonzero bit for each checking piece (0, 1 or 2). It /// currently works by calling Position::attacks_to, which is probably -/// inefficient. Consider rewriting this function to use the last move +/// inefficient. Consider rewriting this function to use the last move /// played, like in non-bitboard versions of Glaurung. void Position::find_checkers() { - checkersBB = attacks_to(king_square(side_to_move()),opposite_color(side_to_move())); + Color us = side_to_move(); + checkersBB = attacks_to(king_square(us), opposite_color(us)); } @@ -469,9 +468,6 @@ bool Position::pl_move_is_legal(Move m) const { bool Position::pl_move_is_legal(Move m, Bitboard pinned) const { - Color us, them; - Square ksq, from; - assert(is_ok()); assert(move_is_ok(m)); assert(pinned == pinned_pieces(side_to_move())); @@ -485,10 +481,10 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const { if (move_is_castle(m)) return true; - us = side_to_move(); - them = opposite_color(us); - from = move_from(m); - ksq = king_square(us); + Color us = side_to_move(); + Color them = opposite_color(us); + Square from = move_from(m); + Square ksq = king_square(us); assert(color_of_piece_on(from) == us); assert(piece_on(ksq) == king_of_color(us)); @@ -522,11 +518,8 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const { // A non-king move is legal if and only if it is not pinned or it // is moving along the ray towards or away from the king. - if ( !bit_is_set(pinned, from) - || (direction_between_squares(from, ksq) == direction_between_squares(move_to(m), ksq))) - return true; - - return false; + return ( !bit_is_set(pinned, from) + || (direction_between_squares(from, ksq) == direction_between_squares(move_to(m), ksq))); } @@ -544,18 +537,15 @@ bool Position::move_is_check(Move m) const { bool Position::move_is_check(Move m, Bitboard dcCandidates) const { - Color us, them; - Square ksq, from, to; - assert(is_ok()); assert(move_is_ok(m)); assert(dcCandidates == discovered_check_candidates(side_to_move())); - us = side_to_move(); - them = opposite_color(us); - from = move_from(m); - to = move_to(m); - ksq = king_square(them); + Color us = side_to_move(); + Color them = opposite_color(us); + Square from = move_from(m); + Square to = move_to(m); + Square ksq = king_square(them); assert(color_of_piece_on(from) == us); assert(piece_on(ksq) == king_of_color(them)); @@ -564,14 +554,14 @@ bool Position::move_is_check(Move m, Bitboard dcCandidates) const { switch (type_of_piece_on(from)) { case PAWN: - + if (bit_is_set(pawn_attacks(them, ksq), to)) // Normal check? return true; - + if ( bit_is_set(dcCandidates, from) // Discovered check? && (direction_between_squares(from, ksq) != direction_between_squares(to, ksq))) return true; - + if (move_promotion(m)) // Promotion with check? { Bitboard b = occupied_squares(); @@ -607,7 +597,7 @@ bool Position::move_is_check(Move m, Bitboard dcCandidates) const { } return false; - case KNIGHT: + case KNIGHT: return bit_is_set(dcCandidates, from) // Discovered check? || bit_is_set(piece_attacks(ksq), to); // Normal check? @@ -621,7 +611,7 @@ bool Position::move_is_check(Move m, Bitboard dcCandidates) const { case QUEEN: // Discovered checks are impossible! - assert(!bit_is_set(dcCandidates, from)); + assert(!bit_is_set(dcCandidates, from)); return bit_is_set(piece_attacks(ksq), to); // Normal check? case KING: @@ -653,9 +643,6 @@ bool Position::move_is_check(Move m, Bitboard dcCandidates) const { return bit_is_set(rook_attacks_bb(rto, b), ksq); } return false; - - default: - assert(false); } assert(false); return false; @@ -667,8 +654,10 @@ bool Position::move_is_check(Move m, Bitboard dcCandidates) const { bool Position::move_is_capture(Move m) const { - return color_of_piece_on(move_to(m)) == opposite_color(side_to_move()) - || move_is_ep(m); + return ( !square_is_empty(move_to(m)) + && (color_of_piece_on(move_to(m)) == opposite_color(side_to_move())) + ) + || move_is_ep(m); } @@ -682,16 +671,16 @@ bool Position::move_is_capture(Move m) const { void Position::backup(UndoInfo& u) const { u.castleRights = castleRights; - u.epSquare = epSquare; - u.checkersBB = checkersBB; - u.key = key; - u.pawnKey = pawnKey; - u.materialKey = materialKey; - u.rule50 = rule50; - u.lastMove = lastMove; - u.capture = NO_PIECE_TYPE; - u.mgValue = mgValue; - u.egValue = egValue; + u.epSquare = epSquare; + u.checkersBB = checkersBB; + u.key = key; + u.pawnKey = pawnKey; + u.materialKey = materialKey; + u.rule50 = rule50; + u.lastMove = lastMove; + u.mgValue = mgValue; + u.egValue = egValue; + u.capture = NO_PIECE_TYPE; } @@ -701,25 +690,24 @@ void Position::backup(UndoInfo& u) const { void Position::restore(const UndoInfo& u) { castleRights = u.castleRights; - epSquare = u.epSquare; - checkersBB = u.checkersBB; - key = u.key; - pawnKey = u.pawnKey; - materialKey = u.materialKey; - rule50 = u.rule50; - lastMove = u.lastMove; + epSquare = u.epSquare; + checkersBB = u.checkersBB; + key = u.key; + pawnKey = u.pawnKey; + materialKey = u.materialKey; + rule50 = u.rule50; + lastMove = u.lastMove; + mgValue = u.mgValue; + egValue = u.egValue; // u.capture is restored in undo_move() - mgValue = u.mgValue; - egValue = u.egValue; } - /// Position::do_move() makes a move, and backs up all information necessary -/// to undo the move to an UndoInfo object. The move is assumed to be legal. +/// to undo the move to an UndoInfo object. The move is assumed to be legal. /// Pseudo-legal moves should be filtered out before this function is called. /// There are two versions of this function, one which takes only the move and /// the UndoInfo as input, and one which takes a third parameter, a bitboard of -/// discovered check candidates. The second version is faster, because knowing +/// discovered check candidates. The second version is faster, because knowing /// the discovered check candidates makes it easier to update the checkersBB /// member variable in the position object. @@ -766,42 +754,8 @@ void Position::do_move(Move m, UndoInfo& u, Bitboard dcCandidates) { if (capture) { - assert(capture != KING); - - // Remove captured piece - clear_bit(&(byColorBB[them]), to); - clear_bit(&(byTypeBB[capture]), to); - - // Update hash key - key ^= zobrist[them][capture][to]; - - // If the captured piece was a pawn, update pawn hash key - if (capture == PAWN) - pawnKey ^= zobrist[them][PAWN][to]; - - // Update incremental scores - mgValue -= mg_pst(them, capture, to); - egValue -= eg_pst(them, capture, to); - - // Update material - if (capture != PAWN) - npMaterial[them] -= piece_value_midgame(capture); - - // Update material hash key - materialKey ^= zobMaterial[them][capture][pieceCount[them][capture]]; - - // Update piece count - 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]; - - // Remember the captured piece, in order to be able to undo the move correctly - u.capture = capture; - - // Reset rule 50 counter - rule50 = 0; + u.capture = capture; + do_capture_move(m, capture, them, to); } // Move the piece @@ -932,8 +886,51 @@ void Position::do_move(Move m, UndoInfo& u, 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(Move m, PieceType capture, Color them, Square to) { + + assert(capture != KING); + + // Remove captured piece + clear_bit(&(byColorBB[them]), to); + clear_bit(&(byTypeBB[capture]), to); + + // Update hash key + key ^= zobrist[them][capture][to]; + + // If the captured piece was a pawn, update pawn hash key + if (capture == PAWN) + pawnKey ^= zobrist[them][PAWN][to]; + + // Update incremental scores + mgValue -= mg_pst(them, capture, to); + egValue -= eg_pst(them, capture, to); + + assert(!move_promotion(m) || capture != PAWN); + + // Update material + if (capture != PAWN) + npMaterial[them] -= piece_value_midgame(capture); + + // Update material hash key + materialKey ^= zobMaterial[them][capture][pieceCount[them][capture]]; + + // Update piece count + 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]; + + // Reset rule 50 counter + rule50 = 0; +} + + /// Position::do_castle_move() is a private method used to make a castling -/// move. It is called from the main Position::do_move function. Note that +/// move. It is called from the main Position::do_move function. Note that /// castling moves are encoded as "king captures friendly rook" moves, for /// instance white short castling in a non-Chess960 game is encoded as e1h1. @@ -1057,36 +1054,8 @@ void Position::do_promotion_move(Move m, UndoInfo &u) { if (capture) { - assert(capture != KING); - - // Remove captured piece - clear_bit(&(byColorBB[them]), to); - clear_bit(&(byTypeBB[capture]), to); - - // Update hash key - key ^= zobrist[them][capture][to]; - - // Update incremental scores - mgValue -= mg_pst(them, capture, to); - egValue -= eg_pst(them, capture, to); - - // Update material. Because our move is a promotion, we know that the - // captured piece is not a pawn. - assert(capture != PAWN); - npMaterial[them] -= piece_value_midgame(capture); - - // Update material hash key - materialKey ^= zobMaterial[them][capture][pieceCount[them][capture]]; - - // Update piece count - 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]; - - // Remember the captured piece, in order to be able to undo the move correctly u.capture = capture; + do_capture_move(m, capture, them, to); } // Remove pawn @@ -1144,7 +1113,7 @@ void Position::do_promotion_move(Move m, UndoInfo &u) { castleRights &= castleRightsMask[to]; key ^= zobCastle[castleRights]; - // Reset rule 50 counter + // Reset rule 50 counter rule50 = 0; // Update checkers BB @@ -1337,7 +1306,6 @@ void Position::undo_castle_move(Move m) { // Position::undo_move. In particular, the side to move has been switched, // so the code below is correct. Color us = side_to_move(); - Color them = opposite_color(us); // Find source squares for king and rook Square kfrom = move_from(m); @@ -1396,7 +1364,7 @@ void Position::undo_castle_move(Move m) { /// Position::do_move, is used to put back the captured piece (if any). void Position::undo_promotion_move(Move m, const UndoInfo &u) { - + Color us, them; Square from, to; PieceType capture, promotion; @@ -1629,16 +1597,16 @@ int Position::see(Square from, Square to) const { | (pawn_attacks(WHITE, to) & pawns(BLACK)) | (pawn_attacks(BLACK, to) & pawns(WHITE)); - attackers &= occ; // Re-add removed piece - // If the opponent has no attackers, we are finished if ((attackers & pieces_of_color(them)) == EmptyBoardBB) return seeValues[capture]; + attackers &= occ; // Remove the moving piece + // The destination square is defended, which makes things rather more // difficult to compute. We proceed by building up a "swap list" containing // the material gain or loss at each stop in a sequence of captures to the - // destianation square, where the sides alternately capture, and always + // destination square, where the sides alternately capture, and always // capture with the least valuable piece. After each capture, we look for // new X-ray attacks from behind the capturing piece. int lastCapturingPieceValue = seeValues[piece]; @@ -2249,7 +2217,7 @@ bool Position::is_ok(int* failedStep) const { { if (mgValue != compute_mg_value()) return false; - + if (egValue != compute_eg_value()) return false; }