X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fposition.cpp;h=004d6994731ca106e0dd3d7afd6fb5f5b31fd719;hp=26f457c54793b49299dda43c13ac75888de9bef6;hb=e3b03278129e4d7f130826aef209668b3268aa94;hpb=e6d8e7415220a11c06b9a707fde6f5c7dd27d34b diff --git a/src/position.cpp b/src/position.cpp index 26f457c5..004d6994 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -40,16 +40,16 @@ static const string PieceToChar(" PNBRQK pnbrqk"); CACHE_LINE_ALIGNMENT -Score pieceSquareTable[16][64]; // [piece][square] -Value PieceValue[2][18] = { // [Mg / Eg][piece / pieceType] +Score pieceSquareTable[PIECE_NB][SQUARE_NB]; +Value PieceValue[PHASE_NB][PIECE_NB] = { { VALUE_ZERO, PawnValueMg, KnightValueMg, BishopValueMg, RookValueMg, QueenValueMg }, { VALUE_ZERO, PawnValueEg, KnightValueEg, BishopValueEg, RookValueEg, QueenValueEg } }; namespace Zobrist { -Key psq[2][8][64]; // [color][pieceType][square / piece count] -Key enpassant[8]; // [file] -Key castle[16]; // [castleRight] +Key psq[COLOR_NB][PIECE_TYPE_NB][SQUARE_NB]; +Key enpassant[FILE_NB]; +Key castle[CASTLE_RIGHT_NB]; Key side; Key exclusion; @@ -86,10 +86,10 @@ void init() { for (PieceType pt = PAWN; pt <= KING; pt++) { - PieceValue[Mg][make_piece(BLACK, pt)] = PieceValue[Mg][pt]; - PieceValue[Eg][make_piece(BLACK, pt)] = PieceValue[Eg][pt]; + PieceValue[MG][make_piece(BLACK, pt)] = PieceValue[MG][pt]; + PieceValue[EG][make_piece(BLACK, pt)] = PieceValue[EG][pt]; - Score v = make_score(PieceValue[Mg][pt], PieceValue[Eg][pt]); + Score v = make_score(PieceValue[MG][pt], PieceValue[EG][pt]); for (Square s = SQ_A1; s <= SQ_H8; s++) { @@ -102,11 +102,13 @@ void init() { } // namespace Zobrist +namespace { + /// next_attacker() is an helper function used by see() to locate the least /// valuable attacker for the side to move, remove the attacker we just found /// from the 'occupied' bitboard and scan for new X-ray attacks behind it. -template static FORCE_INLINE +template FORCE_INLINE PieceType next_attacker(const Bitboard* bb, const Square& to, const Bitboard& stmAttackers, Bitboard& occupied, Bitboard& attackers) { @@ -131,6 +133,8 @@ PieceType next_attacker(const Bitboard*, const Square&, const Bitboard&, B return KING; // No need to update bitboards, it is the last cycle } +} // namespace + /// CheckInfo c'tor @@ -396,10 +400,8 @@ void Position::print(Move move) const { sync_cout; if (move) - { - Position p(*this); - cout << "\nMove is: " << (sideToMove == BLACK ? ".." : "") << move_to_san(p, move); - } + cout << "\nMove is: " << (sideToMove == BLACK ? ".." : "") + << move_to_san(*const_cast(this), move); for (Square sq = SQ_A1; sq <= SQ_H8; sq++) if (piece_on(sq) != NO_PIECE) @@ -471,37 +473,6 @@ Bitboard Position::attacks_from(Piece p, Square s, Bitboard occ) { } -/// Position::move_attacks_square() tests whether a move from the current -/// position attacks a given square. - -bool Position::move_attacks_square(Move m, Square s) const { - - assert(is_ok(m)); - assert(is_ok(s)); - - Bitboard occ, xray; - Square from = from_sq(m); - Square to = to_sq(m); - Piece piece = piece_moved(m); - - assert(!is_empty(from)); - - // Update occupancy as if the piece is moving - occ = pieces() ^ from ^ to; - - // The piece moved in 'to' attacks the square 's' ? - if (attacks_from(piece, to, occ) & s) - return true; - - // Scan for possible X-ray attackers behind the moved piece - xray = (attacks_bb< ROOK>(s, occ) & pieces(color_of(piece), QUEEN, ROOK)) - | (attacks_bb(s, occ) & pieces(color_of(piece), QUEEN, BISHOP)); - - // Verify attackers are triggered by our move and not already existing - return xray && (xray ^ (xray & attacks_from(s))); -} - - /// Position::pl_move_is_legal() tests whether a pseudo-legal move is legal bool Position::pl_move_is_legal(Move m, Bitboard pinned) const { @@ -768,9 +739,9 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI Key k = 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. - memcpy(&newSt, st, sizeof(ReducedStateInfo)); + // which are going to be recalculated from scratch anyway, then switch our state + // pointer to point to the new, ready to be updated, state. + memcpy(&newSt, st, StateCopySize64 * sizeof(uint64_t)); newSt.previous = st; st = &newSt; @@ -826,7 +797,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI st->pawnKey ^= Zobrist::psq[them][PAWN][capsq]; } else - st->npMaterial[them] -= PieceValue[Mg][capture]; + st->npMaterial[them] -= PieceValue[MG][capture]; // Remove the captured piece byTypeBB[ALL_PIECES] ^= capsq; @@ -934,7 +905,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI - pieceSquareTable[make_piece(us, PAWN)][to]; // Update material - st->npMaterial[us] += PieceValue[Mg][promotion]; + st->npMaterial[us] += PieceValue[MG][promotion]; } // Update pawn hash key @@ -1239,7 +1210,7 @@ int Position::see_sign(Move m) const { // Early return if SEE cannot be negative because captured piece value // is not less then capturing one. Note that king moves always return // here because king midgame value is set to 0. - if (PieceValue[Mg][piece_on(to_sq(m))] >= PieceValue[Mg][piece_moved(m)]) + if (PieceValue[MG][piece_on(to_sq(m))] >= PieceValue[MG][piece_moved(m)]) return 1; return see(m); @@ -1286,7 +1257,7 @@ int Position::see(Move m) const { stm = ~color_of(piece_on(from)); stmAttackers = attackers & pieces(stm); if (!stmAttackers) - return PieceValue[Mg][captured]; + return PieceValue[MG][captured]; // The destination square is defended, which makes things rather more // difficult to compute. We proceed by building up a "swap list" containing @@ -1294,14 +1265,14 @@ int Position::see(Move m) const { // 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. - swapList[0] = PieceValue[Mg][captured]; + swapList[0] = PieceValue[MG][captured]; captured = type_of(piece_on(from)); do { assert(slIndex < 32); // Add the new entry to the swap list - swapList[slIndex] = -swapList[slIndex - 1] + PieceValue[Mg][captured]; + swapList[slIndex] = -swapList[slIndex - 1] + PieceValue[MG][captured]; slIndex++; // Locate and remove from 'occupied' the next least valuable attacker @@ -1343,9 +1314,6 @@ void Position::clear() { for (int i = 0; i < 8; i++) for (int j = 0; j < 16; j++) pieceList[0][i][j] = pieceList[1][i][j] = SQ_NONE; - - for (Square sq = SQ_A1; sq <= SQ_H8; sq++) - board[sq] = NO_PIECE; } @@ -1459,7 +1427,7 @@ Value Position::compute_non_pawn_material(Color c) const { Value value = VALUE_ZERO; for (PieceType pt = KNIGHT; pt <= QUEEN; pt++) - value += piece_count(c, pt) * PieceValue[Mg][pt]; + value += piece_count(c, pt) * PieceValue[MG][pt]; return value; } @@ -1468,36 +1436,31 @@ Value Position::compute_non_pawn_material(Color c) const { /// Position::is_draw() tests whether the position is drawn by material, /// repetition, or the 50 moves rule. It does not detect stalemates, this /// must be done by the search. -template +template bool Position::is_draw() const { - // Draw by material? if ( !pieces(PAWN) && (non_pawn_material(WHITE) + non_pawn_material(BLACK) <= BishopValueMg)) return true; - // Draw by the 50 moves rule? if (st->rule50 > 99 && (!in_check() || MoveList(*this).size())) return true; - // Draw by repetition? - if (!SkipRepetition) + if (CheckRepetition) { - int i = 4, e = std::min(st->rule50, st->pliesFromNull); + int i = 4, e = std::min(st->rule50, st->pliesFromNull), cnt; if (i <= e) { StateInfo* stp = st->previous->previous; - do { + for (cnt = 0; i <= e; i += 2) + { stp = stp->previous->previous; - if (stp->key == st->key) + if (stp->key == st->key && (!CheckThreeFold || ++cnt >= 2)) return true; - - i +=2; - - } while (i <= e); + } } } @@ -1505,8 +1468,9 @@ bool Position::is_draw() const { } // Explicit template instantiations -template bool Position::is_draw() const; -template bool Position::is_draw() const; +template bool Position::is_draw() const; +template bool Position::is_draw() const; +template bool Position::is_draw() const; /// Position::flip() flips position with the white and black sides reversed. This @@ -1589,7 +1553,7 @@ bool Position::pos_is_ok(int* failedStep) const { if ((*step)++, debugKingCount) { - int kingCount[2] = {}; + int kingCount[COLOR_NB] = {}; for (Square s = SQ_A1; s <= SQ_H8; s++) if (type_of(piece_on(s)) == KING)