/// Wait for a command from the user, parse this text string as an UCI command, /// and call the appropriate functions. Also intercepts EOF from stdin to ensure /// that we exit gracefully if the GUI dies unexpectedly. In addition to the UCI /// commands, the function also supports a few debug commands. internal static void uci_loop(string args) { for (int i = 0; i < 102; i++) { StateRingBuf[i] = new StateInfo(); } Position pos = new Position(StartFEN, false, Threads.main_thread()); // The root position string cmd, token = string.Empty; while (token != "quit") { if (args.Length > 0) { cmd = args; } else if (String.IsNullOrEmpty(cmd = Plug.ReadLine())) // Block here waiting for input { cmd = "quit"; } Stack<string> stack = Utils.CreateStack(cmd); token = stack.Pop(); if (token == "quit" || token == "stop") { Search.SignalsStop = true; Threads.wait_for_search_finished(); // Cannot quit while threads are running } else if (token == "ponderhit") { // The opponent has played the expected move. GUI sends "ponderhit" if // we were told to ponder on the same move the opponent has played. We // should continue searching but switching from pondering to normal search. Search.Limits.ponder = false; if (Search.SignalsStopOnPonderhit) { Search.SignalsStop = true; Threads.main_thread().wake_up(); // Could be sleeping } } else if (token == "go") { go(pos, stack); } else if (token == "ucinewgame") { /* Avoid returning "Unknown command" */ } else if (token == "isready") { Plug.Write("readyok"); Plug.Write(Constants.endl); } else if (token == "position") { set_position(pos, stack); } else if (token == "setoption") { set_option(stack); } else if (token == "validmoves") { Search.validmoves(pos, stack); } else if (token == "d") { pos.print(0); } else if (token == "flip") { pos.flip(); } else if (token == "eval") { Plug.Write(Evaluate.trace(pos)); Plug.Write(Constants.endl); } else if (token == "bench") { Benchmark.benchmark(pos, stack); } else if (token == "key") { Plug.Write("key: "); Plug.Write(String.Format("{0:X}", pos.key())); Plug.Write("\nmaterial key: "); Plug.Write(pos.material_key().ToString()); Plug.Write("\npawn key: "); Plug.Write(pos.pawn_key().ToString()); Plug.Write(Constants.endl); } else if (token == "uci") { Plug.Write("id name "); Plug.Write(Utils.engine_info(true)); Plug.Write("\n"); Plug.Write(OptionMap.Instance.ToString()); Plug.Write("\nuciok"); Plug.Write(Constants.endl); } else if (token == "perft") { token = stack.Pop(); // Read depth Stack<string> ss = Utils.CreateStack( string.Format("{0} {1} {2} current perft", OptionMap.Instance["Hash"].v, OptionMap.Instance["Threads"].v, token) ); Benchmark.benchmark(pos, ss); } else { Plug.Write("Unknown command: "); Plug.Write(cmd); Plug.Write(Constants.endl); } if (args.Length > 0) // Command line arguments have one-shot behaviour { Threads.wait_for_search_finished(); break; } } }
/// Wait for a command from the user, parse this text string as an UCI command, /// and call the appropriate functions. Also intercepts EOF from stdin to ensure /// that we exit gracefully if the GUI dies unexpectedly. In addition to the UCI /// commands, the function also supports a few debug commands. internal static void loop(string args) { for (var i = 0; i < 102; i++) { StateRingBuf[i] = new StateInfo(); } var pos = new Position(StartFEN, false, Threads.main_thread()); // The root position string cmd, token = string.Empty; while (token != "quit") { if (args.Length > 0) { cmd = args; } else if (string.IsNullOrEmpty(cmd = Plug.ReadLine())) // Block here waiting for input { cmd = "quit"; } var stack = Utils.CreateStack(cmd); token = stack.Pop(); if (token == "quit" || token == "stop" || token == "ponderhit") { // GUI sends 'ponderhit' to tell us to ponder on the same move the // opponent has played. In case Signals.stopOnPonderhit is set we are // waiting for 'ponderhit' to stop the search (for instance because we // already ran out of time), otherwise we should continue searching but // switching from pondering to normal search. if (token != "ponderhit" || Search.SignalsStopOnPonderhit) { Search.SignalsStop = true; Threads.main_thread().notify_one(); // Could be sleeping } else { Search.Limits.ponder = false; } } else if (token == "go") { go(pos, stack); } else if (token == "ucinewgame") { TT.clear(); } else if (token == "isready") { Plug.Write("readyok"); Plug.Write(Constants.endl); } else if (token == "position") { set_position(pos, stack); } else if (token == "setoption") { set_option(stack); } else if (token == "validmoves") { Search.validmoves(pos, stack); } else if (token == "d") { pos.print(0); } else if (token == "flip") { pos.flip(); } else if (token == "eval") { Plug.Write(Evaluate.trace(pos)); Plug.Write(Constants.endl); } else if (token == "bench") { Benchmark.benchmark(pos, stack); } else if (token == "key") { Plug.Write("key: "); Plug.Write(string.Format("{0:X}", pos.key())); Plug.Write("\nmaterial key: "); Plug.Write(pos.material_key().ToString()); Plug.Write("\npawn key: "); Plug.Write(pos.pawn_key().ToString()); Plug.Write(Constants.endl); } else if (token == "uci") { Plug.Write("id name "); Plug.Write(Utils.engine_info(true)); Plug.Write("\n"); Plug.Write(OptionMap.Instance.ToString()); Plug.Write("\nuciok"); Plug.Write(Constants.endl); } else if (token == "perft") { token = stack.Pop(); // Read depth var ss = Utils.CreateStack( string.Format( "{0} {1} {2} current perft", OptionMap.Instance["Hash"].v, OptionMap.Instance["Threads"].v, token)); Benchmark.benchmark(pos, ss); } else { Plug.Write("Unknown command: "); Plug.Write(cmd); Plug.Write(Constants.endl); } if (args.Length > 0) // Command line arguments have one-shot behaviour { Threads.wait_for_think_finished(); break; } } }