UciParser.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. #include "UciParser.h"
  2. #include <sstream>
  3. #include <thread>
  4. #include "ChessGame.h"
  5. #include "EngineInfo.h"
  6. using namespace std;
  7. const map<std::string, UciParser::CommandHandler> UciParser::commandHandlers = {
  8. { "uci", &UciParser::uci },
  9. { "debug", &UciParser::debug },
  10. { "isready", &UciParser::isready },
  11. { "setoption", &UciParser::setoption },
  12. { "register", &UciParser::doNothing },
  13. { "ucinewgame", &UciParser::ucinewgame },
  14. { "position", &UciParser::position },
  15. { "go", &UciParser::go },
  16. { "stop", &UciParser::stop },
  17. { "quit", &UciParser::quit },
  18. { "getfen", &UciParser::getfen },
  19. { "perft", &UciParser::perft },
  20. };
  21. #include<fstream>
  22. int UciParser::parse(istream& in, ostream& out)
  23. {
  24. ofstream log{ "log.log" };
  25. while (!in.eof() && !quitting) {
  26. string line;
  27. getline(in, line);
  28. if (!line.empty()) {
  29. executeLine(line);
  30. log << line << endl;
  31. }
  32. }
  33. log.close();
  34. return 0;
  35. }
  36. int UciParser::executeLine(const string& line)
  37. {
  38. istringstream s{ line };
  39. string token;
  40. string command;
  41. vector<string> args;
  42. s >> command;
  43. while (s >> token) {
  44. args.push_back(std::move(token));
  45. }
  46. return executeCommand(command, args);
  47. }
  48. int UciParser::executeCommand(const string& command,
  49. const vector<string>& args)
  50. {
  51. try {
  52. CommandHandler ch = commandHandlers.at(command);
  53. (this->*ch)(args);
  54. return 0;
  55. }
  56. catch (out_of_range& oor) {
  57. // no handler for command -> invalid command
  58. out << "unknown command: " << command << endl;
  59. return 1;
  60. }
  61. catch (...) {
  62. out << "unknown error occurred" << endl;
  63. return 1;
  64. }
  65. }
  66. void UciParser::sendCommand(const std::string& command,
  67. const std::vector<std::string>& args)
  68. {
  69. std::unique_lock<std::mutex> lock { outStreamLock };
  70. cout << command;
  71. std::for_each(args.begin(), args.end(), [] (auto& x) { cout << " " << x; });
  72. cout << endl;
  73. }
  74. void UciParser::uci(const std::vector<std::string>& args)
  75. {
  76. sendCommand("id", { "name", "Chessy", chessy::info::versionString });
  77. sendCommand("id", { "author", "N. Winkler" });
  78. sendCommand("uciok");
  79. }
  80. void UciParser::debug(const vector<string>& args)
  81. {
  82. // not yet implemented
  83. }
  84. void UciParser::isready(const vector<string>& args)
  85. {
  86. sendCommand("readyok");
  87. }
  88. void UciParser::setoption(const vector<string>& args)
  89. {
  90. Option o;
  91. //optionsManager.setOption();
  92. }
  93. void UciParser::ucinewgame(const vector<string>& args)
  94. {
  95. return;
  96. }
  97. void UciParser::position(const vector<string>& args)
  98. {
  99. try {
  100. size_t movesIndex = 0;
  101. if (args.at(0) == "fen") {
  102. string fenString = args.at(1) + " " + args.at(2) + " " +
  103. args.at(3) + " " + args.at(4) + " " + args.at(5) + " " +
  104. args.at(6);
  105. cg.loadFromFen(fenString);
  106. movesIndex = 6;
  107. }
  108. else if (args.at(0) == "startpos") {
  109. cg = chessy::ChessGame();
  110. movesIndex = 1;
  111. }
  112. if (args.size() > movesIndex + 1 && args.at(movesIndex) == "moves") {
  113. for (size_t i = movesIndex + 1; i < args.size(); i++) {
  114. using chessy::Move;
  115. Move move = Move{ args[i] };
  116. cg.move(move);
  117. }
  118. }
  119. }
  120. catch(out_of_range& oor) {
  121. out << "invalid arguments for command 'position'" << endl;
  122. }
  123. catch(runtime_error& re) {
  124. out << "" << endl;
  125. }
  126. }
  127. void UciParser::go(const vector<string>& args)
  128. {
  129. stop({});
  130. chessy::Move bestMove;
  131. chessy::MoveValue value;
  132. int depth = 5;
  133. tie(bestMove, value) = chessy::miniMax(this->cg, depth);
  134. write("info", "depth", depth, "score", "cp", value);
  135. sendCommand("bestmove", { bestMove.asString() });
  136. /*fst = make_unique<FixedSearchTimer>(cg, *this);
  137. fst->setThinkTime(std::chrono::milliseconds{ 1000 });
  138. fst->startSearch();*/
  139. //chessy::Move m = minimax.calculateBest(5);
  140. // TODO: hack!
  141. /*string suffix;
  142. if (cg.getBoard().getAtPosition(m.origin) == chessy::PieceType::PAWN &&
  143. (m.destination.index < 8 || m.destination.index >= 56)) {
  144. suffix = "Q";
  145. }*/
  146. //sendCommand("bestmove", { m.asString() + suffix });
  147. }
  148. void UciParser::stop(const vector<string>& args)
  149. {
  150. if (fst) {
  151. fst->stop();
  152. fst->join();
  153. fst = nullptr;
  154. }
  155. }
  156. void UciParser::quit(const vector<string>& args)
  157. {
  158. quitting = true;
  159. }
  160. void UciParser::getfen(const vector<string>& args)
  161. {
  162. out << cg.generateFen() << endl;
  163. }
  164. void UciParser::perft(const vector<string>& args)
  165. {
  166. using chessy::perft;
  167. if (!args.empty()) {
  168. int depth = 0;
  169. try {
  170. depth = std::stoi(args[0]);
  171. } catch(...) {
  172. out << "invalid argument to perft: " << args[0] << endl;
  173. return;
  174. }
  175. perft(out, cg, depth);
  176. }
  177. }
  178. void UciParser::doNothing(const vector<string>& args)
  179. {
  180. // explicitly do nothing
  181. return;
  182. }