inline int edge_distance(File f) { return std::min(f, File(FILE_H - f)); }
-/// attacks_bb(Square) returns the pseudo attacks of the give piece type
+/// attacks_bb(Square) returns the pseudo attacks of the given piece type
/// assuming an empty board.
template<PieceType Pt>
template<GenType>
ExtMove* generate(const Position& pos, ExtMove* moveList);
-/// The MoveList struct is a simple wrapper around generate(). It sometimes comes
-/// in handy to use this class instead of the low level generate() function.
+/// The MoveList struct wraps the generate() function and returns a convenient
+/// list of moves. Using MoveList is sometimes preferable to directly calling
+/// the lower level generate() function.
template<GenType T>
struct MoveList {
} // namespace
-/// Constructors of the MovePicker class. As arguments we pass information
-/// to help it to return the (presumably) good moves first, to decide which
+/// Constructors of the MovePicker class. As arguments, we pass information
+/// to help it return the (presumably) good moves first, to decide which
/// moves to return (in the quiescence search, for instance, we only want to
-/// search captures, promotions, and some checks) and how important good move
-/// ordering is at the current node.
+/// search captures, promotions, and some checks) and how important a good
+/// move ordering is at the current node.
/// MovePicker constructor for the main search
MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHistory* mh,
}
-// Marcel van Kervinck's cuckoo algorithm for fast detection of "upcoming repetition"
-// situations. Description of the algorithm in the following paper:
+// Implements Marcel van Kervinck's cuckoo algorithm to detect repetition of positions
+// for 3-fold repetition draws. The algorithm uses two hash tables with Zobrist hashes to
+// allow fast detection of recurring positions. For details see:
// http://web.archive.org/web/20201107002606/https://marcelk.net/2013-04-06/paper/upcoming-rep-v2.pdf
// First and second hash functions for indexing the cuckoo tables
/// Position::pseudo_legal() takes a random move and tests whether the move is
-/// pseudo legal. It is used to validate moves from TT that can be corrupted
+/// pseudo-legal. It is used to validate moves from TT that can be corrupted
/// due to SMP concurrent access or hash position key aliasing.
bool Position::pseudo_legal(const Move m) const {
return checkers() ? MoveList< EVASIONS>(*this).contains(m)
: MoveList<NON_EVASIONS>(*this).contains(m);
- // Is not a promotion, so promotion piece must be empty
+ // Is not a promotion, so the promotion piece must be empty
assert(promotion_type(m) - KNIGHT == NO_PIECE_TYPE);
// If the 'from' square is not occupied by a piece belonging to the side to
{
if (type_of(pc) != KING)
{
- // Double check? In this case a king move is required
+ // Double check? In this case, a king move is required
if (more_than_one(checkers()))
return false;
if (!(between_bb(square<KING>(us), lsb(checkers())) & to))
return false;
}
- // In case of king moves under check we have to remove king so as to catch
+ // In case of king moves under check we have to remove the king so as to catch
// invalid moves like b1a1 when opposite queen is on c1.
else if (attackers_to(to, pieces() ^ from) & pieces(~us))
return false;
}
else // KING
- // If we "capture" with the king but opponent still has attackers,
+ // If we "capture" with the king but the opponent still has attackers,
// reverse the result.
return (attackers & ~pieces(stm)) ? res ^ 1 : res;
}
/// Position::pos_is_ok() performs some consistency checks for the
-/// position object and raises an asserts if something wrong is detected.
+/// position object and raise an assert if something wrong is detected.
/// This is meant to be helpful when debugging.
bool Position::pos_is_ok() const {
return VALUE_DRAW - 1 + Value(thisThread->nodes & 0x2);
}
- // Skill structure is used to implement strength limit. If we have an uci_elo then
- // we convert it to a suitable fractional skill level using anchoring to CCRL Elo
- // (goldfish 1.13 = 2000) and a fit through Ordo derived Elo for a match (TC 60+0.6)
- // results spanning a wide range of k values.
+ // Skill structure is used to implement strength limit.
+ // If we have a UCI_Elo, we convert it to an appropriate skill level, anchored to the Stash engine.
+ // This method is based on a fit of the Elo results for games played between the master at various
+ // skill levels and various versions of the Stash engine, all ranked at CCRL.
+ // Skill 0 .. 19 now covers CCRL Blitz Elo from 1320 to 3190, approximately
+ // Reference: https://github.com/vondele/Stockfish/commit/a08b8d4e9711c20acedbfe17d618c3c384b339ec
struct Skill {
Skill(int skill_level, int uci_elo) {
if (uci_elo)
void Thread::search() {
- // To allow access to (ss-7) up to (ss+2), the stack must be oversized.
- // The former is needed to allow update_continuation_histories(ss-1, ...),
- // which accesses its argument at ss-6, also near the root.
- // The latter is needed for statScore and killer initialization.
+ // Allocate stack with extra size to allow access from (ss-7) to (ss+2)
+ // (ss-7) is needed for update_continuation_histories(ss-1, ...) which accesses (ss-6)
+ // (ss+2) is needed for initialization of statScore and killers
Stack stack[MAX_PLY+10], *ss = stack+7;
Move pv[MAX_PLY+1];
Value alpha, beta, delta;
alpha = std::max(prev - delta,-VALUE_INFINITE);
beta = std::min(prev + delta, VALUE_INFINITE);
- // Adjust optimism based on root move's previousScore
+ // Adjust optimism based on root move's previousScore (~4 Elo)
int opt = 109 * prev / (std::abs(prev) + 141);
optimism[ us] = Value(opt);
optimism[~us] = -optimism[us];
}
else if (excludedMove)
{
- // Providing the hint that this node's accumulator will be used often brings significant Elo gain (13 Elo)
+ // Providing the hint that this node's accumulator will be used often brings significant Elo gain (~13 Elo)
Eval::NNUE::hint_common_parent_position(pos);
eval = ss->staticEval;
}
: (ss-4)->staticEval != VALUE_NONE ? ss->staticEval > (ss-4)->staticEval
: true;
- // Step 7. Razoring (~1 Elo).
+ // Step 7. Razoring (~1 Elo)
// If eval is really low check with qsearch if it can exceed alpha, if it can't,
// return a fail low.
if (eval < alpha - 456 - 252 * depth * depth)
return value;
}
- // Step 8. Futility pruning: child node (~40 Elo).
+ // Step 8. Futility pruning: child node (~40 Elo)
// The depth condition is important for mate finding.
if ( !ss->ttPv
&& depth < 9
#include <cstdint>
#if defined(_MSC_VER)
-// Disable some silly and noisy warning from MSVC compiler
+// Disable some silly and noisy warnings from MSVC compiler
#pragma warning(disable: 4127) // Conditional expression is constant
#pragma warning(disable: 4146) // Unary minus operator applied to unsigned type
#pragma warning(disable: 4800) // Forcing value to bool 'true' or 'false'
return Move(T + ((pt - KNIGHT) << 12) + (from << 6) + to);
}
-/// Based on a congruential pseudo random number generator
+/// Based on a congruential pseudo-random number generator
constexpr Key make_key(uint64_t seed) {
return seed * 6364136223846793005ULL + 1442695040888963407ULL;
}
// bench() is called when the engine receives the "bench" command.
- // Firstly, a list of UCI commands is set up according to the bench
+ // First, a list of UCI commands is set up according to the bench
// parameters, then it is run one by one, printing a summary at the end.
void bench(Position& pos, std::istream& args, StateListPtr& states) {
// Transform the eval to centipawns with limited range
double x = std::clamp(double(v), -4000.0, 4000.0);
- // Return the win rate in per mille units rounded to the nearest value
+ // Return the win rate in per mille units, rounded to the nearest integer
return int(0.5 + 1000 / (1 + std::exp((a - x) / b)));
}
} // namespace
-/// UCI::loop() waits for a command from the stdin, parses it and then calls the appropriate
+/// UCI::loop() waits for a command from the stdin, parses it, and then calls the appropriate
/// function. It also intercepts an end-of-file (EOF) indication from the stdin to ensure a
/// graceful exit if the GUI dies unexpectedly. When called with some command-line arguments,
/// like running 'bench', the function returns immediately after the command is executed.