From: Joona Kiiski Date: Fri, 2 Oct 2009 04:09:24 +0000 (+0300) Subject: Implemented perft X-Git-Url: https://git.sesse.net/?p=stockfish;a=commitdiff_plain;h=fa49311b362a1ab6e4bd5263c7782b19fa59c41f Implemented perft Patch from Joona with extension to benchmark and inclusion of Depth(0) moves generation by me. Note that to test also qsearch and in particulary checks generations a change in the end condition is needed. Signed-off-by: Marco Costalba --- diff --git a/src/benchmark.cpp b/src/benchmark.cpp index b90d3fcb..d7972649 100644 --- a/src/benchmark.cpp +++ b/src/benchmark.cpp @@ -104,7 +104,7 @@ void benchmark(const string& commandLine) { if (limitType == "time") secsPerPos = val * 1000; - else if (limitType == "depth") + else if (limitType == "depth" || limitType == "perft") maxDepth = val; else maxNodes = val; @@ -153,7 +153,9 @@ void benchmark(const string& commandLine) { int dummy[2] = {0, 0}; Position pos(*it); cerr << "\nBench position: " << cnt << '/' << positions.size() << endl << endl; - if (!think(pos, true, false, 0, dummy, dummy, 0, maxDepth, maxNodes, secsPerPos, moves)) + if (limitType == "perft") + totalNodes += perft(pos, maxDepth * OnePly); + else if (!think(pos, true, false, 0, dummy, dummy, 0, maxDepth, maxNodes, secsPerPos, moves)) break; totalNodes += nodes_searched(); } diff --git a/src/main.cpp b/src/main.cpp index c57b1f41..47a03ad1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -63,7 +63,7 @@ int main(int argc, char *argv[]) { if (string(argv[1]) != "bench" || argc < 4 || argc > 8) cout << "Usage: stockfish bench " << "[time = 60s] [fen positions file = default] " - << "[time, depth or node limited = time] " + << "[time, depth, perft or node limited = time] " << "[timing file name = none]" << endl; else { diff --git a/src/search.cpp b/src/search.cpp index d073b7da..3e4341c0 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -326,6 +326,32 @@ namespace { //// Functions //// + +/// perft() is our utility to verify move generation is bug free. All the +/// legal moves up to given depth are generated and counted and the sum returned. + +int perft(Position& pos, Depth depth) +{ + if (depth <= Depth(0)) // Replace with '<' to test also qsearch + return 1; + + Move move; + MovePicker mp = MovePicker(pos, MOVE_NONE, depth, H); + Bitboard dcCandidates = mp.discovered_check_candidates(); + int sum = 0; + + // Loop through all legal moves + while ((move = mp.get_next_move()) != MOVE_NONE) + { + StateInfo st; + pos.do_move(move, st, dcCandidates); + sum += perft(pos, depth - OnePly); + pos.undo_move(move); + } + return sum; +} + + /// think() is the external interface to Stockfish's search, and is called when /// the program receives the UCI 'go' command. It initializes various /// search-related global variables, and calls root_search(). It returns false @@ -447,7 +473,7 @@ bool think(const Position& pos, bool infinite, bool ponder, int side_to_move, if (movesToGo == 1) { MaxSearchTime = myTime / 2; - AbsoluteMaxSearchTime = + AbsoluteMaxSearchTime = (myTime > 3000)? (myTime - 500) : ((myTime * 3) / 4); } else { MaxSearchTime = myTime / Min(movesToGo, 20); @@ -976,7 +1002,7 @@ namespace { std::cout << std::endl; if (UseLogFile) - LogFile << pretty_pv(pos, current_search_time(), Iteration, nodes_searched(), value, + LogFile << pretty_pv(pos, current_search_time(), Iteration, nodes_searched(), value, ((value >= beta)? VALUE_TYPE_LOWER : ((value <= alpha)? VALUE_TYPE_UPPER : VALUE_TYPE_EXACT)), ss[0].pv) diff --git a/src/search.h b/src/search.h index 91f484a1..e87d0d2c 100644 --- a/src/search.h +++ b/src/search.h @@ -69,6 +69,7 @@ extern void stop_threads(); extern bool think(const Position &pos, bool infinite, bool ponder, int side_to_move, int time[], int increment[], int movesToGo, int maxDepth, int maxNodes, int maxTime, Move searchMoves[]); +extern int perft(Position &pos, Depth depth); extern int64_t nodes_searched(); diff --git a/src/uci.cpp b/src/uci.cpp index 36848d83..b9024096 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -61,6 +61,7 @@ namespace { void set_option(UCIInputParser& uip); void set_position(UCIInputParser& uip); bool go(UCIInputParser& uip); + void perft(UCIInputParser& uip); } @@ -155,6 +156,8 @@ namespace { cout << "key: " << hex << RootPosition.get_key() << "\nmaterial key: " << RootPosition.get_material_key() << "\npawn key: " << RootPosition.get_pawn_key() << endl; + else if (token == "perft") + perft(uip); else { cout << "Unknown command: " << command << endl; @@ -318,4 +321,24 @@ namespace { time, inc, movesToGo, depth, nodes, moveTime, searchMoves); } + void perft(UCIInputParser& uip) { + + string token; + int depth = 0; + + while (!uip.eof()) + { + uip >> token; + + if (token == "depth") + uip >> depth; + } + Position pos = RootPosition; + int tm = get_system_time(); + int n = perft(pos, depth * OnePly); + tm = get_system_time() - tm; + std::cout << "\nNodes " << n + << "\nTime (ms) " << tm + << "\nNodes/second " << (int)(n/(tm/1000.0)) << std::endl; + } }