// 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()))
{
ss->currentMove = MOVE_NULL;
moves_loop: // When in check search starts from here
- Square prevSq = to_sq((ss-1)->currentMove);
const CounterMoveStats* cmh = (ss-1)->counterMoves;
const CounterMoveStats* fmh = (ss-2)->counterMoves;
const CounterMoveStats* fmh2 = (ss-4)->counterMoves;
// 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
- if (predictedDepth < 4 * ONE_PLY && pos.see_sign(move) < VALUE_ZERO)
- continue;
+ // Prune moves with negative SEE at low depths and below a decreasing
+ // threshold at higher depths.
+ if (predictedDepth < 8 * ONE_PLY)
+ {
+ Value see_v = predictedDepth < 4 * ONE_PLY ? VALUE_ZERO
+ : -PawnValueMg * 2 * int(predictedDepth - 3 * ONE_PLY);
+
+ if (pos.see_sign(move) < see_v)
+ continue;
+ }
}
// Speculative prefetch as early as possible
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);
+ + (fmh2 ? (*fmh2)[moved_piece][to_sq(move)] : VALUE_ZERO)
+ + thisThread->fromTo.get(~pos.side_to_move(), move);
// Increase reduction for cut nodes
if (cutNode)
// Bonus for prior countermove that caused the fail low
else if ( depth >= 3 * ONE_PLY
&& !bestMove
- && !inCheck
&& !pos.captured_piece_type()
&& is_ok((ss-1)->currentMove))
{
+ Square prevSq = to_sq((ss-1)->currentMove);
Value bonus = Value((depth / ONE_PLY) * (depth / ONE_PLY) + 2 * depth / ONE_PLY - 2);
if ((ss-2)->counterMoves)
(ss-2)->counterMoves->update(pos.piece_on(prevSq), prevSq, bonus);
ss->killers[1] = ss->killers[0];
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);
pos.do_move(pv[0], st, pos.gives_check(pv[0], CheckInfo(pos)));
TTEntry* tte = TT.probe(pos.key(), ttHit);
- pos.undo_move(pv[0]);
if (ttHit)
{
Move m = tte->move(); // Local copy to be SMP safe
if (MoveList<LEGAL>(pos).contains(m))
- return pv.push_back(m), true;
+ pv.push_back(m);
}
- return false;
+ pos.undo_move(pv[0]);
+ return pv.size() > 1;
}
void Tablebases::filter_root_moves(Position& pos, Search::RootMoves& rootMoves) {