예제 #1
0
        /// <summary>
        /// Completes an incomplete move caused by Hierarchical Expansion.
        /// </summary>
        /// <param name="state">The game state to create an action for.</param>
        /// <param name="action">The currently created action.</param>
        private void CompleteHEMove(SabberStoneState state, SabberStoneAction action)
        {
            // Copy state so that we can process the tasks and get an updated options list.
            var copyState = (SabberStoneState)state.Copy();

            // Process the currently selected tasks
            foreach (var task in action.Tasks)
            {
                try {
                    copyState.Game.Process(task.Task);
                }
                catch (Exception e) {
                    Console.WriteLine($"ERROR: {e.GetType()} thrown while trying to process a task.");
                    break;
                }
            }
            // Ask the Searcher to determine the best tasks to complete the action
            var completingAction = Searcher.DetermineBestTasks(copyState);

            // Add the tasks to the provided action
            foreach (var task in completingAction.Tasks)
            {
                action.AddTask(task);
            }

            // If the move is not complete yet (for example, when the game is over), add EndTurn
            if (!action.IsComplete())
            {
                action.AddTask((SabberStonePlayerTask)EndTurnTask.Any(Player));
            }
        }
        public SabberStoneAction Act(SabberStoneState state)
        {
            var timer     = System.Diagnostics.Stopwatch.StartNew();
            var gameState = (SabberStoneState)state.Copy();

            if (_debug)
            {
                Console.WriteLine();
            }
            if (_debug)
            {
                Console.WriteLine(Name());
            }
            if (_debug)
            {
                Console.WriteLine($"Starting a Heuristic search in turn {(gameState.Game.Turn + 1) / 2}");
            }

            var solution = new SabberStoneAction();

            while (gameState.CurrentPlayer() == PlayerID() && gameState.Game.State != State.COMPLETE)
            {
                var poGame = new POGame(gameState.Game, _debug);
                var task   = GetMove(poGame);
                solution.AddTask((SabberStonePlayerTask)task);
                gameState.Game.Process(task);
            }

            var time = timer.ElapsedMilliseconds;

            if (_debug)
            {
                Console.WriteLine();
            }
            if (_debug)
            {
                Console.WriteLine($"Heuristic returned with solution: {solution}");
            }
            if (_debug)
            {
                Console.WriteLine($"My total calculation time was: {time} ms.");
            }

            // Check if the solution is a complete action.
            if (!solution.IsComplete())
            {
                // Otherwise add an End-Turn task before returning.
                if (_debug)
                {
                    Console.WriteLine("Solution was an incomplete action; adding End-Turn task.");
                }
                solution.Tasks.Add((SabberStonePlayerTask)EndTurnTask.Any(Player));
            }

            if (_debug)
            {
                Console.WriteLine();
            }
            return(solution);
        }
예제 #3
0
        /// <inheritdoc />
        public SabberStoneAction Act(SabberStoneState state)
        {
            var timer     = System.Diagnostics.Stopwatch.StartNew();
            var gameState = (SabberStoneState)state.Copy();

            if (_debug)
            {
                Console.WriteLine();
            }
            if (_debug)
            {
                Console.WriteLine(Name());
            }
            if (_debug)
            {
                Console.WriteLine($"Starting a NMCTS search in turn {(gameState.Game.Turn + 1) / 2}");
            }

            // Setup and start the ensemble-search
            EnsembleSolutions = new List <SabberStoneAction>();
            var search  = (NMCTS <List <SabberStoneAction>, SabberStoneState, SabberStoneAction, object, SabberStoneAction>)Builder.Build();
            var context = SearchContext <List <SabberStoneAction>, SabberStoneState, SabberStoneAction, object, SabberStoneAction> .GameSearchSetup(GameLogic, EnsembleSolutions, gameState, null, search);

            Ensemble.EnsembleSearch(context, Searcher.Search, EnsembleSize);
            IterationsSpent = EnsembleSolutions.Sum(i => i.BudgetUsed);

            // Determine the best tasks to play based on the ensemble search, or just take the one in case of a single search.
            var solution = EnsembleSize > 1 ? Searcher.VoteForSolution(EnsembleSolutions, state) : EnsembleSolutions.First();

            if (_debug)
            {
                Console.WriteLine();
            }
            if (_debug)
            {
                Console.WriteLine($"NMCTS returned with solution: {solution}");
            }
            if (_debug)
            {
                Console.WriteLine($"My total calculation time was: {timer.ElapsedMilliseconds} ms.");
            }

            // Check if the solution is a complete action.
            if (!solution.IsComplete())
            {
                // Otherwise add an End-Turn task before returning.
                if (_debug)
                {
                    Console.WriteLine("Solution was an incomplete action; adding End-Turn task.");
                }
                solution.Tasks.Add((SabberStonePlayerTask)EndTurnTask.Any(Player));
            }

            if (_debug)
            {
                Console.WriteLine();
            }
            return(solution);
        }
예제 #4
0
            /// <inheritdoc />
            public SabberStoneAction Sample(SabberStoneState state, OddmentTable <SabberStonePlayerTask> sideInformation)
            {
                var copyState      = (SabberStoneState)state.Copy();
                var availableTasks = GetAvailablePlayerTasks(copyState);
                var action         = new SabberStoneAction();
                var tries          = 0;

                // Keep sampling tasks while we have not passed the turn yet and there are more tasks available than only EndTurn or HeroPower, of if we haven't generated a suitable task in 100 tries
                while (!action.IsComplete() && availableTasks.Any(i => i.Task.PlayerTaskType != PlayerTaskType.END_TURN && i.Task.PlayerTaskType != PlayerTaskType.HERO_POWER) && tries < 100)
                {
                    // Sample a task from the OddmentTable
                    var task = sideInformation.Next();
                    // Check if the task is available in the current state
                    if (!availableTasks.Contains(task, PlayerTaskComparer.Comparer))
                    {
                        tries++;
                        continue;
                    }

                    tries = 0;
                    action.AddTask(task);
                    copyState.Game.Process(task.Task);
                    availableTasks = GetAvailablePlayerTasks(copyState);
                }

                if (action.IsComplete())
                {
                    return(action);
                }

                // If hero power is available, add it
                if (availableTasks.Any(i => i.Task.PlayerTaskType == PlayerTaskType.HERO_POWER))
                {
                    action.AddTask(availableTasks.First(i => i.Task.PlayerTaskType == PlayerTaskType.HERO_POWER));
                }

                // If the action is not complete yet, add EndTurn
                action.AddTask((SabberStonePlayerTask)EndTurnTask.Any(state.Game.CurrentPlayer));

                return(action);
            }
예제 #5
0
        /// <inheritdoc />
        public SabberStoneAction Act(SabberStoneState state)
        {
            var timer     = Stopwatch.StartNew();
            var stateCopy = (SabberStoneState)state.Copy();

            if (_debug)
            {
                Console.WriteLine();
            }
            if (_debug)
            {
                Console.WriteLine(Name());
            }
            if (_debug)
            {
                Console.WriteLine($"Starting an LSI search in turn {(stateCopy.Game.Turn + 1) / 2}");
            }

            // Create a new LSI search
            var search = new LSI <List <SabberStoneAction>, SabberStoneState, SabberStoneAction, object, TreeSearchNode <SabberStoneState, SabberStoneAction>, OddmentTable <SabberStonePlayerTask> >(
                SideInformationStrategy,
                SamplingStrategy,
                Playout,
                Evaluation,
                GameLogic,
                BudgetEstimationStrategy
                );

            // Reset the solutions collection
            EnsembleSolutions = new List <SabberStoneAction>();

            // Create a SearchContext that just holds the current state as Source and the Search.
            var context = SearchContext <List <SabberStoneAction>, SabberStoneState, SabberStoneAction, object, SabberStoneAction> .Context(EnsembleSolutions, stateCopy, null, null, search, null);

            // The Playout strategy will call the Goal strategy from the context, so we set it here
            context.Goal = Goal;

            // Execute the search
            Ensemble.EnsembleSearch(context, Searcher.Search, EnsembleSize);
            SamplesSpent = EnsembleSolutions.Sum(i => i.BudgetUsed);

            // Determine a solution
            var solution = Searcher.VoteForSolution(EnsembleSolutions, state);

            timer.Stop();
            if (_debug)
            {
                Console.WriteLine();
            }
            if (_debug)
            {
                Console.WriteLine($"LSI returned with solution: {solution}");
            }
            if (_debug)
            {
                Console.WriteLine($"My total calculation time was: {timer.ElapsedMilliseconds}ms");
            }

            // Check if the solution is a complete action.
            if (!solution.IsComplete())
            {
                // Otherwise add an End-Turn task before returning.
                solution.Tasks.Add((SabberStonePlayerTask)EndTurnTask.Any(Player));
            }

            // If we are estimating the budget by using the previous search's results, save these now
            if (BudgetEstimation == BudgetEstimationType.PreviousSearchAverage && BudgetEstimationStrategy is PreviousSearchAverageBudgetEstimationStrategy estimationStrategy)
            {
                estimationStrategy.PreviousSearchTime       = timer.ElapsedMilliseconds;
                estimationStrategy.PreviousSearchIterations = SamplesSpent;
            }

            if (_debug)
            {
                Console.WriteLine();
            }
            return(solution);
        }
예제 #6
0
        /// <inheritdoc />
        /// <summary>
        /// Requests the bot to return a SabberStoneAction based on the current SabberStoneState.
        /// </summary>
        /// <param name="state">The current game state.</param>
        /// <returns>SabberStoneAction that was voted as the best option by the ensemble.</returns>
        public SabberStoneAction Act(SabberStoneState state)
        {
            var timer     = System.Diagnostics.Stopwatch.StartNew();
            var gameState = (SabberStoneState)state.Copy();

            if (_debug)
            {
                Console.WriteLine();
            }
            if (_debug)
            {
                Console.WriteLine(Name());
            }
            if (_debug)
            {
                Console.WriteLine($"Starting a MCTS search in turn {(gameState.Game.Turn + 1) / 2}");
            }

            // Check if the task statistics in the searcher should be reset
            if (!RetainTaskStatistics)
            {
                Searcher.ResetTaskStatistics();
            }

            // Setup and start the ensemble-search
            EnsembleSolutions = new List <SabberStoneAction>();
            var search  = (MCTS <List <SabberStoneAction>, SabberStoneState, SabberStoneAction, object, SabberStoneAction>)Builder.Build();
            var context = SearchContext <List <SabberStoneAction>, SabberStoneState, SabberStoneAction, object, SabberStoneAction> .GameSearchSetup(GameLogic, EnsembleSolutions, gameState, null, search);

            Ensemble.EnsembleSearch(context, Searcher.Search, EnsembleSize);
            IterationsSpent = EnsembleSolutions.Sum(i => i.BudgetUsed);

            // Determine the best tasks to play based on the ensemble search, or just take the one in case of a single search.
            var solution = EnsembleSize > 1 ? Searcher.VoteForSolution(EnsembleSolutions, state) : EnsembleSolutions.First();

            var time = timer.ElapsedMilliseconds;

            if (_debug)
            {
                Console.WriteLine();
            }
            if (_debug)
            {
                Console.WriteLine($"MCTS returned with solution: {solution}");
            }
            if (_debug)
            {
                Console.WriteLine($"My total calculation time was: {time} ms.");
            }
            if (_debug)
            {
                Console.WriteLine();
            }

            // Check if MoveCompletion should be used.
            if (!solution.IsComplete())
            {
                CompleteHEMove(state, solution);
            }

            return(solution);
        }