if (relative_rank(strongSide, pawnSq) <= RANK_5)
return SCALE_FACTOR_DRAW;
-
+
Bitboard path = forward_bb(strongSide, pawnSq);
if (path & pos.pieces(weakSide, KING))
// MobilityBonus[PieceType-2][attacked] contains bonuses for middle and end game,
// indexed by piece type and number of attacked squares in the mobility area.
- const Score MobilityBonus[4][32] = {
+ const Score MobilityBonus[][32] = {
{ S(-75,-76), S(-57,-54), S( -9,-28), S( -2,-10), S( 6, 5), S( 14, 12), // Knights
S( 22, 26), S( 29, 29), S( 36, 29) },
{ S(-48,-59), S(-20,-23), S( 16, -3), S( 26, 13), S( 38, 24), S( 51, 42), // Bishops
// RookOnFile[semiopen/open] contains bonuses for each rook when there is no
// friendly pawn on the rook file.
- const Score RookOnFile[2] = { S(20, 7), S(45, 20) };
+ const Score RookOnFile[] = { S(20, 7), S(45, 20) };
// ThreatByMinor/ByRook[attacked PieceType] contains bonuses according to
// which piece type attacks which one. Attacks on lesser pieces which are
// ThreatByKing[on one/on many] contains bonuses for king attacks on
// pawns or pieces which are not pawn-defended.
- const Score ThreatByKing[2] = { S(3, 62), S(9, 138) };
+ const Score ThreatByKing[] = { S(3, 62), S(9, 138) };
// Passed[mg/eg][Rank] contains midgame and endgame bonuses for passed pawns.
// We don't use a Score because we process the two components independently.
// Protector[PieceType-2][distance] contains a protecting bonus for our king,
// indexed by piece type and distance between the piece and the king.
- const Score Protector[4][8] = {
+ const Score Protector[][8] = {
{ S(0, 0), S( 7, 9), S( 7, 1), S( 1, 5), S(-10,-4), S( -1,-4), S( -7,-3), S(-16,-10) }, // Knight
{ S(0, 0), S(11, 8), S(-7,-1), S(-1,-2), S( -1,-7), S(-11,-3), S( -9,-1), S(-16, -1) }, // Bishop
{ S(0, 0), S(10, 0), S(-2, 2), S(-5, 4), S( -6, 2), S(-14,-3), S( -2,-9), S(-12, -7) }, // Rook
- { S(0, 0), S( 3,-5), S( 2,-5), S(-4, 0), S( -9,-6), S(-4, 7), S(-13,-7), S(-10, -7) } // Queen
+ { S(0, 0), S( 3,-5), S( 2,-5), S(-4, 0), S( -9,-6), S( -4, 7), S(-13,-7), S(-10, -7) } // Queen
};
// Assorted bonuses and penalties used by evaluation
const int KingAttackWeights[PIECE_TYPE_NB] = { 0, 0, 78, 56, 45, 11 };
// Penalties for enemy's safe checks
- const int QueenCheck = 810;
- const int RookCheck = 888;
- const int BishopCheck = 400;
- const int KnightCheck = 790;
+ const int QueenCheck = 810;
+ const int RookCheck = 888;
+ const int BishopCheck = 400;
+ const int KnightCheck = 790;
- // Threshold for lazy evaluation
- const Value LazyThreshold = Value(1500);
+ // Threshold for lazy and space evaluation
+ const Value LazyThreshold = Value(1500);
+ const Value SpaceThreshold = Value(12222);
// eval_init() initializes king and attack bitboards for a given color
// adding pawn attacks. To be done at the beginning of the evaluation.
template<bool DoTrace, Color Us = WHITE, PieceType Pt = KNIGHT>
Score evaluate_pieces(const Position& pos, EvalInfo& ei, Score* mobility) {
- const PieceType NextPt = (Us == WHITE ? Pt : PieceType(Pt + 1));
const Color Them = (Us == WHITE ? BLACK : WHITE);
+ const PieceType NextPt = (Us == WHITE ? Pt : PieceType(Pt + 1));
const Bitboard OutpostRanks = (Us == WHITE ? Rank4BB | Rank5BB | Rank6BB
: Rank5BB | Rank4BB | Rank3BB);
const Square* pl = pos.squares<Pt>(Us);
safeThreats = (shift<Right>(b) | shift<Left>(b)) & weak;
+ score += ThreatBySafePawn * popcount(safeThreats);
+
if (weak ^ safeThreats)
score += ThreatByHangingPawn;
-
- score += ThreatBySafePawn * popcount(safeThreats);
}
// Squares strongly protected by the opponent, either because they attack the
- evaluate_passer_pawns<BLACK, DoTrace>(pos, ei);
// Evaluate space for both sides, only during opening
- if (pos.non_pawn_material() >= 12222)
+ if (pos.non_pawn_material() >= SpaceThreshold)
score += evaluate_space<WHITE>(pos, ei)
- evaluate_space<BLACK>(pos, ei);
Trace::add(IMBALANCE, ei.me->imbalance());
Trace::add(PAWN, ei.pe->pawns_score());
Trace::add(MOBILITY, mobility[WHITE], mobility[BLACK]);
- if (pos.non_pawn_material() >= 12222)
+ if (pos.non_pawn_material() >= SpaceThreshold)
Trace::add(SPACE, evaluate_space<WHITE>(pos, ei)
, evaluate_space<BLACK>(pos, ei));
Trace::add(TOTAL, score);
{ 101, 100, -37, 141, 268, 0 } // Queen
};
- // PawnsSet[count] contains a bonus/malus indexed by number of pawns
- const int PawnsSet[FILE_NB + 1] = {
- 24, -32, 107, -51, 117, -9, -126, -21, 31
+ // PawnSet[pawn count] contains a bonus/malus indexed by number of pawns
+ const int PawnSet[] = {
+ 24, -32, 107, -51, 117, -9, -126, -21, 31
};
// Endgame evaluation and scaling functions are accessed directly and not through
const Color Them = (Us == WHITE ? BLACK : WHITE);
- int bonus = PawnsSet[pieceCount[Us][PAWN]];
+ int bonus = PawnSet[pieceCount[Us][PAWN]];
// Second-degree polynomial material imbalance by Tord Romstad
for (int pt1 = NO_PIECE_TYPE; pt1 <= QUEEN; ++pt1)
void prefetch2(void* addr) {
- prefetch(addr);
- prefetch((uint8_t*)addr + 64);
+ prefetch(addr);
+ prefetch((uint8_t*)addr + 64);
}
namespace WinProcGroup {
QSEARCH_RECAPTURES, QRECAPTURES
};
- // An insertion sort, which sorts moves in descending order up to and including a given limit.
- // The order of moves smaller than the limit is left unspecified.
- // To keep the implementation simple, *begin is always included in the list of sorted moves.
- void partial_insertion_sort(ExtMove* begin, ExtMove* end, int limit)
- {
+ // partial_insertion_sort() sorts moves in descending order up to and including
+ // a given limit. The order of moves smaller than the limit is left unspecified.
+ // To keep the implementation simple, *begin is always included in the sorted moves.
+ void partial_insertion_sort(ExtMove* begin, ExtMove* end, int limit) {
+
for (ExtMove *sortedEnd = begin + 1, *p = begin + 1; p < end; ++p)
if (p->value >= limit)
{
// pick_best() finds the best move in the range (begin, end) and moves it to
// the front. It's faster than sorting all the moves in advance when there
// are few moves, e.g., the possible captures.
- Move pick_best(ExtMove* begin, ExtMove* end)
- {
- std::swap(*begin, *std::max_element(begin, end));
- return *begin;
+ Move pick_best(ExtMove* begin, ExtMove* end) {
+
+ std::swap(*begin, *std::max_element(begin, end));
+ return *begin;
}
} // namespace
ttMove = ttm
&& pos.pseudo_legal(ttm)
&& pos.capture(ttm)
- && pos.see_ge(ttm, threshold)? ttm : MOVE_NONE;
+ && pos.see_ge(ttm, threshold) ? ttm : MOVE_NONE;
stage += (ttMove == MOVE_NONE);
}
cur = endBadCaptures;
endMoves = generate<QUIETS>(pos, cur);
score<QUIETS>();
-
partial_insertion_sort(cur, endMoves, -4000 * depth / ONE_PLY);
++stage;
#ifndef MOVEPICK_H_INCLUDED
#define MOVEPICK_H_INCLUDED
-#include <algorithm> // For std::max
#include <cstring> // For std::memset
#include "movegen.h"
Square from = from_sq(m);
Square to = to_sq(m);
- const int denom = 324;
+ const int D = 324;
- assert(abs(int(v)) <= denom); // Needed for stability.
+ assert(abs(int(v)) <= D); // Consistency check for below formula
- table[c][from][to] -= table[c][from][to] * abs(int(v)) / denom;
+ table[c][from][to] -= table[c][from][to] * abs(int(v)) / D;
table[c][from][to] += int(v) * 32;
}
const T* operator[](Piece pc) const { return table[pc]; }
T* operator[](Piece pc) { return table[pc]; }
void clear() { std::memset(table, 0, sizeof(table)); }
- void fill(const int& v) { std::fill(&table[0][0], &table[PIECE_NB-1][SQUARE_NB-1]+1, v); };
void update(Piece pc, Square to, Move m) { table[pc][to] = m; }
void update(Piece pc, Square to, int v) {
- const int denom = 936;
+ const int D = 936;
- assert(abs(int(v)) <= denom); // Needed for stability.
+ assert(abs(int(v)) <= D); // Consistency check for below formula
- table[pc][to] -= table[pc][to] * abs(int(v)) / denom;
+ table[pc][to] -= table[pc][to] * abs(int(v)) / D;
table[pc][to] += int(v) * 32;
}
#define S(mg, eg) make_score(mg, eg)
// Isolated pawn penalty by opposed flag
- const Score Isolated[2] = { S(45, 40), S(30, 27) };
+ const Score Isolated[] = { S(45, 40), S(30, 27) };
// Backward pawn penalty by opposed flag
- const Score Backward[2] = { S(56, 33), S(41, 19) };
+ const Score Backward[] = { S(56, 33), S(41, 19) };
// Unsupported pawn penalty for pawns which are neither isolated or backward
const Score Unsupported = S(17, 8);
}
if (step == Lists)
- {
for (Piece pc : Pieces)
{
if (pieceCount[pc] != popcount(pieces(color_of(pc), type_of(pc))))
if (board[pieceList[pc][i]] != pc || index[pieceList[pc][i]] != i)
return false;
}
- if (pieceCount[PAWN] > FILE_NB)
- return false;
- }
if (step == Castling)
for (Color c = WHITE; c <= BLACK; ++c)
int FutilityMoveCounts[2][16]; // [improving][depth]
int Reductions[2][2][64][64]; // [pv][improving][depth][moveNumber]
- // Threshold used for countermoves based pruning.
+ // Threshold used for countermoves based pruning
const int CounterMovePruneThreshold = 0;
template <bool PvNode> Depth reduction(bool i, Depth d, int mn) {
th->counterMoves.clear();
th->history.clear();
th->counterMoveHistory.clear();
- th->counterMoveHistory[NO_PIECE][0].fill(CounterMovePruneThreshold-1);
th->resetCalls = true;
+ CounterMoveStats& cm = th->counterMoveHistory[NO_PIECE][0];
+ int* t = &cm[NO_PIECE][0];
+ std::fill(t, t + sizeof(cm), CounterMovePruneThreshold - 1);
}
Threads.main()->previousScore = VALUE_INFINITE;
if (thisThread->resetCalls.load(std::memory_order_relaxed))
{
thisThread->resetCalls = false;
+
// At low node count increase the checking rate to about 0.1% of nodes
// otherwise use a default value.
- thisThread->callsCnt = Limits.nodes ? std::min((int64_t)4096, Limits.nodes / 1024)
+ thisThread->callsCnt = Limits.nodes ? std::min(4096, int(Limits.nodes / 1024))
: 4096;
}
if (value < rBeta)
extension = ONE_PLY;
}
- else if ( givesCheck
+ else if ( givesCheck
&& !moveCountPruning
&& pos.see_ge(move, VALUE_ZERO))
extension = ONE_PLY;
{
if ( !captureOrPromotion
&& !givesCheck
- && (!pos.advanced_pawn_push(move) || pos.non_pawn_material() >= 5000))
+ && (!pos.advanced_pawn_push(move) || pos.non_pawn_material() >= Value(5000)))
{
// Move count based pruning
- if (moveCountPruning) {
+ if (moveCountPruning)
+ {
skipQuiets = true;
continue;
}
&& is_ok((ss-1)->currentMove))
update_cm_stats(ss-1, pos.piece_on(prevSq), prevSq, stat_bonus(depth));
- if(!excludedMove)
+ if (!excludedMove)
tte->save(posKey, value_to_tt(bestValue, ss->ply),
- bestValue >= beta ? BOUND_LOWER :
- PvNode && bestMove ? BOUND_EXACT : BOUND_UPPER,
- depth, bestMove, ss->staticEval, TT.generation());
+ bestValue >= beta ? BOUND_LOWER :
+ PvNode && bestMove ? BOUND_EXACT : BOUND_UPPER,
+ depth, bestMove, ss->staticEval, TT.generation());
assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE);
d->flags = *data++;
if (d->flags & TBFlag::SingleValue) {
- d->blocksNum = d->span =
- d->blockLengthSize = d->sparseIndexSize = 0; // Broken MSVC zero-init
+ d->blocksNum = d->blockLengthSize = 0;
+ d->span = d->sparseIndexSize = 0; // Broken MSVC zero-init
d->minSymLen = *data++; // Here we store the single value
return data;
}