summaryrefslogtreecommitdiff
path: root/src/movesup.c
diff options
context:
space:
mode:
authorScott Gasch <[email protected]>2026-10-25 10:39:58 -0700
committerScott Gasch <[email protected]>2026-10-25 10:39:58 -0700
commitf97b2710981e936cfb500ad0cdf1ceab233efad8 (patch)
tree0004275d9dae8f7df4b5f86f3b750d80bc3f4a52 /src/movesup.c
parent3927a4cac6ec254a8e34a5e864300f75c3efc9f3 (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.c430
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)