Jelajahi Sumber

improving move generation

Nicolas Winkler 7 tahun lalu
induk
melakukan
cf8f1dd462
7 mengubah file dengan 115 tambahan dan 30 penghapusan
  1. 17 17
      src/ChessGame.cpp
  2. 16 11
      src/ChessGame.h
  3. 28 1
      src/Minimax.cpp
  4. 26 0
      src/MoveGeneration.cpp
  5. 14 0
      src/MoveGeneration.h
  6. 11 0
      src/Search.h
  7. 3 1
      src/TimeManager.cpp

+ 17 - 17
src/ChessGame.cpp

@@ -32,10 +32,10 @@ std::vector<Move> ChessGame::getValidMoves(void) const
 void ChessGame::move(Move move)
 {
     board.move(move);
-    if (turn == Turn::BLACK) {
+    if (turn == BLACK_SIDE) {
         moveCount++;
     }
-    turn = turn == Turn::WHITE ? Turn::BLACK : Turn::WHITE;
+    turn = turn == WHITE_SIDE ? BLACK_SIDE : WHITE_SIDE;
 }
 
 
@@ -62,29 +62,29 @@ void ChessGame::loadFromFen(const std::string& fenString)
     this->board.setBoard(board);
     this->enPassant = Index {enPassant};
 
-    if (turn == "w"s) this->turn = Turn::WHITE;
-    else if (turn == "b"s) this->turn = Turn::BLACK;
+    if (turn == "w"s) this->turn = WHITE_SIDE;
+    else if (turn == "b"s) this->turn = BLACK_SIDE;
     else throw runtime_error("invalid turn "s + turn);
 
-    canCastleQueenSideWhite = false;
-    canCastleKingSideWhite = false;
-    canCastleQueenSideBlack = false;
-    canCastleKingSideBlack = false;
+    canCastleQueenSide[WHITE_SIDE] = false;
+    canCastleKingSide[WHITE_SIDE] = false;
+    canCastleQueenSide[BLACK_SIDE] = false;
+    canCastleKingSide[BLACK_SIDE] = false;
 
     if (castling != "-")
         for (auto character : castling) {
             switch (character) {
                 case 'k':
-                    canCastleKingSideWhite = true;
+                    canCastleKingSide[WHITE_SIDE] = true;
                     break;
                 case 'q':
-                    canCastleQueenSideWhite = true;
+                    canCastleQueenSide[WHITE_SIDE] = true;
                     break;
                 case 'K':
-                    canCastleKingSideBlack = true;
+                    canCastleKingSide[BLACK_SIDE] = true;
                     break;
                 case 'Q':
-                    canCastleQueenSideBlack = true;
+                    canCastleQueenSide[BLACK_SIDE] = true;
                     break;
                 default:
                     throw runtime_error("invalid castling right: "s + character);
@@ -122,13 +122,13 @@ std::string ChessGame::generateFen(void) const
 
     string board = this->board.getFenBoard();
 
-    string turn = this->turn == Turn::WHITE ? "w"s : "b"s;
+    string turn = this->turn == WHITE_SIDE ? "w"s : "b"s;
 
     string castlingRights =
-        (canCastleKingSideBlack ? "K"s : ""s) +
-        (canCastleQueenSideBlack ? "Q"s : ""s) +
-        (canCastleKingSideWhite ? "k"s : ""s) +
-        (canCastleQueenSideWhite ? "q"s : ""s);
+        (canCastleKingSide[BLACK_SIDE] ? "K"s : ""s) +
+        (canCastleQueenSide[BLACK_SIDE] ? "Q"s : ""s) +
+        (canCastleKingSide[WHITE_SIDE] ? "k"s : ""s) +
+        (canCastleQueenSide[WHITE_SIDE] ? "q"s : ""s);
     if (castlingRights.empty())
         castlingRights = "-"s;
 

+ 16 - 11
src/ChessGame.h

@@ -16,25 +16,20 @@ class chessy::ChessGame
 {
     Board board;
 
-    bool canCastleQueenSideWhite =  true;
-    bool canCastleQueenSideBlack =  true;
-    bool canCastleKingSideWhite =   true;
-    bool canCastleKingSideBlack =   true;
+    bool canCastleQueenSide[2] = { true, true };
+    bool canCastleKingSide [2] = { true, true };
 
     short reversibleHalfMoves =     0;
 
     //! -1 for no en passant possible
     Index enPassant =              -1;
 
-public:
-    enum class Turn { WHITE, BLACK };
-private:
-    Turn turn =                     Turn::WHITE;
+    Side turn =                     WHITE_SIDE;
 
     int moveCount =                 1;
 
-    const static char WHITE =       0;
-    const static char BLACK =       1;
+    /*const static char WHITE =       0;
+    const static char BLACK =       1;*/
 
 
 public:
@@ -50,8 +45,18 @@ public:
     inline const Board& getBoard(void) const { return board; }
     inline       Board& getBoard(void)       { return board; }
 
+    inline bool getCanCastleKingSide(Side side) const
+    {
+        return canCastleKingSide[side];
+    }
+
+    inline bool getCanCastleQueenSide(Side side) const
+    {
+        return canCastleQueenSide[side];
+    }
+
     void move(Move move);
-    inline Turn getTurn(void) const { return turn; }
+    inline Side getTurn(void) const { return turn; }
 
     void loadFromFen(const std::string& fenString);
     std::string generateFen(void) const;

+ 28 - 1
src/Minimax.cpp

@@ -11,7 +11,7 @@ template MiniMax::BestMove MiniMax::minimax<BLACK_SIDE>(int);
 #include <iostream>
 Move MiniMax::calculateBest(int depth)
 {
-    if (game.getTurn() == ChessGame::Turn::WHITE) {
+    if (game.getTurn() == WHITE_SIDE) {
         BestMove bm = minimax<WHITE_SIDE>(depth);
         return bm.move;
     }
@@ -124,6 +124,17 @@ MiniMax::BestMove MiniMax::minimax(int depth)
         board = temp;
     }
 
+    PromotionGenerator<side> pg{ game };
+    for (Move promotion : pg) {
+        Bitboard& pawns = board.getPawns<side>();
+        board.removeAt(promotion.destination);
+        pawns.applyMove(promotion);
+        BestMove m = minimax<otherSide(side)>(depth - 1);
+        m.move = promotion;
+        bestMove.overwriteIfBetter(m);
+        board = temp;
+    }
+
 
     Bitboard& ns = board.getKnights<side>();
     PositionSet knights { ns };
@@ -194,6 +205,22 @@ MiniMax::BestMove MiniMax::minimax(int depth)
         bestMove.overwriteIfBetter(m);
         board = temp;
     }
+
+    /*Bitboard& king = board.getKing<side>();
+    Index kingIndex = king.getLeastSignificantBit();
+    for (auto pos : KingMoveGenerator{ king, friends }) {
+        Move move = { kingIndex, pos };
+        board.removeAt(pos);
+        king.applyMove(move);
+        BestMove m = minimax<otherSide(side)>(depth - 1);
+        m.move = move;
+        //if (depth >= 3)
+        //    std::cout << m.move.asString() << " " << bestMove.value << " -> " << m.value << std::endl;
+        bestMove.overwriteIfBetter(m);
+        board = temp;
+    }*/
+
+
     float v = evaluate<side>();
     bestMove.value *= 0.9f;
     bestMove.value += v * 0.2f;

+ 26 - 0
src/MoveGeneration.cpp

@@ -18,6 +18,9 @@ namespace chessy
     template class PawnCaptureGenerator<WHITE_SIDE, RIGHT>;
     template class PawnCaptureGenerator<BLACK_SIDE, LEFT>;
     template class PawnCaptureGenerator<BLACK_SIDE, RIGHT>;
+
+    template class CastlingGenerator<WHITE_SIDE>;
+    template class CastlingGenerator<BLACK_SIDE>;
 }
 
 
@@ -199,3 +202,26 @@ Bitboard KingMoveGenerator::generateKingMoves(Bitboard king)
         king.neOne() | king.nwOne() | king.swOne() | king.seOne();
 }
 
+
+template<Side side>
+CastlingGenerator<side>::CastlingGenerator(const ChessGame& game) :
+    PositionSet{ 0 }
+{
+    bool canCastleQueenSide = game.getCanCastleQueenSide(side);
+    bool canCastleKingSide = game.getCanCastleKingSide(side);
+
+    if (!canCastleKingSide && !canCastleQueenSide)
+        return;
+
+    Bitboard king = game.getBoard().getKing<side>();
+    Bitboard targets = 0;
+    if (canCastleKingSide) {
+        targets |= king.eastOne().eastOne();
+    }
+    if (canCastleQueenSide) {
+        targets |= king.westOne().westOne();
+    }
+    PositionSet::setBitboard(targets);
+}
+
+

+ 14 - 0
src/MoveGeneration.h

@@ -29,6 +29,8 @@ namespace chessy
     class PrimitiveRookMoveGenerator;
     class PrimitiveBishopMoveGenerator;
     class KingMoveGenerator;
+    template<Side side>
+    class CastlingGenerator;
 }
 
 
@@ -40,6 +42,8 @@ public:
 
     inline PositionSet(Bitboard b) : bitboard{ b } {}
 
+    inline void setBitboard(Bitboard b) { bitboard = b; }
+
     struct PositionSetIterator
     {
         Bitboard bitboard;
@@ -134,6 +138,7 @@ class chessy::PromotionGenerator
         }
     };
 
+public:
     inline PromotionGenerator(const ChessGame& cg) : chessGame{ cg } {}
     MoveIterator begin(void) const;
     MoveIterator end(void) const;
@@ -278,4 +283,13 @@ private:
     Bitboard generateKingMoves(Bitboard king);
 };
 
+
+template<chessy::Side side>
+class chessy::CastlingGenerator :
+    public PositionSet
+{
+    CastlingGenerator(const ChessGame& game);
+};
+
+
 #endif // CHESSY_MOVEGENERATION_H

+ 11 - 0
src/Search.h

@@ -198,6 +198,17 @@ inline void chessy::Search<T>::iteratePawns(Args&&... args)
         bestMove.overwriteIfBetter(m);
         board = temp;
     }
+
+    PromotionGenerator<side> pg{ game };
+    for (Move promotion : pg) {
+        Bitboard& pawns = board.getPawns<side>();
+        board.removeAt(promotion.destination);
+        pawns.applyMove(promotion);
+        BestMove m = minimax<otherSide(side)>(depth - 1);
+        m.move = promotion;
+        bestMove.overwriteIfBetter(m);
+        board = temp;
+    }
 }
 
 

+ 3 - 1
src/TimeManager.cpp

@@ -31,9 +31,11 @@ bool TimeManager::isRunning(void) const
 
 void FixedSearchTimer::startSearch(void)
 {
-    TimeManager::searchThread = 
+    /*TimeManager::searchThread = 
         std::thread{ &FixedSearchTimer::search, this };
+    startPoint = std::chrono::steady_clock::now();*/
     startPoint = std::chrono::steady_clock::now();
+    search();
 }