HooverChessUtils_PgnReader 0.9.0
Loading...
Searching...
No Matches
chessboard-movegen.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_H_INCLUDED
18#define HOOVER_CHESS_UTILS__PGN_READER__CHESSBOARD_MOVEGEN_H_INCLUDED
19
20
21#include "chessboard.h"
22
23#include "bittricks.h"
24#include "bitboard-attacks.h"
25#include "bitboard-intercepts.h"
26#include "chessboard-priv.h"
27#include "pawn-lookups.h"
28
29#include <algorithm>
30#include <array>
31#include <bit>
32#include <cassert>
33#include <cinttypes>
34#include <utility>
35#include <tuple>
36#include <type_traits>
37
39{
40
42{
43private:
44 static std::array<MoveGenFunctions, 3U> m_fns;
45
46public:
47 static inline const MoveGenFunctions &getFunctions(MoveGenType type) noexcept
48 {
49 const std::size_t index { static_cast<std::size_t>(type) };
50
51 assert(index < m_fns.size());
52 return m_fns[index];
53 }
54};
55
56
57
58template <bool shortCastling>
60
61template <>
63{
64 static constexpr std::uint8_t kingTargetColumn { 2U };
65 static constexpr std::uint8_t rookTargetColumn { 3U };
66};
67
68template <>
70{
71 static constexpr std::uint8_t kingTargetColumn { 6U };
72 static constexpr std::uint8_t rookTargetColumn { 5U };
73};
74
75inline constexpr MoveTypeAndPromotion pieceToTypeAndPromotion(Piece promotion) noexcept
76{
77 using UnderlyingType = PieceUnderlyingType;
78 static_assert(std::is_same_v<UnderlyingType, PieceUnderlyingType>);
79
80 constexpr UnderlyingType bias =
81 static_cast<UnderlyingType>(MoveTypeAndPromotion::PROMO_KNIGHT) -
82 static_cast<UnderlyingType>(Piece::KNIGHT);
83
84 static_assert(
85 (static_cast<UnderlyingType>(Piece::KNIGHT) + bias) ==
86 static_cast<UnderlyingType>(MoveTypeAndPromotion::PROMO_KNIGHT));
87 static_assert(
88 (static_cast<UnderlyingType>(Piece::BISHOP) + bias) ==
89 static_cast<UnderlyingType>(MoveTypeAndPromotion::PROMO_BISHOP));
90 static_assert(
91 (static_cast<UnderlyingType>(Piece::ROOK) + bias) ==
92 static_cast<UnderlyingType>(MoveTypeAndPromotion::PROMO_ROOK));
93 static_assert(
94 (static_cast<UnderlyingType>(Piece::KNIGHT) + bias) ==
95 static_cast<UnderlyingType>(MoveTypeAndPromotion::PROMO_KNIGHT));
96
97 assert(promotion >= Piece::KNIGHT && promotion <= Piece::QUEEN);
98 [[assume(promotion >= Piece::KNIGHT && promotion <= Piece::QUEEN)]];
99
100 return static_cast<MoveTypeAndPromotion>(static_cast<UnderlyingType>(promotion) + bias);
101}
102
103// Note about legal destinations during generateMoves().
104//
105// Legal destinations for a non-king move. Rules:
106// - No checkers:
107// - any destination is legal (as long as the move is otherwise legal)
108// - One checker:
109// - Checker must be captured; OR
110// - Check must be intercepted (ray attacks only)
111// - Two checkers or more: (>= 3 cannot be reached legally)
112// - No legal destinations (king move is forced when in double-check)
113
115{
116 constexpr SquareSet operator () () const noexcept
117 {
118 return SquareSet::all();
119 }
120};
121
142
143template <MoveGenType type>
144inline SquareSet blocksAllChecksMaskTempl(Square kingSq, SquareSet checkers, Square dst) noexcept;
145
146template <>
148{
149 static_cast<void>(kingSq);
150 static_cast<void>(checkers);
151 static_cast<void>(dst);
152
153 return SquareSet::all(); // no checks to block
154}
155
156template <>
158{
159 return
160 (Intercepts::getInterceptSquares(kingSq, checkers.firstSquare()) & SquareSet { dst }).allIfAny();
161}
162
174template <MoveGenType type, typename MoveStoreFn, bool shortCastling>
176 const ChessBoard &board,
177 SquareSet attackedSquares,
178 typename MoveStoreFn::Store &store) noexcept
179{
180 // When in check, castling is not legal. Since the caller is supposed to
181 // classify the position before calling this function, we'll just ensure
182 // here that we're not being called when in check.
183 static_assert(type == MoveGenType::NO_CHECK);
184
185 static_assert(static_cast<std::uint8_t>(Color::WHITE) == 0U);
186 static_assert(static_cast<std::uint8_t>(Color::BLACK) == 8U);
187
188 using CastlingSideSpecifics = CastlingSideSpecificsTempl<shortCastling>;
189
190 const Color turn { board.getTurn() };
191 const Square sqRook { board.getCastlingRook(turn, shortCastling) };
192
193 // do we have rights to castle?
194 if (sqRook == Square::NONE)
195 return;
196
197 const std::uint8_t targetRowAdd = (-static_cast<std::uint8_t>(turn)) & 63U;
198 const Square sqKingTarget { static_cast<std::uint8_t>(CastlingSideSpecifics::kingTargetColumn + targetRowAdd) };
199 const Square sqRookTarget { static_cast<std::uint8_t>(CastlingSideSpecifics::rookTargetColumn + targetRowAdd) };
200
201 // note: (startSq, endSq]
202 const SquareSet kingPathHalfOpen { Intercepts::getInterceptSquares(board.getKingInTurn(), sqKingTarget) };
203 const SquareSet rookPathHalfOpen { Intercepts::getInterceptSquares(sqRook, sqRookTarget) };
204
205 const SquareSet requiredEmptySquares {
206 (kingPathHalfOpen | rookPathHalfOpen) &~ SquareSet { board.getKingInTurn(), sqRook } };
207
208 if (((requiredEmptySquares & board.getOccupancyMask()) | // all squares between king and rook empty?
209 (SquareSet { sqRook } & board.getPinnedPieces()) | // castling rook not pinned?
210 (kingPathHalfOpen & attackedSquares) // king path is not attacked?
211 ) != SquareSet { })
212 return;
213
214 if constexpr (shortCastling)
215 MoveStoreFn::storeMove(store, Move { board.getKingInTurn(), sqRook, MoveTypeAndPromotion::CASTLING_SHORT });
216 else
217 MoveStoreFn::storeMove(store, Move { board.getKingInTurn(), sqRook, MoveTypeAndPromotion::CASTLING_LONG });
218}
219
220}
221
222#endif
The chessboard.
Definition chessboard.h:589
static SquareSet getInterceptSquares(Square kingSq, Square checkerSq) noexcept
Returns the set of squares that intercepts a check.
Definition bitboard-intercepts.h:66
static std::array< MoveGenFunctions, 3U > m_fns
Definition chessboard-movegen.h:44
static const MoveGenFunctions & getFunctions(MoveGenType type) noexcept
Definition chessboard-movegen.h:47
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 SquareSet allIfAny() const noexcept
Conditional.
Definition chessboard-types-squareset.h:547
static constexpr SquareSet all() noexcept
Returns a set of all squares.
Definition chessboard-types-squareset.h:460
MoveTypeAndPromotion
Move type (4 bits, range: 0..15)
Definition chessboard.h:91
Piece
Named piece.
Definition chessboard-types.h:204
Color
Color of a piece or side to move.
Definition chessboard-types.h:194
Square
Named square.
Definition chessboard-types.h:122
std::uint_fast8_t PieceUnderlyingType
Underlying type of Piece
Definition chessboard-types.h:56
@ BLACK
Black piece or black side to move.
@ WHITE
White piece or white side to move.
MoveGenType
Move generator type.
Definition chessboard.h:519
@ NO_CHECK
Move generator for when the king is not in check. All moves are considered.
Definition chessboard-types-squareset.h:30
void generateMovesForCastlingStoreFnTempl(const ChessBoard &board, SquareSet attackedSquares, typename MoveStoreFn::Store &store) noexcept
Generates the legal castling move, if any.
Definition chessboard-movegen.h:175
constexpr MoveTypeAndPromotion pieceToTypeAndPromotion(Piece promotion) noexcept
Definition chessboard-movegen.h:75
SquareSet blocksAllChecksMaskTempl(Square kingSq, SquareSet checkers, Square dst) noexcept
constexpr SquareSet blocksAllChecksMaskTempl< MoveGenType::NO_CHECK >(Square kingSq, SquareSet checkers, Square dst) noexcept
Definition chessboard-movegen.h:147
SquareSet blocksAllChecksMaskTempl< MoveGenType::CHECK >(Square kingSq, SquareSet checkers, Square dst) noexcept
Definition chessboard-movegen.h:157
constexpr SquareSet operator()() const noexcept
Definition chessboard-movegen.h:116
Move generator functions.
Definition chessboard.h:1490
SquareSet m_legalDestinations
Definition chessboard-movegen.h:124
ParametrizedLegalDestinationType(ParametrizedLegalDestinationType &&)=default
ParametrizedLegalDestinationType(const ParametrizedLegalDestinationType &)=default
constexpr SquareSet operator()() const noexcept
Definition chessboard-movegen.h:137
ParametrizedLegalDestinationType & operator=(const ParametrizedLegalDestinationType &) &=default
constexpr ParametrizedLegalDestinationType(SquareSet legalDestinations) noexcept
Definition chessboard-movegen.h:126