#include <fstream>
#include <iostream>
+#include <sstream>
#include <vector>
#include "misc.h"
/// format (defaults are the positions defined above) and the type of the
/// limit value: depth (default), time in secs or number of nodes.
-void benchmark(int argc, char* argv[]) {
+void benchmark(istringstream& is) {
- vector<string> fens;
+ string token;
Search::LimitsType limits;
- int64_t nodes = 0;
+ vector<string> fens(Defaults, Defaults + 16);
// Assign default values to missing arguments
- string ttSize = argc > 2 ? argv[2] : "128";
- string threads = argc > 3 ? argv[3] : "1";
- string valStr = argc > 4 ? argv[4] : "12";
- string fenFile = argc > 5 ? argv[5] : "default";
- string valType = argc > 6 ? argv[6] : "depth";
+ string ttSize = (is >> token) ? token : "128";
+ string threads = (is >> token) ? token : "1";
+ string limit = (is >> token) ? token : "12";
+ string fenFile = (is >> token) ? token : "default";
+ string limitType = (is >> token) ? token : "depth";
Options["Hash"] = ttSize;
Options["Threads"] = threads;
- if (valType == "time")
- limits.movetime = 1000 * atoi(valStr.c_str()); // movetime is in ms
+ if (limitType == "time")
+ limits.movetime = 1000 * atoi(limit.c_str()); // movetime is in ms
- else if (valType == "nodes")
- limits.nodes = atoi(valStr.c_str());
+ else if (limitType == "nodes")
+ limits.nodes = atoi(limit.c_str());
else
- limits.depth = atoi(valStr.c_str());
+ limits.depth = atoi(limit.c_str());
if (fenFile != "default")
{
file.close();
}
- else
- fens.assign(Defaults, Defaults + 16);
+ int64_t nodes = 0;
Time time = Time::current_time();
for (size_t i = 0; i < fens.size(); i++)
cerr << "\nPosition: " << i + 1 << '/' << fens.size() << endl;
- if (valType == "perft")
+ if (limitType == "perft")
{
int64_t cnt = Search::perft(pos, limits.depth * ONE_PLY);
cerr << "\nPerft " << limits.depth << " leaf nodes: " << cnt << endl;
#include "tt.h"
#include "ucioption.h"
-using namespace std;
-
-extern void uci_loop();
-extern void benchmark(int argc, char* argv[]);
+extern void uci_loop(const std::string&);
extern void kpk_bitbase_init();
int main(int argc, char* argv[]) {
- cout << engine_info() << endl;
+ std::cout << engine_info() << std::endl;
bitboards_init();
Position::init();
Eval::init();
TT.set_size(Options["Hash"]);
- if (argc == 1)
- uci_loop();
+ std::string args;
- else if (string(argv[1]) == "bench")
- benchmark(argc, argv);
+ for (int i = 1; i < argc; i++)
+ args += std::string(" ") + argv[i];
- else
- cerr << "\nUsage: stockfish bench [hash size = 128] [threads = 1] "
- << "[limit = 12] [fen positions file = default] "
- << "[limited by depth, time, nodes or perft = depth]" << endl;
+ uci_loop(args);
}
using namespace std;
+extern void benchmark(istringstream& is);
+
namespace {
// FEN string of the initial position, normal chess
/// that we exit gracefully if the GUI dies unexpectedly. In addition to the UCI
/// commands, the function also supports a few debug commands.
-void uci_loop() {
+void uci_loop(const string& args) {
Position pos(StartFEN, false, 0); // The root position
string cmd, token;
while (token != "quit")
{
- if (!getline(cin, cmd)) // Block here waiting for input
+ if (!args.empty())
+ cmd = args;
+
+ else if (!getline(cin, cmd)) // Block here waiting for input
cmd = "quit";
istringstream is(cmd);
else if (token == "eval")
cout << Eval::trace(pos) << endl;
+ else if (token == "bench")
+ benchmark(is);
+
else if (token == "key")
cout << "key: " << hex << pos.key()
<< "\nmaterial key: " << pos.material_key()
<< "\nuciok" << endl;
else
cout << "Unknown command: " << cmd << endl;
+
+ if (!args.empty()) // Command line arguments have one-shot behaviour
+ {
+ Threads.wait_for_search_finished();
+ break;
+ }
}
}