summaryrefslogtreecommitdiff
path: root/src/chess.h
diff options
context:
space:
mode:
authorScott Gasch <[email protected]>2026-09-05 02:17:20 -0700
committerScott Gasch <[email protected]>2026-09-05 02:17:20 -0700
commitde3f3663483f846d369efa5234a84c7da385be95 (patch)
tree71af0527a47c0996b0116351dee0d68409db2fad /src/chess.h
parent7e3e6b69969cf6657f518102be515702da6a7343 (diff)
Bishop attack/mobility: bitboard rewrite, deliberate x-ray simplification
_EvalBishop's mobility ray-walk (per-square g_iBDeltas delta-walk + BMobCaseTable switch dispatch) replaced with _BishopAttacksBB(c, pos->bbOccupied) -- generate.c's magic-bitboard slider lookup, already used by move generation -- plus bitboard masks for the mobility count, matching knight's reduction pattern: enemy-non-pawn-terminal counts unconditionally, empty-or-enemy-pawn- terminal counts unless pawn-unsafe (via bbPawnAttacks), and the one case that isn't a pure occupancy mask -- a terminal friendly, non-stationary pawn on this bishop's own color complex -- keeps its credit via bbPc (already computed for the existing good/bad transient-pawn scoring, untouched this change). Adds POSITION::bbMinorAttacks contributions from bishop (direct attack bits) and POSITION::bbMinorXrayAttacks (new field) for squares seen through a friendly bishop/queen battery partner or an x-rayable enemy rook/queen/king. Deliberate behavior change from the old ray-walk, made for speed per direct instruction: the old walk's fStop=FALSE for the x-ray cases meant it kept going -- and kept counting mobility -- through however many x-ray-worthy blockers were stacked consecutively on one ray (e.g. x-raying an enemy rook, then continuing to x-ray *through* an enemy king sitting right behind it too). The bitboard version only extends one hop past the first x-ray-worthy blocker; it does not re-check whether the newly-revealed terminal square is itself x-ray-worthy and extend again. This was found and deliberately kept (not fixed) after a DEBUG assert caught the exact case on 8/1R1B4/2B1r3/5k2/2P2P2/1p6/1Kb5/7n w - - during precommit's random- sample smoke test -- judged an acceptable trade given how rare a ray with >=2 consecutive x-ray-worthy pieces is. Two new transitional helpers (_IsSquareAttackedByMinor's bishop contribution, and new _IsSquareXrayedByMinor) carry bishop's combined state to every remaining consumer (rook/queen mobility-safety checks, king's danger computation, _WhoControlsSquareFast) -- both DEBUG- asserted against an independent from-scratch mailbox ray-walk (using the still-live rgSquare representation, not any shared code with the production bitboard technique) implementing this same single-hop rule, so a real regression fails loudly rather than drifting into a wrong score. Verified via precommit_check.sh and the full tests/ecm_ringers.ep_ suite at sd10 against the prior commit (7e3e6b6): same 10/11 solved (same single miss, ECM.335, in both), node counts now legitimately differ per position (expected given the semantic change) but stay in a bounded, reasonable range (-17% to +20%), nothing resembling the 60%+ blowups a real bug produced earlier in this same session before being caught, isolated, and traced to this exact x-ray-chain gap. Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01P6g6iF6mD1Hau6nCZCzwYj
Diffstat (limited to 'src/chess.h')
-rwxr-xr-xsrc/chess.h32
1 files changed, 21 insertions, 11 deletions
diff --git a/src/chess.h b/src/chess.h
index 2e9189a..305c681 100755
--- a/src/chess.h
+++ b/src/chess.h
@@ -716,19 +716,29 @@ typedef struct _POSITION
// bbRookAttacks/bbQueenAttacks that will retire the rest of it.
BITBOARD bbPawnAttacks[2];
- // First mover of the bbMinorAttacks pair (knight only for now --
- // bishop is a separate, later step; see board_representation/
- // EVAL.md section 2). "Which squares does this side's knight(s)
- // attack" -- computed via g_KnightAttacksBB[c] and OR'd in per
- // knight, Eval()-scoped scratch like bbPawnAttacks above, cleared
- // once per Eval() call in _ClearAttackTables since (unlike
- // bbPawnAttacks) it's accumulated across multiple pieces via |=,
- // not assigned wholesale. Bishop still writes its own minor-bit
- // contribution into the old rgSquare[c|8].bvAttacks structure for
- // now -- every consumer that needs "any minor's attack," not just
- // knight's, ORs both sources together until bishop converts too.
+ // "Which squares does this side's knight(s) or bishop(s) attack" --
+ // knight ORs in g_KnightAttacksBB[c] directly (no per-square
+ // bit-scan needed); bishop ORs in _BishopAttacksBB(c,
+ // pos->bbOccupied), generate.c's magic-bitboard slider lookup.
+ // Eval()-scoped scratch like bbPawnAttacks above, cleared once per
+ // Eval() call in _ClearAttackTables since (unlike bbPawnAttacks)
+ // it's accumulated across multiple pieces via |=, not assigned
+ // wholesale. Rook/queen/king are not converted yet and still write
+ // their own bits into the old rgSquare[c|8].bvAttacks structure --
+ // see _IsSquareAttackedByMinor (eval.c), the transitional helper
+ // every consumer goes through until they convert too.
BITBOARD bbMinorAttacks[2];
+ // Squares seen *through* a friendly bishop/queen battery partner
+ // or an x-rayable enemy rook/queen/king, for bishops only (knights
+ // never x-ray) -- see _EvalBishop's mobility loop. Same lifetime/
+ // clearing discipline as bbMinorAttacks above. Nothing else writes
+ // this yet (rook/queen have their own xray bits still living in
+ // the old bvAttacks structure), so unlike bbMinorAttacks' direct-
+ // bit case there's no old-structure fallback to combine with --
+ // see _IsSquareXrayedByMinor.
+ BITBOARD bbMinorXrayAttacks[2];
+
ULONG uWhiteSqBishopCount[2]; // num bishops on white squares
SCORE iMaterialBalance[2]; // material balance