/// <summary> /// Returns a move to be played on the given position that has the given /// representation in coordinate notation. /// </summary> /// <param name="position">The position the move is to be played on.</param> /// <param name="name">The representation of the move in coordinate notation.</param> /// <returns>A move that has the given representation in coordinate notation.</returns> public static Int32 Create(Position position, String name) { foreach (Int32 move in position.LegalMoves()) { if (name == Stringify.Move(move)) { return(move); } } return(Invalid); }
/// <summary> /// Performs divide on the given position with the given depth. This /// essentially performs perft on each of the positions arising from the /// legal moves for the given position. This method writes the results to /// the terminal. /// </summary> /// <param name="position">The position to perform divide on.</param> /// <param name="depth">The depth to perform divide with.</param> public static void Divide(Position position, Int32 depth) { const Int32 MoveWidth = 8; String format = "{0,-" + MoveWidth + "}{1}"; Terminal.WriteLine(format, "Move", "Nodes"); Terminal.WriteLine("-----------------------------------------------------------------------"); List <Int32> moves = position.LegalMoves(); Int64 totalNodes = 0; foreach (Int32 move in moves) { position.Make(move); Int64 nodes = Nodes(position, depth - 1); position.Unmake(move); totalNodes += nodes; Terminal.WriteLine(format, Stringify.Move(move), nodes); } Terminal.WriteLine("-----------------------------------------------------------------------"); Terminal.WriteLine("Moves: " + moves.Count); Terminal.WriteLine("Nodes: " + totalNodes); }
/// <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; } } }