// Step 14. Reduced search
+ int ReductionLevel = 2; // 0 = most aggressive reductions, 7 = minimum reductions
+
// Reduction lookup tables (initialized at startup) and their getter functions
int8_t PVReductionMatrix[8][64][64]; // [depth][moveNumber]
int8_t NonPVReductionMatrix[8][64][64]; // [depth][moveNumber]
- inline Depth pv_reduction(Depth d, int mn) { return (Depth) PVReductionMatrix[0][Min(d / 2, 63)][Min(mn, 63)]; }
- inline Depth nonpv_reduction(Depth d, int mn) { return (Depth) NonPVReductionMatrix[0][Min(d / 2, 63)][Min(mn, 63)]; }
+ inline Depth pv_reduction(Depth d, int mn) { return (Depth) PVReductionMatrix[ReductionLevel][Min(d / 2, 63)][Min(mn, 63)]; }
+ inline Depth nonpv_reduction(Depth d, int mn) { return (Depth) NonPVReductionMatrix[ReductionLevel][Min(d / 2, 63)][Min(mn, 63)]; }
// Common adjustments
return !Quit;
}
-// init_reduction_tables()
-
-void init_reduction_tables(int8_t pvTable[64][64], int8_t nonPvTable[64][64], int pvInhib, int nonPvInhib)
+// init_reduction_tables() is called by init_search() and initializes
+// the tables used by LMR.
+static void init_reduction_tables(int8_t pvTable[64][64], int8_t nonPvTable[64][64], int pvInhib, int nonPvInhib)
{
double pvBase = 1.001 - log(3.0) * log(16.0) / pvInhib;
double nonPvBase = 1.001 - log(3.0) * log(4.0) / nonPvInhib;
- // Init reduction lookup tables
for (int i = 1; i < 64; i++) // i == depth (OnePly = 1)
for (int j = 1; j < 64; j++) // j == moveNumber
{
}
// init_search() is called during startup. It initializes various lookup tables
-
void init_search() {
+ // Init reduction lookup tables
for (int i = 0; i < 8; i++)
- init_reduction_tables(PVReductionMatrix[i], NonPVReductionMatrix[i], 4.0 * pow(1.3, i), 2.0 * pow(1.3, i));
+ init_reduction_tables(PVReductionMatrix[i], NonPVReductionMatrix[i], int(4 * pow(1.3, i)), int(2 * pow(1.3, i)));
// Init futility margins array
for (int i = 0; i < 16; i++) // i == depth (OnePly = 2)
beta = Min(ValueByIteration[Iteration - 1] + AspirationDelta, VALUE_INFINITE);
}
+ // Choose optimum reduction level
+ ReductionLevel = 2;
+
+ if (UseTimeManagement)
+ {
+ int level = int(floor(log(float(MaxSearchTime) / current_search_time()) / log(2.0) + 1.0));
+ ReductionLevel = Min(Max(level, 0), 7);
+ }
+ else
+ {
+ //FIXME
+ }
+
// Search to the current depth, rml is updated and sorted, alpha and beta could change
value = root_search(p, ss, rml, &alpha, &beta);
// Step 7. Static null move pruning
// We're betting that the opponent doesn't have a move that will reduce
- // the score by more than fuility_margin(depth) if we do a null move.
- if ( !isCheck
- && allowNullmove
- && depth < RazorDepth
- && refinedValue - futility_margin(depth, 0) >= beta)
+ // the score by more than futility_margin(depth) if we do a null move.
+ if ( allowNullmove
+ && depth < RazorDepth
+ && !isCheck
+ && !value_is_mate(beta)
+ && ok_to_do_nullmove(pos)
+ && refinedValue >= beta + futility_margin(depth, 0))
return refinedValue - futility_margin(depth, 0);
// Step 8. Null move search with verification search
{
ss[ply].currentMove = MOVE_NULL;
- pos.do_null_move(st);
-
// Null move dynamic reduction based on depth
int R = 3 + (depth >= 5 * OnePly ? depth / 8 : 0);
if (refinedValue - beta > PawnValueMidgame)
R++;
+ pos.do_null_move(st);
+
nullValue = -search(pos, ss, -(beta-1), depth-R*OnePly, ply+1, false, threadID);
pos.undo_null_move();