// todo: the user should be able to change the search algorithm during the course of the program, as well as other parameters like depth, TT capacity, etc static AI GetAI() { ISearchAlgorithm inner; while (true) { Write("Pick AI strategy [mtdf, mtdf-ids (default)]: "); string input = ReadLine().Trim().ToLower(); switch (input) { case "mtdf": inner = new Mtdf() { Depth = SearchDepth }; inner.Tt = inner.MakeTt(TtCapacity); break; case "": case "mtdf-ids": inner = new MtdfIds() { Depth = SearchDepth }; inner.Tt = inner.MakeTt(TtCapacity); break; default: continue; } return(new AI(inner)); } }
public void MtdfIds() { var ids = new MtdfIds() { Depth = Depth, }; ids.Tt = ids.MakeTt(TtCapacity); ids.Search(State.Start); }
void Go(Stack <string> tokens) { if (_root == null) { Error.WriteLine("Position not set, use the 'position' command to set it"); return; } var settings = new GoSettings(); while (tokens.TryPop(out var paramName)) { switch (paramName) { case "searchmoves": // needs to be the last command on the line var searchMoves = new List <Move>(); while (tokens.TryPop(out var move)) { searchMoves.Add(Move.ParseLong(move)); } settings.SearchMoves = searchMoves.ToImmutableArray(); break; case "ponder": _ponder = true; break; case "depth": settings.Depth = int.Parse(tokens.Pop()); break; case "nodes": settings.Nodes = int.Parse(tokens.Pop()); break; case "mate": // todo settings.Mate = int.Parse(tokens.Pop()); break; case "movetime": // todo settings.MoveTime = TimeSpan.FromMilliseconds(int.Parse(tokens.Pop())); break; case "infinite": settings.Infinite = true; break; } } // go ahead with the search var searcher = new MtdfIds(); searcher.Depth = settings.Depth ?? ((settings.Infinite || settings.Nodes != null) ? int.MaxValue : DefaultSearchDepth); searcher.MaxNodes = settings.Nodes ?? int.MaxValue; int ttCapacity = _options.Get <int>("Hash") * EntriesPerMb; if (_tt == null || _tt.Capacity != ttCapacity) { _tt = searcher.MakeTt(ttCapacity); } searcher.Tt = _tt; _ponder = false; var cts = new CancellationTokenSource(); // define the task and either run it straight away, or add it to the queue if there's one in progress var rootCopy = _root; // if a new search is requested before this one is started, we don't want to pick up on a new position var searchTask = new Task(() => { try { _cts = cts; Search(rootCopy, searcher, settings, this, cts.Token); } // exceptions don't propagate to the main thread unless they are explicitly handled like this catch (Exception e) { Error.WriteLine(e); } finally { cts.Dispose(); _cts = null; // run the next task if one is queued if (_searchQueue.TryDequeue(out var nextTask)) { nextTask.Start(); } else { _searchInProgress = false; } } }); if (!_searchInProgress) { Debug.Assert(_searchQueue.IsEmpty); _searchInProgress = true; searchTask.Start(); } else { _searchQueue.Enqueue(searchTask); } }