Selaa lähdekoodia

rewriting minimax

nicolaswinkler 7 vuotta sitten
vanhempi
commit
7d10eb3715
4 muutettua tiedostoa jossa 63 lisäystä ja 67 poistoa
  1. 35 15
      src/Minimax.cpp
  2. 17 48
      src/Minimax.h
  3. 9 4
      src/UciParser.cpp
  4. 2 0
      src/main.cpp

+ 35 - 15
src/Minimax.cpp

@@ -6,39 +6,60 @@
 
 #include <functional>
 #include <limits>
+#include <chrono>
 
 using namespace chessy;
 
 
-size_t Perft::search(void)
+size_t chessy::perft(std::ostream& out, ChessGame& chessGame, int depth)
 {
     size_t result = 0;
+
     std::function<void(const MoveInfo&, ChessGame&, int, bool)> searcher;
-    searcher = [&result, &searcher] (const MoveInfo& mi, ChessGame& cg, int depth, bool print) {
+    std::function<void(ChessGame&, int, bool)> iterate;
+
+    // apply a move and search deeper
+    searcher = [&result, &iterate] (const MoveInfo& mi, ChessGame& cg,
+                                    int depth, bool print)
+    {
         if (depth > 1) {
             UndoInfo ui = cg.doMove(mi);
-            Search<decltype(searcher)&> search (searcher, cg);
             size_t interRes = result;
-            if (cg.getTurn() == WHITE_SIDE)
-                search.iterateAll<WHITE_SIDE>(cg, depth - 1, false);
-            else 
-                search.iterateAll<BLACK_SIDE>(cg, depth - 1, false);
+            iterate(cg, depth - 1, false);
             if (print)
-                std::cout << mi.move.asString() << ": " << (result - interRes) << std::endl;
-
+                std::cout << mi.move.asString() << ": " <<
+                    (result - interRes) << std::endl;
             cg.undoMove(ui);
         }
         else {
             result++;
         }
     };
-    Search<decltype(searcher)&> search (searcher, chessGame);
-    if (chessGame.getTurn() == WHITE_SIDE)
-        search.iterateAll<WHITE_SIDE>(chessGame, depth, true);
-    else 
-        search.iterateAll<BLACK_SIDE>(chessGame, depth, true);
+
+    // iterate through all positions in the current position
+    iterate = [&searcher] (ChessGame& cg, int depth, bool print)
+    {
+        Search<decltype(searcher)&> search (searcher, cg);
+        if (cg.getTurn() == WHITE_SIDE)
+            search.iterateAll<WHITE_SIDE>(cg, depth, print);
+        else 
+            search.iterateAll<BLACK_SIDE>(cg, depth, print);
+    };
 
 
+    using namespace std::chrono;
+
+    auto begin = high_resolution_clock::now();
+    iterate(chessGame, depth, true);
+    auto end = high_resolution_clock::now(); 
+    auto millis = duration_cast<milliseconds>(end - begin);
+    double seconds = millis.count() / 1000.0;
+    size_t nodesPerSecond = (result * 1000 * 1000 * 1000) /
+        duration_cast<nanoseconds>(end - begin).count();
+
+    out << "Searched " << result << " nodes in " << seconds <<
+        " seconds. (at " << nodesPerSecond << " nodes per second)" << std::endl;
+
     return result;
 }
 
@@ -46,7 +67,6 @@ size_t Perft::search(void)
 template MiniMax::BestMove MiniMax::minimax<WHITE_SIDE>(int);
 template MiniMax::BestMove MiniMax::minimax<BLACK_SIDE>(int);
 
-#include <iostream>
 Move MiniMax::calculateBest(int depth)
 {
     if (game.getTurn() == WHITE_SIDE) {

+ 17 - 48
src/Minimax.h

@@ -1,60 +1,29 @@
 #ifndef CHESSY_MINIMAX_H
 #define CHESSY_MINIMAX_H
 
+#include <iostream>
+
 #include "MoveGeneration.h"
 
 namespace chessy
 {
-    class Perft;
-    class MiniMax;
+    
+    /*!
+     * \brief conducts a performance test iterating through all positions
+     *        up to a specified depth.
+     *
+     * \param out the stream to write info to
+     * \param chessGame the game to iterate through the positions
+     * \param depth how deep to search (in halfmoves)
+     *
+     * \return the number of nodes visited
+     */
+    size_t perft(std::ostream& out, ChessGame& chessGame, int depth);
+
+    Move miniMax(ChessGame& chessGame);
 }
 
 
-class chessy::Perft
-{
-    int depth;
-    ChessGame& chessGame;
-public:
-    inline Perft(int depth, ChessGame& cg) :
-        depth{ depth }, chessGame{ cg } {}
-
-    size_t search(void);
-};
-
-
-class chessy::MiniMax
-{
-    ChessGame& game;
-
-    struct BestMove {
-        Move move;
-        float value;
-
-        inline void overwriteIfBetter(BestMove other)
-        {
-            if (other.value > value)
-                *this = other;
-        }
-
-        inline BestMove operator - (void) const
-        {
-            return { move, -value };
-        }
-    };
-
-public:
-    inline MiniMax(ChessGame& game) :
-        game{ game } {}
-
-    Move calculateBest(int depth);
-
-    template<Side side>
-    float evaluate(void) const;
-
-private:
-    template<Side side>
-    BestMove minimax(int depth);
-};
 
+#endif // CHESSY_MIrIMAX_H
 
-#endif // CHESSY_MINIMAX_H

+ 9 - 4
src/UciParser.cpp

@@ -195,11 +195,16 @@ void UciParser::getfen(const vector<string>& args)
 
 void UciParser::perft(const vector<string>& args)
 {
-    using chessy::Perft;
+    using chessy::perft;
     if (!args.empty()) {
-        int depth = std::stoi(args[0]);
-        Perft p{ depth, cg };
-        out << "Nodes searched: " << p.search() << endl;
+        int depth = 0;
+        try {
+            depth = std::stoi(args[0]);
+        } catch(...) {
+            out << "invalid argument to perft: " << args[0] << endl;
+            return;
+        }
+        perft(out, cg, depth);
     }
 }
 

+ 2 - 0
src/main.cpp

@@ -30,6 +30,8 @@ auto main(int argc, char** argv) -> int
 
     return 0;*/
 
+    argc = popcount(argc);
+
 
 
     if (argc > 1 && (string(argv[1]) == "-h" || string(argv[1]) == "--help")) {