|
@@ -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) {
|