diff options
| author | Scott Gasch <[email protected]> | 2026-10-09 14:18:52 -0700 |
|---|---|---|
| committer | Scott Gasch <[email protected]> | 2026-10-09 14:18:52 -0700 |
| commit | fbdcb9d76dd2444d8bc631331eaeb9435cc247f8 (patch) | |
| tree | 602ab360462d6f23188ba51f962c4abb2dc6c7e5 /src/generate.c | |
| parent | 73b4afb12abf7cc442831dea42b41b63a2ce07be (diff) | |
* Grab bag of eval.c changes.
* Don't bother not hashing when moves are pruned.
* Prune moves move librerally with LMP.
Inexplicably, this is slightly shallower than HEAD (despite pruning
MORE). It may be because it is slightly slower.
It consistently beats HEAD in match_play.py though (3x now).
Diffstat (limited to 'src/generate.c')
| -rw-r--r-- | src/generate.c | 91 |
1 files changed, 25 insertions, 66 deletions
diff --git a/src/generate.c b/src/generate.c index 89796b4..fdfdc79 100644 --- a/src/generate.c +++ b/src/generate.c @@ -4740,40 +4740,35 @@ Return value: // sKillers[0].mv = ctx->mvKiller[uPly][0]; sKillers[0].uBonus = FIRST_KILLER; + sKillers[0].uBonus |= + (SORT_THESE_FIRST * (IS_KILLERMATE_MOVE(sKillers[0].mv) != 0)); sKillers[1].mv = ctx->mvKiller[uPly][1]; sKillers[1].uBonus = SECOND_KILLER; + sKillers[1].uBonus |= + (SORT_THESE_FIRST * (IS_KILLERMATE_MOVE(sKillers[1].mv) != 0)); sKillers[2].mv.uMove = sKillers[3].mv.uMove = 0; if (uPly > 1) { sKillers[2].mv = ctx->mvKiller[uPly - 2][0]; sKillers[2].uBonus = THIRD_KILLER; + sKillers[2].uBonus |= + (SORT_THESE_FIRST * (IS_KILLERMATE_MOVE(sKillers[2].mv) != 0)); sKillers[3].mv = ctx->mvKiller[uPly - 2][1]; sKillers[3].uBonus = FOURTH_KILLER; - } - sKillers[0].uBonus |= - (SORT_THESE_FIRST * (IS_KILLERMATE_MOVE(sKillers[0].mv) != 0)); - sKillers[1].uBonus |= - (SORT_THESE_FIRST * (IS_KILLERMATE_MOVE(sKillers[1].mv) != 0)); - sKillers[2].uBonus |= - (SORT_THESE_FIRST * (IS_KILLERMATE_MOVE(sKillers[2].mv) != 0)); - sKillers[3].uBonus |= - (SORT_THESE_FIRST * (IS_KILLERMATE_MOVE(sKillers[3].mv) != 0)); + sKillers[3].uBonus |= + (SORT_THESE_FIRST * (IS_KILLERMATE_MOVE(sKillers[3].mv) != 0)); - // EXPERIMENT: countermove-match tier. Precompute the previous - // move's countermove-table index once per node (mirrors killer - // precompute above) so the per-move loop below is just an - // IS_SAME_MOVE check, not a recompute. - fHaveCounterMove = FALSE; - if ((uPly > 0) && (0 != (ctx->sPlyInfo[uPly - 1]).mv.uMove)) - { - uCounterMoveIdx = MOVE_TO_INDEX((ctx->sPlyInfo[uPly - 1]).mv); - uCounterMoveContKey = MOVE_TO_CONT_KEY((ctx->sPlyInfo[uPly - 1]).mv); - fHaveCounterMove = TRUE; + // EXPERIMENT: countermove-match tier. Precompute the previous + // move's countermove-table index once per node (mirrors killer + // precompute above) so the per-move loop below is just an + // IS_SAME_MOVE check, not a recompute. + MOVE mvLast = (ctx->sPlyInfo[uPly - 1]).mv; + fHaveCounterMove = (0 != mvLast.uMove); + uCounterMoveIdx = MOVE_TO_INDEX(mvLast); + uCounterMoveContKey = MOVE_TO_CONT_KEY(mvLast); } - // // Score moves - // ASSERT(MOVE_COUNT(ctx, uPly) <= MAX_MOVES_PER_PLY); for (u = pStack->uBegin[uPly]; u < pStack->uEnd[uPly]; @@ -4846,25 +4841,6 @@ Return value: ASSERT(s > 0); ASSERT((s & STRIP_OFF_FLAGS) < VALUE_KING); } -#ifdef DEBUG - else - { - // 2026-10-04: no longer subtracts VALUE_KING here. - // That made this capture's stored iValue differ - // between DEBUG and release builds for no checked - // reason (the ASSERT it fed was tautological -- - // already true by construction, this being the - // else of `s >= 0` above) -- a silent landmine: - // ComputeMoveScore/DecodeMoveValueEstimate's - // MOVE_SCORING_NORMAL case trusts this value - // directly for a losing capture (MIN0(iRawValue)), - // so a DEBUG build fed EstimateHangingMaterialCp a - // ~VALUE_KING-inflated "hang" estimate for an - // ordinary losing capture, release builds never - // saw it. The real check is the bound just above. - ASSERT((s & STRIP_OFF_FLAGS) > -VALUE_KING); - } -#endif } // @@ -5073,8 +5049,8 @@ Return value: ASSERT(s >= SORT_THESE_FIRST); ASSERT(s > 0); ASSERT((s & STRIP_OFF_FLAGS) < VALUE_KING); - } - else if (s == 0) + } + else if (s == 0) { // Even capture -- can't be capturing w/ king ASSERT(!IS_KING(mv.pMoved)); @@ -5083,23 +5059,6 @@ Return value: s |= FIRST_KILLER; ASSERT(s > 0); } -#ifdef DEBUG - else - { - // Losing capture. No `s -= VALUE_KING` here -- - // same landmine, same fix as _ScoreAllMoves' twin - // of this block (2026-10-04): currently harmless in - // practice (DecodeMoveValueEstimate's - // MOVE_SCORING_ESCAPE case recomputes a capture's - // value straight from mv.pCaptured/mv.pMoved rather - // than trusting iValue), but there's no reason for - // this capture's stored iValue to differ between - // DEBUG and release builds when nothing checks the - // difference. - ASSERT(!IS_KING(mv.pMoved)); - ASSERT((s & STRIP_OFF_FLAGS) > -VALUE_KING); - } -#endif } // @@ -5117,7 +5076,7 @@ Return value: else { s = g_iPSQT[mv.pMoved][mv.cTo]; // 0..1000 - if (!IS_KING(mv.pMoved)) + if (!IS_KING(mv.pMoved)) { // 0..2400 s += (VALUE_QUEEN - PIECE_VALUE(mv.pMoved)) * 4; @@ -5128,21 +5087,23 @@ Return value: s |= THIRD_KILLER; ASSERT(s >= 0); } - else + else { // Losing block of check s -= VALUE_KING; ASSERT(s < 0); } - } + } else { // If the king is fleeing, encourage a spot next // to friendly pieces. + // + // TODO: does this matter enough for how slow it is? v = 0; do { c = mv.cTo + g_iQKDeltas[v++]; - if (IS_ON_BOARD(c)) + if (IS_ON_BOARD(c)) { p = pos->rgSquare[c].pPiece; s += _bonus[OPPOSITE_COLORS(pos->uToMove, p)] @@ -5150,7 +5111,7 @@ Return value: ASSERT(_bonus[OPPOSITE_COLORS(pos->uToMove, p)] [PIECE_TYPE(p)] >= 0); } - } + } while(g_iQKDeltas[v] != 0); } } @@ -5264,7 +5225,6 @@ Return value: // scoring scheme -- that check stays (it's shared with // _ScoreQSearchMovesNoChecks, which still needs it), it just // becomes unreachable here, which is harmless. - { ULONG uLiveEnd = pStack->uEnd[uPly]; u = pStack->uBegin[uPly]; while (u < uLiveEnd) @@ -5382,7 +5342,6 @@ Return value: } // next move pStack->uEnd[uPly] = uLiveEnd; - } } |
