X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fposition.cpp;h=e7a0017cb033a8e4c15ce407ca1caeb9bb8e73a8;hb=1ae8c59c0bf7cc87d69673de95363bd222ef6642;hp=4e9a6dc7b02388ddae1c8224a9bfd8eeedea2368;hpb=f05d059b17c8c0614517608c1e1f585dc95597e9;p=stockfish diff --git a/src/position.cpp b/src/position.cpp index 4e9a6dc7..e7a0017c 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -213,8 +213,7 @@ void Position::from_fen(const string& fen) { st->key = compute_key(); st->pawnKey = compute_pawn_key(); st->materialKey = compute_material_key(); - st->mgValue = compute_value(); - st->egValue = compute_value(); + st->value = Score(compute_value(), compute_value()); st->npMaterial[WHITE] = compute_non_pawn_material(WHITE); st->npMaterial[BLACK] = compute_non_pawn_material(BLACK); } @@ -458,19 +457,11 @@ void Position::find_checkers() { /// Position::pl_move_is_legal() tests whether a pseudo-legal move is legal -bool Position::pl_move_is_legal(Move m) const { - - // If we're in check, all pseudo-legal moves are legal, because our - // check evasion generator only generates true legal moves. - return is_check() || pl_move_is_legal(m, pinned_pieces(side_to_move())); -} - bool Position::pl_move_is_legal(Move m, Bitboard pinned) const { assert(is_ok()); assert(move_is_ok(m)); assert(pinned == pinned_pieces(side_to_move())); - assert(!is_check()); // Castling moves are checked for legality during move generation. if (move_is_castle(m)) @@ -482,7 +473,7 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const { assert(color_of_piece_on(from) == us); assert(piece_on(king_square(us)) == piece_of_color_and_type(us, KING)); - // En passant captures are a tricky special case. Because they are + // En passant captures are a tricky special case. Because they are // rather uncommon, we do it simply by testing whether the king is attacked // after the move is made if (move_is_ep(m)) @@ -519,6 +510,32 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const { } +/// Position::pl_move_is_evasion() tests whether a pseudo-legal move is a legal evasion + +bool Position::pl_move_is_evasion(Move m, Bitboard pinned) const +{ + assert(is_check()); + + Color us = side_to_move(); + Square from = move_from(m); + Square to = move_to(m); + + // King moves and en-passant captures are verified in pl_move_is_legal() + if (type_of_piece_on(from) == KING || move_is_ep(m)) + return pl_move_is_legal(m, pinned); + + Bitboard target = checkers(); + Square checksq = pop_1st_bit(&target); + + if (target) // double check ? + return false; + + // Our move must be a blocking evasion or a capture of the checking piece + target = squares_between(checksq, king_square(us)) | checkers(); + return bit_is_set(target, to) && pl_move_is_legal(m, pinned); +} + + /// Position::move_is_check() tests whether a pseudo-legal move is a check bool Position::move_is_check(Move m) const { @@ -812,8 +829,7 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) { } // Update incremental scores - st->mgValue += pst_delta(piece, from, to); - st->egValue += pst_delta(piece, from, to); + st->value += Score(pst_delta(piece, from, to), pst_delta(piece, from, to)); if (pm) // promotion ? { @@ -848,10 +864,8 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) { st->pawnKey ^= zobrist[us][PAWN][to]; // Partially revert and update incremental scores - st->mgValue -= pst(us, PAWN, to); - st->mgValue += pst(us, promotion, to); - st->egValue -= pst(us, PAWN, to); - st->egValue += pst(us, promotion, to); + st->value -= Score(pst(us, PAWN, to), pst(us, PAWN, to)); + st->value += Score(pst(us, promotion, to), pst(us, promotion, to)); // Update material st->npMaterial[us] += piece_value_midgame(promotion); @@ -881,9 +895,7 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) { // Finish sideToMove = opposite_color(sideToMove); - - st->mgValue += (sideToMove == WHITE)? TempoValueMidgame : -TempoValueMidgame; - st->egValue += (sideToMove == WHITE)? TempoValueEndgame : -TempoValueEndgame; + st->value += (sideToMove == WHITE) ? TempoValue : -TempoValue; assert(is_ok()); } @@ -919,8 +931,7 @@ void Position::do_capture_move(Bitboard& key, PieceType capture, Color them, Squ key ^= zobrist[them][capture][capsq]; // Update incremental scores - st->mgValue -= pst(them, capture, capsq); - st->egValue -= pst(them, capture, capsq); + st->value -= Score(pst(them, capture, capsq), pst(them, capture, capsq)); // If the captured piece was a pawn, update pawn hash key, // otherwise update non-pawn material. @@ -1017,10 +1028,8 @@ void Position::do_castle_move(Move m) { index[rto] = tmp; // Update incremental scores - st->mgValue += pst_delta(king, kfrom, kto); - st->egValue += pst_delta(king, kfrom, kto); - st->mgValue += pst_delta(rook, rfrom, rto); - st->egValue += pst_delta(rook, rfrom, rto); + st->value += Score(pst_delta(king, kfrom, kto), pst_delta(king, kfrom, kto)); + st->value += Score(pst_delta(rook, rfrom, rto), pst_delta(rook, rfrom, rto)); // Update hash key st->key ^= zobrist[us][KING][kfrom] ^ zobrist[us][KING][kto]; @@ -1046,9 +1055,7 @@ void Position::do_castle_move(Move m) { // Finish sideToMove = opposite_color(sideToMove); - - st->mgValue += (sideToMove == WHITE)? TempoValueMidgame : -TempoValueMidgame; - st->egValue += (sideToMove == WHITE)? TempoValueEndgame : -TempoValueEndgame; + st->value += (sideToMove == WHITE) ? TempoValue : -TempoValue; assert(is_ok()); } @@ -1240,8 +1247,7 @@ void Position::do_null_move(StateInfo& backupSt) { // a backup storage not as a new state to be used. backupSt.key = st->key; backupSt.epSquare = st->epSquare; - backupSt.mgValue = st->mgValue; - backupSt.egValue = st->egValue; + backupSt.value = st->value; backupSt.previous = st->previous; backupSt.pliesFromNull = st->pliesFromNull; st->previous = &backupSt; @@ -1261,10 +1267,8 @@ void Position::do_null_move(StateInfo& backupSt) { st->epSquare = SQ_NONE; st->rule50++; st->pliesFromNull = 0; + st->value += (sideToMove == WHITE) ? TempoValue : -TempoValue; gamePly++; - - st->mgValue += (sideToMove == WHITE)? TempoValueMidgame : -TempoValueMidgame; - st->egValue += (sideToMove == WHITE)? TempoValueEndgame : -TempoValueEndgame; } @@ -1279,8 +1283,7 @@ void Position::undo_null_move() { StateInfo* backupSt = st->previous; st->key = backupSt->key; st->epSquare = backupSt->epSquare; - st->mgValue = backupSt->mgValue; - st->egValue = backupSt->egValue; + st->value = backupSt->value; st->previous = backupSt->previous; st->pliesFromNull = backupSt->pliesFromNull; @@ -1350,6 +1353,10 @@ int Position::see(Square from, Square to) const { Piece capture = piece_on(to); Bitboard occ = occupied_squares(); + // King cannot be recaptured + if (type_of_piece(piece) == KING) + return seeValues[capture]; + // Handle en passant moves if (st->epSquare == to && type_of_piece_on(from) == PAWN) { @@ -1488,8 +1495,8 @@ void Position::clear() { for (int i = 0; i < 64; i++) board[i] = EMPTY; - for (int i = 0; i < 7; i++) - for (int j = 0; j < 8; j++) + for (int i = 0; i < 8; i++) + for (int j = 0; j < 16; j++) pieceList[0][i][j] = pieceList[1][i][j] = SQ_NONE; sideToMove = WHITE; @@ -1642,8 +1649,8 @@ Value Position::compute_value() const { } } - const Value TempoValue = (Phase == MidGame ? TempoValueMidgame : TempoValueEndgame); - result += (side_to_move() == WHITE)? TempoValue / 2 : -TempoValue / 2; + const Value tv = (Phase == MidGame ? TempoValue.mg() : TempoValue.eg()); + result += (side_to_move() == WHITE)? tv / 2 : -tv / 2; return result; } @@ -1701,8 +1708,7 @@ bool Position::is_draw() const { bool Position::is_mate() const { MoveStack moves[256]; - - return is_check() && (generate_evasions(*this, moves, pinned_pieces(sideToMove)) == moves); + return is_check() && (generate_moves(*this, moves, false) == moves); } @@ -1723,11 +1729,10 @@ bool Position::has_mate_threat(Color c) { MoveStack mlist[120]; bool result = false; - Bitboard dc = discovered_check_candidates(sideToMove); Bitboard pinned = pinned_pieces(sideToMove); // Generate pseudo-legal non-capture and capture check moves - MoveStack* last = generate_non_capture_checks(*this, mlist, dc); + MoveStack* last = generate_non_capture_checks(*this, mlist); last = generate_captures(*this, last); // Loop through the moves, and see if one of them is mate @@ -1858,8 +1863,7 @@ void Position::flipped_copy(const Position& pos) { st->materialKey = compute_material_key(); // Incremental scores - st->mgValue = compute_value(); - st->egValue = compute_value(); + st->value = Score(compute_value(), compute_value()); // Material st->npMaterial[WHITE] = compute_non_pawn_material(WHITE); @@ -1988,10 +1992,10 @@ bool Position::is_ok(int* failedStep) const { if (failedStep) (*failedStep)++; if (debugIncrementalEval) { - if (st->mgValue != compute_value()) + if (st->value.mg() != compute_value()) return false; - if (st->egValue != compute_value()) + if (st->value.eg() != compute_value()) return false; }