summaryrefslogtreecommitdiff
path: root/src/chess.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/chess.h')
-rwxr-xr-xsrc/chess.h161
1 files changed, 111 insertions, 50 deletions
diff --git a/src/chess.h b/src/chess.h
index 702defb..78c0f94 100755
--- a/src/chess.h
+++ b/src/chess.h
@@ -941,19 +941,9 @@ typedef struct _COUNTERS
UINT64 u64AvoidNullSuccess;
UINT64 u64AvoidNullFailures;
#endif
- UINT64 u64EvalHashHits;
UINT64 u64LazyEvals;
- UINT64 u64FullEvals;
- // Placeholder counters for root.c's per-tier eval-exit
- // reporting -- eval.c's super-lazy exit itself hasn't been
- // re-applied yet (see stash), so these always read 0 for now;
- // that's accurate, not a stub bug, since no super-lazy exit
- // exists in this build to increment them.
UINT64 u64SuperLazyEvals;
- UINT64 u64CyclesSuperLazyExit;
- UINT64 u64CyclesLazyExit;
- UINT64 u64CyclesFullEvalExit;
- UINT64 u64CyclesEvalSuperLazy;
+ UINT64 u64FullEvals;
UINT64 u64CyclesInEval;
//
@@ -1021,6 +1011,30 @@ typedef struct _COUNTERS
UINT64 u64CyclesEvalLazyDecision;
UINT64 u64CyclesEvalCountKingSafetyDefects;
UINT64 u64CyclesEvalFileStormDefects;
+
+ //
+ // 2026-09-07: the super-lazy exit (eval.c, before the regular
+ // LAZY_EVAL block) is a much cheaper material-only check than
+ // the regular lazy decision, so it gets its own cycle counter
+ // rather than folding into u64CyclesEvalLazyDecision -- a hit
+ // here never reaches the regular lazy-decision code at all.
+ //
+ UINT64 u64CyclesEvalSuperLazy;
+
+ // Per-exit-path *total call cost*, i.e. the full entry-to-exit
+ // elapsed time for a call that left via that path -- not to be
+ // confused with the sub-timers above, which measure a single
+ // segment's cost regardless of how the call eventually exited.
+ // These three are mutually exclusive by construction (each
+ // Eval() call adds to exactly one) and sum to u64CyclesInEval,
+ // so u64CyclesInEval / (u64SuperLazyEvals + u64LazyEvals +
+ // u64FullEvals) is a real overall average, and each bucket
+ // divided by its own matching count (u64SuperLazyEvals,
+ // u64LazyEvals, u64FullEvals) gives a clean per-path average --
+ // see root.c's eval-exit-breakdown report.
+ UINT64 u64CyclesSuperLazyExit;
+ UINT64 u64CyclesLazyExit;
+ UINT64 u64CyclesFullEvalExit;
}
tree;
@@ -1241,6 +1255,24 @@ typedef struct _SEARCHER_THREAD_CONTEXT
// called on.
FLAG fCalibrateCandidate;
#endif
+ // Which Eval() exit tier supplied the piPositional value most
+ // recently returned to this thread -- set inside Eval() itself
+ // (all three exit points), read right after the Eval() call in
+ // QSearch. Was CALIBRATE_QSEARCH_FUTILITY-only; promoted to
+ // unconditional 2026-09-08 since QSearch's real futility margin
+ // now indexes FUTILITY_BASE_MARGIN_BY_SOURCE with it, not just
+ // the calibration harness. See EVAL_POSITIONAL_SOURCE_* below.
+ ULONG uLastPositionalSource;
+#ifdef CALIBRATE_QSEARCH_FUTILITY
+ // TRUE for the duration of a diagnostic "what if we hadn't pruned
+ // this move" re-search -- search.c's qsearch futility gate checks
+ // this and forces iFutility wide open so the diagnostic subtree
+ // itself isn't contaminated by the same pruning being measured.
+ // Never set recursively: a rejection can't occur while this is
+ // already TRUE (iFutility being wide open means nothing gets
+ // rejected), so there's no risk of runaway nested diagnosis.
+ FLAG fDiagUnprunedSubtree;
+#endif
CHAR szLastPV[SMALL_STRING_LEN_CHAR];
}
SEARCHER_THREAD_CONTEXT;
@@ -2820,14 +2852,27 @@ IsDraw(SEARCHER_THREAD_CONTEXT *ctx);
// search.c
//
#define QPLIES_OF_NON_CAPTURE_CHECKS (2)
-#define FUTILITY_BASE_MARGIN (50)
-// Compatibility aliases for root.c/main.c's per-tier reporting, which
-// expects these three names -- search.c hasn't been split into
-// per-tier margins yet (still one flat FUTILITY_BASE_MARGIN), so all
-// three alias the same value until that split is re-applied.
-#define FUTILITY_BASE_MARGIN_FULL FUTILITY_BASE_MARGIN
-#define FUTILITY_BASE_MARGIN_LAZY FUTILITY_BASE_MARGIN
-#define FUTILITY_BASE_MARGIN_SUPERLAZY FUTILITY_BASE_MARGIN
+
+// Which Eval() exit tier supplied a given piPositional value --
+// SEARCHER_THREAD_CONTEXT.uLastPositionalSource above. Was diagnostic-
+// only (CALIBRATE_QSEARCH_FUTILITY); promoted to unconditional
+// 2026-09-08 once FUTILITY_BASE_MARGIN_BY_SOURCE (search.c) made it
+// load-bearing for real search behavior, not just measurement.
+#define EVAL_POSITIONAL_SOURCE_FULL (0)
+#define EVAL_POSITIONAL_SOURCE_LAZY (1)
+#define EVAL_POSITIONAL_SOURCE_SUPERLAZY (2)
+#define EVAL_POSITIONAL_SOURCE_COUNT (3)
+
+// Per-tier qsearch futility base margins -- see search.c's
+// FUTILITY_BASE_MARGIN_BY_SOURCE for the full derivation. Named here
+// (rather than only as array entries in search.c) so eval.c's
+// piPositional floor -- which only ever applies on the full-eval
+// exit -- can reference the matching tier's constant directly instead
+// of a stale flat value.
+#define FUTILITY_BASE_MARGIN_FULL (450)
+#define FUTILITY_BASE_MARGIN_LAZY (225)
+#define FUTILITY_BASE_MARGIN_SUPERLAZY (275)
+
// Measured: disabling this entirely (see lmr_testing/RESULTS.md) is a
// clear net loss across ringers/confident_quick/hard_quick, so IID itself
// is load-bearing. The "is the top move crappy" gate in search.c's DO_IID
@@ -3144,7 +3189,7 @@ PawnHashLookup(SEARCHER_THREAD_CONTEXT *ctx);
//
#define LAZY_EVAL
#define LAZE_EVAL_BASE_SCORE 10
-#define LAZY_EVAL_BASE_MARGIN (75) // cheap material-only lazy exit margin;
+#define LAZY_EVAL_BASE_MARGIN (75) // cheap material-only lazy exit margin;
// widened by EstimatePositionalScore
// if this isn't enough on its own
// board_representation/EVAL.md section 9 (2026-09-06): below this
@@ -3162,13 +3207,6 @@ PawnHashLookup(SEARCHER_THREAD_CONTEXT *ctx);
extern const int g_iAhead[2];
extern const int g_iBehind[2];
-// No-op placeholder: eval.c's ROOK_FULL_HALF_OPEN_BONUS static cache
-// (the thing InitEval() is meant to (re)build, called at startup and
-// after every DNA reload) hasn't been re-applied yet -- see stash.
-// Nothing to initialize until that cache exists.
-void
-InitEval(void);
-
ULONG
DNABufferSizeBytes();
@@ -3184,14 +3222,15 @@ ImportEvalDNA(char *p);
FLAG
ReadEvalDNA(char *szFilename);
-
+void
+InitEval();
SCORE
-Eval(SEARCHER_THREAD_CONTEXT *, SCORE, SCORE, SCORE *);
+Eval(SEARCHER_THREAD_CONTEXT *, SCORE, SCORE, SCORE (*)[2]);
FLAG
_EvalPasserRacesAgainstLoneKings(POSITION *,
- PAWN_HASH_ENTRY *);
+ PAWN_HASH_ENTRY *);
ULONG
CountKingSafetyDefects(POSITION *pos,
@@ -3212,6 +3251,22 @@ void
DumpMarginSafetyCalibration(void);
#endif
+#ifdef CALIBRATE_QSEARCH_FUTILITY
+// Which futility gate in _ShouldWeConsiderThisMove rejected a move --
+// see search.c's _QFutRecordSample. The recapture gate (used to be
+// QFUT_GATE_RECAPTURE) was retired 2026-09-08 along with the +100
+// recapture bonus itself -- see the "recapture-shaped" comment in
+// _ShouldWeConsiderThisMove for why (fRecaptureShaped never checked
+// mv.cTo == mvLast.cTo, so it wasn't testing real recaptures).
+#define QFUT_GATE_GENERIC_CAPTURE (0)
+#define QFUT_GATE_CHECK_ROOK (1)
+#define QFUT_GATE_CHECK_BISHOP (2)
+#define QFUT_GATE_COUNT (3)
+
+void
+DumpQSearchFutilityCalibration(void);
+#endif
+
//
// testeval.c
//
@@ -3352,22 +3407,13 @@ ParallelCompareUlong(ULONG uComparand, void *pComparators);
ULONG CDECL
ParallelCompareVector(void *pComparand, void *pComparators);
-void CDECL
-GetAttacks(SEE_LIST *pList,
- POSITION *pos,
- COOR cSquare,
- ULONG uSide);
-
-void CDECL
-SlowGetAttacks(SEE_LIST *pList,
- POSITION *pos,
- COOR cSquare,
- ULONG uSide);
-
-// board_representation/MIGRATION.md section 3: bbPieces/bbPawns-backed
-// GetAttacks primitive, verified correct (20,000-position sweep) and
-// faster than asm GetAttacks (0.53-0.89x cycles/call across
-// opening/middlegame/endgame -- see section 3's benchmark writeup).
+// board_representation/MIGRATION.md sections 3/6/7: bbPieces/bbPawns-
+// backed GetAttacks primitive. Verified correct (20,000-position
+// sweep) and faster than the old mailbox implementation (0.53-0.89x
+// cycles/call across opening/middlegame/endgame). Now the only
+// GetAttacks implementation -- the old asm/CROUTINES mailbox versions
+// (SlowGetAttacks, asm GetAttacks) were retired 2026-09-06 once all of
+// section 7's retirement criteria cleared.
void CDECL
_GetAttacksBB(SEE_LIST *pList,
POSITION *pos,
@@ -3386,10 +3432,9 @@ _WhoAttacksSquareBB(POSITION *pos,
BITBOARD bbOccupied);
// _GetAttacksBB is the only implementation as of 2026-09-06 (see
-// MIGRATION.md section 6) -- verified correct and faster than the old
-// asm/CROUTINES mailbox versions (SlowGetAttacks, asm GetAttacks),
-// which have been retired. Every call site written against the name
-// "GetAttacks" didn't need touching when the default changed.
+// MIGRATION.md section 7) -- this macro exists only so call sites
+// written against the name "GetAttacks" didn't need touching when the
+// old asm/CROUTINES mailbox versions were retired.
#define GetAttacks _GetAttacksBB
#ifdef _X86_
@@ -3596,6 +3641,12 @@ COMMAND(BenchCommand);
void
TestDraw(void);
+void
+TestRecogn(void);
+
+void
+TestRecognExhaustiveKNKP(void);
+
//
// probe.c
//
@@ -3683,6 +3734,16 @@ RecognLookup(SEARCHER_THREAD_CONTEXT *ctx,
SCORE *piScore,
FLAG fProbeEGTB);
+//
+// Unregistered/experimental recognizers, exposed only so testrecogn.c
+// can exhaustively validate a candidate before it's ever re-registered
+// in InitializeInteriorNodeRecognizers. Not reachable from the normal
+// RecognLookup dispatch path.
+//
+ULONG
+_RecognizeKNKP(SEARCHER_THREAD_CONTEXT *ctx,
+ SCORE *piScore);
+
SCORE
GetRoughEvalScore(IN SEARCHER_THREAD_CONTEXT *ctx,
IN SCORE iAlpha,