// Initialize FIXME move before Rml.init()
TT.new_search();
H.clear();
- memset(ss, 0, PLY_MAX_PLUS_2 * sizeof(SearchStack));
+ memset(ss, 0, 4 * sizeof(SearchStack));
*ponderMove = bestMove = easyMove = MOVE_NONE;
depth = aspirationDelta = 0;
ss->currentMove = MOVE_NULL; // Hack to skip update_gains()
bestValue = alpha;
// Step 1. Initialize node and poll. Polling can abort search
- ss->currentMove = ss->bestMove = threatMove = MOVE_NONE;
+ ss->currentMove = ss->bestMove = threatMove = (ss+1)->excludedMove = MOVE_NONE;
+ (ss+1)->skipNullMove = false; (ss+1)->reduction = DEPTH_ZERO;
(ss+2)->killers[0] = (ss+2)->killers[1] = (ss+2)->mateKiller = MOVE_NONE;
if (threadID == 0 && ++NodesSincePoll > NodesBetweenPolls)
// Update current move (this must be done after singular extension search)
ss->currentMove = move;
- newDepth = depth - (!Root ? ONE_PLY : DEPTH_ZERO) + ext;
+ newDepth = depth - ONE_PLY + ext;
// Step 12. Futility pruning (is omitted in PV nodes)
if ( !PvNode
alpha = sp->alpha;
}
- if (!Root && value > bestValue && !(SpNode && ThreadsMgr.cutoff_at_splitpoint(threadID)))
+ if (value > bestValue && !(SpNode && ThreadsMgr.cutoff_at_splitpoint(threadID)))
{
bestValue = value;
if (SpNode)
sp->bestValue = value;
- if (value > alpha)
+ if (!Root && value > alpha)
{
if (PvNode && value < beta) // We want always alpha < beta
{
ss->bestMove = move;
if (SpNode)
- sp->parentSstack->bestMove = move;
+ sp->ss->bestMove = move;
}
}
if (Root)
{
- // To avoid to exit with bestValue == -VALUE_INFINITE
- if (value > bestValue)
- bestValue = value;
-
// Finished searching the move. If StopRequest is true, the search
// was aborted because the user interrupted the search or because we
// ran out of time. In this case, the return value of the search cannot
// Remember searched nodes counts for this move
mp.rm->nodes += pos.nodes_searched() - nodes;
- // Step 17. Check for new best move
- if (!isPvMove && value <= alpha)
- mp.rm->pv_score = -VALUE_INFINITE;
- else
+ // PV move or new best move ?
+ if (isPvMove || value > alpha)
{
- // PV move or new best move!
-
// Update PV
ss->bestMove = move;
mp.rm->pv_score = value;
alpha = Rml[Min(moveCount, MultiPV) - 1].pv_score; // FIXME why moveCount?
else if (value > alpha)
alpha = value;
+ }
+ else
+ mp.rm->pv_score = -VALUE_INFINITE;
- } // PV move or new best move
- }
+ } // Root
// Step 18. Check for split
if ( !Root
threads[threadID].state = THREAD_SEARCHING;
- // Here we call search() with SplitPoint template parameter set to true
+ // Copy SplitPoint position and search stack and call search()
+ // with SplitPoint template parameter set to true.
+ SearchStack ss[PLY_MAX_PLUS_2];
SplitPoint* tsp = threads[threadID].splitPoint;
Position pos(*tsp->pos, threadID);
- SearchStack* ss = tsp->sstack[threadID] + 1;
- ss->sp = tsp;
+
+ memcpy(ss, tsp->ss - 1, 4 * sizeof(SearchStack));
+ (ss+1)->sp = tsp;
if (tsp->pvNode)
- search<PV, true, false>(pos, ss, tsp->alpha, tsp->beta, tsp->depth, tsp->ply);
+ search<PV, true, false>(pos, ss+1, tsp->alpha, tsp->beta, tsp->depth, tsp->ply);
else
- search<NonPV, true, false>(pos, ss, tsp->alpha, tsp->beta, tsp->depth, tsp->ply);
+ search<NonPV, true, false>(pos, ss+1, tsp->alpha, tsp->beta, tsp->depth, tsp->ply);
assert(threads[threadID].state == THREAD_SEARCHING);
splitPoint.moveCount = moveCount;
splitPoint.pos = &pos;
splitPoint.nodes = 0;
- splitPoint.parentSstack = ss;
+ splitPoint.ss = ss;
for (i = 0; i < activeThreads; i++)
splitPoint.slaves[i] = 0;
lock_release(&mpLock);
// Tell the threads that they have work to do. This will make them leave
- // their idle loop. But before copy search stack tail for each thread.
+ // their idle loop.
for (i = 0; i < activeThreads; i++)
if (i == master || splitPoint.slaves[i])
{
- memcpy(splitPoint.sstack[i], ss - 1, 4 * sizeof(SearchStack));
-
assert(i == master || threads[i].state == THREAD_BOOKED);
threads[i].state = THREAD_WORKISWAITING; // This makes the slave to exit from idle_loop()