+ if (futilityCaptureValue < beta)
+ {
+ if (futilityCaptureValue > bestValue)
+ bestValue = futilityCaptureValue;
+ continue;
+ }
+ }
+
+ // Futility pruning
+ if ( !isCheck
+ && !dangerous
+ && !captureOrPromotion
+ && !move_is_castle(move)
+ && move != ttMove)
+ {
+ // Move count based pruning
+ if ( moveCount >= FutilityMoveCountMargin
+ && ok_to_prune(pos, move, ss[ply].threatMove)
+ && bestValue > value_mated_in(PLY_MAX))
+ continue;
+
+ // Value based pruning
+ Depth predictedDepth = newDepth;
+
+ //FIXME HACK: awful code duplication
+ double red = 0.5 + ln(moveCount) * ln(depth / 2) / 3.0;
+ if (red >= 1.0)
+ predictedDepth -= int(floor(red * int(OnePly)));
+
+ if (predictedDepth < SelectiveDepth)
+ {
+ int preFutilityValueMargin = 0;
+ if (predictedDepth >= OnePly)
+ preFutilityValueMargin = 112 * bitScanReverse32(int(predictedDepth) * int(predictedDepth) / 2);
+
+ preFutilityValueMargin += H.gain(pos.piece_on(move_from(move)), move_from(move), move_to(move)) + 45;
+
+ futilityValueScaled = ss[ply].eval + preFutilityValueMargin - moveCount * IncrementalFutilityMargin;
+
+ if (futilityValueScaled < beta)
+ {
+ if (futilityValueScaled > bestValue)
+ bestValue = futilityValueScaled;
+ continue;
+ }
+ }
+ }
+
+ // Make and search the move
+ pos.do_move(move, st, ci, moveIsCheck);
+
+ // 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])
+ /* && move != ttMove*/)
+ {
+ double red = 0.5 + ln(moveCount) * ln(depth / 2) / 3.0;
+ if (red >= 1.0)
+ {
+ ss[ply].reduction = Depth(int(floor(red * int(OnePly))));
+ value = -search(pos, ss, -(beta-1), newDepth-ss[ply].reduction, ply+1, true, threadID);
+ doFullDepthSearch = (value >= beta);
+ }
+ }
+
+ if (doFullDepthSearch) // Go with full depth non-pv search
+ {
+ ss[ply].reduction = Depth(0);
+ value = -search(pos, ss, -(beta-1), newDepth, ply+1, true, threadID);
+ }
+ pos.undo_move(move);
+
+ assert(value > -VALUE_INFINITE && value < VALUE_INFINITE);
+
+ // New best move?