mirror of
https://github.com/sockspls/badfish
synced 2025-04-30 16:53:09 +00:00
Big assorted spelling fixes
No functional change.
This commit is contained in:
parent
500b9b0eb3
commit
13a73f67c0
30 changed files with 265 additions and 249 deletions
|
@ -8,7 +8,7 @@ documentation for your GUI of choice for information about how to use
|
|||
Stockfish with it.
|
||||
|
||||
This version of Stockfish supports up to 64 CPUs. The engine defaults
|
||||
to one search thread it is therefore recommended to inspect the value of
|
||||
to one search thread, so it is therefore recommended to inspect the value of
|
||||
the *Threads* UCI parameter, and to make sure it equals the number of CPU
|
||||
cores on your computer.
|
||||
|
||||
|
@ -46,7 +46,7 @@ Stockfish has support for 32 or 64-bit CPUs, the hardware POPCNT
|
|||
instruction, big-endian machines such as Power PC, and other platforms.
|
||||
|
||||
In general it is recommended to run `make help` to see a list of make
|
||||
targets with corresponding descriptions. When not using Makefile to
|
||||
targets with corresponding descriptions. When not using the Makefile to
|
||||
compile (for instance with Microsoft MSVC) you need to manually
|
||||
set/unset some switches in the compiler command line; see file *types.h*
|
||||
for a quick reference.
|
||||
|
|
|
@ -66,7 +66,7 @@ static const char* Defaults[] = {
|
|||
|
||||
|
||||
/// benchmark() runs a simple benchmark by letting Stockfish analyze a set
|
||||
/// of positions for a given limit each. There are five parameters; the
|
||||
/// of positions for a given limit each. There are five parameters, the
|
||||
/// transposition table size, the number of search threads that should
|
||||
/// be used, the limit value spent for each position (optional, default is
|
||||
/// depth 12), an optional file name where to look for positions in fen
|
||||
|
@ -150,7 +150,7 @@ void benchmark(const Position& current, istream& is) {
|
|||
}
|
||||
}
|
||||
|
||||
elapsed = Time::now() - elapsed + 1; // Assure positive to avoid a 'divide by zero'
|
||||
elapsed = Time::now() - elapsed + 1; // Ensure positivity to avoid a 'divide by zero'
|
||||
|
||||
cerr << "\n==========================="
|
||||
<< "\nTotal time (ms) : " << elapsed
|
||||
|
|
|
@ -80,8 +80,8 @@ namespace {
|
|||
}
|
||||
}
|
||||
|
||||
/// lsb()/msb() finds the least/most significant bit in a nonzero bitboard.
|
||||
/// pop_lsb() finds and clears the least significant bit in a nonzero bitboard.
|
||||
/// lsb()/msb() finds the least/most significant bit in a non-zero bitboard.
|
||||
/// pop_lsb() finds and clears the least significant bit in a non-zero bitboard.
|
||||
|
||||
#ifndef USE_BSFQ
|
||||
|
||||
|
|
|
@ -265,8 +265,8 @@ inline Bitboard attacks_bb(Piece p, Square s, Bitboard occ) {
|
|||
}
|
||||
}
|
||||
|
||||
/// lsb()/msb() finds the least/most significant bit in a nonzero bitboard.
|
||||
/// pop_lsb() finds and clears the least significant bit in a nonzero bitboard.
|
||||
/// lsb()/msb() finds the least/most significant bit in a non-zero bitboard.
|
||||
/// pop_lsb() finds and clears the least significant bit in a non-zero bitboard.
|
||||
|
||||
#ifdef USE_BSFQ
|
||||
|
||||
|
|
|
@ -32,14 +32,14 @@ enum BitCountType {
|
|||
CNT_HW_POPCNT
|
||||
};
|
||||
|
||||
/// Determine at compile time the best popcount<> specialization according if
|
||||
/// platform is 32 or 64 bits, to the maximum number of nonzero bits to count
|
||||
/// and if hardware popcnt instruction is available.
|
||||
/// Determine at compile time the best popcount<> specialization according to
|
||||
/// whether the platform is 32 or 64 bits, to the maximum number of non-zero
|
||||
/// bits to count and if the hardware popcnt instruction is available.
|
||||
const BitCountType Full = HasPopCnt ? CNT_HW_POPCNT : Is64Bit ? CNT_64 : CNT_32;
|
||||
const BitCountType Max15 = HasPopCnt ? CNT_HW_POPCNT : Is64Bit ? CNT_64_MAX15 : CNT_32_MAX15;
|
||||
|
||||
|
||||
/// popcount() counts the number of nonzero bits in a bitboard
|
||||
/// popcount() counts the number of non-zero bits in a bitboard
|
||||
template<BitCountType> inline int popcount(Bitboard);
|
||||
|
||||
template<>
|
||||
|
|
17
src/book.cpp
17
src/book.cpp
|
@ -354,7 +354,7 @@ PolyglotBook::~PolyglotBook() { if (is_open()) close(); }
|
|||
|
||||
|
||||
/// operator>>() reads sizeof(T) chars from the file's binary byte stream and
|
||||
/// converts them in a number of type T. A Polyglot book stores numbers in
|
||||
/// converts them into a number of type T. A Polyglot book stores numbers in
|
||||
/// big-endian format.
|
||||
|
||||
template<typename T> PolyglotBook& PolyglotBook::operator>>(T& n) {
|
||||
|
@ -382,14 +382,15 @@ bool PolyglotBook::open(const char* fName) {
|
|||
ifstream::open(fName, ifstream::in | ifstream::binary);
|
||||
|
||||
fileName = is_open() ? fName : "";
|
||||
ifstream::clear(); // Reset any error flag to allow retry ifstream::open()
|
||||
ifstream::clear(); // Reset any error flag to allow a retry ifstream::open()
|
||||
return !fileName.empty();
|
||||
}
|
||||
|
||||
|
||||
/// probe() tries to find a book move for the given position. If no move is
|
||||
/// found returns MOVE_NONE. If pickBest is true returns always the highest
|
||||
/// rated move, otherwise randomly chooses one, based on the move score.
|
||||
/// found, it returns MOVE_NONE. If pickBest is true, then it always returns
|
||||
/// the highest-rated move, otherwise it randomly chooses one based on the
|
||||
/// move score.
|
||||
|
||||
Move PolyglotBook::probe(const Position& pos, const string& fName, bool pickBest) {
|
||||
|
||||
|
@ -426,10 +427,10 @@ Move PolyglotBook::probe(const Position& pos, const string& fName, bool pickBest
|
|||
// bit 6-11: origin square (from 0 to 63)
|
||||
// bit 12-14: promotion piece (from KNIGHT == 1 to QUEEN == 4)
|
||||
//
|
||||
// Castling moves follow "king captures rook" representation. So in case book
|
||||
// move is a promotion we have to convert to our representation, in all the
|
||||
// other cases we can directly compare with a Move after having masked out
|
||||
// the special Move's flags (bit 14-15) that are not supported by PolyGlot.
|
||||
// Castling moves follow the "king captures rook" representation. If a book
|
||||
// move is a promotion, we have to convert it to our representation and in
|
||||
// all other cases, we can directly compare with a Move after having masked
|
||||
// out the special Move flags (bit 14-15) that are not supported by PolyGlot.
|
||||
int pt = (move >> 12) & 7;
|
||||
if (pt)
|
||||
move = make<PROMOTION>(from_sq(move), to_sq(move), PieceType(pt + 1));
|
||||
|
|
|
@ -145,7 +145,7 @@ void Endgames::add(const string& code) {
|
|||
|
||||
|
||||
/// Mate with KX vs K. This function is used to evaluate positions with
|
||||
/// King and plenty of material vs a lone king. It simply gives the
|
||||
/// king and plenty of material vs a lone king. It simply gives the
|
||||
/// attacking side a bonus for driving the defending king towards the edge
|
||||
/// of the board, and for keeping the distance between the two kings small.
|
||||
template<>
|
||||
|
@ -187,9 +187,9 @@ Value Endgame<KBNK>::operator()(const Position& pos) const {
|
|||
Square loserKSq = pos.king_square(weakSide);
|
||||
Square bishopSq = pos.list<BISHOP>(strongSide)[0];
|
||||
|
||||
// kbnk_mate_table() tries to drive toward corners A1 or H8,
|
||||
// if we have a bishop that cannot reach the above squares we
|
||||
// flip the kings so to drive enemy toward corners A8 or H1.
|
||||
// kbnk_mate_table() tries to drive toward corners A1 or H8, if we have a
|
||||
// bishop that cannot reach the above squares we flip the kings in order
|
||||
// to drive the enemy toward corners A8 or H1.
|
||||
if (opposite_colors(bishopSq, SQ_A1))
|
||||
{
|
||||
winnerKSq = ~winnerKSq;
|
||||
|
@ -301,9 +301,10 @@ Value Endgame<KRKN>::operator()(const Position& pos) const {
|
|||
}
|
||||
|
||||
|
||||
/// KQ vs KP. In general, a win for the stronger side, however, there are a few
|
||||
/// important exceptions. Pawn on 7th rank, A,C,F or H file, with king next can
|
||||
/// be a draw, so we scale down to distance between kings only.
|
||||
/// KQ vs KP. In general, this is a win for the stronger side, but there are a
|
||||
/// few important exceptions. A pawn on 7th rank and on the A,C,F or H files
|
||||
/// with a king positioned next to it can be a draw, so in that case, we only
|
||||
/// use the distance between the kings.
|
||||
template<>
|
||||
Value Endgame<KQKP>::operator()(const Position& pos) const {
|
||||
|
||||
|
@ -405,20 +406,20 @@ ScaleFactor Endgame<KBPsK>::operator()(const Position& pos) const {
|
|||
return SCALE_FACTOR_DRAW;
|
||||
}
|
||||
|
||||
// All pawns on same B or G file? Then potential draw
|
||||
// If all the pawns are on the same B or G file, then it's potentially a draw
|
||||
if ( (pawnFile == FILE_B || pawnFile == FILE_G)
|
||||
&& !(pos.pieces(PAWN) & ~file_bb(pawnFile))
|
||||
&& pos.non_pawn_material(weakSide) == 0
|
||||
&& pos.count<PAWN>(weakSide) >= 1)
|
||||
{
|
||||
// Get weakSide pawn that is closest to home rank
|
||||
// Get weakSide pawn that is closest to the home rank
|
||||
Square weakPawnSq = backmost_sq(weakSide, pos.pieces(weakSide, PAWN));
|
||||
|
||||
Square strongKingSq = pos.king_square(strongSide);
|
||||
Square weakKingSq = pos.king_square(weakSide);
|
||||
Square bishopSq = pos.list<BISHOP>(strongSide)[0];
|
||||
|
||||
// Potential for a draw if our pawn is blocked on the 7th rank
|
||||
// There's potential for a draw if our pawn is blocked on the 7th rank
|
||||
// the bishop cannot attack it or they only have one pawn left
|
||||
if ( relative_rank(strongSide, weakPawnSq) == RANK_7
|
||||
&& (pos.pieces(strongSide, PAWN) & (weakPawnSq + pawn_push(weakSide)))
|
||||
|
@ -427,7 +428,7 @@ ScaleFactor Endgame<KBPsK>::operator()(const Position& pos) const {
|
|||
int strongKingDist = square_distance(weakPawnSq, strongKingSq);
|
||||
int weakKingDist = square_distance(weakPawnSq, weakKingSq);
|
||||
|
||||
// Draw if the weak king is on it's back two ranks, within 2
|
||||
// It's a draw if the weak king is on its back two ranks, within 2
|
||||
// squares of the blocking pawn and the strong king is not
|
||||
// closer. (I think this rule only fails in practically
|
||||
// unreachable positions such as 5k1K/6p1/6P1/8/8/3B4/8/8 w
|
||||
|
@ -473,7 +474,7 @@ ScaleFactor Endgame<KQKRPs>::operator()(const Position& pos) const {
|
|||
/// probably be a good idea to add more knowledge in the future.
|
||||
///
|
||||
/// It would also be nice to rewrite the actual code for this function,
|
||||
/// which is mostly copied from Glaurung 1.x, and not very pretty.
|
||||
/// which is mostly copied from Glaurung 1.x, and isn't very pretty.
|
||||
template<>
|
||||
ScaleFactor Endgame<KRPKR>::operator()(const Position& pos) const {
|
||||
|
||||
|
@ -760,8 +761,8 @@ ScaleFactor Endgame<KBPPKB>::operator()(const Position& pos) const {
|
|||
switch (file_distance(psq1, psq2))
|
||||
{
|
||||
case 0:
|
||||
// Both pawns are on the same file. Easy draw if defender firmly controls
|
||||
// some square in the frontmost pawn's path.
|
||||
// Both pawns are on the same file. It's an easy draw if the defender firmly
|
||||
// controls some square in the frontmost pawn's path.
|
||||
if ( file_of(ksq) == file_of(blockSq1)
|
||||
&& relative_rank(strongSide, ksq) >= relative_rank(strongSide, blockSq1)
|
||||
&& opposite_colors(ksq, wbsq))
|
||||
|
@ -770,9 +771,9 @@ ScaleFactor Endgame<KBPPKB>::operator()(const Position& pos) const {
|
|||
return SCALE_FACTOR_NONE;
|
||||
|
||||
case 1:
|
||||
// Pawns on adjacent files. Draw if defender firmly controls the square
|
||||
// in front of the frontmost pawn's path, and the square diagonally behind
|
||||
// this square on the file of the other pawn.
|
||||
// Pawns on adjacent files. It's a draw if the defender firmly controls the
|
||||
// square in front of the frontmost pawn's path, and the square diagonally
|
||||
// behind this square on the file of the other pawn.
|
||||
if ( ksq == blockSq1
|
||||
&& opposite_colors(ksq, wbsq)
|
||||
&& ( bbsq == blockSq2
|
||||
|
|
|
@ -64,9 +64,9 @@ enum EndgameType {
|
|||
};
|
||||
|
||||
|
||||
/// Endgame functions can be of two types according if return a Value or a
|
||||
/// ScaleFactor. Type eg_fun<int>::type equals to either ScaleFactor or Value
|
||||
/// depending if the template parameter is 0 or 1.
|
||||
/// Endgame functions can be of two types depending on whether they return a
|
||||
/// Value or a ScaleFactor. Type eg_fun<int>::type returns either ScaleFactor
|
||||
/// or Value depending on whether the template parameter is 0 or 1.
|
||||
|
||||
template<int> struct eg_fun { typedef Value type; };
|
||||
template<> struct eg_fun<1> { typedef ScaleFactor type; };
|
||||
|
@ -95,9 +95,9 @@ private:
|
|||
};
|
||||
|
||||
|
||||
/// Endgames class stores in two std::map the pointers to endgame evaluation
|
||||
/// and scaling base objects. Then we use polymorphism to invoke the actual
|
||||
/// endgame function calling its operator() that is virtual.
|
||||
/// The Endgames class stores the pointers to endgame evaluation and scaling
|
||||
/// base objects in two std::map typedefs. We then use polymorphism to invoke
|
||||
/// the actual endgame function by calling its virtual operator().
|
||||
|
||||
class Endgames {
|
||||
|
||||
|
|
|
@ -269,9 +269,10 @@ namespace Eval {
|
|||
}
|
||||
|
||||
|
||||
/// trace() is like evaluate() but instead of a value returns a string suitable
|
||||
/// to be print on stdout with the detailed descriptions and values of each
|
||||
/// evaluation term. Used mainly for debugging.
|
||||
/// trace() is like evaluate(), but instead of returning a value, it returns
|
||||
/// a string (suitable for outputting to stdout) that contains the detailed
|
||||
/// descriptions and values of each evaluation term. It's mainly used for
|
||||
/// debugging.
|
||||
std::string trace(const Position& pos) {
|
||||
return Tracing::do_trace(pos);
|
||||
}
|
||||
|
@ -316,7 +317,7 @@ Value do_evaluate(const Position& pos) {
|
|||
Thread* th = pos.this_thread();
|
||||
|
||||
// Initialize score by reading the incrementally updated scores included
|
||||
// in the position object (material + piece square tables) and adding
|
||||
// in the position object (material + piece square tables) and adding a
|
||||
// Tempo bonus. Score is computed from the point of view of white.
|
||||
score = pos.psq_score() + (pos.side_to_move() == WHITE ? Tempo : -Tempo);
|
||||
|
||||
|
@ -378,7 +379,8 @@ Value do_evaluate(const Position& pos) {
|
|||
&& pos.opposite_bishops()
|
||||
&& sf == SCALE_FACTOR_NORMAL)
|
||||
{
|
||||
// Only the two bishops ?
|
||||
// Ignoring any pawns, do both sides only have a single bishop and no
|
||||
// other pieces ?
|
||||
if ( pos.non_pawn_material(WHITE) == BishopValueMg
|
||||
&& pos.non_pawn_material(BLACK) == BishopValueMg)
|
||||
{
|
||||
|
@ -510,7 +512,7 @@ Value do_evaluate(const Position& pos) {
|
|||
|
||||
mobility[Us] += MobilityBonus[Piece][mob];
|
||||
|
||||
// Decrease score if we are attacked by an enemy pawn. Remaining part
|
||||
// Decrease score if we are attacked by an enemy pawn. The remaining part
|
||||
// of threat evaluation must be done later when we have full attack info.
|
||||
if (ei.attackedBy[Them][PAWN] & s)
|
||||
score -= ThreatenedByPawn[Piece];
|
||||
|
@ -568,8 +570,8 @@ Value do_evaluate(const Position& pos) {
|
|||
|
||||
Square ksq = pos.king_square(Us);
|
||||
|
||||
// Penalize rooks which are trapped inside a king. Penalize more if
|
||||
// king has lost castling availability.
|
||||
// Penalize rooks which are trapped by a king. Penalize more if the
|
||||
// king has lost its castling capability.
|
||||
if ( ((file_of(ksq) < FILE_E) == (file_of(s) < file_of(ksq)))
|
||||
&& (rank_of(ksq) == rank_of(s) || relative_rank(Us, ksq) == RANK_1)
|
||||
&& !ei.pi->semiopen_on_side(Us, file_of(ksq), file_of(ksq) < FILE_E))
|
||||
|
@ -644,7 +646,7 @@ Value do_evaluate(const Position& pos) {
|
|||
if ( ei.kingAttackersCount[Them] >= 2
|
||||
&& ei.kingAdjacentZoneAttacksCount[Them])
|
||||
{
|
||||
// Find the attacked squares around the king which has no defenders
|
||||
// Find the attacked squares around the king which have no defenders
|
||||
// apart from the king itself
|
||||
undefended = ei.attackedBy[Them][ALL_PIECES]
|
||||
& ei.attackedBy[Us][KING]
|
||||
|
@ -662,12 +664,13 @@ Value do_evaluate(const Position& pos) {
|
|||
+ KingExposed[relative_square(Us, ksq)]
|
||||
- mg_value(score) / 32;
|
||||
|
||||
// Analyse enemy's safe queen contact checks. First find undefended
|
||||
// squares around the king attacked by enemy queen...
|
||||
// Analyse the enemy's safe queen contact checks. Firstly, find the
|
||||
// undefended squares around the king that are attacked by the enemy's
|
||||
// queen...
|
||||
b = undefended & ei.attackedBy[Them][QUEEN] & ~pos.pieces(Them);
|
||||
if (b)
|
||||
{
|
||||
// ...then remove squares not supported by another enemy piece
|
||||
// ...and then remove squares not supported by another enemy piece
|
||||
b &= ( ei.attackedBy[Them][PAWN] | ei.attackedBy[Them][KNIGHT]
|
||||
| ei.attackedBy[Them][BISHOP] | ei.attackedBy[Them][ROOK]);
|
||||
if (b)
|
||||
|
@ -676,16 +679,17 @@ Value do_evaluate(const Position& pos) {
|
|||
* (Them == pos.side_to_move() ? 2 : 1);
|
||||
}
|
||||
|
||||
// Analyse enemy's safe rook contact checks. First find undefended
|
||||
// squares around the king attacked by enemy rooks...
|
||||
// Analyse the enemy's safe rook contact checks. Firstly, find the
|
||||
// undefended squares around the king that are attacked by the enemy's
|
||||
// rooks...
|
||||
b = undefended & ei.attackedBy[Them][ROOK] & ~pos.pieces(Them);
|
||||
|
||||
// Consider only squares where the enemy rook gives check
|
||||
// Consider only squares where the enemy's rook gives check
|
||||
b &= PseudoAttacks[ROOK][ksq];
|
||||
|
||||
if (b)
|
||||
{
|
||||
// ...then remove squares not supported by another enemy piece
|
||||
// ...and then remove squares not supported by another enemy piece
|
||||
b &= ( ei.attackedBy[Them][PAWN] | ei.attackedBy[Them][KNIGHT]
|
||||
| ei.attackedBy[Them][BISHOP] | ei.attackedBy[Them][QUEEN]);
|
||||
if (b)
|
||||
|
@ -694,7 +698,7 @@ Value do_evaluate(const Position& pos) {
|
|||
* (Them == pos.side_to_move() ? 2 : 1);
|
||||
}
|
||||
|
||||
// Analyse enemy's safe distance checks for sliders and knights
|
||||
// Analyse the enemy's safe distance checks for sliders and knights
|
||||
safe = ~(pos.pieces(Them) | ei.attackedBy[Us][ALL_PIECES]);
|
||||
|
||||
b1 = pos.attacks_from<ROOK>(ksq) & safe;
|
||||
|
@ -746,7 +750,7 @@ Value do_evaluate(const Position& pos) {
|
|||
Bitboard b, undefendedMinors, weakEnemies;
|
||||
Score score = SCORE_ZERO;
|
||||
|
||||
// Undefended minors get penalized even if not under attack
|
||||
// Undefended minors get penalized even if they are not under attack
|
||||
undefendedMinors = pos.pieces(Them, BISHOP, KNIGHT)
|
||||
& ~ei.attackedBy[Them][ALL_PIECES];
|
||||
|
||||
|
@ -807,7 +811,7 @@ Value do_evaluate(const Position& pos) {
|
|||
{
|
||||
Square blockSq = s + pawn_push(Us);
|
||||
|
||||
// Adjust bonus based on kings proximity
|
||||
// Adjust bonus based on the king's proximity
|
||||
ebonus += Value(square_distance(pos.king_square(Them), blockSq) * 5 * rr)
|
||||
- Value(square_distance(pos.king_square(Us ), blockSq) * 2 * rr);
|
||||
|
||||
|
@ -815,7 +819,7 @@ Value do_evaluate(const Position& pos) {
|
|||
if (relative_rank(Us, blockSq) != RANK_8)
|
||||
ebonus -= Value(square_distance(pos.king_square(Us), blockSq + pawn_push(Us)) * rr);
|
||||
|
||||
// If the pawn is free to advance, increase bonus
|
||||
// If the pawn is free to advance, then increase the bonus
|
||||
if (pos.empty(blockSq))
|
||||
{
|
||||
squaresToQueen = forward_bb(Us, s);
|
||||
|
@ -835,12 +839,14 @@ Value do_evaluate(const Position& pos) {
|
|||
else
|
||||
defendedSquares = squaresToQueen & ei.attackedBy[Us][ALL_PIECES];
|
||||
|
||||
// If there aren't enemy attacks huge bonus, a bit smaller if at
|
||||
// least block square is not attacked, otherwise smallest bonus.
|
||||
// If there aren't any enemy attacks, then assign a huge bonus.
|
||||
// The bonus will be a bit smaller if at least the block square
|
||||
// isn't attacked, otherwise assign the smallest possible bonus.
|
||||
int k = !unsafeSquares ? 15 : !(unsafeSquares & blockSq) ? 9 : 3;
|
||||
|
||||
// Big bonus if the path to queen is fully defended, a bit less
|
||||
// if at least block square is defended.
|
||||
// Assign a big bonus if the path to the queen is fully defended,
|
||||
// otherwise assign a bit less of a bonus if at least the block
|
||||
// square is defended.
|
||||
if (defendedSquares == squaresToQueen)
|
||||
k += 6;
|
||||
|
||||
|
@ -892,7 +898,7 @@ Value do_evaluate(const Position& pos) {
|
|||
|
||||
// evaluate_unstoppable_pawns() scores the most advanced among the passed and
|
||||
// candidate pawns. In case opponent has no pieces but pawns, this is somewhat
|
||||
// related to the possibility pawns are unstoppable.
|
||||
// related to the possibility that pawns are unstoppable.
|
||||
|
||||
Score evaluate_unstoppable_pawns(const Position& pos, Color us, const EvalInfo& ei) {
|
||||
|
||||
|
|
|
@ -60,8 +60,8 @@ namespace {
|
|||
{ 106, 101, 3, 151, 171, 0 } // Queen
|
||||
};
|
||||
|
||||
// Endgame evaluation and scaling functions accessed direcly and not through
|
||||
// the function maps because correspond to more then one material hash key.
|
||||
// Endgame evaluation and scaling functions are accessed directly and not through
|
||||
// the function maps because they correspond to more then one material hash key.
|
||||
Endgame<KmmKm> EvaluateKmmKm[] = { Endgame<KmmKm>(WHITE), Endgame<KmmKm>(BLACK) };
|
||||
Endgame<KXK> EvaluateKXK[] = { Endgame<KXK>(WHITE), Endgame<KXK>(BLACK) };
|
||||
|
||||
|
@ -93,7 +93,7 @@ namespace {
|
|||
&& pos.count<PAWN>(Them) >= 1;
|
||||
}
|
||||
|
||||
/// imbalance() calculates imbalance comparing piece count of each
|
||||
/// imbalance() calculates the imbalance by comparing the piece count of each
|
||||
/// piece type for both colors.
|
||||
|
||||
template<Color Us>
|
||||
|
@ -147,9 +147,9 @@ Entry* probe(const Position& pos, Table& entries, Endgames& endgames) {
|
|||
e->factor[WHITE] = e->factor[BLACK] = (uint8_t)SCALE_FACTOR_NORMAL;
|
||||
e->gamePhase = game_phase(pos);
|
||||
|
||||
// Let's look if we have a specialized evaluation function for this
|
||||
// particular material configuration. First we look for a fixed
|
||||
// configuration one, then a generic one if previous search failed.
|
||||
// Let's look if we have a specialized evaluation function for this particular
|
||||
// material configuration. Firstly we look for a fixed configuration one, then
|
||||
// for a generic one if the previous search failed.
|
||||
if (endgames.probe(key, e->evaluationFunction))
|
||||
return e;
|
||||
|
||||
|
@ -194,7 +194,7 @@ Entry* probe(const Position& pos, Table& entries, Endgames& endgames) {
|
|||
}
|
||||
|
||||
// Generic scaling functions that refer to more then one material
|
||||
// distribution. Should be probed after the specialized ones.
|
||||
// distribution. They should be probed after the specialized ones.
|
||||
// Note that these ones don't return after setting the function.
|
||||
if (is_KBPsKs<WHITE>(pos))
|
||||
e->scalingFunction[WHITE] = &ScaleKBPsK[WHITE];
|
||||
|
@ -256,7 +256,7 @@ Entry* probe(const Position& pos, Table& entries, Endgames& endgames) {
|
|||
}
|
||||
|
||||
// Evaluate the material imbalance. We use PIECE_TYPE_NONE as a place holder
|
||||
// for the bishop pair "extended piece", this allow us to be more flexible
|
||||
// for the bishop pair "extended piece", which allows us to be more flexible
|
||||
// in defining bishop pair bonuses.
|
||||
const int pieceCount[COLOR_NB][PIECE_TYPE_NB] = {
|
||||
{ pos.count<BISHOP>(WHITE) > 1, pos.count<PAWN>(WHITE), pos.count<KNIGHT>(WHITE),
|
||||
|
|
18
src/misc.cpp
18
src/misc.cpp
|
@ -81,7 +81,7 @@ void dbg_print() {
|
|||
|
||||
/// Our fancy logging facility. The trick here is to replace cin.rdbuf() and
|
||||
/// cout.rdbuf() with two Tie objects that tie cin and cout to a file stream. We
|
||||
/// can toggle the logging of std::cout and std:cin at runtime while preserving
|
||||
/// can toggle the logging of std::cout and std:cin at runtime whilst preserving
|
||||
/// usual i/o functionality and without changing a single line of code!
|
||||
/// Idea from http://groups.google.com/group/comp.lang.c++/msg/1d941c0f26ea0d81
|
||||
|
||||
|
@ -137,7 +137,7 @@ public:
|
|||
};
|
||||
|
||||
|
||||
/// Used to serialize access to std::cout to avoid multiple threads to write at
|
||||
/// Used to serialize access to std::cout to avoid multiple threads writing at
|
||||
/// the same time.
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, SyncCout sc) {
|
||||
|
@ -158,8 +158,8 @@ std::ostream& operator<<(std::ostream& os, SyncCout sc) {
|
|||
void start_logger(bool b) { Logger::start(b); }
|
||||
|
||||
|
||||
/// timed_wait() waits for msec milliseconds. It is mainly an helper to wrap
|
||||
/// conversion from milliseconds to struct timespec, as used by pthreads.
|
||||
/// timed_wait() waits for msec milliseconds. It is mainly a helper to wrap
|
||||
/// the conversion from milliseconds to struct timespec, as used by pthreads.
|
||||
|
||||
void timed_wait(WaitCondition& sleepCond, Lock& sleepLock, int msec) {
|
||||
|
||||
|
@ -177,9 +177,9 @@ void timed_wait(WaitCondition& sleepCond, Lock& sleepLock, int msec) {
|
|||
}
|
||||
|
||||
|
||||
/// prefetch() preloads the given address in L1/L2 cache. This is a non
|
||||
/// blocking function and do not stalls the CPU waiting for data to be
|
||||
/// loaded from memory, that can be quite slow.
|
||||
/// prefetch() preloads the given address in L1/L2 cache. This is a non-blocking
|
||||
/// function that doesn't stall the CPU waiting for data to be loaded from memory,
|
||||
/// which can be quite slow.
|
||||
#ifdef NO_PREFETCH
|
||||
|
||||
void prefetch(char*) {}
|
||||
|
@ -189,8 +189,8 @@ void prefetch(char*) {}
|
|||
void prefetch(char* addr) {
|
||||
|
||||
# if defined(__INTEL_COMPILER)
|
||||
// This hack prevents prefetches to be optimized away by
|
||||
// Intel compiler. Both MSVC and gcc seems not affected.
|
||||
// This hack prevents prefetches from being optimized away by
|
||||
// Intel compiler. Both MSVC and gcc seem not be affected by this.
|
||||
__asm__ ("");
|
||||
# endif
|
||||
|
||||
|
|
|
@ -88,8 +88,8 @@ namespace {
|
|||
(mlist++)->move = make<PROMOTION>(to - Delta, to, KNIGHT);
|
||||
}
|
||||
|
||||
// Knight-promotion is the only one that can give a direct check not
|
||||
// already included in the queen-promotion.
|
||||
// Knight promotion is the only promotion that can give a direct check
|
||||
// that's not already included in the queen promotion.
|
||||
if (Type == QUIET_CHECKS && (StepAttacksBB[W_KNIGHT][to] & ci->ksq))
|
||||
(mlist++)->move = make<PROMOTION>(to - Delta, to, KNIGHT);
|
||||
else
|
||||
|
@ -144,7 +144,7 @@ namespace {
|
|||
// Add pawn pushes which give discovered check. This is possible only
|
||||
// if the pawn is not on the same file as the enemy king, because we
|
||||
// don't generate captures. Note that a possible discovery check
|
||||
// promotion has been already generated among captures.
|
||||
// promotion has been already generated amongst the captures.
|
||||
if (pawnsNotOn7 & ci->dcCandidates)
|
||||
{
|
||||
dc1 = shift_bb<Up>(pawnsNotOn7 & ci->dcCandidates) & emptySquares & ~file_bb(ci->ksq);
|
||||
|
@ -355,8 +355,9 @@ ExtMove* generate<EVASIONS>(const Position& pos, ExtMove* mlist) {
|
|||
|
||||
assert(pos.checkers());
|
||||
|
||||
// Find squares attacked by slider checkers, we will remove them from the king
|
||||
// evasions so to skip known illegal moves avoiding useless legality check later.
|
||||
// Find all the squares attacked by slider checkers. We will remove them from
|
||||
// the king evasions in order to skip known illegal moves, which avoids any
|
||||
// useless legality checks later on.
|
||||
do
|
||||
{
|
||||
++checkersCnt;
|
||||
|
|
|
@ -36,8 +36,8 @@ class Position;
|
|||
template<GenType>
|
||||
ExtMove* generate(const Position& pos, ExtMove* mlist);
|
||||
|
||||
/// The MoveList struct is a simple wrapper around generate(), sometimes comes
|
||||
/// handy to use this class instead of the low level generate() function.
|
||||
/// 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.
|
||||
template<GenType T>
|
||||
struct MoveList {
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace {
|
|||
STOP
|
||||
};
|
||||
|
||||
// Our insertion sort, guaranteed to be stable, as is needed
|
||||
// Our insertion sort, which is guaranteed (and also needed) to be stable
|
||||
void insertion_sort(ExtMove* begin, ExtMove* end)
|
||||
{
|
||||
ExtMove tmp, *p, *q;
|
||||
|
@ -53,9 +53,9 @@ namespace {
|
|||
// ones so to sort separately the two sets, and with the second sort delayed.
|
||||
inline bool has_positive_score(const ExtMove& ms) { return ms.score > 0; }
|
||||
|
||||
// Picks and moves to the front the best move in the range [begin, end),
|
||||
// it is faster than sorting all the moves in advance when moves are few, as
|
||||
// normally are the possible captures.
|
||||
// Picks the best move in the range (begin, end) and moves it to the front.
|
||||
// It's faster than sorting all the moves in advance when there are few
|
||||
// moves e.g. possible captures.
|
||||
inline ExtMove* pick_best(ExtMove* begin, ExtMove* end)
|
||||
{
|
||||
std::swap(*begin, *std::max_element(begin, end));
|
||||
|
@ -105,7 +105,7 @@ MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const HistoryStats&
|
|||
{
|
||||
stage = QSEARCH_1;
|
||||
|
||||
// Skip TT move if is not a capture or a promotion, this avoids qsearch
|
||||
// Skip TT move if is not a capture or a promotion. This avoids qsearch
|
||||
// tree explosion due to a possible perpetual check or similar rare cases
|
||||
// when TT table is full.
|
||||
if (ttm && !pos.capture_or_promotion(ttm))
|
||||
|
@ -129,7 +129,8 @@ MovePicker::MovePicker(const Position& p, Move ttm, const HistoryStats& h, Piece
|
|||
|
||||
stage = PROBCUT;
|
||||
|
||||
// In ProbCut we generate only captures better than parent's captured piece
|
||||
// In ProbCut we generate only captures that are better than the parent's
|
||||
// captured piece.
|
||||
captureThreshold = PieceValue[MG][pt];
|
||||
ttMove = (ttm && pos.pseudo_legal(ttm) ? ttm : MOVE_NONE);
|
||||
|
||||
|
@ -153,10 +154,10 @@ void MovePicker::score<CAPTURES>() {
|
|||
// where it is possible to recapture with the hanging piece). Exchanging
|
||||
// big pieces before capturing a hanging piece probably helps to reduce
|
||||
// the subtree size.
|
||||
// In main search we want to push captures with negative SEE values to
|
||||
// badCaptures[] array, but instead of doing it now we delay till when
|
||||
// the move has been picked up in pick_move_from_list(), this way we save
|
||||
// some SEE calls in case we get a cutoff (idea from Pablo Vazquez).
|
||||
// In main search we want to push captures with negative SEE values to the
|
||||
// badCaptures[] array, but instead of doing it now we delay until the move
|
||||
// has been picked up in pick_move_from_list(). This way we save some SEE
|
||||
// calls in case we get a cutoff.
|
||||
Move m;
|
||||
|
||||
for (ExtMove* it = moves; it != end; ++it)
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
/// and is used for reduction and move ordering decisions. Gains records the move's
|
||||
/// best evaluation gain from one ply to the next and is used for pruning decisions.
|
||||
/// Countermoves store the move that refute a previous one. Entries are stored
|
||||
/// according only to moving piece and destination square, hence two moves with
|
||||
/// using only the moving piece and destination square, hence two moves with
|
||||
/// different origin but same destination and piece will be considered identical.
|
||||
template<bool Gain, typename T>
|
||||
struct Stats {
|
||||
|
|
|
@ -126,8 +126,8 @@ const string move_to_san(Position& pos, Move m) {
|
|||
{
|
||||
san = PieceToChar[WHITE][pt]; // Upper case
|
||||
|
||||
// Disambiguation if we have more then one piece of type 'pt' that can
|
||||
// reach 'to' with a legal move.
|
||||
// A disambiguation occurs if we have more then one piece of type 'pt'
|
||||
// that can reach 'to' with a legal move.
|
||||
others = b = (pos.attacks_from(pc, to) & pos.pieces(us, pt)) ^ from;
|
||||
|
||||
while (b)
|
||||
|
@ -175,7 +175,7 @@ const string move_to_san(Position& pos, Move m) {
|
|||
|
||||
/// pretty_pv() formats human-readable search information, typically to be
|
||||
/// appended to the search log file. It uses the two helpers below to pretty
|
||||
/// format time and score respectively.
|
||||
/// format the time and score respectively.
|
||||
|
||||
static string time_to_string(int64_t msecs) {
|
||||
|
||||
|
|
|
@ -252,8 +252,9 @@ Value Entry::shelter_storm(const Position& pos, Square ksq) {
|
|||
}
|
||||
|
||||
|
||||
/// Entry::update_safety() calculates and caches a bonus for king safety. It is
|
||||
/// called only when king square changes, about 20% of total king_safety() calls.
|
||||
/// Entry::update_safety() calculates and caches a bonus for king safety.
|
||||
/// It is called only when king square changes, which is about 20% of total
|
||||
/// king_safety() calls.
|
||||
|
||||
template<Color Us>
|
||||
Score Entry::update_safety(const Position& pos, Square ksq) {
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
#ifdef _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'
|
||||
|
@ -89,14 +89,14 @@ inline int64_t system_time_to_msec() {
|
|||
#undef WIN32_LEAN_AND_MEAN
|
||||
#undef NOMINMAX
|
||||
|
||||
// We use critical sections on Windows to support Windows XP and older versions,
|
||||
// unfortunatly cond_wait() is racy between lock_release() and WaitForSingleObject()
|
||||
// We use critical sections on Windows to support Windows XP and older versions.
|
||||
// Unfortunately, cond_wait() is racy between lock_release() and WaitForSingleObject()
|
||||
// but apart from this they have the same speed performance of SRW locks.
|
||||
typedef CRITICAL_SECTION Lock;
|
||||
typedef HANDLE WaitCondition;
|
||||
typedef HANDLE NativeHandle;
|
||||
|
||||
// On Windows 95 and 98 parameter lpThreadId my not be null
|
||||
// On Windows 95 and 98 parameter lpThreadId may not be null
|
||||
inline DWORD* dwWin9xKludge() { static DWORD dw; return &dw; }
|
||||
|
||||
# define lock_init(x) InitializeCriticalSection(&(x))
|
||||
|
|
|
@ -82,7 +82,7 @@ PieceType min_attacker(const Bitboard* bb, const Square& to, const Bitboard& stm
|
|||
|
||||
template<> FORCE_INLINE
|
||||
PieceType min_attacker<KING>(const Bitboard*, const Square&, const Bitboard&, Bitboard&, Bitboard&) {
|
||||
return KING; // No need to update bitboards, it is the last cycle
|
||||
return KING; // No need to update bitboards: it is the last cycle
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -109,9 +109,9 @@ CheckInfo::CheckInfo(const Position& pos) {
|
|||
|
||||
/// Position::init() initializes at startup the various arrays used to compute
|
||||
/// hash keys and the piece square tables. The latter is a two-step operation:
|
||||
/// First, the white halves of the tables are copied from PSQT[] tables. Second,
|
||||
/// the black halves of the tables are initialized by flipping and changing the
|
||||
/// sign of the white scores.
|
||||
/// Firstly, the white halves of the tables are copied from PSQT[] tables.
|
||||
/// Secondly, the black halves of the tables are initialized by flipping and
|
||||
/// changing the sign of the white scores.
|
||||
|
||||
void Position::init() {
|
||||
|
||||
|
@ -155,7 +155,7 @@ void Position::init() {
|
|||
|
||||
|
||||
/// Position::operator=() creates a copy of 'pos'. We want the new born Position
|
||||
/// object do not depend on any external data so we detach state pointer from
|
||||
/// object to not depend on any external data so we detach state pointer from
|
||||
/// the source one.
|
||||
|
||||
Position& Position::operator=(const Position& pos) {
|
||||
|
@ -182,11 +182,11 @@ void Position::set(const string& fenStr, bool isChess960, Thread* th) {
|
|||
A FEN string contains six fields separated by a space. The fields are:
|
||||
|
||||
1) Piece placement (from white's perspective). Each rank is described, starting
|
||||
with rank 8 and ending with rank 1; within each rank, the contents of each
|
||||
with rank 8 and ending with rank 1. Within each rank, the contents of each
|
||||
square are described from file A through file H. Following the Standard
|
||||
Algebraic Notation (SAN), each piece is identified by a single letter taken
|
||||
from the standard English names. White pieces are designated using upper-case
|
||||
letters ("PNBRQK") while Black take lowercase ("pnbrqk"). Blank squares are
|
||||
letters ("PNBRQK") whilst Black uses lowercase ("pnbrqk"). Blank squares are
|
||||
noted using digits 1 through 8 (the number of blank squares), and "/"
|
||||
separates ranks.
|
||||
|
||||
|
@ -324,8 +324,8 @@ void Position::set_castling_flag(Color c, Square rfrom) {
|
|||
}
|
||||
|
||||
|
||||
/// Position::fen() returns a FEN representation of the position. In case
|
||||
/// of Chess960 the Shredder-FEN notation is used. Mainly a debugging function.
|
||||
/// Position::fen() returns a FEN representation of the position. In case of
|
||||
/// Chess960 the Shredder-FEN notation is used. This is mainly a debugging function.
|
||||
|
||||
const string Position::fen() const {
|
||||
|
||||
|
@ -416,14 +416,14 @@ const string Position::pretty(Move move) const {
|
|||
|
||||
|
||||
/// Position:hidden_checkers() returns a bitboard of all pinned / discovery check
|
||||
/// pieces, according to the call parameters. Pinned pieces protect our king,
|
||||
/// pieces, according to the call parameters. Pinned pieces protect our king and
|
||||
/// discovery check pieces attack the enemy king.
|
||||
|
||||
Bitboard Position::hidden_checkers(Square ksq, Color c, Color toMove) const {
|
||||
|
||||
Bitboard b, pinners, result = 0;
|
||||
|
||||
// Pinners are sliders that give check when pinned piece is removed
|
||||
// Pinners are sliders that give check when a pinned piece is removed
|
||||
pinners = ( (pieces( ROOK, QUEEN) & PseudoAttacks[ROOK ][ksq])
|
||||
| (pieces(BISHOP, QUEEN) & PseudoAttacks[BISHOP][ksq])) & pieces(c);
|
||||
|
||||
|
@ -439,7 +439,7 @@ Bitboard Position::hidden_checkers(Square ksq, Color c, Color toMove) const {
|
|||
|
||||
|
||||
/// Position::attackers_to() computes a bitboard of all pieces which attack a
|
||||
/// given square. Slider attacks use occ bitboard as occupancy.
|
||||
/// given square. Slider attacks use the occ bitboard to indicate occupancy.
|
||||
|
||||
Bitboard Position::attackers_to(Square s, Bitboard occ) const {
|
||||
|
||||
|
@ -593,8 +593,8 @@ bool Position::pseudo_legal(const Move m) const {
|
|||
return false;
|
||||
|
||||
// Evasions generator already takes care to avoid some kind of illegal moves
|
||||
// and pl_move_is_legal() relies on this. So we have to take care that the
|
||||
// same kind of moves are filtered out here.
|
||||
// and pl_move_is_legal() relies on this. We therefore have to take care that
|
||||
// the same kind of moves are filtered out here.
|
||||
if (checkers())
|
||||
{
|
||||
if (type_of(pc) != KING)
|
||||
|
@ -629,11 +629,11 @@ bool Position::gives_check(Move m, const CheckInfo& ci) const {
|
|||
Square to = to_sq(m);
|
||||
PieceType pt = type_of(piece_on(from));
|
||||
|
||||
// Direct check ?
|
||||
// Is there a direct check ?
|
||||
if (ci.checkSq[pt] & to)
|
||||
return true;
|
||||
|
||||
// Discovered check ?
|
||||
// Is there a discovered check ?
|
||||
if ( unlikely(ci.dcCandidates)
|
||||
&& (ci.dcCandidates & from)
|
||||
&& !aligned(from, to, king_square(~sideToMove)))
|
||||
|
@ -652,7 +652,7 @@ bool Position::gives_check(Move m, const CheckInfo& ci) const {
|
|||
return attacks_bb(Piece(promotion_type(m)), to, pieces() ^ from) & ksq;
|
||||
|
||||
// En passant capture with check ? We have already handled the case
|
||||
// of direct checks and ordinary discovered check, the only case we
|
||||
// of direct checks and ordinary discovered check, so the only case we
|
||||
// need to handle is the unusual case of a discovered check through
|
||||
// the captured pawn.
|
||||
case ENPASSANT:
|
||||
|
@ -700,7 +700,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
|
|||
|
||||
// Copy some fields of old state to our new StateInfo object except the ones
|
||||
// which are going to be recalculated from scratch anyway, then switch our state
|
||||
// pointer to point to the new, ready to be updated, state.
|
||||
// pointer to point to the new (ready to be updated) state.
|
||||
std::memcpy(&newSt, st, StateCopySize64 * sizeof(uint64_t));
|
||||
|
||||
newSt.previous = st;
|
||||
|
@ -709,7 +709,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
|
|||
// Update side to move
|
||||
k ^= Zobrist::side;
|
||||
|
||||
// Increment ply counters.In particular rule50 will be later reset it to zero
|
||||
// Increment ply counters.In particular rule50 will be reset to zero later on
|
||||
// in case of a capture or a pawn move.
|
||||
++gamePly;
|
||||
++st->rule50;
|
||||
|
@ -812,7 +812,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
|
|||
// If the moving piece is a pawn do some special extra work
|
||||
if (pt == PAWN)
|
||||
{
|
||||
// Set en-passant square, only if moved pawn can be captured
|
||||
// Set en-passant square if the moved pawn can be captured
|
||||
if ( (int(to) ^ int(from)) == 16
|
||||
&& (attacks_from<PAWN>(from + pawn_push(us), us) & pieces(them, PAWN)))
|
||||
{
|
||||
|
@ -860,7 +860,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
|
|||
// Update the key with the final value
|
||||
st->key = k;
|
||||
|
||||
// Update checkers bitboard, piece must be already moved
|
||||
// Update checkers bitboard: piece must be already moved
|
||||
st->checkersBB = 0;
|
||||
|
||||
if (moveIsCheck)
|
||||
|
@ -1133,7 +1133,7 @@ void Position::clear() {
|
|||
|
||||
|
||||
/// Position::compute_key() computes the hash key of the position. The hash
|
||||
/// key is usually updated incrementally as moves are made and unmade, the
|
||||
/// key is usually updated incrementally as moves are made and unmade. The
|
||||
/// compute_key() function is only used when a new position is set up, and
|
||||
/// to verify the correctness of the hash key when running in debug mode.
|
||||
|
||||
|
@ -1158,8 +1158,8 @@ Key Position::compute_key() const {
|
|||
|
||||
|
||||
/// Position::compute_pawn_key() computes the hash key of the position. The
|
||||
/// hash key is usually updated incrementally as moves are made and unmade,
|
||||
/// the compute_pawn_key() function is only used when a new position is set
|
||||
/// hash key is usually updated incrementally as moves are made and unmade.
|
||||
/// The compute_pawn_key() function is only used when a new position is set
|
||||
/// up, and to verify the correctness of the pawn hash key when running in
|
||||
/// debug mode.
|
||||
|
||||
|
@ -1178,8 +1178,8 @@ Key Position::compute_pawn_key() const {
|
|||
|
||||
|
||||
/// Position::compute_material_key() computes the hash key of the position.
|
||||
/// The hash key is usually updated incrementally as moves are made and unmade,
|
||||
/// the compute_material_key() function is only used when a new position is set
|
||||
/// The hash key is usually updated incrementally as moves are made and unmade.
|
||||
/// The compute_material_key() function is only used when a new position is set
|
||||
/// up, and to verify the correctness of the material hash key when running in
|
||||
/// debug mode.
|
||||
|
||||
|
@ -1218,7 +1218,7 @@ Score Position::compute_psq_score() const {
|
|||
|
||||
/// Position::compute_non_pawn_material() computes the total non-pawn middle
|
||||
/// game material value for the given side. Material values are updated
|
||||
/// incrementally during the search, this function is only used while
|
||||
/// incrementally during the search. This function is only used when
|
||||
/// initializing a new Position object.
|
||||
|
||||
Value Position::compute_non_pawn_material(Color c) const {
|
||||
|
@ -1233,7 +1233,7 @@ Value Position::compute_non_pawn_material(Color c) const {
|
|||
|
||||
|
||||
/// Position::is_draw() tests whether the position is drawn by material,
|
||||
/// repetition, or the 50 moves rule. It does not detect stalemates, this
|
||||
/// repetition, or the 50 moves rule. It does not detect stalemates: this
|
||||
/// must be done by the search.
|
||||
bool Position::is_draw() const {
|
||||
|
||||
|
@ -1268,7 +1268,7 @@ bool Position::is_draw() const {
|
|||
|
||||
|
||||
/// Position::flip() flips position with the white and black sides reversed. This
|
||||
/// is only useful for debugging especially for finding evaluation symmetry bugs.
|
||||
/// is only useful for debugging e.g. for finding evaluation symmetry bugs.
|
||||
|
||||
static char toggle_case(char c) {
|
||||
return char(islower(c) ? toupper(c) : tolower(c));
|
||||
|
@ -1305,7 +1305,7 @@ void Position::flip() {
|
|||
}
|
||||
|
||||
|
||||
/// Position::pos_is_ok() performs some consitency checks for the position object.
|
||||
/// Position::pos_is_ok() performs some consistency checks for the position object.
|
||||
/// This is meant to be helpful when debugging.
|
||||
|
||||
bool Position::pos_is_ok(int* failedStep) const {
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
/// PSQT[PieceType][Square] contains Piece-Square scores. For each piece type on
|
||||
/// a given square a (midgame, endgame) score pair is assigned. PSQT is defined
|
||||
/// for white side, for black side the tables are symmetric.
|
||||
/// for the white side and the tables are symmetric for the black side.
|
||||
|
||||
static const Score PSQT[][SQUARE_NB] = {
|
||||
{ },
|
||||
|
|
145
src/search.cpp
145
src/search.cpp
|
@ -263,11 +263,11 @@ finalize:
|
|||
sync_cout << "info nodes " << RootPos.nodes_searched()
|
||||
<< " time " << Time::now() - SearchTime + 1 << sync_endl;
|
||||
|
||||
// When we reach max depth we arrive here even without Signals.stop being raised,
|
||||
// but if we are pondering or in infinite search, according to UCI protocol,
|
||||
// we shouldn't print the best move before the GUI sends a "stop" or "ponderhit"
|
||||
// command. We simply wait here until GUI sends one of those commands (that
|
||||
// raise Signals.stop).
|
||||
// When we reach the maximum depth, we can arrive here without a raise of
|
||||
// Signals.stop. However, if we are pondering or in an infinite search,
|
||||
// the UCI protocol states that we shouldn't print the best move before the
|
||||
// GUI sends a "stop" or "ponderhit" command. We therefore simply wait here
|
||||
// until the GUI sends one of those commands (which also raises Signals.stop).
|
||||
if (!Signals.stop && (Limits.ponder || Limits.infinite))
|
||||
{
|
||||
Signals.stopOnPonderhit = true;
|
||||
|
@ -322,8 +322,8 @@ namespace {
|
|||
// Age out PV variability metric
|
||||
BestMoveChanges *= 0.8;
|
||||
|
||||
// Save last iteration's scores before first PV line is searched and all
|
||||
// the move scores except the (new) PV are set to -VALUE_INFINITE.
|
||||
// Save the last iteration's scores before first PV line is searched and
|
||||
// all the move scores except the (new) PV are set to -VALUE_INFINITE.
|
||||
for (size_t i = 0; i < RootMoves.size(); ++i)
|
||||
RootMoves[i].prevScore = RootMoves[i].score;
|
||||
|
||||
|
@ -338,16 +338,17 @@ namespace {
|
|||
beta = std::min(RootMoves[PVIdx].prevScore + delta, VALUE_INFINITE);
|
||||
}
|
||||
|
||||
// Start with a small aspiration window and, in case of fail high/low,
|
||||
// research with bigger window until not failing high/low anymore.
|
||||
// Start with a small aspiration window and, in the case of a fail
|
||||
// high/low, re-search with a bigger window until we're not failing
|
||||
// high/low anymore.
|
||||
while (true)
|
||||
{
|
||||
bestValue = search<Root>(pos, ss, alpha, beta, depth * ONE_PLY, false);
|
||||
|
||||
// Bring to front the best move. It is critical that sorting is
|
||||
// done with a stable algorithm because all the values but the first
|
||||
// and eventually the new best one are set to -VALUE_INFINITE and
|
||||
// we want to keep the same order for all the moves but the new
|
||||
// Bring the best move to the front. It is critical that sorting
|
||||
// is done with a stable algorithm because all the values but the
|
||||
// first and eventually the new best one are set to -VALUE_INFINITE
|
||||
// and we want to keep the same order for all the moves but the new
|
||||
// PV that goes to the front. Note that in case of MultiPV search
|
||||
// the already searched PV lines are preserved.
|
||||
std::stable_sort(RootMoves.begin() + PVIdx, RootMoves.end());
|
||||
|
@ -359,18 +360,18 @@ namespace {
|
|||
|
||||
// If search has been stopped break immediately. Sorting and
|
||||
// writing PV back to TT is safe becuase RootMoves is still
|
||||
// valid, although refers to previous iteration.
|
||||
// valid, although it refers to previous iteration.
|
||||
if (Signals.stop)
|
||||
break;
|
||||
|
||||
// When failing high/low give some update (without cluttering
|
||||
// the UI) before to research.
|
||||
// the UI) before a re-search.
|
||||
if ( (bestValue <= alpha || bestValue >= beta)
|
||||
&& Time::now() - SearchTime > 3000)
|
||||
sync_cout << uci_pv(pos, depth, alpha, beta) << sync_endl;
|
||||
|
||||
// In case of failing low/high increase aspiration window and
|
||||
// research, otherwise exit the loop.
|
||||
// re-search, otherwise exit the loop.
|
||||
if (bestValue <= alpha)
|
||||
{
|
||||
alpha = std::max(bestValue - delta, -VALUE_INFINITE);
|
||||
|
@ -396,7 +397,7 @@ namespace {
|
|||
sync_cout << uci_pv(pos, depth, alpha, beta) << sync_endl;
|
||||
}
|
||||
|
||||
// Do we now need to pick now the sub-optimal best move ?
|
||||
// If skill levels are enabled and time is up, pick a sub-optimal best move
|
||||
if (skill.enabled() && skill.time_to_pick(depth))
|
||||
skill.pick_move();
|
||||
|
||||
|
@ -426,13 +427,13 @@ namespace {
|
|||
if (depth > 4 && depth < 50 && PVSize == 1)
|
||||
TimeMgr.pv_instability(BestMoveChanges);
|
||||
|
||||
// Stop search if most of the available time is already consumed. We
|
||||
// Stop the search if most of the available time has been used. We
|
||||
// probably don't have enough time to search the first move at the
|
||||
// next iteration anyway.
|
||||
if (Time::now() - SearchTime > (TimeMgr.available_time() * 62) / 100)
|
||||
stop = true;
|
||||
|
||||
// Stop search early if one move seems to be much better than others
|
||||
// Stop the search early if one move seems to be much better than others
|
||||
if ( depth >= 12
|
||||
&& BestMoveChanges <= DBL_EPSILON
|
||||
&& !stop
|
||||
|
@ -455,7 +456,7 @@ namespace {
|
|||
if (stop)
|
||||
{
|
||||
// If we are allowed to ponder do not stop the search now but
|
||||
// keep pondering until GUI sends "ponderhit" or "stop".
|
||||
// keep pondering until the GUI sends "ponderhit" or "stop".
|
||||
if (Limits.ponder)
|
||||
Signals.stopOnPonderhit = true;
|
||||
else
|
||||
|
@ -469,9 +470,9 @@ namespace {
|
|||
// search<>() is the main search function for both PV and non-PV nodes and for
|
||||
// normal and SplitPoint nodes. When called just after a split point the search
|
||||
// is simpler because we have already probed the hash table, done a null move
|
||||
// search, and searched the first move before splitting, we don't have to repeat
|
||||
// all this work again. We also don't need to store anything to the hash table
|
||||
// here: This is taken care of after we return from the split point.
|
||||
// search, and searched the first move before splitting, so we don't have to
|
||||
// repeat all this work again. We also don't need to store anything to the hash
|
||||
// table here: This is taken care of after we return from the split point.
|
||||
|
||||
template <NodeType NT>
|
||||
Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, bool cutNode) {
|
||||
|
@ -535,9 +536,9 @@ namespace {
|
|||
// 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
|
||||
// a shorter mate was found upward in the tree then there is no need to search
|
||||
// further, we will never beat current alpha. Same logic but with reversed signs
|
||||
// applies also in the opposite condition of being mated instead of giving mate,
|
||||
// in this case return a fail-high score.
|
||||
// because we will never beat the current alpha. Same logic but with reversed
|
||||
// signs applies also in the opposite condition of being mated instead of giving
|
||||
// mate. In this case return a fail-high score.
|
||||
alpha = std::max(mated_in(ss->ply), alpha);
|
||||
beta = std::min(mate_in(ss->ply+1), beta);
|
||||
if (alpha >= beta)
|
||||
|
@ -553,8 +554,8 @@ namespace {
|
|||
ttMove = RootNode ? RootMoves[PVIdx].pv[0] : tte ? tte->move() : MOVE_NONE;
|
||||
ttValue = tte ? value_from_tt(tte->value(), ss->ply) : VALUE_NONE;
|
||||
|
||||
// At PV nodes we check for exact scores, while at non-PV nodes we check for
|
||||
// a fail high/low. Biggest advantage at probing at PV nodes is to have a
|
||||
// At PV nodes we check for exact scores, whilst at non-PV nodes we check for
|
||||
// a fail high/low. The biggest advantage to probing at PV nodes is to have a
|
||||
// smooth experience in analysis mode. We don't probe at Root nodes otherwise
|
||||
// we should also update RootMoveList to avoid bogus output.
|
||||
if ( !RootNode
|
||||
|
@ -782,7 +783,7 @@ moves_loop: // When in check and at SpNode search starts from here
|
|||
|
||||
if (SpNode)
|
||||
{
|
||||
// Shared counter cannot be decremented later if move turns out to be illegal
|
||||
// Shared counter cannot be decremented later if the move turns out to be illegal
|
||||
if (!pos.legal(move, ci.pinned))
|
||||
continue;
|
||||
|
||||
|
@ -816,8 +817,8 @@ moves_loop: // When in check and at SpNode search starts from here
|
|||
// Singular extension search. If all moves but one fail low on a search of
|
||||
// (alpha-s, beta-s), and just one fails high on (alpha, beta), then that move
|
||||
// is singular and should be extended. To verify this we do a reduced search
|
||||
// on all the other moves but the ttMove, if result is lower than ttValue minus
|
||||
// a margin then we extend ttMove.
|
||||
// on all the other moves but the ttMove and if the result is lower than
|
||||
// ttValue minus a margin then we extend the ttMove.
|
||||
if ( singularExtensionNode
|
||||
&& move == ttMove
|
||||
&& !ext
|
||||
|
@ -837,7 +838,7 @@ moves_loop: // When in check and at SpNode search starts from here
|
|||
ext = ONE_PLY;
|
||||
}
|
||||
|
||||
// Update current move (this must be done after singular extension search)
|
||||
// Update the current move (this must be done after singular extension search)
|
||||
newDepth = depth - ONE_PLY + ext;
|
||||
|
||||
// Step 13. Pruning at shallow depth (exclude PV nodes)
|
||||
|
@ -891,7 +892,7 @@ moves_loop: // When in check and at SpNode search starts from here
|
|||
}
|
||||
}
|
||||
|
||||
// Check for legality only before to do the move
|
||||
// Check for legality just before making the move
|
||||
if (!RootNode && !SpNode && !pos.legal(move, ci.pinned))
|
||||
{
|
||||
moveCount--;
|
||||
|
@ -950,8 +951,8 @@ moves_loop: // When in check and at SpNode search starts from here
|
|||
: - search<NonPV>(pos, ss+1, -(alpha+1), -alpha, newDepth, !cutNode);
|
||||
}
|
||||
|
||||
// Only for PV nodes do a full PV search on the first move or after a fail
|
||||
// high, in the latter case search only if value < beta, otherwise let the
|
||||
// For PV nodes only, do a full PV search on the first move or after a fail
|
||||
// high (in the latter case search only if value < beta), otherwise let the
|
||||
// parent node fail low with value <= alpha and to try another move.
|
||||
if (PvNode && (pvMove || (value > alpha && (RootNode || value < beta))))
|
||||
value = newDepth < ONE_PLY ?
|
||||
|
@ -995,9 +996,9 @@ moves_loop: // When in check and at SpNode search starts from here
|
|||
++BestMoveChanges;
|
||||
}
|
||||
else
|
||||
// All other moves but the PV are set to the lowest value, this
|
||||
// is not a problem when sorting becuase sort is stable and move
|
||||
// position in the list is preserved, just the PV is pushed up.
|
||||
// All other moves but the PV are set to the lowest value: this is
|
||||
// not a problem when sorting because the sort is stable and the
|
||||
// move position in the list is preserved - just the PV is pushed up.
|
||||
rm.score = -VALUE_INFINITE;
|
||||
}
|
||||
|
||||
|
@ -1047,7 +1048,7 @@ moves_loop: // When in check and at SpNode search starts from here
|
|||
// case of Signals.stop or thread.cutoff_occurred() are set, but this is
|
||||
// harmless because return value is discarded anyhow in the parent nodes.
|
||||
// If we are in a singular extension search then return a fail low score.
|
||||
// A split node has at least one move, the one tried before to be splitted.
|
||||
// A split node has at least one move - the one tried before to be splitted.
|
||||
if (!moveCount)
|
||||
return excludedMove ? alpha
|
||||
: inCheck ? mated_in(ss->ply) : DrawValue[pos.side_to_move()];
|
||||
|
@ -1122,11 +1123,11 @@ moves_loop: // When in check and at SpNode search starts from here
|
|||
ss->currentMove = bestMove = MOVE_NONE;
|
||||
ss->ply = (ss-1)->ply + 1;
|
||||
|
||||
// Check for an instant draw or maximum ply reached
|
||||
// Check for an instant draw or if the maximum ply has been reached
|
||||
if (pos.is_draw() || ss->ply > MAX_PLY)
|
||||
return DrawValue[pos.side_to_move()];
|
||||
|
||||
// Decide whether or not to include checks, this fixes also the type of
|
||||
// Decide whether or not to include checks: this fixes also the type of
|
||||
// TT entry depth that we are going to use. Note that in qsearch we use
|
||||
// only two types of depth in TT: DEPTH_QS_CHECKS or DEPTH_QS_NO_CHECKS.
|
||||
ttDepth = InCheck || depth >= DEPTH_QS_CHECKS ? DEPTH_QS_CHECKS
|
||||
|
@ -1230,7 +1231,7 @@ moves_loop: // When in check and at SpNode search starts from here
|
|||
}
|
||||
}
|
||||
|
||||
// Detect non-capture evasions that are candidate to be pruned
|
||||
// Detect non-capture evasions that are candidates to be pruned
|
||||
evasionPrunable = InCheck
|
||||
&& bestValue > VALUE_MATED_IN_MAX_PLY
|
||||
&& !pos.capture(move)
|
||||
|
@ -1244,7 +1245,7 @@ moves_loop: // When in check and at SpNode search starts from here
|
|||
&& pos.see_sign(move) < 0)
|
||||
continue;
|
||||
|
||||
// Check for legality only before to do the move
|
||||
// Check for legality just before making the move
|
||||
if (!pos.legal(move, ci.pinned))
|
||||
continue;
|
||||
|
||||
|
@ -1298,7 +1299,7 @@ moves_loop: // When in check and at SpNode search starts from here
|
|||
|
||||
// value_to_tt() adjusts a mate score from "plies to mate from the root" to
|
||||
// "plies to mate from the current position". Non-mate scores are unchanged.
|
||||
// The function is called before storing a value to the transposition table.
|
||||
// The function is called before storing a value in the transposition table.
|
||||
|
||||
Value value_to_tt(Value v, int ply) {
|
||||
|
||||
|
@ -1310,7 +1311,7 @@ moves_loop: // When in check and at SpNode search starts from here
|
|||
|
||||
|
||||
// value_from_tt() is the inverse of value_to_tt(): It adjusts a mate score
|
||||
// from the transposition table (where refers to the plies to mate/be mated
|
||||
// from the transposition table (which refers to the plies to mate/be mated
|
||||
// from current position) to "plies to mate/be mated from the root".
|
||||
|
||||
Value value_from_tt(Value v, int ply) {
|
||||
|
@ -1322,9 +1323,9 @@ moves_loop: // When in check and at SpNode search starts from here
|
|||
|
||||
|
||||
// allows() tests whether the 'first' move at previous ply somehow makes the
|
||||
// 'second' move possible, for instance if the moving piece is the same in
|
||||
// both moves. Normally the second move is the threat (the best move returned
|
||||
// from a null search that fails low).
|
||||
// 'second' move possible e.g. if the moving piece is the same in both moves.
|
||||
// Normally the second move is the threat (the best move returned from a null
|
||||
// search that fails low).
|
||||
|
||||
bool allows(const Position& pos, Move first, Move second) {
|
||||
|
||||
|
@ -1338,7 +1339,7 @@ moves_loop: // When in check and at SpNode search starts from here
|
|||
Square m1to = to_sq(first);
|
||||
Square m2to = to_sq(second);
|
||||
|
||||
// The piece is the same or second's destination was vacated by the first move
|
||||
// The piece is the same or second's destination was vacated by the first move.
|
||||
// We exclude the trivial case where a sliding piece does in two moves what
|
||||
// it could do in one move: eg. Ra1a2, Ra2a3.
|
||||
if ( m2to == m1from
|
||||
|
@ -1383,8 +1384,8 @@ moves_loop: // When in check and at SpNode search starts from here
|
|||
if (m1from == m2to)
|
||||
return true;
|
||||
|
||||
// If the threatened piece has value less than or equal to the value of the
|
||||
// threat piece, don't prune moves which defend it.
|
||||
// If the threatened piece has a value less than or equal to the value of
|
||||
// the threat piece, don't prune moves which defend it.
|
||||
if ( pos.capture(second)
|
||||
&& ( PieceValue[MG][pos.piece_on(m2from)] >= PieceValue[MG][pos.piece_on(m2to)]
|
||||
|| type_of(pos.piece_on(m2from)) == KING))
|
||||
|
@ -1393,7 +1394,7 @@ moves_loop: // When in check and at SpNode search starts from here
|
|||
Bitboard occ = pos.pieces() ^ m1from ^ m1to ^ m2from;
|
||||
Piece pc = pos.piece_on(m1from);
|
||||
|
||||
// The moved piece attacks the square 'tto' ?
|
||||
// Does the moved piece attack the square 'm2to' ?
|
||||
if (attacks_bb(pc, m1to, occ) & m2to)
|
||||
return true;
|
||||
|
||||
|
@ -1401,7 +1402,7 @@ moves_loop: // When in check and at SpNode search starts from here
|
|||
Bitboard xray = (attacks_bb< ROOK>(m2to, occ) & pos.pieces(color_of(pc), QUEEN, ROOK))
|
||||
| (attacks_bb<BISHOP>(m2to, occ) & pos.pieces(color_of(pc), QUEEN, BISHOP));
|
||||
|
||||
// Verify attackers are triggered by our move and not already existing
|
||||
// Verify attackers are triggered by our move and not already exist
|
||||
if (unlikely(xray) && (xray & ~pos.attacks_from<QUEEN>(m2to)))
|
||||
return true;
|
||||
}
|
||||
|
@ -1414,8 +1415,8 @@ moves_loop: // When in check and at SpNode search starts from here
|
|||
}
|
||||
|
||||
|
||||
// When playing with strength handicap choose best move among the MultiPV set
|
||||
// using a statistical rule dependent on 'level'. Idea by Heinz van Saanen.
|
||||
// When playing with a strength handicap, choose best move among the MultiPV
|
||||
// set using a statistical rule dependent on 'level'. Idea by Heinz van Saanen.
|
||||
|
||||
Move Skill::pick_move() {
|
||||
|
||||
|
@ -1432,7 +1433,7 @@ moves_loop: // When in check and at SpNode search starts from here
|
|||
best = MOVE_NONE;
|
||||
|
||||
// Choose best move. For each move score we add two terms both dependent on
|
||||
// weakness, one deterministic and bigger for weaker moves, and one random,
|
||||
// weakness. One deterministic and bigger for weaker moves, and one random,
|
||||
// then we choose the move with the resulting highest score.
|
||||
for (size_t i = 0; i < PVSize; ++i)
|
||||
{
|
||||
|
@ -1456,9 +1457,9 @@ moves_loop: // When in check and at SpNode search starts from here
|
|||
}
|
||||
|
||||
|
||||
// uci_pv() formats PV information according to UCI protocol. UCI requires
|
||||
// to send all the PV lines also if are still to be searched and so refer to
|
||||
// the previous search score.
|
||||
// uci_pv() formats PV information according to the UCI protocol. UCI
|
||||
// requires that all (if any) unsearched PV lines are sent using a previous
|
||||
// search score.
|
||||
|
||||
string uci_pv(const Position& pos, int depth, Value alpha, Value beta) {
|
||||
|
||||
|
@ -1504,9 +1505,9 @@ moves_loop: // When in check and at SpNode search starts from here
|
|||
|
||||
|
||||
/// RootMove::extract_pv_from_tt() builds a PV by adding moves from the TT table.
|
||||
/// We consider also failing high nodes and not only BOUND_EXACT nodes so to
|
||||
/// allow to always have a ponder move even when we fail high at root, and a
|
||||
/// long PV to print that is important for position analysis.
|
||||
/// We also consider both failing high nodes and BOUND_EXACT nodes here to
|
||||
/// ensure that we have a ponder move even when we fail high at root. This
|
||||
/// results in a long PV to print that is important for position analysis.
|
||||
|
||||
void RootMove::extract_pv_from_tt(Position& pos) {
|
||||
|
||||
|
@ -1568,7 +1569,7 @@ void RootMove::insert_pv_in_tt(Position& pos) {
|
|||
void Thread::idle_loop() {
|
||||
|
||||
// Pointer 'this_sp' is not null only if we are called from split(), and not
|
||||
// at the thread creation. So it means we are the split point's master.
|
||||
// at the thread creation. This means we are the split point's master.
|
||||
SplitPoint* this_sp = splitPointsSize ? activeSplitPoint : NULL;
|
||||
|
||||
assert(!this_sp || (this_sp->masterThread == this && searching));
|
||||
|
@ -1595,7 +1596,7 @@ void Thread::idle_loop() {
|
|||
break;
|
||||
}
|
||||
|
||||
// Do sleep after retesting sleep conditions under lock protection, in
|
||||
// Do sleep after retesting sleep conditions under lock protection. In
|
||||
// particular we need to avoid a deadlock in case a master thread has,
|
||||
// in the meanwhile, allocated us and sent the notify_one() call before
|
||||
// we had the chance to grab the lock.
|
||||
|
@ -1651,8 +1652,8 @@ void Thread::idle_loop() {
|
|||
sp->slavesMask &= ~(1ULL << idx);
|
||||
sp->nodes += pos.nodes_searched();
|
||||
|
||||
// Wake up master thread so to allow it to return from the idle loop
|
||||
// in case we are the last slave of the split point.
|
||||
// Wake up the master thread so to allow it to return from the idle
|
||||
// loop in case we are the last slave of the split point.
|
||||
if ( Threads.sleepWhileIdle
|
||||
&& this != sp->masterThread
|
||||
&& !sp->slavesMask)
|
||||
|
@ -1661,10 +1662,10 @@ void Thread::idle_loop() {
|
|||
sp->masterThread->notify_one();
|
||||
}
|
||||
|
||||
// After releasing the lock we cannot access anymore any SplitPoint
|
||||
// related data in a safe way becuase it could have been released under
|
||||
// our feet by the sp master. Also accessing other Thread objects is
|
||||
// unsafe because if we are exiting there is a chance are already freed.
|
||||
// After releasing the lock we can't access any SplitPoint related data
|
||||
// in a safe way because it could have been released under our feet by
|
||||
// the sp master. Also accessing other Thread objects is unsafe because
|
||||
// if we are exiting there is a chance that they are already freed.
|
||||
sp->mutex.unlock();
|
||||
}
|
||||
|
||||
|
@ -1683,8 +1684,8 @@ void Thread::idle_loop() {
|
|||
|
||||
|
||||
/// check_time() is called by the timer thread when the timer triggers. It is
|
||||
/// used to print debug info and, more important, to detect when we are out of
|
||||
/// available time and so stop the search.
|
||||
/// used to print debug info and, more importantly, to detect when we are out of
|
||||
/// available time and thus stop the search.
|
||||
|
||||
void check_time() {
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ struct LimitsType {
|
|||
|
||||
|
||||
/// The SignalsType struct stores volatile flags updated during the search
|
||||
/// typically in an async fashion, for instance to stop the search by the GUI.
|
||||
/// typically in an async fashion e.g. to stop the search by the GUI.
|
||||
|
||||
struct SignalsType {
|
||||
bool stopOnPonderhit, firstRootMove, stop, failedLowAtRoot;
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace {
|
|||
|
||||
|
||||
// Helpers to launch a thread after creation and joining before delete. Must be
|
||||
// outside Thread c'tor and d'tor because object shall be fully initialized
|
||||
// outside Thread c'tor and d'tor because the object will be fully initialized
|
||||
// when start_routine (and hence virtual idle_loop) is called and when joining.
|
||||
|
||||
template<typename T> T* new_thread() {
|
||||
|
@ -77,8 +77,8 @@ void ThreadBase::wait_for(volatile const bool& b) {
|
|||
}
|
||||
|
||||
|
||||
// Thread c'tor just inits data but does not launch any thread of execution that
|
||||
// instead will be started only upon c'tor returns.
|
||||
// Thread c'tor just inits data and does not launch any execution thread.
|
||||
// Such a thread will only be started when c'tor returns.
|
||||
|
||||
Thread::Thread() /* : splitPoints() */ { // Value-initialization bug in MSVC
|
||||
|
||||
|
@ -112,7 +112,7 @@ void TimerThread::idle_loop() {
|
|||
|
||||
|
||||
// MainThread::idle_loop() is where the main thread is parked waiting to be started
|
||||
// when there is a new search. Main thread will launch all the slave threads.
|
||||
// when there is a new search. The main thread will launch all the slave threads.
|
||||
|
||||
void MainThread::idle_loop() {
|
||||
|
||||
|
@ -124,7 +124,7 @@ void MainThread::idle_loop() {
|
|||
|
||||
while (!thinking && !exit)
|
||||
{
|
||||
Threads.sleepCondition.notify_one(); // Wake up UI thread if needed
|
||||
Threads.sleepCondition.notify_one(); // Wake up the UI thread if needed
|
||||
sleepCondition.wait(mutex);
|
||||
}
|
||||
|
||||
|
@ -170,7 +170,7 @@ bool Thread::available_to(const Thread* master) const {
|
|||
return false;
|
||||
|
||||
// Make a local copy to be sure doesn't become zero under our feet while
|
||||
// testing next condition and so leading to an out of bound access.
|
||||
// testing next condition and so leading to an out of bounds access.
|
||||
int size = splitPointsSize;
|
||||
|
||||
// No split points means that the thread is available as a slave for any
|
||||
|
@ -206,8 +206,9 @@ void ThreadPool::exit() {
|
|||
|
||||
// read_uci_options() updates internal threads parameters from the corresponding
|
||||
// UCI options and creates/destroys threads to match the requested number. Thread
|
||||
// objects are dynamically allocated to avoid creating in advance all possible
|
||||
// threads, with included pawns and material tables, if only few are used.
|
||||
// objects are dynamically allocated to avoid creating all possible threads
|
||||
// in advance (which include pawns and material tables), even if only a few
|
||||
// are to be used.
|
||||
|
||||
void ThreadPool::read_uci_options() {
|
||||
|
||||
|
@ -323,8 +324,9 @@ void Thread::split(Position& pos, const Stack* ss, Value alpha, Value beta, Valu
|
|||
|
||||
Thread::idle_loop(); // Force a call to base class idle_loop()
|
||||
|
||||
// In helpful master concept a master can help only a sub-tree of its split
|
||||
// point, and because here is all finished is not possible master is booked.
|
||||
// In the helpful master concept, a master can help only a sub-tree of its
|
||||
// split point and because everything is finished here, it's not possible
|
||||
// for the master to be booked.
|
||||
assert(!searching);
|
||||
assert(!activePosition);
|
||||
|
||||
|
|
|
@ -151,7 +151,7 @@ struct TimerThread : public ThreadBase {
|
|||
|
||||
|
||||
/// ThreadPool struct handles all the threads related stuff like init, starting,
|
||||
/// parking and, the most important, launching a slave thread at a split point.
|
||||
/// parking and, most importantly, launching a slave thread at a split point.
|
||||
/// All the access to shared thread data is done through this class.
|
||||
|
||||
struct ThreadPool : public std::vector<Thread*> {
|
||||
|
|
|
@ -112,11 +112,11 @@ void TimeManager::init(const Search::LimitsType& limits, int currentPly, Color u
|
|||
unstablePVExtraTime = 0;
|
||||
optimumSearchTime = maximumSearchTime = limits.time[us];
|
||||
|
||||
// We calculate optimum time usage for different hypothetic "moves to go"-values and choose the
|
||||
// We calculate optimum time usage for different hypothetical "moves to go"-values and choose the
|
||||
// minimum of calculated search time values. Usually the greatest hypMTG gives the minimum values.
|
||||
for (hypMTG = 1; hypMTG <= (limits.movestogo ? std::min(limits.movestogo, MoveHorizon) : MoveHorizon); ++hypMTG)
|
||||
{
|
||||
// Calculate thinking time for hypothetic "moves to go"-value
|
||||
// Calculate thinking time for hypothetical "moves to go"-value
|
||||
hypMyTime = limits.time[us]
|
||||
+ limits.inc[us] * (hypMTG - 1)
|
||||
- emergencyBaseTime
|
||||
|
|
10
src/tt.cpp
10
src/tt.cpp
|
@ -83,11 +83,11 @@ const TTEntry* TranspositionTable::probe(const Key key) const {
|
|||
|
||||
/// TranspositionTable::store() writes a new entry containing position key and
|
||||
/// valuable information of current position. The lowest order bits of position
|
||||
/// key are used to decide on which cluster the position will be placed.
|
||||
/// When a new entry is written and there are no empty entries available in cluster,
|
||||
/// it replaces the least valuable of entries. A TTEntry t1 is considered to be
|
||||
/// more valuable than a TTEntry t2 if t1 is from the current search and t2 is from
|
||||
/// a previous search, or if the depth of t1 is bigger than the depth of t2.
|
||||
/// key are used to decide in which cluster the position will be placed.
|
||||
/// When a new entry is written and there are no empty entries available in the
|
||||
/// cluster, it replaces the least valuable of the entries. A TTEntry t1 is considered
|
||||
/// to be more valuable than a TTEntry t2 if t1 is from the current search and t2
|
||||
/// is from a previous search, or if the depth of t1 is bigger than the depth of t2.
|
||||
|
||||
void TranspositionTable::store(const Key key, Value v, Bound b, Depth d, Move m, Value statV) {
|
||||
|
||||
|
|
8
src/tt.h
8
src/tt.h
|
@ -66,9 +66,9 @@ private:
|
|||
|
||||
/// A TranspositionTable consists of a power of 2 number of clusters and each
|
||||
/// cluster consists of ClusterSize number of TTEntry. Each non-empty entry
|
||||
/// contains information of exactly one position. Size of a cluster shall not be
|
||||
/// bigger than a cache line size. In case it is less, it should be padded to
|
||||
/// guarantee always aligned accesses.
|
||||
/// contains information of exactly one position. The size of a cluster should
|
||||
/// not be bigger than a cache line size. In case it is less, it should be padded
|
||||
/// to guarantee always aligned accesses.
|
||||
|
||||
class TranspositionTable {
|
||||
|
||||
|
@ -106,7 +106,7 @@ inline TTEntry* TranspositionTable::first_entry(const Key key) const {
|
|||
|
||||
|
||||
/// TranspositionTable::refresh() updates the 'generation' value of the TTEntry
|
||||
/// to avoid aging. Normally called after a TT hit.
|
||||
/// to avoid aging. It is normally called after a TT hit.
|
||||
|
||||
inline void TranspositionTable::refresh(const TTEntry* tte) const {
|
||||
|
||||
|
|
11
src/types.h
11
src/types.h
|
@ -26,7 +26,7 @@
|
|||
/// For Windows, part of the configuration is detected automatically, but some
|
||||
/// switches need to be set manually:
|
||||
///
|
||||
/// -DNDEBUG | Disable debugging mode. Use always.
|
||||
/// -DNDEBUG | Disable debugging mode. Always use this.
|
||||
///
|
||||
/// -DNO_PREFETCH | Disable use of prefetch asm-instruction. A must if you want
|
||||
/// | the executable to run on some very old machines.
|
||||
|
@ -236,10 +236,11 @@ enum Rank {
|
|||
};
|
||||
|
||||
|
||||
/// Score enum keeps a midgame and an endgame value in a single integer (enum),
|
||||
/// first LSB 16 bits are used to store endgame value, while upper bits are used
|
||||
/// for midgame value. Compiler is free to choose the enum type as long as can
|
||||
/// keep its data, so ensure Score to be an integer type.
|
||||
/// The Score enum stores a midgame and an endgame value in a single integer
|
||||
/// (enum). The least significant 16 bits are used to store the endgame value
|
||||
/// and the upper 16 bits are used to store the midgame value. The compiler is
|
||||
/// free to choose the enum type as long as it can store the data, so we
|
||||
/// ensure that Score is an integer type by assigning some big int values.
|
||||
enum Score {
|
||||
SCORE_ZERO,
|
||||
SCORE_ENSURE_INTEGER_SIZE_P = INT_MAX,
|
||||
|
|
11
src/uci.cpp
11
src/uci.cpp
|
@ -39,8 +39,9 @@ namespace {
|
|||
// FEN string of the initial position, normal chess
|
||||
const char* StartFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
|
||||
|
||||
// Keep track of position keys along the setup moves (from start position to the
|
||||
// position just before to start searching). Needed by repetition draw detection.
|
||||
// Keep a track of the position keys along the setup moves (from the start position
|
||||
// to the position just before the search starts). This is needed by the repetition
|
||||
// draw detection code.
|
||||
Search::StateStackPtr SetupStates;
|
||||
|
||||
void setoption(istringstream& up);
|
||||
|
@ -69,11 +70,11 @@ void UCI::loop(const string& args) {
|
|||
|
||||
if (token == "quit" || token == "stop" || token == "ponderhit")
|
||||
{
|
||||
// GUI sends 'ponderhit' to tell us to ponder on the same move the
|
||||
// The GUI sends 'ponderhit' to tell us to ponder on the same move the
|
||||
// opponent has played. In case Signals.stopOnPonderhit is set we are
|
||||
// waiting for 'ponderhit' to stop the search (for instance because we
|
||||
// already ran out of time), otherwise we should continue searching but
|
||||
// switching from pondering to normal search.
|
||||
// switch from pondering to normal search.
|
||||
if (token != "ponderhit" || Search::Signals.stopOnPonderhit)
|
||||
{
|
||||
Search::Signals.stop = true;
|
||||
|
@ -121,7 +122,7 @@ void UCI::loop(const string& args) {
|
|||
|
||||
} while (token != "quit" && args.empty()); // Args have one-shot behaviour
|
||||
|
||||
Threads.wait_for_think_finished(); // Cannot quit while search is running
|
||||
Threads.wait_for_think_finished(); // Cannot quit whilst the search is running
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ bool CaseInsensitiveLess::operator() (const string& s1, const string& s2) const
|
|||
}
|
||||
|
||||
|
||||
/// init() initializes the UCI options to their hard coded default values
|
||||
/// init() initializes the UCI options to their hard-coded default values
|
||||
|
||||
void init(OptionsMap& o) {
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue