Value search(Position& pos, SearchStack* ss, Value alpha, Value beta, Depth depth, int ply);
template <NodeType PvNode>
- inline Value search(Position& pos, SearchStack* ss, Value alpha, Value beta, Depth depth, int ply) {
- return search<PvNode, false>(pos, ss, alpha, beta, depth, ply);
- }
+ Value qsearch(Position& pos, SearchStack* ss, Value alpha, Value beta, Depth depth, int ply);
template <NodeType PvNode>
- Value qsearch(Position& pos, SearchStack* ss, Value alpha, Value beta, Depth depth, int ply);
+ inline Value search(Position& pos, SearchStack* ss, Value alpha, Value beta, Depth depth, int ply) {
+
+ return depth < ONE_PLY ? qsearch<PvNode>(pos, ss, alpha, beta, DEPTH_ZERO, ply)
+ : search<PvNode, false>(pos, ss, alpha, beta, depth, ply);
+ }
template <NodeType PvNode>
Depth extension(const Position& pos, Move m, bool captureOrPromotion, bool moveIsCheck, bool singleEvasion, bool mateThreat, bool* dangerous);
}
// Step 2. Check for aborted search and immediate draw
- if (AbortSearch || ThreadsMgr.thread_should_stop(threadID))
- return VALUE_DRAW;
-
- if (pos.is_draw() || ply >= PLY_MAX - 1)
+ if ( AbortSearch || ThreadsMgr.thread_should_stop(threadID)
+ || pos.is_draw() || ply >= PLY_MAX - 1)
return VALUE_DRAW;
// Step 3. Mate distance pruning
posKey = excludedMove ? pos.get_exclusion_key() : pos.get_key();
tte = TT.retrieve(posKey);
- ttMove = (tte ? tte->move() : MOVE_NONE);
+ ttMove = tte ? tte->move() : MOVE_NONE;
// At PV nodes, we don't use the TT for pruning, but only for move ordering.
// This is to avoid problems in the following areas:
// * Fifty move rule detection
// * Searching for a mate
// * Printing of full PV line
-
if (!PvNode && tte && ok_to_use_TT(tte, depth, beta, ply))
{
- // Refresh tte entry to avoid aging
- TT.store(posKey, tte->value(), tte->type(), tte->depth(), ttMove, tte->static_value(), tte->static_value_margin());
-
+ TT.refresh(tte);
ss->bestMove = ttMove; // Can be MOVE_NONE
return value_from_tt(tte->value(), ply);
}
pos.do_null_move(st);
(ss+1)->skipNullMove = true;
-
- nullValue = depth-R*ONE_PLY < ONE_PLY ? -qsearch<NonPV>(pos, ss+1, -beta, -alpha, DEPTH_ZERO, ply+1)
- : - search<NonPV>(pos, ss+1, -beta, -alpha, depth-R*ONE_PLY, ply+1);
+ nullValue = -search<NonPV>(pos, ss+1, -beta, -alpha, depth-R*ONE_PLY, ply+1);
(ss+1)->skipNullMove = false;
pos.undo_null_move();
// Initialize a MovePicker object for the current position
// FIXME currently MovePicker() c'tor is needless called also in SplitPoint
- MovePicker mpBase = MovePicker(pos, ttMove, depth, H, ss, (PvNode ? -VALUE_INFINITE : beta));
+ MovePicker mpBase(pos, ttMove, depth, H, ss, (PvNode ? -VALUE_INFINITE : beta));
MovePicker& mp = SpNode ? *sp->mp : mpBase;
CheckInfo ci(pos);
ss->bestMove = MOVE_NONE;
newDepth = depth - ONE_PLY + ext;
// Update current move (this must be done after singular extension search)
- movesSearched[moveCount++] = ss->currentMove = move;
+ movesSearched[moveCount] = ss->currentMove = move;
+
+ if (!SpNode)
+ moveCount++;
// Step 12. Futility pruning (is omitted in PV nodes)
if ( !PvNode
// Step extra. pv search (only in PV nodes)
// The first move in list is the expected PV
if (!SpNode && PvNode && moveCount == 1)
- value = newDepth < ONE_PLY ? -qsearch<PV>(pos, ss+1, -beta, -alpha, DEPTH_ZERO, ply+1)
- : - search<PV>(pos, ss+1, -beta, -alpha, newDepth, ply+1);
+ value = -search<PV>(pos, ss+1, -beta, -alpha, newDepth, ply+1);
else
{
// Step 14. Reduced depth search
{
alpha = SpNode ? sp->alpha : alpha;
Depth d = newDepth - ss->reduction;
- value = d < ONE_PLY ? -qsearch<NonPV>(pos, ss+1, -(alpha+1), -alpha, DEPTH_ZERO, ply+1)
- : - search<NonPV>(pos, ss+1, -(alpha+1), -alpha, d, ply+1);
+ value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, d, ply+1);
doFullDepthSearch = (value > alpha);
}
if (doFullDepthSearch)
{
alpha = SpNode ? sp->alpha : alpha;
- value = newDepth < ONE_PLY ? -qsearch<NonPV>(pos, ss+1, -(alpha+1), -alpha, DEPTH_ZERO, ply+1)
- : - search<NonPV>(pos, ss+1, -(alpha+1), -alpha, newDepth, ply+1);
+ value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, newDepth, ply+1);
// Step extra. pv search (only in PV nodes)
// Search only for possible new PV nodes, if instead value >= beta then
// parent node fails low with value <= alpha and tries another move.
if (PvNode && value > alpha && value < beta)
- value = newDepth < ONE_PLY ? -qsearch<PV>(pos, ss+1, -beta, -alpha, DEPTH_ZERO, ply+1)
- : - search<PV>(pos, ss+1, -beta, -alpha, newDepth, ply+1);
+ value = -search<PV>(pos, ss+1, -beta, -alpha, newDepth, ply+1);
}
}
if (value > bestValue && !(SpNode && ThreadsMgr.thread_should_stop(threadID)))
{
bestValue = value;
+
+ if (SpNode)
+ sp->bestValue = value;
+
if (value > alpha)
{
if (SpNode && (!PvNode || value >= beta))
sp->stopRequest = true;
if (PvNode && value < beta) // We want always alpha < beta
+ {
alpha = value;
+ if (SpNode)
+ sp->alpha = value;
+ }
if (value == value_mate_in(ply + 1))
ss->mateKiller = move;
ss->bestMove = move;
- }
- if (SpNode)
- {
- sp->bestValue = bestValue;
- sp->alpha = alpha;
- sp->parentSstack->bestMove = ss->bestMove;
+
+ if (SpNode)
+ sp->parentSstack->bestMove = move;
}
}
if (tsp->pvNode)
search<PV, true>(pos, ss, tsp->alpha, tsp->beta, tsp->depth, tsp->ply);
- else
+ else {
search<NonPV, true>(pos, ss, tsp->alpha, tsp->beta, tsp->depth, tsp->ply);
-
+ }
assert(threads[threadID].state == THREAD_SEARCHING);
threads[threadID].state = THREAD_AVAILABLE;
#if !defined(_MSC_VER)
pthread_t pthread[1];
ok = (pthread_create(pthread, NULL, init_thread, (void*)(&i)) == 0);
+ pthread_detach(pthread[0]);
#else
ok = (CreateThread(NULL, 0, init_thread, (LPVOID)(&i), 0, NULL) != NULL);
#endif
// split point objects), the function immediately returns. If splitting is
// possible, a SplitPoint object is initialized with all the data that must be
// copied to the helper threads and we tell our helper threads that they have
- // been assigned work. This will cause them to instantly leave their idle loops
- // and call sp_search(). When all threads have returned from sp_search() then
- // split() returns.
+ // been assigned work. This will cause them to instantly leave their idle loops and
+ // call search().When all threads have returned from search() then split() returns.
template <bool Fake>
void ThreadsManager::split(const Position& p, SearchStack* ss, int ply, Value* alpha,