예제 #1
0
            public OddmentTable <int> Create(SearchContext <object, TicTacToeState, TicTacToeMove, object, TicTacToeMove> context, int samplesForGeneration)
            {
                var table = new Dictionary <int, double>();

                for (var i = 0; i < samplesForGeneration; i++)
                {
                    var action   = new TicTacToeMove(TicTacToeMoveGenerator.AllEmptyPositions(context.Source).RandomElementOrDefault(), context.Source.ActivePlayerID);
                    var newState = GameLogic.Apply(context, (TicTacToeState)context.Source.Copy(), action);
                    var endState = PlayoutStrategy.Playout(context, newState);
                    var value    = EvaluationStrategy.Evaluate(context, new TreeSearchNode <TicTacToeState, TicTacToeMove>(action), endState);
                    if (!table.ContainsKey(action.PositionToPlace))
                    {
                        table.Add(action.PositionToPlace, 0);
                    }
                    table[action.PositionToPlace] += value;
                }

                var maxValue = table.Values.Max();
                var minValue = table.Values.Min();

                var oddmentTable = new OddmentTable <int>();

                foreach (var kvPair in table)
                {
                    var normalisedValue = Util.Normalise(kvPair.Value, minValue, maxValue);
                    oddmentTable.Add(kvPair.Key, normalisedValue, recalculate: false);
                }
                oddmentTable.Recalculate();

                return(oddmentTable);
            }
예제 #2
0
            /// <inheritdoc />
            public OddmentTable <SabberStonePlayerTask> Create(SearchContext <List <SabberStoneAction>, SabberStoneState, SabberStoneAction, object, SabberStoneAction> context, int samplesForGeneration)
            {
                // So we have an issue here, because it's Hearthstone we don't know in advance how many dimensions we have.
                //      -> We can just evenly distribute budget over the currently available dimensions
                //      -- Reason is that some dimensions would be `locked' until after a specific dimensions is explored
                //      -> Another option is to expand all possible sequences, this might be too complex though...

                // In Hearthstone we don't really have multiple available actions per dimension
                // It's more like you either play/attack or not
                // Although each minion can have multiple choices on what to attack

                // We can still try to distillate individual actions
                // It might be best to keep track of these through a dictionary/array
                //      So we'd randomly choose actions and simulate when `end-turn' is chosen
                //      And then update the value of any selected PlayerTask

                // I guess use OddmentTable again?

                var table = new Dictionary <SabberStonePlayerTask, double>(PlayerTaskComparer.Comparer);

                // So, we have a number of samples to use
                // For each of those, generate a random SabberStoneAction and playout
                for (var i = 0; i < samplesForGeneration; i++)
                {
                    var action = PlayoutBot.CreateRandomAction(context.Source);

                    var newState = GameLogic.Apply(context, (SabberStoneState)context.Source.Copy(), action);

                    var endState = Playout.Playout(context, newState);

                    var value = Evaluation.Evaluate(context, null, endState);

                    foreach (var task in action.Tasks)
                    {
                        if (!table.ContainsKey(task))
                        {
                            table.Add(task, 0);
                        }
                        table[task] += value;
                    }
                }

                // Create the Oddment table
                var oddmentTable = new OddmentTable <SabberStonePlayerTask>();

                foreach (var kvPair in table)
                {
                    oddmentTable.Add(kvPair.Key, kvPair.Value, recalculate: false);
                }

                oddmentTable.Recalculate();

                return(oddmentTable);
            }
예제 #3
0
            public TicTacToeMove Sample(TicTacToeState state, OddmentTable <int> sideInformation)
            {
                // Get all available positions in this state
                var emptyPositions = TicTacToeMoveGenerator.AllEmptyPositions(state);

                var positionSelected = false;
                var selectedPosition = -1;

                while (!positionSelected)
                {
                    // Sample a position from the OddmentTable
                    selectedPosition = sideInformation.Next();
                    // Check if this position can be played, otherwise generate a new one
                    positionSelected = emptyPositions.Contains(selectedPosition);
                }

                return(new TicTacToeMove(selectedPosition, state.ActivePlayerID));
            }
예제 #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);
            }