Exemple #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);
            }
Exemple #2
0
        /// <summary>
        /// Selects the best half of a collection of actions by evaluating them based on the provided search context.
        /// </summary>
        /// <param name="context">The current search context.</param>
        /// <param name="actions">The collection of actions to filter.</param>
        /// <param name="samplesPerAction">How many samples to run per action.</param>
        /// <returns>Collection of actions which Count is half of the original collection, rounded up. This collection is ordered by descending value.</returns>
        private List <ActionValue> SelectBestHalf(SearchContext <D, P, A, S, A> context, IReadOnlyCollection <ActionValue> actions, int samplesPerAction)
        {
            var clone = context.Cloner;

            // Evaluate each action by running a playout for it.
            foreach (var item in actions)
            {
                var tempNode = new N {
                    Payload = item.Action
                };
                var newState = GameLogic.Apply(context, clone.Clone(context.Source), item.Action);

                double value = 0;
                for (var i = 0; i < samplesPerAction; i++)
                {
                    try {
                        var endState = Playout.Playout(context, clone.Clone(newState));
                        value += Evaluation.Evaluate(context, tempNode, endState);
                        SamplesUsedEvaluation++;
                    }
                    catch (Exception e) {
                        //Console.WriteLine($"ERROR: {e.GetType()} while cloning state.");
                        // TODO fix
                        // Cloning here seems to very seldom cause a NullReference in the SabberStone dll
                        // I believe failing and just using 0 as a value here is acceptable
                    }
                }

                item.Value = value;
            }

            // Return the half with the highest value.
            var half = (int)Math.Max(1, Math.Ceiling(actions.Count / 2.0));

            return(actions.OrderByDescending(i => i.Value).Take(half).ToList());
        }