// Razoring and futility margin based on depth
const int razor_margin[4] = { 483, 570, 603, 554 };
- Value futility_margin(Depth d) { return Value(200 * d); }
+ Value futility_margin(Depth d) { return Value(150 * d); }
// Futility and reductions lookup tables, initialized at startup
int FutilityMoveCounts[2][16]; // [improving][depth]
{
th->history.clear();
th->counterMoves.clear();
+ th->fromTo.clear();
}
Threads.main()->previousScore = VALUE_INFINITE;
// Step 8. Null move search with verification search (is omitted in PV nodes)
if ( !PvNode
- && depth >= 2 * ONE_PLY
&& eval >= beta
&& (ss->staticEval >= beta - 35 * (depth / ONE_PLY - 6) || depth >= 13 * ONE_PLY)
&& pos.non_pawn_material(pos.side_to_move()))
if (moveCountPruning)
continue;
+ predictedDepth = std::max(newDepth - reduction<PvNode>(improving, depth, moveCount), DEPTH_ZERO);
+
// Countermoves based pruning
- if ( depth <= 4 * ONE_PLY
+ if ( predictedDepth < 3 * ONE_PLY
&& move != ss->killers[0]
&& (!cmh || (*cmh )[moved_piece][to_sq(move)] < VALUE_ZERO)
&& (!fmh || (*fmh )[moved_piece][to_sq(move)] < VALUE_ZERO)
&& (!fmh2 || (*fmh2)[moved_piece][to_sq(move)] < VALUE_ZERO || (cmh && fmh)))
continue;
- predictedDepth = std::max(newDepth - reduction<PvNode>(improving, depth, moveCount), DEPTH_ZERO);
-
// Futility pruning: parent node
if ( predictedDepth < 7 * ONE_PLY
- && ss->staticEval + futility_margin(predictedDepth) + 256 <= alpha)
+ && ss->staticEval + 256 + 200 * predictedDepth / ONE_PLY <= alpha)
continue;
// Prune moves with negative SEE at low depths and below a decreasing
// re-searched at full depth.
if ( depth >= 3 * ONE_PLY
&& moveCount > 1
- && !captureOrPromotion)
+ && (!captureOrPromotion || moveCountPruning))
{
Depth r = reduction<PvNode>(improving, depth, moveCount);
- Value val = thisThread->history[moved_piece][to_sq(move)]
- + (cmh ? (*cmh )[moved_piece][to_sq(move)] : VALUE_ZERO)
- + (fmh ? (*fmh )[moved_piece][to_sq(move)] : VALUE_ZERO)
- + (fmh2 ? (*fmh2)[moved_piece][to_sq(move)] : VALUE_ZERO);
-
- // Increase reduction for cut nodes
- if (cutNode)
- r += 2 * ONE_PLY;
-
- // Decrease reduction for moves that escape a capture. Filter out
- // castling moves, because they are coded as "king captures rook" and
- // hence break make_move(). Also use see() instead of see_sign(),
- // because the destination square is empty.
- else if ( type_of(move) == NORMAL
- && type_of(pos.piece_on(to_sq(move))) != PAWN
- && pos.see(make_move(to_sq(move), from_sq(move))) < VALUE_ZERO)
- r -= 2 * ONE_PLY;
-
- // Decrease/increase reduction for moves with a good/bad history
- int rHist = (val - 10000) / 20000;
- r = std::max(DEPTH_ZERO, r - rHist * ONE_PLY);
+
+ if (captureOrPromotion)
+ r -= r ? ONE_PLY : DEPTH_ZERO;
+ else
+ {
+ Value val = thisThread->history[moved_piece][to_sq(move)]
+ + (cmh ? (*cmh )[moved_piece][to_sq(move)] : VALUE_ZERO)
+ + (fmh ? (*fmh )[moved_piece][to_sq(move)] : VALUE_ZERO)
+ + (fmh2 ? (*fmh2)[moved_piece][to_sq(move)] : VALUE_ZERO)
+ + thisThread->fromTo.get(~pos.side_to_move(), move);
+
+ // Increase reduction for cut nodes
+ if (cutNode)
+ r += 2 * ONE_PLY;
+
+ // Decrease reduction for moves that escape a capture. Filter out
+ // castling moves, because they are coded as "king captures rook" and
+ // hence break make_move(). Also use see() instead of see_sign(),
+ // because the destination square is empty.
+ else if ( type_of(move) == NORMAL
+ && type_of(pos.piece_on(to_sq(move))) != PAWN
+ && pos.see(make_move(to_sq(move), from_sq(move))) < VALUE_ZERO)
+ r -= 2 * ONE_PLY;
+
+ // Decrease/increase reduction for moves with a good/bad history
+ int rHist = (val - 10000) / 20000;
+ r = std::max(DEPTH_ZERO, r - rHist * ONE_PLY);
+ }
Depth d = std::max(newDepth - r, ONE_PLY);
value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, d, true);
- doFullDepthSearch = (value > alpha && r != DEPTH_ZERO);
+ doFullDepthSearch = (value > alpha && d != newDepth);
}
else
doFullDepthSearch = !PvNode || moveCount > 1;
ss->killers[0] = move;
}
+ Color c = pos.side_to_move();
Value bonus = Value((depth / ONE_PLY) * (depth / ONE_PLY) + 2 * depth / ONE_PLY - 2);
Square prevSq = to_sq((ss-1)->currentMove);
Thread* thisThread = pos.this_thread();
thisThread->history.update(pos.moved_piece(move), to_sq(move), bonus);
+ thisThread->fromTo.update(c, move, bonus);
if (cmh)
{
for (int i = 0; i < quietsCnt; ++i)
{
thisThread->history.update(pos.moved_piece(quiets[i]), to_sq(quiets[i]), -bonus);
+ thisThread->fromTo.update(c, quiets[i], -bonus);
if (cmh)
cmh->update(pos.moved_piece(quiets[i]), to_sq(quiets[i]), -bonus);