Ejemplo n.º 1
0
        /// <summary>
        /// Executes the parsing.
        /// </summary>
        public static void Run()
        {
            Restrictions.Output = OutputType.UCI;
            Engine   engine   = new Engine();
            Position position = Position.Create(Position.StartingFEN);

            String command;

            while ((command = Console.ReadLine()) != null)
            {
                List <String> terms = new List <String>(command.Split(' '));

                switch (terms[0])
                {
                default:
                    Terminal.WriteLine("Unknown command: {0}", terms[0]);
                    Terminal.WriteLine("Enter \"help\" for assistance.");
                    break;

                case "uci":
                    Terminal.WriteLine("id name " + engine.Name);
                    Terminal.WriteLine("id author Zong Zheng Li");
                    Terminal.WriteLine("option name Hash type spin default " + Engine.DefaultHashAllocation + " min 1 max 2047");
                    Terminal.WriteLine("uciok");
                    break;

                case "ucinewgame":
                    engine.Reset();
                    break;

                case "setoption":
                    if (terms.Contains("Hash"))
                    {
                        engine.HashAllocation = Int32.Parse(terms[terms.IndexOf("value") + 1]);
                    }
                    break;

                case "position":
                    String fen = Position.StartingFEN;
                    if (terms[1] != "startpos")
                    {
                        fen = command.Substring(command.IndexOf("fen") + 4);
                    }
                    position = Position.Create(fen);

                    Int32 movesIndex = terms.IndexOf("moves");
                    if (movesIndex >= 0)
                    {
                        for (Int32 i = movesIndex + 1; i < terms.Count; i++)
                        {
                            position.Make(Move.Create(position, terms[i]));
                        }
                    }
                    break;

                case "go":
                    Restrictions.Reset();
                    for (Int32 i = 1; i < terms.Count; i++)
                    {
                        switch (terms[i])
                        {
                        default:
                        case "infinite":
                            break;

                        case "depth":
                            Restrictions.Depth           = Int32.Parse(terms[i + 1]);
                            Restrictions.UseTimeControls = false;
                            break;

                        case "movetime":
                            Restrictions.MoveTime        = Int32.Parse(terms[i + 1]);
                            Restrictions.UseTimeControls = false;
                            break;

                        case "wtime":
                            Restrictions.TimeControl[Colour.White] = Int32.Parse(terms[i + 1]);
                            Restrictions.UseTimeControls           = true;
                            break;

                        case "btime":
                            Restrictions.TimeControl[Colour.Black] = Int32.Parse(terms[i + 1]);
                            Restrictions.UseTimeControls           = true;
                            break;

                        case "winc":
                            Restrictions.TimeIncrement[Colour.White] = Int32.Parse(terms[i + 1]);
                            Restrictions.UseTimeControls             = true;
                            break;

                        case "binc":
                            Restrictions.TimeIncrement[Colour.Black] = Int32.Parse(terms[i + 1]);
                            Restrictions.UseTimeControls             = true;
                            break;

                        case "nodes":
                            Restrictions.Nodes           = Int32.Parse(terms[i + 1]);
                            Restrictions.UseTimeControls = false;
                            break;

                        case "ponder":
                            // TODO: implement command.
                            break;

                        case "mate":
                            // TODO: implement command.
                            break;

                        case "movestogo":
                            // TODO: implement command.
                            break;
                        }
                    }
                    new Thread(new ThreadStart(() => {
                        Int32 bestMove = engine.GetMove(position);
                        Terminal.WriteLine("bestmove " + Stringify.Move(bestMove));
                    }))
                    {
                        IsBackground = true
                    }.Start();
                    break;

                case "stop":
                    engine.Stop();
                    break;

                case "isready":
                    Terminal.WriteLine("readyok");
                    break;

                case "quit":
                    return;

                case "perft":
                    Perft.Iterate(position, Int32.Parse(terms[1]));
                    break;

                case "divide":
                    Perft.Divide(position, Int32.Parse(terms[1]));
                    break;

                case "draw":
                    Terminal.WriteLine(position);
                    break;

                case "fen":
                    Terminal.WriteLine(position.GetFEN());
                    break;

                case "ponderhit":
                    // TODO: implement command.
                    break;

                case "register":
                    // TODO: implement command.
                    break;

                case "help":
                    Terminal.WriteLine("Command             Function");
                    Terminal.WriteLine("-----------------------------------------------------------------------");
                    Terminal.WriteLine("position [fen]      Sets the current position to the position denoted");
                    Terminal.WriteLine("                    by the given FEN. \"startpos\" is accepted for the");
                    Terminal.WriteLine("                    starting position");
                    Terminal.WriteLine("go [type] [number]  Searches the current position. Search types include");
                    Terminal.WriteLine("                    \"movetime\", \"depth\", \"nodes\", \"wtime\", \"btime\",");
                    Terminal.WriteLine("                    \"winc\", and \"binc\"");
                    Terminal.WriteLine("perft [number]      Runs perft() on the current position to the given");
                    Terminal.WriteLine("                    depth");
                    Terminal.WriteLine("divide [number]     Runs divide() on the current position for the given");
                    Terminal.WriteLine("                    depth");
                    Terminal.WriteLine("fen                 Prints the FEN of the current position.");
                    Terminal.WriteLine("draw                Draws the current position");
                    Terminal.WriteLine("stop                Stops an ongoing search");
                    Terminal.WriteLine("quit                Exits the application");
                    Terminal.WriteLine("-----------------------------------------------------------------------");
                    break;
                }
            }
        }
Ejemplo n.º 2
0
        public static void Main(String[] args)
        {
            // Display terminal window by default. We will hide it later if necessary.
            Terminal.Initialize();

            // Run as GUI application if there are no command-line arguments. Display
            // the Settings window, which will display the main board window as needed.
            if (args.Length == 0)
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Settings());
            }

            // Run as command-line application if there are command-line arguments.
            else
            {
                Action        run = null;
                List <String> epd = new List <String>();

                for (Int32 i = 0; i < args.Length; i++)
                {
                    if (args[i].EndsWith(".epd", StringComparison.InvariantCultureIgnoreCase))
                    {
                        using (StreamReader sr = new StreamReader(args[i]))
                            while (!sr.EndOfStream)
                            {
                                String line = sr.ReadLine();
                                if (line.Length > 0)
                                {
                                    epd.Add(line);
                                }
                            }
                    }
                    else
                    {
                        switch (args[i])
                        {
                        // Unrecognized command.
                        default:
                            Terminal.WriteLine("Unrecognized parameter: {0}", args[i]);
                            Terminal.WriteLine("Valid parameters are:");
                            Terminal.WriteLine("-u           UCI/command-line mode");
                            Terminal.WriteLine("-t           Tournament mode");
                            Terminal.WriteLine("-s           Test suite mode");
                            Terminal.WriteLine("-m [number]  Limit move time");
                            Terminal.WriteLine("-d [number]  Limit depth");
                            Terminal.WriteLine("-n [number]  Limit nodes");
                            break;

                        // Limit move time.
                        case "-m":
                            Restrictions.MoveTime = Int32.Parse(args[++i]);
                            break;

                        // Limit depth.
                        case "-d":
                            Restrictions.Depth = Int32.Parse(args[++i]);
                            break;

                        // Limit nodes.
                        case "-n":
                            Restrictions.Nodes = Int32.Parse(args[++i]);
                            break;

                        // UCI mode.
                        case "uci":
                        case "-uci":
                        case "-u":
                            run = () => { UCI.Run(); };
                            break;

                        // Tournament mode.
                        case "-t":
                            run = () => { Tournament.Run(epd); };

                            break;

                        // Test suite mode.
                        case "-s":
                            run = () => { TestSuite.Run(epd); };
                            break;
                        }
                    }
                }

                run();
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Returns the best move for the given position as determined by an
        /// iterative deepening search framework. This is the main entry point for
        /// the search algorithm.
        /// </summary>
        /// <param name="position">The position to search on.</param>
        /// <returns>The predicted best move.</returns>
        private Int32 Search(Position position)
        {
            // Generate legal moves. Return immediately if there is only one legal move
            // when playing with time controls.
            List <Int32> moves = position.LegalMoves();

            if (Restrictions.UseTimeControls && moves.Count <= 1)
            {
                return(moves[0]);
            }

            // Initialize variables to prepare for search.
            Int32 colour     = position.SideToMove;
            Int32 depthLimit = Math.Min(DepthLimit, Restrictions.Depth);

            _timeLimit     = Restrictions.MoveTime;
            _timeExtension = 0;

            // Allocate search time when playing with time controls.
            if (Restrictions.UseTimeControls)
            {
                Double timeAllocation = Restrictions.TimeControl[colour] / Math.Max(20, Math.Ceiling(60 * Math.Exp(-0.007 * position.HalfMoves)));
                _timeLimit          = timeAllocation + Restrictions.TimeIncrement[colour] - TimeControlsExpectedLatency;
                _timeExtensionLimit = 0.3 * Restrictions.TimeControl[colour] - timeAllocation;
            }

            // Apply iterative deepening. The search is repeated with incrementally
            // higher depths until it is terminated.
            for (Int32 depth = 1; depth <= depthLimit; depth++)
            {
                Int32 alpha = -Infinity;

                // Go through the move list.
                for (Int32 i = 0; i < moves.Count; i++)
                {
                    _movesSearched++;

                    Int32   value       = alpha + 1;
                    Int32   move        = moves[i];
                    Boolean causesCheck = position.CausesCheck(move);
                    position.Make(move);

                    // Apply principal variation search with aspiration windows. The first move
                    // is searched with a window centered around the best value found from the
                    // most recent preceding search. If the result does not lie within the
                    // window, a re-search is initiated with an open window.
                    if (i == 0)
                    {
                        Int32 lower = _rootAlpha - AspirationWindow;
                        Int32 upper = _rootAlpha + AspirationWindow;

                        value = -Search(position, depth - 1, 1, -upper, -lower, causesCheck);
                        if (value <= lower || value >= upper)
                        {
                            TryTimeExtension(TimeControlsResearchThreshold, TimeControlsResearchExtension);
                            value = -Search(position, depth - 1, 1, -Infinity, Infinity, causesCheck);
                        }
                    }

                    // Subsequent moves are searched with a zero window search. If the result is
                    // better than the best value so far, a re-search is initiated with a wider
                    // window.
                    else
                    {
                        value = -Search(position, depth - 1, 1, -alpha - 1, -alpha, causesCheck);
                        if (value > alpha)
                        {
                            value = -Search(position, depth - 1, 1, -Infinity, -alpha, causesCheck);
                        }
                    }

                    // Unmake the move and check for search termination.
                    position.Unmake(move);
                    if (_abortSearch)
                    {
                        goto exit;
                    }

                    // Check for new best move. If the current move has the best value so far,
                    // it is moved to the front of the list. This ensures the best move is
                    // always the first move in the list, also gives a rough ordering of the
                    // moves, and so subsequent searches are more efficient. The principal
                    // variation is collected at this point.
                    if (value > alpha)
                    {
                        alpha = _rootAlpha = value;
                        moves.RemoveAt(i);
                        moves.Insert(0, move);
                        PrependPV(move, 0);
                        _pv = GetPrincipalVariation();

                        // Output principal variation for high depths. This happens on every depth
                        // increase and every time an improvement is found.
                        if (Restrictions.Output != OutputType.None && depth > SingleVariationDepth)
                        {
                            Terminal.WriteLine(GetPVString(position, depth, alpha, _pv));
                        }
                    }
                }

                // Output principal variation for low depths. This happens once for every
                // depth since improvements are very frequent.
                if (Restrictions.Output != OutputType.None && depth <= SingleVariationDepth)
                {
                    Terminal.WriteLine(GetPVString(position, depth, alpha, _pv));
                }

                // Check for early search termination. If there is no time extension and a
                // significiant proportion of time has already been used, so that completing
                // one more depth is unlikely, the search is terminated.
                if (Restrictions.UseTimeControls && _timeExtension <= 0 && _stopwatch.ElapsedMilliseconds / _timeLimit > TimeControlsContinuationThreshold)
                {
                    goto exit;
                }
            }
exit:
            _finalAlpha = _rootAlpha;
            return(moves[0]);
        }