Esempio n. 1
0
    /// UCI::loop() waits for a command from stdin, parses it and calls the appropriate
    /// function. Also intercepts EOF from stdin to ensure gracefully exiting if the
    /// GUI dies unexpectedly. When called with some command line arguments, e.g. to
    /// run 'bench', once the command is executed the function returns immediately.
    /// In addition to the UCI ones, also some additional debug commands are supported.
    internal static void loop(string args)
    {
        var pos = new Position(StartFEN, false, ThreadPool.main()); // The root position
        string token = string.Empty;

        do
        {
            try
            {
                string cmd;
                if (args.Length > 0)
                {
                    cmd = args;
                }
                else if (null == (cmd = Console.ReadLine())) // Block here waiting for input
                {
                    cmd = "quit";
                }
                
                var stack = Position.CreateStack(cmd);
                if (stack.Count == 0)
                {
                    continue;
                }

                token = stack.Pop();

                // The 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 == "quit" || token == "stop" || (token == "ponderhit") && Search.Signals.stopOnPonderhit)
                {
                    Search.Signals.stop = true;
                    ThreadPool.main().notify_one(); // Could be sleeping
                }
                else if (token == "ponderhit")
                {
                    Search.Limits.ponder = false; // Switch to normal search
                }
                else if (token == "uci")
                {
                    Output.Write("id name ");
                    Output.Write(Utils.engine_info(true));
                    Output.Write("\n");
                    Output.Write(OptionMap.Instance.ToString());
                    Output.WriteLine("\nuciok");
                }
                else if (token == "ucinewgame")
                {
                    Search.reset();
                    TimeManagement.availableNodes = 0;
                }
                else if (token == "isready")
                {
                    Output.WriteLine("readyok");
                }
                else if (token == "go")
                {
                    go(pos, stack);
                }
                else if (token == "position")
                {
                    position(pos, stack);
                }
                else if (token == "setoption")
                {
                    setoption(stack);
                }

                // Additional custom non-UCI commands, useful for debugging
                else if (token == "flip")
                {
                    pos.flip();
                }
                else if (token == "eval")
                {
                    Output.WriteLine(Eval.trace(pos));
                }
                else if (token == "bench")
                {
                    Benchmark.benchmark(pos, stack);
                }
                else if (token == "d")
                {
                    Output.Write(pos.displayString());
                }
                else if (token == "perft")
                {
                    token = stack.Pop(); // Read depth
                    var ss =
                        Position.CreateStack(
                            $"{OptionMap.Instance["Hash"].v} {OptionMap.Instance["Threads"].v} {token} current perft");
                    Benchmark.benchmark(pos, ss);
                }

                else
                {
                    Output.Write("Unknown command: ");
                    Output.WriteLine(cmd);
                }
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine($"An error occurred: {ex}");
            }
        } while (token != "quit" && args.Length == 0); // Passed args have one-shot behaviour

        ThreadPool.main().join(); // Cannot quit whilst the search is running
    }