closes https://github.com/official-stockfish/Stockfish/pull/2801
No functional change
17 files changed:
[![Build Status](https://ci.appveyor.com/api/projects/status/github/official-stockfish/Stockfish?branch=master&svg=true)](https://ci.appveyor.com/project/mcostalba/stockfish/branch/master)
[Stockfish](https://stockfishchess.org) is a free, powerful UCI chess engine
[![Build Status](https://ci.appveyor.com/api/projects/status/github/official-stockfish/Stockfish?branch=master&svg=true)](https://ci.appveyor.com/project/mcostalba/stockfish/branch/master)
[Stockfish](https://stockfishchess.org) is a free, powerful UCI chess engine
-derived from Glaurung 2.1. It features two evaluation functions, the classical
-evaluation based on handcrafted terms, and the NNUE evaluation based on
-efficiently updateable neural networks. The classical evaluation runs efficiently
-on most 64bit CPU architectures, while the NNUE evaluation benefits strongly from the
-vector intrinsics available on modern CPUs (avx2 or similar).
+derived from Glaurung 2.1. Stockfish is not a complete chess program and requires a
+UCI-compatible graphical user interface (GUI) (e.g. XBoard with PolyGlot, Scid,
+Cute Chess, eboard, Arena, Sigma Chess, Shredder, Chess Partner or Fritz) in order
+to be used comfortably. Read the documentation for your GUI of choice for information
+about how to use Stockfish with it.
-Stockfish is not a complete chess program and requires a
-UCI-compatible GUI (e.g. XBoard with PolyGlot, Scid, Cute Chess, eboard, Arena,
-Sigma Chess, Shredder, Chess Partner or Fritz) in order to be used comfortably.
-Read the documentation for your GUI of choice for information about how to use
-Stockfish with it.
+The Stockfish engine features two evaluation functions for chess, the classical
+evaluation based on handcrafted terms, and the NNUE evaluation based on efficiently
+updateable neural networks. The classical evaluation runs efficiently on most 64bit
+CPU architectures, while the NNUE evaluation benefits strongly from the vector
+intrinsics available on modern CPUs (avx2 or similar).
* src, a subdirectory containing the full source code, including a Makefile
that can be used to compile Stockfish on Unix-like systems.
* src, a subdirectory containing the full source code, including a Makefile
that can be used to compile Stockfish on Unix-like systems.
-To use the NNUE evaluation an additional data file with neural network parameters
-needs to be downloaded. The filename for the default set can be found as the default
-value of the `EvalFile` UCI option, with the format
-`nn-[SHA256 first 12 digits].nnue` (e.g. nn-c157e0a5755b.nnue). This file can be downloaded from
+ * a file with the .nnue extension, storing the neural network for the NNUE
+ evaluation.
+
+Note: to use the NNUE evaluation, the additional data file with neural network parameters
+needs to be downloaded. The filename for the default net can be found as the default
+value of the `EvalFile` UCI option, with the format `nn-[SHA256 first 12 digits].nnue`
+(for instance, `nn-c157e0a5755b.nnue`). This file can be downloaded from
```
https://tests.stockfishchess.org/api/nn/[filename]
```
```
https://tests.stockfishchess.org/api/nn/[filename]
```
The name of the file of the NNUE evaluation parameters. Depending on the GUI the
filename should include the full path to the folder/directory that contains the file.
The name of the file of the NNUE evaluation parameters. Depending on the GUI the
filename should include the full path to the folder/directory that contains the file.
- * #### Contempt
- A positive value for contempt favors middle game positions and avoids draws,
- effective for the classical evaluation only.
-
- * #### Analysis Contempt
- By default, contempt is set to prefer the side to move. Set this option to "White"
- or "Black" to analyse with contempt for that side, or "Off" to disable contempt.
-
* #### UCI_AnalyseMode
An option handled by your GUI.
* #### UCI_AnalyseMode
An option handled by your GUI.
Limit Syzygy tablebase probing to positions with at most this many pieces left
(including kings and pawns).
Limit Syzygy tablebase probing to positions with at most this many pieces left
(including kings and pawns).
+ * #### Contempt
+ A positive value for contempt favors middle game positions and avoids draws,
+ effective for the classical evaluation only.
+
+ * #### Analysis Contempt
+ By default, contempt is set to prefer the side to move. Set this option to "White"
+ or "Black" to analyse with contempt for that side, or "Off" to disable contempt.
+
* #### Move Overhead
Assume a time delay of x ms due to network and GUI overheads. This is useful to
avoid losses on time in those cases.
* #### Move Overhead
Assume a time delay of x ms due to network and GUI overheads. This is useful to
avoid losses on time in those cases.
* #### Debug Log File
Write all communication to and from the engine into a text file.
* #### Debug Log File
Write all communication to and from the engine into a text file.
-## Classical and NNUE evaluation
+## A note on classical and NNUE evaluation
Both approaches assign a value to a position that is used in alpha-beta (PVS) search
to find the best move. The classical evaluation computes this value as a function
Both approaches assign a value to a position that is used in alpha-beta (PVS) search
to find the best move. The classical evaluation computes this value as a function
cd src
make help
make build ARCH=x86-64-modern
cd src
make help
make build ARCH=x86-64-modern
```
When not using the Makefile to compile (for instance with Microsoft MSVC) you
```
When not using the Makefile to compile (for instance with Microsoft MSVC) you
be found by typing the following commands in a console:
```
be found by typing the following commands in a console:
```
```
## Understanding the code base and participating in the project
```
## Understanding the code base and participating in the project
CXXFLAGS += -arch $(arch) -mmacosx-version-min=10.14
LDFLAGS += -arch $(arch) -mmacosx-version-min=10.14
XCRUN = xcrun
CXXFLAGS += -arch $(arch) -mmacosx-version-min=10.14
LDFLAGS += -arch $(arch) -mmacosx-version-min=10.14
XCRUN = xcrun
Bitboard BishopTable[0x1480]; // To store bishop attacks
void init_magics(PieceType pt, Bitboard table[], Magic magics[]);
Bitboard BishopTable[0x1480]; // To store bishop attacks
void init_magics(PieceType pt, Bitboard table[], Magic magics[]);
+
+}
+
+
+/// 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) {
+ Square to = Square(s + step);
+ return is_ok(to) && distance(s, to) <= 2 ? square_bb(to) : Bitboard(0);
Direction RookDirections[4] = {NORTH, SOUTH, EAST, WEST};
Direction BishopDirections[4] = {NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST};
Direction RookDirections[4] = {NORTH, SOUTH, EAST, WEST};
Direction BishopDirections[4] = {NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST};
- for(Direction d : (pt == ROOK ? RookDirections : BishopDirections))
+ for (Direction d : (pt == ROOK ? RookDirections : BishopDirections))
{
Square s = sq;
while(safe_destination(s, d) && !(occupied & s))
{
Square s = sq;
while(safe_destination(s, d) && !(occupied & s))
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)); }
-/// 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)
-{
- Square to = Square(s + 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.
/// attacks_bb(Square) returns the pseudo attacks of the give piece type
/// assuming an empty board.
attackedBy2[Us] = dblAttackByPawn | (attackedBy[Us][KING] & attackedBy[Us][PAWN]);
// Init our king safety tables
attackedBy2[Us] = dblAttackByPawn | (attackedBy[Us][KING] & attackedBy[Us][PAWN]);
// Init our king safety tables
- Square s = make_square(Utility::clamp(file_of(ksq), FILE_B, FILE_G),
- Utility::clamp(rank_of(ksq), RANK_2, RANK_7));
+ Square s = make_square(std::clamp(file_of(ksq), FILE_B, FILE_G),
+ std::clamp(rank_of(ksq), RANK_2, RANK_7));
kingRing[Us] = attacks_bb<KING>(s) | s;
kingAttackersCount[Them] = popcount(kingRing[Us] & pe->pawn_attacks(Them));
kingRing[Us] = attacks_bb<KING>(s) | s;
kingAttackersCount[Them] = popcount(kingRing[Us] & pe->pawn_attacks(Them));
Square blockSq = s + Up;
// Adjust bonus based on the king's proximity
Square blockSq = s + Up;
// Adjust bonus based on the king's proximity
- bonus += make_score(0, ( (king_proximity(Them, blockSq) * 19) / 4
- - king_proximity(Us, blockSq) * 2) * w);
+ bonus += make_score(0, ( king_proximity(Them, blockSq) * 19 / 4
+ - king_proximity(Us, blockSq) * 2) * w);
// If blockSq is not the queening square then consider also a second push
if (r != RANK_7)
// If blockSq is not the queening square then consider also a second push
if (r != RANK_7)
// Evaluation::space() computes a space evaluation for a given side, aiming to improve game
// Evaluation::space() computes a space evaluation for a given side, aiming to improve game
- // play in the opening. It is based on the number of safe squares on the 4 central files
+ // play in the opening. It is based on the number of safe squares on the four central files
// on ranks 2 to 4. Completely safe squares behind a friendly pawn are counted twice.
// Finally, the space bonus is multiplied by a weight which decreases according to occupancy.
// on ranks 2 to 4. Completely safe squares behind a friendly pawn are counted twice.
// Finally, the space bonus is multiplied by a weight which decreases according to occupancy.
// Now apply the bonus: note that we find the attacking side by extracting the
// sign of the midgame or endgame values, and that we carefully cap the bonus
// so that the midgame and endgame scores do not change sign after the bonus.
// Now apply the bonus: note that we find the attacking side by extracting the
// sign of the midgame or endgame values, and that we carefully cap the bonus
// so that the midgame and endgame scores do not change sign after the bonus.
- int u = ((mg > 0) - (mg < 0)) * Utility::clamp(complexity + 50, -abs(mg), 0);
+ int u = ((mg > 0) - (mg < 0)) * std::clamp(complexity + 50, -abs(mg), 0);
int v = ((eg > 0) - (eg < 0)) * std::max(complexity, -abs(eg));
mg += u;
int v = ((eg > 0) - (eg < 0)) * std::max(complexity, -abs(eg));
mg += u;
// Damp down the evaluation linearly when shuffling
v = v * (100 - pos.rule50_count()) / 100;
// Damp down the evaluation linearly when shuffling
v = v * (100 - pos.rule50_count()) / 100;
- // Guarantee evalution outside of TB range
- v = Utility::clamp(v, VALUE_TB_LOSS_IN_MAX_PLY + 1, VALUE_TB_WIN_IN_MAX_PLY - 1);
+ // Guarantee evaluation does not hit the tablebase range
+ v = std::clamp(v, VALUE_TB_LOSS_IN_MAX_PLY + 1, VALUE_TB_WIN_IN_MAX_PLY - 1);
v = pos.side_to_move() == WHITE ? v : -v;
ss << "\nFinal evaluation: " << to_cp(v) << " (white side)\n";
v = pos.side_to_move() == WHITE ? v : -v;
ss << "\nFinal evaluation: " << to_cp(v) << " (white side)\n";
Value npm_w = pos.non_pawn_material(WHITE);
Value npm_b = pos.non_pawn_material(BLACK);
Value npm_w = pos.non_pawn_material(WHITE);
Value npm_b = pos.non_pawn_material(BLACK);
- Value npm = Utility::clamp(npm_w + npm_b, EndgameLimit, MidgameLimit);
+ Value npm = std::clamp(npm_w + npm_b, EndgameLimit, MidgameLimit);
// Map total non-pawn material into [PHASE_ENDGAME, PHASE_MIDGAME]
e->gamePhase = Phase(((npm - EndgameLimit) * PHASE_MIDGAME) / (MidgameLimit - EndgameLimit));
// Map total non-pawn material into [PHASE_ENDGAME, PHASE_MIDGAME]
e->gamePhase = Phase(((npm - EndgameLimit) * PHASE_MIDGAME) / (MidgameLimit - EndgameLimit));
-/// Wrappers for systems where the c++17 implementation doesn't guarantee the availability of aligned_alloc.
-/// Memory allocated with std_aligned_alloc must be freed with std_aligned_free.
-///
+
+/// std_aligned_alloc() is our wrapper for systems where the c++17 implementation
+/// does not guarantee the availability of aligned_alloc(). Memory allocated with
+/// std_aligned_alloc() must be freed with std_aligned_free().
void* std_aligned_alloc(size_t alignment, size_t size) {
void* std_aligned_alloc(size_t alignment, size_t size) {
#if defined(POSIXALIGNEDALLOC)
#if defined(POSIXALIGNEDALLOC)
- void *pointer;
- if(posix_memalign(&pointer, alignment, size) == 0)
- return pointer;
- return nullptr;
+ void *mem;
+ return posix_memalign(&mem, alignment, size) ? nullptr : mem;
#elif defined(_WIN32)
return _mm_malloc(size, alignment);
#else
#elif defined(_WIN32)
return _mm_malloc(size, alignment);
#else
}
void std_aligned_free(void* ptr) {
}
void std_aligned_free(void* ptr) {
#if defined(POSIXALIGNEDALLOC)
free(ptr);
#elif defined(_WIN32)
#if defined(POSIXALIGNEDALLOC)
free(ptr);
#elif defined(_WIN32)
-/// aligned_ttmem_alloc() will return suitably aligned memory, and if possible use large pages.
+/// aligned_ttmem_alloc() will return suitably aligned memory, if possible using 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.
/// 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.
#define sync_cout std::cout << IO_LOCK
#define sync_endl std::endl << IO_UNLOCK
#define sync_cout std::cout << IO_LOCK
#define sync_endl std::endl << IO_UNLOCK
-namespace Utility {
-
-/// Clamp a value between lo and hi. Available in c++17.
-template<class T> constexpr const T& clamp(const T& v, const T& lo, const T& hi) {
- return v < lo ? lo : v > hi ? hi : v;
-}
-
-}
/// xorshift64star Pseudo-Random Number Generator
/// This class is based on original code written and dedicated
/// xorshift64star Pseudo-Random Number Generator
/// This class is based on original code written and dedicated
*moveList++ = make_move(ksq, pop_lsb(&b));
if ((Type != CAPTURES) && pos.can_castle(Us & ANY_CASTLING))
*moveList++ = make_move(ksq, pop_lsb(&b));
if ((Type != CAPTURES) && pos.can_castle(Us & ANY_CASTLING))
- for(CastlingRights cr : { Us & KING_SIDE, Us & QUEEN_SIDE } )
+ for (CastlingRights cr : { Us & KING_SIDE, Us & QUEEN_SIDE } )
if (!pos.castling_impeded(cr) && pos.can_castle(cr))
*moveList++ = make<CASTLING>(ksq, pos.castling_rook_square(cr));
}
if (!pos.castling_impeded(cr) && pos.can_castle(cr))
*moveList++ = make<CASTLING>(ksq, pos.castling_rook_square(cr));
}
case REFUTATION:
if (select<Next>([&](){ return *cur != MOVE_NONE
case REFUTATION:
if (select<Next>([&](){ return *cur != MOVE_NONE
&& pos.pseudo_legal(*cur); }))
return *(cur - 1);
++stage;
&& pos.pseudo_legal(*cur); }))
return *(cur - 1);
++stage;
case QUIET_INIT:
if (!skipQuiets)
case QUIET_INIT:
if (!skipQuiets)
case QUIET:
if ( !skipQuiets
case QUIET:
if ( !skipQuiets
endMoves = endBadCaptures;
++stage;
endMoves = endBadCaptures;
++stage;
case BAD_CAPTURE:
return select<Next>([](){ return true; });
case BAD_CAPTURE:
return select<Next>([](){ return true; });
score<EVASIONS>();
++stage;
score<EVASIONS>();
++stage;
case EVASION:
return select<Best>([](){ return true; });
case EVASION:
return select<Best>([](){ return true; });
return MOVE_NONE;
++stage;
return MOVE_NONE;
++stage;
case QCHECK_INIT:
cur = moves;
endMoves = generate<QUIET_CHECKS>(pos, cur);
++stage;
case QCHECK_INIT:
cur = moves;
endMoves = generate<QUIET_CHECKS>(pos, cur);
++stage;
case QCHECK:
return select<Next>([](){ return true; });
case QCHECK:
return select<Next>([](){ return true; });
/// the move's from and to squares, see www.chessprogramming.org/Butterfly_Boards
typedef Stats<int16_t, 10692, COLOR_NB, int(SQUARE_NB) * int(SQUARE_NB)> ButterflyHistory;
/// the move's from and to squares, see www.chessprogramming.org/Butterfly_Boards
typedef Stats<int16_t, 10692, COLOR_NB, int(SQUARE_NB) * int(SQUARE_NB)> ButterflyHistory;
-/// At higher depths LowPlyHistory records successful quiet moves near the root and quiet
-/// moves which are/were in the PV (ttPv)
-/// It is cleared with each new search and filled during iterative deepening
+/// At higher depths LowPlyHistory records successful quiet moves near the root
+/// and quiet moves which are/were in the PV (ttPv). It is cleared with each new
+/// search and filled during iterative deepening.
constexpr int MAX_LPH = 4;
typedef Stats<int16_t, 10692, MAX_LPH, int(SQUARE_NB) * int(SQUARE_NB)> LowPlyHistory;
/// CounterMoveHistory stores counter moves indexed by [piece][to] of the previous
constexpr int MAX_LPH = 4;
typedef Stats<int16_t, 10692, MAX_LPH, int(SQUARE_NB) * int(SQUARE_NB)> LowPlyHistory;
/// CounterMoveHistory stores counter moves indexed by [piece][to] of the previous
-/// move, see www.chessprogramming.org/Countermove_Heuristic
+/// move, see www.chessprogramming.org/Countermove_Heuristic
typedef Stats<Move, NOT_USED, PIECE_NB, SQUARE_NB> CounterMoveHistory;
/// CapturePieceToHistory is addressed by a move's [piece][to][captured piece type]
typedef Stats<Move, NOT_USED, PIECE_NB, SQUARE_NB> CounterMoveHistory;
/// CapturePieceToHistory is addressed by a move's [piece][to][captured piece type]
Score bonus = make_score(5, 5);
Score bonus = make_score(5, 5);
- File center = Utility::clamp(file_of(ksq), FILE_B, FILE_G);
+ File center = std::clamp(file_of(ksq), FILE_B, FILE_G);
for (File f = File(center - 1); f <= File(center + 1); ++f)
{
b = ourPawns & file_bb(f);
for (File f = File(center - 1); f <= File(center + 1); ++f)
{
b = ourPawns & file_bb(f);
// Don't allow pinned pieces to attack (except the king) as long as
// there are pinners on their original square.
// Don't allow pinned pieces to attack (except the king) as long as
// there are pinners on their original square.
- if (st->pinners[~stm] & occupied)
- stmAttackers &= ~st->blockersForKing[stm];
+ if (pinners(~stm) & occupied)
+ stmAttackers &= ~blockers_for_king(stm);
if (!stmAttackers)
break;
if (!stmAttackers)
break;
Bitboard checkers() const;
Bitboard blockers_for_king(Color c) const;
Bitboard check_squares(PieceType pt) const;
Bitboard checkers() const;
Bitboard blockers_for_king(Color c) const;
Bitboard check_squares(PieceType pt) const;
+ Bitboard pinners(Color c) const;
bool is_discovery_check_on_king(Color c, Move m) const;
// Attacks to/from a given square
bool is_discovery_check_on_king(Color c, Move m) const;
// Attacks to/from a given square
return st->blockersForKing[c];
}
return st->blockersForKing[c];
}
+inline Bitboard Position::pinners(Color c) const {
+ return st->pinners[c];
+}
+
inline Bitboard Position::check_squares(PieceType pt) const {
return st->checkSquares[pt];
}
inline Bitboard Position::check_squares(PieceType pt) const {
return st->checkSquares[pt];
}
// for match (TC 60+0.6) results spanning a wide range of k values.
PRNG rng(now());
double floatLevel = Options["UCI_LimitStrength"] ?
// for match (TC 60+0.6) results spanning a wide range of k values.
PRNG rng(now());
double floatLevel = Options["UCI_LimitStrength"] ?
- Utility::clamp(std::pow((Options["UCI_Elo"] - 1346.6) / 143.4, 1 / 0.806), 0.0, 20.0) :
+ std::clamp(std::pow((Options["UCI_Elo"] - 1346.6) / 143.4, 1 / 0.806), 0.0, 20.0) :
double(Options["Skill Level"]);
int intLevel = int(floatLevel) +
((floatLevel - int(floatLevel)) * 1024 > rng.rand<unsigned>() % 1024 ? 1 : 0);
double(Options["Skill Level"]);
int intLevel = int(floatLevel) +
((floatLevel - int(floatLevel)) * 1024 > rng.rand<unsigned>() % 1024 ? 1 : 0);
{
double fallingEval = (318 + 6 * (mainThread->bestPreviousScore - bestValue)
+ 6 * (mainThread->iterValue[iterIdx] - bestValue)) / 825.0;
{
double fallingEval = (318 + 6 * (mainThread->bestPreviousScore - bestValue)
+ 6 * (mainThread->iterValue[iterIdx] - bestValue)) / 825.0;
- fallingEval = Utility::clamp(fallingEval, 0.5, 1.5);
+ fallingEval = std::clamp(fallingEval, 0.5, 1.5);
// If the bestMove is stable over several iterations, reduce time accordingly
timeReduction = lastBestMoveDepth + 9 < completedDepth ? 1.92 : 0.95;
// If the bestMove is stable over several iterations, reduce time accordingly
timeReduction = lastBestMoveDepth + 9 < completedDepth ? 1.92 : 0.95;
&& eval <= alpha - RazorMargin)
return qsearch<NT>(pos, ss, alpha, beta);
&& eval <= alpha - RazorMargin)
return qsearch<NT>(pos, ss, alpha, beta);
- improving = (ss-2)->staticEval == VALUE_NONE ? (ss->staticEval > (ss-4)->staticEval
- || (ss-4)->staticEval == VALUE_NONE) : ss->staticEval > (ss-2)->staticEval;
+ improving = (ss-2)->staticEval == VALUE_NONE
+ ? ss->staticEval > (ss-4)->staticEval || (ss-4)->staticEval == VALUE_NONE
+ : ss->staticEval > (ss-2)->staticEval;
// Step 8. Futility pruning: child node (~50 Elo)
if ( !PvNode
// Step 8. Futility pruning: child node (~50 Elo)
if ( !PvNode
// there and in further interactions with transposition table cutoff depth is set to depth - 3
// because probCut search has depth set to depth - 4 but we also do a move before it
// so effective depth is equal to depth - 3
// there and in further interactions with transposition table cutoff depth is set to depth - 3
// because probCut search has depth set to depth - 4 but we also do a move before it
// so effective depth is equal to depth - 3
- && !( ttHit
- && tte->depth() >= depth - 3
+ && !( ttHit
+ && tte->depth() >= depth - 3
&& ttValue != VALUE_NONE
&& ttValue < probCutBeta))
{
&& ttValue != VALUE_NONE
&& ttValue < probCutBeta))
{
- Depth d = Utility::clamp(newDepth - r, 1, newDepth);
+ Depth d = std::clamp(newDepth - r, 1, newDepth);
value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, d, true);
value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, d, true);
TimePoint slowMover = TimePoint(Options["Slow Mover"]);
TimePoint npmsec = TimePoint(Options["nodestime"]);
TimePoint slowMover = TimePoint(Options["Slow Mover"]);
TimePoint npmsec = TimePoint(Options["nodestime"]);
- // opt_scale is a percentage of available time to use for the current move.
- // max_scale is a multiplier applied to optimumTime.
- double opt_scale, max_scale;
+ // optScale is a percentage of available time to use for the current move.
+ // maxScale is a multiplier applied to optimumTime.
+ double optScale, maxScale;
// If we have to play in 'nodes as time' mode, then convert from time
// to nodes, and use resulting values in time management formulas.
// If we have to play in 'nodes as time' mode, then convert from time
// to nodes, and use resulting values in time management formulas.
// game time for the current move, so also cap to 20% of available game time.
if (limits.movestogo == 0)
{
// game time for the current move, so also cap to 20% of available game time.
if (limits.movestogo == 0)
{
- opt_scale = std::min(0.008 + std::pow(ply + 3.0, 0.5) / 250.0,
+ optScale = std::min(0.008 + std::pow(ply + 3.0, 0.5) / 250.0,
0.2 * limits.time[us] / double(timeLeft));
0.2 * limits.time[us] / double(timeLeft));
- max_scale = std::min(7.0, 4.0 + ply / 12.0);
+ maxScale = std::min(7.0, 4.0 + ply / 12.0);
}
// x moves in y seconds (+ z increment)
else
{
}
// x moves in y seconds (+ z increment)
else
{
- opt_scale = std::min((0.8 + ply / 128.0) / mtg,
+ optScale = std::min((0.8 + ply / 128.0) / mtg,
0.8 * limits.time[us] / double(timeLeft));
0.8 * limits.time[us] / double(timeLeft));
- max_scale = std::min(6.3, 1.5 + 0.11 * mtg);
+ maxScale = std::min(6.3, 1.5 + 0.11 * mtg);
}
// Never use more than 80% of the available time for this move
}
// Never use more than 80% of the available time for this move
- optimumTime = TimePoint(opt_scale * timeLeft);
- maximumTime = TimePoint(std::min(0.8 * limits.time[us] - moveOverhead, max_scale * optimumTime));
+ optimumTime = TimePoint(optScale * timeLeft);
+ maximumTime = TimePoint(std::min(0.8 * limits.time[us] - moveOverhead, maxScale * optimumTime));
if (Options["Ponder"])
optimumTime += optimumTime / 4;
if (Options["Ponder"])
optimumTime += optimumTime / 4;
double b = (((bs[0] * m + bs[1]) * m + bs[2]) * m) + bs[3];
// Transform eval to centipawns with limited range
double b = (((bs[0] * m + bs[1]) * m + bs[2]) * m) + bs[3];
// Transform eval to centipawns with limited range
- double x = Utility::clamp(double(100 * v) / PawnValueEg, -1000.0, 1000.0);
+ double x = std::clamp(double(100 * v) / PawnValueEg, -1000.0, 1000.0);
// Return win rate in per mille (rounded to nearest)
return int(0.5 + 1000 / (1 + std::exp((a - x) / b)));
// Return win rate in per mille (rounded to nearest)
return int(0.5 + 1000 / (1 + std::exp((a - x) / b)));