X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fposition.cpp;h=874c7545bf4dc31b1745a920ba6f7bcbef2106d6;hp=6e6bf38b3dda159a5703386f3d7e1fe192d693ab;hb=4251eac8601af47d1ee2d6f613f00a4bf00fedbb;hpb=3376c68f4bb83dc9fd874eb9d710dab09609ae54 diff --git a/src/position.cpp b/src/position.cpp index 6e6bf38b..874c7545 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -34,6 +34,7 @@ #include "position.h" #include "psqtab.h" #include "san.h" +#include "tt.h" #include "ucioption.h" using std::string; @@ -71,6 +72,14 @@ Position::Position(const string& fen) { } +/// Position::setTranspositionTable() is used by search functions to pass +/// the pointer to the used TT so that do_move() will prefetch TT access. + +void Position::setTranspositionTable(TranspositionTable* tt) { + TT = tt; +} + + /// Position::from_fen() initializes the position object with the given 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). @@ -315,9 +324,10 @@ void Position::print(Move m) const { /// Position::copy() creates a copy of the input position. -void Position::copy(const Position &pos) { +void Position::copy(const Position& pos) { memcpy(this, &pos, sizeof(Position)); + saveState(); // detach and copy state info } @@ -554,12 +564,12 @@ bool Position::move_is_check(Move m, Bitboard dcCandidates) const { && (direction_between_squares(from, ksq) != direction_between_squares(to, ksq))) return true; - if (move_promotion(m)) // Promotion with check? + if (move_is_promotion(m)) // Promotion with check? { Bitboard b = occupied_squares(); clear_bit(&b, from); - switch (move_promotion(m)) + switch (move_promotion_piece(m)) { case KNIGHT: return bit_is_set(piece_attacks(to), ksq); @@ -720,7 +730,7 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) { if (move_is_castle(m)) do_castle_move(m); - else if (move_promotion(m)) + else if (move_is_promotion(m)) do_promotion_move(m); else if (move_is_ep(m)) do_ep_move(m); @@ -734,34 +744,17 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) { assert(color_of_piece_on(from) == us); assert(color_of_piece_on(to) == them || piece_on(to) == EMPTY); - PieceType piece = type_of_piece_on(from); + Piece piece = piece_on(from); + PieceType pt = type_of_piece(piece); st->capture = type_of_piece_on(to); if (st->capture) do_capture_move(st->capture, them, to); - // Move the piece - 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; - // Update hash key - st->key ^= zobrist[us][piece][from] ^ zobrist[us][piece][to]; - - // Update incremental scores - st->mgValue -= pst(us, piece, from); - st->mgValue += pst(us, piece, to); - st->egValue -= pst(us, piece, from); - st->egValue += pst(us, piece, to); - - // If the moving piece was a king, update the king square - if (piece == KING) - kingSquare[us] = to; + st->key ^= zobrist[us][pt][from] ^ zobrist[us][pt][to]; + st->key ^= zobSideToMove; // Reset en passant square if (st->epSquare != SQ_NONE) @@ -770,8 +763,32 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) { st->epSquare = SQ_NONE; } + // Update castle rights, try to shortcut a common case + if ((castleRightsMask[from] & castleRightsMask[to]) != ALL_CASTLES) + { + st->key ^= zobCastle[st->castleRights]; + st->castleRights &= castleRightsMask[from]; + st->castleRights &= castleRightsMask[to]; + st->key ^= zobCastle[st->castleRights]; + } + + bool checkEpSquare = (pt == PAWN && abs(int(to) - int(from)) == 16); + + // Prefetch TT access as soon as we know key is updated + if (!checkEpSquare && TT) + TT->prefetch(st->key); + + // Move the piece + Bitboard move_bb = make_move_bb(from, to); + do_move_bb(&(byColorBB[us]), move_bb); + do_move_bb(&(byTypeBB[pt]), move_bb); + do_move_bb(&(byTypeBB[0]), move_bb); // HACK: byTypeBB[0] == occupied squares + + board[to] = board[from]; + board[from] = EMPTY; + // If the moving piece was a pawn do some special extra work - if (piece == PAWN) + if (pt == PAWN) { // Reset rule 50 draw counter st->rule50 = 0; @@ -780,7 +797,7 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) { st->pawnKey ^= zobrist[us][PAWN][from] ^ zobrist[us][PAWN][to]; // Set en passant square, only if moved pawn can be captured - if (abs(int(to) - int(from)) == 16) + if (checkEpSquare) { if ( (us == WHITE && (pawn_attacks(WHITE, from + DELTA_N) & pawns(BLACK))) || (us == BLACK && (pawn_attacks(BLACK, from + DELTA_S) & pawns(WHITE)))) @@ -791,20 +808,26 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) { } } + // Prefetch only here in the few cases we needed zobEp[] to update the key + if (checkEpSquare && TT) + TT->prefetch(st->key); + + // Update incremental scores + st->mgValue += pst_delta(piece, from, to); + st->egValue += pst_delta(piece, from, to); + + // If the moving piece was a king, update the king square + if (pt == KING) + kingSquare[us] = to; + // Update piece lists - pieceList[us][piece][index[from]] = to; + pieceList[us][pt][index[from]] = to; index[to] = index[from]; - // Update castle rights - st->key ^= zobCastle[st->castleRights]; - st->castleRights &= castleRightsMask[from]; - st->castleRights &= castleRightsMask[to]; - st->key ^= zobCastle[st->castleRights]; - // Update checkers bitboard, piece must be already moved st->checkersBB = EmptyBoardBB; Square ksq = king_square(them); - switch (piece) + switch (pt) { case PAWN: update_checkers(&(st->checkersBB), ksq, from, to, dcCandidates); break; case KNIGHT: update_checkers(&(st->checkersBB), ksq, from, to, dcCandidates); break; @@ -817,7 +840,6 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) { } // Finish - st->key ^= zobSideToMove; sideToMove = opposite_color(sideToMove); gamePly++; @@ -902,26 +924,23 @@ void Position::do_castle_move(Move m) { rto = relative_square(us, SQ_D1); } - // Remove pieces from source squares - clear_bit(&(byColorBB[us]), kfrom); - clear_bit(&(byTypeBB[KING]), kfrom); - clear_bit(&(byTypeBB[0]), kfrom); // HACK: byTypeBB[0] == occupied squares - clear_bit(&(byColorBB[us]), rfrom); - clear_bit(&(byTypeBB[ROOK]), rfrom); - clear_bit(&(byTypeBB[0]), rfrom); // HACK: byTypeBB[0] == occupied squares - - // Put pieces on destination squares - set_bit(&(byColorBB[us]), kto); - set_bit(&(byTypeBB[KING]), kto); - set_bit(&(byTypeBB[0]), kto); // HACK: byTypeBB[0] == occupied squares - set_bit(&(byColorBB[us]), rto); - set_bit(&(byTypeBB[ROOK]), rto); - set_bit(&(byTypeBB[0]), rto); // HACK: byTypeBB[0] == occupied squares + // Move the pieces + Bitboard kmove_bb = make_move_bb(kfrom, kto); + do_move_bb(&(byColorBB[us]), kmove_bb); + do_move_bb(&(byTypeBB[KING]), kmove_bb); + do_move_bb(&(byTypeBB[0]), kmove_bb); // HACK: byTypeBB[0] == occupied squares + + Bitboard rmove_bb = make_move_bb(rfrom, rto); + do_move_bb(&(byColorBB[us]), rmove_bb); + do_move_bb(&(byTypeBB[ROOK]), rmove_bb); + do_move_bb(&(byTypeBB[0]), rmove_bb); // HACK: byTypeBB[0] == occupied squares // Update board array + Piece king = piece_of_color_and_type(us, KING); + Piece rook = piece_of_color_and_type(us, ROOK); board[kfrom] = board[rfrom] = EMPTY; - board[kto] = piece_of_color_and_type(us, KING); - board[rto] = piece_of_color_and_type(us, ROOK); + board[kto] = king; + board[rto] = rook; // Update king square kingSquare[us] = kto; @@ -934,14 +953,10 @@ void Position::do_castle_move(Move m) { index[rto] = tmp; // Update incremental scores - st->mgValue -= pst(us, KING, kfrom); - st->mgValue += pst(us, KING, kto); - st->egValue -= pst(us, KING, kfrom); - st->egValue += pst(us, KING, kto); - st->mgValue -= pst(us, ROOK, rfrom); - st->mgValue += pst(us, ROOK, rto); - st->egValue -= pst(us, ROOK, rfrom); - st->egValue += pst(us, ROOK, rto); + 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); // Update hash key st->key ^= zobrist[us][KING][kfrom] ^ zobrist[us][KING][kto]; @@ -964,6 +979,8 @@ void Position::do_castle_move(Move m) { // Update checkers BB st->checkersBB = attacks_to(king_square(them), us); + + st->key ^= zobSideToMove; } @@ -978,7 +995,7 @@ void Position::do_promotion_move(Move m) { assert(is_ok()); assert(move_is_ok(m)); - assert(move_promotion(m)); + assert(move_is_promotion(m)); us = side_to_move(); them = opposite_color(us); @@ -1001,7 +1018,7 @@ void Position::do_promotion_move(Move m) { board[from] = EMPTY; // Insert promoted piece - promotion = move_promotion(m); + promotion = move_promotion_piece(m); assert(promotion >= KNIGHT && promotion <= QUEEN); set_bit(&(byColorBB[us]), to); set_bit(&(byTypeBB[promotion]), to); @@ -1054,6 +1071,8 @@ void Position::do_promotion_move(Move m) { // Update checkers BB st->checkersBB = attacks_to(king_square(them), us); + + st->key ^= zobSideToMove; } @@ -1117,12 +1136,11 @@ void Position::do_ep_move(Move m) { st->pawnKey ^= zobrist[them][PAWN][capsq]; // Update incremental scores + Piece pawn = piece_of_color_and_type(us, PAWN); + st->mgValue += pst_delta(pawn, from, to); + st->egValue += pst_delta(pawn, from, to); st->mgValue -= pst(them, PAWN, capsq); - st->mgValue -= pst(us, PAWN, from); - st->mgValue += pst(us, PAWN, to); st->egValue -= pst(them, PAWN, capsq); - st->egValue -= pst(us, PAWN, from); - st->egValue += pst(us, PAWN, to); // Reset en passant square st->epSquare = SQ_NONE; @@ -1132,6 +1150,8 @@ void Position::do_ep_move(Move m) { // Update checkers BB st->checkersBB = attacks_to(king_square(them), us); + + st->key ^= zobSideToMove; } @@ -1148,7 +1168,7 @@ void Position::undo_move(Move m) { if (move_is_castle(m)) undo_castle_move(m); - else if (move_promotion(m)) + else if (move_is_promotion(m)) undo_promotion_move(m); else if (move_is_ep(m)) undo_ep_move(m); @@ -1242,21 +1262,16 @@ void Position::undo_castle_move(Move m) { assert(piece_on(kto) == piece_of_color_and_type(us, KING)); assert(piece_on(rto) == piece_of_color_and_type(us, ROOK)); - // Remove pieces from destination squares - clear_bit(&(byColorBB[us]), kto); - clear_bit(&(byTypeBB[KING]), kto); - clear_bit(&(byTypeBB[0]), kto); // HACK: byTypeBB[0] == occupied squares - clear_bit(&(byColorBB[us]), rto); - clear_bit(&(byTypeBB[ROOK]), rto); - clear_bit(&(byTypeBB[0]), rto); // HACK: byTypeBB[0] == occupied squares - - // Put pieces on source squares - set_bit(&(byColorBB[us]), kfrom); - set_bit(&(byTypeBB[KING]), kfrom); - set_bit(&(byTypeBB[0]), kfrom); // HACK: byTypeBB[0] == occupied squares - set_bit(&(byColorBB[us]), rfrom); - set_bit(&(byTypeBB[ROOK]), rfrom); - set_bit(&(byTypeBB[0]), rfrom); // HACK: byTypeBB[0] == occupied squares + // Put the pieces back at the source square + Bitboard kmove_bb = make_move_bb(kto, kfrom); + do_move_bb(&(byColorBB[us]), kmove_bb); + do_move_bb(&(byTypeBB[KING]), kmove_bb); + do_move_bb(&(byTypeBB[0]), kmove_bb); // HACK: byTypeBB[0] == occupied squares + + Bitboard rmove_bb = make_move_bb(rto, rfrom); + do_move_bb(&(byColorBB[us]), rmove_bb); + do_move_bb(&(byTypeBB[ROOK]), rmove_bb); + do_move_bb(&(byTypeBB[0]), rmove_bb); // HACK: byTypeBB[0] == occupied squares // Update board board[rto] = board[kto] = EMPTY; @@ -1286,7 +1301,7 @@ void Position::undo_promotion_move(Move m) { PieceType promotion; assert(move_is_ok(m)); - assert(move_promotion(m)); + assert(move_is_promotion(m)); // When we have arrived here, some work has already been done by // Position::undo_move. In particular, the side to move has been switched, @@ -1300,7 +1315,7 @@ void Position::undo_promotion_move(Move m) { assert(piece_on(from) == EMPTY); // Remove promoted piece - promotion = move_promotion(m); + promotion = move_promotion_piece(m); assert(piece_on(to)==piece_of_color_and_type(us, promotion)); assert(promotion >= KNIGHT && promotion <= QUEEN); clear_bit(&(byColorBB[us]), to); @@ -1417,14 +1432,15 @@ void Position::do_null_move(StateInfo& backupSt) { history[gamePly] = st->key; // Update the necessary information - sideToMove = opposite_color(sideToMove); if (st->epSquare != SQ_NONE) st->key ^= zobEp[st->epSquare]; + st->key ^= zobSideToMove; + TT->prefetch(st->key); + sideToMove = opposite_color(sideToMove); st->epSquare = SQ_NONE; st->rule50++; gamePly++; - st->key ^= zobSideToMove; st->mgValue += (sideToMove == WHITE)? TempoValueMidgame : -TempoValueMidgame; st->egValue += (sideToMove == WHITE)? TempoValueEndgame : -TempoValueEndgame; @@ -1474,6 +1490,22 @@ int Position::see(Move m) const { return see(move_from(m), move_to(m)); } +int Position::see_sign(Move m) const { + + assert(move_is_ok(m)); + + Square from = move_from(m); + Square to = move_to(m); + + // Early return if SEE cannot be negative because capturing piece value + // is not bigger then captured one. + if ( midgame_value_of_piece_on(from) <= midgame_value_of_piece_on(to) + && type_of_piece_on(from) != KING) + return 1; + + return see(from, to); +} + int Position::see(Square from, Square to) const { // Material values @@ -1593,7 +1625,7 @@ int Position::see(Square from, Square to) const { if (pt == KING && stmAttackers) { assert(n < 32); - swapList[n++] = 100; + swapList[n++] = QueenValueMidgame*10; break; } } while (stmAttackers); @@ -1607,15 +1639,16 @@ int Position::see(Square from, Square to) const { } -/// Position::setStartState() copies the content of the argument +/// Position::saveState() copies the content of the current state /// inside startState and makes st point to it. This is needed /// when the st pointee could become stale, as example because /// the caller is about to going out of scope. -void Position::setStartState(const StateInfo& s) { +void Position::saveState() { - startState = s; + startState = *st; st = &startState; + st->previous = NULL; // as a safe guard } @@ -1647,6 +1680,7 @@ void Position::clear() { initialKFile = FILE_E; initialKRFile = FILE_H; initialQRFile = FILE_A; + TT = NULL; } @@ -1966,7 +2000,7 @@ void Position::init_piece_square_tables() { /// the white and black sides reversed. This is only useful for debugging, /// especially for finding evaluation symmetry bugs. -void Position::flipped_copy(const Position &pos) { +void Position::flipped_copy(const Position& pos) { assert(pos.is_ok()); @@ -2091,7 +2125,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? @@ -2166,7 +2200,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)++;