diff options
| author | Scott Gasch <[email protected]> | 2026-08-27 07:41:41 -0700 |
|---|---|---|
| committer | Scott Gasch <[email protected]> | 2026-08-27 07:42:25 -0700 |
| commit | 4ce6a76b0946e4ba943d29c506c9e2fb00601efd (patch) | |
| tree | b072c6fe2a5e8527a28f5c821d76591e93fa86f6 /src/chess.h | |
| parent | 7857096f39e16619a42ee85b4aa593abd846b74a (diff) | |
Baseline: uPositional data-calibrated fix, enprise/trapped hints, EBF/beta-cutoff/counter-move stats, script.c FPE fix.
No LMR, no counter-move-driven move ordering (both explored separately,
kept out for now -- counter-move measured worse, ~655->647 solved on
ecm879 @ sn=4M with a leaner tree beforehand). Futility pruning restored.
Verified: 647/879 solved, EBF 4.609 @ sn=4M; 684/879 solved, EBF 3.995
@ 20s/move, 1cpu, 256m hash (typhoon_baseline.log).
The counter-move table is still written and its stats still tracked
(dynamic.c) for diagnostic purposes, but generate.c no longer reads it
for move ordering, so it has no effect on search behavior in this
commit.
lmr_testing/ holds the in-flight graded-LMR + counter-move code (not
applied here) with notes on what was already tried and measured, so a
future session can resume without re-deriving it.
Diffstat (limited to 'src/chess.h')
| -rwxr-xr-x | src/chess.h | 98 |
1 files changed, 62 insertions, 36 deletions
diff --git a/src/chess.h b/src/chess.h index d6d4fa4..9689189 100755 --- a/src/chess.h +++ b/src/chess.h @@ -808,6 +808,8 @@ typedef struct _COUNTERS UINT64 u64TerminalPositionCount; UINT64 u64BetaCutoffs; UINT64 u64BetaCutoffsOnFirstMove; + UINT64 u64CounterMoveTries; // valid counter-move slot existed + UINT64 u64CounterMoveHits; // ...and it was the move that won UINT64 u64NullMoves; UINT64 u64NullMoveSuccess; #ifdef TEST_NULL @@ -932,6 +934,8 @@ typedef struct _PLY_INFO INT iExtensionAmount; FLAG fInCheck; FLAG fInQsearch; + FLAG fPvNode; // this node's own window was wide + MOVE mv; MOVE mvBest; MOVE PV[MAX_PLY_PER_SEARCH]; @@ -997,6 +1001,16 @@ PAWN_HASH_ENTRY; #define NUM_SPLIT_PTRS_IN_CONTEXT (8) +// +// Counter-move table (Crafty-style): keyed by a hash of the *previous* +// move (whatever the opponent just played to reach this node), not by +// ply -- unlike killers, this generalizes across different branches +// that happen to share the same preceding move, anywhere in the tree. +// Sized to MOVE_TO_INDEX's full range so the index is exact, not a +// lossy hash. +// +#define COUNTER_MOVE_TABLE_SIZE (0x20000) + typedef struct _SEARCHER_THREAD_CONTEXT { ULONG uPly; // its distance from root @@ -1008,6 +1022,12 @@ typedef struct _SEARCHER_THREAD_CONTEXT MOVE mvKiller[MAX_PLY_PER_SEARCH][2]; MOVE mvKillerEscapes[MAX_PLY_PER_SEARCH][2]; MOVE mvNullmoveRefutations[MAX_PLY_PER_SEARCH]; + MOVE mvCounter[COUNTER_MOVE_TABLE_SIZE][2]; // counter-move table + UCHAR uCounterDepth[COUNTER_MOVE_TABLE_SIZE]; // ply depth slot 0 was set at + COOR cEnprise[MAX_PLY_PER_SEARCH][2]; // en prise piece hints + PIECE pEnprise[MAX_PLY_PER_SEARCH][2]; + COOR cTrapped[MAX_PLY_PER_SEARCH]; // trapped piece hint + PIECE pTrapped[MAX_PLY_PER_SEARCH]; COUNTERS sCounters; ULONG uThreadNumber; SPLIT_INFO *pSplitInfo[NUM_SPLIT_PTRS_IN_CONTEXT]; @@ -1074,6 +1094,10 @@ typedef struct _GAME_OPTIONS FLAG fShouldAnnounceOpening; SCORE iLastEvalScore; UINT64 u64NodesSearched; + UINT64 u64BetaCutoffs; + UINT64 u64BetaCutoffsOnFirstMove; + UINT64 u64CounterMoveTries; + UINT64 u64CounterMoveHits; CHAR szLogfile[SMALL_STRING_LEN_CHAR]; CHAR szEGTBPath[SMALL_STRING_LEN_CHAR]; CHAR szBookName[SMALL_STRING_LEN_CHAR]; @@ -1816,7 +1840,9 @@ TestMakeUnmakeMove(void); #define THIRD_KILLER (0x08000000) #define FOURTH_KILLER (0x04000000) #define GOOD_MOVE (0x02000000) -#define STRIP_OFF_FLAGS (0x00FFFFFF) +#define FIRST_COUNTER_MOVE (0x01000000) +#define SECOND_COUNTER_MOVE (0x00800000) +#define STRIP_OFF_FLAGS (0x007FFFFF) extern const int g_iQKDeltas[9]; extern const int g_iNDeltas[9]; @@ -2317,16 +2343,26 @@ ComputeMoveScore(IN SEARCHER_THREAD_CONTEXT *ctx, FLAG ThreadUnderTerminatingSplit(SEARCHER_THREAD_CONTEXT *); -FLAG -WeShouldDoHistoryPruning(IN SCORE iRoughEval, - IN SCORE iAlpha, - IN SCORE iBeta, - IN SEARCHER_THREAD_CONTEXT *ctx, - IN ULONG uRemainingDepth, - IN ULONG uLegalMoves, - IN MOVE mv, - IN ULONG uMoveNum, - IN INT iExtend); +// LMR reduction table -- built once at startup (InitLMRTable, dynamic.c), +// no floating point in the search hot path. [depth in plies][move number, +// clamped]. Value is a ply-fraction in ONE_PLY units, i.e. directly +// usable as a negative iExtend. +#define LMR_TABLE_MAX_MOVES (63) +extern SCORE g_iLMRQuietReduction[MAX_PLY_PER_SEARCH + 1][LMR_TABLE_MAX_MOVES + 1]; + +void +InitLMRTable(void); + +INT +GetLMRReduction(IN SCORE iRoughEval, + IN SCORE iAlpha, + IN SCORE iBeta, + IN SEARCHER_THREAD_CONTEXT *ctx, + IN ULONG uRemainingDepth, + IN ULONG uLegalMoves, + IN MOVE mv, + IN ULONG uMoveNum, + IN INT iExtend); FLAG WeShouldTryNullmovePruning(IN SEARCHER_THREAD_CONTEXT *ctx, @@ -2532,44 +2568,34 @@ void AnalyzeFullHashTable(void); // -// positionhash.c +// dynamic.c -- enprise/trapped piece hints // -// IDEA: store "mate threat" flag in here? -// IDEA: store "king safety" numbers in here? +// Ply-indexed, like killer moves: cheap, lock-free, thread-local hints +// about which piece(s) looked en prise or trapped the last time full +// Eval() (or a fail-high capture) ran at this ply. Not guaranteed +// fresh for the position currently at that ply -- readers must +// re-validate via the recorded PIECE still being on the recorded COOR +// before trusting it (RecordEnprisePiece/RecordTrappedPiece store +// both for exactly this reason). Nice-to-have only: pruning/ordering +// decisions must work correctly with none of this data available. // -typedef struct _POSITION_HASH_ENTRY { - UINT64 u64Sig; - UCHAR cEnprise[2]; - UCHAR uEnpriseCount[2]; - UCHAR cTrapped[2]; -} POSITION_HASH_ENTRY; - -void -InitializePositionHashSystem(void); - void -CleanupPositionHashSystem(void); +RecordEnprisePiece(SEARCHER_THREAD_CONTEXT *ctx, COOR cSquare); void -StoreEnprisePiece(POSITION *pos, COOR cSquare); +RecordEnprisePieceAtPly(SEARCHER_THREAD_CONTEXT *ctx, ULONG uPly, COOR cSquare); void -StoreTrappedPiece(POSITION *pos, COOR cSquare); - -COOR -GetEnprisePiece(POSITION *pos, ULONG uSide); - -ULONG -GetEnpriseCount(POSITION *pos, ULONG uSide); +RecordTrappedPiece(SEARCHER_THREAD_CONTEXT *ctx, COOR cSquare); COOR -GetTrappedPiece(POSITION *pos, ULONG uSide); +FindEnprisePiece(SEARCHER_THREAD_CONTEXT *ctx, ULONG uSide); ULONG -ValueOfMaterialInTroubleDespiteMove(POSITION *pos, ULONG uSide); +ValueOfMaterialInTroubleDespiteMove(SEARCHER_THREAD_CONTEXT *ctx, ULONG uSide); ULONG -ValueOfMaterialInTroubleAfterNull(POSITION *pos, ULONG uSide); +ValueOfMaterialInTroubleAfterNull(SEARCHER_THREAD_CONTEXT *ctx, ULONG uSide); // // pawnhash.c |
