From 9e995e7c39a83ae9b5ba86f3346e0281744bf773 Mon Sep 17 00:00:00 2001 From: Scott Gasch Date: Sat, 5 Sep 2026 21:52:40 -0700 Subject: King-safety recalibration, lazy-eval material floor, eval hot-path trimming Recalibrate iKingSwingP90 against the bitboard-rewritten CountKingSafetyDefects (~1.28B samples via new CALIBRATE_POSITIONAL/ CALIBRATE_BASE_MARGIN/CALIBRATE_MARGIN_SAFETY diagnostic build flags, board_representation/EVAL.md section 9). Add LAZY_EVAL_MIN_MATERIAL: measured the regular lazy exit's real swing exceeding its own assumed margin 20.6% of the time in near-bare-king endgames (vs <=0.36% elsewhere) -- skip lazy eval entirely below that material floor. Double the stale search.c/searchsup.c CountKingSafetyDefects extension thresholds as a stopgap pending their own recalibration. Eval hot-path trimming (measured via EVAL_TIME, ~1759 -> ~1386 avg cycles/eval on a representative middlegame position): - Pull _GetFileStormDefects out of EstimatePositionalScore's hot path (cost more than the "cheap cached lookup" it was assumed to be, running on ~90% of all Eval() calls). - Add pos->bbOccupiedSide[2], incrementally maintained alongside bbOccupied, so _BuildFriendlySideBB is a field read instead of a 6-term OR. - Switch CoorFromBitBoardRank8ToRank1/Rank1ToRank8 to the existing static-inline FastFirstBit/FastLastBit (same bsf/bsr instruction, no call/ret overhead). - Defer EvalPasserRaces' uRacerDist/fDontCountMeOut past its no-passer early return. - Remove the mailbox-era "max mobility in a row" term from _EvalBishop/_EvalRook (no bitboard-mobility equivalent need for it). - Simplify _EvalBishopPairs and rook file-openness/passer bonuses to flat DNA-tunable constants instead of distance/pawn-count-scaled tables, rook file-openness now a branchless bitboard-indexed lookup. - Remove pos->cPiece (write-only, no reader anywhere). - Collapse WHITE/BLACK mirror-branches (castle-rights block, rook-trapped-in-corner) to color-indexed constants. - Close the PAWN_BIT..KING_BIT gap (bits 7-3 -> bits 4-0), removing the bvPattern >>= 3 before its KING_COUNTER_BY_ATTACK_PATTERN lookup. This also fixes a real bug introduced earlier this session when _WhoControlsSquareFast was converted to read these constants directly: g_SwapTable is only [32][32], but the old bit values (up to 0xF8) indexed far out of bounds on any attacked square -- data.c's InitializeSwapTable was always built assuming the bits 0-4 range this change now actually produces. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01XxmVi2sTMwpPp4i6WYFjan --- src/move.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src/move.c') diff --git a/src/move.c b/src/move.c index 27d86df..1da5546 100755 --- a/src/move.c +++ b/src/move.c @@ -66,6 +66,8 @@ Return value: pos->bbPieces[c][PIECE_TYPE(p)] |= COOR_TO_BB(cTo); pos->bbOccupied &= ~COOR_TO_BB(cFrom); pos->bbOccupied |= COOR_TO_BB(cTo); + pos->bbOccupiedSide[c] &= ~COOR_TO_BB(cFrom); + pos->bbOccupiedSide[c] |= COOR_TO_BB(cTo); pos->u64NonPawnSig ^= g_u64SigSeeds[cFrom][PIECE_TYPE(p)][c]; pos->u64NonPawnSig ^= g_u64SigSeeds[cTo][PIECE_TYPE(p)][c]; #ifdef DEBUG @@ -127,6 +129,8 @@ Return value: pos->bbPawns[c] |= COOR_TO_BB(cTo); pos->bbOccupied &= ~COOR_TO_BB(cFrom); pos->bbOccupied |= COOR_TO_BB(cTo); + pos->bbOccupiedSide[c] &= ~COOR_TO_BB(cFrom); + pos->bbOccupiedSide[c] |= COOR_TO_BB(cTo); pos->u64PawnSig ^= g_u64PawnSigSeeds[cFrom][c]; pos->u64PawnSig ^= g_u64PawnSigSeeds[cTo][c]; pos->rgSquare[cTo].pPiece = p; @@ -183,6 +187,8 @@ Return value: pos->bbPieces[c][PIECE_TYPE(p)] |= COOR_TO_BB(cTo); pos->bbOccupied &= ~COOR_TO_BB(cFrom); pos->bbOccupied |= COOR_TO_BB(cTo); + pos->bbOccupiedSide[c] &= ~COOR_TO_BB(cFrom); + pos->bbOccupiedSide[c] |= COOR_TO_BB(cTo); pos->rgSquare[cTo].pPiece = p; pos->rgSquare[cTo].uIndex = uIndex; #ifdef DEBUG @@ -236,6 +242,8 @@ Return value: pos->bbPawns[c] |= COOR_TO_BB(cTo); pos->bbOccupied &= ~COOR_TO_BB(cFrom); pos->bbOccupied |= COOR_TO_BB(cTo); + pos->bbOccupiedSide[c] &= ~COOR_TO_BB(cFrom); + pos->bbOccupiedSide[c] |= COOR_TO_BB(cTo); pos->rgSquare[cTo].pPiece = p; pos->rgSquare[cTo].uIndex = uIndex; #ifdef DEBUG @@ -284,6 +292,7 @@ Return value: ASSERT(IS_VALID_PIECE(pLifted)); ASSERT(!IS_KING(pLifted)); pos->bbOccupied &= ~COOR_TO_BB(cSquare); + pos->bbOccupiedSide[GET_COLOR(pLifted)] &= ~COOR_TO_BB(cSquare); uIndex = pos->rgSquare[cSquare].uIndex; #ifdef DEBUG ASSERT(IS_VALID_PIECE_INDEX(uIndex)); @@ -420,6 +429,7 @@ Return value: ASSERT(IS_VALID_PIECE(pLifted)); ASSERT(!IS_KING(pLifted)); pos->bbOccupied &= ~COOR_TO_BB(cSquare); + pos->bbOccupiedSide[GET_COLOR(pLifted)] &= ~COOR_TO_BB(cSquare); uIndex = pos->rgSquare[cSquare].uIndex; #ifdef DEBUG @@ -544,6 +554,7 @@ Return value: pos->iMaterialBalance[FLIP(color)] -= pv; ASSERT(pos->iMaterialBalance[WHITE] * -1 == pos->iMaterialBalance[BLACK]); pos->bbOccupied |= COOR_TO_BB(cSquare); + pos->bbOccupiedSide[color] |= COOR_TO_BB(cSquare); if (IS_PAWN(pPiece)) { @@ -638,6 +649,7 @@ Return value: pos->iMaterialBalance[FLIP(color)] -= pv; ASSERT(pos->iMaterialBalance[WHITE] * -1 == pos->iMaterialBalance[BLACK]); pos->bbOccupied |= COOR_TO_BB(cSquare); + pos->bbOccupiedSide[color] |= COOR_TO_BB(cSquare); if (IS_PAWN(pPiece)) { -- cgit v1.3