- // 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 || 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)
- {
- BetaCounter.add(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 < ActiveThreads);
-
- Move movesSearched[256];
- EvalInfo ei;
- StateInfo st;
- const TTEntry* tte;
- Move ttMove, move;
- Depth ext, newDepth;
- Value staticValue, nullValue, value, futilityValue, futilityValueScaled;
- bool isCheck, useFutilityPruning, singleEvasion, moveIsCheck, captureOrPromotion, dangerous;
- bool mateThreat = false;
- int moveCount = 0;
- Value bestValue = -VALUE_INFINITE;
-
- if (depth < OnePly)
- return qsearch(pos, ss, beta-1, beta, Depth(0), ply, threadID);
-
- // Initialize, and make an early exit in case of an aborted search,
- // an instant draw, maximum ply reached, etc.
- init_node(ss, ply, threadID);
-
- // After init_node() that calls poll()
- if (AbortSearch || thread_should_stop(threadID))
- return Value(0);
-
- if (pos.is_draw() || ply >= PLY_MAX - 1)
- return VALUE_DRAW;
-
- // Mate distance pruning
- if (value_mated_in(ply) >= beta)
- return beta;
-
- if (value_mate_in(ply + 1) < beta)
- return beta - 1;
-
- // 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();
-
- // Transposition table lookup
- 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
- return value_from_tt(tte->value(), ply);
- }
-
- isCheck = pos.is_check();
- ei.futilityMargin = Value(0); // Manually initialize futilityMargin
-
- // Calculate depth dependant futility pruning parameters
- const int FutilityMoveCountMargin = 3 + (1 << (3 * int(depth) / 8));
- const int FutilityValueMargin = 112 * bitScanReverse32(int(depth) * int(depth) / 2);
-
- // Evaluate the position statically
- if (isCheck)
- ss[ply].eval = VALUE_NONE;
- else