X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=054ef45d5d05858ad1c6e97c624dcc224edb5241;hp=6f2c48c9cbbd67d60227815b730a2340f126f09e;hb=96d05017354fa838462a7f8f6e25b8731e2ec400;hpb=c831b0054426df008278bb09db2541f7db25c293 diff --git a/src/search.cpp b/src/search.cpp index 6f2c48c9..054ef45d 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -267,6 +267,7 @@ namespace { void update_pv(SearchStack ss[], int ply); void sp_update_pv(SearchStack *pss, SearchStack ss[], int ply); bool connected_moves(const Position &pos, Move m1, Move m2); + bool value_is_mate(Value value); bool move_is_killer(Move m, const SearchStack& ss); Depth extension(const Position &pos, Move m, bool pvNode, bool check, bool singleReply, bool mateThreat, bool* dangerous); bool ok_to_do_nullmove(const Position &pos); @@ -1002,9 +1003,8 @@ namespace { movesSearched[moveCount++] = ss[ply].currentMove = move; if (moveIsCapture) - ss[ply].currentMoveCaptureValue = pos.midgame_value_of_piece_on(move_to(move)); - else if (move_is_ep(move)) - ss[ply].currentMoveCaptureValue = PawnValueMidgame; + ss[ply].currentMoveCaptureValue = + move_is_ep(move)? PawnValueMidgame : pos.midgame_value_of_piece_on(move_to(move)); else ss[ply].currentMoveCaptureValue = Value(0); @@ -1176,6 +1176,7 @@ namespace { if ( allowNullmove && depth > OnePly && !isCheck + && !value_is_mate(beta) && ok_to_do_nullmove(pos) && approximateEval >= beta - NullMoveMargin) { @@ -1183,7 +1184,7 @@ namespace { UndoInfo u; pos.do_null_move(u); - int R = (depth > 7 ? 4 : 3); + int R = (depth >= 4 * OnePly ? 4 : 3); // Null move dynamic reduction Value nullValue = -search(pos, ss, -(beta-1), depth-R*OnePly, ply+1, false, threadID); @@ -1193,6 +1194,7 @@ namespace { if ( UseNullDrivenIID && nullValue < beta && depth > 6 * OnePly + &&!value_is_mate(nullValue) && ttMove == MOVE_NONE && ss[ply + 1].currentMove != MOVE_NONE && pos.move_is_capture(ss[ply + 1].currentMove) @@ -1201,7 +1203,11 @@ namespace { pos.undo_null_move(u); - if (nullValue >= beta) + if (value_is_mate(nullValue)) + { + /* Do not return unproven mates */ + } + else if (nullValue >= beta) { if (depth < 6 * OnePly) return beta; @@ -1230,11 +1236,12 @@ namespace { } } // Null move search not allowed, try razoring - else if ( (approximateEval < beta - RazorMargin && depth < RazorDepth) - ||(approximateEval < beta - PawnValueMidgame && depth <= OnePly)) + else if ( !value_is_mate(beta) + && approximateEval < beta - RazorMargin + && depth < RazorDepth) { Value v = qsearch(pos, ss, beta-1, beta, Depth(0), ply, threadID); - if (v < beta) + if (v < beta - RazorMargin / 2) return v; } @@ -1298,10 +1305,12 @@ namespace { && !moveIsCapture && !move_promotion(move)) { + // History pruning. See ok_to_prune() definition. if ( moveCount >= 2 + int(depth) && ok_to_prune(pos, move, ss[ply].threatMove, depth)) continue; + // Value based pruning. if (depth < 3 * OnePly && approximateEval < beta) { if (futilityValue == VALUE_NONE) @@ -1428,14 +1437,15 @@ namespace { return value_from_tt(tte->value(), ply); // Evaluate the position statically - Value staticValue = evaluate(pos, ei, threadID); + bool isCheck = pos.is_check(); + Value staticValue = (isCheck ? -VALUE_INFINITE : evaluate(pos, ei, threadID)); if (ply == PLY_MAX - 1) - return staticValue; + return evaluate(pos, ei, threadID); // Initialize "stand pat score", and return it immediately if it is // at least beta. - Value bestValue = (pos.is_check() ? -VALUE_INFINITE : staticValue); + Value bestValue = staticValue; if (bestValue >= beta) return bestValue; @@ -1446,12 +1456,11 @@ namespace { // Initialize a MovePicker object for the current position, and prepare // to search the moves. Because the depth is <= 0 here, only captures, // queen promotions and checks (only if depth == 0) will be generated. - MovePicker mp = MovePicker(pos, false, MOVE_NONE, EmptySearchStack, depth, &ei); + bool pvNode = (beta - alpha != 1); + MovePicker mp = MovePicker(pos, pvNode, MOVE_NONE, EmptySearchStack, depth, isCheck ? NULL : &ei); Move move; int moveCount = 0; Bitboard dcCandidates = mp.discovered_check_candidates(); - bool isCheck = pos.is_check(); - bool pvNode = (beta - alpha != 1); bool enoughMaterial = pos.non_pawn_material(pos.side_to_move()) > RookValueMidgame; // Loop through the moves until no moves remain or a beta cutoff @@ -1476,6 +1485,7 @@ namespace { Value futilityValue = staticValue + Max(pos.midgame_value_of_piece_on(move_to(move)), pos.endgame_value_of_piece_on(move_to(move))) + + (move_is_ep(move) ? PawnValueEndgame : Value(0)) + FutilityMargin0 + ei.futilityMargin; @@ -1679,8 +1689,11 @@ namespace { assert(move_is_ok(move)); - ss[sp->ply].currentMoveCaptureValue = move_is_ep(move)? - PawnValueMidgame : pos.midgame_value_of_piece_on(move_to(move)); + if (moveIsCapture) + ss[sp->ply].currentMoveCaptureValue = + move_is_ep(move)? PawnValueMidgame : pos.midgame_value_of_piece_on(move_to(move)); + else + ss[sp->ply].currentMoveCaptureValue = Value(0); lock_grab(&(sp->lock)); int moveCount = ++sp->moves; @@ -2120,6 +2133,18 @@ namespace { } + // value_is_mate() checks if the given value is a mate one + // eventually compensated for the ply. + + bool value_is_mate(Value value) { + + assert(abs(value) <= VALUE_INFINITE); + + return value <= value_mated_in(PLY_MAX) + || value >= value_mate_in(PLY_MAX); + } + + // move_is_killer() checks if the given move is among the // killer moves of that ply. @@ -2144,6 +2169,8 @@ namespace { Depth extension(const Position &pos, Move m, bool pvNode, bool check, bool singleReply, bool mateThreat, bool* dangerous) { + assert(m != MOVE_NONE); + Depth result = Depth(0); *dangerous = check || singleReply || mateThreat; @@ -2167,10 +2194,12 @@ namespace { *dangerous = true; } - if ( pos.midgame_value_of_piece_on(move_to(m)) >= RookValueMidgame + if ( pos.move_is_capture(m) + && pos.type_of_piece_on(move_to(m)) != PAWN && ( pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK) - pos.midgame_value_of_piece_on(move_to(m)) == Value(0)) - && !move_promotion(m)) + && !move_promotion(m) + && !move_is_ep(m)) { result += PawnEndgameExtension[pvNode]; *dangerous = true; @@ -2236,7 +2265,7 @@ namespace { // value of the threatening piece, don't prune move which defend it. if ( !PruneDefendingMoves && threat != MOVE_NONE - && pos.type_of_piece_on(tto) != NO_PIECE_TYPE + && pos.move_is_capture(threat) && ( pos.midgame_value_of_piece_on(tfrom) >= pos.midgame_value_of_piece_on(tto) || pos.type_of_piece_on(tfrom) == KING) && pos.move_attacks_square(m, tto))