/// <summary> /// Executes the parsing. /// </summary> public static void Run() { Restrictions.Output = OutputType.Universal; IEngine engine = new Zero(); Position position = new Position(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 " + Zero.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 = new Position(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; } } }
/// <summary> /// Begins the test with the given positions. /// </summary> /// <param name="epd">A list of positions in EPD format.</param> public static void Run(List <String> epd) { // Perform testing on a background thread. new Thread(new ThreadStart(() => { IEngine engine = new Zero(); Restrictions.Output = OutputType.None; Int32 totalPositions = 0; Int32 totalSolved = 0; Int64 totalNodes = 0; Double totalTime = 0; Terminal.WriteLine(ResultFormat, "Position", "Result", "Time", "Nodes"); Terminal.WriteLine("-----------------------------------------------------------------------"); foreach (String line in epd) { List <String> terms = new List <String>(line.Replace(";", " ;").Split(' ')); // Strip everything to get the FEN. Int32 bmIndex = line.IndexOf("bm "); bmIndex = bmIndex < 0 ? Int32.MaxValue : bmIndex; Int32 amIndex = line.IndexOf("am "); amIndex = amIndex < 0 ? Int32.MaxValue : amIndex; String fen = line.Remove(Math.Min(bmIndex, amIndex)); // Get the best moves. List <String> solutions = new List <String>(); for (Int32 i = terms.IndexOf("bm") + 1; i >= 0 && i < terms.Count && terms[i] != ";"; i++) { solutions.Add(terms[i]); } // Get the ID of the position. Int32 idIndex = line.IndexOf("id ") + 3; String id = line.Substring(idIndex, line.IndexOf(';', idIndex) - idIndex).Replace(@"\", ""); if (id.Length > IDWidthLimit) { id = id.Remove(IDWidthLimit) + ".."; } // Set the position and invoke a search on it. Position position = new Position(fen); VisualPosition.Set(position); engine.Reset(); Stopwatch stopwatch = Stopwatch.StartNew(); Int32 move = engine.GetMove(position); stopwatch.Stop(); Double elapsed = stopwatch.Elapsed.TotalMilliseconds; totalPositions++; totalTime += elapsed; totalNodes += engine.Nodes; // Determine whether the engine found a solution. String result = "fail"; if (solutions.Contains(Stringify.MoveAlgebraically(position, move))) { result = "pass"; totalSolved++; } // Print the result for the search on the position. Terminal.WriteLine(ResultFormat, id, result, String.Format("{0:0} ms", elapsed), engine.Nodes); } // Print final results after all positions have been searched. Terminal.WriteLine("-----------------------------------------------------------------------"); Terminal.WriteLine("Result {0} / {1}", totalSolved, totalPositions); Terminal.WriteLine("Time {0:0} ms", totalTime); Terminal.WriteLine("Average nodes {0:0}", (Double)totalNodes / totalPositions); })) { IsBackground = true }.Start(); // Open the GUI window to draw positions. Application.Run(new Window()); }
/// <summary> /// Begins the tournament with the given positions. /// </summary> /// <param name="epd">A list of positions to play in EPD format.</param> public static void Run(List <String> epd) { IEngine experimental = new Zero() { IsExperimental = true }; IEngine standard = new Zero(); Restrictions.Output = OutputType.None; Int32 wins = 0; Int32 losses = 0; Int32 draws = 0; using (StreamWriter sw = new StreamWriter(ID + ".txt")) { sw.WriteLine(new String(' ', UpdateInterval) + String.Format(ResultFormat, "Games", "Wins", "Losses", "Draws", "Elo", "Error")); sw.WriteLine("--------------------------------------------------------------------"); // Play the tournament. for (Int32 games = 1; ; games++) { sw.Flush(); experimental.Reset(); standard.Reset(); Position position = new Position(epd[Random.Int32(epd.Count - 1)]); MatchResult result = Match.Play(experimental, standard, position, MatchOptions.RandomizeColour); // Write the match result. switch (result) { case MatchResult.Win: sw.Write('1'); wins++; break; case MatchResult.Loss: sw.Write('0'); losses++; break; case MatchResult.Draw: sw.Write('-'); draws++; break; case MatchResult.Unresolved: sw.Write('*'); draws++; break; } // Write the cummulative results. if (games % UpdateInterval == 0) { Double delta = Elo.GetDelta(wins, losses, draws); String elo = String.Format("{0:+0;-0}", delta); Double[] bound = Elo.GetError(Elo.Z95, wins, losses, draws); Double lower = Math.Max(bound[0], -999); Double upper = Math.Min(bound[1], 999); String asterisk = Elo.IsErrorValid(wins, losses, draws) ? String.Empty : "*"; String error = String.Format("{0:+0;-0} {1:+0;-0}{2}", lower, upper, asterisk); sw.WriteLine(String.Format(ResultFormat, games, wins, losses, draws, elo, error)); } } } }