void update_quiet_stats(const Position& pos, Stack* ss, Move move, Move* quiets, int quietsCnt, int bonus);
void update_capture_stats(const Position& pos, Move move, Move* captures, int captureCnt, int bonus);
+ inline bool gives_check(const Position& pos, Move move) {
+ Color us = pos.side_to_move();
+ return type_of(move) == NORMAL && !(pos.blockers_for_king(~us) & pos.pieces(us))
+ ? pos.check_squares(type_of(pos.moved_piece(move))) & to_sq(move)
+ : pos.gives_check(move);
+ }
+
// perft() is our utility to verify move generation. All the leaf nodes up
// to the given depth are generated and counted, and the sum is returned.
template<bool Root>
Thread* thisThread = pos.this_thread();
inCheck = pos.checkers();
moveCount = captureCount = quietCount = ss->moveCount = 0;
- ss->statScore = 0;
bestValue = -VALUE_INFINITE;
maxValue = VALUE_INFINITE;
(ss+2)->killers[0] = (ss+2)->killers[1] = MOVE_NONE;
Square prevSq = to_sq((ss-1)->currentMove);
+ // Initialize statScore to zero for the grandchildren of the current position.
+ // So statScore is shared between all grandchildren and only the first grandchild
+ // starts with statScore = 0. Later grandchildren start with the last calculated
+ // statScore of the previous grandchild. This influences the reduction rules in
+ // LMR which are based on the statScore of parent position.
+ (ss+2)->statScore = 0;
+
// Step 4. Transposition table lookup. We don't want the score of a partial
// search to overwrite a previous full search TT value, so we use a different
// position key in case of an excluded move.
// Step 7. Razoring (skipped when in check)
if ( !PvNode
- && depth < 3 * ONE_PLY
+ && depth <= ONE_PLY
&& eval + RazorMargin <= alpha)
- {
- if (depth <= ONE_PLY)
- return qsearch<NonPV, false>(pos, ss, alpha, alpha+1);
-
- Value ralpha = alpha - RazorMargin;
- Value v = qsearch<NonPV, false>(pos, ss, ralpha, ralpha+1);
- if (v <= ralpha)
- return v;
- }
+ return qsearch<NonPV, false>(pos, ss, alpha, alpha+1);
// Step 8. Futility pruning: child node (skipped when in check)
if ( !rootNode
assert(depth >= 5 * ONE_PLY);
pos.do_move(move, st);
- value = -search<NonPV>(pos, ss+1, -rbeta, -rbeta+1, depth - 4 * ONE_PLY, !cutNode, false);
+
+ // Perform a preliminary search at depth 1 to verify that the move holds.
+ // We will only do this search if the depth is not 5, thus avoiding two
+ // searches at depth 1 in a row.
+ if (depth != 5 * ONE_PLY)
+ value = -search<NonPV>(pos, ss+1, -rbeta, -rbeta+1, ONE_PLY, !cutNode, true);
+
+ // If the first search was skipped or was performed and held, perform
+ // the regular search.
+ if (depth == 5 * ONE_PLY || value >= rbeta)
+ value = -search<NonPV>(pos, ss+1, -rbeta, -rbeta+1, depth - 4 * ONE_PLY, !cutNode, false);
+
pos.undo_move(move);
if (value >= rbeta)
return value;
search<NT>(pos, ss, alpha, beta, d, cutNode, true);
tte = TT.probe(posKey, ttHit);
+ ttValue = ttHit ? value_from_tt(tte->value(), ss->ply) : VALUE_NONE;
ttMove = ttHit ? tte->move() : MOVE_NONE;
}
extension = DEPTH_ZERO;
captureOrPromotion = pos.capture_or_promotion(move);
movedPiece = pos.moved_piece(move);
-
- givesCheck = type_of(move) == NORMAL && !pos.discovered_check_candidates()
- ? pos.check_squares(type_of(movedPiece)) & to_sq(move)
- : pos.gives_check(move);
+ givesCheck = gives_check(pos, move);
moveCountPruning = depth < 16 * ONE_PLY
&& moveCount >= FutilityMoveCounts[improving][depth / ONE_PLY];
// Transposition table lookup
posKey = pos.key();
tte = TT.probe(posKey, ttHit);
- ttMove = ttHit ? tte->move() : MOVE_NONE;
ttValue = ttHit ? value_from_tt(tte->value(), ss->ply) : VALUE_NONE;
+ ttMove = ttHit ? tte->move() : MOVE_NONE;
if ( !PvNode
&& ttHit
{
assert(is_ok(move));
- givesCheck = type_of(move) == NORMAL && !pos.discovered_check_candidates()
- ? pos.check_squares(type_of(pos.moved_piece(move))) & to_sq(move)
- : pos.gives_check(move);
+ givesCheck = gives_check(pos, move);
moveCount++;