summaryrefslogtreecommitdiff
path: root/src/search.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/search.c')
-rwxr-xr-xsrc/search.c45
1 files changed, 40 insertions, 5 deletions
diff --git a/src/search.c b/src/search.c
index eb931bc..6e596ab 100755
--- a/src/search.c
+++ b/src/search.c
@@ -200,6 +200,7 @@ Search(IN SEARCHER_THREAD_CONTEXT *ctx,
DTEnterNode(ctx, uDepth, FALSE, iAlpha, iBeta);
iInitialAlpha = iAlpha;
pi->fPvNode = (iBeta != iAlpha + 1);
+ pi->fMovesRescoredByIID = FALSE;
ASSERT((IS_CHECKING_MOVE(mvLast) && (TRUE == pi->fInCheck)) ||
(!IS_CHECKING_MOVE(mvLast) && (FALSE == pi->fInCheck)));
@@ -413,13 +414,19 @@ Search(IN SEARCHER_THREAD_CONTEXT *ctx,
// EXPERIMENT: If we got no best move from the
// hash table and the best move we got from the
// generator looks crappy (i.e. is not a winning
- // or even capture/promotion) then rescore the
- // moves we generated at this ply using a
- // shallower search. "Internal Iterative
- // Deepening" or something like it.
+ // or even capture/promotion, AND not a killer --
+ // a killer move already proved itself elsewhere in
+ // the tree, unlike an untested quiet move, so it
+ // doesn't need IID's help) then rescore the moves
+ // we generated at this ply using a shallower
+ // search. "Internal Iterative Deepening" or
+ // something like it.
if ((iAlpha + 1 != iBeta) &&
(mvHash.uMove == 0) &&
(ctx->sMoveStack.mvf[x].iValue < SORT_THESE_FIRST) &&
+ (0 == (ctx->sMoveStack.mvf[x].iValue &
+ (FIRST_KILLER | SECOND_KILLER |
+ THIRD_KILLER | FOURTH_KILLER))) &&
(uDepth >= FOUR_PLY))
{
ASSERT(uDepth >= (IID_R_FACTOR + ONE_PLY));
@@ -457,7 +464,35 @@ Search(IN SEARCHER_THREAD_CONTEXT *ctx,
ASSERT(x >= ctx->sMoveStack.uBegin[ctx->uPly]);
if (uLegalMoves < SEARCH_SORT_LIMIT(ctx->uPly))
{
- SelectBestWithHistory(ctx, x);
+ // On an IID-rescored ply, mvf[].iValue holds a
+ // real, honest eval-axis score from an actual
+ // shallow search (see RescoreMovesViaSearch) --
+ // trust it outright, same principle as
+ // ComputeMoveScore's IID-trust branch. Two
+ // alternatives were measured and rejected (see
+ // RESULTS.md): blending history into the real
+ // score (scaled or capped) invents a new,
+ // leak-prone move-scoring axis on top of an
+ // already-crowded set (generate.c's ordering
+ // encoding, RescoreMovesViaSearch's real scores,
+ // root.c's own scheme) and measures no better
+ // than trusting the score outright; a pure
+ // tiebreak-on-exact-ties compromise still cost
+ // solves relative to full mixing, so it wasn't
+ // buying its complexity either. The branch lives
+ // here (once per selection call), not inside
+ // SelectBestWithHistory (once per candidate
+ // move in a hot per-node loop), to keep the
+ // overwhelmingly common non-rescored path at
+ // zero added cost.
+ if (TRUE == pi->fMovesRescoredByIID)
+ {
+ SelectBestNoHistory(ctx, x);
+ }
+ else
+ {
+ SelectBestWithHistory(ctx, x);
+ }
}
mv = ctx->sMoveStack.mvf[x].mv;
#ifdef DEBUG