MoveGeneration.h 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. #ifndef CHESSY_MOVEGENERATION_H
  2. #define CHESSY_MOVEGENERATION_H
  3. #include "BitBoard.h"
  4. #include <string>
  5. #include <vector>
  6. #include <array>
  7. namespace chessy
  8. {
  9. // forward declaration
  10. class ChessGame;
  11. using Leftright = int;
  12. const Leftright LEFT = -1;
  13. const Leftright RIGHT = 1;
  14. class PositionSet;
  15. template<Side side>
  16. class PawnPushGenerator;
  17. template<Side side>
  18. class PromotionGenerator;
  19. template<Side side>
  20. class PawnDoublePushGenerator;
  21. template<Side side, Leftright leftright>
  22. class PawnCaptureGenerator;
  23. class KnightMoveGenerator;
  24. class PrimitiveQueenMoveGenerator;
  25. class PrimitiveRookMoveGenerator;
  26. class PrimitiveBishopMoveGenerator;
  27. class KingMoveGenerator;
  28. template<Side side>
  29. class CastlingGenerator;
  30. template<Side side>
  31. void generatePawnPushes(const ChessGame& cg, std::vector<Move>& moves);
  32. template<Side side>
  33. void generatePawnDoublePushes(const ChessGame& cg, std::vector<Move>& moves);
  34. template<Side side>
  35. void generatePawnCaptures(const ChessGame& cg, std::vector<Move>& moves);
  36. template<Side side>
  37. void generatePawnPromotions(const ChessGame& cg, std::vector<Move>& moves);
  38. template<Side side>
  39. void generateKnightMoves(const ChessGame& cg, std::vector<Move>& moves);
  40. template<Side side>
  41. void generateQueenMoves(const ChessGame& cg, std::vector<Move>& moves);
  42. template<Side side>
  43. void generateRookMoves(const ChessGame& cg, std::vector<Move>& moves);
  44. template<Side side>
  45. void generateBishopMoves(const ChessGame& cg, std::vector<Move>& moves);
  46. template<Side side>
  47. void generateKingMoves(const ChessGame& cg, std::vector<Move>& moves);
  48. template<Side side>
  49. void generateCastling(const ChessGame& cg, std::vector<Move>& moves);
  50. template<Side side>
  51. void generateAllMoves(const ChessGame& cg, std::vector<Move>& moves);
  52. }
  53. class chessy::PositionSet
  54. {
  55. Bitboard bitboard;
  56. public:
  57. inline PositionSet(Bitboard b) : bitboard{ b } {}
  58. inline void setBitboard(Bitboard b) { bitboard = b; }
  59. inline Bitboard getBitboard(void) const { return bitboard; }
  60. struct PositionSetIterator
  61. {
  62. Bitboard bitboard;
  63. inline Index operator *(void) const
  64. {
  65. return Index{ int8_t(trailingZeroes(bitboard.bits)) };
  66. }
  67. inline void operator ++(void)
  68. {
  69. bitboard.bits &= bitboard.bits - 1ULL; // remove least significant one bit
  70. }
  71. inline bool operator !=(const PositionSetIterator& psi) const
  72. {
  73. return bitboard != psi.bitboard;
  74. }
  75. };
  76. inline PositionSetIterator begin(void) const
  77. {
  78. return PositionSetIterator{ bitboard };
  79. }
  80. inline static PositionSetIterator end(void)
  81. {
  82. return PositionSetIterator{ 0 };
  83. }
  84. };
  85. template<chessy::Side side>
  86. class chessy::PawnPushGenerator
  87. {
  88. const ChessGame& chessGame;
  89. struct MoveIterator
  90. {
  91. PositionSet::PositionSetIterator pawnPushes;
  92. inline Move operator *(void) const
  93. {
  94. Index pp = *pawnPushes;
  95. return Move{ int8_t(pp + (side != WHITE_SIDE ? 8 : -8)), pp };
  96. }
  97. inline void operator ++(void)
  98. {
  99. ++pawnPushes;
  100. }
  101. inline bool operator !=(const MoveIterator& psi) const
  102. {
  103. return pawnPushes != psi.pawnPushes;
  104. }
  105. };
  106. public:
  107. inline PawnPushGenerator(const ChessGame& cg) : chessGame{ cg } {}
  108. MoveIterator begin(void) const;
  109. MoveIterator end(void) const;
  110. };
  111. // TODO: rewrite better
  112. template<chessy::Side side>
  113. class chessy::PromotionGenerator
  114. {
  115. const ChessGame& chessGame;
  116. struct MoveIterator
  117. {
  118. const ChessGame& chessGame;
  119. PositionSet::PositionSetIterator pawns;
  120. PieceType promotionType;
  121. char direction;
  122. inline Move operator *(void) const
  123. {
  124. Index pp = *pawns;
  125. return Move{ pp, int8_t(pp + (side == WHITE_SIDE ? 8 : -8) +
  126. direction), promotionType };
  127. }
  128. private:
  129. void next(void);
  130. bool valid(void) const;
  131. public:
  132. inline void operator ++(void)
  133. {
  134. do {
  135. next();
  136. } while(!valid());
  137. }
  138. inline bool operator !=(const MoveIterator& psi) const
  139. {
  140. return pawns != psi.pawns;
  141. }
  142. };
  143. public:
  144. inline PromotionGenerator(const ChessGame& cg) : chessGame{ cg } {}
  145. MoveIterator begin(void) const;
  146. MoveIterator end(void) const;
  147. };
  148. template<chessy::Side side>
  149. class chessy::PawnDoublePushGenerator
  150. {
  151. const ChessGame& chessGame;
  152. struct MoveIterator
  153. {
  154. PositionSet::PositionSetIterator pawnPushes;
  155. inline Move operator *(void) const
  156. {
  157. Index pp = *pawnPushes;
  158. return Move{ int8_t(pp + (side != WHITE_SIDE ? 16 : -16)), pp };
  159. }
  160. inline void operator ++(void)
  161. {
  162. ++pawnPushes;
  163. }
  164. inline bool operator !=(const MoveIterator& psi) const
  165. {
  166. return pawnPushes != psi.pawnPushes;
  167. }
  168. };
  169. public:
  170. inline PawnDoublePushGenerator(const ChessGame& cg) : chessGame{ cg } {}
  171. MoveIterator begin(void) const;
  172. MoveIterator end(void) const;
  173. };
  174. template<chessy::Side side, chessy::Leftright leftright>
  175. class chessy::PawnCaptureGenerator
  176. {
  177. const ChessGame& chessGame;
  178. struct MoveIterator
  179. {
  180. PositionSet::PositionSetIterator pawnPushes;
  181. inline Move operator *(void) const
  182. {
  183. Index pp = *pawnPushes;
  184. return Move{
  185. int8_t(pp + (side != WHITE_SIDE ? 8 : -8) - leftright), pp
  186. };
  187. }
  188. inline void operator ++(void)
  189. {
  190. ++pawnPushes;
  191. }
  192. inline bool operator !=(const MoveIterator& psi) const
  193. {
  194. return pawnPushes != psi.pawnPushes;
  195. }
  196. };
  197. public:
  198. inline PawnCaptureGenerator(const ChessGame& cg) : chessGame{ cg } {}
  199. MoveIterator begin(void) const;
  200. MoveIterator end(void) const;
  201. };
  202. /*!
  203. * extends \link PositionSet \endlink so that all possible destinations for
  204. * a knight can be iterated over.
  205. */
  206. class chessy::KnightMoveGenerator :
  207. public PositionSet
  208. {
  209. static const std::array<Bitboard, 64> moveSets;
  210. public:
  211. inline KnightMoveGenerator(Index knight, Bitboard occupied) :
  212. PositionSet{ moveSets[knight] & ~occupied } {}
  213. private:
  214. static Bitboard generateFromIndex(Index i);
  215. static std::array<Bitboard, 64> generateKnightMoves(void);
  216. };
  217. /*!
  218. * uses a primitive algorithm to calculate all possible move destinations
  219. * for a queen.
  220. */
  221. class chessy::PrimitiveQueenMoveGenerator :
  222. public PositionSet
  223. {
  224. protected:
  225. inline PrimitiveQueenMoveGenerator(Index i, Bitboard enemies, Bitboard friendly,
  226. bool straight, bool diagonal) :
  227. PositionSet{ generateAttackSet(i, enemies, friendly, straight, diagonal) } {}
  228. public:
  229. inline PrimitiveQueenMoveGenerator(Index i, Bitboard enemies,
  230. Bitboard friendly) :
  231. PrimitiveQueenMoveGenerator{ i, enemies, friendly, true, true } {}
  232. private:
  233. Bitboard generateAttackSet(Index i, Bitboard enemies, Bitboard friendly,
  234. bool straight, bool diagonal);
  235. };
  236. class chessy::PrimitiveBishopMoveGenerator :
  237. public PrimitiveQueenMoveGenerator
  238. {
  239. public:
  240. inline PrimitiveBishopMoveGenerator(Index i, Bitboard enemies,
  241. Bitboard friendly) :
  242. // bishop moves are actually just diagonal queen moves
  243. PrimitiveQueenMoveGenerator{ i, enemies, friendly, false, true } {}
  244. };
  245. class chessy::PrimitiveRookMoveGenerator :
  246. public PrimitiveQueenMoveGenerator
  247. {
  248. public:
  249. inline PrimitiveRookMoveGenerator(Index i, Bitboard enemies,
  250. Bitboard friendly) :
  251. // rook moves are actually just straight queen moves
  252. PrimitiveQueenMoveGenerator{ i, enemies, friendly, true, false } {}
  253. };
  254. class chessy::KingMoveGenerator :
  255. public PositionSet
  256. {
  257. public:
  258. inline KingMoveGenerator(Bitboard king, Bitboard friendly) :
  259. PositionSet{ generateKingMoves(king) & ~friendly } {}
  260. private:
  261. Bitboard generateKingMoves(Bitboard king);
  262. };
  263. template<chessy::Side side>
  264. class chessy::CastlingGenerator :
  265. public PositionSet
  266. {
  267. public:
  268. CastlingGenerator(const ChessGame& game);
  269. };
  270. #endif // CHESSY_MOVEGENERATION_H