UCICommand.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /*
  2. * Copyright (c) 2020, the SerenityOS developers.
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "UCICommand.h"
  7. #include <AK/StringBuilder.h>
  8. namespace Chess::UCI {
  9. UCICommand UCICommand::from_string(StringView command)
  10. {
  11. auto tokens = command.split_view(' ');
  12. VERIFY(tokens[0] == "uci");
  13. VERIFY(tokens.size() == 1);
  14. return UCICommand();
  15. }
  16. DeprecatedString UCICommand::to_deprecated_string() const
  17. {
  18. return "uci\n";
  19. }
  20. DebugCommand DebugCommand::from_string(StringView command)
  21. {
  22. auto tokens = command.split_view(' ');
  23. VERIFY(tokens[0] == "debug");
  24. VERIFY(tokens.size() == 2);
  25. if (tokens[1] == "on")
  26. return DebugCommand(Flag::On);
  27. if (tokens[1] == "off")
  28. return DebugCommand(Flag::On);
  29. VERIFY_NOT_REACHED();
  30. }
  31. DeprecatedString DebugCommand::to_deprecated_string() const
  32. {
  33. if (flag() == Flag::On) {
  34. return "debug on\n";
  35. } else {
  36. return "debug off\n";
  37. }
  38. }
  39. IsReadyCommand IsReadyCommand::from_string(StringView command)
  40. {
  41. auto tokens = command.split_view(' ');
  42. VERIFY(tokens[0] == "isready");
  43. VERIFY(tokens.size() == 1);
  44. return IsReadyCommand();
  45. }
  46. DeprecatedString IsReadyCommand::to_deprecated_string() const
  47. {
  48. return "isready\n";
  49. }
  50. SetOptionCommand SetOptionCommand::from_string(StringView command)
  51. {
  52. auto tokens = command.split_view(' ');
  53. VERIFY(tokens[0] == "setoption");
  54. VERIFY(tokens[1] == "name");
  55. VERIFY(tokens.size() > 2);
  56. StringBuilder name;
  57. StringBuilder value;
  58. bool in_name = false;
  59. bool in_value = false;
  60. for (auto& part : tokens) {
  61. if (in_name) {
  62. if (part == "value") {
  63. in_name = false;
  64. in_value = true;
  65. continue;
  66. }
  67. name.append(part);
  68. name.append(' ');
  69. continue;
  70. }
  71. if (in_value) {
  72. value.append(part);
  73. value.append(' ');
  74. continue;
  75. }
  76. if (part == "name") {
  77. in_name = true;
  78. continue;
  79. }
  80. }
  81. VERIFY(!name.is_empty());
  82. return SetOptionCommand(name.to_deprecated_string().trim_whitespace(), value.to_deprecated_string().trim_whitespace());
  83. }
  84. DeprecatedString SetOptionCommand::to_deprecated_string() const
  85. {
  86. StringBuilder builder;
  87. builder.append("setoption name "sv);
  88. builder.append(name());
  89. if (value().has_value()) {
  90. builder.append(" value "sv);
  91. builder.append(value().value());
  92. }
  93. builder.append('\n');
  94. return builder.to_deprecated_string();
  95. }
  96. PositionCommand PositionCommand::from_string(StringView command)
  97. {
  98. auto tokens = command.split_view(' ');
  99. VERIFY(tokens.size() >= 3);
  100. VERIFY(tokens[0] == "position");
  101. VERIFY(tokens[2] == "moves");
  102. Optional<DeprecatedString> fen;
  103. if (tokens[1] != "startpos")
  104. fen = tokens[1];
  105. Vector<Move> moves;
  106. for (size_t i = 3; i < tokens.size(); ++i) {
  107. moves.append(Move(tokens[i]));
  108. }
  109. return PositionCommand(fen, moves);
  110. }
  111. DeprecatedString PositionCommand::to_deprecated_string() const
  112. {
  113. StringBuilder builder;
  114. builder.append("position "sv);
  115. if (fen().has_value()) {
  116. builder.append(fen().value());
  117. } else {
  118. builder.append("startpos "sv);
  119. }
  120. builder.append("moves"sv);
  121. for (auto& move : moves()) {
  122. builder.append(' ');
  123. builder.append(move.to_long_algebraic());
  124. }
  125. builder.append('\n');
  126. return builder.to_deprecated_string();
  127. }
  128. GoCommand GoCommand::from_string(StringView command)
  129. {
  130. auto tokens = command.split_view(' ');
  131. VERIFY(tokens[0] == "go");
  132. GoCommand go_command;
  133. for (size_t i = 1; i < tokens.size(); ++i) {
  134. if (tokens[i] == "searchmoves") {
  135. VERIFY_NOT_REACHED();
  136. } else if (tokens[i] == "ponder") {
  137. go_command.ponder = true;
  138. } else if (tokens[i] == "wtime") {
  139. VERIFY(i++ < tokens.size());
  140. go_command.wtime = tokens[i].to_int().value();
  141. } else if (tokens[i] == "btime") {
  142. VERIFY(i++ < tokens.size());
  143. go_command.btime = tokens[i].to_int().value();
  144. } else if (tokens[i] == "winc") {
  145. VERIFY(i++ < tokens.size());
  146. go_command.winc = tokens[i].to_int().value();
  147. } else if (tokens[i] == "binc") {
  148. VERIFY(i++ < tokens.size());
  149. go_command.binc = tokens[i].to_int().value();
  150. } else if (tokens[i] == "movestogo") {
  151. VERIFY(i++ < tokens.size());
  152. go_command.movestogo = tokens[i].to_int().value();
  153. } else if (tokens[i] == "depth") {
  154. VERIFY(i++ < tokens.size());
  155. go_command.depth = tokens[i].to_int().value();
  156. } else if (tokens[i] == "nodes") {
  157. VERIFY(i++ < tokens.size());
  158. go_command.nodes = tokens[i].to_int().value();
  159. } else if (tokens[i] == "mate") {
  160. VERIFY(i++ < tokens.size());
  161. go_command.mate = tokens[i].to_int().value();
  162. } else if (tokens[i] == "movetime") {
  163. VERIFY(i++ < tokens.size());
  164. go_command.movetime = tokens[i].to_int().value();
  165. } else if (tokens[i] == "infinite") {
  166. go_command.infinite = true;
  167. }
  168. }
  169. return go_command;
  170. }
  171. DeprecatedString GoCommand::to_deprecated_string() const
  172. {
  173. StringBuilder builder;
  174. builder.append("go"sv);
  175. if (searchmoves.has_value()) {
  176. builder.append(" searchmoves"sv);
  177. for (auto& move : searchmoves.value()) {
  178. builder.append(' ');
  179. builder.append(move.to_long_algebraic());
  180. }
  181. }
  182. if (ponder)
  183. builder.append(" ponder"sv);
  184. if (wtime.has_value())
  185. builder.appendff(" wtime {}", wtime.value());
  186. if (btime.has_value())
  187. builder.appendff(" btime {}", btime.value());
  188. if (winc.has_value())
  189. builder.appendff(" winc {}", winc.value());
  190. if (binc.has_value())
  191. builder.appendff(" binc {}", binc.value());
  192. if (movestogo.has_value())
  193. builder.appendff(" movestogo {}", movestogo.value());
  194. if (depth.has_value())
  195. builder.appendff(" depth {}", depth.value());
  196. if (nodes.has_value())
  197. builder.appendff(" nodes {}", nodes.value());
  198. if (mate.has_value())
  199. builder.appendff(" mate {}", mate.value());
  200. if (movetime.has_value())
  201. builder.appendff(" movetime {}", movetime.value());
  202. if (infinite)
  203. builder.append(" infinite"sv);
  204. builder.append('\n');
  205. return builder.to_deprecated_string();
  206. }
  207. StopCommand StopCommand::from_string(StringView command)
  208. {
  209. auto tokens = command.split_view(' ');
  210. VERIFY(tokens[0] == "stop");
  211. VERIFY(tokens.size() == 1);
  212. return StopCommand();
  213. }
  214. DeprecatedString StopCommand::to_deprecated_string() const
  215. {
  216. return "stop\n";
  217. }
  218. IdCommand IdCommand::from_string(StringView command)
  219. {
  220. auto tokens = command.split_view(' ');
  221. VERIFY(tokens[0] == "id");
  222. StringBuilder value;
  223. for (size_t i = 2; i < tokens.size(); ++i) {
  224. if (i != 2)
  225. value.append(' ');
  226. value.append(tokens[i]);
  227. }
  228. if (tokens[1] == "name") {
  229. return IdCommand(Type::Name, value.to_deprecated_string());
  230. } else if (tokens[1] == "author") {
  231. return IdCommand(Type::Author, value.to_deprecated_string());
  232. }
  233. VERIFY_NOT_REACHED();
  234. }
  235. DeprecatedString IdCommand::to_deprecated_string() const
  236. {
  237. StringBuilder builder;
  238. builder.append("id "sv);
  239. if (field_type() == Type::Name) {
  240. builder.append("name "sv);
  241. } else {
  242. builder.append("author "sv);
  243. }
  244. builder.append(value());
  245. builder.append('\n');
  246. return builder.to_deprecated_string();
  247. }
  248. UCIOkCommand UCIOkCommand::from_string(StringView command)
  249. {
  250. auto tokens = command.split_view(' ');
  251. VERIFY(tokens[0] == "uciok");
  252. VERIFY(tokens.size() == 1);
  253. return UCIOkCommand();
  254. }
  255. DeprecatedString UCIOkCommand::to_deprecated_string() const
  256. {
  257. return "uciok\n";
  258. }
  259. ReadyOkCommand ReadyOkCommand::from_string(StringView command)
  260. {
  261. auto tokens = command.split_view(' ');
  262. VERIFY(tokens[0] == "readyok");
  263. VERIFY(tokens.size() == 1);
  264. return ReadyOkCommand();
  265. }
  266. DeprecatedString ReadyOkCommand::to_deprecated_string() const
  267. {
  268. return "readyok\n";
  269. }
  270. BestMoveCommand BestMoveCommand::from_string(StringView command)
  271. {
  272. auto tokens = command.split_view(' ');
  273. VERIFY(tokens[0] == "bestmove");
  274. VERIFY(tokens.size() == 2);
  275. return BestMoveCommand(Move(tokens[1]));
  276. }
  277. DeprecatedString BestMoveCommand::to_deprecated_string() const
  278. {
  279. StringBuilder builder;
  280. builder.append("bestmove "sv);
  281. builder.append(move().to_long_algebraic());
  282. builder.append('\n');
  283. return builder.to_deprecated_string();
  284. }
  285. InfoCommand InfoCommand::from_string([[maybe_unused]] StringView command)
  286. {
  287. // FIXME: Implement this.
  288. VERIFY_NOT_REACHED();
  289. }
  290. DeprecatedString InfoCommand::to_deprecated_string() const
  291. {
  292. // FIXME: Implement this.
  293. VERIFY_NOT_REACHED();
  294. return "info";
  295. }
  296. }