|
@@ -9,26 +9,78 @@ namespace chessy
|
|
|
template<typename T>
|
|
|
class Search;
|
|
|
|
|
|
+ struct MoveInfo;
|
|
|
+
|
|
|
class MinimaxN;
|
|
|
}
|
|
|
|
|
|
|
|
|
+struct chessy::MoveInfo
|
|
|
+{
|
|
|
+ Move move;
|
|
|
+ PieceType movedPiece;
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
template<typename T>
|
|
|
class chessy::Search
|
|
|
{
|
|
|
T& handler;
|
|
|
ChessGame& game;
|
|
|
+ Board& board;
|
|
|
+ Bitboard whites;
|
|
|
+ Bitboard blacks;
|
|
|
public:
|
|
|
inline Search(T& handler, ChessGame& game) :
|
|
|
- game{ game }, handler{ handler } {}
|
|
|
+ handler{ handler }, game{ game }, board{ game.getBoard() },
|
|
|
+ whites{ board.getWhites() }, blacks{ board.getBlacks() } {}
|
|
|
|
|
|
|
|
|
- template<typename... Args>
|
|
|
+ template<Side side, typename... Args>
|
|
|
inline void iterateAll(Args&&... args);
|
|
|
|
|
|
template<Side side, typename... Args>
|
|
|
+ inline void iterateKnights(Args&&... args);
|
|
|
+
|
|
|
+ template<Side side, typename... Args>
|
|
|
+ inline void iterateBishops(Args&&... args);
|
|
|
+
|
|
|
+ template<Side side, typename... Args>
|
|
|
+ inline void iterateRooks(Args&&... args);
|
|
|
+
|
|
|
+ template<Side side, typename... Args>
|
|
|
+ inline void iterateQueens(Args&&... args);
|
|
|
+
|
|
|
+ template<Side side, typename... Args>
|
|
|
+ inline void iterateKing(Args&&... args);
|
|
|
+
|
|
|
+ template<Side side, typename... Args>
|
|
|
inline void iteratePawns(Args&&... args);
|
|
|
+
|
|
|
+ template<Side side, typename... Args>
|
|
|
+ inline void iterateSinglePawnPushes(Args&&... args);
|
|
|
+
|
|
|
+ template<Side side, typename... Args>
|
|
|
+ inline void iterateDoublePawnPushes(Args&&... args);
|
|
|
+
|
|
|
+ template<Side side, typename... Args>
|
|
|
+ inline void iteratePawnCaptures(Args&&... args);
|
|
|
+
|
|
|
+ template<Side side, typename... Args>
|
|
|
+ inline void iteratePromotions(Args&&... args);
|
|
|
private:
|
|
|
+
|
|
|
+ template<Side side>
|
|
|
+ inline Bitboard friends(void) const
|
|
|
+ {
|
|
|
+ return side == WHITE_SIDE ? whites : blacks;
|
|
|
+ }
|
|
|
+
|
|
|
+ template<Side side>
|
|
|
+ inline Bitboard enemies(void) const
|
|
|
+ {
|
|
|
+ return side == WHITE_SIDE ? blacks : whites;
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
|
|
@@ -50,57 +102,18 @@ public:
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
-template<typename... Args>
|
|
|
+template<chessy::Side side, typename... Args>
|
|
|
inline void chessy::Search<T>::iterateAll(Args&&... args)
|
|
|
{
|
|
|
- Board& board = game.getBoard();
|
|
|
-
|
|
|
- Bitboard friends;
|
|
|
- Bitboard enemies;
|
|
|
- Side side = WHITE_SIDE;
|
|
|
- if (side == WHITE_SIDE) {
|
|
|
- friends = board.getWhites();
|
|
|
- enemies = board.getBlacks();
|
|
|
- }
|
|
|
- else {
|
|
|
- friends = board.getBlacks();
|
|
|
- enemies = board.getWhites();
|
|
|
- }
|
|
|
+ iteratePawns<side, Args...>(std::forward<Args>(args)...);
|
|
|
+ iterateKnights<side, Args...>(std::forward<Args>(args)...);
|
|
|
+ iterateBishops<side, Args...>(std::forward<Args>(args)...);
|
|
|
+ iterateRooks<side, Args...>(std::forward<Args>(args)...);
|
|
|
+ iterateQueens<side, Args...>(std::forward<Args>(args)...);
|
|
|
+ iterateKing<side, Args...>(std::forward<Args>(args)...);
|
|
|
|
|
|
- const Board temp = board;
|
|
|
-
|
|
|
- if (side == WHITE_SIDE)
|
|
|
- iteratePawns<Args...>(std::forward<Args>(args)...);
|
|
|
- else
|
|
|
- iteratePawns<Args...>(std::forward<Args>(args)...);
|
|
|
-
|
|
|
- Bitboard& ns = board.getKnights<side>();
|
|
|
- PositionSet knights{ ns };
|
|
|
- for (auto knight : knights) {
|
|
|
- for (auto pos : KnightMoveGenerator{ knight, friends }) {
|
|
|
- Move move = { knight, pos };
|
|
|
- board.removeAt(move.destination);
|
|
|
- ns.applyMove(move);
|
|
|
- BestMove m = minimax<otherSide(side)>(depth - 1);
|
|
|
- m.move = move;
|
|
|
- bestMove.overwriteIfBetter(m);
|
|
|
- board = temp;
|
|
|
- }
|
|
|
- }
|
|
|
+ /*
|
|
|
|
|
|
- Bitboard& bs = board.getBishops<side>();
|
|
|
- PositionSet bishops { bs };
|
|
|
- for (auto bishop : bishops) {
|
|
|
- for (auto pos : PrimitiveBishopMoveGenerator{ bishop, enemies, friends }) {
|
|
|
- Move move = { bishop, pos };
|
|
|
- board.removeAt(move.destination);
|
|
|
- bs.applyMove(move);
|
|
|
- BestMove m = minimax<otherSide(side)>(depth - 1);
|
|
|
- m.move = move;
|
|
|
- bestMove.overwriteIfBetter(m);
|
|
|
- board = temp;
|
|
|
- }
|
|
|
- }
|
|
|
|
|
|
Bitboard& rs = board.getRooks<side>();
|
|
|
PositionSet rooks { rs };
|
|
@@ -109,7 +122,7 @@ inline void chessy::Search<T>::iterateAll(Args&&... args)
|
|
|
Move move = { rook, pos };
|
|
|
board.removeAt(move.destination);
|
|
|
rs.applyMove(move);
|
|
|
- BestMove m = minimax<otherSide(side)>(depth - 1);
|
|
|
+ //BestMove m = minimax<otherSide(side)>(depth - 1);
|
|
|
m.move = move;
|
|
|
bestMove.overwriteIfBetter(m);
|
|
|
board = temp;
|
|
@@ -123,7 +136,7 @@ inline void chessy::Search<T>::iterateAll(Args&&... args)
|
|
|
Move move = { queen, pos };
|
|
|
board.removeAt(move.destination);
|
|
|
qs.applyMove(move);
|
|
|
- BestMove m = minimax<otherSide(side)>(depth - 1);
|
|
|
+ //BestMove m = minimax<otherSide(side)>(depth - 1);
|
|
|
m.move = move;
|
|
|
bestMove.overwriteIfBetter(m);
|
|
|
board = temp;
|
|
@@ -143,40 +156,180 @@ inline void chessy::Search<T>::iterateAll(Args&&... args)
|
|
|
bestMove.overwriteIfBetter(m);
|
|
|
board = temp;
|
|
|
}
|
|
|
+
|
|
|
+ if (side == WHITE_SIDE) {
|
|
|
+ if (game.getCanCastleKingSide(side)) {
|
|
|
+ if((friends.bits & 0x6) == 0) {
|
|
|
+ Move kingMove = {3, 1};
|
|
|
+ Move rookMove = {0, 2};
|
|
|
+ king.applyMove(kingMove);
|
|
|
+ rs.applyMove(rookMove);
|
|
|
+ board = temp;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
float v = evaluate<side>();
|
|
|
bestMove.value *= 0.9f;
|
|
|
bestMove.value += v * 0.2f;
|
|
|
- return -bestMove;
|
|
|
+ return -bestMove;*/
|
|
|
}
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
template<chessy::Side side, typename... Args>
|
|
|
-inline void chessy::Search<T>::iteratePawns(Args&&... args)
|
|
|
+inline void chessy::Search<T>::iterateKnights(Args&&... args)
|
|
|
{
|
|
|
- const Board temp = board;
|
|
|
+ MoveInfo moveInfo;
|
|
|
+ Bitboard& ns = board.getKnights<side>();
|
|
|
+ PositionSet knights{ ns };
|
|
|
+ moveInfo.movedPiece = PieceType::KNIGHT;
|
|
|
+ for (auto knight : knights) {
|
|
|
+ for (auto pos : KnightMoveGenerator{ knight, friends<side>() }) {
|
|
|
+ moveInfo.move = Move{ knight, pos };
|
|
|
+ handler(moveInfo, std::forward<Args>(args)...);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+template<typename T>
|
|
|
+template<chessy::Side side, typename... Args>
|
|
|
+inline void chessy::Search<T>::iterateBishops(Args&&... args)
|
|
|
+{
|
|
|
+ MoveInfo moveInfo;
|
|
|
+ moveInfo.movedPiece = PieceType::BISHOP;
|
|
|
+ PositionSet bishops { board.getBishops<side>() };
|
|
|
+ for (auto bishop : bishops) {
|
|
|
+ for (auto pos : PrimitiveBishopMoveGenerator{
|
|
|
+ bishop, enemies<side>(), friends<side>() }) {
|
|
|
+ moveInfo.move = Move{ bishop, pos };
|
|
|
+ handler(moveInfo, std::forward<Args>(args)...);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+template<typename T>
|
|
|
+template<chessy::Side side, typename... Args>
|
|
|
+inline void chessy::Search<T>::iterateRooks(Args&&... args)
|
|
|
+{
|
|
|
+ MoveInfo moveInfo;
|
|
|
+ moveInfo.movedPiece = PieceType::ROOK;
|
|
|
+ PositionSet rooks { board.getRooks<side>() };
|
|
|
+ for (auto rook : rooks) {
|
|
|
+ for (auto pos : PrimitiveRookMoveGenerator{
|
|
|
+ rook, enemies<side>(), friends<side>() }) {
|
|
|
+
|
|
|
+ moveInfo.move = Move{ rook, pos };
|
|
|
+ handler(moveInfo, std::forward<Args>(args)...);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+template<typename T>
|
|
|
+template<chessy::Side side, typename... Args>
|
|
|
+inline void chessy::Search<T>::iterateQueens(Args&&... args)
|
|
|
+{
|
|
|
+ MoveInfo moveInfo;
|
|
|
+ moveInfo.movedPiece = PieceType::QUEEN;
|
|
|
+ PositionSet queens { board.getQueens<side>() };
|
|
|
+ for (auto queen : queens) {
|
|
|
+ for (auto pos : PrimitiveQueenMoveGenerator{
|
|
|
+ queen, enemies<side>(), friends<side>() }) {
|
|
|
+
|
|
|
+ moveInfo.move = Move{ queen, pos };
|
|
|
+ handler(moveInfo, std::forward<Args>(args)...);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+template<typename T>
|
|
|
+template<chessy::Side side, typename... Args>
|
|
|
+inline void chessy::Search<T>::iterateKing(Args&&... args)
|
|
|
+{
|
|
|
+ MoveInfo moveInfo;
|
|
|
+ moveInfo.movedPiece = PieceType::KING;
|
|
|
+ Bitboard king = board.getKing<side>();
|
|
|
+ for (auto pos : KingMoveGenerator{ king, friends<side>() }) {
|
|
|
+ moveInfo.move = Move{ king.getLeastSignificantBit(), pos };
|
|
|
+ handler(moveInfo, std::forward<Args>(args)...);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+template<typename T>
|
|
|
+template<chessy::Side side, typename... Args>
|
|
|
+inline void chessy::Search<T>::iterateSinglePawnPushes(Args&&... args)
|
|
|
+{
|
|
|
+ MoveInfo moveInfo;
|
|
|
+ moveInfo.movedPiece = PieceType::PAWN;
|
|
|
PawnPushGenerator<side> mg{ game };
|
|
|
for (Move push : mg) {
|
|
|
- Bitboard& pawns = board.getPawns<side>();
|
|
|
- Bitboard pTemp = pawns;
|
|
|
- pawns.applyMove(push);
|
|
|
- BestMove m = minimax<otherSide(side)>(depth - 1);
|
|
|
- m.move = push;
|
|
|
- bestMove.overwriteIfBetter(m);
|
|
|
- pawns = pTemp;
|
|
|
+ moveInfo.move = push;
|
|
|
+ handler(moveInfo, std::forward<Args>(args)...);
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- PawnDoublePushGenerator<side> dp{ game };
|
|
|
- for (Move push : dp) {
|
|
|
- Bitboard& pawns = board.getPawns<side>();
|
|
|
- Bitboard pTemp = pawns;
|
|
|
- pawns.applyMove(push);
|
|
|
- BestMove m = minimax<otherSide(side)>(depth - 1);
|
|
|
- m.move = push;
|
|
|
- bestMove.overwriteIfBetter(m);
|
|
|
- pawns = pTemp;
|
|
|
+
|
|
|
+template<typename T>
|
|
|
+template<chessy::Side side, typename... Args>
|
|
|
+inline void chessy::Search<T>::iterateDoublePawnPushes(Args&&... args)
|
|
|
+{
|
|
|
+ MoveInfo moveInfo;
|
|
|
+ moveInfo.movedPiece = PieceType::PAWN;
|
|
|
+ PawnDoublePushGenerator<side> mg{ game };
|
|
|
+ for (Move push : mg) {
|
|
|
+ moveInfo.move = push;
|
|
|
+ handler(moveInfo, std::forward<Args>(args)...);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+template<typename T>
|
|
|
+template<chessy::Side side, typename... Args>
|
|
|
+inline void chessy::Search<T>::iteratePawnCaptures(Args&&... args)
|
|
|
+{
|
|
|
+ MoveInfo moveInfo;
|
|
|
+ moveInfo.movedPiece = PieceType::PAWN;
|
|
|
+ PawnCaptureGenerator<side, LEFT> mgl{ game };
|
|
|
+ for (Move push : mgl) {
|
|
|
+ moveInfo.move = push;
|
|
|
+ handler(moveInfo, std::forward<Args>(args)...);
|
|
|
}
|
|
|
+ PawnCaptureGenerator<side, RIGHT> mgr{ game };
|
|
|
+ for (Move push : mgr) {
|
|
|
+ moveInfo.move = push;
|
|
|
+ handler(moveInfo, std::forward<Args>(args)...);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
+template<typename T>
|
|
|
+template<chessy::Side side, typename... Args>
|
|
|
+inline void chessy::Search<T>::iteratePromotions(Args&&... args)
|
|
|
+{
|
|
|
+ MoveInfo moveInfo;
|
|
|
+ moveInfo.movedPiece = PieceType::PAWN;
|
|
|
+ PromotionGenerator<side> pg{ game };
|
|
|
+ for (Move promotion : pg) {
|
|
|
+ moveInfo.move = promotion;
|
|
|
+ handler(moveInfo, std::forward<Args>(args)...);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+template<typename T>
|
|
|
+template<chessy::Side side, typename... Args>
|
|
|
+inline void chessy::Search<T>::iteratePawns(Args&&... args)
|
|
|
+{
|
|
|
+ iterateSinglePawnPushes<side, Args...>(std::forward(args)...);
|
|
|
+ iterateDoublePawnPushes<side, Args...>(std::forward(args)...);
|
|
|
+ iteratePawnCaptures<side, Args...>(std::forward(args)...);
|
|
|
+ iteratePromotions<side, Args...>(std::forward(args)...);
|
|
|
+ /*
|
|
|
PawnCaptureGenerator<side, LEFT> pl{ game };
|
|
|
for (Move capture : pl) {
|
|
|
Bitboard& pawns = board.getPawns<side>();
|
|
@@ -208,7 +361,7 @@ inline void chessy::Search<T>::iteratePawns(Args&&... args)
|
|
|
m.move = promotion;
|
|
|
bestMove.overwriteIfBetter(m);
|
|
|
board = temp;
|
|
|
- }
|
|
|
+ }*/
|
|
|
}
|
|
|
|
|
|
|