40 ParamType legalDestinations)
noexcept -> IteratorType
44 const SquareSet pawns { board.getPawns() & board.getPiecesInTurn() };
46 const SquareSet unpinnedPawns { pawns & ~board.getPinnedPieces() };
50 SideSpecifics::pawnAdvance(unpinnedPawns) & ~board.getOccupancyMask() };
53 const SquareSet doubleAdvanceMaskUnpinned {
54 SideSpecifics::pawnAdvance(advanceMaskUnpinned & SideSpecifics::rank3) & ~board.getOccupancyMask() };
61 advanceMaskUnpinned & ~SideSpecifics::promoRank & legalDestinations(),
69 doubleAdvanceMaskUnpinned & legalDestinations(),
77 advanceMaskUnpinned & SideSpecifics::promoRank & legalDestinations(),
79 const Square src { SideSpecifics::pawnRetreatSq(dst) };
96 i += ((advanceMaskUnpinned | doubleAdvanceMaskUnpinned) &~ SideSpecifics::promoRank & legalDestinations()).
99 i += (advanceMaskUnpinned & SideSpecifics::promoRank & legalDestinations()).popcount() * 4U;
102 const SquareSet oppPieces { (board.getOccupancyMask() ^ board.getPiecesInTurn()) };
104 Attacks::getPawnAttackersMask<turn, false>(oppPieces & legalDestinations()) & pawns };
106 Attacks::getPawnAttackersMask<turn, true>(oppPieces & legalDestinations()) & pawns };
113 leftCapturingPawns & ~SideSpecifics::rank7 & ~board.getPinnedPieces(),
115 *i = Move { src, SideSpecifics::captureLeftSq(src), MoveTypeAndPromotion::REGULAR_PAWN_MOVE };
122 rightCapturingPawns & ~SideSpecifics::rank7 & ~board.getPinnedPieces(),
124 *i = Move { src, SideSpecifics::captureRightSq(src), MoveTypeAndPromotion::REGULAR_PAWN_MOVE };
131 leftCapturingPawns & SideSpecifics::rank7 & ~board.getPinnedPieces(),
133 const Square dst { SideSpecifics::captureLeftSq(src) };
151 rightCapturingPawns & SideSpecifics::rank7 & ~board.getPinnedPieces(),
153 const Square dst { SideSpecifics::captureRightSq(src) };
155 *i =
Move { src, dst, MoveTypeAndPromotion::PROMO_QUEEN };
158 *i =
Move { src, dst, MoveTypeAndPromotion::PROMO_ROOK };
161 *i =
Move { src, dst, MoveTypeAndPromotion::PROMO_BISHOP };
164 *i =
Move { src, dst, MoveTypeAndPromotion::PROMO_KNIGHT };
170 i += (leftCapturingPawns & ~SideSpecifics::rank7 & ~board.getPinnedPieces()).popcount();
171 i += (rightCapturingPawns & ~SideSpecifics::rank7 & ~board.getPinnedPieces()).popcount();
172 i += (leftCapturingPawns & SideSpecifics::rank7 & ~board.getPinnedPieces()).popcount() * 4U;
173 i += (rightCapturingPawns & SideSpecifics::rank7 & ~board.getPinnedPieces()).popcount() * 4U;
178 if constexpr (type == MoveGenType::NO_CHECK)
181 const SquareSet pinnedPawns { board.getPawns() & board.getPinnedPieces() };
187 SquareSet pawnBit { src };
188 const SquareSet advanceMask { SideSpecifics::pawnAdvance(pawnBit) & ~board.getOccupancyMask() };
189 const SquareSet doubleAdvanceMask { SideSpecifics::pawnAdvance(advanceMask & SideSpecifics::rank3) & ~board.getOccupancyMask() };
194 (advanceMask | doubleAdvanceMask) & (~SideSpecifics::promoRank) &
195 Intercepts::getPinRestiction<true>(board.getKingInTurn(), src) &
198 *i =
Move { src, dst, MoveTypeAndPromotion::REGULAR_PAWN_MOVE };
207 oppPieces & SideSpecifics::captureLeft(pawnBit) & (~SideSpecifics::promoRank) &
208 Intercepts::getPinRestiction<true>(board.getKingInTurn(), src) & legalDestinations(),
210 *i =
Move { src, dst, MoveTypeAndPromotion::REGULAR_PAWN_MOVE };
217 oppPieces & SideSpecifics::captureLeft(pawnBit) & SideSpecifics::promoRank &
218 Intercepts::getPinRestiction<true>(board.getKingInTurn(), src) & legalDestinations(),
220 *i =
Move { src, dst, MoveTypeAndPromotion::PROMO_QUEEN };
223 *i =
Move { src, dst, MoveTypeAndPromotion::PROMO_ROOK };
226 *i =
Move { src, dst, MoveTypeAndPromotion::PROMO_BISHOP };
229 *i =
Move { src, dst, MoveTypeAndPromotion::PROMO_KNIGHT };
236 oppPieces & SideSpecifics::captureRight(pawnBit) & (~SideSpecifics::promoRank) &
237 Intercepts::getPinRestiction<true>(board.getKingInTurn(), src) & legalDestinations(),
239 *i =
Move { src, dst, MoveTypeAndPromotion::REGULAR_PAWN_MOVE };
246 oppPieces & SideSpecifics::captureRight(pawnBit) & SideSpecifics::promoRank &
247 Intercepts::getPinRestiction<true>(board.getKingInTurn(), src) & legalDestinations(),
249 *i =
Move { src, dst, MoveTypeAndPromotion::PROMO_QUEEN };
252 *i =
Move { src, dst, MoveTypeAndPromotion::PROMO_ROOK };
255 *i =
Move { src, dst, MoveTypeAndPromotion::PROMO_BISHOP };
258 *i =
Move { src, dst, MoveTypeAndPromotion::PROMO_KNIGHT };
265 if (board.getEpSquare() <= Square::H8)
269 Attacks::getPawnAttackerMask(board.getEpSquare(), turn) & pawns,
272 if (Attacks::pinCheck(src, SquareSet { board.getEpSquare() }, board.getKingInTurn(), board.getPinnedPieces()))
274 *i =
Move { src, board.getEpSquare(), MoveTypeAndPromotion::EN_PASSANT };
486 IteratorType i)
noexcept
489 constexpr ParamType legalDestinations { };
491 i = generateMovesForPawns<IteratorType, MoveGenType::NO_CHECK>(board, i, legalDestinations);
494 if (i.hasLegalMoves())
499 board.getKnights() & board.getPiecesInTurn() & ~board.getPinnedPieces(),
500 i = generateMovesForKnight<IteratorType, MoveGenType::NO_CHECK>(board, i, sq, legalDestinations));
503 if (i.hasLegalMoves())
508 board.getBishopsAndQueens() & board.getPiecesInTurn() & ~board.getPinnedPieces(),
510 const MoveTypeAndPromotion typeAndPromo {
511 (board.getRooksAndQueens() & SquareSet { sq }) != SquareSet { } ?
512 MoveTypeAndPromotion::REGULAR_QUEEN_MOVE :
513 MoveTypeAndPromotion::REGULAR_BISHOP_MOVE
515 i = generateMovesForBishop<IteratorType, MoveGenType::NO_CHECK, ParamType, false>(board, i, sq, legalDestinations, typeAndPromo);
520 board.getBishopsAndQueens() & board.getPinnedPieces(),
522 const MoveTypeAndPromotion typeAndPromo {
523 (board.getRooksAndQueens() & SquareSet { sq }) != SquareSet { } ?
524 MoveTypeAndPromotion::REGULAR_QUEEN_MOVE :
525 MoveTypeAndPromotion::REGULAR_BISHOP_MOVE
527 i = generateMovesForBishop<IteratorType, MoveGenType::NO_CHECK, ParamType, true>(board, i, sq, legalDestinations, typeAndPromo);
530 if constexpr (MoveGenIteratorTraits<IteratorType>::canCompleteEarly)
531 if (i.hasLegalMoves())
536 board.getRooksAndQueens() & board.getPiecesInTurn() & ~board.getPinnedPieces(),
538 const MoveTypeAndPromotion typeAndPromo {
539 (board.getBishopsAndQueens() & SquareSet { sq }) != SquareSet { } ?
540 MoveTypeAndPromotion::REGULAR_QUEEN_MOVE :
541 MoveTypeAndPromotion::REGULAR_ROOK_MOVE
543 i = generateMovesForRook<IteratorType, MoveGenType::NO_CHECK, ParamType, false>(board, i, sq, legalDestinations, typeAndPromo);
548 board.getRooksAndQueens() & board.getPinnedPieces(),
550 const MoveTypeAndPromotion typeAndPromo {
551 (board.getBishopsAndQueens() & SquareSet { sq }) != SquareSet { } ?
552 MoveTypeAndPromotion::REGULAR_QUEEN_MOVE :
553 MoveTypeAndPromotion::REGULAR_ROOK_MOVE
555 i = generateMovesForRook<IteratorType, MoveGenType::NO_CHECK, ParamType, true>(board, i, sq, legalDestinations, typeAndPromo);
558 if constexpr (MoveGenIteratorTraits<IteratorType>::canCompleteEarly)
559 if (i.hasLegalMoves())
565 const SquareSet attackedSquares {
566 Attacks::determineAttackedSquares(
567 board.getOccupancyMask() &~ (board.getKings() & board.getPiecesInTurn()),
568 board.getPawns() &~ board.getPiecesInTurn(),
569 board.getKnights() &~ board.getPiecesInTurn(),
570 board.getBishopsAndQueens() &~ board.getPiecesInTurn(),
571 board.getRooksAndQueens() &~ board.getPiecesInTurn(),
572 board.getKingNotInTurn(),
575 i = generateMovesForKing<IteratorType>(board, i, attackedSquares);
577 if constexpr (MoveGenIteratorTraits<IteratorType>::canCompleteEarly)
578 if (i.hasLegalMoves())
581 generateMovesForCastlingStoreFnTempl<MoveGenType::NO_CHECK, IteratorStoreMoveFn<IteratorType>,
false>(board, attackedSquares, i);
582 generateMovesForCastlingStoreFnTempl<MoveGenType::NO_CHECK, IteratorStoreMoveFn<IteratorType>,
true>(board, attackedSquares, i);
598 IteratorType i)
noexcept
601 ParamType legalDestinations {
602 Intercepts::getInterceptSquares(board.getKingInTurn(), board.getCheckers().firstSquare()) };
607 Attacks::determineAttackedSquares(
608 board.getOccupancyMask() &~ (board.getKings() & board.getPiecesInTurn()),
609 board.getPawns() &~ board.getPiecesInTurn(),
610 board.getKnights() &~ board.getPiecesInTurn(),
611 board.getBishopsAndQueens() &~ board.getPiecesInTurn(),
612 board.getRooksAndQueens() &~ board.getPiecesInTurn(),
613 board.getKingNotInTurn(),
616 i = generateMovesForKing<IteratorType>(board, i, attackedSquares);
618 if (i.hasLegalMoves())
622 i = generateMovesForPawns<IteratorType, MoveGenType::CHECK, ParamType>(board, i, legalDestinations);
625 if (i.hasLegalMoves())
630 board.getKnights() & board.getPiecesInTurn() & ~board.getPinnedPieces(),
631 i = generateMovesForKnight<IteratorType, MoveGenType::CHECK, ParamType>(board, i, sq, legalDestinations));
634 if (i.hasLegalMoves())
639 board.getBishopsAndQueens() & board.getPiecesInTurn() & ~board.getPinnedPieces(),
641 const MoveTypeAndPromotion typeAndPromo {
642 (board.getRooksAndQueens() & SquareSet { sq }) != SquareSet { } ?
643 MoveTypeAndPromotion::REGULAR_QUEEN_MOVE :
644 MoveTypeAndPromotion::REGULAR_BISHOP_MOVE
646 i = generateMovesForBishop<IteratorType, MoveGenType::CHECK, ParamType, false>(board, i, sq, legalDestinations, typeAndPromo);
651 if constexpr (MoveGenIteratorTraits<IteratorType>::canCompleteEarly)
652 if (i.hasLegalMoves())
657 board.getRooksAndQueens() & board.getPiecesInTurn() & ~board.getPinnedPieces(),
659 const MoveTypeAndPromotion typeAndPromo {
660 (board.getBishopsAndQueens() & SquareSet { sq }) != SquareSet { } ?
661 MoveTypeAndPromotion::REGULAR_QUEEN_MOVE :
662 MoveTypeAndPromotion::REGULAR_ROOK_MOVE
664 i = generateMovesForRook<IteratorType, MoveGenType::CHECK, ParamType, false>(board, i, sq, legalDestinations, typeAndPromo);
669 if constexpr (MoveGenIteratorTraits<IteratorType>::canCompleteEarly)
670 if (i.hasLegalMoves())