summaryrefslogtreecommitdiff
path: root/src/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util.c')
-rwxr-xr-xsrc/util.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/src/util.c b/src/util.c
index b69a166..1bcfca9 100755
--- a/src/util.c
+++ b/src/util.c
@@ -991,6 +991,9 @@ FinishPVTailFromHash(SEARCHER_THREAD_CONTEXT *ctx,
MOVE mv;
ULONG uPly = ctx->uPly;
ULONG uLen;
+ ULONG u, uVisited = 0;
+ UINT64 u64Sig;
+ UINT64 u64VisitedSigs[MAX_PLY_PER_SEARCH];
#ifdef DEBUG
POSITION board;
memcpy(&board, &(ctx->sPosition), sizeof(POSITION));
@@ -999,6 +1002,29 @@ FinishPVTailFromHash(SEARCHER_THREAD_CONTEXT *ctx,
if (NULL == g_pHashTable) return;
do
{
+ // This tail is display-only (cosmetic) -- it walks hash-table
+ // best-moves one at a time with no relation to the real,
+ // backed-up search score printed alongside it (that score
+ // covers only the PV up to the <TT> marker). Unlike the real
+ // search, there's no natural depth bound here, so a drawish
+ // position whose hash entries chain back into each other (very
+ // common in king-shuffle endgames) can loop forever. Break on
+ // the first repeated position instead of relying on the output
+ // buffer filling up, which just produces a wall of repeated
+ // moves that looks like -- but has no actual bearing on --
+ // the printed score.
+ u64Sig = (ctx->sPosition.u64NonPawnSig ^ ctx->sPosition.u64PawnSig);
+ for (u = 0; u < uVisited; u++)
+ {
+ if (u64VisitedSigs[u] == u64Sig)
+ {
+ if (uLenRemain > 6) strcat(buf, "<REP>");
+ goto unmake;
+ }
+ }
+ ASSERT(uVisited < MAX_PLY_PER_SEARCH);
+ u64VisitedSigs[uVisited++] = u64Sig;
+
mv = GetPonderMove(&ctx->sPosition);
if (mv.uMove == 0) break;
PV[ctx->uPly] = mv;
@@ -1014,6 +1040,8 @@ FinishPVTailFromHash(SEARCHER_THREAD_CONTEXT *ctx,
}
while(1);
+ unmake:
+
//
// Unmake the moves
//