assert(0 <= ss->ply && ss->ply < MAX_PLY);
- (ss+1)->ttPv = false;
(ss+1)->excludedMove = bestMove = MOVE_NONE;
(ss+2)->killers[0] = (ss+2)->killers[1] = MOVE_NONE;
(ss+2)->cutoffCnt = 0;
ss->doubleExtensions = (ss-1)->doubleExtensions;
- Square prevSq = to_sq((ss-1)->currentMove);
+ Square prevSq = is_ok((ss-1)->currentMove) ? to_sq((ss-1)->currentMove) : SQ_NONE;
// Initialize statScore to zero for the grandchildren of the current position.
// So statScore is shared between all grandchildren and only the first grandchild
ttValue = ss->ttHit ? value_from_tt(tte->value(), ss->ply, pos.rule50_count()) : VALUE_NONE;
ttMove = rootNode ? thisThread->rootMoves[thisThread->pvIdx].pv[0]
: ss->ttHit ? tte->move() : MOVE_NONE;
- ttCapture = ttMove && pos.capture(ttMove);
+ ttCapture = ttMove && pos.capture_stage(ttMove);
// At this point, if excluded, skip straight to step 6, static eval. However,
// to save indentation, we list the condition in all code between here and there.
update_quiet_stats(pos, ss, ttMove, stat_bonus(depth));
// Extra penalty for early quiet moves of the previous ply (~0 Elo on STC, ~2 Elo on LTC)
- if ((ss-1)->moveCount <= 2 && !priorCapture)
+ if (prevSq != SQ_NONE && (ss-1)->moveCount <= 2 && !priorCapture)
update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, -stat_bonus(depth + 1));
}
// Penalty for a quiet ttMove that fails low (~1 Elo)
if (eval == VALUE_NONE)
ss->staticEval = eval = evaluate(pos, &complexity);
else // Fall back to (semi)classical complexity for TT hits, the NNUE complexity is lost
+ {
complexity = abs(ss->staticEval - pos.psq_eg_stm());
+ if (PvNode)
+ Eval::NNUE::hint_common_parent_position(pos);
+ }
// ttValue can be used as a better position evaluation (~7 Elo)
if ( ttValue != VALUE_NONE
probCutBeta = beta + 186 - 54 * improving;
// Step 10. ProbCut (~10 Elo)
- // If we have a good enough capture and a reduced search returns a value
+ // If we have a good enough capture (or queen promotion) and a reduced search returns a value
// much above beta, we can (almost) safely prune the previous move.
if ( !PvNode
&& depth > 4
while ((move = mp.next_move()) != MOVE_NONE)
if (move != excludedMove && pos.legal(move))
{
- assert(pos.capture(move) || promotion_type(move) == QUEEN);
+ assert(pos.capture_stage(move));
ss->currentMove = move;
ss->continuationHistory = &thisThread->continuationHistory[ss->inCheck]
return value;
}
}
+
+ Eval::NNUE::hint_common_parent_position(pos);
}
// Step 11. If the position is not in TT, decrease depth by 3.
nullptr , (ss-4)->continuationHistory,
nullptr , (ss-6)->continuationHistory };
- Move countermove = thisThread->counterMoves[pos.piece_on(prevSq)][prevSq];
+ Move countermove = prevSq != SQ_NONE ? thisThread->counterMoves[pos.piece_on(prevSq)][prevSq] : MOVE_NONE;
MovePicker mp(pos, ttMove, depth, &thisThread->mainHistory,
&captureHistory,
(ss+1)->pv = nullptr;
extension = 0;
- capture = pos.capture(move);
+ capture = pos.capture_stage(move);
movedPiece = pos.moved_piece(move);
givesCheck = pos.gives_check(move);
&& (tte->bound() & BOUND_LOWER)
&& tte->depth() >= depth - 3)
{
- Value singularBeta = ttValue - (2 + (ss->ttPv && !PvNode)) * depth;
+ Value singularBeta = ttValue - (3 + 2 * (ss->ttPv && !PvNode)) * depth / 2;
Depth singularDepth = (depth - 1) / 2;
ss->excludedMove = move;
- // the search with excludedMove will update ss->staticEval
value = search<NonPV>(pos, ss, singularBeta - 1, singularBeta, singularDepth, cutNode);
ss->excludedMove = MOVE_NONE;
// If the eval of ttMove is greater than beta, we reduce it (negative extension)
else if (ttValue >= beta)
- extension = -2;
+ extension = -2 - !PvNode;
// If the eval of ttMove is less than value, we reduce it (negative extension)
else if (ttValue <= value)
extension = -1;
+
+ // If the eval of ttMove is less than alpha, we reduce it (negative extension)
+ else if (ttValue <= alpha)
+ extension = -1;
}
// Check extensions (~1 Elo)
quietsSearched, quietCount, capturesSearched, captureCount, depth);
// Bonus for prior countermove that caused the fail low
- else if (!priorCapture)
+ else if (!priorCapture && prevSq != SQ_NONE)
{
- // Extra bonuses for PV/Cut nodes or bad fail lows
- int bonus = (depth > 5) + (PvNode || cutNode) + (bestValue < alpha - 97 * depth);
+ int bonus = (depth > 5) + (PvNode || cutNode) + (bestValue < alpha - 97 * depth) + ((ss-1)->moveCount > 10);
update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, stat_bonus(depth) * bonus);
}
// to search the moves. Because the depth is <= 0 here, only captures,
// queen promotions, and other checks (only if depth >= DEPTH_QS_CHECKS)
// will be generated.
- Square prevSq = to_sq((ss-1)->currentMove);
+ Square prevSq = (ss-1)->currentMove != MOVE_NULL ? to_sq((ss-1)->currentMove) : SQ_NONE;
MovePicker mp(pos, ttMove, depth, &thisThread->mainHistory,
&thisThread->captureHistory,
contHist,
continue;
givesCheck = pos.gives_check(move);
- capture = pos.capture(move);
+ capture = pos.capture_stage(move);
moveCount++;
Thread* thisThread = pos.this_thread();
CapturePieceToHistory& captureHistory = thisThread->captureHistory;
Piece moved_piece = pos.moved_piece(bestMove);
- PieceType captured = type_of(pos.piece_on(to_sq(bestMove)));
+ PieceType captured;
+
int bonus1 = stat_bonus(depth + 1);
- if (!pos.capture(bestMove))
+ if (!pos.capture_stage(bestMove))
{
int bonus2 = bestValue > beta + 153 ? bonus1 // larger bonus
: stat_bonus(depth); // smaller bonus
}
}
else
+ {
// Increase stats for the best move in case it was a capture move
+ captured = type_of(pos.piece_on(to_sq(bestMove)));
captureHistory[moved_piece][to_sq(bestMove)][captured] << bonus1;
+ }
// Extra penalty for a quiet early move that was not a TT move or
// main killer move in previous ply when it gets refuted.
- if ( ((ss-1)->moveCount == 1 + (ss-1)->ttHit || ((ss-1)->currentMove == (ss-1)->killers[0]))
+ if ( prevSq != SQ_NONE
+ && ((ss-1)->moveCount == 1 + (ss-1)->ttHit || ((ss-1)->currentMove == (ss-1)->killers[0]))
&& !pos.captured_piece())
update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, -bonus1);