X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fposition.cpp;h=09daeba04ae10c6af40d68bee1b2697af24d7b32;hp=7d01cb60f10a293c78d354b357b9cd3bc6a09be3;hb=05c5f08372f2ba6e28eec0c3d66fbb4f27e853b1;hpb=9fc602bae74b8e09bd45ace3b42a8ce84d56b23c diff --git a/src/position.cpp b/src/position.cpp index 7d01cb60..09daeba0 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -44,12 +44,9 @@ using std::string; //// Variables //// -int Position::castleRightsMask[64]; - Key Position::zobrist[2][8][64]; Key Position::zobEp[64]; Key Position::zobCastle[16]; -Key Position::zobMaterial[2][8][16]; Key Position::zobSideToMove; Key Position::zobExclusion; @@ -87,7 +84,7 @@ Position::Position() {} Position::Position(const Position& pos) { - fast_copy(pos); + memcpy(this, &pos, sizeof(Position)); detach(); // Always detach() in copy c'tor to avoid surprises } @@ -97,19 +94,6 @@ Position::Position(const string& fen) { } -/// Position::fast_copy() creates a partial copy of the given position, -/// only data that changes with a do_move() / undo_move() cycle is copied, -/// in particular for stateInfo are copied only the pointers, so that the -/// actual data remains stored in the parent Position. This is not a problem -/// if the parent Position is known not to be destroyed while we are still alive, -/// as is the common case, see detach() otherwise. - -void Position::fast_copy(const Position& pos) { - - memcpy(this, &pos, sizeof(Position)); -} - - /// Position::detach() copies the content of the current state and castling /// masks inside the position itself. This is needed when the st pointee could /// become stale, as example because the caller is about to going out of scope. @@ -712,14 +696,14 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI assert(is_ok()); assert(move_is_ok(m)); - Bitboard key = st->key; + Key key = st->key; // Copy some fields of old state to our new StateInfo object except the // ones which are recalculated from scratch anyway, then switch our state // pointer to point to the new, ready to be updated, state. struct ReducedStateInfo { Key pawnKey, materialKey; - int castleRights, rule50, pliesFromNull; + int castleRights, rule50, ply, pliesFromNull; Square epSquare; Score value; Value npMaterial[2]; @@ -731,8 +715,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI // Save the current key to the history[] array, in order to be able to // detect repetition draws. - history[gamePly] = key; - gamePly++; + history[st->ply++] = key; // Update side to move key ^= zobSideToMove; @@ -824,6 +807,46 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI key ^= zobEp[st->epSquare]; } } + + if (pm) // promotion ? + { + PieceType promotion = move_promotion_piece(m); + + assert(promotion >= KNIGHT && promotion <= QUEEN); + + // Insert promoted piece instead of pawn + clear_bit(&(byTypeBB[PAWN]), to); + set_bit(&(byTypeBB[promotion]), to); + board[to] = piece_of_color_and_type(us, promotion); + + // Update piece counts + pieceCount[us][promotion]++; + pieceCount[us][PAWN]--; + + // Update material key + st->materialKey ^= zobrist[us][PAWN][pieceCount[us][PAWN]]; + st->materialKey ^= zobrist[us][promotion][pieceCount[us][promotion]-1]; + + // Update piece lists, move the last pawn at index[to] position + // and shrink the list. Add a new promotion piece to the list. + Square lastPawnSquare = pieceList[us][PAWN][pieceCount[us][PAWN]]; + index[lastPawnSquare] = index[to]; + pieceList[us][PAWN][index[lastPawnSquare]] = lastPawnSquare; + pieceList[us][PAWN][pieceCount[us][PAWN]] = SQ_NONE; + index[to] = pieceCount[us][promotion] - 1; + pieceList[us][promotion][index[to]] = to; + + // Partially revert hash keys update + key ^= zobrist[us][PAWN][to] ^ zobrist[us][promotion][to]; + st->pawnKey ^= zobrist[us][PAWN][to]; + + // Partially revert and update incremental scores + st->value -= pst(us, PAWN, to); + st->value += pst(us, promotion, to); + + // Update material + st->npMaterial[us] += piece_value_midgame(promotion); + } } // Update incremental scores @@ -832,46 +855,6 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI // Set capture piece st->capture = capture; - if (pm) // promotion ? - { - PieceType promotion = move_promotion_piece(m); - - assert(promotion >= KNIGHT && promotion <= QUEEN); - - // Insert promoted piece instead of pawn - clear_bit(&(byTypeBB[PAWN]), to); - set_bit(&(byTypeBB[promotion]), to); - board[to] = piece_of_color_and_type(us, promotion); - - // Update material key - st->materialKey ^= zobMaterial[us][PAWN][pieceCount[us][PAWN]]; - st->materialKey ^= zobMaterial[us][promotion][pieceCount[us][promotion]+1]; - - // Update piece counts - pieceCount[us][PAWN]--; - pieceCount[us][promotion]++; - - // Update piece lists, move the last pawn at index[to] position - // and shrink the list. Add a new promotion piece to the list. - Square lastPawnSquare = pieceList[us][PAWN][pieceCount[us][PAWN]]; - index[lastPawnSquare] = index[to]; - pieceList[us][PAWN][index[lastPawnSquare]] = lastPawnSquare; - pieceList[us][PAWN][pieceCount[us][PAWN]] = SQ_NONE; - index[to] = pieceCount[us][promotion] - 1; - pieceList[us][promotion][index[to]] = to; - - // Partially revert hash keys update - key ^= zobrist[us][PAWN][to] ^ zobrist[us][promotion][to]; - st->pawnKey ^= zobrist[us][PAWN][to]; - - // Partially revert and update incremental scores - st->value -= pst(us, PAWN, to); - st->value += pst(us, promotion, to); - - // Update material - st->npMaterial[us] += piece_value_midgame(promotion); - } - // Update the key with the final value st->key = key; @@ -911,23 +894,31 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI /// 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(Bitboard& key, PieceType capture, Color them, Square to, bool ep) { +void Position::do_capture_move(Key& key, PieceType capture, Color them, Square to, bool ep) { assert(capture != KING); Square capsq = to; - if (ep) // en passant ? + // If the captured piece was a pawn, update pawn hash key, + // otherwise update non-pawn material. + if (capture == PAWN) { - capsq = (them == BLACK)? (to - DELTA_N) : (to - DELTA_S); + if (ep) // en passant ? + { + capsq = (them == BLACK)? (to - DELTA_N) : (to - DELTA_S); - assert(to == st->epSquare); - assert(relative_rank(opposite_color(them), to) == RANK_6); - assert(piece_on(to) == EMPTY); - assert(piece_on(capsq) == piece_of_color_and_type(them, PAWN)); + assert(to == st->epSquare); + assert(relative_rank(opposite_color(them), to) == RANK_6); + assert(piece_on(to) == EMPTY); + assert(piece_on(capsq) == piece_of_color_and_type(them, PAWN)); - board[capsq] = EMPTY; + board[capsq] = EMPTY; + } + st->pawnKey ^= zobrist[them][PAWN][capsq]; } + else + st->npMaterial[them] -= piece_value_midgame(capture); // Remove captured piece clear_bit(&(byColorBB[them]), capsq); @@ -940,19 +931,12 @@ void Position::do_capture_move(Bitboard& key, PieceType capture, Color them, Squ // Update incremental scores st->value -= pst(them, capture, capsq); - // If the captured piece was a pawn, update pawn hash key, - // otherwise update non-pawn material. - if (capture == PAWN) - st->pawnKey ^= zobrist[them][PAWN][capsq]; - else - st->npMaterial[them] -= piece_value_midgame(capture); - - // Update material hash key - st->materialKey ^= zobMaterial[them][capture][pieceCount[them][capture]]; - // Update piece count pieceCount[them][capture]--; + // Update material hash key + st->materialKey ^= zobrist[them][capture][pieceCount[them][capture]]; + // Update piece list, move the last piece at index[capsq] position // // WARNING: This is a not perfectly revresible operation. When we @@ -1076,7 +1060,6 @@ void Position::undo_move(Move m) { assert(is_ok()); assert(move_is_ok(m)); - gamePly--; sideToMove = opposite_color(sideToMove); if (move_is_castle(m)) @@ -1126,7 +1109,6 @@ void Position::undo_move(Move m) { pieceList[us][PAWN][index[to]] = to; } - // Put the piece back at the source square Bitboard move_bb = make_move_bb(to, from); do_move_bb(&(byColorBB[us]), move_bb); @@ -1261,7 +1243,7 @@ void Position::do_null_move(StateInfo& backupSt) { // Save the current key to the history[] array, in order to be able to // detect repetition draws. - history[gamePly] = st->key; + history[st->ply++] = st->key; // Update the necessary information if (st->epSquare != SQ_NONE) @@ -1275,7 +1257,6 @@ void Position::do_null_move(StateInfo& backupSt) { st->rule50++; st->pliesFromNull = 0; st->value += (sideToMove == WHITE) ? TempoValue : -TempoValue; - gamePly++; } @@ -1297,7 +1278,7 @@ void Position::undo_null_move() { // Update the necessary information sideToMove = opposite_color(sideToMove); st->rule50--; - gamePly--; + st->ply--; } @@ -1494,22 +1475,21 @@ void Position::clear() { pieceList[0][i][j] = pieceList[1][i][j] = SQ_NONE; sideToMove = WHITE; - gamePly = 0; initialKFile = FILE_E; initialKRFile = FILE_H; initialQRFile = FILE_A; } -/// Position::reset_game_ply() simply sets gamePly to 0. It is used from the +/// Position::reset_ply() simply sets ply to 0. It is used from the /// UCI interface code, whenever a non-reversible move is made in a /// 'position fen moves m1 m2 ...' command. This makes it possible /// for the program to handle games of arbitrary length, as long as the GUI /// handles draws by the 50 move rule correctly. -void Position::reset_game_ply() { +void Position::reset_ply() { - gamePly = 0; + st->ply = 0; } @@ -1613,8 +1593,8 @@ Key Position::compute_material_key() const { for (PieceType pt = PAWN; pt <= QUEEN; pt++) { int count = piece_count(c, pt); - for (int i = 0; i <= count; i++) - result ^= zobMaterial[c][pt][i]; + for (int i = 0; i < count; i++) + result ^= zobrist[c][pt][i]; } return result; } @@ -1686,9 +1666,11 @@ bool Position::is_draw() const { if (st->rule50 > 100 || (st->rule50 == 100 && !is_check())) return true; - // Draw by repetition? - for (int i = 4; i <= Min(Min(gamePly, st->rule50), st->pliesFromNull); i += 2) - if (history[gamePly - i] == st->key) + assert(st->ply >= st->rule50); + + // Draw by repetition? + for (int i = 4, e = Min(st->rule50, st->pliesFromNull); i <= e; i += 2) + if (history[st->ply - i] == st->key) return true; return false; @@ -1767,15 +1749,6 @@ void Position::init_zobrist() { zobCastle[i] = genrand_int64(); zobSideToMove = genrand_int64(); - - for (int i = 0; i < 2; i++) - for (int j = 0; j < 8; j++) - for (int k = 0; k < 16; k++) - zobMaterial[i][j][k] = (k > 0)? Key(genrand_int64()) : Key(0LL); - - for (int i = 0; i < 16; i++) - zobMaterial[0][KING][i] = zobMaterial[1][KING][i] = Key(0ULL); - zobExclusion = genrand_int64(); }