diff options
| author | Scott Gasch <[email protected]> | 2026-10-25 10:39:58 -0700 |
|---|---|---|
| committer | Scott Gasch <[email protected]> | 2026-10-25 10:39:58 -0700 |
| commit | f97b2710981e936cfb500ad0cdf1ceab233efad8 (patch) | |
| tree | 0004275d9dae8f7df4b5f86f3b750d80bc3f4a52 /src/movesup.c | |
| parent | 3927a4cac6ec254a8e34a5e864300f75c3efc9f3 (diff) | |
Make bitboard move generation unconditional; delete the mailbox fallback
All GENERATE_*_BITBOARD/EXPOSESCHECK_BITBOARD/ISATTACKED_BITBOARD/
UNBLOCKED_BITBOARD flags were already default-on (ifndef
DISABLE_BITBOARD_MOVEGEN); this removes that opt-out entirely (GNUmakefile)
and deletes the mailbox-era code the flags used to toggle between, since
there's no longer a build configuration that still needs it:
- generate.c: the mailbox per-piece generators and escape-generators
(GenerateKnight/GenerateWhiteKnight/GenerateBishop/GenerateRook/
GenerateQueen/GenerateBlackKing/GenerateWhiteKing/GenerateWhitePawn/
GenerateBlackPawn and their SaveMe* escape-generator counterparts),
_FindUnblockedSquares and its DEBUG-build cross-check inside
_FindUnblockedSquaresBB, and the dispatch-table #if/#else pairs that
chose between mailbox and bitboard functions (now unconditionally
bitboard). WouldGiveCheck simplified to its UNBLOCKED_BITBOARD-only
body. g_iBDeltas/g_iRDeltas (orphaned once their only consumers were
deleted) removed; g_iNDeltas (still used by data.c's InitMagic) moved
there, next to its real consumer.
- movesup.c: mailbox FasterExposesCheck/ExposesCheck/ExposesCheckEp/
IsAttacked/InCheck deleted; chess.h's three-way macro choice
simplified to a direct #define onto the BB versions (ExposesCheckBB/
IsAttackedBB/etc. are simply "the" implementation now).
- testsee.c/testgenerate.c: deleted the mailbox-vs-BB comparison/speed
harnesses that only existed to validate code just removed
(TestIsAttackedBB, TestGenerateKnightSpeed/KingSpeed/RookSpeed/
BishopSpeed/QueenSpeed, TestFindUnblockedSquaresSpeed's mailbox arm).
TestGetAttacks and the _GenerateAllMoves-vs-_GenerateAllMovesBB
dispatch-overhead benchmark are unaffected -- GetAttacks' mailbox/asm
predecessors were already retired independently, and that pair
compares two still-live BB-only dispatch strategies, not mailbox vs
BB.
Verified: clean release build and a clean DEBUG=1 TEST=1 self-test run
(move generation, perft-style legal-move checks, SAN/ICS parsing,
search smoke test) with no assertion failures.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Diffstat (limited to 'src/movesup.c')
| -rw-r--r-- | src/movesup.c | 430 |
1 files changed, 0 insertions, 430 deletions
diff --git a/src/movesup.c b/src/movesup.c index 7266177..ac12f10 100644 --- a/src/movesup.c +++ b/src/movesup.c @@ -35,33 +35,6 @@ Revision History: #define SKIP_SELECT_AFTER_N_MOVES (6) #endif -// Unlike GetAttacks (a real asm symbol in a different file, so -// chess.h's macro-swap never touches its own definition), -// ExposesCheck/FasterExposesCheck/ExposesCheckEp's mailbox -// implementations live in *this* file, right below their BB -// counterparts -- chess.h's #define would otherwise rename these -// functions' own definitions too, colliding with the real -// ExposesCheckBB/etc. symbols. #undef restores the real names for -// this file's own definitions; every other translation unit that -// includes chess.h still sees the macro-renamed calls. -#if defined(EXPOSESCHECK_BITBOARD) -#undef ExposesCheck -#undef FasterExposesCheck -#undef ExposesCheckEp -#endif -#if defined(ISATTACKED_BITBOARD) -#undef IsAttacked -#undef InCheck -#endif - -// See eval.c's identical comment: routes this file's (dead-under- -// ISATTACKED_BITBOARD) mailbox IsAttacked's bitboard-scan loop to the -// inlined FastCoorFromBitBoardRank8ToRank1 (chess.h) instead of the -// real out-of-line extern call. -#ifndef CROUTINES -#define CoorFromBitBoardRank8ToRank1 FastCoorFromBitBoardRank8ToRank1 -#endif - // board_representation/MOVEGEN_MIGRATION.md section 6b: bitboard // equivalents of ExposesCheck/FasterExposesCheck/ExposesCheckEp. // ExposesCheck is called from MakeMove (move.c) on essentially every @@ -360,265 +333,6 @@ Return value: return _ValidateExposedBlockerBB(pos, cBlocker, cKing); } -COOR -FasterExposesCheck(POSITION *pos, - COOR cRemove, - COOR cLocation) -/** - -Routine description: - - This is just like ExposesCheck (see below) but it does not bother - checking whether its possible to expose check with the piece at - cRemove because we already know it is. - -Parameters: - - POSITION *pos, - COOR cRemove, - COOR cLocation - -Return value: - - COOR - -**/ -{ - register int iDelta; - register COOR cBlockIndex; - int iIndex; - PIECE xPiece; - ULONG uColor = GET_COLOR(pos->rgSquare[cLocation].pPiece); - - ASSERT(IS_KING(pos->rgSquare[cLocation].pPiece)); - iIndex = (int)cLocation - (int)cRemove; - - ASSERT(IS_ON_BOARD(cRemove)); - ASSERT(IS_ON_BOARD(cLocation)); - ASSERT(!IS_EMPTY(pos->rgSquare[cLocation].pPiece)); - ASSERT(0 != (CHECK_VECTOR_WITH_INDEX(iIndex, BLACK) & (1 << QUEEN))); - - iDelta = CHECK_DELTA_WITH_INDEX(iIndex); - ASSERT(iDelta != 0); - - for (cBlockIndex = cRemove + iDelta; - IS_ON_BOARD(cBlockIndex); - cBlockIndex += iDelta) - { - ASSERT(cBlockIndex != cRemove); - ASSERT(cBlockIndex != cLocation); - xPiece = pos->rgSquare[cBlockIndex].pPiece; - if (!IS_EMPTY(xPiece)) - { - // - // Is it an enemy? - // - if (OPPOSITE_COLORS(xPiece, uColor)) - { - // - // Does it move the right way to attack? - // - iIndex = (int)cBlockIndex - (int)cLocation; - if (0 != (CHECK_VECTOR_WITH_INDEX(iIndex, WHITE) & - (1 << (PIECE_TYPE(xPiece))))) - { - return(cBlockIndex); - } - } - - // - // Either we found another friendly piece or an enemy piece - // that was unable to reach us. Either way we are safe. - // - return(ILLEGAL_COOR); - } - } - - // - // We fell off the board without seeing another piece. - // - return(ILLEGAL_COOR); -} - - - -COOR -ExposesCheck(POSITION *pos, - COOR cRemove, - COOR cLocation) -/** - -Routine description: - - Test if removing the piece at cRemove exposes the piece at - cLocation to attack by the other side. Note: there must be a - piece at cLocation because the color of that piece is used to - determine what side is "checking" and what side is "being - checked". - -Parameters: - - POSITION *pos : the board - COOR cRemove : the square where a piece hypothetically removed from - COOR cLocation : the square where the attackee is sitting - -Return value: - - COOR : the location of an attacker piece or 0x88 (!IS_ON_BOARD) if - the removal of cRemove does not expose check. - -**/ -{ - register int iDelta; - register COOR cBlockIndex; - int iIndex; - PIECE xPiece; - - ASSERT(IS_ON_BOARD(cRemove)); - ASSERT(IS_ON_BOARD(cLocation)); - ASSERT(!IS_EMPTY(pos->rgSquare[cLocation].pPiece)); - - iIndex = (int)cLocation - (int)cRemove; - - // - // If there is no way for a queen sitting at the square removed to - // reach the square we are testing (i.e. the two squares are not - // on the same rank, file, or diagonal) then there is no way - // removing it can expose cLocation to check. - // - if (0 == (CHECK_VECTOR_WITH_INDEX(iIndex, BLACK) & (1 << QUEEN))) - { - return(ILLEGAL_COOR); - } - iDelta = CHECK_DELTA_WITH_INDEX(iIndex); - for (cBlockIndex = cLocation + iDelta; - IS_ON_BOARD(cBlockIndex); - cBlockIndex += iDelta) - { - if (cBlockIndex == cRemove) - { - continue; - } - xPiece = pos->rgSquare[cBlockIndex].pPiece; - if (!IS_EMPTY(xPiece)) - { - // - // Is it an enemy? - // - if (OPPOSITE_COLORS(xPiece, pos->rgSquare[cLocation].pPiece)) - { - // - // Does it move the right way to attack? - // - iIndex = (int)cBlockIndex - (int)cLocation; - if (0 != (CHECK_VECTOR_WITH_INDEX(iIndex, GET_COLOR(xPiece)) & - (1 << (PIECE_TYPE(xPiece))))) - { - return(cBlockIndex); - } - } - - // - // Either we found another friendly piece or an enemy piece - // that was unable to reach us. Either way we are safe. - // - return(ILLEGAL_COOR); - } - } - - // - // We fell off the board without seeing another piece. - // - return(ILLEGAL_COOR); -} - - -COOR -ExposesCheckEp(POSITION *pos, - COOR cTest, - COOR cIgnore, - COOR cBlock, - COOR cKing) -/** - -Routine description: - -Parameters: - - POSITION *pos, - COOR cTest : The square from whence the attack comes - COOR cIgnore : Ignore this square, the pawn moved - COOR cBlock : This square is where the pawn moved to and now blocks - COOR cKing : The square under attack - -Return value: - - COOR - -**/ -{ - register int iDelta; - register COOR cBlockIndex; - int iIndex; - PIECE xPiece; - - ASSERT(IS_ON_BOARD(cTest)); - ASSERT(IS_ON_BOARD(cIgnore)); - ASSERT(IS_ON_BOARD(cBlock)); - ASSERT(IS_ON_BOARD(cKing)); - - iIndex = (int)cKing - (int)cTest; - - // - // If there is no way for a queen sitting at the square removed to - // reach the square we are testing (i.e. the two squares are not - // on the same rank, file, or diagonal) then no problemo. - // - if (0 == (CHECK_VECTOR_WITH_INDEX(iIndex, BLACK) & (1 << QUEEN))) - { - return(ILLEGAL_COOR); - } - - iDelta = CHECK_DELTA_WITH_INDEX(iIndex); - for (cBlockIndex = cKing + iDelta; - IS_ON_BOARD(cBlockIndex); - cBlockIndex += iDelta) - { - if (cBlockIndex == cTest) continue; - if (cBlockIndex == cIgnore) continue; - if (cBlockIndex == cBlock) return(ILLEGAL_COOR); - - xPiece = pos->rgSquare[cBlockIndex].pPiece; - if (!IS_EMPTY(xPiece)) - { - if (OPPOSITE_COLORS(xPiece, pos->rgSquare[cKing].pPiece)) - { - // - // Does it move the right way to attack? - // - iIndex = (int)cBlockIndex - (int)cKing; - if (0 != (CHECK_VECTOR_WITH_INDEX(iIndex, GET_COLOR(xPiece)) & - (1 << (PIECE_TYPE(xPiece))))) - { - return(cBlockIndex); - } - } - - // - // Either we found another friendly piece or an enemy piece - // that was unable to reach us. Either way we are safe. - // - return(ILLEGAL_COOR); - } - } - - // - // We fell off the board without seeing another piece. - // - return(ILLEGAL_COOR); -} - - // // board_representation/MOVEGEN_MIGRATION.md section 6b: bitboard // equivalent of IsAttacked/InCheck. IsAttacked's own direct callers @@ -697,150 +411,6 @@ Return value: return IsAttackedBB(cKingLoc, pos, FLIP(uSide)); } -FLAG -IsAttacked(COOR cTest, POSITION *pos, ULONG uSide) -/** - -Routine description: - - Determine whether the square cTest is attacked by the side uSide. - -Parameters: - - COOR cTest : the square we want to determine if is under attack - POSITION *pos : the board - ULONG uSide : the side we want to see if is attacking cTest - -Return value: - - FLAG : TRUE if uSide attacks cTest, FALSE otherwise - -**/ -{ - PIECE pPiece; - COOR cLocation; - COOR cBlockIndex; - int iIndex; - int iDelta; - BITBOARD bbNonPawns; - static int iPawnLoc[2] = { -17, +15 }; - static PIECE pPawn[2] = { BLACK_PAWN, WHITE_PAWN }; - - ASSERT(IS_ON_BOARD(cTest)); - ASSERT(IS_VALID_COLOR(uSide)); - - // - // Dead in this build (ISATTACKED_BITBOARD routes every caller to - // IsAttackedBB instead -- see this file's #undef block above), so - // iteration order here has no measured perf consequence; combining - // king + non-king pieces into one bitboard scan (instead of the - // old cNonPawns[uSide][] list, which deliberately visited the king - // -- always list slot 0 -- last) is simplest and just as correct. - // - bbNonPawns = NON_KING_PIECES_BB(pos, uSide) | COOR_TO_BB(KingPosition(pos, uSide)); - while (IS_ON_BOARD(cLocation = CoorFromBitBoardRank8ToRank1(&bbNonPawns))) - { - ASSERT(IS_ON_BOARD(cLocation)); - pPiece = pos->rgSquare[cLocation].pPiece; - ASSERT(!IS_EMPTY(pPiece)); - ASSERT(!IS_PAWN(pPiece)); - ASSERT(GET_COLOR(pPiece) == uSide); - iIndex = (int)cLocation - (int)cTest; - - if (!(CHECK_VECTOR_WITH_INDEX(iIndex, uSide) & - (1 << (PIECE_TYPE(pPiece))))) - { - continue; - } - - // - // These pieces do not slide, we don't need to look for - // blockers. If they can get there then there is nothing - // we can do to stop them. - // - if (IS_KNIGHT(pPiece) || IS_KING(pPiece)) - { - return(TRUE); - } - - // - // Well, here we have a sliding piece (bishop, rook or queen) - // that is on the same line (file, rank or diagonal) as the - // cTest. We now have to see if the attacker (pPiece) is - // blocked or is free to attack cTest. - // - iDelta = NEG_DELTA_WITH_INDEX(iIndex); - for (cBlockIndex = cTest + iDelta; - cBlockIndex != cLocation; - cBlockIndex += iDelta) - { - if (!IS_EMPTY(pos->rgSquare[cBlockIndex].pPiece)) - { - break; - } - } - if (cBlockIndex == cLocation) - { - return(TRUE); - } - } - - // - // Check the locations a pawn could attack cTest from. - // - cLocation = cTest + iPawnLoc[uSide]; - if (IS_ON_BOARD(cLocation) && - (pos->rgSquare[cLocation].pPiece == pPawn[uSide])) - { - return(TRUE); - } - - cLocation += 2; - if (IS_ON_BOARD(cLocation) && - (pos->rgSquare[cLocation].pPiece == pPawn[uSide])) - { - return(TRUE); - } - return(FALSE); -} - - -FLAG -InCheck(POSITION *pos, ULONG uSide) -/** - -Routine description: - - Determine if a side is in check or not. - -Parameters: - - POSITION *pos : the board - ULONG uSide : the side we want to determine if is in check - -Return value: - - FLAG : TRUE if side is in check, FALSE otherwise. - -**/ -{ - COOR cKingLoc; -#ifdef DEBUG - PIECE pKing; -#endif - - ASSERT(IS_VALID_COLOR(uSide)); - - cKingLoc = KingPosition(pos, uSide); -#ifdef DEBUG - pKing = pos->rgSquare[cKingLoc].pPiece; - ASSERT(IS_KING(pKing)); - ASSERT(IS_VALID_COLOR(uSide)); - ASSERT(GET_COLOR(pKing) == uSide); -#endif - return(IsAttacked(cKingLoc, pos, FLIP(uSide))); -} - static FLAG _SanityCheckPawnMove(POSITION *pos, MOVE mv) |
