diff options
Diffstat (limited to 'src/search.c')
| -rwxr-xr-x | src/search.c | 45 |
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 |
