Пример #1
0
        internal static int SetupStatePos = 0; // *SetupState = StateRingBuf;

        /// 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 == "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;
                }
            }
        }
Пример #2
0
        /// benchmark() runs a simple benchmark by letting Stockfish analyze a set
        /// of positions for a given limit each. There are five parameters; the
        /// transposition table size, the number of search threads that should
        /// be used, the limit value spent for each position (optional, default is
        /// depth 12), an optional file name where to look for positions in fen
        /// format (defaults are the positions defined above) and the type of the
        /// limit value: depth (default), time in secs or number of nodes.
        internal static void benchmark(Position current, Stack <string> stack)
        {
            List <string> fens = new List <string>();

            LimitsType limits   = new LimitsType();
            Int64      nodes    = 0;
            Int64      nodesAll = 0;
            long       e        = 0;
            long       eAll     = 0;

            // Assign default values to missing arguments
            string ttSize    = (stack.Count > 0) ? (stack.Pop()) : "128";
            string threads   = (stack.Count > 0) ? (stack.Pop()) : "1";
            string limit     = (stack.Count > 0) ? (stack.Pop()) : "12";
            string fenFile   = (stack.Count > 0) ? (stack.Pop()) : "default";
            string limitType = (stack.Count > 0) ? (stack.Pop()) : "depth";

            OptionMap.Instance["Hash"].v    = ttSize;
            OptionMap.Instance["Threads"].v = threads;
            TT.clear();

            if (limitType == "time")
            {
                limits.movetime = 1000 * int.Parse(limit); // maxTime is in ms
            }
            else if (limitType == "nodes")
            {
                limits.nodes = int.Parse(limit);
            }

            else
            {
                limits.depth = int.Parse(limit);
            }

            if (fenFile == "default")
            {
                fens.AddRange(Defaults);
            }
            else if (fenFile == "current")
            {
                fens.Add(current.to_fen());
            }
            else
            {
#if PORTABLE
                throw new Exception("File cannot be read.");
#else
                System.IO.StreamReader sr = new System.IO.StreamReader(fenFile, true);
                string fensFromFile       = sr.ReadToEnd();
                sr.Close();
                sr.Dispose();

                string[] split = fensFromFile.Replace("\r", "").Split('\n');
                foreach (string fen in split)
                {
                    if (fen.Trim().Length > 0)
                    {
                        fens.Add(fen.Trim());
                    }
                }
#endif
            }

            Stopwatch time = new Stopwatch();
            long[]    res  = new long[fens.Count];
            for (int i = 0; i < fens.Count; i++)
            {
                time.Reset(); time.Start();
                Position pos = new Position(fens[i], bool.Parse(OptionMap.Instance["UCI_Chess960"].v), Threads.main_thread());

                Plug.Write("\nPosition: ");
                Plug.Write((i + 1).ToString());
                Plug.Write("/");
                Plug.Write(fens.Count.ToString());
                Plug.Write(Constants.endl);

                if (limitType == "perft")
                {
                    Int64 cnt = Search.perft(pos, limits.depth * DepthC.ONE_PLY);
                    Plug.Write("\nPerft ");
                    Plug.Write(limits.depth.ToString());
                    Plug.Write(" leaf nodes: ");
                    Plug.Write(cnt.ToString());
                    Plug.Write(Constants.endl);
                    nodes = cnt;
                }
                else
                {
                    Threads.start_searching(pos, limits, new List <Move>());
                    Threads.wait_for_search_finished();
                    nodes  = Search.RootPosition.nodes;
                    res[i] = nodes;
                }

                e = time.ElapsedMilliseconds;

                nodesAll += nodes;
                eAll     += e;

                Plug.Write("\n===========================");
                Plug.Write("\nTotal time (ms) : ");
                Plug.Write(e.ToString());
                Plug.Write("\nNodes searched  : ");
                Plug.Write(nodes.ToString());
                Plug.Write("\nNodes/second    : ");
                Plug.Write(((int)(nodes / (e / 1000.0))).ToString());
                Plug.Write(Constants.endl);
            }

            Plug.Write("\n===========================");
            Plug.Write("\nTotal time (ms) : ");
            Plug.Write(eAll.ToString());
            Plug.Write("\nNodes searched  : ");
            Plug.Write(nodesAll.ToString());
            Plug.Write("\nNodes/second    : ");
            Plug.Write(((int)(nodesAll / (eAll / 1000.0))).ToString());
            Plug.Write(Constants.endl);

            //for (int i = 0; i < res.Length; i++)
            //{
            //    Plug.Write(string.Format("{0}: {1}", i, res[i]));
            //    Plug.Write(Constants.endl);
            //}
        }