- // Update current move
- movesSearched[moveCount++] = ss[ply].currentMove = move;
-
- // Make and search the move
- pos.do_move(move, st, ci, moveIsCheck);
-
- if (moveCount == 1) // The first move in list is the PV
- value = -search_pv(pos, ss, -beta, -alpha, newDepth, ply+1, threadID);
- else
- {
- // Try to reduce non-pv search depth by one ply if move seems not problematic,
- // if the move fails high will be re-searched at full depth.
- bool doFullDepthSearch = true;
-
- if ( depth >= 3*OnePly
- && !dangerous
- && !captureOrPromotion
- && !move_is_castle(move)
- && !move_is_killer(move, ss[ply]))
- {
- ss[ply].reduction = pv_reduction(depth, moveCount);
- if (ss[ply].reduction)
- {
- value = -search(pos, ss, -alpha, newDepth-ss[ply].reduction, ply+1, true, threadID);
- doFullDepthSearch = (value > alpha);
- }
- }
-
- if (doFullDepthSearch) // Go with full depth non-pv search
- {
- ss[ply].reduction = Depth(0);
- value = -search(pos, ss, -alpha, newDepth, ply+1, true, threadID);
- if (value > alpha && value < beta)
- value = -search_pv(pos, ss, -beta, -alpha, newDepth, ply+1, threadID);
- }
- }
- pos.undo_move(move);
-
- assert(value > -VALUE_INFINITE && value < VALUE_INFINITE);
-
- // New best move?
- if (value > bestValue)
- {
- bestValue = value;
- if (value > alpha)
- {
- alpha = value;
- update_pv(ss, ply);
- if (value == value_mate_in(ply + 1))
- ss[ply].mateKiller = move;
- }
- }
-
- // Split?
- if ( TM.active_threads() > 1
- && bestValue < beta
- && depth >= MinimumSplitDepth
- && Iteration <= 99
- && TM.available_thread_exists(threadID)
- && !AbortSearch
- && !TM.thread_should_stop(threadID)
- && TM.split(pos, ss, ply, &alpha, beta, &bestValue, VALUE_NONE,
- depth, &moveCount, &mp, threadID, true))
- break;
- }
-
- // All legal moves have been searched. A special case: If there were
- // no legal moves, it must be mate or stalemate.
- if (moveCount == 0)
- return (isCheck ? value_mated_in(ply) : VALUE_DRAW);
-
- // If the search is not aborted, update the transposition table,
- // history counters, and killer moves.
- if (AbortSearch || TM.thread_should_stop(threadID))
- return bestValue;
-
- if (bestValue <= oldAlpha)
- TT.store(pos.get_key(), value_to_tt(bestValue, ply), VALUE_TYPE_UPPER, depth, MOVE_NONE);
-
- else if (bestValue >= beta)
- {
- TM.incrementBetaCounter(pos.side_to_move(), depth, threadID);
- move = ss[ply].pv[ply];
- if (!pos.move_is_capture_or_promotion(move))
- {
- update_history(pos, move, depth, movesSearched, moveCount);
- update_killers(move, ss[ply]);
- }
- TT.store(pos.get_key(), value_to_tt(bestValue, ply), VALUE_TYPE_LOWER, depth, move);
- }
- else
- TT.store(pos.get_key(), value_to_tt(bestValue, ply), VALUE_TYPE_EXACT, depth, ss[ply].pv[ply]);
-
- return bestValue;
- }
-
-
- // search() is the search function for zero-width nodes.
-
- Value search(Position& pos, SearchStack ss[], Value beta, Depth depth,
- int ply, bool allowNullmove, int threadID, Move excludedMove) {
-
- assert(beta >= -VALUE_INFINITE && beta <= VALUE_INFINITE);
- assert(ply >= 0 && ply < PLY_MAX);
- assert(threadID >= 0 && threadID < TM.active_threads());
-
- Move movesSearched[256];
- EvalInfo ei;
- StateInfo st;
- const TTEntry* tte;
- Move ttMove, move;
- Depth ext, newDepth;
- Value bestValue, staticValue, nullValue, value, futilityValue, futilityValueScaled;
- bool isCheck, singleEvasion, moveIsCheck, captureOrPromotion, dangerous;
- bool mateThreat = false;
- int moveCount = 0;
- futilityValue = staticValue = bestValue = value = -VALUE_INFINITE;
-
- if (depth < OnePly)
- return qsearch(pos, ss, beta-1, beta, Depth(0), ply, threadID);
-
- // Step 1. Initialize node and poll
- // Polling can abort search.
- init_node(ss, ply, threadID);
-
- // Step 2. Check for aborted search and immediate draw
- if (AbortSearch || TM.thread_should_stop(threadID))
- return Value(0);
-
- if (pos.is_draw() || ply >= PLY_MAX - 1)
- return VALUE_DRAW;
-
- // Step 3. Mate distance pruning
- if (value_mated_in(ply) >= beta)
- return beta;
-
- if (value_mate_in(ply + 1) < beta)
- return beta - 1;
-
- // 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 exsists.
- Key posKey = excludedMove ? pos.get_exclusion_key() : pos.get_key();
-
- tte = TT.retrieve(posKey);
- ttMove = (tte ? tte->move() : MOVE_NONE);
-
- if (tte && ok_to_use_TT(tte, depth, beta, ply))
- {
- ss[ply].currentMove = ttMove; // Can be MOVE_NONE