1
0
Fork 0
mirror of https://github.com/sockspls/badfish synced 2025-04-30 08:43:09 +00:00

Merge branch 'master' into sf-nnue-nodchip

This commit is contained in:
joergoster 2020-06-25 15:10:12 +02:00
commit 151a0dda91
20 changed files with 149 additions and 115 deletions

View file

@ -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)

View file

@ -69,7 +69,7 @@ endif
### Section 2. High-level Configuration
### ==========================================================================
#
# flag --- Comp switch --- Description
# flag --- Comp switch --- Description
# ----------------------------------------------------------------------------
#
# debug = yes/no --- -DNDEBUG --- Enable/Disable debug mode
@ -92,7 +92,7 @@ endif
optimize = yes
debug = no
sanitize = no
bits = 32
bits = 64
prefetch = no
popcnt = no
sse = no
@ -100,36 +100,35 @@ avx2 = 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
@ -146,7 +145,6 @@ endif
ifeq ($(ARCH),x86-64-bmi2)
arch = x86_64
bits = 64
prefetch = yes
popcnt = yes
sse = yes
@ -157,26 +155,31 @@ endif
ifeq ($(ARCH),armv7)
arch = armv7
prefetch = yes
bits = 32
endif
ifeq ($(ARCH),armv8)
arch = armv8-a
bits = 64
prefetch = yes
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++17 $(EXTRACXXFLAGS)
DEPENDFLAGS += -std=c++17
LDFLAGS += $(EXTRALDFLAGS)
@ -190,7 +193,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)
@ -247,7 +250,7 @@ ifeq ($(COMP),clang)
endif
endif
ifeq ($(ARCH),armv7)
ifeq ($(ARCH),$(filter $(ARCH),armv7 armv8))
ifeq ($(OS),Android)
CXXFLAGS += -m$(bits)
LDFLAGS += -m$(bits)
@ -396,17 +399,10 @@ endif
### needs access to the optimization flags.
ifeq ($(optimize),yes)
ifeq ($(debug), no)
ifeq ($(comp),$(filter $(comp),gcc clang msys2))
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
@ -417,9 +413,8 @@ ifeq ($(OS), Android)
LDFLAGS += -fPIE -pie
endif
### ==========================================================================
### Section 4. Public targets
### Section 4. Public Targets
### ==========================================================================
help:
@ -447,6 +442,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 ""
@ -518,7 +514,7 @@ default:
help
### ==========================================================================
### Section 5. Private targets
### Section 5. Private Targets
### ==========================================================================
all: $(EXE) .depend
@ -550,7 +546,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"
@ -613,4 +610,3 @@ nnue-learn-use-blas: config-sanity
-@$(CXX) $(DEPENDFLAGS) -MM $(OBJS:.o=.cpp) > $@ 2> /dev/null
-include .depend

View file

@ -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<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.
/// 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>(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.

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
/// 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<KQKR>::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<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));
// 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<KBPsK>::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<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.
template<>
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 stronger side's bishop, it's a draw.
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 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).

View file

@ -129,23 +129,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);
@ -154,8 +154,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
@ -218,6 +219,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<Tracing T> template<Color Us>
void Evaluation<T>::initialize() {
@ -257,6 +259,7 @@ namespace {
// Evaluation::pieces() scores pieces of a given color and type
template<Tracing T> template<Color Us, PieceType Pt>
Score Evaluation<T>::pieces() {
@ -379,7 +382,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)
@ -390,6 +393,7 @@ namespace {
// Evaluation::king() assigns bonuses and penalties to a king of a given color
template<Tracing T> template<Color Us>
Score Evaluation<T>::king() const {
@ -498,6 +502,7 @@ namespace {
// Evaluation::threats() assigns bonuses according to the types of the
// attacking and the attacked pieces.
template<Tracing T> template<Color Us>
Score Evaluation<T>::threats() const {
@ -723,8 +728,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<Tracing T>
Value Evaluation<T>::winnable(Score score) const {
@ -830,12 +835,11 @@ namespace {
return pos.side_to_move() == WHITE ? v : -v;
// Main evaluation begins here
initialize<WHITE>();
initialize<BLACK>();
// 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>()
+ pieces<WHITE, BISHOP>() - pieces<BLACK, BISHOP>()
+ pieces<WHITE, ROOK >() - pieces<BLACK, ROOK >()

View file

@ -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<PAWN>(~us) >= 1;
}
/// imbalance() calculates the imbalance by comparing the piece count of each
/// piece type for both colors.
template<Color Us>
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

View file

@ -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

View file

@ -295,9 +295,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) {
@ -337,17 +338,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);
}
}
@ -361,7 +362,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'
@ -375,7 +376,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);
@ -395,7 +396,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) {

View file

@ -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<Color Us>
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

View file

@ -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() {
@ -1278,6 +1277,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.

View file

@ -68,6 +68,7 @@ struct StateInfo {
#endif // defined(EVAL_NNUE)
};
/// 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

View file

@ -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];
}
}

View file

@ -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)
{
@ -1026,8 +1027,10 @@ 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)
&& ss->staticEval + 267 + 391 * lmrDepth
+ PieceValue[MG][type_of(pos.piece_on(to_sq(move)))] <= alpha)
continue;
// See based pruning
@ -1073,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;
@ -1152,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++;
@ -1289,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;
@ -1523,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;
@ -1576,7 +1579,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
@ -1593,7 +1596,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) {
@ -1605,11 +1608,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) {
@ -1769,6 +1772,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.

View file

@ -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 {

View file

@ -28,14 +28,14 @@
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) {
TimePoint minThinkingTime = TimePoint(Options["Minimum Thinking Time"]);
TimePoint moveOverhead = TimePoint(Options["Move Overhead"]);
TimePoint slowMover = TimePoint(Options["Slow Mover"]);
TimePoint npmsec = TimePoint(Options["nodestime"]);
@ -61,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
@ -91,7 +91,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"])

View file

@ -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

View file

@ -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 {

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);
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 << ","

View file

@ -356,16 +356,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) {

View file

@ -53,7 +53,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) {
@ -69,7 +69,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);