#include "lock.h"
#include "san.h"
#include "search.h"
+#include "timeman.h"
#include "thread.h"
#include "tt.h"
#include "ucioption.h"
Depth PassedPawnExtension[2], PawnEndgameExtension[2], MateThreatExtension[2];
// Minimum depth for use of singular extension
- const Depth SingularExtensionDepth[2] = { 8 * OnePly /* non-PV */, 6 * OnePly /* PV */};
+ const Depth SingularExtensionDepth[2] = { 7 * OnePly /* non-PV */, 6 * OnePly /* PV */};
// If the TT move is at least SingularExtensionMargin better then the
// remaining ones we will extend it.
}
-// SearchStack::init() initializes a search stack entry.
-// Called at the beginning of search() when starting to examine a new node.
-void SearchStack::init() {
-
- currentMove = bestMove = MOVE_NONE;
-}
-
-// SearchStack::initKillers() initializes killers for a search stack entry
-void SearchStack::initKillers() {
-
- killers[0] = killers[1] = mateKiller = MOVE_NONE;
-}
-
-
/// perft() is our utility to verify move generation is bug free. All the legal
/// moves up to given depth are generated and counted and the sum returned.
int myIncrement = increment[pos.side_to_move()];
if (UseTimeManagement)
{
- if (!movesToGo) // Sudden death time control
- {
- if (myIncrement)
- {
- MaxSearchTime = myTime / 30 + myIncrement;
- AbsoluteMaxSearchTime = Max(myTime / 4, myIncrement - 100);
- }
- else // Blitz game without increment
- {
- MaxSearchTime = myTime / 30;
- AbsoluteMaxSearchTime = myTime / 8;
- }
- }
- else // (x moves) / (y minutes)
- {
- if (movesToGo == 1)
- {
- MaxSearchTime = myTime / 2;
- AbsoluteMaxSearchTime = (myTime > 3000)? (myTime - 500) : ((myTime * 3) / 4);
- }
- else
- {
- MaxSearchTime = myTime / Min(movesToGo, 20);
- AbsoluteMaxSearchTime = Min((4 * myTime) / movesToGo, myTime / 3);
- }
- }
+ calc_search_times(myTime, myIncrement, movesToGo, pos.startpos_ply_counter(), MaxSearchTime, AbsoluteMaxSearchTime);
if (get_option_value_bool("Ponder"))
{
isCheck = pos.is_check();
// Step 1. Initialize node (polling is omitted at root)
- ss->init();
+ ss->currentMove = ss->bestMove = MOVE_NONE;
// Step 2. Check for aborted search (omitted at root)
// Step 3. Mate distance pruning (omitted at root)
StateInfo st;
const TTEntry* tte;
Key posKey;
- Move ttMove, move, excludedMove;
+ Move ttMove, move, excludedMove, threatMove;
Depth ext, newDepth;
Value bestValue, value, oldAlpha;
Value refinedValue, nullValue, futilityValueScaled; // Non-PV specific
bool mateThreat = false;
int moveCount = 0;
int threadID = pos.thread();
- Move threatMove = MOVE_NONE;
refinedValue = bestValue = value = -VALUE_INFINITE;
oldAlpha = alpha;
// Step 1. Initialize node and poll. Polling can abort search
TM.incrementNodeCounter(threadID);
- ss->init();
- (ss+2)->initKillers();
+ ss->currentMove = ss->bestMove = threatMove = MOVE_NONE;
+ (ss+2)->killers[0] = (ss+2)->killers[1] = (ss+2)->mateKiller = MOVE_NONE;
if (threadID == 0 && ++NodesSincePoll > NodesBetweenPolls)
{
// Refresh tte entry to avoid aging
TT.store(posKey, tte->value(), tte->type(), tte->depth(), ttMove, tte->static_value(), tte->king_danger());
- ss->currentMove = ttMove; // Can be MOVE_NONE
+ ss->bestMove = ttMove; // Can be MOVE_NONE
return value_from_tt(tte->value(), ply);
}
if (nullValue == value_mated_in(ply + 2))
mateThreat = true;
- threatMove = (ss+1)->currentMove;
+ threatMove = (ss+1)->bestMove;
if ( depth < ThreatDepth
&& (ss-1)->reduction
&& connected_moves(pos, (ss-1)->currentMove, threatMove))
&& is_lower_bound(tte->type())
&& tte->depth() >= depth - 3 * OnePly;
+ // Avoid to do an expensive singular extension search on nodes where
+ // such search had already failed in the past.
+ if ( !PvNode
+ && singularExtensionNode
+ && depth < SingularExtensionDepth[PvNode] + 5 * OnePly)
+ {
+ TTEntry* ttx = TT.retrieve(pos.get_exclusion_key());
+ if (ttx && is_lower_bound(ttx->type()))
+ singularExtensionNode = false;
+ }
+
// Step 10. Loop through moves
// Loop through all legal moves until no moves remain or a beta cutoff occurs
while ( bestValue < beta
if (!PvNode && tte && ok_to_use_TT(tte, depth, beta, ply))
{
- ss->currentMove = ttMove; // Can be MOVE_NONE
+ ss->bestMove = ttMove; // Can be MOVE_NONE
return value_from_tt(tte->value(), ply);
}
ss->reduction = Depth(0);
if (i < 3)
- ss->initKillers();
+ ss->killers[0] = ss->killers[1] = ss->mateKiller = MOVE_NONE;
}
}
#endif
// Initialize global locks
- lock_init(&MPLock, NULL);
- lock_init(&WaitLock, NULL);
+ lock_init(&MPLock);
+ lock_init(&WaitLock);
#if !defined(_MSC_VER)
pthread_cond_init(&WaitCond, NULL);
// Initialize splitPoints[] locks
for (i = 0; i < MAX_THREADS; i++)
for (int j = 0; j < MAX_ACTIVE_SPLIT_POINTS; j++)
- lock_init(&(threads[i].splitPoints[j].lock), NULL);
+ lock_init(&(threads[i].splitPoints[j].lock));
// Will be set just before program exits to properly end the threads
AllThreadsShouldExit = false;
// Initialize search stack
init_ss_array(ss, PLY_MAX_PLUS_2);
- ss[0].init();
+ ss[0].currentMove = ss[0].bestMove = MOVE_NONE;
ss[0].eval = VALUE_NONE;
// Generate all legal moves