- // Step 14. Reduced search
- // If the move fails high will be re-searched at full depth.
- bool doFullDepthSearch = true;
-
- if ( !captureOrPromotion
- && !dangerous
- && !move_is_castle(move)
- && !move_is_killer(move, ss))
- {
- ss->reduction = reduction<PvNode>(sp->depth, moveCount);
- if (ss->reduction)
- {
- Value localAlpha = sp->alpha;
- Depth d = newDepth - ss->reduction;
- value = d < OnePly ? -qsearch<NonPV>(pos, ss+1, -(localAlpha+1), -localAlpha, Depth(0), sp->ply+1)
- : - search<NonPV>(pos, ss+1, -(localAlpha+1), -localAlpha, d, sp->ply+1);
-
- doFullDepthSearch = (value > localAlpha);
- }
-
- // The move failed high, but if reduction is very big we could
- // face a false positive, retry with a less aggressive reduction,
- // if the move fails high again then go with full depth search.
- if (doFullDepthSearch && ss->reduction > 2 * OnePly)
- {
- assert(newDepth - OnePly >= OnePly);
-
- ss->reduction = OnePly;
- Value localAlpha = sp->alpha;
- value = -search<NonPV>(pos, ss+1, -(localAlpha+1), -localAlpha, newDepth-ss->reduction, sp->ply+1);
- doFullDepthSearch = (value > localAlpha);
- }
- ss->reduction = Depth(0); // Restore original reduction
- }
-
- // Step 15. Full depth search
- if (doFullDepthSearch)
- {
- Value localAlpha = sp->alpha;
- value = newDepth < OnePly ? -qsearch<NonPV>(pos, ss+1, -(localAlpha+1), -localAlpha, Depth(0), sp->ply+1)
- : - search<NonPV>(pos, ss+1, -(localAlpha+1), -localAlpha, newDepth, sp->ply+1);
-
- // Step extra. pv search (only in PV nodes)
- // Search only for possible new PV nodes, if instead value >= beta then
- // parent node fails low with value <= alpha and tries another move.
- if (PvNode && value > localAlpha && value < sp->beta)
- value = newDepth < OnePly ? -qsearch<PV>(pos, ss+1, -sp->beta, -sp->alpha, Depth(0), sp->ply+1)
- : - search<PV>(pos, ss+1, -sp->beta, -sp->alpha, newDepth, sp->ply+1);
- }
-
- // Step 16. Undo move
- pos.undo_move(move);
-
- assert(value > -VALUE_INFINITE && value < VALUE_INFINITE);
-
- // Step 17. Check for new best move
- lock_grab(&(sp->lock));
-
- if (value > sp->bestValue && !TM.thread_should_stop(threadID))
- {
- sp->bestValue = value;
-
- if (sp->bestValue > sp->alpha)
- {
- if (!PvNode || value >= sp->beta)
- sp->stopRequest = true;
-
- if (PvNode && value < sp->beta) // This guarantees that always: sp->alpha < sp->beta
- sp->alpha = value;
-
- sp->parentSstack->bestMove = ss->bestMove = move;
- }
- }
- }
-
- /* Here we have the lock still grabbed */
-
- sp->slaves[threadID] = 0;
-
- lock_release(&(sp->lock));
- }
-
-
- // connected_moves() tests whether two moves are 'connected' in the sense
- // that the first move somehow made the second move possible (for instance
- // if the moving piece is the same in both moves). The first move is assumed
- // to be the move that was made to reach the current position, while the
- // second move is assumed to be a move from the current position.
-
- bool connected_moves(const Position& pos, Move m1, Move m2) {
-
- Square f1, t1, f2, t2;
- Piece p;
-
- assert(move_is_ok(m1));
- assert(move_is_ok(m2));
-
- if (m2 == MOVE_NONE)
- return false;