const Value EasyMoveMargin = Value(0x200);
// Last seconds noise filtering (LSN)
- const bool UseLSNFiltering = false;
+ const bool UseLSNFiltering = true;
const int LSNTime = 4000; // In milliseconds
const Value LSNValue = value_from_centipawns(200);
bool loseOnTime = false;
int SearchStartTime, MaxNodes, MaxDepth, MaxSearchTime;
int AbsoluteMaxSearchTime, ExtraSearchTime, ExactMaxTime;
bool UseTimeManagement, InfiniteSearch, PonderSearch, StopOnPonderhit;
- bool FirstRootMove, AbortSearch, Quit, AspirationFailLow, ZugDetection;
+ bool FirstRootMove, AbortSearch, Quit, AspirationFailLow;
// Log file
bool UseLogFile;
Depth extension(const Position&, Move, bool, bool, bool, bool, bool, bool*);
bool ok_to_do_nullmove(const Position& pos);
bool ok_to_prune(const Position& pos, Move m, Move threat);
- bool ok_to_use_TT(const TTEntry* tte, Depth depth, Value beta, int ply, bool allowNullmove);
+ bool ok_to_use_TT(const TTEntry* tte, Depth depth, Value beta, int ply);
Value refine_eval(const TTEntry* tte, Value defaultEval, int ply);
void update_history(const Position& pos, Move move, Depth depth, Move movesSearched[], int moveCount);
void update_killers(Move m, SearchStack& ss);
if (get_option_value_string("Book File") != OpeningBook.file_name())
OpeningBook.open(get_option_value_string("Book File"));
- Move bookMove = OpeningBook.get_move(pos);
+ Move bookMove = OpeningBook.get_move(pos, get_option_value_bool("Best Book Move"));
if (bookMove != MOVE_NONE)
{
if (PonderSearch)
MultiPV = get_option_value_int("MultiPV");
Chess960 = get_option_value_bool("UCI_Chess960");
UseLogFile = get_option_value_bool("Use Search Log");
- ZugDetection = get_option_value_bool("Zugzwang detection"); // To be removed after 1.7.1
if (UseLogFile)
LogFile.open(get_option_value_string("Search Log Filename").c_str(), std::ios::out | std::ios::app);
for (int j = 0; j < 64; j++) // j == moveNumber
{
// FIXME: test using log instead of BSR
- FutilityMarginsMatrix[i][j] = (i < 2 ? 0 : 112 * bitScanReverse32(i * i / 2)) - 8 * j;
+ FutilityMarginsMatrix[i][j] = (i < 2 ? 0 : 112 * bitScanReverse32(i * i / 2)) - 8 * j + 45;
}
// Init futility move count array
tte = TT.retrieve(posKey);
ttMove = (tte ? tte->move() : MOVE_NONE);
- if (tte && ok_to_use_TT(tte, depth, beta, ply, allowNullmove))
+ 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);
if (nullValue >= value_mate_in(PLY_MAX))
nullValue = beta;
- // Do zugzwang verification search for high depths, don't store in TT
- // if search was stopped.
- if ( ( depth < 6 * OnePly
- || search(pos, ss, beta, depth-5*OnePly, ply, false, threadID) >= beta)
- && !AbortSearch
- && !TM.thread_should_stop(threadID))
- {
- assert(value_to_tt(nullValue, ply) == nullValue);
+ if (depth < 6 * OnePly)
+ return nullValue;
- TT.store(posKey, nullValue, VALUE_TYPE_NS_LO, depth, MOVE_NONE);
+ // Do zugzwang verification search
+ Value v = search(pos, ss, beta, depth-5*OnePly, ply, false, threadID);
+ if (v >= beta)
return nullValue;
- }
} else {
// The null move failed low, which means that we may be faced with
// some kind of threat. If the previous move was reduced, check if
// Value based pruning
Depth predictedDepth = newDepth - nonpv_reduction(depth, moveCount); // We illogically ignore reduction condition depth >= 3*OnePly
futilityValueScaled = ss[ply].eval + futility_margin(predictedDepth, moveCount)
- + H.gain(pos.piece_on(move_from(move)), move_to(move)) + 45;
+ + H.gain(pos.piece_on(move_from(move)), move_to(move));
if (futilityValueScaled < beta)
{
tte = TT.retrieve(pos.get_key());
ttMove = (tte ? tte->move() : MOVE_NONE);
- if (!pvNode && tte && ok_to_use_TT(tte, depth, beta, ply, true))
+ if (!pvNode && tte && ok_to_use_TT(tte, depth, beta, ply))
{
assert(tte->type() != VALUE_TYPE_EVAL);
// Detect blocking evasions that are candidate to be pruned
evasionPrunable = isCheck
- && bestValue != -VALUE_INFINITE
+ && bestValue > value_mated_in(PLY_MAX)
&& !pos.move_is_capture(move)
&& pos.type_of_piece_on(move_from(move)) != KING
&& !pos.can_castle(pos.side_to_move());
// Value based pruning
Depth predictedDepth = newDepth - nonpv_reduction(sp->depth, moveCount);
futilityValueScaled = ss[sp->ply].eval + futility_margin(predictedDepth, moveCount)
- + H.gain(pos.piece_on(move_from(move)), move_to(move)) + 45;
+ + H.gain(pos.piece_on(move_from(move)), move_to(move));
if (futilityValueScaled < sp->beta)
{
}
- // ok_to_use_TT() returns true if a transposition table score can be used at a
- // given point in search. To avoid zugzwang issues TT cutoffs at the root node
- // of a null move verification search are not allowed if the TT value was found
- // by a null search, this is implemented testing allowNullmove and TT entry type.
+ // ok_to_use_TT() returns true if a transposition table score
+ // can be used at a given point in search.
- bool ok_to_use_TT(const TTEntry* tte, Depth depth, Value beta, int ply, bool allowNullmove) {
+ bool ok_to_use_TT(const TTEntry* tte, Depth depth, Value beta, int ply) {
Value v = value_from_tt(tte->value(), ply);
- return (allowNullmove || !(tte->type() & VALUE_TYPE_NULL) || !ZugDetection)
-
- && ( tte->depth() >= depth
+ return ( tte->depth() >= depth
|| v >= Max(value_mate_in(PLY_MAX), beta)
|| v < Min(value_mated_in(PLY_MAX), beta))
}
// Wait until the thread has finished launching and is gone to sleep
- while (threads[i].state != THREAD_SLEEPING);
+ while (threads[i].state != THREAD_SLEEPING) {}
}
}
SplitPoint* sp;
- for (sp = threads[threadID].splitPoint; sp && !sp->stopRequest; sp = sp->parent);
+ for (sp = threads[threadID].splitPoint; sp && !sp->stopRequest; sp = sp->parent) {}
return sp != NULL;
}