// init_magics() computes all rook and bishop attacks at startup. Magic
// bitboards are used to look up attacks of sliding pieces. As a reference see
- // chessprogramming.wikispaces.com/Magic+Bitboards. In particular, here we
- // use the so called "fancy" approach.
+ // www.chessprogramming.org/Magic_Bitboards. In particular, here we use the so
+ // called "fancy" approach.
void init_magics(Bitboard table[], Magic magics[], Direction directions[]) {
Square loserKSq = pos.square<KING>(weakSide);
Square bishopSq = pos.square<BISHOP>(strongSide);
- // If our Bishop does not attack A1/H8, we flip the enemy king square
+ // If our Bishop does not attack A1/H8, we flip the enemy king square
// to drive to opposite corners (A8/H1).
Value result = VALUE_KNOWN_WIN
template<>
ScaleFactor Endgame<KNPKB>::operator()(const Position& pos) const {
+ assert(verify_material(pos, strongSide, KnightValueMg, 1));
+ assert(verify_material(pos, weakSide, BishopValueMg, 0));
+
Square pawnSq = pos.square<PAWN>(strongSide);
Square bishopSq = pos.square<BISHOP>(weakSide);
Square weakKingSq = pos.square<KING>(weakSide);
// kingRing[color] are the squares adjacent to the king, plus (only for a
// king on its first rank) the squares two ranks in front. For instance,
// if black's king is on g8, kingRing[BLACK] is f8, h8, f7, g7, h7, f6, g6
- // and h6. It is set to 0 when king safety evaluation is skipped.
+ // and h6.
Bitboard kingRing[COLOR_NB];
// kingAttackersCount[color] is the number of pieces of the given color
Score score = SCORE_ZERO;
// Non-pawn enemies
- nonPawnEnemies = pos.pieces(Them) & ~pos.pieces(Them, PAWN);
+ nonPawnEnemies = pos.pieces(Them) & ~pos.pieces(PAWN);
// Squares strongly protected by the enemy, either because they defend the
// square with a pawn, or because they defend the square twice and we don't.
behind |= (Us == WHITE ? behind >> 16 : behind << 16);
int bonus = popcount(safe) + popcount(behind & safe);
- int weight = pos.count<ALL_PIECES>(Us)
- - 2 * popcount(pe->semiopenFiles[WHITE] & pe->semiopenFiles[BLACK]);
+ int weight = pos.count<ALL_PIECES>(Us)
+ - 2 * popcount(pe->semiopenFiles[WHITE] & pe->semiopenFiles[BLACK]);
Score score = make_score(bonus * weight * weight / 16, 0);
template<Color Us, CastlingSide Cs, bool Checks, bool Chess960>
ExtMove* generate_castling(const Position& pos, ExtMove* moveList) {
+ constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
constexpr CastlingRight Cr = Us | Cs;
constexpr bool KingSide = (Cs == KING_SIDE);
Square kfrom = pos.square<KING>(Us);
Square rfrom = pos.castling_rook_square(Cr);
Square kto = relative_square(Us, KingSide ? SQ_G1 : SQ_C1);
- Bitboard enemies = pos.pieces(~Us);
+ Bitboard enemies = pos.pieces(Them);
assert(!pos.checkers());
// Because we generate only legal castling moves we need to verify that
// when moving the castling rook we do not discover some hidden checker.
// For instance an enemy queen in SQ_A1 when castling rook is in SQ_B1.
- if (Chess960 && (attacks_bb<ROOK>(kto, pos.pieces() ^ rfrom) & pos.pieces(~Us, ROOK, QUEEN)))
+ if (Chess960 && (attacks_bb<ROOK>(kto, pos.pieces() ^ rfrom) & pos.pieces(Them, ROOK, QUEEN)))
return moveList;
Move m = make<CASTLING>(kfrom, rfrom);
template<Color Us, GenType Type>
ExtMove* generate_pawn_moves(const Position& pos, ExtMove* moveList, Bitboard target) {
- // Compute our parametrized parameters at compile time, named according to
- // the point of view of white side.
+ // Compute some compile time parameters relative to the white side
constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
constexpr Bitboard TRank7BB = (Us == WHITE ? Rank7BB : Rank2BB);
constexpr Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB);
/// ButterflyHistory records how often quiet moves have been successful or
/// unsuccessful during the current search, and is used for reduction and move
/// ordering decisions. It uses 2 tables (one for each color) indexed by
-/// the move's from and to squares, see chessprogramming.wikispaces.com/Butterfly+Boards
+/// the move's from and to squares, see www.chessprogramming.org/Butterfly_Boards
typedef Stats<int16_t, 10692, COLOR_NB, int(SQUARE_NB) * int(SQUARE_NB)> ButterflyHistory;
/// CounterMoveHistory stores counter moves indexed by [piece][to] of the previous
-/// move, see chessprogramming.wikispaces.com/Countermove+Heuristic
+/// move, see www.chessprogramming.org/Countermove_Heuristic
typedef Stats<Move, NOT_USED, PIECE_NB, SQUARE_NB> CounterMoveHistory;
/// CapturePieceToHistory is addressed by a move's [piece][to][captured piece type]
// not attacked more times than defended.
if ( !(stoppers ^ lever ^ leverPush)
&& popcount(support) >= popcount(lever) - 1
- && popcount(phalanx) >= popcount(leverPush))
+ && popcount(phalanx) >= popcount(leverPush))
e->passedPawns[Us] |= s;
else if ( stoppers == SquareBB[s + Up]
{
std::swap(cuckoo[i], key);
std::swap(cuckooMove[i], move);
- if (move == 0) // Arrived at empty slot ?
+ if (move == MOVE_NONE) // Arrived at empty slot?
break;
i = (i == H1(key)) ? H2(key) : H1(key); // Push victim to alternative slot
}
ss << (sideToMove == WHITE ? " w " : " b ");
if (can_castle(WHITE_OO))
- ss << (chess960 ? char('A' + file_of(castling_rook_square(WHITE | KING_SIDE))) : 'K');
+ ss << (chess960 ? char('A' + file_of(castling_rook_square(WHITE_OO ))) : 'K');
if (can_castle(WHITE_OOO))
- ss << (chess960 ? char('A' + file_of(castling_rook_square(WHITE | QUEEN_SIDE))) : 'Q');
+ ss << (chess960 ? char('A' + file_of(castling_rook_square(WHITE_OOO))) : 'Q');
if (can_castle(BLACK_OO))
- ss << (chess960 ? char('a' + file_of(castling_rook_square(BLACK | KING_SIDE))) : 'k');
+ ss << (chess960 ? char('a' + file_of(castling_rook_square(BLACK_OO ))) : 'k');
if (can_castle(BLACK_OOO))
- ss << (chess960 ? char('a' + file_of(castling_rook_square(BLACK | QUEEN_SIDE))) : 'q');
+ ss << (chess960 ? char('a' + file_of(castling_rook_square(BLACK_OOO))) : 'q');
if (!can_castle(ANY_CASTLING))
ss << '-';
}
};
-constexpr Score PBonus[RANK_NB][FILE_NB] =\r
- { // Pawn\r
- { S( 0, 0), S( 0, 0), S( 0, 0), S( 0, 0), S( 0, 0), S( 0, 0), S( 0, 0), S( 0, 0) },\r
- { S( 0,-11), S( -3, -4), S( 13, -1), S( 19, -4), S( 16, 17), S( 13, 7), S( 4, 4), S( -4,-13) },\r
- { S(-16, -8), S(-12, -6), S( 20, -3), S( 21, 0), S( 25,-11), S( 29, 3), S( 0, 0), S(-27, -1) },\r
- { S(-11, 3), S(-17, 6), S( 11,-10), S( 21, 1), S( 32, -6), S( 19,-11), S( -5, 0), S(-14, -2) },\r
- { S( 4, 13), S( 6, 7), S( -8, 3), S( 3, -5), S( 8,-15), S( -2, -1), S(-19, 9), S( -5, 13) },\r
- { S( -5, 25), S(-19, 20), S( 7, 16), S( 8, 12), S( -7, 21), S( -2, 3), S(-10, -4), S(-16, 15) },\r
- { S(-10, 6), S( 9, -5), S( -7, 16), S(-12, 27), S( -7, 15), S( -8, 11), S( 16, -7), S( -8, 4) }\r
+constexpr Score PBonus[RANK_NB][FILE_NB] =
+ { // Pawn (asymmetric distribution)
+ { },
+ { S( 0,-11), S( -3,-4), S(13, -1), S( 19, -4), S(16, 17), S(13, 7), S( 4, 4), S( -4,-13) },
+ { S(-16, -8), S(-12,-6), S(20, -3), S( 21, 0), S(25,-11), S(29, 3), S( 0, 0), S(-27, -1) },
+ { S(-11, 3), S(-17, 6), S(11,-10), S( 21, 1), S(32, -6), S(19,-11), S( -5, 0), S(-14, -2) },
+ { S( 4, 13), S( 6, 7), S(-8, 3), S( 3, -5), S( 8,-15), S(-2, -1), S(-19, 9), S( -5, 13) },
+ { S( -5, 25), S(-19,20), S( 7, 16), S( 8, 12), S(-7, 21), S(-2, 3), S(-10, -4), S(-16, 15) },
+ { S(-10, 6), S( 9,-5), S(-7, 16), S(-12, 27), S(-7, 15), S(-8, 11), S( 16, -7), S( -8, 4) }
};
#undef S
Value value_from_tt(Value v, int ply);
void update_pv(Move* pv, Move move, Move* childPv);
void update_continuation_histories(Stack* ss, Piece pc, Square to, int bonus);
- void update_quiet_stats(const Position& pos, Stack* ss, Move move, Move* quiets, int quietsCnt, int bonus);
- void update_capture_stats(const Position& pos, Move move, Move* captures, int captureCnt, int bonus);
+ void update_quiet_stats(const Position& pos, Stack* ss, Move move, Move* quiets, int quietCount, int bonus);
+ void update_capture_stats(const Position& pos, Move move, Move* captures, int captureCount, int bonus);
inline bool gives_check(const Position& pos, Move move) {
Color us = pos.side_to_move();
if ( Limits.use_time_management()
&& !Threads.stop
&& !Threads.stopOnPonderhit)
+ {
+ double fallingEval = (306 + 119 * failedLow + 6 * (mainThread->previousScore - bestValue)) / 581.0;
+ fallingEval = std::max(0.5, std::min(1.5, fallingEval));
+
+ // If the bestMove is stable over several iterations, reduce time accordingly
+ timeReduction = 1.0;
+ for (int i : {3, 4, 5})
+ if (lastBestMoveDepth * i < completedDepth)
+ timeReduction *= 1.25;
+
+ // Use part of the gained time from a previous stable move for the current move
+ double bestMoveInstability = 1.0 + mainThread->bestMoveChanges;
+ bestMoveInstability *= std::pow(mainThread->previousTimeReduction, 0.528) / timeReduction;
+
+ // Stop the search if we have only one legal move, or if available time elapsed
+ if ( rootMoves.size() == 1
+ || Time.elapsed() > Time.optimum() * bestMoveInstability * fallingEval)
{
- double fallingEval = (306 + 119 * failedLow + 6 * (mainThread->previousScore - bestValue)) / 581.0;
- fallingEval = std::max(0.5, std::min(1.5, fallingEval));
-
- // If the bestMove is stable over several iterations, reduce time accordingly
- timeReduction = 1.0;
- for (int i : {3, 4, 5})
- if (lastBestMoveDepth * i < completedDepth)
- timeReduction *= 1.25;
-
- // Use part of the gained time from a previous stable move for the current move
- double bestMoveInstability = 1.0 + mainThread->bestMoveChanges;
- bestMoveInstability *= std::pow(mainThread->previousTimeReduction, 0.528) / timeReduction;
-
- // Stop the search if we have only one legal move, or if available time elapsed
- if ( rootMoves.size() == 1
- || Time.elapsed() > Time.optimum() * bestMoveInstability * fallingEval)
- {
- // If we are allowed to ponder do not stop the search now but
- // keep pondering until the GUI sends "ponderhit" or "stop".
- if (Threads.ponder)
- Threads.stopOnPonderhit = true;
- else
- Threads.stop = true;
- }
+ // If we are allowed to ponder do not stop the search now but
+ // keep pondering until the GUI sends "ponderhit" or "stop".
+ if (Threads.ponder)
+ Threads.stopOnPonderhit = true;
+ else
+ Threads.stop = true;
}
+ }
}
if (!mainThread)
// update_capture_stats() updates move sorting heuristics when a new capture best move is found
void update_capture_stats(const Position& pos, Move move,
- Move* captures, int captureCnt, int bonus) {
+ Move* captures, int captureCount, int bonus) {
CapturePieceToHistory& captureHistory = pos.this_thread()->captureHistory;
Piece moved_piece = pos.moved_piece(move);
captureHistory[moved_piece][to_sq(move)][captured] << bonus;
// Decrease all the other played capture moves
- for (int i = 0; i < captureCnt; ++i)
+ for (int i = 0; i < captureCount; ++i)
{
moved_piece = pos.moved_piece(captures[i]);
captured = type_of(pos.piece_on(to_sq(captures[i])));
// update_quiet_stats() updates move sorting heuristics when a new quiet best move is found
void update_quiet_stats(const Position& pos, Stack* ss, Move move,
- Move* quiets, int quietsCnt, int bonus) {
+ Move* quiets, int quietCount, int bonus) {
if (ss->killers[0] != move)
{
}
// Decrease all the other played quiet moves
- for (int i = 0; i < quietsCnt; ++i)
+ for (int i = 0; i < quietCount; ++i)
{
thisThread->mainHistory[us][from_to(quiets[i])] << -bonus;
update_continuation_histories(ss, pos.moved_piece(quiets[i]), to_sq(quiets[i]), -bonus);
assert(pv.size() == 1);
- if (!pv[0])
+ if (pv[0] == MOVE_NONE)
return false;
pos.do_move(pv[0], st);
#!/bin/bash
-# verify perft numbers (positions from https://chessprogramming.wikispaces.com/Perft+Results)
+# verify perft numbers (positions from www.chessprogramming.org/Perft_Results)
error()
{