-
-
-////
-//// Functions
-////
-
-/// benchmark() runs a simple benchmark by letting Stockfish analyze a set
-/// of positions for a given time each. There are four parameters; the
-/// transposition table size, the number of search threads that should
-/// be used, the time in seconds spent for each position (optional, default
-/// is 60) and an optional file name where to look for positions in fen
-/// format (default are the BenchmarkPositions defined above).
-/// The analysis is written to a file named bench.txt.
-
-void benchmark(const std::string& commandLine) {
-
- std::istringstream csVal(commandLine);
- std::istringstream csStr(commandLine);
- std::string ttSize, threads, fileName, limitType;
- int val, secsPerPos, maxDepth, maxNodes;
-
- csStr >> ttSize;
- csVal >> val;
- if (val < 4 || val > 1024)
- {
- std::cerr << "The hash table size must be between 4 and 1024" << std::endl;
- Application::exit_with_failure();
- }
- csStr >> threads;
- csVal >> val;
- if (val < 1 || val > THREAD_MAX)
- {
- std::cerr << "The number of threads must be between 1 and " << THREAD_MAX << std::endl;
- Application::exit_with_failure();
- }
- set_option_value("Hash", ttSize);
- set_option_value("Threads", threads);
- set_option_value("OwnBook", "false");
- set_option_value("Use Search Log", "true");
- set_option_value("Search Log Filename", "bench.txt");
-
- csVal >> val;
- csVal >> fileName;
- csVal >> limitType;
-
- secsPerPos = maxDepth = maxNodes = 0;
-
- if (limitType == "time")
- secsPerPos = val * 1000;
- else if (limitType == "depth")
- maxDepth = val;
- else
- maxNodes = val;
-
- std::vector<std::string> positions;
-
- if (fileName != "default")
- {
- std::ifstream fenFile(fileName.c_str());
- if (!fenFile.is_open())
- {
- std::cerr << "Unable to open positions file " << fileName << std::endl;
- Application::exit_with_failure();
- }
- std::string pos;
- while (fenFile.good())
- {
- std::getline(fenFile, pos);
- if (!pos.empty())
- positions.push_back(pos);
- }
- fenFile.close();
- } else
- for (int i = 0; i < 16; i++)
- positions.push_back(std::string(BenchmarkPositions[i]));
-
- int startTime = get_system_time();
- std::vector<std::string>::iterator it;
- int cnt = 1;
- int64_t totalNodes = 0;
- for (it = positions.begin(); it != positions.end(); ++it, ++cnt)
- {
- Move moves[1] = {MOVE_NONE};
- int dummy[2] = {0, 0};
- Position pos(*it);
- std::cout << "\nProcessing position " << cnt << '/' << positions.size() << std::endl << std::endl;
- if (!think(pos, true, false, 0, dummy, dummy, 0, maxDepth, maxNodes, secsPerPos, moves))
- break;
- totalNodes += nodes_searched();
- }
- std::cout << "\nProcessing time (ms) " << get_system_time() - startTime << std::endl
- << "Nodes searched " << totalNodes << std::endl
- << "Press any key to exit" << std::endl;
- std::cin >> fileName;
+// clang-format on
+
+} // namespace
+
+namespace Stockfish {
+
+// Builds a list of UCI commands to be run by bench. There
+// are five parameters: TT size in MB, number of search threads that
+// should be used, the limit value spent for each position, a file name
+// where to look for positions in FEN format, and the type of the limit:
+// depth, perft, nodes and movetime (in milliseconds). Examples:
+//
+// bench : search default positions up to depth 13
+// bench 64 1 15 : search default positions up to depth 15 (TT = 64MB)
+// bench 64 1 100000 default nodes : search default positions for 100K nodes each
+// bench 64 4 5000 current movetime : search current position with 4 threads for 5 sec
+// bench 16 1 5 blah perft : run a perft 5 on positions in file "blah"
+std::vector<std::string> setup_bench(const Position& current, std::istream& is) {
+
+ std::vector<std::string> fens, list;
+ std::string go, token;
+
+ // Assign default values to missing arguments
+ std::string ttSize = (is >> token) ? token : "16";
+ std::string threads = (is >> token) ? token : "1";
+ std::string limit = (is >> token) ? token : "13";
+ std::string fenFile = (is >> token) ? token : "default";
+ std::string limitType = (is >> token) ? token : "depth";
+
+ go = limitType == "eval" ? "eval" : "go " + limitType + " " + limit;
+
+ if (fenFile == "default")
+ fens = Defaults;
+
+ else if (fenFile == "current")
+ fens.push_back(current.fen());
+
+ else
+ {
+ std::string fen;
+ std::ifstream file(fenFile);
+
+ if (!file.is_open())
+ {
+ std::cerr << "Unable to open file " << fenFile << std::endl;
+ exit(EXIT_FAILURE);
+ }
+
+ while (getline(file, fen))
+ if (!fen.empty())
+ fens.push_back(fen);
+
+ file.close();
+ }
+
+ list.emplace_back("setoption name Threads value " + threads);
+ list.emplace_back("setoption name Hash value " + ttSize);
+ list.emplace_back("ucinewgame");
+
+ for (const std::string& fen : fens)
+ if (fen.find("setoption") != std::string::npos)
+ list.emplace_back(fen);
+ else
+ {
+ list.emplace_back("position fen " + fen);
+ list.emplace_back(go);
+ }
+
+ return list;