diff options
| author | Scott Gasch <[email protected]> | 2026-10-13 11:12:35 -0700 |
|---|---|---|
| committer | Scott Gasch <[email protected]> | 2026-10-13 11:12:35 -0700 |
| commit | 7400001fc2d43a507b54281f9860c60177860fe5 (patch) | |
| tree | 0ab8e3d1bd5fe54cc7f2883e38da67c3bfac36d8 /src/chess.h | |
| parent | 78881b8e6422b7980e5f71780ae4bed862b93e72 (diff) | |
Add 5D FH% joint table (improve axis) + beta-side static-null-move
table, wire up static null-move pruning; misc searchsup.c tuning;
--cpus=4 fix; multi-pool match_play.py openings.
data.c: g_uJointFHThousandths grows a 5th "improve" axis
([12][11][11][15] -> [12][11][11][16][11]); new
g_uBetaFHThousandths[12][21][11][11] table added. chess.h/searchsup.c/
search.c/split.c: minimal consumer wiring for the improve axis
(ImproveBucket(), extended _JointTablePredictedFHThousandths
signature/callers).
search.c: new static (score-only, no verification search) null-move
cutoff ahead of the existing real null-move check -- when iEval > iBeta
by enough that the new beta-side table predicts a real null-move
search would fail high with >95% confidence, take the cutoff on the
table's say-so instead of paying for the verification search.
searchsup.c: EstimateHangingMaterialCp now gives half credit when the
mover has an unrelated piece already flagged trapped at node entry;
bumped the SEE>=0 check extension from 3/4 ply to a full ply when the
opponent has significant material left; removed the "entering the
endgame extension" bonus (recapture extension and its window check
untouched).
main.c: accept "--opt=value" in addition to "--opt value" on the
command line (a bare "--cpus=4" used to silently fail to match and
leave uNumProcessors at its default of 1); also fixes a latent
off-by-one that could read one past the end of argv for a value-taking
flag given as the last command-line argument.
unix.c: brace-scoping cleanup around signal handler setup, no behavior
change.
eval_tune/match_play.py, test_vs_head.sh: sample opening positions from
multiple PGN pools (twic_filtered.pgn + lichess*.pgn) instead of one,
for more opening diversity in match-play testing.
Brought out of a larger stashed changeset one piece at a time, each
verified independently against a --cpus 1 / --cpus 4 ratio benchmark
to rule out the MP scaling regression that changeset originally
triggered (see SCOTT_IS_A_MORON.md) -- no regression reproduced in any
of the pieces here. Playing-strength impact measured as neutral via
self-play (170 games, llr=-0.04, score=0.500) despite ~1 ply deeper
average search. The stashed changeset's EFP margin rewrite, LMP
threshold rewrite, and a disabled null-move-skip experiment are
deliberately excluded -- those need their own careful, separate
commits and testing. The stash's eval.c retuning is abandoned (measured
~even/worse over a ~700-game overnight self-play run).
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Diffstat (limited to 'src/chess.h')
| -rwxr-xr-x | src/chess.h | 51 |
1 files changed, 48 insertions, 3 deletions
diff --git a/src/chess.h b/src/chess.h index 7e37245..91c6a0c 100755 --- a/src/chess.h +++ b/src/chess.h @@ -1007,6 +1007,24 @@ MOVE_STACK; #define GAP_CP_BUCKET_WIDTH (100) #define GAP_CP_BUCKETS (11) +// 2026-10-10: "improving" axis -- does (iEval - iEval two plies ago, +// same side to move) predict FH%? Signed and genuinely two-sided, so +// a symmetric 100cp-wide-bin shape around a center "no real change" +// bucket (index 5), with overflow buckets at both tails, matching +// HANG/GAP's own 11-bucket count. Added as g_uJointFHThousandths's +// 5th (trailing) axis -- see data.c. +#define IMPROVE_BUCKET_WIDTH (100) +#define IMPROVE_BUCKETS (11) +#define IMPROVE_CP_CENTER_WIDTH (100) // center bucket covers (-100, 100) + +// 2026-10-10: gap-above-beta, for the beta-side static-NM table -- +// gated on iEval > iBeta, so always >= 0, no symmetric/center bucket +// needed. Plain 100cp-wide bins from 0, wide enough (2000cp) to find +// where FH% actually saturates toward ~100%, with an overflow bucket +// past that. +#define GAP_BETA_BUCKET_WIDTH (100) +#define GAP_BETA_BUCKETS (21) // 0-99 .. 1900-1999, 20 == 2000cp+ overflow + // 2026-09-28: the "late axis" -- this move's own 1-based ordinal // position in the list of moves actually tried at this node // (uLegalMoves, right after MakeMove succeeds). Direct, unpaired @@ -1094,7 +1112,8 @@ MOVE_STACK; // COST of a wrong prune scales with remaining depth even where the rate // does not. // Shipped depth dimension of g_uJointFHThousandths (data.c declares it -// as [12][11][11][15]; the 12 is _ShipDepthBucket's range). +// as [12][11][11][16][11], including the 5th/improve axis; the 12 is +// _ShipDepthBucket's range). #define SHIP_DEPTH_BUCKETS (12) #define PRUNE_VERIFY_BANDS (8) // band edges, predicted FH in thousandths of a percent: @@ -1330,6 +1349,13 @@ typedef struct _COUNTERS #endif UINT64 u64NullMoves; UINT64 u64NullMoveSuccess; + + // 2026-10-10: static (score-only, no verification search) + // null-move cutoff, gated on iEval > iBeta and the beta-side + // FH% table (g_uBetaFHThousandths) predicting a cutoff with + // >95% confidence -- see search.c's fTryBetaPruningHere block. + UINT64 u64QuickNullMoves; + UINT64 u64QuickNullMoveSuccess; #ifdef TEST_NULL // Precision/recall calibration for the null-move try/avoid // decision. Indexed by _NullCalibBucketIndex() (search.c). @@ -3299,7 +3325,13 @@ extern BITBOARD g_KingAttacksBB[128]; // depth outermost for cache locality -- a whole node's move loop shares // one depth-slice (11*11*15 = 1,815 cells, ~3.5KB). Not yet consumed by // search.c -- phase 2 (LMR replacement) is a separate, later step. -extern USHORT g_uJointFHThousandths[12][11][11][15]; +extern USHORT g_uJointFHThousandths[12][11][11][16][11]; + +// 2026-10-10: beta-side (static-null-move) 4D FH% table -- see data.c's +// header. [depth][gapBeta][ownImprove][enemyImprove]. Cell stores the +// GAP TO 100% FH rate (thousandths of a percentage point), not FH% +// itself -- see _BetaTablePredictedFHThousandths's comment for why. +extern USHORT g_uBetaFHThousandths[12][21][11][11]; // 2026-09-15: king-ring bitboard split for _EvalKing's linear-SCORE // rewrite -- front/back mirror EmptyAttackedSquare's old color-dependent @@ -3857,11 +3889,24 @@ MoveNumBucket(ULONG uMoveNum); ULONG DepthBucket(ULONG uCandDepth); +ULONG +ImproveBucket(SCORE iImprovement); + +ULONG +GapBetaBucket(SCORE iGapBeta); + USHORT _JointTablePredictedFHThousandths(IN ULONG uRawDepthBucket, IN ULONG uRawDumbBucket, IN ULONG uRawGapBucket, - IN ULONG uRawLateBucket); + IN ULONG uRawLateBucket, + IN ULONG uRawImproveBucket); + +ULONG +_BetaTablePredictedFHThousandths(IN ULONG uRawDepthBucket, + IN ULONG uGapBetaBucket, + IN ULONG uOwnImproveBucket, + IN ULONG uEnemyImproveBucket); FLAG WeShouldTryNullmovePruning(IN SEARCHER_THREAD_CONTEXT *ctx, |
