// Time managment variables
int SearchStartTime;
int MaxNodes, MaxDepth;
- int MaxSearchTime, AbsoluteMaxSearchTime, EmergencyMaxSearchTime, ExtraSearchTime;
+ int MaxSearchTime, AbsoluteMaxSearchTime, ExtraSearchTime;
Move EasyMove;
int RootMoveNumber;
bool InfiniteSearch;
void update_killers(Move m, SearchStack& ss);
bool fail_high_ply_1();
+ bool aspiration_fail_high_ply_1();
int current_search_time();
int nps();
void poll();
{
Threads[i].nodes = 0ULL;
Threads[i].failHighPly1 = false;
+ Threads[i].aspirationFailHighPly1 = false;
}
NodesSincePoll = 0;
InfiniteSearch = infinite;
{
MaxSearchTime = myTime / 30 + myIncrement;
AbsoluteMaxSearchTime = Max(myTime / 4, myIncrement - 100);
- EmergencyMaxSearchTime = Max(myTime / 2, myIncrement - 100);
} else { // Blitz game without increment
MaxSearchTime = myTime / 30;
AbsoluteMaxSearchTime = myTime / 8;
- EmergencyMaxSearchTime = myTime / 4;
}
}
else // (x moves) / (y minutes)
{
MaxSearchTime = myTime / 2;
AbsoluteMaxSearchTime = Min(myTime / 2, myTime - 500);
- EmergencyMaxSearchTime = myTime - 500;
} else {
MaxSearchTime = myTime / Min(movesToGo, 20);
AbsoluteMaxSearchTime = Min((4 * myTime) / movesToGo, myTime / 3);
- EmergencyMaxSearchTime = Min((8 * myTime) / movesToGo, myTime / 2);
}
}
Position p(pos);
SearchStack ss[PLY_MAX_PLUS_2];
- Value alpha;
- Value beta;
-
// searchMoves are verified, copied, scored and sorted
RootMoveList rml(p, searchMoves);
std::cout << "info depth " << Iteration << std::endl;
//Calculate dynamic search window based on previous iterations.
+ Value alpha;
+ Value beta;
+
if (MultiPV == 1 && Iteration >= 6) {
Value prevDelta1 = IterationInfo[Iteration - 1].speculated_value() - IterationInfo[Iteration - 2].speculated_value();
Value prevDelta2 = IterationInfo[Iteration - 2].speculated_value() - IterationInfo[Iteration - 3].speculated_value();
// Search to the current depth
Value value = root_search(p, ss, rml, alpha, beta);
+ if (AbortSearch)
+ break; //Value cannot be trusted. Break out immediately!
// Write PV to transposition table, in case the relevant entries have
// been overwritten during the search:
TT.insert_pv(p, ss[0].pv);
- if (AbortSearch)
- break; //Value cannot be trusted. Break out immediately!
-
//Save info about search result
Value speculated_value = value;
bool fHigh = false;
if (stopSearch)
{
+ //FIXME: Implement fail-low emergency measures
if (!PonderSearch)
break;
else
break;
}
- if (FailLow)
- {
- //Here we face the rare, but extremely difficult case:
- //Our aspiration search has failed low and we've run out of time!
- //So we have no move to play!
- //Now use the emergency time and try as quickly as possible to
- //find even one playable move.
-
- //FIXME: this is only for grepping logs purpose. Remove me when we are sure that this stuff really works!!
- if (AbortSearch)
- std::cout << "info depth " << 999 << std::endl;
- else
- std::cout << "info depth " << 998 << std::endl;
-
- //Prepare variables for emergency search
- AbortSearch = false;
- FailLow = false;
- AbsoluteMaxSearchTime = EmergencyMaxSearchTime;
- MaxSearchTime = EmergencyMaxSearchTime;
- ExtraSearchTime = 0;
- rml.sort();
-
- std::cout << "info depth " << Iteration << std::endl;
-
- //Cause we failed low, it's _likely_ that we couldn't get over alpha anyway.
- root_search(p, ss, rml, -VALUE_INFINITE, alpha);
- }
-
rml.sort();
// If we are pondering, we shouldn't print the best move before we
{
ss[ply].reduction = Depth(0);
value = -search(pos, ss, -alpha, newDepth, ply+1, true, threadID);
- if (value > alpha && value < beta)
+ if (value > alpha /*&& value < beta*/)
{
// When the search fails high at ply 1 while searching the first
// move at the root, set the flag failHighPly1. This is used for
// time managment: We don't want to stop the search early in
// such cases, because resolving the fail high at ply 1 could
// result in a big drop in score at the root.
- if (ply == 1 && RootMoveNumber == 1)
+ if (ply == 1 && RootMoveNumber == 1) {
Threads[threadID].failHighPly1 = true;
+ if (value >= beta) {
+ Threads[threadID].aspirationFailHighPly1 = true;
+ }
+ }
// A fail high occurred. Re-search at full window (pv search)
value = -search_pv(pos, ss, -beta, -alpha, newDepth, ply+1, threadID);
Threads[threadID].failHighPly1 = false;
+ //FIXME: Current implementation of Problem code is not completely thread-safe.
+ //If poll is called before pv is updated, we lose this move.
+ //(failHighPly1 also suffers from same kind of problems though. There is also a small
+ //fraction of time when failHighPly1 and Problem are _both_ false, though we
+ //are facing bad problems. If we are very unlucky search is terminated).
+ Threads[threadID].aspirationFailHighPly1 = false;
}
}
}
ss[sp->ply].reduction = Depth(0);
value = -search(pos, ss, -sp->alpha, newDepth, sp->ply+1, true, threadID);
- if (value > sp->alpha && value < sp->beta)
+ if (value > sp->alpha /*&& value < sp->beta*/)
{
// When the search fails high at ply 1 while searching the first
// move at the root, set the flag failHighPly1. This is used for
// time managment: We don't want to stop the search early in
// such cases, because resolving the fail high at ply 1 could
// result in a big drop in score at the root.
- if (sp->ply == 1 && RootMoveNumber == 1)
+ if (sp->ply == 1 && RootMoveNumber == 1) {
Threads[threadID].failHighPly1 = true;
+ if (value >= sp->beta) {
+ Threads[threadID].aspirationFailHighPly1 = true;
+ }
+ }
value = -search_pv(pos, ss, -sp->beta, -sp->alpha, newDepth, sp->ply+1, threadID);
Threads[threadID].failHighPly1 = false;
+ Threads[threadID].aspirationFailHighPly1 = false;
}
}
pos.undo_move(move);
return false;
}
+ bool aspiration_fail_high_ply_1() {
+ for(int i = 0; i < ActiveThreads; i++)
+ if(Threads[i].aspirationFailHighPly1)
+ return true;
+ return false;
+ }
+
// current_search_time() returns the number of milliseconds which have passed
// since the beginning of the current search.
return;
bool overTime = t > AbsoluteMaxSearchTime
- || (RootMoveNumber == 1 && t > MaxSearchTime + ExtraSearchTime && !FailLow) //FIXME: BUG??
- || ( !FailHigh && !FailLow && !fail_high_ply_1() && !Problem
+ || (RootMoveNumber == 1 && t > MaxSearchTime + ExtraSearchTime && !FailLow && !aspiration_fail_high_ply_1())
+ || ( !FailHigh && !FailLow && !fail_high_ply_1() && !aspiration_fail_high_ply_1() && !Problem
&& t > 6*(MaxSearchTime + ExtraSearchTime));
if ( (Iteration >= 3 && (!InfiniteSearch && overTime))