summaryrefslogtreecommitdiff
path: root/src/split.c
diff options
context:
space:
mode:
authorScott Gasch <[email protected]>2026-08-30 18:51:38 -0700
committerScott Gasch <[email protected]>2026-08-30 18:51:38 -0700
commitdbf71219abeb51d386b0f7294f1664f2906d2b82 (patch)
tree77dc53e1cb3f223ee04a45130b559b08c91991cc /src/split.c
parentfd1460b2c135f6cef502fd167d1df0edf223e312 (diff)
Plumb iImprovement into LMR and futiltiy and parallel search.
Fix a bug (iEval) in HelpSearch This commit changes the heuristics for: nullmove pruning, LMR, and EFP slightly.
Diffstat (limited to 'src/split.c')
-rwxr-xr-xsrc/split.c87
1 files changed, 45 insertions, 42 deletions
diff --git a/src/split.c b/src/split.c
index 8bc4e60..b3fc659 100755
--- a/src/split.c
+++ b/src/split.c
@@ -246,7 +246,7 @@ Return value:
v++)
{
ctx->sMoveStack.mvf[v] = g_SplitInfo[u].mvf[v];
- ASSERT(SanityCheckMove(&ctx->sPosition,
+ ASSERT(SanityCheckMove(&ctx->sPosition,
g_SplitInfo[u].mvf[v].mv));
}
@@ -459,6 +459,7 @@ SCORE
StartParallelSearch(IN SEARCHER_THREAD_CONTEXT *ctx,
IN OUT SCORE *piAlpha,
IN SCORE iBeta,
+ IN SCORE iImprovement,
IN OUT SCORE *piBestScore,
IN OUT MOVE *pmvBest,
IN ULONG uMoveNum,
@@ -565,6 +566,8 @@ Return value:
memcpy(&(g_SplitInfo[u].sRootPosition),
GetRootPosition(),
sizeof(POSITION));
+ g_SplitInfo[u].iEval = ctx->sPlyInfo[ctx->uPly].iEval;
+ g_SplitInfo[u].iImprovement = iImprovement;
#if DEBUG
g_SplitInfo[u].uSplitPly = ctx->uPly;
memcpy(&(g_SplitInfo[u].sSplitPosition),
@@ -579,7 +582,7 @@ Return value:
// useless. Before we grab any helper threads, see if we
// need to bail out of this split.
//
- if (g_MoveTimer.bvFlags & TIMER_STOPPING)
+ if (g_MoveTimer.bvFlags & TIMER_STOPPING)
{
g_uNumSplitsAvailable++;
g_SplitInfo[u].uNumThreadsHelping = 0;
@@ -690,11 +693,11 @@ Return value:
// Update the context of the thread that is initiating the
// split with a pointer to the split info node we are using.
//
- for (uSplitNum = 0;
- uSplitNum < NUM_SPLIT_PTRS_IN_CONTEXT;
- uSplitNum++)
+ for (uSplitNum = 0;
+ uSplitNum < NUM_SPLIT_PTRS_IN_CONTEXT;
+ uSplitNum++)
{
- if (ctx->pSplitInfo[uSplitNum] == NULL)
+ if (ctx->pSplitInfo[uSplitNum] == NULL)
{
ctx->pSplitInfo[uSplitNum] = &(g_SplitInfo[u]);
break;
@@ -726,7 +729,7 @@ Return value:
if (g_fExitProgram) break;
}
- //
+ //
// Note: past this point we are the only ones using the
// split until we return it to the pool by making its
// refcount zero again.
@@ -848,7 +851,7 @@ Parameters:
MOVE mv : move it just searched
SCORE iScore : score of the move's subtree
ULONG u : split node number
-
+
Return value:
static void
@@ -856,13 +859,13 @@ Return value:
**/
{
ULONG v;
-
+
AcquireSpinLock(&(g_SplitInfo[u].uLock));
//
// See if this split is shutting down
//
- if (TRUE == g_SplitInfo[u].fTerminate)
+ if (TRUE == g_SplitInfo[u].fTerminate)
{
ReleaseSpinLock(&(g_SplitInfo[u].uLock));
return;
@@ -909,8 +912,8 @@ Return value:
}
-static void
-_SetFinalStats(IN SEARCHER_THREAD_CONTEXT *ctx,
+static void
+_SetFinalStats(IN SEARCHER_THREAD_CONTEXT *ctx,
IN ULONG u)
/**
@@ -934,13 +937,13 @@ Return value:
// Before we stop searching this node, update some stuff.
//
AcquireSpinLock(&(g_SplitInfo[u].uLock));
-
+
//
// Counters to persist in the main counter struct via the split.
//
- g_SplitInfo[u].sCounters.tree.u64TotalNodeCount +=
+ g_SplitInfo[u].sCounters.tree.u64TotalNodeCount +=
ctx->sCounters.tree.u64TotalNodeCount;
- g_SplitInfo[u].sCounters.tree.u64BetaCutoffs +=
+ g_SplitInfo[u].sCounters.tree.u64BetaCutoffs +=
ctx->sCounters.tree.u64BetaCutoffs;
g_SplitInfo[u].sCounters.tree.u64BetaCutoffsOnFirstMove +=
ctx->sCounters.tree.u64BetaCutoffsOnFirstMove;
@@ -954,11 +957,11 @@ Return value:
//
// TODO: Any other counters we care about?
//
-
+
//
// IDEA: Save the killers from this context to bring back to main
//
-
+
//
// Decrement threadcount in this split. Note: the main thread
// incremented it by two.
@@ -970,18 +973,18 @@ Return value:
}
-static MOVE
-_GetNextParallelMove(OUT SCORE *piAlpha,
- OUT SCORE *piBestScore,
+static MOVE
+_GetNextParallelMove(OUT SCORE *piAlpha,
+ OUT SCORE *piBestScore,
OUT ULONG *puMoveNumber,
IN ULONG u)
/**
-
+
Routine description:
Retrieve the next parallel move to search at the split node. Also
update alpha and bestscore.
-
+
Parameters:
SCORE *piAlpha : current alpha
@@ -995,7 +998,7 @@ Return value:
**/
{
MOVE mv = {0};
-
+
AcquireSpinLock(&(g_SplitInfo[u].uLock));
if (g_SplitInfo[u].fTerminate)
{
@@ -1012,7 +1015,7 @@ Return value:
#ifdef DEBUG
ASSERT(!(g_SplitInfo[u].mvf[g_SplitInfo[u].uOnDeckMove].bvFlags &
MVF_MOVE_SEARCHED));
- g_SplitInfo[u].mvf[g_SplitInfo[u].uOnDeckMove].bvFlags |=
+ g_SplitInfo[u].mvf[g_SplitInfo[u].uOnDeckMove].bvFlags |=
MVF_MOVE_SEARCHED;
ASSERT(mv.uMove);
ASSERT(SanityCheckMove(&g_SplitInfo[u].sSplitPosition, mv));
@@ -1029,8 +1032,8 @@ Return value:
}
-void
-HelpSearch(IN OUT SEARCHER_THREAD_CONTEXT *ctx,
+void
+HelpSearch(IN OUT SEARCHER_THREAD_CONTEXT *ctx,
IN ULONG u)
/**
@@ -1063,7 +1066,7 @@ Return value:
SCORE iCheckSee;
#ifdef DEBUG
POSITION board;
-
+
memcpy(&board, &ctx->sPosition, sizeof(POSITION));
ASSERT(PositionsAreEquivalent(&board, &g_SplitInfo[u].sSplitPosition));
#endif
@@ -1072,21 +1075,24 @@ Return value:
iBeta = g_SplitInfo[u].iBeta;
uOrigDepth = g_SplitInfo[u].uDepth;
ctx->sSearchFlags = g_SplitInfo[u].sSearchFlags;
+ SCORE iEval = g_SplitInfo[u].iEval;
+ SCORE iImprovement = g_SplitInfo[u].iImprovement;
+
do
{
iExtend = iOrigExtend;
uDepth = uOrigDepth;
ASSERT(ctx->uPly == g_SplitInfo[u].uSplitPly);
-
+
mv = _GetNextParallelMove(&iAlpha,
- &iBestScore,
+ &iBestScore,
&uMoveNum,
u);
if (mv.uMove == 0) break; // Split is terminating
ASSERT(IS_VALID_SCORE(iBestScore));
ASSERT(uMoveNum < MAX_MOVES_PER_PLY);
- ASSERT(IS_SAME_MOVE(mv,
+ ASSERT(IS_SAME_MOVE(mv,
ctx->sMoveStack.mvf[ctx->sMoveStack.uBegin[ctx->uPly]+uMoveNum].mv));
ASSERT(uDepth <= MAX_DEPTH_PER_SEARCH);
ASSERT(IS_VALID_SCORE(iAlpha));
@@ -1094,7 +1100,7 @@ Return value:
ASSERT(iAlpha < iBeta);
ASSERT(iExtend >= -ONE_PLY);
ASSERT(iExtend <= +ONE_PLY);
-
+
// SEE on the PRE-move position -- see search.c's identical comment.
iCheckSee = 0;
if (IS_CHECKING_MOVE(mv))
@@ -1105,25 +1111,21 @@ Return value:
uMoveNum);
}
- if (MakeMove(ctx, mv))
+ if (TRUE == MakeMove(ctx, mv))
{
- ASSERT((IS_CHECKING_MOVE(mv) &&
- InCheck(&ctx->sPosition, ctx->sPosition.uToMove)) ||
- (!IS_CHECKING_MOVE(mv) &&
- !InCheck(&ctx->sPosition, ctx->sPosition.uToMove)));
- iRoughEval = GetRoughEvalScore(ctx, iAlpha, iBeta, TRUE);
+ ASSERT((IS_CHECKING_MOVE(mv) && InCheck(&ctx->sPosition, ctx->sPosition.uToMove)) ||
+ (!IS_CHECKING_MOVE(mv) && !InCheck(&ctx->sPosition, ctx->sPosition.uToMove)));
// Compute extension
ComputeMoveExtension(ctx,
iAlpha,
iBeta,
- (ctx->sMoveStack.uBegin[ctx->uPly - 1] +
- uMoveNum),
- iRoughEval,
+ (ctx->sMoveStack.uBegin[ctx->uPly - 1] + uMoveNum),
+ iEval,
uDepth,
iCheckSee,
&iExtend);
-
+
//
// Cap total extension plies spent on this line, same as the
// non-split move loop in search.c does.
@@ -1139,9 +1141,10 @@ Return value:
// Decide how much (if any) to reduce this move's depth.
//
{
- INT iLMR = GetLMRReduction(iRoughEval,
+ INT iLMR = GetLMRReduction(iEval,
iAlpha,
iBeta,
+ iImprovement,
ctx,
uDepth,
(g_SplitInfo[u].uAlreadyDone +