Код: Выделить всё
x & -x[*] Эффективная компоновка и повторное использование данных (плоские массивы, предварительные маски)
[*] Нет динамических ассигнований
с ними. Реализация: < /p>
Код: Выделить всё
size_t perft(int depth, bool printCountAfterMoves) {
size_t nodes = 0;
MoveList legalMoves = moveGenerator.generateLegalMoves();
if (depth == 1) {
return static_cast(legalMoves.getMovesCount());
}
for (Move move : legalMoves) {
position.makeMove(move);
size_t count = perft(depth - 1, false);
if (printCountAfterMoves) [[unlikely]] {
std::cout pieces[position->usColor * 6 + PT_KING]);
assert(kingSq < 64);
Bitboard occ = position->occForColor[WHITE] | position->occForColor[BLACK];
Bitboard attackMask = computeAttackMask(occ);
Bitboard checkerMask = computeCheckerMask(kingSq, occ);
bool isInCheck = std::popcount(checkerMask) >= 1;
bool isInDoubleCheck = std::popcount(checkerMask) == 2;
// if in normal check and the checking piece is a slider piece, generate the block mask
Bitboard checkBlockMask =
isInCheck && !isInDoubleCheck &&
(checkerMask & ~position->pieces[position->oppColor * 6 + PT_PAWN] &
~position->pieces[position->oppColor * 6 + PT_KNIGHT])
? BETWEEN_MASK[kingSq][std::countr_zero(checkerMask)]
: 0ULL;
Bitboard checkEvasionMask = checkerMask | checkBlockMask;
Bitboard pinMask = computePinMask(kingSq, occ);
Bitboard capturableSquares = ~position->occForColor[position->usColor];
if (!isInDoubleCheck) [[likely]] {
// pawns
Bitboard freeSquares = ~occ;
Bitboard pawns = position->pieces[position->usColor * 6 + PT_PAWN];
while (pawns) {
Bitboard currPawn = pawns & -pawns;
int currPawnSq = std::countr_zero(currPawn);
if (position->usColor == WHITE) {
// we are white
// pushes
Bitboard singlePush = WHITE_PAWN_SINGLE_PUSH_MASK[currPawnSq] & freeSquares;
Bitboard doublePush = ((singlePush & RANK_3) occForColor[position->oppColor];
Bitboard rightCapture = WHITE_PAWN_CAPTURE_RIGHT_MASK[currPawnSq] &
position->occForColor[position->oppColor];
Bitboard normalMoves = singlePush | doublePush | leftCapture | rightCapture;
// en-passant
Bitboard ep =
isEpLegal(kingSq, occ, currPawn)
? (WHITE_PAWN_CAPTURE_LEFT_MASK[currPawnSq] & position->epSquare) |
(WHITE_PAWN_CAPTURE_RIGHT_MASK[currPawnSq] & position->epSquare)
: 0ULL;
if (isInCheck) {
normalMoves &= checkEvasionMask;
// if en-passant does not resolve the check, disallow it
if ((ep >> 8) != checkEvasionMask) {
ep = 0ULL;
}
}
if (currPawn & pinMask) {
normalMoves &= LINE_MASK[currPawnSq][kingSq];
ep &= LINE_MASK[currPawnSq][kingSq];
}
// add en-passant move
if (ep) {
moveList.add(Move(currPawn, ep, PT_PAWN, PT_NULL, false, true));
}
// add each normal move
while (normalMoves) {
Bitboard to = normalMoves & -normalMoves;
// promotion
if (to & RANK_8) {
moveList.add(Move(currPawn, to, PT_PAWN, PT_KNIGHT, false, false));
moveList.add(Move(currPawn, to, PT_PAWN, PT_BISHOP, false, false));
moveList.add(Move(currPawn, to, PT_PAWN, PT_ROOK, false, false));
moveList.add(Move(currPawn, to, PT_PAWN, PT_QUEEN, false, false));
}
else {
moveList.add(Move(currPawn, to, PT_PAWN, PT_NULL, false, false));
}
normalMoves &= normalMoves - 1;
}
}
else {
// we are black
// pushes
Bitboard singlePush = BLACK_PAWN_SINGLE_PUSH_MASK[currPawnSq] & freeSquares;
Bitboard doublePush = ((singlePush & RANK_6) >> 8) & freeSquares;
// captures
Bitboard leftCapture = BLACK_PAWN_CAPTURE_LEFT_MASK[currPawnSq] &
position->occForColor[position->oppColor];
Bitboard rightCapture = BLACK_PAWN_CAPTURE_RIGHT_MASK[currPawnSq] &
position->occForColor[position->oppColor];
Bitboard normalMoves = singlePush | doublePush | leftCapture | rightCapture;
// en-passant
Bitboard ep =
isEpLegal(kingSq, occ, currPawn)
? (BLACK_PAWN_CAPTURE_LEFT_MASK[currPawnSq] & position->epSquare) |
(BLACK_PAWN_CAPTURE_RIGHT_MASK[currPawnSq] & position->epSquare)
: 0ULL;
if (isInCheck) {
normalMoves &= checkEvasionMask;
// if en-passant does not resolve the check, disallow it
if ((ep pieces[position->usColor * 6 + PT_KNIGHT];
while (knights) {
Bitboard currKnight = knights & -knights;
Bitboard moves = KNIGHT_MOVE_MASK[std::countr_zero(currKnight)] & capturableSquares;
// checks & pins
if (isInCheck) {
moves &= checkEvasionMask;
}
if (currKnight & pinMask) {
moves &= LINE_MASK[std::countr_zero(currKnight)][kingSq];
}
addMovesToList(moveList, currKnight, moves, PT_KNIGHT);
knights &= knights - 1;
}
// bishops
Bitboard bishops = position->pieces[position->usColor * 6 + PT_BISHOP];
while (bishops) {
Bitboard currBishop = bishops & -bishops;
Bitboard moves =
getBishopAttacks(std::countr_zero(currBishop), occ) & capturableSquares;
// checks & pins
if (isInCheck) {
moves &= checkEvasionMask;
}
if (currBishop & pinMask) {
moves &= LINE_MASK[std::countr_zero(currBishop)][kingSq];
}
addMovesToList(moveList, currBishop, moves, PT_BISHOP);
bishops &= bishops - 1;
}
// rooks
Bitboard rooks = position->pieces[position->usColor * 6 + PT_ROOK];
while (rooks) {
Bitboard currRook = rooks & -rooks;
Bitboard moves = getRookAttacks(std::countr_zero(currRook), occ) & capturableSquares;
// checks & pins
if (isInCheck) {
moves &= checkEvasionMask;
}
if (currRook & pinMask) {
moves &= LINE_MASK[std::countr_zero(currRook)][kingSq];
}
addMovesToList(moveList, currRook, moves, PT_ROOK);
rooks &= rooks - 1;
}
// queens
Bitboard queens = position->pieces[position->usColor * 6 + PT_QUEEN];
while (queens) {
Bitboard currQueen = queens & -queens;
Bitboard moves = (getRookAttacks(std::countr_zero(currQueen), occ) |
getBishopAttacks(std::countr_zero(currQueen), occ)) &
capturableSquares;
// checks & pins
if (isInCheck) {
moves &= checkEvasionMask;
}
if (currQueen & pinMask) {
moves &= LINE_MASK[std::countr_zero(currQueen)][kingSq];
}
addMovesToList(moveList, currQueen, moves, PT_QUEEN);
queens &= queens - 1;
}
}
// king
Bitboard kingMoves = KING_MOVE_MASK[kingSq] & capturableSquares & ~attackMask;
addMovesToList(moveList, position->pieces[position->usColor * 6 + PT_KING], kingMoves, PT_KING);
if (!isInCheck) {
if (position->usColor == WHITE) {
constexpr Bitboard E1 = 1ULL
Подробнее здесь: [url]https://stackoverflow.com/questions/79760571/how-can-i-further-optimize-move-generation-in-my-c-chess-engine[/url]