diff options
Diffstat (limited to 'src/dynamic.c')
| -rwxr-xr-x | src/dynamic.c | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/src/dynamic.c b/src/dynamic.c index c6e86e3..694fe50 100755 --- a/src/dynamic.c +++ b/src/dynamic.c @@ -289,10 +289,21 @@ Return value: { ctx->mvKillerEscapes[uPly][1] = ctx->mvKillerEscapes[uPly][0]; ctx->mvKillerEscapes[uPly][0] = mv; - if (ctx->mvKillerEscapes[uPly][1].uMove == 0) - { - ctx->mvKillerEscapes[uPly][1] = ctx->mvNullmoveRefutations[uPly]; - } + // No mvNullmoveQuietRefutations backfill here, unlike the + // regular killer table below: TryNullmovePruning asserts + // !InCheck() before probing, and a null move doesn't move + // any piece, so the move that refutes it is necessarily + // played from a position where the opponent was *not* in + // check either -- it can never legitimately be a check + // evasion. Backfilling with it here wouldn't be dead code + // the way the old capture-into-quiet-slot bug was (that + // was mathematically guaranteed to never match); since + // IS_SAME_MOVE ignores bvFlags, an ordinary quiet move + // from some unrelated non-check position could coincide + // with a real escaping candidate by cFrom/cTo/pMoved/ + // pCaptured/pPromoted alone and pick up an undeserved + // SECOND_KILLER bonus in evasion ordering. Leave the slot + // empty instead of risking that. } ASSERT(!IS_SAME_MOVE(ctx->mvKillerEscapes[uPly][0], ctx->mvKillerEscapes[uPly][1])); @@ -304,9 +315,9 @@ Return value: { ctx->mvKiller[uPly][1] = ctx->mvKiller[uPly][0]; ctx->mvKiller[uPly][0] = mv; - if (ctx->mvKiller[uPly][1].uMove == 0) + if (ctx->mvKiller[uPly][1].uMove == 0) { - ctx->mvKiller[uPly][1] = ctx->mvNullmoveRefutations[uPly]; + ctx->mvKiller[uPly][1] = ctx->mvNullmoveQuietRefutations[uPly]; } } ASSERT(!IS_SAME_MOVE(ctx->mvKiller[uPly][0], ctx->mvKiller[uPly][1])); |
