mirror of
https://github.com/sockspls/badfish
synced 2025-04-30 08:43: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;
|
||||
|
||||
// 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
|
||||
// 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
|
||||
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
|
||||
|
@ -233,20 +233,13 @@ namespace {
|
|||
|
||||
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);
|
||||
|
||||
template <NodeType PvNode>
|
||||
template <NodeType NT>
|
||||
Value qsearch(Position& pos, SearchStack* ss, Value alpha, Value beta, Depth depth);
|
||||
|
||||
template <NodeType 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>
|
||||
template <bool PvNode>
|
||||
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);
|
||||
|
@ -304,8 +297,8 @@ void init_search() {
|
|||
{
|
||||
double pvRed = log(double(hd)) * log(double(mc)) / 3.0;
|
||||
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[NonPV][hd][mc] = (int8_t) (nonPVRed >= 1.0 ? floor(nonPVRed * int(ONE_PLY)) : 0);
|
||||
Reductions[1][hd][mc] = (int8_t) ( pvRed >= 1.0 ? floor( pvRed * int(ONE_PLY)) : 0);
|
||||
Reductions[0][hd][mc] = (int8_t) (nonPVRed >= 1.0 ? floor(nonPVRed * int(ONE_PLY)) : 0);
|
||||
}
|
||||
|
||||
// Init futility margins array
|
||||
|
@ -541,7 +534,7 @@ namespace {
|
|||
// research with bigger window until not failing high/low anymore.
|
||||
do {
|
||||
// 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
|
||||
// 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
|
||||
// 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) {
|
||||
|
||||
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(beta > alpha && beta <= VALUE_INFINITE);
|
||||
assert(PvNode || alpha == beta - 1);
|
||||
|
@ -703,7 +700,7 @@ namespace {
|
|||
threatMove = sp->threatMove;
|
||||
goto split_point_start;
|
||||
}
|
||||
else if (Root)
|
||||
else if (RootNode)
|
||||
bestValue = alpha;
|
||||
|
||||
// Step 1. Initialize node and poll. Polling can abort search
|
||||
|
@ -721,7 +718,7 @@ namespace {
|
|||
if (( StopRequest
|
||||
|| Threads[threadID].cutoff_occurred()
|
||||
|| pos.is_draw()
|
||||
|| ss->ply > PLY_MAX) && !Root)
|
||||
|| ss->ply > PLY_MAX) && !RootNode)
|
||||
return VALUE_DRAW;
|
||||
|
||||
// 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
|
||||
// a fail high/low. Biggest advantage at probing at PV nodes is to have a
|
||||
// smooth experience in analysis mode.
|
||||
if ( !Root
|
||||
if ( !RootNode
|
||||
&& tte
|
||||
&& (PvNode ? tte->depth() >= depth && tte->type() == VALUE_TYPE_EXACT
|
||||
: ok_to_use_TT(tte, depth, beta, ss->ply)))
|
||||
|
@ -821,7 +818,8 @@ namespace {
|
|||
|
||||
pos.do_null_move(st);
|
||||
(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;
|
||||
pos.undo_null_move();
|
||||
|
||||
|
@ -868,7 +866,7 @@ namespace {
|
|||
Depth d = (PvNode ? depth - 2 * ONE_PLY : depth / 2);
|
||||
|
||||
ss->skipNullMove = true;
|
||||
search<PvNode>(pos, ss, alpha, beta, d);
|
||||
search<PvNode ? PV : NonPV>(pos, ss, alpha, beta, d);
|
||||
ss->skipNullMove = false;
|
||||
|
||||
tte = TT.probe(posKey);
|
||||
|
@ -878,12 +876,12 @@ namespace {
|
|||
split_point_start: // At split points actual search starts from here
|
||||
|
||||
// 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);
|
||||
Bitboard pinned = pos.pinned_pieces(pos.side_to_move());
|
||||
ss->bestMove = MOVE_NONE;
|
||||
futilityBase = ss->eval + ss->evalMargin;
|
||||
singularExtensionNode = !Root
|
||||
singularExtensionNode = !RootNode
|
||||
&& !SpNode
|
||||
&& depth >= SingularExtensionDepth[PvNode]
|
||||
&& ttMove != MOVE_NONE
|
||||
|
@ -919,7 +917,7 @@ split_point_start: // At split points actual search starts from here
|
|||
else
|
||||
moveCount++;
|
||||
|
||||
if (Root)
|
||||
if (RootNode)
|
||||
{
|
||||
// This is used by time management
|
||||
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
|
||||
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);
|
||||
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
|
||||
// We illogically ignore reduction condition depth >= 3*ONE_PLY for predicted depth,
|
||||
// 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)
|
||||
+ 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)
|
||||
{
|
||||
// Aspiration window is disabled in multi-pv case
|
||||
if (Root && MultiPV > 1)
|
||||
if (RootNode && MultiPV > 1)
|
||||
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
|
||||
{
|
||||
|
@ -1072,8 +1071,8 @@ split_point_start: // At split points actual search starts from here
|
|||
if (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);
|
||||
}
|
||||
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;
|
||||
Value rAlpha = alpha - 300;
|
||||
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);
|
||||
ss->reduction = DEPTH_ZERO; // Restore original reduction
|
||||
}
|
||||
|
@ -1101,13 +1101,15 @@ split_point_start: // At split points actual search starts from here
|
|||
if (doFullDepthSearch)
|
||||
{
|
||||
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)
|
||||
// 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 && (Root || value < beta))
|
||||
value = -search<PV>(pos, ss+1, -beta, -alpha, newDepth);
|
||||
if (PvNode && value > alpha && (RootNode || value < beta))
|
||||
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)
|
||||
sp->bestValue = value;
|
||||
|
||||
if (!Root && value > alpha)
|
||||
if (!RootNode && value > alpha)
|
||||
{
|
||||
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
|
||||
// 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
|
||||
mp.rm->pv_score = -VALUE_INFINITE;
|
||||
|
||||
} // Root
|
||||
} // RootNode
|
||||
|
||||
// Step 18. Check for split
|
||||
if ( !Root
|
||||
if ( !RootNode
|
||||
&& !SpNode
|
||||
&& depth >= Threads.min_split_depth()
|
||||
&& 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,
|
||||
// less than ONE_PLY).
|
||||
|
||||
template <NodeType PvNode>
|
||||
template <NodeType NT>
|
||||
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(beta >= -VALUE_INFINITE && beta <= VALUE_INFINITE);
|
||||
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
|
||||
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);
|
||||
|
||||
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
|
||||
// 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.
|
||||
template <NodeType PvNode>
|
||||
template <bool PvNode>
|
||||
Depth extension(const Position& pos, Move m, bool captureOrPromotion,
|
||||
bool moveIsCheck, bool* dangerous) {
|
||||
|
||||
|
@ -2178,9 +2183,9 @@ void ThreadsManager::idle_loop(int threadID, SplitPoint* sp) {
|
|||
(ss+1)->sp = tsp;
|
||||
|
||||
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
|
||||
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);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue