/// <summary> /// Calculates the best possible move for the specified parameters. /// </summary> /// <param name="color">The initial player.</param> /// <param name="bitboard">The bitboard.</param> /// <param name="preferredTime">Time allocated for AI.</param> /// <returns>The result of AI calculating.</returns> public AIResult Calculate(Color color, Bitboard bitboard, float preferredTime) { var result = new AIResult(); var colorSign = ColorOperations.ToSign(color); var stopwatch = new Stopwatch(); int estimatedTimeForNextIteration; result.Color = color; result.PreferredTime = preferredTime; if (bitboard.ReversibleMoves == 0 && preferredTime != 0) { _transpositionTable.Clear(); } stopwatch.Start(); do { result.Depth++; var stats = new AIStats(); result.Score = colorSign * _regularSearch.Do(color, new Bitboard(bitboard), result.Depth, AIConstants.InitialAlphaValue, AIConstants.InitialBetaValue, stats); result.PVNodes = GetPVNodes(bitboard, color); result.Stats = stats; result.Ticks = stopwatch.Elapsed.Ticks; OnThinkingOutput?.Invoke(this, new ThinkingOutputEventArgs(result)); estimatedTimeForNextIteration = (int)stopwatch.Elapsed.TotalMilliseconds * result.Stats.BranchingFactor; }while (estimatedTimeForNextIteration < preferredTime * 1000 && result.Depth < 12 && Math.Abs(result.Score) != AIConstants.MateValue); return(result); }
private void StartSearch() { TranspositionTable.Clear(); ProcessNode(); NodesSearched = 0; Moves.Clear(); Score = 0; }
public void Run(params string[] parameters) { TranspositionTable.Clear(); PawnHashTable.Clear(); EvaluationHashTable.Clear(); KillerHeuristic.Clear(); HistoryHeuristic.Clear(); _uciClient.BoardState.SetDefaultState(); }
public async Task <Move> Calculate(CancellationToken ct) { Move openingMove; if (Config.UseOpeningBook && openingBook.TryGetMove(gameState, out openingMove)) { return(openingMove); } EngineColor = gameState.Turn; GameStage = GetGameStage(); PVList pv; using (internalCts = new CancellationTokenSource()) using (linkedCts = CancellationTokenSource.CreateLinkedTokenSource(internalCts.Token, ct)) { Task <PVList> searchTask = threadMaster.Search(linkedCts.Token); if (!Config.ConstantDepth) { Task timeoutTask = Task.Delay(Config.TimeLimit, linkedCts.Token); try { await timeoutTask; internalCts.Cancel(); } catch (OperationCanceledException) { } } pv = await searchTask; } transpositionTable.Clear(); if (pv != null && pv.First != null) { pv.First.Move.SetGameState(gameState); return(pv.First.Move); } else { throw new Exception("Principal Variation is empty"); } }
private void Test(BoardState boardState, string name, int depth) { _interactiveConsole.WriteLine($" == {name}:"); TranspositionTable.Clear(); PawnHashTable.Clear(); EvaluationHashTable.Clear(); KillerHeuristic.Clear(); HistoryHeuristic.Clear(); var context = new SearchContext(boardState) { MaxDepth = depth }; IterativeDeepening.OnSearchUpdate += IterativeDeepening_OnSearchUpdate; IterativeDeepening.FindBestMove(context); IterativeDeepening.OnSearchUpdate -= IterativeDeepening_OnSearchUpdate; _interactiveConsole.WriteLine(); }
/// <summary> /// Calculates the best possible move for the specified parameters. /// </summary> /// <param name="color">The initial player.</param> /// <param name="bitboard">The bitboard.</param> /// <param name="preferredTime">Time allocated for AI.</param> /// <param name="helperTasks">The helper tasks count (0 for single thread).</param> /// <returns>The result of AI calculating.</returns> public AIResult Calculate(Color color, Bitboard bitboard, float preferredTime, int helperTasks) { var result = new AIResult(); var colorSign = ColorOperations.ToSign(color); var stopwatch = new Stopwatch(); int estimatedTimeForNextIteration; var historyTable = new HistoryTable(); var killerTable = new KillerTable(); var regularSearch = new RegularSearch(_transpositionTable, historyTable, killerTable); result.Color = color; result.PreferredTime = preferredTime; var deadline = preferredTime != 0 ? DateTime.Now.AddSeconds(preferredTime * 2).Ticks : DateTime.Now.AddSeconds(1).Ticks; historyTable.Clear(); killerTable.Clear(); if (bitboard.ReversibleMoves == 0 && preferredTime > 0) { _transpositionTable.Clear(); } stopwatch.Start(); do { result.Depth++; killerTable.SetInitialDepth(result.Depth); if (result.Depth >= AIConstants.MinimalDepthToStartHelperThreads) { for (var i = 0; i < helperTasks; i++) { var param = new HelperTaskParameters { Bitboard = new Bitboard(bitboard), Color = color, Deadline = deadline, InitialDepth = result.Depth }; Task.Run(() => HelperTask(param)); } } var stats = new AIStats(); var score = colorSign * regularSearch.Do(color, new Bitboard(bitboard), result.Depth, AIConstants.InitialAlphaValue, AIConstants.InitialBetaValue, deadline, false, stats); if (DateTime.Now.Ticks <= deadline) { result.PVNodes = GetPVNodes(bitboard, color); result.Score = score; OnThinkingOutput?.Invoke(this, new ThinkingOutputEventArgs(result)); } else { result.Depth--; _transpositionTable.Clear(); } result.Stats = stats; result.Ticks = stopwatch.Elapsed.Ticks; estimatedTimeForNextIteration = (int)stopwatch.Elapsed.TotalMilliseconds * result.Stats.BranchingFactor; }while (estimatedTimeForNextIteration < preferredTime * 1000 && result.Depth < AIConstants.MaxDepth && Math.Abs(result.Score) != AIConstants.MateValue); return(result); }