1
0
Fork 0
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:
Marco Costalba 2011-05-28 12:13:42 +01:00
parent 853e2a9495
commit 013dc43d5d

View file

@ -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);