HooverChessUtils_PgnReader 0.9.0
Loading...
Searching...
No Matches
chessboard-movegen-all.h
Go to the documentation of this file.
1// Hoover Chess Utilities / PGN reader
2// Copyright (C) 2024-2025 Sami Kiminki
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <https://www.gnu.org/licenses/>.
16
17#ifndef HOOVER_CHESS_UTILS__PGN_READER__CHESSBOARD_MOVEGEN_ALL_H_INCLUDED
18#define HOOVER_CHESS_UTILS__PGN_READER__CHESSBOARD_MOVEGEN_ALL_H_INCLUDED
19
20#include "chessboard-movegen.h"
21
22
24{
25
36template <typename IteratorType, MoveGenType type, typename ParamType, Color turn>
38 const ChessBoard &board,
39 IteratorType i,
40 ParamType legalDestinations) noexcept -> IteratorType
41{
42 using SideSpecifics = PawnLookups_SideSpecificsTempl<turn>;
43
44 const SquareSet pawns { board.getPawns() & board.getPiecesInTurn() };
45
46 const SquareSet unpinnedPawns { pawns & ~board.getPinnedPieces() };
47
48 // destination squares for advancing pawns (must be empty)
49 const SquareSet advanceMaskUnpinned {
50 SideSpecifics::pawnAdvance(unpinnedPawns) & ~board.getOccupancyMask() };
51
52 // destination squares for double-advancing pawns (must be empty)
53 const SquareSet doubleAdvanceMaskUnpinned {
54 SideSpecifics::pawnAdvance(advanceMaskUnpinned & SideSpecifics::rank3) & ~board.getOccupancyMask() };
55
56 // pawn advances for unpinned pawns
58 {
60 dst,
61 advanceMaskUnpinned & ~SideSpecifics::promoRank & legalDestinations(),
62 {
63 *i = Move { SideSpecifics::pawnRetreatSq(dst), dst, MoveTypeAndPromotion::REGULAR_PAWN_MOVE };
64 ++i;
65 });
66
68 dst,
69 doubleAdvanceMaskUnpinned & legalDestinations(),
70 {
71 *i = Move { SideSpecifics::pawnDoubleRetreatSq(dst), dst, MoveTypeAndPromotion::REGULAR_PAWN_MOVE };
72 ++i;
73 });
74
76 dst,
77 advanceMaskUnpinned & SideSpecifics::promoRank & legalDestinations(),
78 {
79 const Square src { SideSpecifics::pawnRetreatSq(dst) };
80
81 *i = Move { src, dst, pieceToTypeAndPromotion(Piece::QUEEN) };
82 ++i;
83
84 *i = Move { src, dst, pieceToTypeAndPromotion(Piece::ROOK) };
85 ++i;
86
87 *i = Move { src, dst, pieceToTypeAndPromotion(Piece::BISHOP) };
88 ++i;
89
90 *i = Move { src, dst, pieceToTypeAndPromotion(Piece::KNIGHT) };
91 ++i;
92 });
93 }
94 else
95 {
96 i += ((advanceMaskUnpinned | doubleAdvanceMaskUnpinned) &~ SideSpecifics::promoRank & legalDestinations()).
97 popcount();
98
99 i += (advanceMaskUnpinned & SideSpecifics::promoRank & legalDestinations()).popcount() * 4U;
100 }
101
102 const SquareSet oppPieces { (board.getOccupancyMask() ^ board.getPiecesInTurn()) };
103 const SquareSet leftCapturingPawns {
104 Attacks::getPawnAttackersMask<turn, false>(oppPieces & legalDestinations()) & pawns };
105 const SquareSet rightCapturingPawns {
106 Attacks::getPawnAttackersMask<turn, true>(oppPieces & legalDestinations()) & pawns };
107
109 {
110 // capture left
112 src,
113 leftCapturingPawns & ~SideSpecifics::rank7 & ~board.getPinnedPieces(),
114 {
115 *i = Move { src, SideSpecifics::captureLeftSq(src), MoveTypeAndPromotion::REGULAR_PAWN_MOVE };
116 ++i;
117 });
118
119 // capture right
121 src,
122 rightCapturingPawns & ~SideSpecifics::rank7 & ~board.getPinnedPieces(),
123 {
124 *i = Move { src, SideSpecifics::captureRightSq(src), MoveTypeAndPromotion::REGULAR_PAWN_MOVE };
125 ++i;
126 });
127
128 // capture left + promo
130 src,
131 leftCapturingPawns & SideSpecifics::rank7 & ~board.getPinnedPieces(),
132 {
133 const Square dst { SideSpecifics::captureLeftSq(src) };
134
135 *i = Move { src, dst, MoveTypeAndPromotion::PROMO_QUEEN };
136 ++i;
137
138 *i = Move { src, dst, MoveTypeAndPromotion::PROMO_ROOK };
139 ++i;
140
141 *i = Move { src, dst, MoveTypeAndPromotion::PROMO_BISHOP };
142 ++i;
143
144 *i = Move { src, dst, MoveTypeAndPromotion::PROMO_KNIGHT };
145 ++i;
146 });
147
148 // capture right + promo
150 src,
151 rightCapturingPawns & SideSpecifics::rank7 & ~board.getPinnedPieces(),
152 {
153 const Square dst { SideSpecifics::captureRightSq(src) };
154
155 *i = Move { src, dst, MoveTypeAndPromotion::PROMO_QUEEN };
156 ++i;
157
158 *i = Move { src, dst, MoveTypeAndPromotion::PROMO_ROOK };
159 ++i;
160
161 *i = Move { src, dst, MoveTypeAndPromotion::PROMO_BISHOP };
162 ++i;
163
164 *i = Move { src, dst, MoveTypeAndPromotion::PROMO_KNIGHT };
165 ++i;
166 });
167 }
168 else
169 {
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;
174 }
175
176 // pinned pawns
177 // note: pinned pawns can never resolve a check
178 if constexpr (type == MoveGenType::NO_CHECK)
179 {
180 // note: we need to filter out the EP square with board.getPiecesInTurn()
181 const SquareSet pinnedPawns { board.getPawns() & board.getPinnedPieces() };
182
184 src,
185 pinnedPawns,
186 {
187 SquareSet pawnBit { src };
188 const SquareSet advanceMask { SideSpecifics::pawnAdvance(pawnBit) & ~board.getOccupancyMask() };
189 const SquareSet doubleAdvanceMask { SideSpecifics::pawnAdvance(advanceMask & SideSpecifics::rank3) & ~board.getOccupancyMask() };
190
191 // advances, non-promo
193 dst,
194 (advanceMask | doubleAdvanceMask) & (~SideSpecifics::promoRank) &
195 Intercepts::getPinRestiction<true>(board.getKingInTurn(), src) &
196 legalDestinations(),
197 {
198 *i = Move { src, dst, MoveTypeAndPromotion::REGULAR_PAWN_MOVE };
199 ++i;
200 });
201
202 // note: pinned pawn can never promote without capture
203
204 // left-capture, non-promo
206 dst,
207 oppPieces & SideSpecifics::captureLeft(pawnBit) & (~SideSpecifics::promoRank) &
208 Intercepts::getPinRestiction<true>(board.getKingInTurn(), src) & legalDestinations(),
209 {
210 *i = Move { src, dst, MoveTypeAndPromotion::REGULAR_PAWN_MOVE };
211 ++i;
212 });
213
214 // left-capture, promo
216 dst,
217 oppPieces & SideSpecifics::captureLeft(pawnBit) & SideSpecifics::promoRank &
218 Intercepts::getPinRestiction<true>(board.getKingInTurn(), src) & legalDestinations(),
219 {
220 *i = Move { src, dst, MoveTypeAndPromotion::PROMO_QUEEN };
221 ++i;
222
223 *i = Move { src, dst, MoveTypeAndPromotion::PROMO_ROOK };
224 ++i;
225
226 *i = Move { src, dst, MoveTypeAndPromotion::PROMO_BISHOP };
227 ++i;
228
229 *i = Move { src, dst, MoveTypeAndPromotion::PROMO_KNIGHT };
230 ++i;
231 });
232
233 // right-capture, non-promo
235 dst,
236 oppPieces & SideSpecifics::captureRight(pawnBit) & (~SideSpecifics::promoRank) &
237 Intercepts::getPinRestiction<true>(board.getKingInTurn(), src) & legalDestinations(),
238 {
239 *i = Move { src, dst, MoveTypeAndPromotion::REGULAR_PAWN_MOVE };
240 ++i;
241 });
242
243 // right-capture, promo
245 dst,
246 oppPieces & SideSpecifics::captureRight(pawnBit) & SideSpecifics::promoRank &
247 Intercepts::getPinRestiction<true>(board.getKingInTurn(), src) & legalDestinations(),
248 {
249 *i = Move { src, dst, MoveTypeAndPromotion::PROMO_QUEEN };
250 ++i;
251
252 *i = Move { src, dst, MoveTypeAndPromotion::PROMO_ROOK };
253 ++i;
254
255 *i = Move { src, dst, MoveTypeAndPromotion::PROMO_BISHOP };
256 ++i;
257
258 *i = Move { src, dst, MoveTypeAndPromotion::PROMO_KNIGHT };
259 ++i;
260 });
261 });
262 }
263
264 // EP captures
265 if (board.getEpSquare() <= Square::H8)
266 {
268 src,
269 Attacks::getPawnAttackerMask(board.getEpSquare(), turn) & pawns,
270 {
271 // The only legality check we need is the capturer pin check
272 if (Attacks::pinCheck(src, SquareSet { board.getEpSquare() }, board.getKingInTurn(), board.getPinnedPieces()))
273 {
274 *i = Move { src, board.getEpSquare(), MoveTypeAndPromotion::EN_PASSANT };
275 ++i;
276 }
277 });
278 }
279
280 return i;
281}
282
292template <typename IteratorType, MoveGenType type, typename ParamType>
294 const ChessBoard &board,
295 IteratorType i,
296 ParamType legalDestinations) noexcept -> IteratorType
297{
298 if (board.getTurn() == Color::WHITE)
299 return generateMovesForPawnsTempl<IteratorType, type, ParamType, Color::WHITE>(board, i, legalDestinations);
300 else
301 return generateMovesForPawnsTempl<IteratorType, type, ParamType, Color::BLACK>(board, i, legalDestinations);
302}
303
314template <typename IteratorType, MoveGenType type, typename ParamType>
316 const ChessBoard &board,
317 IteratorType i,
318 Square sq,
319 ParamType legalDestinations) noexcept -> IteratorType
320{
321 const SquareSet emptyOrCapture { SquareSet::all() &~ board.getPiecesInTurn() };
322 const SquareSet dstSquares { Attacks::getKnightAttackMask(sq) & emptyOrCapture & legalDestinations() };
323
325 {
327 dst,
328 dstSquares,
329 {
330 *i = Move { sq, dst, MoveTypeAndPromotion::REGULAR_KNIGHT_MOVE };
331 ++i;
332 });
333 }
334 else
335 {
336 i += dstSquares.popcount();
337 }
338
339 return i;
340}
341
356template <typename IteratorType, MoveGenType type, typename ParamType, bool pinned>
358 const ChessBoard &board,
359 IteratorType i,
360 Square sq,
361 ParamType legalDestinations,
362 MoveTypeAndPromotion typeAndPromo) noexcept -> IteratorType
363{
364 const SquareSet emptyOrCapture { SquareSet::all() &~ board.getPiecesInTurn() };
365 const SquareSet dstSquares {
366 Attacks::getBishopAttackMask(sq, board.getOccupancyMask()) &
367 emptyOrCapture &
368 Intercepts::getPinRestiction<pinned>(board.getKingInTurn(), sq) &
369 legalDestinations() };
370
372 {
374 dst,
375 dstSquares,
376 {
377 *i = Move { sq, dst, typeAndPromo };
378 ++i;
379 });
380 }
381 else
382 {
383 i += dstSquares.popcount();
384 }
385
386 return i;
387}
388
403template <typename IteratorType, MoveGenType type, typename ParamType, bool pinned>
405 const ChessBoard &board,
406 IteratorType i,
407 Square sq,
408 ParamType legalDestinations,
409 MoveTypeAndPromotion typeAndPromo) noexcept -> IteratorType
410{
411 const SquareSet emptyOrCapture { SquareSet::all() &~ board.getPiecesInTurn() };
412 const SquareSet dstSquares {
413 Attacks::getRookAttackMask(sq, board.getOccupancyMask()) &
414 emptyOrCapture &
415 Intercepts::getPinRestiction<pinned>(board.getKingInTurn(), sq) &
416 legalDestinations() };
417
419 {
421 dst,
422 dstSquares,
423 {
424 *i = Move { sq, dst, typeAndPromo };
425 ++i;
426 });
427 }
428 else
429 {
430 i += dstSquares.popcount();
431 }
432
433 return i;
434}
435
446template <typename IteratorType>
448 const ChessBoard &board,
449 IteratorType i,
450 SquareSet attackedSquares) noexcept -> IteratorType
451{
452 const SquareSet emptyOrCapture { SquareSet::all() &~ board.getPiecesInTurn() };
453
454 const SquareSet dstSquares {
455 Attacks::getKingAttackMask(board.getKingInTurn()) & emptyOrCapture &~ attackedSquares };
456
458 {
460 dst,
461 dstSquares,
462 {
463 *i = Move { board.getKingInTurn(), dst, MoveTypeAndPromotion::REGULAR_KING_MOVE };
464 ++i;
465 });
466 }
467 else
468 {
469 i += dstSquares.popcount();
470 }
471
472 return i;
473}
474
483template <typename IteratorType>
485 const ChessBoard &board,
486 IteratorType i) noexcept
487{
488 using ParamType = AllLegalDestinationType;
489 constexpr ParamType legalDestinations { };
490
491 i = generateMovesForPawns<IteratorType, MoveGenType::NO_CHECK>(board, i, legalDestinations);
492
494 if (i.hasLegalMoves())
495 return i;
496
498 sq,
499 board.getKnights() & board.getPiecesInTurn() & ~board.getPinnedPieces(),
500 i = generateMovesForKnight<IteratorType, MoveGenType::NO_CHECK>(board, i, sq, legalDestinations));
501
503 if (i.hasLegalMoves())
504 return i;
505
507 sq,
508 board.getBishopsAndQueens() & board.getPiecesInTurn() & ~board.getPinnedPieces(),
509 {
510 const MoveTypeAndPromotion typeAndPromo {
511 (board.getRooksAndQueens() & SquareSet { sq }) != SquareSet { } ?
512 MoveTypeAndPromotion::REGULAR_QUEEN_MOVE :
513 MoveTypeAndPromotion::REGULAR_BISHOP_MOVE
514 };
515 i = generateMovesForBishop<IteratorType, MoveGenType::NO_CHECK, ParamType, false>(board, i, sq, legalDestinations, typeAndPromo);
516 });
517
519 sq,
520 board.getBishopsAndQueens() & board.getPinnedPieces(),
521 {
522 const MoveTypeAndPromotion typeAndPromo {
523 (board.getRooksAndQueens() & SquareSet { sq }) != SquareSet { } ?
524 MoveTypeAndPromotion::REGULAR_QUEEN_MOVE :
525 MoveTypeAndPromotion::REGULAR_BISHOP_MOVE
526 };
527 i = generateMovesForBishop<IteratorType, MoveGenType::NO_CHECK, ParamType, true>(board, i, sq, legalDestinations, typeAndPromo);
528 });
529
530 if constexpr (MoveGenIteratorTraits<IteratorType>::canCompleteEarly)
531 if (i.hasLegalMoves())
532 return i;
533
535 sq,
536 board.getRooksAndQueens() & board.getPiecesInTurn() & ~board.getPinnedPieces(),
537 {
538 const MoveTypeAndPromotion typeAndPromo {
539 (board.getBishopsAndQueens() & SquareSet { sq }) != SquareSet { } ?
540 MoveTypeAndPromotion::REGULAR_QUEEN_MOVE :
541 MoveTypeAndPromotion::REGULAR_ROOK_MOVE
542 };
543 i = generateMovesForRook<IteratorType, MoveGenType::NO_CHECK, ParamType, false>(board, i, sq, legalDestinations, typeAndPromo);
544 });
545
547 sq,
548 board.getRooksAndQueens() & board.getPinnedPieces(),
549 {
550 const MoveTypeAndPromotion typeAndPromo {
551 (board.getBishopsAndQueens() & SquareSet { sq }) != SquareSet { } ?
552 MoveTypeAndPromotion::REGULAR_QUEEN_MOVE :
553 MoveTypeAndPromotion::REGULAR_ROOK_MOVE
554 };
555 i = generateMovesForRook<IteratorType, MoveGenType::NO_CHECK, ParamType, true>(board, i, sq, legalDestinations, typeAndPromo);
556 });
557
558 if constexpr (MoveGenIteratorTraits<IteratorType>::canCompleteEarly)
559 if (i.hasLegalMoves())
560 return i;
561
562 // In no check, we'll do the king and castling moves last. This helps the
563 // LegalMoveDetectorIterator with early exit, since these are a bit more
564 // expensive than the other moves,
565 const SquareSet attackedSquares {
566 Attacks::determineAttackedSquares(
567 board.getOccupancyMask() &~ (board.getKings() & board.getPiecesInTurn()), // remove potentially attacked king
568 board.getPawns() &~ board.getPiecesInTurn(),
569 board.getKnights() &~ board.getPiecesInTurn(),
570 board.getBishopsAndQueens() &~ board.getPiecesInTurn(),
571 board.getRooksAndQueens() &~ board.getPiecesInTurn(),
572 board.getKingNotInTurn(),
573 board.getTurn()) };
574
575 i = generateMovesForKing<IteratorType>(board, i, attackedSquares);
576
577 if constexpr (MoveGenIteratorTraits<IteratorType>::canCompleteEarly)
578 if (i.hasLegalMoves())
579 return i;
580
581 generateMovesForCastlingStoreFnTempl<MoveGenType::NO_CHECK, IteratorStoreMoveFn<IteratorType>, false>(board, attackedSquares, i);
582 generateMovesForCastlingStoreFnTempl<MoveGenType::NO_CHECK, IteratorStoreMoveFn<IteratorType>, true>(board, attackedSquares, i);
583
584 return i;
585}
586
595template <typename IteratorType>
597 const ChessBoard &board,
598 IteratorType i) noexcept
599{
600 using ParamType = ParametrizedLegalDestinationType;
601 ParamType legalDestinations {
602 Intercepts::getInterceptSquares(board.getKingInTurn(), board.getCheckers().firstSquare()) };
603
604 // if we're in check, we'll try the king moves first
605 {
606 const SquareSet attackedSquares {
607 Attacks::determineAttackedSquares(
608 board.getOccupancyMask() &~ (board.getKings() & board.getPiecesInTurn()), // remove potentially attacked king
609 board.getPawns() &~ board.getPiecesInTurn(),
610 board.getKnights() &~ board.getPiecesInTurn(),
611 board.getBishopsAndQueens() &~ board.getPiecesInTurn(),
612 board.getRooksAndQueens() &~ board.getPiecesInTurn(),
613 board.getKingNotInTurn(),
614 board.getTurn()) };
615
616 i = generateMovesForKing<IteratorType>(board, i, attackedSquares);
618 if (i.hasLegalMoves())
619 return i;
620 }
621
622 i = generateMovesForPawns<IteratorType, MoveGenType::CHECK, ParamType>(board, i, legalDestinations);
623
625 if (i.hasLegalMoves())
626 return i;
627
629 sq,
630 board.getKnights() & board.getPiecesInTurn() & ~board.getPinnedPieces(),
631 i = generateMovesForKnight<IteratorType, MoveGenType::CHECK, ParamType>(board, i, sq, legalDestinations));
632
634 if (i.hasLegalMoves())
635 return i;
636
638 sq,
639 board.getBishopsAndQueens() & board.getPiecesInTurn() & ~board.getPinnedPieces(),
640 {
641 const MoveTypeAndPromotion typeAndPromo {
642 (board.getRooksAndQueens() & SquareSet { sq }) != SquareSet { } ?
643 MoveTypeAndPromotion::REGULAR_QUEEN_MOVE :
644 MoveTypeAndPromotion::REGULAR_BISHOP_MOVE
645 };
646 i = generateMovesForBishop<IteratorType, MoveGenType::CHECK, ParamType, false>(board, i, sq, legalDestinations, typeAndPromo);
647 });
648
649 // Note: pinned pieces cannot resolve checks
650
651 if constexpr (MoveGenIteratorTraits<IteratorType>::canCompleteEarly)
652 if (i.hasLegalMoves())
653 return i;
654
656 sq,
657 board.getRooksAndQueens() & board.getPiecesInTurn() & ~board.getPinnedPieces(),
658 {
659 const MoveTypeAndPromotion typeAndPromo {
660 (board.getBishopsAndQueens() & SquareSet { sq }) != SquareSet { } ?
661 MoveTypeAndPromotion::REGULAR_QUEEN_MOVE :
662 MoveTypeAndPromotion::REGULAR_ROOK_MOVE
663 };
664 i = generateMovesForRook<IteratorType, MoveGenType::CHECK, ParamType, false>(board, i, sq, legalDestinations, typeAndPromo);
665 });
666
667 // Note: pinned pieces cannot resolve checks
668
669 if constexpr (MoveGenIteratorTraits<IteratorType>::canCompleteEarly)
670 if (i.hasLegalMoves())
671 return i;
672
673 return i;
674}
675
684template <typename IteratorType>
686 const ChessBoard &board,
687 IteratorType i) noexcept
688{
689 // in double-check, king moves are the only legal moves
690 const SquareSet attackedSquares {
691 Attacks::determineAttackedSquares(
692 board.getOccupancyMask() &~ (board.getKings() & board.getPiecesInTurn()), // remove potentially attacked king
693 board.getPawns() &~ board.getPiecesInTurn(),
694 board.getKnights() &~ board.getPiecesInTurn(),
695 board.getBishopsAndQueens() &~ board.getPiecesInTurn(),
696 board.getRooksAndQueens() &~ board.getPiecesInTurn(),
697 board.getKingNotInTurn(),
698 board.getTurn()) };
699
700 i = generateMovesForKing<IteratorType>(board, i, attackedSquares);
701
702 return i;
703}
704
733template <MoveGenType type, typename IteratorType>
734inline IteratorType generateMovesIterTempl(
735 const ChessBoard &board,
736 IteratorType i) noexcept
737{
738 if constexpr (type == MoveGenType::NO_CHECK)
739 {
740 // all destinations are ok as long as the move is ok
741 i = generateAllLegalMovesTemplNoCheck<IteratorType>(board, i);
742 }
743 else if constexpr (type == MoveGenType::CHECK)
744 {
745 // must capture the checker or block the check
746 i = generateAllLegalMovesTemplInCheck<IteratorType>(board, i);
747 }
748 else
749 {
750 static_assert(type == MoveGenType::DOUBLE_CHECK);
751
752 // king moves only
753 i = generateAllLegalMovesTemplInDoubleCheck<IteratorType>(board, i);
754 }
755
756 return i;
757}
758
765template <MoveGenType type>
766std::size_t generateMovesTempl(const ChessBoard &board, MoveList &moves) noexcept
767{
768 const MoveList::iterator i { generateMovesIterTempl<type>(board, moves.begin()) };
769 return i - moves.begin();
770}
771
777template <MoveGenType type>
778std::size_t getNumberOfLegalMovesTempl(const ChessBoard &board) noexcept
779{
780 return generateMovesIterTempl<type>(board, LegalMoveCounterIterator { }).getNumberOfLegalMoves();
781}
782
788template <MoveGenType type>
789bool hasLegalMovesTempl(const ChessBoard &board) noexcept
790{
791 const LegalMoveDetectorIterator legalMovesIterator {
792 generateMovesIterTempl<type>(board, LegalMoveDetectorIterator { }) };
793
794 return legalMovesIterator.hasLegalMoves();
795}
796
797}
798
799#endif
The chessboard.
Definition chessboard.h:589
bool hasLegalMoves() const noexcept
Definition chessboard-priv.h:58
A legal move. Important: see the note!
Definition chessboard.h:198
Set of squares. Implemented using a bit-mask.
Definition chessboard-types-squareset.h:35
constexpr std::uint_fast8_t popcount() const noexcept
Returns the number of squares in the set.
Definition chessboard-types-squareset.h:95
std::array< CompactMove, 256U > MoveList
Move list returned by ChessBoard::generateMoves().
Definition chessboard.h:508
MoveTypeAndPromotion
Move type (4 bits, range: 0..15)
Definition chessboard.h:91
Square
Named square.
Definition chessboard-types.h:122
#define SQUARESET_ENUMERATE(sq, squareSet,...)
Enumerates all squares in a square set.
Definition chessboard-types-squareset.h:623
@ REGULAR_PAWN_MOVE
Regular non-capturing or capturing move (no promotion or en passant)
Definition chessboard-types-squareset.h:30
std::size_t generateMovesTempl(const ChessBoard &board, MoveList &moves) noexcept
Generates all legal moves for a position.
Definition chessboard-movegen-all.h:766
IteratorType generateAllLegalMovesTemplInCheck(const ChessBoard &board, IteratorType i) noexcept
Generates all legal moves when in check (but not in double check)
Definition chessboard-movegen-all.h:596
auto generateMovesForPawnsTempl(const ChessBoard &board, IteratorType i, ParamType legalDestinations) noexcept -> IteratorType
Generates legal pawn moves, the actual implementation.
Definition chessboard-movegen-all.h:37
auto generateMovesForRook(const ChessBoard &board, IteratorType i, Square sq, ParamType legalDestinations, MoveTypeAndPromotion typeAndPromo) noexcept -> IteratorType
Generates legal rook moves for queen or rook.
Definition chessboard-movegen-all.h:404
auto generateMovesForBishop(const ChessBoard &board, IteratorType i, Square sq, ParamType legalDestinations, MoveTypeAndPromotion typeAndPromo) noexcept -> IteratorType
Generates legal bishop moves for queen or bishop.
Definition chessboard-movegen-all.h:357
auto generateMovesForKing(const ChessBoard &board, IteratorType i, SquareSet attackedSquares) noexcept -> IteratorType
Generates legal king moves.
Definition chessboard-movegen-all.h:447
constexpr MoveTypeAndPromotion pieceToTypeAndPromotion(Piece promotion) noexcept
Definition chessboard-movegen.h:75
IteratorType generateAllLegalMovesTemplNoCheck(const ChessBoard &board, IteratorType i) noexcept
Generates all legal moves when not in check.
Definition chessboard-movegen-all.h:484
bool hasLegalMovesTempl(const ChessBoard &board) noexcept
Determines whether there are any legal moves.
Definition chessboard-movegen-all.h:789
auto generateMovesForPawns(const ChessBoard &board, IteratorType i, ParamType legalDestinations) noexcept -> IteratorType
Generates legal pawn moves, dispatch for side-to-move.
Definition chessboard-movegen-all.h:293
IteratorType generateMovesIterTempl(const ChessBoard &board, IteratorType i) noexcept
Generates all legal moves for a specific iterator type.
Definition chessboard-movegen-all.h:734
IteratorType generateAllLegalMovesTemplInDoubleCheck(const ChessBoard &board, IteratorType i) noexcept
Generates all legal moves when in double check.
Definition chessboard-movegen-all.h:685
auto generateMovesForKnight(const ChessBoard &board, IteratorType i, Square sq, ParamType legalDestinations) noexcept -> IteratorType
Generates legal knight moves.
Definition chessboard-movegen-all.h:315
std::size_t getNumberOfLegalMovesTempl(const ChessBoard &board) noexcept
Returns the number of legal moves for a position.
Definition chessboard-movegen-all.h:778
static constexpr bool storesMoves() noexcept