// History and stats update bonus, based on depth
int stat_bonus(Depth depth) {
int d = depth / ONE_PLY;
- return d > 17 ? 0 : 32 * d * d + 64 * d - 64;
+ return d > 17 ? 0 : 33 * d * d + 66 * d - 66;
}
// Skill structure is used to implement strength limit
&& !Skill(Options["Skill Level"]).enabled()
&& rootMoves[0].pv[0] != MOVE_NONE)
{
- for (Thread* th : Threads)
+ std::map<Move, int> votes;
+ Value minScore = this->rootMoves[0].score;
+
+ // Find out minimum score and reset votes for moves which can be voted
+ for (Thread* th: Threads)
{
- Depth depthDiff = th->completedDepth - bestThread->completedDepth;
- Value scoreDiff = th->rootMoves[0].score - bestThread->rootMoves[0].score;
+ minScore = std::min(minScore, th->rootMoves[0].score);
+ votes[th->rootMoves[0].pv[0]] = 0;
+ }
+
+ // Vote according to score and depth
+ for (Thread* th : Threads)
+ votes[th->rootMoves[0].pv[0]] += int(th->rootMoves[0].score - minScore)
+ + int(th->completedDepth);
- // Select the thread with the best score, always if it is a mate
- if ( scoreDiff > 0
- && (depthDiff >= 0 || th->rootMoves[0].score >= VALUE_MATE_IN_MAX_PLY))
+ // Select best thread
+ int bestVote = votes[this->rootMoves[0].pv[0]];
+ for (Thread* th : Threads)
+ {
+ if (votes[th->rootMoves[0].pv[0]] > bestVote)
+ {
+ bestVote = votes[th->rootMoves[0].pv[0]];
bestThread = th;
+ }
}
}
std::memset(ss-4, 0, 7 * sizeof(Stack));
for (int i = 4; i > 0; i--)
- (ss-i)->continuationHistory = this->continuationHistory[NO_PIECE][0].get(); // Use as sentinel
+ (ss-i)->continuationHistory = &this->continuationHistory[NO_PIECE][0]; // Use as sentinel
bestValue = delta = alpha = -VALUE_INFINITE;
beta = VALUE_INFINITE;
(ss+1)->ply = ss->ply + 1;
ss->currentMove = (ss+1)->excludedMove = bestMove = MOVE_NONE;
- ss->continuationHistory = thisThread->continuationHistory[NO_PIECE][0].get();
+ ss->continuationHistory = &thisThread->continuationHistory[NO_PIECE][0];
(ss+2)->killers[0] = (ss+2)->killers[1] = MOVE_NONE;
Square prevSq = to_sq((ss-1)->currentMove);
Depth R = ((823 + 67 * depth / ONE_PLY) / 256 + std::min((eval - beta) / PawnValueMg, 3)) * ONE_PLY;
ss->currentMove = MOVE_NULL;
- ss->continuationHistory = thisThread->continuationHistory[NO_PIECE][0].get();
+ ss->continuationHistory = &thisThread->continuationHistory[NO_PIECE][0];
pos.do_null_move(st);
probCutCount++;
ss->currentMove = move;
- ss->continuationHistory = thisThread->continuationHistory[pos.moved_piece(move)][to_sq(move)].get();
+ ss->continuationHistory = &thisThread->continuationHistory[pos.moved_piece(move)][to_sq(move)];
assert(depth >= 5 * ONE_PLY);
int lmrDepth = std::max(newDepth - reduction<PvNode>(improving, depth, moveCount), DEPTH_ZERO) / ONE_PLY;
// Countermoves based pruning (~20 Elo)
- if ( lmrDepth < 3
+ if ( lmrDepth < 3 + ((ss-1)->statScore > 0)
&& (*contHist[0])[movedPiece][to_sq(move)] < CounterMovePruneThreshold
&& (*contHist[1])[movedPiece][to_sq(move)] < CounterMovePruneThreshold)
continue;
// Update the current move (this must be done after singular extension search)
ss->currentMove = move;
- ss->continuationHistory = thisThread->continuationHistory[movedPiece][to_sq(move)].get();
+ ss->continuationHistory = &thisThread->continuationHistory[movedPiece][to_sq(move)];
// Step 15. Make the move
pos.do_move(move, st, givesCheck);
{
Depth r = reduction<PvNode>(improving, depth, moveCount);
- if (captureOrPromotion) // (~5 Elo)
- {
- // Decrease reduction by comparing opponent's stat score
- if ((ss-1)->statScore < 0)
- r -= ONE_PLY;
- }
- else
- {
- // Decrease reduction if opponent's move count is high (~5 Elo)
- if ((ss-1)->moveCount > 15)
- r -= ONE_PLY;
+ // Decrease reduction if opponent's move count is high (~10 Elo)
+ if ((ss-1)->moveCount > 15)
+ r -= ONE_PLY;
+ if (!captureOrPromotion)
+ {
// Decrease reduction for exact PV nodes (~0 Elo)
if (pvExact)
r -= ONE_PLY;
Thread* thisThread = pos.this_thread();
(ss+1)->ply = ss->ply + 1;
ss->currentMove = bestMove = MOVE_NONE;
- ss->continuationHistory = thisThread->continuationHistory[NO_PIECE][0].get();
+ ss->continuationHistory = &thisThread->continuationHistory[NO_PIECE][0];
inCheck = pos.checkers();
moveCount = 0;
}
ss->currentMove = move;
- ss->continuationHistory = thisThread->continuationHistory[pos.moved_piece(move)][to_sq(move)].get();
+ ss->continuationHistory = &thisThread->continuationHistory[pos.moved_piece(move)][to_sq(move)];
// Make and search the move
pos.do_move(move, st, givesCheck);