Small cleanups

closes https://github.com/official-stockfish/Stockfish/pull/2756

No functional change
This commit is contained in:
Joost VandeVondele
2020-06-24 22:19:58 +02:00
parent 11483fe6d9
commit ab5cd8340f
18 changed files with 124 additions and 86 deletions
+18 -11
View File
@@ -110,6 +110,7 @@ inline Bitboard square_bb(Square s) {
return SquareBB[s]; return SquareBB[s];
} }
/// Overloads of bitwise operators between a Bitboard and a Square for testing /// Overloads of bitwise operators between a Bitboard and a Square for testing
/// whether a given bit is set in a bitboard, and for setting and clearing bits. /// whether a given bit is set in a bitboard, and for setting and clearing bits.
@@ -200,10 +201,11 @@ inline Bitboard adjacent_files_bb(Square s) {
return shift<EAST>(file_bb(s)) | shift<WEST>(file_bb(s)); return shift<EAST>(file_bb(s)) | shift<WEST>(file_bb(s));
} }
/// line_bb(Square, Square) returns a Bitboard representing an entire line
/// (from board edge to board edge) that intersects the given squares. /// line_bb(Square, Square) returns a bitboard representing an entire line,
/// If the given squares are not on a same file/rank/diagonal, return 0. /// from board edge to board edge, that intersects the given squares. If the
/// Ex. line_bb(SQ_C4, SQ_F7) returns a bitboard with the A2-G8 diagonal. /// given squares are not on a same file/rank/diagonal, returns 0. For instance,
/// line_bb(SQ_C4, SQ_F7) will return a bitboard with the A2-G8 diagonal.
inline Bitboard line_bb(Square s1, Square s2) { inline Bitboard line_bb(Square s1, Square s2) {
@@ -211,10 +213,11 @@ inline Bitboard line_bb(Square s1, Square s2) {
return LineBB[s1][s2]; return LineBB[s1][s2];
} }
/// between_bb() returns a Bitboard representing squares that are linearly
/// between the given squares (excluding the given squares). /// between_bb() returns a bitboard representing squares that are linearly
/// If the given squares are not on a same file/rank/diagonal, return 0. /// between the given squares (excluding the given squares). If the given
/// Ex. between_bb(SQ_C4, SQ_F7) returns a bitboard with squares D5 and E6. /// squares are not on a same file/rank/diagonal, return 0. For instance,
/// between_bb(SQ_C4, SQ_F7) will return a bitboard with squares D5 and E6.
inline Bitboard between_bb(Square s1, Square s2) { inline Bitboard between_bb(Square s1, Square s2) {
Bitboard b = line_bb(s1, s2) & ((AllSquares << s1) ^ (AllSquares << s2)); Bitboard b = line_bb(s1, s2) & ((AllSquares << s1) ^ (AllSquares << s2));
@@ -241,8 +244,8 @@ inline Bitboard forward_file_bb(Color c, Square s) {
/// pawn_attack_span() returns a bitboard representing all the squares that can /// pawn_attack_span() returns a bitboard representing all the squares that can
/// be attacked by a pawn of the given color when it moves along its file, /// be attacked by a pawn of the given color when it moves along its file, starting
/// starting from the given square. /// from the given square.
inline Bitboard pawn_attack_span(Color c, Square s) { inline Bitboard pawn_attack_span(Color c, Square s) {
return forward_ranks_bb(c, s) & adjacent_files_bb(s); return forward_ranks_bb(c, s) & adjacent_files_bb(s);
@@ -276,7 +279,9 @@ template<> inline int distance<Square>(Square x, Square y) { return SquareDistan
inline int edge_distance(File f) { return std::min(f, File(FILE_H - f)); } inline int edge_distance(File f) { return std::min(f, File(FILE_H - f)); }
inline int edge_distance(Rank r) { return std::min(r, Rank(RANK_8 - r)); } inline int edge_distance(Rank r) { return std::min(r, Rank(RANK_8 - r)); }
/// Return the target square bitboard if we do not step off the board, empty otherwise
/// safe_destination() returns the bitboard of target square for the given step
/// from the given square. If the step is off the board, returns empty bitboard.
inline Bitboard safe_destination(Square s, int step) inline Bitboard safe_destination(Square s, int step)
{ {
@@ -284,6 +289,7 @@ inline Bitboard safe_destination(Square s, int step)
return is_ok(to) && distance(s, to) <= 2 ? square_bb(to) : Bitboard(0); return is_ok(to) && distance(s, to) <= 2 ? square_bb(to) : Bitboard(0);
} }
/// attacks_bb(Square) returns the pseudo attacks of the give piece type /// attacks_bb(Square) returns the pseudo attacks of the give piece type
/// assuming an empty board. /// assuming an empty board.
@@ -295,6 +301,7 @@ inline Bitboard attacks_bb(Square s) {
return PseudoAttacks[Pt][s]; return PseudoAttacks[Pt][s];
} }
/// attacks_bb(Square, Bitboard) returns the attacks by the given piece /// attacks_bb(Square, Bitboard) returns the attacks by the given piece
/// assuming the board is occupied according to the passed Bitboard. /// assuming the board is occupied according to the passed Bitboard.
/// Sliding piece attacks do not continue passed an occupied square. /// Sliding piece attacks do not continue passed an occupied square.
+7 -7
View File
@@ -268,7 +268,7 @@ Value Endgame<KQKP>::operator()(const Position& pos) const {
} }
/// KQ vs KR. This is almost identical to KX vs K: We give the attacking /// KQ vs KR. This is almost identical to KX vs K: we give the attacking
/// king a bonus for having the kings close together, and for forcing the /// king a bonus for having the kings close together, and for forcing the
/// defending king towards the edge. If we also take care to avoid null move for /// defending king towards the edge. If we also take care to avoid null move for
/// the defending side in the search, this is usually sufficient to win KQ vs KR. /// the defending side in the search, this is usually sufficient to win KQ vs KR.
@@ -291,7 +291,7 @@ Value Endgame<KQKR>::operator()(const Position& pos) const {
/// KNN vs KP. Very drawish, but there are some mate opportunities if we can /// KNN vs KP. Very drawish, but there are some mate opportunities if we can
// press the weakSide King to a corner before the pawn advances too much. /// press the weakSide King to a corner before the pawn advances too much.
template<> template<>
Value Endgame<KNNKP>::operator()(const Position& pos) const { Value Endgame<KNNKP>::operator()(const Position& pos) const {
@@ -352,7 +352,7 @@ ScaleFactor Endgame<KBPsK>::operator()(const Position& pos) const {
Square weakPawn = frontmost_sq(strongSide, pos.pieces(weakSide, PAWN)); Square weakPawn = frontmost_sq(strongSide, pos.pieces(weakSide, PAWN));
// There's potential for a draw if our pawn is blocked on the 7th rank, // There's potential for a draw if our pawn is blocked on the 7th rank,
// the bishop cannot attack it or they only have one pawn left // the bishop cannot attack it or they only have one pawn left.
if ( relative_rank(strongSide, weakPawn) == RANK_7 if ( relative_rank(strongSide, weakPawn) == RANK_7
&& (strongPawns & (weakPawn + pawn_push(weakSide))) && (strongPawns & (weakPawn + pawn_push(weakSide)))
&& (opposite_colors(strongBishop, weakPawn) || !more_than_one(strongPawns))) && (opposite_colors(strongBishop, weakPawn) || !more_than_one(strongPawns)))
@@ -365,7 +365,7 @@ ScaleFactor Endgame<KBPsK>::operator()(const Position& pos) const {
// closer. (I think this rule only fails in practically // closer. (I think this rule only fails in practically
// unreachable positions such as 5k1K/6p1/6P1/8/8/3B4/8/8 w // unreachable positions such as 5k1K/6p1/6P1/8/8/3B4/8/8 w
// and positions where qsearch will immediately correct the // and positions where qsearch will immediately correct the
// problem such as 8/4k1p1/6P1/1K6/3B4/8/8/8 w) // problem such as 8/4k1p1/6P1/1K6/3B4/8/8/8 w).
if ( relative_rank(strongSide, weakKing) >= RANK_7 if ( relative_rank(strongSide, weakKing) >= RANK_7
&& weakKingDist <= 2 && weakKingDist <= 2
&& weakKingDist <= strongKingDist) && weakKingDist <= strongKingDist)
@@ -576,7 +576,7 @@ ScaleFactor Endgame<KRPPKRP>::operator()(const Position& pos) const {
} }
/// K and two or more pawns vs K. There is just a single rule here: If all pawns /// K and two or more pawns vs K. There is just a single rule here: if all pawns
/// are on the same rook file and are blocked by the defending king, it's a draw. /// are on the same rook file and are blocked by the defending king, it's a draw.
template<> template<>
ScaleFactor Endgame<KPsK>::operator()(const Position& pos) const { ScaleFactor Endgame<KPsK>::operator()(const Position& pos) const {
@@ -693,7 +693,7 @@ ScaleFactor Endgame<KBPPKB>::operator()(const Position& pos) const {
} }
/// KBP vs KN. There is a single rule: If the defending king is somewhere along /// KBP vs KN. There is a single rule: if the defending king is somewhere along
/// the path of the pawn, and the square of the king is not of the same color as /// the path of the pawn, and the square of the king is not of the same color as
/// the stronger side's bishop, it's a draw. /// the stronger side's bishop, it's a draw.
template<> template<>
@@ -717,7 +717,7 @@ ScaleFactor Endgame<KBPKN>::operator()(const Position& pos) const {
/// KP vs KP. This is done by removing the weakest side's pawn and probing the /// KP vs KP. This is done by removing the weakest side's pawn and probing the
/// KP vs K bitbase: If the weakest side has a draw without the pawn, it probably /// KP vs K bitbase: if the weakest side has a draw without the pawn, it probably
/// has at least a draw with the pawn as well. The exception is when the stronger /// has at least a draw with the pawn as well. The exception is when the stronger
/// side's pawn is far advanced and not on a rook file; in this case it is often /// side's pawn is far advanced and not on a rook file; in this case it is often
/// possible to win (e.g. 8/4k3/3p4/3P4/6K1/8/8/8 w - - 0 1). /// possible to win (e.g. 8/4k3/3p4/3P4/6K1/8/8/8 w - - 0 1).
+14 -10
View File
@@ -127,23 +127,23 @@ namespace {
}; };
// Assorted bonuses and penalties // Assorted bonuses and penalties
constexpr Score BishopPawns = S( 3, 7); constexpr Score BishopKingProtector = S( 6, 9);
constexpr Score BishopOnKingRing = S( 24, 0); constexpr Score BishopOnKingRing = S( 24, 0);
constexpr Score BishopOutpost = S( 30, 23);
constexpr Score BishopPawns = S( 3, 7);
constexpr Score BishopXRayPawns = S( 4, 5); constexpr Score BishopXRayPawns = S( 4, 5);
constexpr Score CorneredBishop = S( 50, 50); constexpr Score CorneredBishop = S( 50, 50);
constexpr Score FlankAttacks = S( 8, 0); constexpr Score FlankAttacks = S( 8, 0);
constexpr Score Hanging = S( 69, 36); constexpr Score Hanging = S( 69, 36);
constexpr Score BishopKingProtector = S( 6, 9);
constexpr Score KnightKingProtector = S( 8, 9); constexpr Score KnightKingProtector = S( 8, 9);
constexpr Score KnightOnQueen = S( 16, 11); constexpr Score KnightOnQueen = S( 16, 11);
constexpr Score KnightOutpost = S( 56, 36);
constexpr Score LongDiagonalBishop = S( 45, 0); constexpr Score LongDiagonalBishop = S( 45, 0);
constexpr Score MinorBehindPawn = S( 18, 3); constexpr Score MinorBehindPawn = S( 18, 3);
constexpr Score KnightOutpost = S( 56, 36);
constexpr Score BishopOutpost = S( 30, 23);
constexpr Score ReachableOutpost = S( 31, 22);
constexpr Score PassedFile = S( 11, 8); constexpr Score PassedFile = S( 11, 8);
constexpr Score PawnlessFlank = S( 17, 95); constexpr Score PawnlessFlank = S( 17, 95);
constexpr Score QueenInfiltration = S( -2, 14); constexpr Score QueenInfiltration = S( -2, 14);
constexpr Score ReachableOutpost = S( 31, 22);
constexpr Score RestrictedPiece = S( 7, 7); constexpr Score RestrictedPiece = S( 7, 7);
constexpr Score RookOnKingRing = S( 16, 0); constexpr Score RookOnKingRing = S( 16, 0);
constexpr Score RookOnQueenFile = S( 6, 11); constexpr Score RookOnQueenFile = S( 6, 11);
@@ -152,8 +152,9 @@ namespace {
constexpr Score ThreatByPawnPush = S( 48, 39); constexpr Score ThreatByPawnPush = S( 48, 39);
constexpr Score ThreatBySafePawn = S(173, 94); constexpr Score ThreatBySafePawn = S(173, 94);
constexpr Score TrappedRook = S( 55, 13); constexpr Score TrappedRook = S( 55, 13);
constexpr Score WeakQueen = S( 56, 15);
constexpr Score WeakQueenProtection = S( 14, 0); constexpr Score WeakQueenProtection = S( 14, 0);
constexpr Score WeakQueen = S( 56, 15);
#undef S #undef S
@@ -216,6 +217,7 @@ namespace {
// Evaluation::initialize() computes king and pawn attacks, and the king ring // Evaluation::initialize() computes king and pawn attacks, and the king ring
// bitboard for a given color. This is done at the beginning of the evaluation. // bitboard for a given color. This is done at the beginning of the evaluation.
template<Tracing T> template<Color Us> template<Tracing T> template<Color Us>
void Evaluation<T>::initialize() { void Evaluation<T>::initialize() {
@@ -255,6 +257,7 @@ namespace {
// Evaluation::pieces() scores pieces of a given color and type // Evaluation::pieces() scores pieces of a given color and type
template<Tracing T> template<Color Us, PieceType Pt> template<Tracing T> template<Color Us, PieceType Pt>
Score Evaluation<T>::pieces() { Score Evaluation<T>::pieces() {
@@ -388,6 +391,7 @@ namespace {
// Evaluation::king() assigns bonuses and penalties to a king of a given color // Evaluation::king() assigns bonuses and penalties to a king of a given color
template<Tracing T> template<Color Us> template<Tracing T> template<Color Us>
Score Evaluation<T>::king() const { Score Evaluation<T>::king() const {
@@ -496,6 +500,7 @@ namespace {
// Evaluation::threats() assigns bonuses according to the types of the // Evaluation::threats() assigns bonuses according to the types of the
// attacking and the attacked pieces. // attacking and the attacked pieces.
template<Tracing T> template<Color Us> template<Tracing T> template<Color Us>
Score Evaluation<T>::threats() const { Score Evaluation<T>::threats() const {
@@ -721,8 +726,8 @@ namespace {
// Evaluation::winnable() adjusts the mg and eg score components based on the // Evaluation::winnable() adjusts the mg and eg score components based on the
// known attacking/defending status of the players. // known attacking/defending status of the players. A single value is derived
// A single value is derived from the mg and eg values and returned. // by interpolation from the mg and eg values and returned.
template<Tracing T> template<Tracing T>
Value Evaluation<T>::winnable(Score score) const { Value Evaluation<T>::winnable(Score score) const {
@@ -828,12 +833,11 @@ namespace {
return pos.side_to_move() == WHITE ? v : -v; return pos.side_to_move() == WHITE ? v : -v;
// Main evaluation begins here // Main evaluation begins here
initialize<WHITE>(); initialize<WHITE>();
initialize<BLACK>(); initialize<BLACK>();
// Pieces evaluated first (also populates attackedBy, attackedBy2). // Pieces evaluated first (also populates attackedBy, attackedBy2).
// Note that the order of evaluation of the terms is left unspecified // Note that the order of evaluation of the terms is left unspecified.
score += pieces<WHITE, KNIGHT>() - pieces<BLACK, KNIGHT>() score += pieces<WHITE, KNIGHT>() - pieces<BLACK, KNIGHT>()
+ pieces<WHITE, BISHOP>() - pieces<BLACK, BISHOP>() + pieces<WHITE, BISHOP>() - pieces<BLACK, BISHOP>()
+ pieces<WHITE, ROOK >() - pieces<BLACK, ROOK >() + pieces<WHITE, ROOK >() - pieces<BLACK, ROOK >()
+11 -8
View File
@@ -44,12 +44,12 @@ namespace {
constexpr int QuadraticTheirs[][PIECE_TYPE_NB] = { constexpr int QuadraticTheirs[][PIECE_TYPE_NB] = {
// THEIR PIECES // THEIR PIECES
// pair pawn knight bishop rook queen // pair pawn knight bishop rook queen
{ 0 }, // Bishop pair { }, // Bishop pair
{ 36, 0 }, // Pawn { 36, }, // Pawn
{ 9, 63, 0 }, // Knight OUR PIECES { 9, 63, }, // Knight OUR PIECES
{ 59, 65, 42, 0 }, // Bishop { 59, 65, 42, }, // Bishop
{ 46, 39, 24, -24, 0 }, // Rook { 46, 39, 24, -24, }, // Rook
{ 97, 100, -42, 137, 268, 0 } // Queen { 97, 100, -42, 137, 268, } // Queen
}; };
// Endgame evaluation and scaling functions are accessed directly and not through // Endgame evaluation and scaling functions are accessed directly and not through
@@ -79,8 +79,10 @@ namespace {
&& pos.count<PAWN>(~us) >= 1; && pos.count<PAWN>(~us) >= 1;
} }
/// imbalance() calculates the imbalance by comparing the piece count of each /// imbalance() calculates the imbalance by comparing the piece count of each
/// piece type for both colors. /// piece type for both colors.
template<Color Us> template<Color Us>
int imbalance(const int pieceCount[][PIECE_TYPE_NB]) { int imbalance(const int pieceCount[][PIECE_TYPE_NB]) {
@@ -94,9 +96,9 @@ namespace {
if (!pieceCount[Us][pt1]) if (!pieceCount[Us][pt1])
continue; continue;
int v = 0; int v = QuadraticOurs[pt1][pt1] * pieceCount[Us][pt1];
for (int pt2 = NO_PIECE_TYPE; pt2 <= pt1; ++pt2) for (int pt2 = NO_PIECE_TYPE; pt2 < pt1; ++pt2)
v += QuadraticOurs[pt1][pt2] * pieceCount[Us][pt2] v += QuadraticOurs[pt1][pt2] * pieceCount[Us][pt2]
+ QuadraticTheirs[pt1][pt2] * pieceCount[Them][pt2]; + QuadraticTheirs[pt1][pt2] * pieceCount[Them][pt2];
@@ -110,6 +112,7 @@ namespace {
namespace Material { namespace Material {
/// Material::probe() looks up the current position's material configuration in /// Material::probe() looks up the current position's material configuration in
/// the material hash table. It returns a pointer to the Entry if the position /// the material hash table. It returns a pointer to the Entry if the position
/// is found. Otherwise a new Entry is computed and stored there, so we don't /// is found. Otherwise a new Entry is computed and stored there, so we don't
+1 -1
View File
@@ -44,7 +44,7 @@ struct Entry {
bool specialized_eval_exists() const { return evaluationFunction != nullptr; } bool specialized_eval_exists() const { return evaluationFunction != nullptr; }
Value evaluate(const Position& pos) const { return (*evaluationFunction)(pos); } Value evaluate(const Position& pos) const { return (*evaluationFunction)(pos); }
// scale_factor takes a position and a color as input and returns a scale factor // scale_factor() takes a position and a color as input and returns a scale factor
// for the given color. We have to provide the position in addition to the color // for the given color. We have to provide the position in addition to the color
// because the scale factor may also be a function which should be applied to // because the scale factor may also be a function which should be applied to
// the position. For instance, in KBP vs K endgames, the scaling function looks // the position. For instance, in KBP vs K endgames, the scaling function looks
+12 -9
View File
@@ -294,9 +294,10 @@ void prefetch(void* addr) {
#endif #endif
/// aligned_ttmem_alloc will return suitably aligned memory, and if possible use large pages. /// aligned_ttmem_alloc() will return suitably aligned memory, and if possible use large pages.
/// The returned pointer is the aligned one, while the mem argument is the one that needs to be passed to free. /// The returned pointer is the aligned one, while the mem argument is the one that needs
/// With c++17 some of this functionality can be simplified. /// to be passed to free. With c++17 some of this functionality could be simplified.
#if defined(__linux__) && !defined(__ANDROID__) #if defined(__linux__) && !defined(__ANDROID__)
void* aligned_ttmem_alloc(size_t allocSize, void*& mem) { void* aligned_ttmem_alloc(size_t allocSize, void*& mem) {
@@ -336,17 +337,17 @@ static void* aligned_ttmem_alloc_large_pages(size_t allocSize) {
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// Try to enable SeLockMemoryPrivilege. Note that even if AdjustTokenPrivileges() succeeds, // Try to enable SeLockMemoryPrivilege. Note that even if AdjustTokenPrivileges() succeeds,
// we still need to query GetLastError() to ensure that the privileges were actually obtained... // we still need to query GetLastError() to ensure that the privileges were actually obtained.
if (AdjustTokenPrivileges( if (AdjustTokenPrivileges(
hProcessToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &prevTp, &prevTpLen) && hProcessToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &prevTp, &prevTpLen) &&
GetLastError() == ERROR_SUCCESS) GetLastError() == ERROR_SUCCESS)
{ {
// round up size to full pages and allocate // Round up size to full pages and allocate
allocSize = (allocSize + largePageSize - 1) & ~size_t(largePageSize - 1); allocSize = (allocSize + largePageSize - 1) & ~size_t(largePageSize - 1);
mem = VirtualAlloc( mem = VirtualAlloc(
NULL, allocSize, MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); NULL, allocSize, MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE);
// privilege no longer needed, restore previous state // Privilege no longer needed, restore previous state
AdjustTokenPrivileges(hProcessToken, FALSE, &prevTp, 0, NULL, NULL); AdjustTokenPrivileges(hProcessToken, FALSE, &prevTp, 0, NULL, NULL);
} }
} }
@@ -360,7 +361,7 @@ void* aligned_ttmem_alloc(size_t allocSize, void*& mem) {
static bool firstCall = true; static bool firstCall = true;
// try to allocate large pages // Try to allocate large pages
mem = aligned_ttmem_alloc_large_pages(allocSize); mem = aligned_ttmem_alloc_large_pages(allocSize);
// Suppress info strings on the first call. The first call occurs before 'uci' // Suppress info strings on the first call. The first call occurs before 'uci'
@@ -374,7 +375,7 @@ void* aligned_ttmem_alloc(size_t allocSize, void*& mem) {
} }
firstCall = false; firstCall = false;
// fall back to regular, page aligned, allocation if necessary // Fall back to regular, page aligned, allocation if necessary
if (!mem) if (!mem)
mem = VirtualAlloc(NULL, allocSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); mem = VirtualAlloc(NULL, allocSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
@@ -394,7 +395,9 @@ void* aligned_ttmem_alloc(size_t allocSize, void*& mem) {
#endif #endif
/// aligned_ttmem_free will free the previously allocated ttmem
/// aligned_ttmem_free() will free the previously allocated ttmem
#if defined(_WIN64) #if defined(_WIN64)
void aligned_ttmem_free(void* mem) { void aligned_ttmem_free(void* mem) {
+7
View File
@@ -66,6 +66,12 @@ namespace {
#undef S #undef S
#undef V #undef V
/// evaluate() calculates a score for the static pawn structure of the given position.
/// We cannot use the location of pieces or king in this function, as the evaluation
/// of the pawn structure will be stored in a small cache for speed reasons, and will
/// be re-used even when the pieces have moved.
template<Color Us> template<Color Us>
Score evaluate(const Position& pos, Pawns::Entry* e) { Score evaluate(const Position& pos, Pawns::Entry* e) {
@@ -170,6 +176,7 @@ namespace {
namespace Pawns { namespace Pawns {
/// Pawns::probe() looks up the current position's pawns configuration in /// Pawns::probe() looks up the current position's pawns configuration in
/// the pawns hash table. It returns a pointer to the Entry if the position /// the pawns hash table. It returns a pointer to the Entry if the position
/// is found. Otherwise a new Entry is computed and stored there, so we don't /// is found. Otherwise a new Entry is computed and stored there, so we don't
+2 -2
View File
@@ -105,8 +105,7 @@ Key cuckoo[8192];
Move cuckooMove[8192]; Move cuckooMove[8192];
/// Position::init() initializes at startup the various arrays used to compute /// Position::init() initializes at startup the various arrays used to compute hash keys
/// hash keys.
void Position::init() { void Position::init() {
@@ -1112,6 +1111,7 @@ bool Position::see_ge(Move m, Value threshold) const {
return bool(res); return bool(res);
} }
/// Position::is_draw() tests whether the position is drawn by 50-move rule /// Position::is_draw() tests whether the position is drawn by 50-move rule
/// or by repetition. It does not detect stalemates. /// or by repetition. It does not detect stalemates.
+1
View File
@@ -56,6 +56,7 @@ struct StateInfo {
int repetition; int repetition;
}; };
/// A list to keep track of the position states along the setup moves (from the /// A list to keep track of the position states along the setup moves (from the
/// start position to the position just before the search starts). Needed by /// start position to the position just before the search starts). Needed by
/// 'draw by repetition' detection. Use a std::deque because pointers to /// 'draw by repetition' detection. Use a std::deque because pointers to
+4 -3
View File
@@ -101,9 +101,10 @@ constexpr Score PBonus[RANK_NB][FILE_NB] =
Score psq[PIECE_NB][SQUARE_NB]; Score psq[PIECE_NB][SQUARE_NB];
// init() initializes piece-square tables: the white halves of the tables are
// copied from Bonus[] adding the piece value, then the black halves of the // PSQT::init() initializes piece-square tables: the white halves of the tables are
// tables are initialized by flipping and changing the sign of the white scores. // copied from Bonus[] and PBonus[], adding the piece value, then the black halves of
// the tables are initialized by flipping and changing the sign of the white scores.
void init() { void init() {
for (Piece pc : {W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING}) for (Piece pc : {W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING})
+18 -15
View File
@@ -525,7 +525,7 @@ void Thread::search() {
double totalTime = rootMoves.size() == 1 ? 0 : double totalTime = rootMoves.size() == 1 ? 0 :
Time.optimum() * fallingEval * reduction * bestMoveInstability; Time.optimum() * fallingEval * reduction * bestMoveInstability;
// Stop the search if we have exceeded the totalTime, at least 1ms search. // Stop the search if we have exceeded the totalTime, at least 1ms search
if (Time.elapsed() > totalTime) if (Time.elapsed() > totalTime)
{ {
// If we are allowed to ponder do not stop the search now but // If we are allowed to ponder do not stop the search now but
@@ -767,9 +767,10 @@ namespace {
// Step 6. Static evaluation of the position // Step 6. Static evaluation of the position
if (ss->inCheck) if (ss->inCheck)
{ {
// Skip early pruning when in check
ss->staticEval = eval = VALUE_NONE; ss->staticEval = eval = VALUE_NONE;
improving = false; improving = false;
goto moves_loop; // Skip early pruning when in check goto moves_loop;
} }
else if (ttHit) else if (ttHit)
{ {
@@ -1028,7 +1029,8 @@ moves_loop: // When in check, search starts from here
&& !(PvNode && abs(bestValue) < 2) && !(PvNode && abs(bestValue) < 2)
&& PieceValue[MG][type_of(movedPiece)] >= PieceValue[MG][type_of(pos.piece_on(to_sq(move)))] && PieceValue[MG][type_of(movedPiece)] >= PieceValue[MG][type_of(pos.piece_on(to_sq(move)))]
&& !ss->inCheck && !ss->inCheck
&& ss->staticEval + 267 + 391 * lmrDepth + PieceValue[MG][type_of(pos.piece_on(to_sq(move)))] <= alpha) && ss->staticEval + 267 + 391 * lmrDepth
+ PieceValue[MG][type_of(pos.piece_on(to_sq(move)))] <= alpha)
continue; continue;
// See based pruning // See based pruning
@@ -1074,8 +1076,8 @@ moves_loop: // When in check, search starts from here
else if (singularBeta >= beta) else if (singularBeta >= beta)
return singularBeta; return singularBeta;
// If the eval of ttMove is greater than beta we try also if there is an other move that // If the eval of ttMove is greater than beta we try also if there is another
// pushes it over beta, if so also produce a cutoff // move that pushes it over beta, if so also produce a cutoff.
else if (ttValue >= beta) else if (ttValue >= beta)
{ {
ss->excludedMove = move; ss->excludedMove = move;
@@ -1153,7 +1155,7 @@ moves_loop: // When in check, search starts from here
if (thisThread->ttHitAverage > 473 * TtHitAverageResolution * TtHitAverageWindow / 1024) if (thisThread->ttHitAverage > 473 * TtHitAverageResolution * TtHitAverageWindow / 1024)
r--; r--;
// Reduction if other threads are searching this position. // Reduction if other threads are searching this position
if (th.marked()) if (th.marked())
r++; r++;
@@ -1290,7 +1292,7 @@ moves_loop: // When in check, search starts from here
rm.pv.push_back(*m); rm.pv.push_back(*m);
// We record how often the best move has been changed in each // We record how often the best move has been changed in each
// iteration. This information is used for time management: When // iteration. This information is used for time management: when
// the best move changes frequently, we allocate some more time. // the best move changes frequently, we allocate some more time.
if (moveCount > 1) if (moveCount > 1)
++thisThread->bestMoveChanges; ++thisThread->bestMoveChanges;
@@ -1524,7 +1526,7 @@ moves_loop: // When in check, search starts from here
} }
} }
// Don't search moves with negative SEE values // Do not search moves with negative SEE values
if ( !ss->inCheck && !pos.see_ge(move)) if ( !ss->inCheck && !pos.see_ge(move))
continue; continue;
@@ -1571,7 +1573,7 @@ moves_loop: // When in check, search starts from here
} }
} }
// All legal moves have been searched. A special case: If we're in check // All legal moves have been searched. A special case: if we're in check
// and no legal moves were found, it is checkmate. // and no legal moves were found, it is checkmate.
if (ss->inCheck && bestValue == -VALUE_INFINITE) if (ss->inCheck && bestValue == -VALUE_INFINITE)
return mated_in(ss->ply); // Plies to mate from the root return mated_in(ss->ply); // Plies to mate from the root
@@ -1588,7 +1590,7 @@ moves_loop: // When in check, search starts from here
// value_to_tt() adjusts a mate or TB score from "plies to mate from the root" to // value_to_tt() adjusts a mate or TB score from "plies to mate from the root" to
// "plies to mate from the current position". standard scores are unchanged. // "plies to mate from the current position". Standard scores are unchanged.
// The function is called before storing a value in the transposition table. // The function is called before storing a value in the transposition table.
Value value_to_tt(Value v, int ply) { Value value_to_tt(Value v, int ply) {
@@ -1600,11 +1602,11 @@ moves_loop: // When in check, search starts from here
} }
// value_from_tt() is the inverse of value_to_tt(): It adjusts a mate or TB score // value_from_tt() is the inverse of value_to_tt(): it adjusts a mate or TB score
// from the transposition table (which refers to the plies to mate/be mated // from the transposition table (which refers to the plies to mate/be mated from
// from current position) to "plies to mate/be mated (TB win/loss) from the root". // current position) to "plies to mate/be mated (TB win/loss) from the root". However,
// However, for mate scores, to avoid potentially false mate scores related to the 50 moves rule, // for mate scores, to avoid potentially false mate scores related to the 50 moves rule
// and the graph history interaction, return an optimal TB score instead. // and the graph history interaction, we return an optimal TB score instead.
Value value_from_tt(Value v, int ply, int r50c) { Value value_from_tt(Value v, int ply, int r50c) {
@@ -1764,6 +1766,7 @@ moves_loop: // When in check, search starts from here
} // namespace } // namespace
/// MainThread::check_time() is used to print debug info and, more importantly, /// MainThread::check_time() is used to print debug info and, more importantly,
/// to detect when we are out of available time and thus stop the search. /// to detect when we are out of available time and thus stop the search.
+10 -3
View File
@@ -52,6 +52,7 @@ Thread::~Thread() {
stdThread.join(); stdThread.join();
} }
/// Thread::bestMoveCount(Move move) return best move counter for the given root move /// Thread::bestMoveCount(Move move) return best move counter for the given root move
int Thread::best_move_count(Move move) const { int Thread::best_move_count(Move move) const {
@@ -62,6 +63,7 @@ int Thread::best_move_count(Move move) const {
return rm != rootMoves.begin() + pvLast ? rm->bestMoveCount : 0; return rm != rootMoves.begin() + pvLast ? rm->bestMoveCount : 0;
} }
/// Thread::clear() reset histories, usually before a new game /// Thread::clear() reset histories, usually before a new game
void Thread::clear() { void Thread::clear() {
@@ -81,6 +83,7 @@ void Thread::clear() {
} }
} }
/// Thread::start_searching() wakes up the thread that will start the search /// Thread::start_searching() wakes up the thread that will start the search
void Thread::start_searching() { void Thread::start_searching() {
@@ -158,7 +161,8 @@ void ThreadPool::set(size_t requested) {
} }
} }
/// ThreadPool::clear() sets threadPool data to initial values.
/// ThreadPool::clear() sets threadPool data to initial values
void ThreadPool::clear() { void ThreadPool::clear() {
@@ -170,6 +174,7 @@ void ThreadPool::clear() {
main()->previousTimeReduction = 1.0; main()->previousTimeReduction = 1.0;
} }
/// ThreadPool::start_thinking() wakes up main thread waiting in idle_loop() and /// ThreadPool::start_thinking() wakes up main thread waiting in idle_loop() and
/// returns immediately. Main thread will wake up other threads and start the search. /// returns immediately. Main thread will wake up other threads and start the search.
@@ -250,7 +255,8 @@ Thread* ThreadPool::get_best_thread() const {
return bestThread; return bestThread;
} }
/// Start non-main threads.
/// Start non-main threads
void ThreadPool::start_searching() { void ThreadPool::start_searching() {
@@ -259,7 +265,8 @@ void ThreadPool::start_searching() {
th->start_searching(); th->start_searching();
} }
/// Wait for non-main threads.
/// Wait for non-main threads
void ThreadPool::wait_for_search_finished() const { void ThreadPool::wait_for_search_finished() const {
+3 -2
View File
@@ -28,8 +28,9 @@
TimeManagement Time; // Our global time management object TimeManagement Time; // Our global time management object
/// init() is called at the beginning of the search and calculates the bounds
/// of time allowed for the current game ply. We currently support: /// TimeManagement::init() is called at the beginning of the search and calculates
/// the bounds of time allowed for the current game ply. We currently support:
// 1) x basetime (+ z increment) // 1) x basetime (+ z increment)
// 2) x moves in y seconds (+ z increment) // 2) x moves in y seconds (+ z increment)
+2 -1
View File
@@ -30,7 +30,7 @@
TranspositionTable TT; // Our global transposition table TranspositionTable TT; // Our global transposition table
/// TTEntry::save populates the TTEntry with a new node's data, possibly /// TTEntry::save() populates the TTEntry with a new node's data, possibly
/// overwriting an old position. Update is not atomic and can be racy. /// overwriting an old position. Update is not atomic and can be racy.
void TTEntry::save(Key k, Value v, bool pv, Bound b, Depth d, Move m, Value ev) { void TTEntry::save(Key k, Value v, bool pv, Bound b, Depth d, Move m, Value ev) {
@@ -107,6 +107,7 @@ void TranspositionTable::clear() {
th.join(); th.join();
} }
/// TranspositionTable::probe() looks up the current position in the transposition /// TranspositionTable::probe() looks up the current position in the transposition
/// table. It returns true and a pointer to the TTEntry if the position is found. /// table. It returns true and a pointer to the TTEntry if the position is found.
/// Otherwise, it returns false and a pointer to an empty or least valuable TTEntry /// Otherwise, it returns false and a pointer to an empty or least valuable TTEntry
+2 -2
View File
@@ -60,8 +60,8 @@ private:
/// A TranspositionTable is an array of Cluster, of size clusterCount. Each /// A TranspositionTable is an array of Cluster, of size clusterCount. Each
/// cluster consists of ClusterSize number of TTEntry. Each non-empty TTEntry /// cluster consists of ClusterSize number of TTEntry. Each non-empty TTEntry
/// contains information on exactly one position. The size of a Cluster should /// contains information on exactly one position. The size of a Cluster should
/// divide the size of a cache line for best performance, /// divide the size of a cache line for best performance, as the cacheline is
/// as the cacheline is prefetched when possible. /// prefetched when possible.
class TranspositionTable { class TranspositionTable {
+1 -1
View File
@@ -70,7 +70,7 @@ static void make_option(const string& n, int v, const SetRange& r) {
Options[n] << UCI::Option(v, r(v).first, r(v).second, on_tune); Options[n] << UCI::Option(v, r(v).first, r(v).second, on_tune);
LastOption = &Options[n]; LastOption = &Options[n];
// Print formatted parameters, ready to be copy-pasted in fishtest // Print formatted parameters, ready to be copy-pasted in Fishtest
std::cout << n << "," std::cout << n << ","
<< v << "," << v << ","
<< r(v).first << "," << r(v).second << "," << r(v).first << "," << r(v).second << ","
+3 -3
View File
@@ -349,16 +349,16 @@ constexpr Color operator~(Color c) {
return Color(c ^ BLACK); // Toggle color return Color(c ^ BLACK); // Toggle color
} }
constexpr Square flip_rank(Square s) { constexpr Square flip_rank(Square s) { // Swap A1 <-> A8
return Square(s ^ SQ_A8); return Square(s ^ SQ_A8);
} }
constexpr Square flip_file(Square s) { constexpr Square flip_file(Square s) { // Swap A1 <-> H1
return Square(s ^ SQ_H1); return Square(s ^ SQ_H1);
} }
constexpr Piece operator~(Piece pc) { constexpr Piece operator~(Piece pc) {
return Piece(pc ^ 8); // Swap color of piece B_KNIGHT -> W_KNIGHT return Piece(pc ^ 8); // Swap color of piece B_KNIGHT <-> W_KNIGHT
} }
constexpr CastlingRights operator&(Color c, CastlingRights cr) { constexpr CastlingRights operator&(Color c, CastlingRights cr) {
+1 -1
View File
@@ -52,7 +52,7 @@ bool CaseInsensitiveLess::operator() (const string& s1, const string& s2) const
} }
/// init() initializes the UCI options to their hard-coded default values /// UCI::init() initializes the UCI options to their hard-coded default values
void init(OptionsMap& o) { void init(OptionsMap& o) {