From bbe98576846ad44ca531cdb6f42bf3eefa7d47c5 Mon Sep 17 00:00:00 2001 From: Vizvezdenec Date: Tue, 23 Jun 2020 14:55:52 +0300 Subject: [PATCH 1/5] Do less futility pruning for captures. The idea of this patch is that if capture can be described as "less valuable piece takes more valuable piece" it's not really correct to add only piece value of captured piece to static evaluation since there can be more threats in other places and opponent can't really do much but recapture our capturing piece which leaves us space for more captures thus winning more material and increasing static eval. passed STC https://tests.stockfishchess.org/tests/view/5ef0167b122d6514328d760f LLR: 2.96 (-2.94,2.94) {-0.50,1.50} Total: 24736 W: 4838 L: 4607 D: 15291 Ptnml(0-2): 438, 2812, 5648, 3021, 449 passed LTC https://tests.stockfishchess.org/tests/view/5ef073bc122d6514328d7693 LLR: 2.93 (-2.94,2.94) {0.25,1.75} Total: 46152 W: 5865 L: 5567 D: 34720 Ptnml(0-2): 312, 4160, 13886, 4354, 364 closes https://github.com/official-stockfish/Stockfish/pull/2761 bench 4789930 --- src/search.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/search.cpp b/src/search.cpp index 563d1aab..671ac489 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1026,6 +1026,7 @@ moves_loop: // When in check, search starts from here if ( !givesCheck && lmrDepth < 6 && !(PvNode && abs(bestValue) < 2) + && PieceValue[MG][type_of(movedPiece)] >= PieceValue[MG][type_of(pos.piece_on(to_sq(move)))] && !ss->inCheck && ss->staticEval + 267 + 391 * lmrDepth + PieceValue[MG][type_of(pos.piece_on(to_sq(move)))] <= alpha) continue; From 527d832a6de81c455cc8818e85c309fa1443f862 Mon Sep 17 00:00:00 2001 From: Niklas Fiekas Date: Tue, 23 Jun 2020 10:41:53 +0200 Subject: [PATCH 2/5] Support ARCH=armv8 in Makefile (#2355) Tested with bench run after compiling with - g++ (Debian 6.3.0-18+deb9u1) 6.3.0 20170516 - clang version 3.8.1-24 on ThunderX CN8890. closes https://github.com/official-stockfish/Stockfish/pull/2760 fixes https://github.com/official-stockfish/Stockfish/issues/2355 No functional change. --- src/Makefile | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Makefile b/src/Makefile index 41c2aff6..83e0bb14 100644 --- a/src/Makefile +++ b/src/Makefile @@ -133,6 +133,12 @@ ifeq ($(ARCH),armv7) prefetch = yes endif +ifeq ($(ARCH),armv8) + arch = armv8-a + bits = 64 + prefetch = yes +endif + ifeq ($(ARCH),ppc-32) arch = ppc endif @@ -164,7 +170,7 @@ ifeq ($(COMP),gcc) CXX=g++ CXXFLAGS += -pedantic -Wextra -Wshadow - ifeq ($(ARCH),armv7) + ifeq ($(ARCH),$(filter $(ARCH),armv7 armv8)) ifeq ($(OS),Android) CXXFLAGS += -m$(bits) LDFLAGS += -m$(bits) @@ -221,7 +227,7 @@ ifeq ($(COMP),clang) endif endif - ifeq ($(ARCH),armv7) + ifeq ($(ARCH),$(filter $(ARCH),armv7 armv8)) ifeq ($(OS),Android) CXXFLAGS += -m$(bits) LDFLAGS += -m$(bits) @@ -391,6 +397,7 @@ help: @echo "ppc-64 > PPC 64-bit" @echo "ppc-32 > PPC 32-bit" @echo "armv7 > ARMv7 32-bit" + @echo "armv8 > ARMv8 64-bit" @echo "general-64 > unspecified 64-bit" @echo "general-32 > unspecified 32-bit" @echo "" @@ -492,7 +499,8 @@ config-sanity: @test "$(sanitize)" = "undefined" || test "$(sanitize)" = "thread" || test "$(sanitize)" = "address" || test "$(sanitize)" = "no" @test "$(optimize)" = "yes" || test "$(optimize)" = "no" @test "$(arch)" = "any" || test "$(arch)" = "x86_64" || test "$(arch)" = "i386" || \ - test "$(arch)" = "ppc64" || test "$(arch)" = "ppc" || test "$(arch)" = "armv7" + test "$(arch)" = "ppc64" || test "$(arch)" = "ppc" || \ + test "$(arch)" = "armv7" || test "$(arch)" = "armv8-a" @test "$(bits)" = "32" || test "$(bits)" = "64" @test "$(prefetch)" = "yes" || test "$(prefetch)" = "no" @test "$(popcnt)" = "yes" || test "$(popcnt)" = "no" From 208c53df0fc289466def7deae58f687957efb734 Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Wed, 24 Jun 2020 16:23:31 +0200 Subject: [PATCH 3/5] Remove 'Minimum Thinking Time' UCI option. the option was, since at least 2014, not correctly implemented, ignoring all dynamic adjustments to optimum time in search. Instead of fixing it, remove it, no need to expose an option that will influence time management negatively. closes https://github.com/official-stockfish/Stockfish/pull/2765 No functional change. --- src/timeman.cpp | 3 +-- src/ucioption.cpp | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/timeman.cpp b/src/timeman.cpp index d27962b7..a61c36d7 100644 --- a/src/timeman.cpp +++ b/src/timeman.cpp @@ -35,7 +35,6 @@ TimeManagement Time; // Our global time management object void TimeManagement::init(Search::LimitsType& limits, Color us, int ply) { - TimePoint minThinkingTime = TimePoint(Options["Minimum Thinking Time"]); TimePoint moveOverhead = TimePoint(Options["Move Overhead"]); TimePoint slowMover = TimePoint(Options["Slow Mover"]); TimePoint npmsec = TimePoint(Options["nodestime"]); @@ -91,7 +90,7 @@ void TimeManagement::init(Search::LimitsType& limits, Color us, int ply) { } // Never use more than 80% of the available time for this move - optimumTime = std::max(minThinkingTime, TimePoint(opt_scale * timeLeft)); + optimumTime = TimePoint(opt_scale * timeLeft); maximumTime = TimePoint(std::min(0.8 * limits.time[us] - moveOverhead, max_scale * optimumTime)); if (Options["Ponder"]) diff --git a/src/ucioption.cpp b/src/ucioption.cpp index 7037ea57..871edb29 100644 --- a/src/ucioption.cpp +++ b/src/ucioption.cpp @@ -68,7 +68,6 @@ void init(OptionsMap& o) { o["MultiPV"] << Option(1, 1, 500); o["Skill Level"] << Option(20, 0, 20); o["Move Overhead"] << Option(10, 0, 5000); - o["Minimum Thinking Time"] << Option( 0, 0, 5000); o["Slow Mover"] << Option(100, 10, 1000); o["nodestime"] << Option(0, 0, 10000); o["UCI_Chess960"] << Option(false); From 11483fe6d942a4fee6fa272f72251d6b6d6d7454 Mon Sep 17 00:00:00 2001 From: UnaiCorzo Date: Tue, 23 Jun 2020 17:56:38 +0200 Subject: [PATCH 4/5] Makefile: support lto on mingw, default to 64bits Clean and organize uppercase and spaces fixes https://github.com/official-stockfish/Stockfish/issues/2731 closes https://github.com/official-stockfish/Stockfish/pull/2763 No functional change --- AUTHORS | 1 + src/Makefile | 34 +++++++++++----------------------- 2 files changed, 12 insertions(+), 23 deletions(-) diff --git a/AUTHORS b/AUTHORS index 1cd7ff54..f08d71d3 100644 --- a/AUTHORS +++ b/AUTHORS @@ -155,6 +155,7 @@ Tom Vijlbrief (tomtor) Tomasz Sobczyk (Sopel97) Torsten Franz (torfranz, tfranzer) Tracey Emery (basepr1me) +Unai Corzo (unaiic) Uri Blass (uriblass) Vince Negri (cuddlestmonkey) diff --git a/src/Makefile b/src/Makefile index 83e0bb14..81731e66 100644 --- a/src/Makefile +++ b/src/Makefile @@ -54,7 +54,7 @@ endif ### Section 2. High-level Configuration ### ========================================================================== # -# flag --- Comp switch --- Description +# flag --- Comp switch --- Description # ---------------------------------------------------------------------------- # # debug = yes/no --- -DNDEBUG --- Enable/Disable debug mode @@ -77,43 +77,42 @@ endif optimize = yes debug = no sanitize = no -bits = 32 +bits = 64 prefetch = no popcnt = no sse = no pext = no ### 2.2 Architecture specific - ifeq ($(ARCH),general-32) arch = any + bits = 32 endif ifeq ($(ARCH),x86-32-old) arch = i386 + bits = 32 endif ifeq ($(ARCH),x86-32) arch = i386 + bits = 32 prefetch = yes sse = yes endif ifeq ($(ARCH),general-64) arch = any - bits = 64 endif ifeq ($(ARCH),x86-64) arch = x86_64 - bits = 64 prefetch = yes sse = yes endif ifeq ($(ARCH),x86-64-modern) arch = x86_64 - bits = 64 prefetch = yes popcnt = yes sse = yes @@ -121,7 +120,6 @@ endif ifeq ($(ARCH),x86-64-bmi2) arch = x86_64 - bits = 64 prefetch = yes popcnt = yes sse = yes @@ -131,6 +129,7 @@ endif ifeq ($(ARCH),armv7) arch = armv7 prefetch = yes + bits = 32 endif ifeq ($(ARCH),armv8) @@ -141,22 +140,20 @@ endif ifeq ($(ARCH),ppc-32) arch = ppc + bits = 32 endif ifeq ($(ARCH),ppc-64) arch = ppc64 - bits = 64 popcnt = yes prefetch = yes endif - ### ========================================================================== -### Section 3. Low-level configuration +### Section 3. Low-level Configuration ### ========================================================================== ### 3.1 Selecting compiler (default = gcc) - CXXFLAGS += -Wall -Wcast-qual -fno-exceptions -std=c++11 $(EXTRACXXFLAGS) DEPENDFLAGS += -std=c++11 LDFLAGS += $(EXTRALDFLAGS) @@ -347,17 +344,10 @@ endif ### needs access to the optimization flags. ifeq ($(optimize),yes) ifeq ($(debug), no) - ifeq ($(comp),$(filter $(comp),gcc clang)) + ifeq ($(comp),$(filter $(comp),gcc clang mingw)) CXXFLAGS += -flto LDFLAGS += $(CXXFLAGS) endif - - ifeq ($(comp),mingw) - ifeq ($(KERNEL),Linux) - CXXFLAGS += -flto - LDFLAGS += $(CXXFLAGS) - endif - endif endif endif @@ -368,9 +358,8 @@ ifeq ($(OS), Android) LDFLAGS += -fPIE -pie endif - ### ========================================================================== -### Section 4. Public targets +### Section 4. Public Targets ### ========================================================================== help: @@ -468,7 +457,7 @@ default: help ### ========================================================================== -### Section 5. Private targets +### Section 5. Private Targets ### ========================================================================== all: $(EXE) .depend @@ -551,4 +540,3 @@ icc-profile-use: -@$(CXX) $(DEPENDFLAGS) -MM $(SRCS) > $@ 2> /dev/null -include .depend - From ab5cd8340f2f7f8730aa7c77476edf4a98a166e4 Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Wed, 24 Jun 2020 22:19:58 +0200 Subject: [PATCH 5/5] Small cleanups closes https://github.com/official-stockfish/Stockfish/pull/2756 No functional change --- src/bitboard.h | 29 ++++++++++++++++++----------- src/endgame.cpp | 14 +++++++------- src/evaluate.cpp | 26 +++++++++++++++----------- src/material.cpp | 19 +++++++++++-------- src/material.h | 2 +- src/misc.cpp | 21 ++++++++++++--------- src/pawns.cpp | 7 +++++++ src/position.cpp | 4 ++-- src/position.h | 1 + src/psqt.cpp | 11 ++++++----- src/search.cpp | 35 +++++++++++++++++++---------------- src/thread.cpp | 13 ++++++++++--- src/timeman.cpp | 11 ++++++----- src/tt.cpp | 3 ++- src/tt.h | 4 ++-- src/tune.cpp | 2 +- src/types.h | 6 +++--- src/ucioption.cpp | 2 +- 18 files changed, 124 insertions(+), 86 deletions(-) diff --git a/src/bitboard.h b/src/bitboard.h index 0f55810c..1c598108 100644 --- a/src/bitboard.h +++ b/src/bitboard.h @@ -110,6 +110,7 @@ inline Bitboard square_bb(Square s) { return SquareBB[s]; } + /// 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. @@ -200,10 +201,11 @@ inline Bitboard adjacent_files_bb(Square s) { return shift(file_bb(s)) | shift(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. -/// If the given squares are not on a same file/rank/diagonal, return 0. -/// Ex. line_bb(SQ_C4, SQ_F7) returns a bitboard with the A2-G8 diagonal. + +/// line_bb(Square, Square) returns a bitboard representing an entire line, +/// from board edge to board edge, that intersects the given squares. If the +/// 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) { @@ -211,10 +213,11 @@ inline Bitboard line_bb(Square s1, Square s2) { return LineBB[s1][s2]; } -/// between_bb() returns a Bitboard representing squares that are linearly -/// between the given squares (excluding the given squares). -/// If the given squares are not on a same file/rank/diagonal, return 0. -/// Ex. between_bb(SQ_C4, SQ_F7) returns a bitboard with squares D5 and E6. + +/// between_bb() returns a bitboard representing squares that are linearly +/// between the given squares (excluding the given squares). If the given +/// 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) { 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 -/// be attacked by a pawn of the given color when it moves along its file, -/// starting from the given square. +/// be attacked by a pawn of the given color when it moves along its file, starting +/// from the given square. inline Bitboard pawn_attack_span(Color c, Square s) { return forward_ranks_bb(c, s) & adjacent_files_bb(s); @@ -276,7 +279,9 @@ template<> inline int distance(Square x, Square y) { return SquareDistan 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)); } -/// 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) { @@ -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); } + /// attacks_bb(Square) returns the pseudo attacks of the give piece type /// assuming an empty board. @@ -295,6 +301,7 @@ inline Bitboard attacks_bb(Square s) { return PseudoAttacks[Pt][s]; } + /// attacks_bb(Square, Bitboard) returns the attacks by the given piece /// assuming the board is occupied according to the passed Bitboard. /// Sliding piece attacks do not continue passed an occupied square. diff --git a/src/endgame.cpp b/src/endgame.cpp index d9e76348..be0755a8 100644 --- a/src/endgame.cpp +++ b/src/endgame.cpp @@ -268,7 +268,7 @@ Value Endgame::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 /// 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. @@ -291,7 +291,7 @@ Value Endgame::operator()(const Position& pos) const { /// 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<> Value Endgame::operator()(const Position& pos) const { @@ -352,7 +352,7 @@ ScaleFactor Endgame::operator()(const Position& pos) const { Square weakPawn = frontmost_sq(strongSide, pos.pieces(weakSide, PAWN)); // 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 && (strongPawns & (weakPawn + pawn_push(weakSide))) && (opposite_colors(strongBishop, weakPawn) || !more_than_one(strongPawns))) @@ -365,7 +365,7 @@ ScaleFactor Endgame::operator()(const Position& pos) const { // closer. (I think this rule only fails in practically // unreachable positions such as 5k1K/6p1/6P1/8/8/3B4/8/8 w // 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 && weakKingDist <= 2 && weakKingDist <= strongKingDist) @@ -576,7 +576,7 @@ ScaleFactor Endgame::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. template<> ScaleFactor Endgame::operator()(const Position& pos) const { @@ -693,7 +693,7 @@ ScaleFactor Endgame::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 stronger side's bishop, it's a draw. template<> @@ -717,7 +717,7 @@ ScaleFactor Endgame::operator()(const Position& pos) const { /// 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 /// 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). diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 8b4a27bc..60ec9c72 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -127,23 +127,23 @@ namespace { }; // Assorted bonuses and penalties - constexpr Score BishopPawns = S( 3, 7); + constexpr Score BishopKingProtector = S( 6, 9); 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 CorneredBishop = S( 50, 50); constexpr Score FlankAttacks = S( 8, 0); constexpr Score Hanging = S( 69, 36); - constexpr Score BishopKingProtector = S( 6, 9); constexpr Score KnightKingProtector = S( 8, 9); constexpr Score KnightOnQueen = S( 16, 11); + constexpr Score KnightOutpost = S( 56, 36); constexpr Score LongDiagonalBishop = S( 45, 0); 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 PawnlessFlank = S( 17, 95); constexpr Score QueenInfiltration = S( -2, 14); + constexpr Score ReachableOutpost = S( 31, 22); constexpr Score RestrictedPiece = S( 7, 7); constexpr Score RookOnKingRing = S( 16, 0); constexpr Score RookOnQueenFile = S( 6, 11); @@ -152,8 +152,9 @@ namespace { constexpr Score ThreatByPawnPush = S( 48, 39); constexpr Score ThreatBySafePawn = S(173, 94); constexpr Score TrappedRook = S( 55, 13); - constexpr Score WeakQueen = S( 56, 15); constexpr Score WeakQueenProtection = S( 14, 0); + constexpr Score WeakQueen = S( 56, 15); + #undef S @@ -216,6 +217,7 @@ namespace { // 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. + template template void Evaluation::initialize() { @@ -255,6 +257,7 @@ namespace { // Evaluation::pieces() scores pieces of a given color and type + template template Score Evaluation::pieces() { @@ -377,7 +380,7 @@ namespace { // Bonus for queen on weak square in enemy camp if (relative_rank(Us, s) > RANK_4 && (~pe->pawn_attacks_span(Them) & s)) - score += QueenInfiltration; + score += QueenInfiltration; } } if (T) @@ -388,6 +391,7 @@ namespace { // Evaluation::king() assigns bonuses and penalties to a king of a given color + template template Score Evaluation::king() const { @@ -496,6 +500,7 @@ namespace { // Evaluation::threats() assigns bonuses according to the types of the // attacking and the attacked pieces. + template template Score Evaluation::threats() const { @@ -721,8 +726,8 @@ namespace { // Evaluation::winnable() adjusts the mg and eg score components based on the - // known attacking/defending status of the players. - // A single value is derived from the mg and eg values and returned. + // known attacking/defending status of the players. A single value is derived + // by interpolation from the mg and eg values and returned. template Value Evaluation::winnable(Score score) const { @@ -828,12 +833,11 @@ namespace { return pos.side_to_move() == WHITE ? v : -v; // Main evaluation begins here - initialize(); initialize(); // 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() - pieces() + pieces() - pieces() + pieces() - pieces() diff --git a/src/material.cpp b/src/material.cpp index 93699f5f..bb25d3ca 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -44,12 +44,12 @@ namespace { constexpr int QuadraticTheirs[][PIECE_TYPE_NB] = { // THEIR PIECES // pair pawn knight bishop rook queen - { 0 }, // Bishop pair - { 36, 0 }, // Pawn - { 9, 63, 0 }, // Knight OUR PIECES - { 59, 65, 42, 0 }, // Bishop - { 46, 39, 24, -24, 0 }, // Rook - { 97, 100, -42, 137, 268, 0 } // Queen + { }, // Bishop pair + { 36, }, // Pawn + { 9, 63, }, // Knight OUR PIECES + { 59, 65, 42, }, // Bishop + { 46, 39, 24, -24, }, // Rook + { 97, 100, -42, 137, 268, } // Queen }; // Endgame evaluation and scaling functions are accessed directly and not through @@ -79,8 +79,10 @@ namespace { && pos.count(~us) >= 1; } + /// imbalance() calculates the imbalance by comparing the piece count of each /// piece type for both colors. + template int imbalance(const int pieceCount[][PIECE_TYPE_NB]) { @@ -94,9 +96,9 @@ namespace { if (!pieceCount[Us][pt1]) 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] + QuadraticTheirs[pt1][pt2] * pieceCount[Them][pt2]; @@ -110,6 +112,7 @@ namespace { namespace Material { + /// 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 /// is found. Otherwise a new Entry is computed and stored there, so we don't diff --git a/src/material.h b/src/material.h index 9ab1d81c..21647f23 100644 --- a/src/material.h +++ b/src/material.h @@ -44,7 +44,7 @@ struct Entry { bool specialized_eval_exists() const { return evaluationFunction != nullptr; } 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 // 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 diff --git a/src/misc.cpp b/src/misc.cpp index c6254784..2bc05c5b 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -294,9 +294,10 @@ void prefetch(void* addr) { #endif -/// 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. -/// With c++17 some of this functionality can be simplified. +/// 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. With c++17 some of this functionality could be simplified. + #if defined(__linux__) && !defined(__ANDROID__) 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; // 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( hProcessToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &prevTp, &prevTpLen) && 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); mem = VirtualAlloc( 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); } } @@ -360,7 +361,7 @@ void* aligned_ttmem_alloc(size_t allocSize, void*& mem) { static bool firstCall = true; - // try to allocate large pages + // Try to allocate large pages mem = aligned_ttmem_alloc_large_pages(allocSize); // 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; - // fall back to regular, page aligned, allocation if necessary + // Fall back to regular, page aligned, allocation if necessary if (!mem) mem = VirtualAlloc(NULL, allocSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); @@ -394,7 +395,9 @@ void* aligned_ttmem_alloc(size_t allocSize, void*& mem) { #endif -/// aligned_ttmem_free will free the previously allocated ttmem + +/// aligned_ttmem_free() will free the previously allocated ttmem + #if defined(_WIN64) void aligned_ttmem_free(void* mem) { diff --git a/src/pawns.cpp b/src/pawns.cpp index 597dff2b..d741b2ef 100644 --- a/src/pawns.cpp +++ b/src/pawns.cpp @@ -66,6 +66,12 @@ namespace { #undef S #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 Score evaluate(const Position& pos, Pawns::Entry* e) { @@ -170,6 +176,7 @@ namespace { namespace Pawns { + /// 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 /// is found. Otherwise a new Entry is computed and stored there, so we don't diff --git a/src/position.cpp b/src/position.cpp index c9db6224..471ef01f 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -105,8 +105,7 @@ Key cuckoo[8192]; Move cuckooMove[8192]; -/// Position::init() initializes at startup the various arrays used to compute -/// hash keys. +/// Position::init() initializes at startup the various arrays used to compute hash keys void Position::init() { @@ -1112,6 +1111,7 @@ bool Position::see_ge(Move m, Value threshold) const { return bool(res); } + /// Position::is_draw() tests whether the position is drawn by 50-move rule /// or by repetition. It does not detect stalemates. diff --git a/src/position.h b/src/position.h index 8f8c8f7a..8cfa3920 100644 --- a/src/position.h +++ b/src/position.h @@ -56,6 +56,7 @@ struct StateInfo { int repetition; }; + /// 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 /// 'draw by repetition' detection. Use a std::deque because pointers to diff --git a/src/psqt.cpp b/src/psqt.cpp index 27c7a36f..c5da9785 100644 --- a/src/psqt.cpp +++ b/src/psqt.cpp @@ -101,9 +101,10 @@ constexpr Score PBonus[RANK_NB][FILE_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 -// tables are initialized by flipping and changing the sign of the white scores. + +// PSQT::init() initializes piece-square tables: the white halves of the tables are +// 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() { for (Piece pc : {W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING}) @@ -113,8 +114,8 @@ void init() { for (Square s = SQ_A1; s <= SQ_H8; ++s) { File f = File(edge_distance(file_of(s))); - psq[ pc][ s] = score + (type_of(pc) == PAWN ? PBonus[rank_of(s)][file_of(s)] - : Bonus[pc][rank_of(s)][f]); + psq[ pc][s] = score + (type_of(pc) == PAWN ? PBonus[rank_of(s)][file_of(s)] + : Bonus[pc][rank_of(s)][f]); psq[~pc][flip_rank(s)] = -psq[pc][s]; } } diff --git a/src/search.cpp b/src/search.cpp index 671ac489..1e2980cb 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -525,7 +525,7 @@ void Thread::search() { double totalTime = rootMoves.size() == 1 ? 0 : 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 we are allowed to ponder do not stop the search now but @@ -627,7 +627,7 @@ namespace { || pos.is_draw(ss->ply) || ss->ply >= MAX_PLY) return (ss->ply >= MAX_PLY && !ss->inCheck) ? evaluate(pos) - : value_draw(pos.this_thread()); + : value_draw(pos.this_thread()); // Step 3. Mate distance pruning. Even if we mate at the next move our score // would be at best mate_in(ss->ply+1), but if alpha is already bigger because @@ -767,9 +767,10 @@ namespace { // Step 6. Static evaluation of the position if (ss->inCheck) { + // Skip early pruning when in check ss->staticEval = eval = VALUE_NONE; improving = false; - goto moves_loop; // Skip early pruning when in check + goto moves_loop; } else if (ttHit) { @@ -1028,7 +1029,8 @@ moves_loop: // When in check, search starts from here && !(PvNode && abs(bestValue) < 2) && PieceValue[MG][type_of(movedPiece)] >= PieceValue[MG][type_of(pos.piece_on(to_sq(move)))] && !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; // See based pruning @@ -1074,8 +1076,8 @@ moves_loop: // When in check, search starts from here else if (singularBeta >= beta) return singularBeta; - // If the eval of ttMove is greater than beta we try also if there is an other move that - // pushes it over beta, if so also produce a cutoff + // If the eval of ttMove is greater than beta we try also if there is another + // move that pushes it over beta, if so also produce a cutoff. else if (ttValue >= beta) { ss->excludedMove = move; @@ -1153,7 +1155,7 @@ moves_loop: // When in check, search starts from here if (thisThread->ttHitAverage > 473 * TtHitAverageResolution * TtHitAverageWindow / 1024) r--; - // Reduction if other threads are searching this position. + // Reduction if other threads are searching this position if (th.marked()) r++; @@ -1290,7 +1292,7 @@ moves_loop: // When in check, search starts from here rm.pv.push_back(*m); // 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. if (moveCount > 1) ++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)) 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. if (ss->inCheck && bestValue == -VALUE_INFINITE) 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 - // "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. 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 - // from the transposition table (which refers to the plies to mate/be mated - // from current position) to "plies to mate/be mated (TB win/loss) from the root". - // However, 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. + // 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 + // current position) to "plies to mate/be mated (TB win/loss) from the root". However, + // for mate scores, to avoid potentially false mate scores related to the 50 moves rule + // and the graph history interaction, we return an optimal TB score instead. Value value_from_tt(Value v, int ply, int r50c) { @@ -1764,6 +1766,7 @@ moves_loop: // When in check, search starts from here } // namespace + /// 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. diff --git a/src/thread.cpp b/src/thread.cpp index a27a60c6..a0ee2b25 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -52,6 +52,7 @@ Thread::~Thread() { stdThread.join(); } + /// Thread::bestMoveCount(Move move) return best move counter for the given root move 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; } + /// Thread::clear() reset histories, usually before a new game void Thread::clear() { @@ -81,6 +83,7 @@ void Thread::clear() { } } + /// Thread::start_searching() wakes up the thread that will start the search 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() { @@ -170,6 +174,7 @@ void ThreadPool::clear() { main()->previousTimeReduction = 1.0; } + /// 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. @@ -250,7 +255,8 @@ Thread* ThreadPool::get_best_thread() const { return bestThread; } -/// Start non-main threads. + +/// Start non-main threads void ThreadPool::start_searching() { @@ -259,7 +265,8 @@ void ThreadPool::start_searching() { th->start_searching(); } -/// Wait for non-main threads. + +/// Wait for non-main threads void ThreadPool::wait_for_search_finished() const { diff --git a/src/timeman.cpp b/src/timeman.cpp index a61c36d7..546eadd2 100644 --- a/src/timeman.cpp +++ b/src/timeman.cpp @@ -28,10 +28,11 @@ 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: -// 1) x basetime (+z increment) -// 2) x moves in y seconds (+z increment) + +/// 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) +// 2) x moves in y seconds (+ z increment) void TimeManagement::init(Search::LimitsType& limits, Color us, int ply) { @@ -60,7 +61,7 @@ void TimeManagement::init(Search::LimitsType& limits, Color us, int ply) { startTime = limits.startTime; - //Maximum move horizon of 50 moves + // Maximum move horizon of 50 moves int mtg = limits.movestogo ? std::min(limits.movestogo, 50) : 50; // Make sure timeLeft is > 0 since we may use it as a divisor diff --git a/src/tt.cpp b/src/tt.cpp index d0a5d4e0..34590903 100644 --- a/src/tt.cpp +++ b/src/tt.cpp @@ -30,7 +30,7 @@ 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. 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(); } + /// 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. /// Otherwise, it returns false and a pointer to an empty or least valuable TTEntry diff --git a/src/tt.h b/src/tt.h index 3e1d0e99..e18db8ce 100644 --- a/src/tt.h +++ b/src/tt.h @@ -60,8 +60,8 @@ private: /// A TranspositionTable is an array of Cluster, of size clusterCount. Each /// cluster consists of ClusterSize number of TTEntry. Each non-empty TTEntry /// contains information on exactly one position. The size of a Cluster should -/// divide the size of a cache line for best performance, -/// as the cacheline is prefetched when possible. +/// divide the size of a cache line for best performance, as the cacheline is +/// prefetched when possible. class TranspositionTable { diff --git a/src/tune.cpp b/src/tune.cpp index 696b4cb8..c1b1c76b 100644 --- a/src/tune.cpp +++ b/src/tune.cpp @@ -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); 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 << "," << v << "," << r(v).first << "," << r(v).second << "," diff --git a/src/types.h b/src/types.h index 969d4e65..0c512f5b 100644 --- a/src/types.h +++ b/src/types.h @@ -349,16 +349,16 @@ constexpr Color operator~(Color c) { 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); } -constexpr Square flip_file(Square s) { +constexpr Square flip_file(Square s) { // Swap A1 <-> H1 return Square(s ^ SQ_H1); } 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) { diff --git a/src/ucioption.cpp b/src/ucioption.cpp index 871edb29..c268c975 100644 --- a/src/ucioption.cpp +++ b/src/ucioption.cpp @@ -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) {