Search.h 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. #ifndef CHESSY_SEARCH_H
  2. #define CHESSY_SEARCH_H
  3. #include "ChessGame.h"
  4. #include <utility>
  5. namespace chessy
  6. {
  7. template<typename T>
  8. class Search;
  9. class MinimaxN;
  10. }
  11. template<typename T>
  12. class chessy::Search
  13. {
  14. T handler;
  15. ChessGame& game;
  16. Board& board;
  17. Bitboard whites;
  18. Bitboard blacks;
  19. public:
  20. inline Search(T&& handler, ChessGame& game) :
  21. handler{ handler }, game{ game }, board{ game.getBoard() },
  22. whites{ board.getWhites() }, blacks{ board.getBlacks() } {}
  23. template<Side side, typename... Args>
  24. inline void iterateAll(Args&&... args);
  25. template<Side side, typename... Args>
  26. inline void iterateKnights(Args&&... args);
  27. template<Side side, typename... Args>
  28. inline void iterateBishops(Args&&... args);
  29. template<Side side, typename... Args>
  30. inline void iterateRooks(Args&&... args);
  31. template<Side side, typename... Args>
  32. inline void iterateQueens(Args&&... args);
  33. template<Side side, typename... Args>
  34. inline void iterateKing(Args&&... args);
  35. template<Side side, typename... Args>
  36. inline void iterateCastling(Args&&... args);
  37. template<Side side, typename... Args>
  38. inline void iteratePawns(Args&&... args);
  39. template<Side side, typename... Args>
  40. inline void iterateSinglePawnPushes(Args&&... args);
  41. template<Side side, typename... Args>
  42. inline void iterateDoublePawnPushes(Args&&... args);
  43. template<Side side, typename... Args>
  44. inline void iteratePawnCaptures(Args&&... args);
  45. template<Side side, typename... Args>
  46. inline void iteratePromotions(Args&&... args);
  47. template<Side side, typename... Args>
  48. inline void iterateEnPassant(Args&&... args);
  49. private:
  50. template<Side side>
  51. inline Bitboard friends(void) const
  52. {
  53. return side == WHITE_SIDE ? whites : blacks;
  54. }
  55. template<Side side>
  56. inline Bitboard enemies(void) const
  57. {
  58. return side == WHITE_SIDE ? blacks : whites;
  59. }
  60. };
  61. class chessy::MinimaxN
  62. {
  63. public:
  64. bool operator () (int a, int b) {
  65. return true;
  66. }
  67. };
  68. /*inline void aga() {
  69. chessy::ChessGame cg;
  70. chessy::MinimaxN mm;
  71. chessy::Search<chessy::MinimaxN> search = { mm, cg };
  72. search.iterateAll(5, 7);
  73. }*/
  74. template<typename T>
  75. template<chessy::Side side, typename... Args>
  76. inline void chessy::Search<T>::iterateAll(Args&&... args)
  77. {
  78. iteratePawns<side, Args...>(std::forward<Args>(args)...);
  79. iterateKnights<side, Args...>(std::forward<Args>(args)...);
  80. iterateBishops<side, Args...>(std::forward<Args>(args)...);
  81. iterateRooks<side, Args...>(std::forward<Args>(args)...);
  82. iterateQueens<side, Args...>(std::forward<Args>(args)...);
  83. iterateKing<side, Args...>(std::forward<Args>(args)...);
  84. iterateCastling<side, Args...>(std::forward<Args>(args)...);
  85. }
  86. template<typename T>
  87. template<chessy::Side side, typename... Args>
  88. inline void chessy::Search<T>::iterateKnights(Args&&... args)
  89. {
  90. MoveInfo moveInfo;
  91. Bitboard& ns = board.getKnights<side>();
  92. PositionSet knights{ ns };
  93. moveInfo.movedPiece = PieceType::KNIGHT;
  94. for (auto knight : knights) {
  95. for (auto pos : KnightMoveGenerator{ knight, friends<side>() }) {
  96. moveInfo.move = Move{ knight, pos };
  97. handler(moveInfo, std::forward<Args>(args)...);
  98. }
  99. }
  100. }
  101. template<typename T>
  102. template<chessy::Side side, typename... Args>
  103. inline void chessy::Search<T>::iterateBishops(Args&&... args)
  104. {
  105. MoveInfo moveInfo;
  106. moveInfo.movedPiece = PieceType::BISHOP;
  107. PositionSet bishops { board.getBishops<side>() };
  108. for (auto bishop : bishops) {
  109. for (auto pos : PrimitiveBishopMoveGenerator{
  110. bishop, enemies<side>(), friends<side>() }) {
  111. moveInfo.move = Move{ bishop, pos };
  112. handler(moveInfo, std::forward<Args>(args)...);
  113. }
  114. }
  115. }
  116. template<typename T>
  117. template<chessy::Side side, typename... Args>
  118. inline void chessy::Search<T>::iterateRooks(Args&&... args)
  119. {
  120. MoveInfo moveInfo;
  121. moveInfo.movedPiece = PieceType::ROOK;
  122. PositionSet rooks { board.getRooks<side>() };
  123. for (auto rook : rooks) {
  124. for (auto pos : PrimitiveRookMoveGenerator{
  125. rook, enemies<side>(), friends<side>() }) {
  126. moveInfo.move = Move{ rook, pos };
  127. handler(moveInfo, std::forward<Args>(args)...);
  128. }
  129. }
  130. }
  131. template<typename T>
  132. template<chessy::Side side, typename... Args>
  133. inline void chessy::Search<T>::iterateQueens(Args&&... args)
  134. {
  135. MoveInfo moveInfo;
  136. moveInfo.movedPiece = PieceType::QUEEN;
  137. PositionSet queens { board.getQueens<side>() };
  138. for (auto queen : queens) {
  139. for (auto pos : PrimitiveQueenMoveGenerator{
  140. queen, enemies<side>(), friends<side>() }) {
  141. moveInfo.move = Move{ queen, pos };
  142. handler(moveInfo, std::forward<Args>(args)...);
  143. }
  144. }
  145. }
  146. template<typename T>
  147. template<chessy::Side side, typename... Args>
  148. inline void chessy::Search<T>::iterateKing(Args&&... args)
  149. {
  150. MoveInfo moveInfo;
  151. moveInfo.movedPiece = PieceType::KING;
  152. Bitboard king = board.getKing<side>();
  153. for (auto pos : KingMoveGenerator{ king, friends<side>() }) {
  154. moveInfo.move = Move{ king.getLeastSignificantBit(), pos };
  155. handler(moveInfo, std::forward<Args>(args)...);
  156. }
  157. }
  158. template<typename T>
  159. template<chessy::Side side, typename... Args>
  160. inline void chessy::Search<T>::iterateCastling(Args&&... args)
  161. {
  162. Bitboard king = board.getKing<side>();
  163. Bitboard allOccupied = whites | blacks;
  164. MoveInfo moveInfo;
  165. moveInfo.movedPiece = PieceType::KING;
  166. if (game.getCanCastleKingSide(side)) {
  167. Bitboard target = king.bits >> 2; // move king to the right
  168. Bitboard rook = king.bits << 3;
  169. Bitboard rookTarget = king.bits >> 1;
  170. if (!(target & allOccupied) &&
  171. !(rookTarget & allOccupied)) {
  172. moveInfo.move = Move{ king.getLeastSignificantBit(),
  173. target.getLeastSignificantBit(), true };
  174. handler(moveInfo, std::forward<Args>(args)...);
  175. }
  176. }
  177. if (game.getCanCastleQueenSide(side)) {
  178. Bitboard target = king.bits << 2; // move king to the left
  179. Bitboard rook = king.bits >> 3;
  180. Bitboard rookTarget = king.bits << 1;
  181. if (!(target & allOccupied) &&
  182. !(rookTarget & allOccupied)) {
  183. moveInfo.move = Move{ king.getLeastSignificantBit(),
  184. target.getLeastSignificantBit(), true };
  185. handler(moveInfo, std::forward<Args>(args)...);
  186. }
  187. }
  188. }
  189. template<typename T>
  190. template<chessy::Side side, typename... Args>
  191. inline void chessy::Search<T>::iterateSinglePawnPushes(Args&&... args)
  192. {
  193. MoveInfo moveInfo;
  194. moveInfo.movedPiece = PieceType::PAWN;
  195. PawnPushGenerator<side> mg{ game };
  196. for (Move push : mg) {
  197. moveInfo.move = push;
  198. handler(moveInfo, std::forward<Args>(args)...);
  199. }
  200. }
  201. template<typename T>
  202. template<chessy::Side side, typename... Args>
  203. inline void chessy::Search<T>::iterateDoublePawnPushes(Args&&... args)
  204. {
  205. MoveInfo moveInfo;
  206. moveInfo.movedPiece = PieceType::PAWN;
  207. PawnDoublePushGenerator<side> mg{ game };
  208. for (Move push : mg) {
  209. moveInfo.move = push;
  210. handler(moveInfo, std::forward<Args>(args)...);
  211. }
  212. }
  213. template<typename T>
  214. template<chessy::Side side, typename... Args>
  215. inline void chessy::Search<T>::iteratePawnCaptures(Args&&... args)
  216. {
  217. MoveInfo moveInfo;
  218. moveInfo.movedPiece = PieceType::PAWN;
  219. PawnCaptureGenerator<side, LEFT> mgl{ game };
  220. for (Move push : mgl) {
  221. moveInfo.move = push;
  222. handler(moveInfo, std::forward<Args>(args)...);
  223. }
  224. PawnCaptureGenerator<side, RIGHT> mgr{ game };
  225. for (Move push : mgr) {
  226. moveInfo.move = push;
  227. handler(moveInfo, std::forward<Args>(args)...);
  228. }
  229. }
  230. template<typename T>
  231. template<chessy::Side side, typename... Args>
  232. inline void chessy::Search<T>::iteratePromotions(Args&&... args)
  233. {
  234. MoveInfo moveInfo;
  235. moveInfo.movedPiece = PieceType::PAWN;
  236. PromotionGenerator<side> pg{ game };
  237. for (Move promotion : pg) {
  238. moveInfo.move = promotion;
  239. handler(moveInfo, std::forward<Args>(args)...);
  240. }
  241. }
  242. template<typename T>
  243. template<chessy::Side side, typename... Args>
  244. inline void chessy::Search<T>::iterateEnPassant(Args&&... args)
  245. {
  246. MoveInfo moveInfo;
  247. moveInfo.movedPiece = PieceType::PAWN;
  248. Index enPassant = game.getEnPassantIndex();
  249. if (enPassant.index != -1) {
  250. Bitboard pawns = board.getPawns<side>();
  251. int rowIndex = side == WHITE_SIDE ? 4 : 3;
  252. int targetRowIndex = side == WHITE_SIDE ? 5 : 2;
  253. int columnIndex = enPassant.index;
  254. Bitboard pawnColumns = 0;
  255. if (columnIndex > 0)
  256. pawnColumns |= Bitboard::getColumn(columnIndex - 1);
  257. if (columnIndex < 7)
  258. pawnColumns |= Bitboard::getColumn(columnIndex + 1);
  259. pawns &= rowIndex & pawnColumns;
  260. moveInfo.enPassantTarget = Index{ enPassant.index, rowIndex };
  261. Index target{ enPassant.index, targetRowIndex };
  262. PositionSet sources = pawns;
  263. for (auto source : sources) {
  264. moveInfo.move = Move{ source, target };
  265. handler(moveInfo, std::forward<Args>(args)...);
  266. }
  267. }
  268. }
  269. template<typename T>
  270. template<chessy::Side side, typename... Args>
  271. inline void chessy::Search<T>::iteratePawns(Args&&... args)
  272. {
  273. iterateSinglePawnPushes<side, Args...>(std::forward<Args>(args)...);
  274. iterateDoublePawnPushes<side, Args...>(std::forward<Args>(args)...);
  275. iteratePawnCaptures<side, Args...>(std::forward<Args>(args)...);
  276. iteratePromotions<side, Args...>(std::forward<Args>(args)...);
  277. iterateEnPassant<side, Args...>(std::forward<Args>(args)...);
  278. }
  279. #endif // CHESSY_SEARCH_H