|
@@ -208,10 +208,163 @@ CastlingGenerator<side>::CastlingGenerator(const ChessGame& game) :
|
|
|
}
|
|
|
|
|
|
|
|
|
+template<Side side>
|
|
|
+void chessy::generatePawnPushes(const ChessGame& cg, std::vector<Move>& moves)
|
|
|
+{
|
|
|
+ PawnPushGenerator<side> ppg{ cg };
|
|
|
+ for (const auto& move : ppg)
|
|
|
+ moves.push_back(move);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+template<Side side>
|
|
|
+void chessy::generatePawnDoublePushes(const ChessGame& cg, std::vector<Move>& moves)
|
|
|
+{
|
|
|
+ PawnDoublePushGenerator<side> pdpg{ cg };
|
|
|
+ for (const auto& move : pdpg)
|
|
|
+ moves.push_back(move);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+template<Side side>
|
|
|
+void chessy::generatePawnCaptures(const ChessGame& cg, std::vector<Move>& moves)
|
|
|
+{
|
|
|
+ PawnCaptureGenerator<side, LEFT> pcgl{ cg };
|
|
|
+ PawnCaptureGenerator<side, RIGHT> pcgr{ cg };
|
|
|
+ for (const auto& move : pcgl)
|
|
|
+ moves.push_back(move);
|
|
|
+ for (const auto& move : pcgr)
|
|
|
+ moves.push_back(move);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+template<Side side>
|
|
|
+void chessy::generatePawnPromotions(const ChessGame& cg, std::vector<Move>& moves)
|
|
|
+{
|
|
|
+ PromotionGenerator<side> pg{ cg };
|
|
|
+ for (const auto& move : pg)
|
|
|
+ moves.push_back(move);
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+template<Side side>
|
|
|
+void chessy::generateKnightMoves(const ChessGame& cg, std::vector<Move>& moves)
|
|
|
+{
|
|
|
+ const Board& b = cg.getBoard();
|
|
|
+ PositionSet p{ b.getKnights<side>() };
|
|
|
+ for (auto pos : p) {
|
|
|
+ KnightMoveGenerator g{ pos, b.get<side>() };
|
|
|
+ for (auto target : g) {
|
|
|
+ moves.emplace_back(pos, target);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+template<Side side, typename Generator>
|
|
|
+void generateMoves(Bitboard position, Bitboard enemies, Bitboard friendly,
|
|
|
+ std::vector<Move>& moves)
|
|
|
+{
|
|
|
+ PositionSet p{ position };
|
|
|
+ for (auto pos : p) {
|
|
|
+ Generator g{ pos, enemies, friendly };
|
|
|
+ for (auto target : g) {
|
|
|
+ moves.emplace_back(pos, target);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+template<Side side>
|
|
|
+void chessy::generateQueenMoves(const ChessGame& cg, std::vector<Move>& moves)
|
|
|
+{
|
|
|
+ const Board& b = cg.getBoard();
|
|
|
+ generateMoves<side, PrimitiveQueenMoveGenerator>(
|
|
|
+ b.getKnights<side>(), b.get<otherSide(side)>(), b.get<side>(), moves
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+template<Side side>
|
|
|
+void chessy::generateRookMoves(const ChessGame& cg, std::vector<Move>& moves)
|
|
|
+{
|
|
|
+ const Board& b = cg.getBoard();
|
|
|
+ generateMoves<side, PrimitiveRookMoveGenerator>(
|
|
|
+ b.getKnights<side>(), b.get<otherSide(side)>(), b.get<side>(), moves
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+template<Side side>
|
|
|
+void chessy::generateBishopMoves(const ChessGame& cg, std::vector<Move>& moves)
|
|
|
+{
|
|
|
+ const Board& b = cg.getBoard();
|
|
|
+ generateMoves<side,PrimitiveBishopMoveGenerator>(
|
|
|
+ b.getKnights<side>(), b.get<otherSide(side)>(), b.get<side>(), moves
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+template<Side side>
|
|
|
+void chessy::generateKingMoves(const ChessGame& cg, std::vector<Move>& moves)
|
|
|
+{
|
|
|
+ const Board& b = cg.getBoard();
|
|
|
+ Bitboard king = b.getKing<side>();
|
|
|
+ Index kingIndex = king.getLeastSignificantBit();
|
|
|
+ for (auto pos : KingMoveGenerator{ king, b.get<side>() })
|
|
|
+ moves.emplace_back(kingIndex, pos);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+template<Side side>
|
|
|
+void chessy::generateCastling(const ChessGame& cg, std::vector<Move>& moves)
|
|
|
+{
|
|
|
+ const Board& b = cg.getBoard();
|
|
|
+ Bitboard king = b.getKing<side>();
|
|
|
+ Bitboard allOccupied = b.getOccupied();
|
|
|
+ if (cg.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)) {
|
|
|
+ moves.emplace_back(king.getLeastSignificantBit(),
|
|
|
+ target.getLeastSignificantBit(), true);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (cg.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)) {
|
|
|
+ moves.emplace_back(king.getLeastSignificantBit(),
|
|
|
+ target.getLeastSignificantBit(), true);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+template<Side side>
|
|
|
+void chessy::generateAllMoves(const ChessGame& cg, std::vector<Move>& moves)
|
|
|
+{
|
|
|
+ generatePawnPushes<side>(cg, moves);
|
|
|
+ generatePawnDoublePushes<side>(cg, moves);
|
|
|
+ generatePawnCaptures<side>(cg, moves);
|
|
|
+ generatePawnPromotions<side>(cg, moves);
|
|
|
+ generateKnightMoves<side>(cg, moves);
|
|
|
+ generateQueenMoves<side>(cg, moves);
|
|
|
+ generateBishopMoves<side>(cg, moves);
|
|
|
+ generateRookMoves<side>(cg, moves);
|
|
|
+ generateKingMoves<side>(cg, moves);
|
|
|
+ generateCastling<side>(cg, moves);
|
|
|
+}
|
|
|
+
|
|
|
// explicit instatiations
|
|
|
namespace chessy
|
|
|
{
|
|
|
- template class PawnPushGenerator<WHITE_SIDE>;
|
|
|
+ /*template class PawnPushGenerator<WHITE_SIDE>;
|
|
|
template class PawnPushGenerator<BLACK_SIDE>;
|
|
|
|
|
|
template class PromotionGenerator<WHITE_SIDE>;
|
|
@@ -226,5 +379,8 @@ namespace chessy
|
|
|
template class PawnCaptureGenerator<BLACK_SIDE, RIGHT>;
|
|
|
|
|
|
template class CastlingGenerator<WHITE_SIDE>;
|
|
|
- template class CastlingGenerator<BLACK_SIDE>;
|
|
|
+ template class CastlingGenerator<BLACK_SIDE>;*/
|
|
|
+
|
|
|
+ template void generateAllMoves<WHITE_SIDE>(const ChessGame&, std::vector<Move>&);
|
|
|
+ template void generateAllMoves<BLACK_SIDE>(const ChessGame&, std::vector<Move>&);
|
|
|
}
|