mirror of
https://github.com/sockspls/badfish
synced 2025-05-01 01:03:09 +00:00
Unify search() template parameters
No functional change. Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This commit is contained in:
parent
853e2a9495
commit
013dc43d5d
1 changed files with 49 additions and 44 deletions
|
@ -47,7 +47,7 @@ namespace {
|
||||||
const bool FakeSplit = false;
|
const bool FakeSplit = false;
|
||||||
|
|
||||||
// Different node types, used as template parameter
|
// Different node types, used as template parameter
|
||||||
enum NodeType { NonPV, PV };
|
enum NodeType { Root, PV, NonPV, SplitPointPV, SplitPointNonPV };
|
||||||
|
|
||||||
// RootMove struct is used for moves at the root of the tree. For each root
|
// RootMove struct is used for moves at the root of the tree. For each root
|
||||||
// move, we store two scores, a node count, and a PV (really a refutation
|
// move, we store two scores, a node count, and a PV (really a refutation
|
||||||
|
@ -189,9 +189,9 @@ namespace {
|
||||||
// Reduction lookup tables (initialized at startup) and their access function
|
// Reduction lookup tables (initialized at startup) and their access function
|
||||||
int8_t Reductions[2][64][64]; // [pv][depth][moveNumber]
|
int8_t Reductions[2][64][64]; // [pv][depth][moveNumber]
|
||||||
|
|
||||||
template <NodeType PV> inline Depth reduction(Depth d, int mn) {
|
template <bool PvNode> inline Depth reduction(Depth d, int mn) {
|
||||||
|
|
||||||
return (Depth) Reductions[PV][Min(d / ONE_PLY, 63)][Min(mn, 63)];
|
return (Depth) Reductions[PvNode][Min(d / ONE_PLY, 63)][Min(mn, 63)];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Easy move margin. An easy move candidate must be at least this much
|
// Easy move margin. An easy move candidate must be at least this much
|
||||||
|
@ -233,20 +233,13 @@ namespace {
|
||||||
|
|
||||||
Move id_loop(Position& pos, Move searchMoves[], Move* ponderMove);
|
Move id_loop(Position& pos, Move searchMoves[], Move* ponderMove);
|
||||||
|
|
||||||
template <NodeType PvNode, bool SpNode, bool Root>
|
template <NodeType NT>
|
||||||
Value search(Position& pos, SearchStack* ss, Value alpha, Value beta, Depth depth);
|
Value search(Position& pos, SearchStack* ss, Value alpha, Value beta, Depth depth);
|
||||||
|
|
||||||
template <NodeType PvNode>
|
template <NodeType NT>
|
||||||
Value qsearch(Position& pos, SearchStack* ss, Value alpha, Value beta, Depth depth);
|
Value qsearch(Position& pos, SearchStack* ss, Value alpha, Value beta, Depth depth);
|
||||||
|
|
||||||
template <NodeType PvNode>
|
template <bool PvNode>
|
||||||
inline Value search(Position& pos, SearchStack* ss, Value alpha, Value beta, Depth depth) {
|
|
||||||
|
|
||||||
return depth < ONE_PLY ? qsearch<PvNode>(pos, ss, alpha, beta, DEPTH_ZERO)
|
|
||||||
: search<PvNode, false, false>(pos, ss, alpha, beta, depth);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <NodeType PvNode>
|
|
||||||
Depth extension(const Position& pos, Move m, bool captureOrPromotion, bool moveIsCheck, bool* dangerous);
|
Depth extension(const Position& pos, Move m, bool captureOrPromotion, bool moveIsCheck, bool* dangerous);
|
||||||
|
|
||||||
bool check_is_dangerous(Position &pos, Move move, Value futilityBase, Value beta, Value *bValue);
|
bool check_is_dangerous(Position &pos, Move move, Value futilityBase, Value beta, Value *bValue);
|
||||||
|
@ -304,8 +297,8 @@ void init_search() {
|
||||||
{
|
{
|
||||||
double pvRed = log(double(hd)) * log(double(mc)) / 3.0;
|
double pvRed = log(double(hd)) * log(double(mc)) / 3.0;
|
||||||
double nonPVRed = 0.33 + log(double(hd)) * log(double(mc)) / 2.25;
|
double nonPVRed = 0.33 + log(double(hd)) * log(double(mc)) / 2.25;
|
||||||
Reductions[PV][hd][mc] = (int8_t) ( pvRed >= 1.0 ? floor( pvRed * int(ONE_PLY)) : 0);
|
Reductions[1][hd][mc] = (int8_t) ( pvRed >= 1.0 ? floor( pvRed * int(ONE_PLY)) : 0);
|
||||||
Reductions[NonPV][hd][mc] = (int8_t) (nonPVRed >= 1.0 ? floor(nonPVRed * int(ONE_PLY)) : 0);
|
Reductions[0][hd][mc] = (int8_t) (nonPVRed >= 1.0 ? floor(nonPVRed * int(ONE_PLY)) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init futility margins array
|
// Init futility margins array
|
||||||
|
@ -541,7 +534,7 @@ namespace {
|
||||||
// research with bigger window until not failing high/low anymore.
|
// research with bigger window until not failing high/low anymore.
|
||||||
do {
|
do {
|
||||||
// Search starting from ss+1 to allow calling update_gains()
|
// Search starting from ss+1 to allow calling update_gains()
|
||||||
value = search<PV, false, true>(pos, ss+1, alpha, beta, depth * ONE_PLY);
|
value = search<Root>(pos, ss+1, alpha, beta, depth * ONE_PLY);
|
||||||
|
|
||||||
// Write PV back to transposition table in case the relevant entries
|
// Write PV back to transposition table in case the relevant entries
|
||||||
// have been overwritten during the search.
|
// have been overwritten during the search.
|
||||||
|
@ -663,9 +656,13 @@ namespace {
|
||||||
// all this work again. We also don't need to store anything to the hash table
|
// all this work again. We also don't need to store anything to the hash table
|
||||||
// here: This is taken care of after we return from the split point.
|
// here: This is taken care of after we return from the split point.
|
||||||
|
|
||||||
template <NodeType PvNode, bool SpNode, bool Root>
|
template <NodeType NT>
|
||||||
Value search(Position& pos, SearchStack* ss, Value alpha, Value beta, Depth depth) {
|
Value search(Position& pos, SearchStack* ss, Value alpha, Value beta, Depth depth) {
|
||||||
|
|
||||||
|
const bool PvNode = (NT == PV || NT == Root || NT == SplitPointPV);
|
||||||
|
const bool SpNode = (NT == SplitPointPV || NT == SplitPointNonPV);
|
||||||
|
const bool RootNode = (NT == Root);
|
||||||
|
|
||||||
assert(alpha >= -VALUE_INFINITE && alpha <= VALUE_INFINITE);
|
assert(alpha >= -VALUE_INFINITE && alpha <= VALUE_INFINITE);
|
||||||
assert(beta > alpha && beta <= VALUE_INFINITE);
|
assert(beta > alpha && beta <= VALUE_INFINITE);
|
||||||
assert(PvNode || alpha == beta - 1);
|
assert(PvNode || alpha == beta - 1);
|
||||||
|
@ -703,7 +700,7 @@ namespace {
|
||||||
threatMove = sp->threatMove;
|
threatMove = sp->threatMove;
|
||||||
goto split_point_start;
|
goto split_point_start;
|
||||||
}
|
}
|
||||||
else if (Root)
|
else if (RootNode)
|
||||||
bestValue = alpha;
|
bestValue = alpha;
|
||||||
|
|
||||||
// Step 1. Initialize node and poll. Polling can abort search
|
// Step 1. Initialize node and poll. Polling can abort search
|
||||||
|
@ -721,7 +718,7 @@ namespace {
|
||||||
if (( StopRequest
|
if (( StopRequest
|
||||||
|| Threads[threadID].cutoff_occurred()
|
|| Threads[threadID].cutoff_occurred()
|
||||||
|| pos.is_draw()
|
|| pos.is_draw()
|
||||||
|| ss->ply > PLY_MAX) && !Root)
|
|| ss->ply > PLY_MAX) && !RootNode)
|
||||||
return VALUE_DRAW;
|
return VALUE_DRAW;
|
||||||
|
|
||||||
// Step 3. Mate distance pruning
|
// Step 3. Mate distance pruning
|
||||||
|
@ -742,7 +739,7 @@ namespace {
|
||||||
// At PV nodes we check for exact scores, while at non-PV nodes we check for
|
// At PV nodes we check for exact scores, while at non-PV nodes we check for
|
||||||
// a fail high/low. Biggest advantage at probing at PV nodes is to have a
|
// a fail high/low. Biggest advantage at probing at PV nodes is to have a
|
||||||
// smooth experience in analysis mode.
|
// smooth experience in analysis mode.
|
||||||
if ( !Root
|
if ( !RootNode
|
||||||
&& tte
|
&& tte
|
||||||
&& (PvNode ? tte->depth() >= depth && tte->type() == VALUE_TYPE_EXACT
|
&& (PvNode ? tte->depth() >= depth && tte->type() == VALUE_TYPE_EXACT
|
||||||
: ok_to_use_TT(tte, depth, beta, ss->ply)))
|
: ok_to_use_TT(tte, depth, beta, ss->ply)))
|
||||||
|
@ -821,7 +818,8 @@ namespace {
|
||||||
|
|
||||||
pos.do_null_move(st);
|
pos.do_null_move(st);
|
||||||
(ss+1)->skipNullMove = true;
|
(ss+1)->skipNullMove = true;
|
||||||
nullValue = -search<NonPV>(pos, ss+1, -beta, -alpha, depth-R*ONE_PLY);
|
nullValue = depth-R*ONE_PLY < ONE_PLY ? -qsearch<NonPV>(pos, ss+1, -beta, -alpha, DEPTH_ZERO)
|
||||||
|
: - search<NonPV>(pos, ss+1, -beta, -alpha, depth-R*ONE_PLY);
|
||||||
(ss+1)->skipNullMove = false;
|
(ss+1)->skipNullMove = false;
|
||||||
pos.undo_null_move();
|
pos.undo_null_move();
|
||||||
|
|
||||||
|
@ -868,7 +866,7 @@ namespace {
|
||||||
Depth d = (PvNode ? depth - 2 * ONE_PLY : depth / 2);
|
Depth d = (PvNode ? depth - 2 * ONE_PLY : depth / 2);
|
||||||
|
|
||||||
ss->skipNullMove = true;
|
ss->skipNullMove = true;
|
||||||
search<PvNode>(pos, ss, alpha, beta, d);
|
search<PvNode ? PV : NonPV>(pos, ss, alpha, beta, d);
|
||||||
ss->skipNullMove = false;
|
ss->skipNullMove = false;
|
||||||
|
|
||||||
tte = TT.probe(posKey);
|
tte = TT.probe(posKey);
|
||||||
|
@ -878,12 +876,12 @@ namespace {
|
||||||
split_point_start: // At split points actual search starts from here
|
split_point_start: // At split points actual search starts from here
|
||||||
|
|
||||||
// Initialize a MovePicker object for the current position
|
// Initialize a MovePicker object for the current position
|
||||||
MovePickerExt<SpNode, Root> mp(pos, ttMove, depth, H, ss, (PvNode ? -VALUE_INFINITE : beta));
|
MovePickerExt<SpNode, RootNode> mp(pos, ttMove, depth, H, ss, (PvNode ? -VALUE_INFINITE : beta));
|
||||||
CheckInfo ci(pos);
|
CheckInfo ci(pos);
|
||||||
Bitboard pinned = pos.pinned_pieces(pos.side_to_move());
|
Bitboard pinned = pos.pinned_pieces(pos.side_to_move());
|
||||||
ss->bestMove = MOVE_NONE;
|
ss->bestMove = MOVE_NONE;
|
||||||
futilityBase = ss->eval + ss->evalMargin;
|
futilityBase = ss->eval + ss->evalMargin;
|
||||||
singularExtensionNode = !Root
|
singularExtensionNode = !RootNode
|
||||||
&& !SpNode
|
&& !SpNode
|
||||||
&& depth >= SingularExtensionDepth[PvNode]
|
&& depth >= SingularExtensionDepth[PvNode]
|
||||||
&& ttMove != MOVE_NONE
|
&& ttMove != MOVE_NONE
|
||||||
|
@ -919,7 +917,7 @@ split_point_start: // At split points actual search starts from here
|
||||||
else
|
else
|
||||||
moveCount++;
|
moveCount++;
|
||||||
|
|
||||||
if (Root)
|
if (RootNode)
|
||||||
{
|
{
|
||||||
// This is used by time management
|
// This is used by time management
|
||||||
FirstRootMove = (moveCount == 1);
|
FirstRootMove = (moveCount == 1);
|
||||||
|
@ -941,7 +939,7 @@ split_point_start: // At split points actual search starts from here
|
||||||
}
|
}
|
||||||
|
|
||||||
// At Root and at first iteration do a PV search on all the moves to score root moves
|
// At Root and at first iteration do a PV search on all the moves to score root moves
|
||||||
isPvMove = (PvNode && moveCount <= (Root ? depth <= ONE_PLY ? 1000 : MultiPV : 1));
|
isPvMove = (PvNode && moveCount <= (RootNode ? depth <= ONE_PLY ? 1000 : MultiPV : 1));
|
||||||
givesCheck = pos.move_gives_check(move, ci);
|
givesCheck = pos.move_gives_check(move, ci);
|
||||||
captureOrPromotion = pos.move_is_capture(move) || move_is_promotion(move);
|
captureOrPromotion = pos.move_is_capture(move) || move_is_promotion(move);
|
||||||
|
|
||||||
|
@ -999,7 +997,7 @@ split_point_start: // At split points actual search starts from here
|
||||||
// Value based pruning
|
// Value based pruning
|
||||||
// We illogically ignore reduction condition depth >= 3*ONE_PLY for predicted depth,
|
// We illogically ignore reduction condition depth >= 3*ONE_PLY for predicted depth,
|
||||||
// but fixing this made program slightly weaker.
|
// but fixing this made program slightly weaker.
|
||||||
Depth predictedDepth = newDepth - reduction<NonPV>(depth, moveCount);
|
Depth predictedDepth = newDepth - reduction<PvNode>(depth, moveCount);
|
||||||
futilityValueScaled = futilityBase + futility_margin(predictedDepth, moveCount)
|
futilityValueScaled = futilityBase + futility_margin(predictedDepth, moveCount)
|
||||||
+ H.gain(pos.piece_on(move_from(move)), move_to(move));
|
+ H.gain(pos.piece_on(move_from(move)), move_to(move));
|
||||||
|
|
||||||
|
@ -1049,10 +1047,11 @@ split_point_start: // At split points actual search starts from here
|
||||||
if (isPvMove)
|
if (isPvMove)
|
||||||
{
|
{
|
||||||
// Aspiration window is disabled in multi-pv case
|
// Aspiration window is disabled in multi-pv case
|
||||||
if (Root && MultiPV > 1)
|
if (RootNode && MultiPV > 1)
|
||||||
alpha = -VALUE_INFINITE;
|
alpha = -VALUE_INFINITE;
|
||||||
|
|
||||||
value = -search<PV>(pos, ss+1, -beta, -alpha, newDepth);
|
value = newDepth < ONE_PLY ? -qsearch<PV>(pos, ss+1, -beta, -alpha, DEPTH_ZERO)
|
||||||
|
: - search<PV>(pos, ss+1, -beta, -alpha, newDepth);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1072,8 +1071,8 @@ split_point_start: // At split points actual search starts from here
|
||||||
if (ss->reduction)
|
if (ss->reduction)
|
||||||
{
|
{
|
||||||
Depth d = newDepth - ss->reduction;
|
Depth d = newDepth - ss->reduction;
|
||||||
value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, d);
|
value = d < ONE_PLY ? -qsearch<NonPV>(pos, ss+1, -(alpha+1), -alpha, DEPTH_ZERO)
|
||||||
|
: - search<NonPV>(pos, ss+1, -(alpha+1), -alpha, d);
|
||||||
doFullDepthSearch = (value > alpha);
|
doFullDepthSearch = (value > alpha);
|
||||||
}
|
}
|
||||||
ss->reduction = DEPTH_ZERO; // Restore original reduction
|
ss->reduction = DEPTH_ZERO; // Restore original reduction
|
||||||
|
@ -1092,7 +1091,8 @@ split_point_start: // At split points actual search starts from here
|
||||||
ss->reduction = 3 * ONE_PLY;
|
ss->reduction = 3 * ONE_PLY;
|
||||||
Value rAlpha = alpha - 300;
|
Value rAlpha = alpha - 300;
|
||||||
Depth d = newDepth - ss->reduction;
|
Depth d = newDepth - ss->reduction;
|
||||||
value = -search<NonPV>(pos, ss+1, -(rAlpha+1), -rAlpha, d);
|
value = d < ONE_PLY ? -qsearch<NonPV>(pos, ss+1, -(rAlpha+1), -rAlpha, DEPTH_ZERO)
|
||||||
|
: - search<NonPV>(pos, ss+1, -(rAlpha+1), -rAlpha, d);
|
||||||
doFullDepthSearch = (value > rAlpha);
|
doFullDepthSearch = (value > rAlpha);
|
||||||
ss->reduction = DEPTH_ZERO; // Restore original reduction
|
ss->reduction = DEPTH_ZERO; // Restore original reduction
|
||||||
}
|
}
|
||||||
|
@ -1101,13 +1101,15 @@ split_point_start: // At split points actual search starts from here
|
||||||
if (doFullDepthSearch)
|
if (doFullDepthSearch)
|
||||||
{
|
{
|
||||||
alpha = SpNode ? sp->alpha : alpha;
|
alpha = SpNode ? sp->alpha : alpha;
|
||||||
value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, newDepth);
|
value = newDepth < ONE_PLY ? -qsearch<NonPV>(pos, ss+1, -(alpha+1), -alpha, DEPTH_ZERO)
|
||||||
|
: - search<NonPV>(pos, ss+1, -(alpha+1), -alpha, newDepth);
|
||||||
|
|
||||||
// Step extra. pv search (only in PV nodes)
|
// Step extra. pv search (only in PV nodes)
|
||||||
// Search only for possible new PV nodes, if instead value >= beta then
|
// Search only for possible new PV nodes, if instead value >= beta then
|
||||||
// parent node fails low with value <= alpha and tries another move.
|
// parent node fails low with value <= alpha and tries another move.
|
||||||
if (PvNode && value > alpha && (Root || value < beta))
|
if (PvNode && value > alpha && (RootNode || value < beta))
|
||||||
value = -search<PV>(pos, ss+1, -beta, -alpha, newDepth);
|
value = newDepth < ONE_PLY ? -qsearch<PV>(pos, ss+1, -beta, -alpha, DEPTH_ZERO)
|
||||||
|
: - search<PV>(pos, ss+1, -beta, -alpha, newDepth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1131,7 +1133,7 @@ split_point_start: // At split points actual search starts from here
|
||||||
if (SpNode)
|
if (SpNode)
|
||||||
sp->bestValue = value;
|
sp->bestValue = value;
|
||||||
|
|
||||||
if (!Root && value > alpha)
|
if (!RootNode && value > alpha)
|
||||||
{
|
{
|
||||||
if (PvNode && value < beta) // We want always alpha < beta
|
if (PvNode && value < beta) // We want always alpha < beta
|
||||||
{
|
{
|
||||||
|
@ -1153,7 +1155,7 @@ split_point_start: // At split points actual search starts from here
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Root)
|
if (RootNode)
|
||||||
{
|
{
|
||||||
// Finished searching the move. If StopRequest is true, the search
|
// Finished searching the move. If StopRequest is true, the search
|
||||||
// was aborted because the user interrupted the search or because we
|
// was aborted because the user interrupted the search or because we
|
||||||
|
@ -1192,10 +1194,10 @@ split_point_start: // At split points actual search starts from here
|
||||||
else
|
else
|
||||||
mp.rm->pv_score = -VALUE_INFINITE;
|
mp.rm->pv_score = -VALUE_INFINITE;
|
||||||
|
|
||||||
} // Root
|
} // RootNode
|
||||||
|
|
||||||
// Step 18. Check for split
|
// Step 18. Check for split
|
||||||
if ( !Root
|
if ( !RootNode
|
||||||
&& !SpNode
|
&& !SpNode
|
||||||
&& depth >= Threads.min_split_depth()
|
&& depth >= Threads.min_split_depth()
|
||||||
&& bestValue < beta
|
&& bestValue < beta
|
||||||
|
@ -1255,9 +1257,12 @@ split_point_start: // At split points actual search starts from here
|
||||||
// search function when the remaining depth is zero (or, to be more precise,
|
// search function when the remaining depth is zero (or, to be more precise,
|
||||||
// less than ONE_PLY).
|
// less than ONE_PLY).
|
||||||
|
|
||||||
template <NodeType PvNode>
|
template <NodeType NT>
|
||||||
Value qsearch(Position& pos, SearchStack* ss, Value alpha, Value beta, Depth depth) {
|
Value qsearch(Position& pos, SearchStack* ss, Value alpha, Value beta, Depth depth) {
|
||||||
|
|
||||||
|
const bool PvNode = (NT == PV);
|
||||||
|
|
||||||
|
assert(NT == PV || NT == NonPV);
|
||||||
assert(alpha >= -VALUE_INFINITE && alpha <= VALUE_INFINITE);
|
assert(alpha >= -VALUE_INFINITE && alpha <= VALUE_INFINITE);
|
||||||
assert(beta >= -VALUE_INFINITE && beta <= VALUE_INFINITE);
|
assert(beta >= -VALUE_INFINITE && beta <= VALUE_INFINITE);
|
||||||
assert(PvNode || alpha == beta - 1);
|
assert(PvNode || alpha == beta - 1);
|
||||||
|
@ -1417,7 +1422,7 @@ split_point_start: // At split points actual search starts from here
|
||||||
|
|
||||||
// Make and search the move
|
// Make and search the move
|
||||||
pos.do_move(move, st, ci, givesCheck);
|
pos.do_move(move, st, ci, givesCheck);
|
||||||
value = -qsearch<PvNode>(pos, ss+1, -beta, -alpha, depth-ONE_PLY);
|
value = -qsearch<NT>(pos, ss+1, -beta, -alpha, depth-ONE_PLY);
|
||||||
pos.undo_move(move);
|
pos.undo_move(move);
|
||||||
|
|
||||||
assert(value > -VALUE_INFINITE && value < VALUE_INFINITE);
|
assert(value > -VALUE_INFINITE && value < VALUE_INFINITE);
|
||||||
|
@ -1596,7 +1601,7 @@ split_point_start: // At split points actual search starts from here
|
||||||
// any case are marked as 'dangerous'. Note that also if a move is not
|
// any case are marked as 'dangerous'. Note that also if a move is not
|
||||||
// extended, as example because the corresponding UCI option is set to zero,
|
// extended, as example because the corresponding UCI option is set to zero,
|
||||||
// the move is marked as 'dangerous' so, at least, we avoid to prune it.
|
// the move is marked as 'dangerous' so, at least, we avoid to prune it.
|
||||||
template <NodeType PvNode>
|
template <bool PvNode>
|
||||||
Depth extension(const Position& pos, Move m, bool captureOrPromotion,
|
Depth extension(const Position& pos, Move m, bool captureOrPromotion,
|
||||||
bool moveIsCheck, bool* dangerous) {
|
bool moveIsCheck, bool* dangerous) {
|
||||||
|
|
||||||
|
@ -2178,9 +2183,9 @@ void ThreadsManager::idle_loop(int threadID, SplitPoint* sp) {
|
||||||
(ss+1)->sp = tsp;
|
(ss+1)->sp = tsp;
|
||||||
|
|
||||||
if (tsp->pvNode)
|
if (tsp->pvNode)
|
||||||
search<PV, true, false>(pos, ss+1, tsp->alpha, tsp->beta, tsp->depth);
|
search<SplitPointPV>(pos, ss+1, tsp->alpha, tsp->beta, tsp->depth);
|
||||||
else
|
else
|
||||||
search<NonPV, true, false>(pos, ss+1, tsp->alpha, tsp->beta, tsp->depth);
|
search<SplitPointNonPV>(pos, ss+1, tsp->alpha, tsp->beta, tsp->depth);
|
||||||
|
|
||||||
assert(threads[threadID].state == Thread::SEARCHING);
|
assert(threads[threadID].state == Thread::SEARCHING);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue