Пример #1
0
        protected async Task replaceRandomAmountParallel(ActionQueue q, QueueActionEventArgs e)
        {
            // Choosing a random value (damage amount in this case)
            // Clone and start processing for every possibility
#if _TREE_DEBUG
            DebugLog.WriteLine("");
            DebugLog.WriteLine("--> Depth: " + e.Game.Depth);
#endif
            double perItemWeight = 1.0 / ((e.Args[RandomAmount.MAX] - e.Args[RandomAmount.MIN]) + 1);
            await Task.WhenAll(
                Enumerable.Range(e.Args[RandomAmount.MIN], (e.Args[RandomAmount.MAX] - e.Args[RandomAmount.MIN]) + 1).Select(i =>
                                                                                                                             Task.Run(async() => {
                // When cloning occurs, RandomAmount has been pulled from the action queue,
                // so we can just insert a fixed number at the start of the queue and restart the queue
                // to effectively replace it
                var clonedNode = ((ProbabilisticGameNode)e.UserData).Branch(perItemWeight);
                NodeCount++;
                clonedNode.Game.ActionQueue.StackPush(i);
                await clonedNode.Game.ActionQueue.ProcessAllAsync(clonedNode);
                searcher.Visitor(clonedNode, this, e);
            })
                                                                                                                             )
                );

#if _TREE_DEBUG
            DebugLog.WriteLine("<-- Depth: " + e.Game.Depth);
            DebugLog.WriteLine("");
#endif
        }
Пример #2
0
        protected async Task replaceRandomChoiceParallel(ActionQueue q, QueueActionEventArgs e)
        {
            // Choosing a random entity (minion in this case)
            // Clone and start processing for every possibility
#if _TREE_DEBUG
            DebugLog.WriteLine("");
            DebugLog.WriteLine("--> Depth: " + e.Game.Depth);
#endif
            double perItemWeight = 1.0 / e.Args[RandomChoice.ENTITIES].Count();
            await Task.WhenAll(
                e.Args[RandomChoice.ENTITIES].Select(entity =>
                                                     Task.Run(async() => {
                // When cloning occurs, RandomChoice has been pulled from the action queue,
                // so we can just insert a fixed item at the start of the queue and restart the queue
                // to effectively replace it
                var clonedNode = ((ProbabilisticGameNode)e.UserData).Branch(perItemWeight);
                NodeCount++;
                clonedNode.Game.ActionQueue.StackPush((Entity)clonedNode.Game.Entities[entity.Id]);
                await clonedNode.Game.ActionQueue.ProcessAllAsync(clonedNode);
                searcher.Visitor(clonedNode, this, e);
            })
                                                     )
                );

#if _TREE_DEBUG
            DebugLog.WriteLine("<-- Depth: " + e.Game.Depth);
            DebugLog.WriteLine("");
#endif
        }
Пример #3
0
        protected Task replaceRandomAmount(ActionQueue q, QueueActionEventArgs e)
        {
            // Choosing a random value (damage amount in this case)
            // Clone and start processing for every possibility
#if _TREE_DEBUG
            DebugLog.WriteLine("");
            DebugLog.WriteLine("--> Depth: " + e.Game.Depth);
#endif
            double perItemWeight = 1.0 / ((e.Args[RandomAmount.MAX] - e.Args[RandomAmount.MIN]) + 1);
            for (int i = e.Args[RandomAmount.MIN]; i <= e.Args[RandomAmount.MAX]; i++)
            {
                // When cloning occurs, RandomAmount has been pulled from the action queue,
                // so we can just insert a fixed number at the start of the queue and restart the queue
                // to effectively replace it
                var clonedNode = ((ProbabilisticGameNode)e.UserData).Branch(perItemWeight);
                NodeCount++;
                clonedNode.Game.ActionQueue.StackPush(i);
                clonedNode.Game.ActionQueue.ProcessAll(clonedNode);
                searcher.Visitor(clonedNode, this, e);
            }
#if _TREE_DEBUG
            DebugLog.WriteLine("<-- Depth: " + e.Game.Depth);
            DebugLog.WriteLine("");
#endif
            return(Task.FromResult(0));
        }
Пример #4
0
        // When an in-game action completes, check if the game state has changed
        // Some actions (like selectors) won't cause the game state to change,
        // so we continue running these until a game state change occurs
        public override void PostAction(ActionQueue q, GameTree <GameNode> t, QueueActionEventArgs e)
        {
            // This game will be on the same thread as the calling task in parallel mode if it hasn't been cloned
            // If it has been cloned, it may be on a different thread
            if (e.Game.Changed)
            {
                e.Game.Changed = false;

                // If the action queue is empty, we have reached a leaf node game state
                // so compare it for equality with other final game states
                if (e.Game.ActionQueue.IsEmpty)
                {
                    t.LeafNodeCount++;
                    // This will cause the game to be discarded if its fuzzy hash matches any other final game state
                    if (!tlsUniqueGames.Value.ContainsKey(e.Game))
                    {
                        tlsUniqueGames.Value.Add(e.Game, e.UserData as ProbabilisticGameNode);
#if _TREE_DEBUG
                        DebugLog.WriteLine("UNIQUE GAME FOUND ({0}) - Hash: {1:x8}", uniqueGames.Count + tlsUniqueGames.Value.Count, e.Game.FuzzyGameHash);
                        DebugLog.WriteLine("{0:S}", e.Game);
#endif
                    }
                    else
                    {
                        tlsUniqueGames.Value[e.Game].Probability += ((ProbabilisticGameNode)e.UserData).Probability;
#if _TREE_DEBUG
                        DebugLog.WriteLine("DUPLICATE GAME FOUND - Hash: {0:x8}", e.Game.FuzzyGameHash);
#endif
                    }
                }
                else
                {
                    // The game state has changed but there are more actions to do
                    // (which may or may not involve further cloning) so add it to the search queue
#if _TREE_DEBUG
                    DebugLog.WriteLine("QUEUEING GAME " + e.Game.GameId + " FOR NEXT SEARCH");
#endif
                    if (!tlsSearchQueue.Value.ContainsKey(e.Game))
                    {
                        tlsSearchQueue.Value.Add(e.Game, e.UserData as ProbabilisticGameNode);
                    }
                    else
                    {
                        tlsSearchQueue.Value[e.Game].Probability += ((ProbabilisticGameNode)e.UserData).Probability;
                    }
                }
#if _TREE_DEBUG
                DebugLog.WriteLine("");
#endif
                e.Cancel = true;
            }
        }
Пример #5
0
        public override void Visitor(ProbabilisticGameNode cloned, GameTree <GameNode> tree, QueueActionEventArgs e)
        {
            // If the action queue is empty, we have reached a leaf node game state
            // so compare it for equality with other final game states
            if (cloned.Game.ActionQueue.IsEmpty)
            {
                if (!cloned.Game.EquivalentTo(e.Game))
                {
                    tree.LeafNodeCount++;
                    // This will cause the game to be discarded if its fuzzy hash matches any other final game state
                    // TODO: Optimize to use TLS and avoid spinlocks
                    lock (uniqueGames) {
                        if (!uniqueGames.ContainsKey(cloned.Game))
                        {
                            uniqueGames.Add(cloned.Game, cloned.Probability);
#if _TREE_DEBUG
                            DebugLog.WriteLine("UNIQUE GAME FOUND ({0}) - Hash: {1:x8}", uniqueGames.Count, cloned.Game.FuzzyGameHash);
                            DebugLog.WriteLine("{0:S}", cloned.Game);
#endif
                        }
                        else
                        {
                            uniqueGames[cloned.Game] += cloned.Probability;
#if _TREE_DEBUG
                            DebugLog.WriteLine("DUPLICATE GAME FOUND - Hash: {0:x8}", cloned.Game.FuzzyGameHash);
#endif
                        }
                    }
                }
            }
        }
Пример #6
0
 public override void Visitor(ProbabilisticGameNode cloned, GameTree <GameNode> tree, QueueActionEventArgs e)
 {
     // If the action queue is empty, we have reached a leaf node game state
     // TODO: Optimize to use TLS and avoid spinlocks
     if (cloned.Game.ActionQueue.IsEmpty)
     {
         tree.LeafNodeCount++;
         lock (leafNodeGames) {
             leafNodeGames.Add(cloned);
         }
     }
 }
Пример #7
0
 public virtual void Visitor(ProbabilisticGameNode cloned, GameTree <GameNode> tree, QueueActionEventArgs e)
 {
 }
Пример #8
0
 public virtual void PostAction(ActionQueue q, GameTree <GameNode> tree, QueueActionEventArgs e)
 {
 }