X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=5fd016a6db59500df25c5e2122d9ea8845c08e7a;hp=744bb7886c5a2f06749faf41e23e68445f25e32c;hb=04407e35d67959b2e9011aa6aff43e2bb632b189;hpb=de0889612f93d021e0754a201ce751fe05d8cb2c diff --git a/src/search.cpp b/src/search.cpp index 744bb788..5fd016a6 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -577,6 +577,17 @@ namespace { beta = std::min(mate_in(ss->ply+1), beta); if (alpha >= beta) return alpha; + + // Check if there exists a move which draws by repetition, or an alternative + // earlier move to this position. + if ( pos.rule50_count() >= 3 + && alpha < VALUE_DRAW + && pos.has_game_cycle(ss->ply)) + { + alpha = VALUE_DRAW; + if (alpha >= beta) + return alpha; + } } assert(0 <= ss->ply && ss->ply < MAX_PLY); @@ -682,12 +693,12 @@ namespace { } } - // Step 6. Evaluate the position statically + // Step 6. Static evaluation of the position if (inCheck) { ss->staticEval = eval = VALUE_NONE; improving = false; - goto moves_loop; + goto moves_loop; // Skip early pruning when in check } else if (ttHit) { @@ -710,13 +721,7 @@ namespace { ss->staticEval, TT.generation()); } - improving = ss->staticEval >= (ss-2)->staticEval - ||(ss-2)->staticEval == VALUE_NONE; - - if (ss->excludedMove || !pos.non_pawn_material(pos.side_to_move())) - goto moves_loop; - - // Step 7. Razoring (skipped when in check, ~2 Elo) + // Step 7. Razoring (~2 Elo) if ( !PvNode && depth < 3 * ONE_PLY && eval <= alpha - RazorMargin[depth / ONE_PLY]) @@ -727,7 +732,10 @@ namespace { return v; } - // Step 8. Futility pruning: child node (skipped when in check, ~30 Elo) + improving = ss->staticEval >= (ss-2)->staticEval + || (ss-2)->staticEval == VALUE_NONE; + + // Step 8. Futility pruning: child node (~30 Elo) if ( !rootNode && depth < 7 * ONE_PLY && eval - futility_margin(depth, improving) >= beta @@ -737,9 +745,11 @@ namespace { // Step 9. Null move search with verification search (~40 Elo) if ( !PvNode && (ss-1)->currentMove != MOVE_NULL - && (ss-1)->statScore < 30000 + && (ss-1)->statScore < 22500 && eval >= beta && ss->staticEval >= beta - 36 * depth / ONE_PLY + 225 + && !excludedMove + && pos.non_pawn_material(pos.side_to_move()) && (ss->ply >= thisThread->nmp_ply || ss->ply % 2 != thisThread->nmp_odd)) { assert(eval - beta >= 0); @@ -779,7 +789,7 @@ namespace { } } - // Step 10. ProbCut (skipped when in check, ~10 Elo) + // Step 10. ProbCut (~10 Elo) // If we have a good enough capture and a reduced search returns a value // much above beta, we can (almost) safely prune the previous move. if ( !PvNode @@ -817,7 +827,7 @@ namespace { } } - // Step 11. Internal iterative deepening (skipped when in check, ~2 Elo) + // Step 11. Internal iterative deepening (~2 Elo) if ( depth >= 8 * ONE_PLY && !ttMove) { @@ -1107,7 +1117,7 @@ moves_loop: // When in check, search starts from here else { assert(value >= beta); // Fail high - ss->statScore = std::max(ss->statScore, 0); + ss->statScore = 0; break; } } @@ -1154,7 +1164,7 @@ moves_loop: // When in check, search starts from here update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, -stat_bonus(depth + ONE_PLY)); } // Bonus for prior countermove that caused the fail low - else if ( depth >= 3 * ONE_PLY + else if ( (depth >= 3 * ONE_PLY || PvNode) && !pos.captured_piece() && is_ok((ss-1)->currentMove)) update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, stat_bonus(depth));