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

Big assorted spelling fixes

No functional change.
This commit is contained in:
Richard Lloyd 2013-12-02 19:04:09 +01:00 committed by Marco Costalba
parent 500b9b0eb3
commit 13a73f67c0
30 changed files with 265 additions and 249 deletions

View file

@ -8,7 +8,7 @@ documentation for your GUI of choice for information about how to use
Stockfish with it. Stockfish with it.
This version of Stockfish supports up to 64 CPUs. The engine defaults 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 the *Threads* UCI parameter, and to make sure it equals the number of CPU
cores on your computer. 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. 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 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 compile (for instance with Microsoft MSVC) you need to manually
set/unset some switches in the compiler command line; see file *types.h* set/unset some switches in the compiler command line; see file *types.h*
for a quick reference. for a quick reference.

View file

@ -66,7 +66,7 @@ static const char* Defaults[] = {
/// benchmark() runs a simple benchmark by letting Stockfish analyze a set /// 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 /// transposition table size, the number of search threads that should
/// be used, the limit value spent for each position (optional, default is /// 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 /// 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===========================" cerr << "\n==========================="
<< "\nTotal time (ms) : " << elapsed << "\nTotal time (ms) : " << elapsed

View file

@ -80,8 +80,8 @@ namespace {
} }
} }
/// lsb()/msb() finds the least/most 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 nonzero bitboard. /// pop_lsb() finds and clears the least significant bit in a non-zero bitboard.
#ifndef USE_BSFQ #ifndef USE_BSFQ

View file

@ -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. /// lsb()/msb() finds the least/most significant bit in a non-zero bitboard.
/// pop_lsb() finds and clears the least significant bit in a nonzero bitboard. /// pop_lsb() finds and clears the least significant bit in a non-zero bitboard.
#ifdef USE_BSFQ #ifdef USE_BSFQ

View file

@ -32,14 +32,14 @@ enum BitCountType {
CNT_HW_POPCNT CNT_HW_POPCNT
}; };
/// Determine at compile time the best popcount<> specialization according if /// Determine at compile time the best popcount<> specialization according to
/// platform is 32 or 64 bits, to the maximum number of nonzero bits to count /// whether the platform is 32 or 64 bits, to the maximum number of non-zero
/// and if hardware popcnt instruction is available. /// 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 Full = HasPopCnt ? CNT_HW_POPCNT : Is64Bit ? CNT_64 : CNT_32;
const BitCountType Max15 = HasPopCnt ? CNT_HW_POPCNT : Is64Bit ? CNT_64_MAX15 : CNT_32_MAX15; 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<BitCountType> inline int popcount(Bitboard);
template<> template<>

View file

@ -354,7 +354,7 @@ PolyglotBook::~PolyglotBook() { if (is_open()) close(); }
/// operator>>() reads sizeof(T) chars from the file's binary byte stream and /// 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. /// big-endian format.
template<typename T> PolyglotBook& PolyglotBook::operator>>(T& n) { 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); ifstream::open(fName, ifstream::in | ifstream::binary);
fileName = is_open() ? fName : ""; 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(); return !fileName.empty();
} }
/// probe() tries to find a book move for the given position. If no move is /// 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 /// found, it returns MOVE_NONE. If pickBest is true, then it always returns
/// rated move, otherwise randomly chooses one, based on the move score. /// 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) { 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 6-11: origin square (from 0 to 63)
// bit 12-14: promotion piece (from KNIGHT == 1 to QUEEN == 4) // bit 12-14: promotion piece (from KNIGHT == 1 to QUEEN == 4)
// //
// Castling moves follow "king captures rook" representation. So in case book // Castling moves follow the "king captures rook" representation. If a book
// move is a promotion we have to convert to our representation, in all the // move is a promotion, we have to convert it to our representation and in
// other cases we can directly compare with a Move after having masked out // all other cases, we can directly compare with a Move after having masked
// the special Move's flags (bit 14-15) that are not supported by PolyGlot. // out the special Move flags (bit 14-15) that are not supported by PolyGlot.
int pt = (move >> 12) & 7; int pt = (move >> 12) & 7;
if (pt) if (pt)
move = make<PROMOTION>(from_sq(move), to_sq(move), PieceType(pt + 1)); move = make<PROMOTION>(from_sq(move), to_sq(move), PieceType(pt + 1));

View file

@ -145,7 +145,7 @@ void Endgames::add(const string& code) {
/// Mate with KX vs K. This function is used to evaluate positions with /// 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 /// 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. /// of the board, and for keeping the distance between the two kings small.
template<> template<>
@ -187,9 +187,9 @@ Value Endgame<KBNK>::operator()(const Position& pos) const {
Square loserKSq = pos.king_square(weakSide); Square loserKSq = pos.king_square(weakSide);
Square bishopSq = pos.list<BISHOP>(strongSide)[0]; Square bishopSq = pos.list<BISHOP>(strongSide)[0];
// kbnk_mate_table() tries to drive toward corners A1 or H8, // kbnk_mate_table() tries to drive toward corners A1 or H8, if we have a
// if we have a bishop that cannot reach the above squares we // bishop that cannot reach the above squares we flip the kings in order
// flip the kings so to drive enemy toward corners A8 or H1. // to drive the enemy toward corners A8 or H1.
if (opposite_colors(bishopSq, SQ_A1)) if (opposite_colors(bishopSq, SQ_A1))
{ {
winnerKSq = ~winnerKSq; 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 /// KQ vs KP. In general, this is a win for the stronger side, but there are a
/// important exceptions. Pawn on 7th rank, A,C,F or H file, with king next can /// few important exceptions. A pawn on 7th rank and on the A,C,F or H files
/// be a draw, so we scale down to distance between kings only. /// with a king positioned next to it can be a draw, so in that case, we only
/// use the distance between the kings.
template<> template<>
Value Endgame<KQKP>::operator()(const Position& pos) const { Value Endgame<KQKP>::operator()(const Position& pos) const {
@ -405,20 +406,20 @@ ScaleFactor Endgame<KBPsK>::operator()(const Position& pos) const {
return SCALE_FACTOR_DRAW; 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) if ( (pawnFile == FILE_B || pawnFile == FILE_G)
&& !(pos.pieces(PAWN) & ~file_bb(pawnFile)) && !(pos.pieces(PAWN) & ~file_bb(pawnFile))
&& pos.non_pawn_material(weakSide) == 0 && pos.non_pawn_material(weakSide) == 0
&& pos.count<PAWN>(weakSide) >= 1) && 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 weakPawnSq = backmost_sq(weakSide, pos.pieces(weakSide, PAWN));
Square strongKingSq = pos.king_square(strongSide); Square strongKingSq = pos.king_square(strongSide);
Square weakKingSq = pos.king_square(weakSide); Square weakKingSq = pos.king_square(weakSide);
Square bishopSq = pos.list<BISHOP>(strongSide)[0]; 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 // the bishop cannot attack it or they only have one pawn left
if ( relative_rank(strongSide, weakPawnSq) == RANK_7 if ( relative_rank(strongSide, weakPawnSq) == RANK_7
&& (pos.pieces(strongSide, PAWN) & (weakPawnSq + pawn_push(weakSide))) && (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 strongKingDist = square_distance(weakPawnSq, strongKingSq);
int weakKingDist = square_distance(weakPawnSq, weakKingSq); 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 // squares of the blocking pawn and the strong king is not
// closer. (I think this rule only fails in practically // closer. (I think this rule only fails in practically
// unreachable positions such as 5k1K/6p1/6P1/8/8/3B4/8/8 w // 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. /// 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, /// 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<> template<>
ScaleFactor Endgame<KRPKR>::operator()(const Position& pos) const { 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)) switch (file_distance(psq1, psq2))
{ {
case 0: case 0:
// Both pawns are on the same file. Easy draw if defender firmly controls // Both pawns are on the same file. It's an easy draw if the defender firmly
// some square in the frontmost pawn's path. // controls some square in the frontmost pawn's path.
if ( file_of(ksq) == file_of(blockSq1) if ( file_of(ksq) == file_of(blockSq1)
&& relative_rank(strongSide, ksq) >= relative_rank(strongSide, blockSq1) && relative_rank(strongSide, ksq) >= relative_rank(strongSide, blockSq1)
&& opposite_colors(ksq, wbsq)) && opposite_colors(ksq, wbsq))
@ -770,9 +771,9 @@ ScaleFactor Endgame<KBPPKB>::operator()(const Position& pos) const {
return SCALE_FACTOR_NONE; return SCALE_FACTOR_NONE;
case 1: case 1:
// Pawns on adjacent files. Draw if defender firmly controls the square // Pawns on adjacent files. It's a draw if the defender firmly controls the
// in front of the frontmost pawn's path, and the square diagonally behind // square in front of the frontmost pawn's path, and the square diagonally
// this square on the file of the other pawn. // behind this square on the file of the other pawn.
if ( ksq == blockSq1 if ( ksq == blockSq1
&& opposite_colors(ksq, wbsq) && opposite_colors(ksq, wbsq)
&& ( bbsq == blockSq2 && ( bbsq == blockSq2

View file

@ -64,9 +64,9 @@ enum EndgameType {
}; };
/// Endgame functions can be of two types according if return a Value or a /// Endgame functions can be of two types depending on whether they return a
/// ScaleFactor. Type eg_fun<int>::type equals to either ScaleFactor or Value /// Value or a ScaleFactor. Type eg_fun<int>::type returns either ScaleFactor
/// depending if the template parameter is 0 or 1. /// or Value depending on whether the template parameter is 0 or 1.
template<int> struct eg_fun { typedef Value type; }; template<int> struct eg_fun { typedef Value type; };
template<> struct eg_fun<1> { typedef ScaleFactor 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 /// The Endgames class stores the pointers to endgame evaluation and scaling
/// and scaling base objects. Then we use polymorphism to invoke the actual /// base objects in two std::map typedefs. We then use polymorphism to invoke
/// endgame function calling its operator() that is virtual. /// the actual endgame function by calling its virtual operator().
class Endgames { class Endgames {

View file

@ -269,9 +269,10 @@ namespace Eval {
} }
/// trace() is like evaluate() but instead of a value returns a string suitable /// trace() is like evaluate(), but instead of returning a value, it returns
/// to be print on stdout with the detailed descriptions and values of each /// a string (suitable for outputting to stdout) that contains the detailed
/// evaluation term. Used mainly for debugging. /// descriptions and values of each evaluation term. It's mainly used for
/// debugging.
std::string trace(const Position& pos) { std::string trace(const Position& pos) {
return Tracing::do_trace(pos); return Tracing::do_trace(pos);
} }
@ -316,7 +317,7 @@ Value do_evaluate(const Position& pos) {
Thread* th = pos.this_thread(); Thread* th = pos.this_thread();
// Initialize score by reading the incrementally updated scores included // 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. // Tempo bonus. Score is computed from the point of view of white.
score = pos.psq_score() + (pos.side_to_move() == WHITE ? Tempo : -Tempo); score = pos.psq_score() + (pos.side_to_move() == WHITE ? Tempo : -Tempo);
@ -378,7 +379,8 @@ Value do_evaluate(const Position& pos) {
&& pos.opposite_bishops() && pos.opposite_bishops()
&& sf == SCALE_FACTOR_NORMAL) && 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 if ( pos.non_pawn_material(WHITE) == BishopValueMg
&& pos.non_pawn_material(BLACK) == BishopValueMg) && pos.non_pawn_material(BLACK) == BishopValueMg)
{ {
@ -510,7 +512,7 @@ Value do_evaluate(const Position& pos) {
mobility[Us] += MobilityBonus[Piece][mob]; 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. // of threat evaluation must be done later when we have full attack info.
if (ei.attackedBy[Them][PAWN] & s) if (ei.attackedBy[Them][PAWN] & s)
score -= ThreatenedByPawn[Piece]; score -= ThreatenedByPawn[Piece];
@ -568,8 +570,8 @@ Value do_evaluate(const Position& pos) {
Square ksq = pos.king_square(Us); Square ksq = pos.king_square(Us);
// Penalize rooks which are trapped inside a king. Penalize more if // Penalize rooks which are trapped by a king. Penalize more if the
// king has lost castling availability. // king has lost its castling capability.
if ( ((file_of(ksq) < FILE_E) == (file_of(s) < file_of(ksq))) if ( ((file_of(ksq) < FILE_E) == (file_of(s) < file_of(ksq)))
&& (rank_of(ksq) == rank_of(s) || relative_rank(Us, ksq) == RANK_1) && (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)) && !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 if ( ei.kingAttackersCount[Them] >= 2
&& ei.kingAdjacentZoneAttacksCount[Them]) && 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 // apart from the king itself
undefended = ei.attackedBy[Them][ALL_PIECES] undefended = ei.attackedBy[Them][ALL_PIECES]
& ei.attackedBy[Us][KING] & ei.attackedBy[Us][KING]
@ -662,12 +664,13 @@ Value do_evaluate(const Position& pos) {
+ KingExposed[relative_square(Us, ksq)] + KingExposed[relative_square(Us, ksq)]
- mg_value(score) / 32; - mg_value(score) / 32;
// Analyse enemy's safe queen contact checks. First find undefended // Analyse the enemy's safe queen contact checks. Firstly, find the
// squares around the king attacked by enemy queen... // undefended squares around the king that are attacked by the enemy's
// queen...
b = undefended & ei.attackedBy[Them][QUEEN] & ~pos.pieces(Them); b = undefended & ei.attackedBy[Them][QUEEN] & ~pos.pieces(Them);
if (b) 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] b &= ( ei.attackedBy[Them][PAWN] | ei.attackedBy[Them][KNIGHT]
| ei.attackedBy[Them][BISHOP] | ei.attackedBy[Them][ROOK]); | ei.attackedBy[Them][BISHOP] | ei.attackedBy[Them][ROOK]);
if (b) if (b)
@ -676,16 +679,17 @@ Value do_evaluate(const Position& pos) {
* (Them == pos.side_to_move() ? 2 : 1); * (Them == pos.side_to_move() ? 2 : 1);
} }
// Analyse enemy's safe rook contact checks. First find undefended // Analyse the enemy's safe rook contact checks. Firstly, find the
// squares around the king attacked by enemy rooks... // undefended squares around the king that are attacked by the enemy's
// rooks...
b = undefended & ei.attackedBy[Them][ROOK] & ~pos.pieces(Them); 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]; b &= PseudoAttacks[ROOK][ksq];
if (b) 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] b &= ( ei.attackedBy[Them][PAWN] | ei.attackedBy[Them][KNIGHT]
| ei.attackedBy[Them][BISHOP] | ei.attackedBy[Them][QUEEN]); | ei.attackedBy[Them][BISHOP] | ei.attackedBy[Them][QUEEN]);
if (b) if (b)
@ -694,7 +698,7 @@ Value do_evaluate(const Position& pos) {
* (Them == pos.side_to_move() ? 2 : 1); * (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]); safe = ~(pos.pieces(Them) | ei.attackedBy[Us][ALL_PIECES]);
b1 = pos.attacks_from<ROOK>(ksq) & safe; b1 = pos.attacks_from<ROOK>(ksq) & safe;
@ -746,7 +750,7 @@ Value do_evaluate(const Position& pos) {
Bitboard b, undefendedMinors, weakEnemies; Bitboard b, undefendedMinors, weakEnemies;
Score score = SCORE_ZERO; 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) undefendedMinors = pos.pieces(Them, BISHOP, KNIGHT)
& ~ei.attackedBy[Them][ALL_PIECES]; & ~ei.attackedBy[Them][ALL_PIECES];
@ -807,7 +811,7 @@ Value do_evaluate(const Position& pos) {
{ {
Square blockSq = s + pawn_push(Us); 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) ebonus += Value(square_distance(pos.king_square(Them), blockSq) * 5 * rr)
- Value(square_distance(pos.king_square(Us ), blockSq) * 2 * 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) if (relative_rank(Us, blockSq) != RANK_8)
ebonus -= Value(square_distance(pos.king_square(Us), blockSq + pawn_push(Us)) * rr); 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)) if (pos.empty(blockSq))
{ {
squaresToQueen = forward_bb(Us, s); squaresToQueen = forward_bb(Us, s);
@ -835,12 +839,14 @@ Value do_evaluate(const Position& pos) {
else else
defendedSquares = squaresToQueen & ei.attackedBy[Us][ALL_PIECES]; defendedSquares = squaresToQueen & ei.attackedBy[Us][ALL_PIECES];
// If there aren't enemy attacks huge bonus, a bit smaller if at // If there aren't any enemy attacks, then assign a huge bonus.
// least block square is not attacked, otherwise smallest 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; int k = !unsafeSquares ? 15 : !(unsafeSquares & blockSq) ? 9 : 3;
// Big bonus if the path to queen is fully defended, a bit less // Assign a big bonus if the path to the queen is fully defended,
// if at least block square is defended. // otherwise assign a bit less of a bonus if at least the block
// square is defended.
if (defendedSquares == squaresToQueen) if (defendedSquares == squaresToQueen)
k += 6; k += 6;
@ -892,7 +898,7 @@ Value do_evaluate(const Position& pos) {
// evaluate_unstoppable_pawns() scores the most advanced among the passed and // evaluate_unstoppable_pawns() scores the most advanced among the passed and
// candidate pawns. In case opponent has no pieces but pawns, this is somewhat // 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) { Score evaluate_unstoppable_pawns(const Position& pos, Color us, const EvalInfo& ei) {

View file

@ -60,8 +60,8 @@ namespace {
{ 106, 101, 3, 151, 171, 0 } // Queen { 106, 101, 3, 151, 171, 0 } // Queen
}; };
// Endgame evaluation and scaling functions accessed direcly and not through // Endgame evaluation and scaling functions are accessed directly and not through
// the function maps because correspond to more then one material hash key. // the function maps because they correspond to more then one material hash key.
Endgame<KmmKm> EvaluateKmmKm[] = { Endgame<KmmKm>(WHITE), Endgame<KmmKm>(BLACK) }; Endgame<KmmKm> EvaluateKmmKm[] = { Endgame<KmmKm>(WHITE), Endgame<KmmKm>(BLACK) };
Endgame<KXK> EvaluateKXK[] = { Endgame<KXK>(WHITE), Endgame<KXK>(BLACK) }; Endgame<KXK> EvaluateKXK[] = { Endgame<KXK>(WHITE), Endgame<KXK>(BLACK) };
@ -93,7 +93,7 @@ namespace {
&& pos.count<PAWN>(Them) >= 1; && 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. /// piece type for both colors.
template<Color Us> 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->factor[WHITE] = e->factor[BLACK] = (uint8_t)SCALE_FACTOR_NORMAL;
e->gamePhase = game_phase(pos); e->gamePhase = game_phase(pos);
// Let's look if we have a specialized evaluation function for this // Let's look if we have a specialized evaluation function for this particular
// particular material configuration. First we look for a fixed // material configuration. Firstly we look for a fixed configuration one, then
// configuration one, then a generic one if previous search failed. // for a generic one if the previous search failed.
if (endgames.probe(key, e->evaluationFunction)) if (endgames.probe(key, e->evaluationFunction))
return e; 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 // 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. // Note that these ones don't return after setting the function.
if (is_KBPsKs<WHITE>(pos)) if (is_KBPsKs<WHITE>(pos))
e->scalingFunction[WHITE] = &ScaleKBPsK[WHITE]; 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 // 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. // in defining bishop pair bonuses.
const int pieceCount[COLOR_NB][PIECE_TYPE_NB] = { const int pieceCount[COLOR_NB][PIECE_TYPE_NB] = {
{ pos.count<BISHOP>(WHITE) > 1, pos.count<PAWN>(WHITE), pos.count<KNIGHT>(WHITE), { pos.count<BISHOP>(WHITE) > 1, pos.count<PAWN>(WHITE), pos.count<KNIGHT>(WHITE),

View file

@ -81,7 +81,7 @@ void dbg_print() {
/// Our fancy logging facility. The trick here is to replace cin.rdbuf() and /// 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 /// 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! /// usual i/o functionality and without changing a single line of code!
/// Idea from http://groups.google.com/group/comp.lang.c++/msg/1d941c0f26ea0d81 /// 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. /// the same time.
std::ostream& operator<<(std::ostream& os, SyncCout sc) { 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); } void start_logger(bool b) { Logger::start(b); }
/// timed_wait() waits for msec milliseconds. It is mainly an helper to wrap /// timed_wait() waits for msec milliseconds. It is mainly a helper to wrap
/// conversion from milliseconds to struct timespec, as used by pthreads. /// the conversion from milliseconds to struct timespec, as used by pthreads.
void timed_wait(WaitCondition& sleepCond, Lock& sleepLock, int msec) { 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 /// prefetch() preloads the given address in L1/L2 cache. This is a non-blocking
/// blocking function and do not stalls the CPU waiting for data to be /// function that doesn't stall the CPU waiting for data to be loaded from memory,
/// loaded from memory, that can be quite slow. /// which can be quite slow.
#ifdef NO_PREFETCH #ifdef NO_PREFETCH
void prefetch(char*) {} void prefetch(char*) {}
@ -189,8 +189,8 @@ void prefetch(char*) {}
void prefetch(char* addr) { void prefetch(char* addr) {
# if defined(__INTEL_COMPILER) # if defined(__INTEL_COMPILER)
// This hack prevents prefetches to be optimized away by // This hack prevents prefetches from being optimized away by
// Intel compiler. Both MSVC and gcc seems not affected. // Intel compiler. Both MSVC and gcc seem not be affected by this.
__asm__ (""); __asm__ ("");
# endif # endif

View file

@ -88,8 +88,8 @@ namespace {
(mlist++)->move = make<PROMOTION>(to - Delta, to, KNIGHT); (mlist++)->move = make<PROMOTION>(to - Delta, to, KNIGHT);
} }
// Knight-promotion is the only one that can give a direct check not // Knight promotion is the only promotion that can give a direct check
// already included in the queen-promotion. // that's not already included in the queen promotion.
if (Type == QUIET_CHECKS && (StepAttacksBB[W_KNIGHT][to] & ci->ksq)) if (Type == QUIET_CHECKS && (StepAttacksBB[W_KNIGHT][to] & ci->ksq))
(mlist++)->move = make<PROMOTION>(to - Delta, to, KNIGHT); (mlist++)->move = make<PROMOTION>(to - Delta, to, KNIGHT);
else else
@ -144,7 +144,7 @@ namespace {
// Add pawn pushes which give discovered check. This is possible only // 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 // 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 // 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) if (pawnsNotOn7 & ci->dcCandidates)
{ {
dc1 = shift_bb<Up>(pawnsNotOn7 & ci->dcCandidates) & emptySquares & ~file_bb(ci->ksq); 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()); assert(pos.checkers());
// Find squares attacked by slider checkers, we will remove them from the king // Find all the squares attacked by slider checkers. We will remove them from
// evasions so to skip known illegal moves avoiding useless legality check later. // the king evasions in order to skip known illegal moves, which avoids any
// useless legality checks later on.
do do
{ {
++checkersCnt; ++checkersCnt;

View file

@ -36,8 +36,8 @@ class Position;
template<GenType> template<GenType>
ExtMove* generate(const Position& pos, ExtMove* mlist); ExtMove* generate(const Position& pos, ExtMove* mlist);
/// The MoveList struct is a simple wrapper around generate(), sometimes comes /// The MoveList struct is a simple wrapper around generate(). It sometimes comes
/// handy to use this class instead of the low level generate() function. /// in handy to use this class instead of the low level generate() function.
template<GenType T> template<GenType T>
struct MoveList { struct MoveList {

View file

@ -35,7 +35,7 @@ namespace {
STOP 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) void insertion_sort(ExtMove* begin, ExtMove* end)
{ {
ExtMove tmp, *p, *q; ExtMove tmp, *p, *q;
@ -53,9 +53,9 @@ namespace {
// ones so to sort separately the two sets, and with the second sort delayed. // 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; } 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), // Picks the best move in the range (begin, end) and moves it to the front.
// it is faster than sorting all the moves in advance when moves are few, as // It's faster than sorting all the moves in advance when there are few
// normally are the possible captures. // moves e.g. possible captures.
inline ExtMove* pick_best(ExtMove* begin, ExtMove* end) inline ExtMove* pick_best(ExtMove* begin, ExtMove* end)
{ {
std::swap(*begin, *std::max_element(begin, 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; 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 // tree explosion due to a possible perpetual check or similar rare cases
// when TT table is full. // when TT table is full.
if (ttm && !pos.capture_or_promotion(ttm)) if (ttm && !pos.capture_or_promotion(ttm))
@ -129,7 +129,8 @@ MovePicker::MovePicker(const Position& p, Move ttm, const HistoryStats& h, Piece
stage = PROBCUT; 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]; captureThreshold = PieceValue[MG][pt];
ttMove = (ttm && pos.pseudo_legal(ttm) ? ttm : MOVE_NONE); 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 // where it is possible to recapture with the hanging piece). Exchanging
// big pieces before capturing a hanging piece probably helps to reduce // big pieces before capturing a hanging piece probably helps to reduce
// the subtree size. // the subtree size.
// In main search we want to push captures with negative SEE values to // In main search we want to push captures with negative SEE values to the
// badCaptures[] array, but instead of doing it now we delay till when // badCaptures[] array, but instead of doing it now we delay until the move
// the move has been picked up in pick_move_from_list(), this way we save // has been picked up in pick_move_from_list(). This way we save some SEE
// some SEE calls in case we get a cutoff (idea from Pablo Vazquez). // calls in case we get a cutoff.
Move m; Move m;
for (ExtMove* it = moves; it != end; ++it) for (ExtMove* it = moves; it != end; ++it)

View file

@ -35,7 +35,7 @@
/// and is used for reduction and move ordering decisions. Gains records the move's /// 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. /// 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 /// 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. /// different origin but same destination and piece will be considered identical.
template<bool Gain, typename T> template<bool Gain, typename T>
struct Stats { struct Stats {

View file

@ -126,8 +126,8 @@ const string move_to_san(Position& pos, Move m) {
{ {
san = PieceToChar[WHITE][pt]; // Upper case san = PieceToChar[WHITE][pt]; // Upper case
// Disambiguation if we have more then one piece of type 'pt' that can // A disambiguation occurs if we have more then one piece of type 'pt'
// reach 'to' with a legal move. // that can reach 'to' with a legal move.
others = b = (pos.attacks_from(pc, to) & pos.pieces(us, pt)) ^ from; others = b = (pos.attacks_from(pc, to) & pos.pieces(us, pt)) ^ from;
while (b) 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 /// pretty_pv() formats human-readable search information, typically to be
/// appended to the search log file. It uses the two helpers below to pretty /// 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) { static string time_to_string(int64_t msecs) {

View file

@ -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 /// Entry::update_safety() calculates and caches a bonus for king safety.
/// called only when king square changes, about 20% of total king_safety() calls. /// It is called only when king square changes, which is about 20% of total
/// king_safety() calls.
template<Color Us> template<Color Us>
Score Entry::update_safety(const Position& pos, Square ksq) { Score Entry::update_safety(const Position& pos, Square ksq) {

View file

@ -22,7 +22,7 @@
#ifdef _MSC_VER #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: 4127) // Conditional expression is constant
#pragma warning(disable: 4146) // Unary minus operator applied to unsigned type #pragma warning(disable: 4146) // Unary minus operator applied to unsigned type
#pragma warning(disable: 4800) // Forcing value to bool 'true' or 'false' #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 WIN32_LEAN_AND_MEAN
#undef NOMINMAX #undef NOMINMAX
// We use critical sections on Windows to support Windows XP and older versions, // We use critical sections on Windows to support Windows XP and older versions.
// unfortunatly cond_wait() is racy between lock_release() and WaitForSingleObject() // Unfortunately, cond_wait() is racy between lock_release() and WaitForSingleObject()
// but apart from this they have the same speed performance of SRW locks. // but apart from this they have the same speed performance of SRW locks.
typedef CRITICAL_SECTION Lock; typedef CRITICAL_SECTION Lock;
typedef HANDLE WaitCondition; typedef HANDLE WaitCondition;
typedef HANDLE NativeHandle; 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; } inline DWORD* dwWin9xKludge() { static DWORD dw; return &dw; }
# define lock_init(x) InitializeCriticalSection(&(x)) # define lock_init(x) InitializeCriticalSection(&(x))

View file

@ -82,7 +82,7 @@ PieceType min_attacker(const Bitboard* bb, const Square& to, const Bitboard& stm
template<> FORCE_INLINE template<> FORCE_INLINE
PieceType min_attacker<KING>(const Bitboard*, const Square&, const Bitboard&, Bitboard&, Bitboard&) { 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 } // namespace
@ -109,9 +109,9 @@ CheckInfo::CheckInfo(const Position& pos) {
/// Position::init() initializes at startup the various arrays used to compute /// 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: /// 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, /// Firstly, the white halves of the tables are copied from PSQT[] tables.
/// the black halves of the tables are initialized by flipping and changing the /// Secondly, the black halves of the tables are initialized by flipping and
/// sign of the white scores. /// changing the sign of the white scores.
void Position::init() { void Position::init() {
@ -155,7 +155,7 @@ void Position::init() {
/// Position::operator=() creates a copy of 'pos'. We want the new born Position /// 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. /// the source one.
Position& Position::operator=(const Position& pos) { 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: 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 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 square are described from file A through file H. Following the Standard
Algebraic Notation (SAN), each piece is identified by a single letter taken Algebraic Notation (SAN), each piece is identified by a single letter taken
from the standard English names. White pieces are designated using upper-case 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 "/" noted using digits 1 through 8 (the number of blank squares), and "/"
separates ranks. 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 /// Position::fen() returns a FEN representation of the position. In case of
/// of Chess960 the Shredder-FEN notation is used. Mainly a debugging function. /// Chess960 the Shredder-FEN notation is used. This is mainly a debugging function.
const string Position::fen() const { 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 /// 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. /// discovery check pieces attack the enemy king.
Bitboard Position::hidden_checkers(Square ksq, Color c, Color toMove) const { Bitboard Position::hidden_checkers(Square ksq, Color c, Color toMove) const {
Bitboard b, pinners, result = 0; 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]) pinners = ( (pieces( ROOK, QUEEN) & PseudoAttacks[ROOK ][ksq])
| (pieces(BISHOP, QUEEN) & PseudoAttacks[BISHOP][ksq])) & pieces(c); | (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 /// 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 { Bitboard Position::attackers_to(Square s, Bitboard occ) const {
@ -593,8 +593,8 @@ bool Position::pseudo_legal(const Move m) const {
return false; return false;
// Evasions generator already takes care to avoid some kind of illegal moves // 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 // and pl_move_is_legal() relies on this. We therefore have to take care that
// same kind of moves are filtered out here. // the same kind of moves are filtered out here.
if (checkers()) if (checkers())
{ {
if (type_of(pc) != KING) if (type_of(pc) != KING)
@ -629,11 +629,11 @@ bool Position::gives_check(Move m, const CheckInfo& ci) const {
Square to = to_sq(m); Square to = to_sq(m);
PieceType pt = type_of(piece_on(from)); PieceType pt = type_of(piece_on(from));
// Direct check ? // Is there a direct check ?
if (ci.checkSq[pt] & to) if (ci.checkSq[pt] & to)
return true; return true;
// Discovered check ? // Is there a discovered check ?
if ( unlikely(ci.dcCandidates) if ( unlikely(ci.dcCandidates)
&& (ci.dcCandidates & from) && (ci.dcCandidates & from)
&& !aligned(from, to, king_square(~sideToMove))) && !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; return attacks_bb(Piece(promotion_type(m)), to, pieces() ^ from) & ksq;
// En passant capture with check ? We have already handled the case // 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 // need to handle is the unusual case of a discovered check through
// the captured pawn. // the captured pawn.
case ENPASSANT: 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 // 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 // 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)); std::memcpy(&newSt, st, StateCopySize64 * sizeof(uint64_t));
newSt.previous = st; newSt.previous = st;
@ -709,7 +709,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
// Update side to move // Update side to move
k ^= Zobrist::side; 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. // in case of a capture or a pawn move.
++gamePly; ++gamePly;
++st->rule50; ++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 the moving piece is a pawn do some special extra work
if (pt == PAWN) 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 if ( (int(to) ^ int(from)) == 16
&& (attacks_from<PAWN>(from + pawn_push(us), us) & pieces(them, PAWN))) && (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 // Update the key with the final value
st->key = k; st->key = k;
// Update checkers bitboard, piece must be already moved // Update checkers bitboard: piece must be already moved
st->checkersBB = 0; st->checkersBB = 0;
if (moveIsCheck) if (moveIsCheck)
@ -1133,7 +1133,7 @@ void Position::clear() {
/// Position::compute_key() computes the hash key of the position. The hash /// 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 /// 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. /// 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 /// Position::compute_pawn_key() computes the hash key of the position. The
/// hash key is usually updated incrementally as moves are made and unmade, /// 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 /// 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 /// up, and to verify the correctness of the pawn hash key when running in
/// debug mode. /// debug mode.
@ -1178,8 +1178,8 @@ Key Position::compute_pawn_key() const {
/// Position::compute_material_key() computes the hash key of the position. /// 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 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 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 /// up, and to verify the correctness of the material hash key when running in
/// debug mode. /// debug mode.
@ -1218,7 +1218,7 @@ Score Position::compute_psq_score() const {
/// Position::compute_non_pawn_material() computes the total non-pawn middle /// Position::compute_non_pawn_material() computes the total non-pawn middle
/// game material value for the given side. Material values are updated /// 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. /// initializing a new Position object.
Value Position::compute_non_pawn_material(Color c) const { 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, /// 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. /// must be done by the search.
bool Position::is_draw() const { 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 /// 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) { static char toggle_case(char c) {
return char(islower(c) ? toupper(c) : tolower(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. /// This is meant to be helpful when debugging.
bool Position::pos_is_ok(int* failedStep) const { bool Position::pos_is_ok(int* failedStep) const {

View file

@ -27,7 +27,7 @@
/// PSQT[PieceType][Square] contains Piece-Square scores. For each piece type on /// 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 /// 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] = { static const Score PSQT[][SQUARE_NB] = {
{ }, { },

View file

@ -263,11 +263,11 @@ finalize:
sync_cout << "info nodes " << RootPos.nodes_searched() sync_cout << "info nodes " << RootPos.nodes_searched()
<< " time " << Time::now() - SearchTime + 1 << sync_endl; << " time " << Time::now() - SearchTime + 1 << sync_endl;
// When we reach max depth we arrive here even without Signals.stop being raised, // When we reach the maximum depth, we can arrive here without a raise of
// but if we are pondering or in infinite search, according to UCI protocol, // Signals.stop. However, if we are pondering or in an infinite search,
// we shouldn't print the best move before the GUI sends a "stop" or "ponderhit" // the UCI protocol states that we shouldn't print the best move before the
// command. We simply wait here until GUI sends one of those commands (that // GUI sends a "stop" or "ponderhit" command. We therefore simply wait here
// raise Signals.stop). // until the GUI sends one of those commands (which also raises Signals.stop).
if (!Signals.stop && (Limits.ponder || Limits.infinite)) if (!Signals.stop && (Limits.ponder || Limits.infinite))
{ {
Signals.stopOnPonderhit = true; Signals.stopOnPonderhit = true;
@ -322,8 +322,8 @@ namespace {
// Age out PV variability metric // Age out PV variability metric
BestMoveChanges *= 0.8; BestMoveChanges *= 0.8;
// Save last iteration's scores before first PV line is searched and all // Save the last iteration's scores before first PV line is searched and
// the move scores except the (new) PV are set to -VALUE_INFINITE. // all the move scores except the (new) PV are set to -VALUE_INFINITE.
for (size_t i = 0; i < RootMoves.size(); ++i) for (size_t i = 0; i < RootMoves.size(); ++i)
RootMoves[i].prevScore = RootMoves[i].score; RootMoves[i].prevScore = RootMoves[i].score;
@ -338,16 +338,17 @@ namespace {
beta = std::min(RootMoves[PVIdx].prevScore + delta, VALUE_INFINITE); beta = std::min(RootMoves[PVIdx].prevScore + delta, VALUE_INFINITE);
} }
// Start with a small aspiration window and, in case of fail high/low, // Start with a small aspiration window and, in the case of a fail
// research with bigger window until not failing high/low anymore. // high/low, re-search with a bigger window until we're not failing
// high/low anymore.
while (true) while (true)
{ {
bestValue = search<Root>(pos, ss, alpha, beta, depth * ONE_PLY, false); bestValue = search<Root>(pos, ss, alpha, beta, depth * ONE_PLY, false);
// Bring to front the best move. It is critical that sorting is // Bring the best move to the front. It is critical that sorting
// done with a stable algorithm because all the values but the first // is done with a stable algorithm because all the values but the
// and eventually the new best one are set to -VALUE_INFINITE and // first and eventually the new best one are set to -VALUE_INFINITE
// we want to keep the same order for all the moves but the new // 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 // PV that goes to the front. Note that in case of MultiPV search
// the already searched PV lines are preserved. // the already searched PV lines are preserved.
std::stable_sort(RootMoves.begin() + PVIdx, RootMoves.end()); std::stable_sort(RootMoves.begin() + PVIdx, RootMoves.end());
@ -359,18 +360,18 @@ namespace {
// If search has been stopped break immediately. Sorting and // If search has been stopped break immediately. Sorting and
// writing PV back to TT is safe becuase RootMoves is still // 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) if (Signals.stop)
break; break;
// When failing high/low give some update (without cluttering // 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) if ( (bestValue <= alpha || bestValue >= beta)
&& Time::now() - SearchTime > 3000) && Time::now() - SearchTime > 3000)
sync_cout << uci_pv(pos, depth, alpha, beta) << sync_endl; sync_cout << uci_pv(pos, depth, alpha, beta) << sync_endl;
// In case of failing low/high increase aspiration window and // In case of failing low/high increase aspiration window and
// research, otherwise exit the loop. // re-search, otherwise exit the loop.
if (bestValue <= alpha) if (bestValue <= alpha)
{ {
alpha = std::max(bestValue - delta, -VALUE_INFINITE); alpha = std::max(bestValue - delta, -VALUE_INFINITE);
@ -396,7 +397,7 @@ namespace {
sync_cout << uci_pv(pos, depth, alpha, beta) << sync_endl; 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)) if (skill.enabled() && skill.time_to_pick(depth))
skill.pick_move(); skill.pick_move();
@ -426,13 +427,13 @@ namespace {
if (depth > 4 && depth < 50 && PVSize == 1) if (depth > 4 && depth < 50 && PVSize == 1)
TimeMgr.pv_instability(BestMoveChanges); 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 // probably don't have enough time to search the first move at the
// next iteration anyway. // next iteration anyway.
if (Time::now() - SearchTime > (TimeMgr.available_time() * 62) / 100) if (Time::now() - SearchTime > (TimeMgr.available_time() * 62) / 100)
stop = true; 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 if ( depth >= 12
&& BestMoveChanges <= DBL_EPSILON && BestMoveChanges <= DBL_EPSILON
&& !stop && !stop
@ -455,7 +456,7 @@ namespace {
if (stop) if (stop)
{ {
// If we are allowed to ponder do not stop the search now but // 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) if (Limits.ponder)
Signals.stopOnPonderhit = true; Signals.stopOnPonderhit = true;
else else
@ -469,9 +470,9 @@ namespace {
// search<>() is the main search function for both PV and non-PV nodes and for // 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 // 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 // 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 // search, and searched the first move before splitting, so we don't have to
// all this work again. We also don't need to store anything to the hash table // repeat all this work again. We also don't need to store anything to the hash
// here: This is taken care of after we return from the split point. // table here: This is taken care of after we return from the split point.
template <NodeType NT> template <NodeType NT>
Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, bool cutNode) { 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 // 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 // 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 // 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 // because we will never beat the current alpha. Same logic but with reversed
// applies also in the opposite condition of being mated instead of giving mate, // signs applies also in the opposite condition of being mated instead of giving
// in this case return a fail-high score. // mate. In this case return a fail-high score.
alpha = std::max(mated_in(ss->ply), alpha); alpha = std::max(mated_in(ss->ply), alpha);
beta = std::min(mate_in(ss->ply+1), beta); beta = std::min(mate_in(ss->ply+1), beta);
if (alpha >= beta) if (alpha >= beta)
@ -553,8 +554,8 @@ namespace {
ttMove = RootNode ? RootMoves[PVIdx].pv[0] : tte ? tte->move() : MOVE_NONE; ttMove = RootNode ? RootMoves[PVIdx].pv[0] : tte ? tte->move() : MOVE_NONE;
ttValue = tte ? value_from_tt(tte->value(), ss->ply) : VALUE_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 // At PV nodes we check for exact scores, whilst at non-PV nodes we check for
// a fail high/low. Biggest advantage at probing at PV nodes is to have a // 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 // smooth experience in analysis mode. We don't probe at Root nodes otherwise
// we should also update RootMoveList to avoid bogus output. // we should also update RootMoveList to avoid bogus output.
if ( !RootNode if ( !RootNode
@ -782,7 +783,7 @@ moves_loop: // When in check and at SpNode search starts from here
if (SpNode) 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)) if (!pos.legal(move, ci.pinned))
continue; 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 // 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 // (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 // 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 // on all the other moves but the ttMove and if the result is lower than
// a margin then we extend ttMove. // ttValue minus a margin then we extend the ttMove.
if ( singularExtensionNode if ( singularExtensionNode
&& move == ttMove && move == ttMove
&& !ext && !ext
@ -837,7 +838,7 @@ moves_loop: // When in check and at SpNode search starts from here
ext = ONE_PLY; 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; newDepth = depth - ONE_PLY + ext;
// Step 13. Pruning at shallow depth (exclude PV nodes) // 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)) if (!RootNode && !SpNode && !pos.legal(move, ci.pinned))
{ {
moveCount--; 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); : - 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 // 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 // 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. // parent node fail low with value <= alpha and to try another move.
if (PvNode && (pvMove || (value > alpha && (RootNode || value < beta)))) if (PvNode && (pvMove || (value > alpha && (RootNode || value < beta))))
value = newDepth < ONE_PLY ? value = newDepth < ONE_PLY ?
@ -995,9 +996,9 @@ moves_loop: // When in check and at SpNode search starts from here
++BestMoveChanges; ++BestMoveChanges;
} }
else else
// All other moves but the PV are set to the lowest value, this // All other moves but the PV are set to the lowest value: this is
// is not a problem when sorting becuase sort is stable and move // not a problem when sorting because the sort is stable and the
// position in the list is preserved, just the PV is pushed up. // move position in the list is preserved - just the PV is pushed up.
rm.score = -VALUE_INFINITE; 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 // case of Signals.stop or thread.cutoff_occurred() are set, but this is
// harmless because return value is discarded anyhow in the parent nodes. // 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. // 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) if (!moveCount)
return excludedMove ? alpha return excludedMove ? alpha
: inCheck ? mated_in(ss->ply) : DrawValue[pos.side_to_move()]; : 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->currentMove = bestMove = MOVE_NONE;
ss->ply = (ss-1)->ply + 1; 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) if (pos.is_draw() || ss->ply > MAX_PLY)
return DrawValue[pos.side_to_move()]; 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 // 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. // only two types of depth in TT: DEPTH_QS_CHECKS or DEPTH_QS_NO_CHECKS.
ttDepth = InCheck || depth >= DEPTH_QS_CHECKS ? DEPTH_QS_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 evasionPrunable = InCheck
&& bestValue > VALUE_MATED_IN_MAX_PLY && bestValue > VALUE_MATED_IN_MAX_PLY
&& !pos.capture(move) && !pos.capture(move)
@ -1244,7 +1245,7 @@ moves_loop: // When in check and at SpNode search starts from here
&& pos.see_sign(move) < 0) && pos.see_sign(move) < 0)
continue; continue;
// Check for legality only before to do the move // Check for legality just before making the move
if (!pos.legal(move, ci.pinned)) if (!pos.legal(move, ci.pinned))
continue; 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 // 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. // "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) { 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 // 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". // from current position) to "plies to mate/be mated from the root".
Value value_from_tt(Value v, int ply) { 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 // 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 // 'second' move possible e.g. if the moving piece is the same in both moves.
// both moves. Normally the second move is the threat (the best move returned // Normally the second move is the threat (the best move returned from a null
// from a null search that fails low). // search that fails low).
bool allows(const Position& pos, Move first, Move second) { 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 m1to = to_sq(first);
Square m2to = to_sq(second); 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 // We exclude the trivial case where a sliding piece does in two moves what
// it could do in one move: eg. Ra1a2, Ra2a3. // it could do in one move: eg. Ra1a2, Ra2a3.
if ( m2to == m1from if ( m2to == m1from
@ -1383,8 +1384,8 @@ moves_loop: // When in check and at SpNode search starts from here
if (m1from == m2to) if (m1from == m2to)
return true; return true;
// If the threatened piece has value less than or equal to the value of the // If the threatened piece has a value less than or equal to the value of
// threat piece, don't prune moves which defend it. // the threat piece, don't prune moves which defend it.
if ( pos.capture(second) if ( pos.capture(second)
&& ( PieceValue[MG][pos.piece_on(m2from)] >= PieceValue[MG][pos.piece_on(m2to)] && ( PieceValue[MG][pos.piece_on(m2from)] >= PieceValue[MG][pos.piece_on(m2to)]
|| type_of(pos.piece_on(m2from)) == KING)) || 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; Bitboard occ = pos.pieces() ^ m1from ^ m1to ^ m2from;
Piece pc = pos.piece_on(m1from); 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) if (attacks_bb(pc, m1to, occ) & m2to)
return true; 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)) 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)); | (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))) if (unlikely(xray) && (xray & ~pos.attacks_from<QUEEN>(m2to)))
return true; 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 // When playing with a strength handicap, choose best move among the MultiPV
// using a statistical rule dependent on 'level'. Idea by Heinz van Saanen. // set using a statistical rule dependent on 'level'. Idea by Heinz van Saanen.
Move Skill::pick_move() { Move Skill::pick_move() {
@ -1432,7 +1433,7 @@ moves_loop: // When in check and at SpNode search starts from here
best = MOVE_NONE; best = MOVE_NONE;
// Choose best move. For each move score we add two terms both dependent on // 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. // then we choose the move with the resulting highest score.
for (size_t i = 0; i < PVSize; ++i) 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 // uci_pv() formats PV information according to the UCI protocol. UCI
// to send all the PV lines also if are still to be searched and so refer to // requires that all (if any) unsearched PV lines are sent using a previous
// the previous search score. // search score.
string uci_pv(const Position& pos, int depth, Value alpha, Value beta) { 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. /// 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 /// We also consider both failing high nodes and BOUND_EXACT nodes here to
/// allow to always have a ponder move even when we fail high at root, and a /// ensure that we have a ponder move even when we fail high at root. This
/// long PV to print that is important for position analysis. /// results in a long PV to print that is important for position analysis.
void RootMove::extract_pv_from_tt(Position& pos) { void RootMove::extract_pv_from_tt(Position& pos) {
@ -1568,7 +1569,7 @@ void RootMove::insert_pv_in_tt(Position& pos) {
void Thread::idle_loop() { void Thread::idle_loop() {
// Pointer 'this_sp' is not null only if we are called from split(), and not // 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; SplitPoint* this_sp = splitPointsSize ? activeSplitPoint : NULL;
assert(!this_sp || (this_sp->masterThread == this && searching)); assert(!this_sp || (this_sp->masterThread == this && searching));
@ -1595,7 +1596,7 @@ void Thread::idle_loop() {
break; 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, // 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 // in the meanwhile, allocated us and sent the notify_one() call before
// we had the chance to grab the lock. // we had the chance to grab the lock.
@ -1651,8 +1652,8 @@ void Thread::idle_loop() {
sp->slavesMask &= ~(1ULL << idx); sp->slavesMask &= ~(1ULL << idx);
sp->nodes += pos.nodes_searched(); sp->nodes += pos.nodes_searched();
// Wake up master thread so to allow it to return from the idle loop // Wake up the master thread so to allow it to return from the idle
// in case we are the last slave of the split point. // loop in case we are the last slave of the split point.
if ( Threads.sleepWhileIdle if ( Threads.sleepWhileIdle
&& this != sp->masterThread && this != sp->masterThread
&& !sp->slavesMask) && !sp->slavesMask)
@ -1661,10 +1662,10 @@ void Thread::idle_loop() {
sp->masterThread->notify_one(); sp->masterThread->notify_one();
} }
// After releasing the lock we cannot access anymore any SplitPoint // After releasing the lock we can't access any SplitPoint related data
// related data in a safe way becuase it could have been released under // in a safe way because it could have been released under our feet by
// our feet by the sp master. Also accessing other Thread objects is // the sp master. Also accessing other Thread objects is unsafe because
// unsafe because if we are exiting there is a chance are already freed. // if we are exiting there is a chance that they are already freed.
sp->mutex.unlock(); 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 /// 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 /// used to print debug info and, more importantly, to detect when we are out of
/// available time and so stop the search. /// available time and thus stop the search.
void check_time() { void check_time() {

View file

@ -85,7 +85,7 @@ struct LimitsType {
/// The SignalsType struct stores volatile flags updated during the search /// 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 { struct SignalsType {
bool stopOnPonderhit, firstRootMove, stop, failedLowAtRoot; bool stopOnPonderhit, firstRootMove, stop, failedLowAtRoot;

View file

@ -38,7 +38,7 @@ namespace {
// Helpers to launch a thread after creation and joining before delete. Must be // 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. // when start_routine (and hence virtual idle_loop) is called and when joining.
template<typename T> T* new_thread() { 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 // Thread c'tor just inits data and does not launch any execution thread.
// instead will be started only upon c'tor returns. // Such a thread will only be started when c'tor returns.
Thread::Thread() /* : splitPoints() */ { // Value-initialization bug in MSVC 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 // 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() { void MainThread::idle_loop() {
@ -124,7 +124,7 @@ void MainThread::idle_loop() {
while (!thinking && !exit) 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); sleepCondition.wait(mutex);
} }
@ -170,7 +170,7 @@ bool Thread::available_to(const Thread* master) const {
return false; return false;
// Make a local copy to be sure doesn't become zero under our feet while // 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; int size = splitPointsSize;
// No split points means that the thread is available as a slave for any // 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 // read_uci_options() updates internal threads parameters from the corresponding
// UCI options and creates/destroys threads to match the requested number. Thread // UCI options and creates/destroys threads to match the requested number. Thread
// objects are dynamically allocated to avoid creating in advance all possible // objects are dynamically allocated to avoid creating all possible threads
// threads, with included pawns and material tables, if only few are used. // in advance (which include pawns and material tables), even if only a few
// are to be used.
void ThreadPool::read_uci_options() { 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() 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 // In the helpful master concept, a master can help only a sub-tree of its
// point, and because here is all finished is not possible master is booked. // split point and because everything is finished here, it's not possible
// for the master to be booked.
assert(!searching); assert(!searching);
assert(!activePosition); assert(!activePosition);

View file

@ -151,7 +151,7 @@ struct TimerThread : public ThreadBase {
/// ThreadPool struct handles all the threads related stuff like init, starting, /// 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. /// All the access to shared thread data is done through this class.
struct ThreadPool : public std::vector<Thread*> { struct ThreadPool : public std::vector<Thread*> {

View file

@ -112,11 +112,11 @@ void TimeManager::init(const Search::LimitsType& limits, int currentPly, Color u
unstablePVExtraTime = 0; unstablePVExtraTime = 0;
optimumSearchTime = maximumSearchTime = limits.time[us]; 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. // 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) 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] hypMyTime = limits.time[us]
+ limits.inc[us] * (hypMTG - 1) + limits.inc[us] * (hypMTG - 1)
- emergencyBaseTime - emergencyBaseTime

View file

@ -83,11 +83,11 @@ const TTEntry* TranspositionTable::probe(const Key key) const {
/// TranspositionTable::store() writes a new entry containing position key and /// TranspositionTable::store() writes a new entry containing position key and
/// valuable information of current position. The lowest order bits of position /// valuable information of current position. The lowest order bits of position
/// key are used to decide on which cluster the position will be placed. /// 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 cluster, /// When a new entry is written and there are no empty entries available in the
/// it replaces the least valuable of entries. A TTEntry t1 is considered to be /// cluster, it replaces the least valuable of the entries. A TTEntry t1 is considered
/// more valuable than a TTEntry t2 if t1 is from the current search and t2 is from /// to be more valuable than a TTEntry t2 if t1 is from the current search and t2
/// a previous search, or if the depth of t1 is bigger than the depth of 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) { void TranspositionTable::store(const Key key, Value v, Bound b, Depth d, Move m, Value statV) {

View file

@ -66,9 +66,9 @@ private:
/// A TranspositionTable consists of a power of 2 number of clusters and each /// A TranspositionTable consists of a power of 2 number of clusters and each
/// cluster consists of ClusterSize number of TTEntry. Each non-empty entry /// cluster consists of ClusterSize number of TTEntry. Each non-empty entry
/// contains information of exactly one position. Size of a cluster shall not be /// contains information of exactly one position. The size of a cluster should
/// bigger than a cache line size. In case it is less, it should be padded to /// not be bigger than a cache line size. In case it is less, it should be padded
/// guarantee always aligned accesses. /// to guarantee always aligned accesses.
class TranspositionTable { class TranspositionTable {
@ -106,7 +106,7 @@ inline TTEntry* TranspositionTable::first_entry(const Key key) const {
/// TranspositionTable::refresh() updates the 'generation' value of the TTEntry /// 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 { inline void TranspositionTable::refresh(const TTEntry* tte) const {

View file

@ -26,7 +26,7 @@
/// For Windows, part of the configuration is detected automatically, but some /// For Windows, part of the configuration is detected automatically, but some
/// switches need to be set manually: /// 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 /// -DNO_PREFETCH | Disable use of prefetch asm-instruction. A must if you want
/// | the executable to run on some very old machines. /// | 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), /// The Score enum stores a midgame and an endgame value in a single integer
/// first LSB 16 bits are used to store endgame value, while upper bits are used /// (enum). The least significant 16 bits are used to store the endgame value
/// for midgame value. Compiler is free to choose the enum type as long as can /// and the upper 16 bits are used to store the midgame value. The compiler is
/// keep its data, so ensure Score to be an integer type. /// 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 { enum Score {
SCORE_ZERO, SCORE_ZERO,
SCORE_ENSURE_INTEGER_SIZE_P = INT_MAX, SCORE_ENSURE_INTEGER_SIZE_P = INT_MAX,

View file

@ -39,8 +39,9 @@ namespace {
// FEN string of the initial position, normal chess // FEN string of the initial position, normal chess
const char* StartFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"; 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 // Keep a track of the position keys along the setup moves (from the start position
// position just before to start searching). Needed by repetition draw detection. // to the position just before the search starts). This is needed by the repetition
// draw detection code.
Search::StateStackPtr SetupStates; Search::StateStackPtr SetupStates;
void setoption(istringstream& up); void setoption(istringstream& up);
@ -69,11 +70,11 @@ void UCI::loop(const string& args) {
if (token == "quit" || token == "stop" || token == "ponderhit") 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 // opponent has played. In case Signals.stopOnPonderhit is set we are
// waiting for 'ponderhit' to stop the search (for instance because we // waiting for 'ponderhit' to stop the search (for instance because we
// already ran out of time), otherwise we should continue searching but // 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) if (token != "ponderhit" || Search::Signals.stopOnPonderhit)
{ {
Search::Signals.stop = true; Search::Signals.stop = true;
@ -121,7 +122,7 @@ void UCI::loop(const string& args) {
} while (token != "quit" && args.empty()); // Args have one-shot behaviour } 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
} }

View file

@ -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) { void init(OptionsMap& o) {