#ifndef CHESSY_SEARCH_H #define CHESSY_SEARCH_H #include "ChessGame.h" #include namespace chessy { template class Search; class MinimaxN; } template class chessy::Search { T handler; ChessGame& game; Board& board; Bitboard whites; Bitboard blacks; public: inline Search(T&& handler, ChessGame& game) : handler{ handler }, game{ game }, board{ game.getBoard() }, whites{ board.getWhites() }, blacks{ board.getBlacks() } {} template inline void iterateAll(Args&&... args); template inline void iterateKnights(Args&&... args); template inline void iterateBishops(Args&&... args); template inline void iterateRooks(Args&&... args); template inline void iterateQueens(Args&&... args); template inline void iterateKing(Args&&... args); template inline void iterateCastling(Args&&... args); template inline void iteratePawns(Args&&... args); template inline void iterateSinglePawnPushes(Args&&... args); template inline void iterateDoublePawnPushes(Args&&... args); template inline void iteratePawnCaptures(Args&&... args); template inline void iteratePromotions(Args&&... args); template inline void iterateEnPassant(Args&&... args); private: template inline Bitboard friends(void) const { return side == WHITE_SIDE ? whites : blacks; } template inline Bitboard enemies(void) const { return side == WHITE_SIDE ? blacks : whites; } }; class chessy::MinimaxN { public: bool operator () (int a, int b) { return true; } }; /*inline void aga() { chessy::ChessGame cg; chessy::MinimaxN mm; chessy::Search search = { mm, cg }; search.iterateAll(5, 7); }*/ template template inline void chessy::Search::iterateAll(Args&&... args) { iteratePawns(std::forward(args)...); iterateKnights(std::forward(args)...); iterateBishops(std::forward(args)...); iterateRooks(std::forward(args)...); iterateQueens(std::forward(args)...); iterateKing(std::forward(args)...); iterateCastling(std::forward(args)...); } template template inline void chessy::Search::iterateKnights(Args&&... args) { MoveInfo moveInfo; Bitboard& ns = board.getKnights(); PositionSet knights{ ns }; moveInfo.movedPiece = PieceType::KNIGHT; for (auto knight : knights) { for (auto pos : KnightMoveGenerator{ knight, friends() }) { moveInfo.move = Move{ knight, pos }; handler(moveInfo, std::forward(args)...); } } } template template inline void chessy::Search::iterateBishops(Args&&... args) { MoveInfo moveInfo; moveInfo.movedPiece = PieceType::BISHOP; PositionSet bishops { board.getBishops() }; for (auto bishop : bishops) { for (auto pos : PrimitiveBishopMoveGenerator{ bishop, enemies(), friends() }) { moveInfo.move = Move{ bishop, pos }; handler(moveInfo, std::forward(args)...); } } } template template inline void chessy::Search::iterateRooks(Args&&... args) { MoveInfo moveInfo; moveInfo.movedPiece = PieceType::ROOK; PositionSet rooks { board.getRooks() }; for (auto rook : rooks) { for (auto pos : PrimitiveRookMoveGenerator{ rook, enemies(), friends() }) { moveInfo.move = Move{ rook, pos }; handler(moveInfo, std::forward(args)...); } } } template template inline void chessy::Search::iterateQueens(Args&&... args) { MoveInfo moveInfo; moveInfo.movedPiece = PieceType::QUEEN; PositionSet queens { board.getQueens() }; for (auto queen : queens) { for (auto pos : PrimitiveQueenMoveGenerator{ queen, enemies(), friends() }) { moveInfo.move = Move{ queen, pos }; handler(moveInfo, std::forward(args)...); } } } template template inline void chessy::Search::iterateKing(Args&&... args) { MoveInfo moveInfo; moveInfo.movedPiece = PieceType::KING; Bitboard king = board.getKing(); for (auto pos : KingMoveGenerator{ king, friends() }) { moveInfo.move = Move{ king.getLeastSignificantBit(), pos }; handler(moveInfo, std::forward(args)...); } } template template inline void chessy::Search::iterateCastling(Args&&... args) { Bitboard king = board.getKing(); Bitboard allOccupied = whites | blacks; MoveInfo moveInfo; moveInfo.movedPiece = PieceType::KING; if (game.getCanCastleKingSide(side)) { Bitboard target = king.bits >> 2; // move king to the right Bitboard rook = king.bits << 3; Bitboard rookTarget = king.bits >> 1; if (!(target & allOccupied) && !(rookTarget & allOccupied)) { moveInfo.move = Move{ king.getLeastSignificantBit(), target.getLeastSignificantBit(), true }; handler(moveInfo, std::forward(args)...); } } if (game.getCanCastleQueenSide(side)) { Bitboard target = king.bits << 2; // move king to the left Bitboard rook = king.bits >> 3; Bitboard rookTarget = king.bits << 1; if (!(target & allOccupied) && !(rookTarget & allOccupied)) { moveInfo.move = Move{ king.getLeastSignificantBit(), target.getLeastSignificantBit(), true }; handler(moveInfo, std::forward(args)...); } } } template template inline void chessy::Search::iterateSinglePawnPushes(Args&&... args) { MoveInfo moveInfo; moveInfo.movedPiece = PieceType::PAWN; PawnPushGenerator mg{ game }; for (Move push : mg) { moveInfo.move = push; handler(moveInfo, std::forward(args)...); } } template template inline void chessy::Search::iterateDoublePawnPushes(Args&&... args) { MoveInfo moveInfo; moveInfo.movedPiece = PieceType::PAWN; PawnDoublePushGenerator mg{ game }; for (Move push : mg) { moveInfo.move = push; handler(moveInfo, std::forward(args)...); } } template template inline void chessy::Search::iteratePawnCaptures(Args&&... args) { MoveInfo moveInfo; moveInfo.movedPiece = PieceType::PAWN; PawnCaptureGenerator mgl{ game }; for (Move push : mgl) { moveInfo.move = push; handler(moveInfo, std::forward(args)...); } PawnCaptureGenerator mgr{ game }; for (Move push : mgr) { moveInfo.move = push; handler(moveInfo, std::forward(args)...); } } template template inline void chessy::Search::iteratePromotions(Args&&... args) { MoveInfo moveInfo; moveInfo.movedPiece = PieceType::PAWN; PromotionGenerator pg{ game }; for (Move promotion : pg) { moveInfo.move = promotion; handler(moveInfo, std::forward(args)...); } } template template inline void chessy::Search::iterateEnPassant(Args&&... args) { MoveInfo moveInfo; moveInfo.movedPiece = PieceType::PAWN; Index enPassant = game.getEnPassantIndex(); if (enPassant.index != -1) { Bitboard pawns = board.getPawns(); int rowIndex = side == WHITE_SIDE ? 4 : 3; int targetRowIndex = side == WHITE_SIDE ? 5 : 2; int columnIndex = enPassant.index; Bitboard pawnColumns = 0; if (columnIndex > 0) pawnColumns |= Bitboard::getColumn(columnIndex - 1); if (columnIndex < 7) pawnColumns |= Bitboard::getColumn(columnIndex + 1); pawns &= rowIndex & pawnColumns; moveInfo.enPassantTarget = Index{ enPassant.index, rowIndex }; Index target{ enPassant.index, targetRowIndex }; PositionSet sources = pawns; for (auto source : sources) { moveInfo.move = Move{ source, target }; handler(moveInfo, std::forward(args)...); } } } template template inline void chessy::Search::iteratePawns(Args&&... args) { iterateSinglePawnPushes(std::forward(args)...); iterateDoublePawnPushes(std::forward(args)...); iteratePawnCaptures(std::forward(args)...); iteratePromotions(std::forward(args)...); iterateEnPassant(std::forward(args)...); } #endif // CHESSY_SEARCH_H