diff options
| author | Scott Gasch <[email protected]> | 2026-09-05 00:19:59 -0700 |
|---|---|---|
| committer | Scott Gasch <[email protected]> | 2026-09-05 00:19:59 -0700 |
| commit | 2ce3570dc6aa67f82dd6f02fc4e518be3e33aabf (patch) | |
| tree | 111f28a4b9587be62e3252aebc4c64b7d8350f4f /src/generate.c | |
| parent | 5883f5a64f4f464b877b7637b8e13c25f7d208fc (diff) | |
Maintain pos->bbOccupied incrementally, dedupe its two from-scratch builders
chess.h: add POSITION::bbOccupied (full-board occupancy, both colors,
every piece including kings), maintained incrementally alongside
bbPieces/bbPawns rather than rebuilt on demand -- resolves the open
question in EVAL.md section 0 about whether this is worth doing given
both generate.c and the planned eval.c mobility rewrite need it.
move.c: SlidePiece/SlidePawn/LiftPiece/PlacePiece and their
WithoutSigs variants now maintain bbOccupied at the same choke points
that already maintain bbPieces/bbPawns -- unconditionally, since
occupancy doesn't care about piece type or color. Kings only ever
move through SlidePiece/SlidePieceWithoutSigs (never Lift/Place), so
no separate king-specific update site was needed.
fen.c: populate bbOccupied when parsing a FEN.
board.c: VerifyPositionConsistency cross-checks pos->bbOccupied
against a from-scratch rebuild, same pattern already used for
bbPieces/bbPawns.
generate.c/movesup.c/see.c: replace call sites that rebuilt full
occupancy via _BuildFullOccupiedBB/_BuildOccupiedBB with direct reads
of pos->bbOccupied; delete see.c's _BuildOccupiedBB, which was a
byte-for-byte duplicate of generate.c's _BuildFullOccupiedBB (kept
only as the from-scratch ground truth for the new consistency check
and testgenerate.c's benchmark harness).
testsup.c: GenerateRandomLegalPosition builds POSITIONs by poking
rgSquare/bbPieces/bbPawns directly, bypassing both move.c and fen.c --
a third construction path the above missed. It never set bbOccupied,
so the new VerifyPositionConsistency check failed on every generated
position, and since generation retries until a position verifies, the
self-test suite spun forever (100% CPU, no progress) instead of
crashing outright. Fixed by setting bbOccupied at all four placement
sites (both kings, pawn, non-pawn piece). Full self-test suite and
precommit_check.sh verified clean afterward.
board_representation/EVAL.md: record the bbOccupied decision and
rationale, resolving section 0's open question.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01P6g6iF6mD1Hau6nCZCzwYj
Diffstat (limited to 'src/generate.c')
| -rwxr-xr-x | src/generate.c | 37 |
1 files changed, 19 insertions, 18 deletions
diff --git a/src/generate.c b/src/generate.c index 69e431f..faecc2a 100755 --- a/src/generate.c +++ b/src/generate.c @@ -739,14 +739,14 @@ GenerateWhiteKnight(IN MOVE_STACK *pStack, // lookup needs no such color-specific shortcut, it just ANDs off // whichever side's occupancy pos->uToMove identifies. // -// Full-board occupancy, both sides -- same formula as see.c's static -// _BuildOccupiedBB (a separate copy, not shared, since that one is -// file-local to see.c and this module's own convention keeps its -// bitboard helpers together). Needed by the slider magic-bitboard -// generators (_GenerateRookBB/_GenerateBishopBB) to index into -// g_RookAttackTable/g_BishopAttackTable -- see MOVE_STACK's -// bbOccupied field comment in chess.h. Non-static so testgenerate.c's -// harness can call it directly. +// Full-board occupancy, both sides. Callers should prefer reading +// pos->bbOccupied directly (incrementally maintained, see chess.h and +// board_representation/EVAL.md section 0) -- this from-scratch +// rebuild now exists mainly as the ground truth used to verify that +// field stays in sync (VerifyPositionConsistency, board.c; the +// ASSERT(pStack->bbOccupied == _BuildFullOccupiedBB(pos)) calls +// below) and for testgenerate.c's benchmark harness. Non-static so +// both of those can call it directly. BITBOARD _BuildFullOccupiedBB(IN POSITION *pos) /** @@ -850,10 +850,11 @@ _BuildFriendlySideBB(IN POSITION *pos, IN ULONG uSide) Routine description: Full occupancy bitboard for one side only (all piece types - including pawns and king) -- see.c's _BuildOccupiedBB ORs both - sides together for a different purpose (SEE's "is this square - occupied at all" query); move generation needs just one side's - squares, to AND off as illegal (self-occupied) destinations. + including pawns and king) -- pos->bbOccupied ORs both sides + together for a different purpose (SEE's/generation's "is this + square occupied at all" query); move generation also needs just + one side's squares here, to AND off as illegal (self-occupied) + destinations. Parameters: @@ -2733,7 +2734,7 @@ Return value: **/ { BITBOARD bbPawns = pos->bbPawns[uSide]; - BITBOARD bbOccupied = _BuildFullOccupiedBB(pos); + BITBOARD bbOccupied = pos->bbOccupied; BITBOARD bbEmpty = ~bbOccupied; BITBOARD bbEnemy = bbOccupied & ~_BuildFriendlySideBB(pos, uSide); BITBOARD bbSinglePush, bbDoublePush, bbCapLeft, bbCapRight, bb; @@ -3072,7 +3073,7 @@ Return value: **/ { BITBOARD bbPawns = pos->bbPawns[uSide]; - BITBOARD bbOccupied = _BuildFullOccupiedBB(pos); + BITBOARD bbOccupied = pos->bbOccupied; BITBOARD bbEmpty = ~bbOccupied; BITBOARD bbEnemy = bbOccupied & ~_BuildFriendlySideBB(pos, uSide); BITBOARD bbSinglePush, bbDoublePush, bbCapLeft, bbCapRight, bb; @@ -3382,7 +3383,7 @@ Return value: #endif #if defined(GENERATE_ROOK_BITBOARD) || defined(GENERATE_BISHOP_BITBOARD) || \ defined(GENERATE_QUEEN_BITBOARD) - pStack->bbOccupied = _BuildFullOccupiedBB(pos); + pStack->bbOccupied = pos->bbOccupied; #endif for(u = pos->uNonPawnCount[pos->uToMove][0] - 1; @@ -3511,7 +3512,7 @@ Return value: #endif pStack->bbFriendlyOccupied = _BuildFriendlySideBB(pos, uSide); - pStack->bbOccupied = _BuildFullOccupiedBB(pos); + pStack->bbOccupied = pos->bbOccupied; bb = pos->bbPieces[uSide][KNIGHT]; while (bb) @@ -3728,7 +3729,7 @@ Return value: (void)pKing; BITBOARD bbFriendly = _BuildFriendlySideBB(pos, pos->uToMove); BITBOARD bbOccupiedWithoutKing = - _BuildFullOccupiedBB(pos) & ~COOR_TO_BB(cKing); + pos->bbOccupied & ~COOR_TO_BB(cKing); BITBOARD bbDest = g_KingAttacksBB[cKing] & ~bbFriendly; ULONG uBitIndex; @@ -3875,7 +3876,7 @@ Return value: // _SaveMe*BB call below to share (same amortization reasoning // as _GenerateAllMoves's own precompute block). pStack->bbFriendlyOccupied = _BuildFriendlySideBB(pos, pos->uToMove); - pStack->bbOccupied = _BuildFullOccupiedBB(pos); + pStack->bbOccupied = pos->bbOccupied; bbTargetMask = _ComputeCheckTargetMaskBB(cKing, c, pStack->bbOccupied); |
