コード例 #1
0
ファイル: TestGameTree.cs プロジェクト: Lat0ur/Brimstone
        private Dictionary <Game, double> _search(Game game, ITreeActionWalker searcher, TestAction testAction)
        {
            return(RandomOutcomeSearch.Find(
                       Game: game,
                       SearchMode: searcher,
                       Action: () => {
                // This is the action that shall be taken to build the tree
                switch (testAction)
                {
                case TestAction.BoomBot:
                    game.CurrentPlayer.Board.First(t => t.Card.Id == "GVG_110t").Hit(1);
                    break;

                case TestAction.ArcaneMissiles:
                    game.CurrentPlayer.Hand.First(t => t.Card.Name == "Arcane Missiles").Play();
                    break;
                }
            }
                       ));
        }
コード例 #2
0
ファイル: TestActionGraph.cs プロジェクト: mindnumb/Brimstone
        public void TestPartialArgumentSyntax()
        {
            // Arrange
            var ActionGraphs = new List <ActionGraph> {
                // The default
                Damage(RandomOpponentHealthyMinion, RandomAmount(1, 4)),
                // Swapped named arguments
                Damage(Amount: RandomAmount(1, 4), Targets: RandomOpponentHealthyMinion),
                // No arguments to Damage
                RandomOpponentHealthyMinion.Then(1).Then(4).Then(RandomAmount()).Then(Damage()),
                RandomOpponentHealthyMinion.Then(RandomAmount(1, 4)).Then(Damage()),
                // No Targets argument to Damage
                RandomOpponentHealthyMinion.Then(Damage(Amount: RandomAmount(1, 4))),
                RandomOpponentHealthyMinion.Then(Damage(Amount: ((ActionGraph)1).Then(4).Then(RandomAmount()))),
                // No Amount argument to damage
                RandomAmount(1, 4).Then(Damage(Targets: RandomOpponentHealthyMinion)),
                ((ActionGraph)1).Then(4).Then(RandomAmount()).Then(Damage(Targets: RandomOpponentHealthyMinion))
            };

            Cards.FromName("Arcane Missiles").Behaviour.Battlecry = Damage(RandomOpponentHealthyCharacter, 1) * 1;

            foreach (var graph in ActionGraphs)
            {
                // Arrange
                var game = _setupGame(7, 2, "Bloodfen Raptor");

                // This converts the ActionGraph to a List<QueueAction>
                Cards.FromId("GVG_110t").Behaviour.Deathrattle = graph;

                // Act
                var count = RandomOutcomeSearch.Find(game, () => game.CurrentPlayer.Hand.First(t => t.Card.Name == "Arcane Missiles").Play()).Count;

                // Assert
                // 1 missile produces 30 game states if Boom Bot deathrattle works correctly
                Assert.AreEqual(30, count);
            }
        }
コード例 #3
0
ファイル: TestGameTree.cs プロジェクト: Lat0ur/Brimstone
        public void TestTreeUsage([Values(true, false)] bool ParallelClone)
        {
            Settings.ParallelClone = ParallelClone;

            var game = _setupGame(7, 2, "Bloodfen Raptor");

            game.MaxMinionsOnBoard = 10;

            // Make a new tree with the game as the root
            var tree = new GameTree <ProbabilisticGameNode>(new ProbabilisticGameNode(game));

            // Add arbitrary number of children
            int children = 3;

            var depth1Nodes = tree.RootNode.Branch(children).ToList();

            // Check the correct number of games were cloned
            Assert.AreEqual(children, depth1Nodes.Count);
            Assert.AreEqual(children, tree.RootNode.Children.Count);

            // Assert all children have correct parent in both GameNode and Game
            foreach (var n in depth1Nodes)
            {
                Assert.AreSame(game, n.Parent.Game);
                Assert.AreSame(tree.RootNode, n.Parent);
            }

            // Check all child games are unique but exact clones
            var childGameIds = new List <int>();

            foreach (var n in depth1Nodes)
            {
                Assert.False(childGameIds.Contains(n.Game.GameId));
                Assert.True(game.EquivalentTo(n.Game));
                childGameIds.Add(n.Game.GameId);
            }

            // Get all games from nodes
            var depth1Games = depth1Nodes.Select(n => n.Game).ToList();

            // Do something different on each child
            depth1Games[0].CurrentPlayer.Give("Flame Juggler").Play();
            depth1Games[1].CurrentPlayer.Give("Arcane Missiles").Play();
            depth1Games[2].CurrentPlayer.Give("Whirlwind").Play();

            // Check every game is different
            var childHashes = new List <int>();

            foreach (var g in depth1Games)
            {
                Assert.False(childHashes.Contains(g.FuzzyGameHash));
                childHashes.Add(g.FuzzyGameHash);
            }

            // Do a random action on the first game in depth 1 and add all possible outcomes as children
            Minion FirstBoomBot   = depth1Games[0].CurrentPlayer.Board.First(x => x.Card.Id == "GVG_110t");
            var    boomBotResults = RandomOutcomeSearch.Find(depth1Games[0], () => FirstBoomBot.Hit(1));

            var depth2Nodes = depth1Nodes[0].AddChildren(boomBotResults).ToList();

            // Check the correct number of games were cloned
            Assert.AreEqual(boomBotResults.Count, depth2Nodes.Count);
            Assert.AreEqual(boomBotResults.Count, depth1Nodes[0].Children.Count);

            // Assert all children have correct parent in both GameNode and Game
            foreach (var n in depth2Nodes)
            {
                Assert.AreSame(depth1Games[0], n.Parent.Game);
                Assert.AreSame(depth1Nodes[0], n.Parent);
            }
        }
コード例 #4
0
ファイル: Program.cs プロジェクト: mindnumb/Brimstone
        static async Task DepthFirstAsync()
        {
            // Create initial game state
            Console.WriteLine("Initializing game state...");

            var game = new Game(HeroClass.Druid, HeroClass.Druid, PowerHistory: true);

            game.Start(FirstPlayer: 1, SkipMulligan: true);

            for (int i = 0; i < MaxMinions - NumBoomBots; i++)
            {
                game.CurrentPlayer.Give(FillMinion).Play();
            }
            for (int i = 0; i < NumBoomBots; i++)
            {
                game.CurrentPlayer.Give("GVG_110t").Play();
            }
            game.EndTurn();
            for (int i = 0; i < MaxMinions - NumBoomBots; i++)
            {
                game.CurrentPlayer.Give(FillMinion).Play();
            }
            for (int i = 0; i < NumBoomBots; i++)
            {
                game.CurrentPlayer.Give("GVG_110t").Play();
            }

            var ArcaneMissiles = game.CurrentPlayer.Give("Arcane Missiles");

            Cards.FromName("Arcane Missiles").Behaviour.Battlecry = Damage(RandomOpponentHealthyCharacter, 1) * 2;
            Cards.FromId("GVG_110t").Behaviour.Deathrattle        = Damage(RandomOpponentHealthyMinion, RandomAmount(1, 4));

            // Start timing
            var sw = new Stopwatch();

            sw.Start();

            // Start the search going on another thread and retrieve its task handle
            var treeTask = RandomOutcomeSearch.BuildAsync(
                Game: game,
                SearchMode: new DepthFirstActionWalker(),
                Action: () => {
                if (BoomBotTest)
                {
                    var BoomBot = game.CurrentPlayer.Board.First(t => t.Card.Id == "GVG_110t");
                    BoomBot.Hit(1);
                }

                if (ArcaneMissilesTest)
                {
                    ArcaneMissiles.Play();
                }
            }
                );

            // Now we can do other stuff until our tree search results are ready!
            while (!treeTask.IsCompleted)
            {
                Console.Write(".");
                await Task.Delay(100);
            }

            // Get the results
            var tree = treeTask.Result;

            Console.WriteLine("");

            // Print benchmark results
            Console.WriteLine("{0} branches in {1}ms", tree.NodeCount, sw.ElapsedMilliseconds);
            Console.WriteLine("{0} intermediate clones pruned ({1} unique branches kept)", tree.NodeCount - tree.LeafNodeCount, tree.LeafNodeCount);

            var uniqueGames = tree.GetUniqueGames();

            sw.Stop();

            foreach (var kv in uniqueGames)
            {
                Console.WriteLine(Math.Round(kv.Value * 100, 2) + "%: ");
                Console.WriteLine("{0:s}", kv.Key);
            }
            Console.WriteLine("{0} unique games found in {1}ms", uniqueGames.Count, sw.ElapsedMilliseconds);
        }
コード例 #5
0
        static void Main(string[] args)
        {
            for (int missiles = 1; missiles <= 6; missiles++)
            {
                // Create initial game state
                Console.WriteLine("Initializing game state for {0} missiles test...", missiles);

                var game = new Game(HeroClass.Druid, HeroClass.Druid, PowerHistory: true);
                game.Start(FirstPlayer: 1, SkipMulligan: true);

                for (int i = 0; i < MaxMinions - NumBoomBots; i++)
                {
                    game.CurrentPlayer.Give(FillMinion).Play();
                }
                for (int i = 0; i < NumBoomBots; i++)
                {
                    game.CurrentPlayer.Give("GVG_110t").Play();
                }
                game.EndTurn();
                for (int i = 0; i < MaxMinions - NumBoomBots; i++)
                {
                    game.CurrentPlayer.Give(FillMinion).Play();
                }
                for (int i = 0; i < NumBoomBots; i++)
                {
                    game.CurrentPlayer.Give("GVG_110t").Play();
                }

                var ArcaneMissiles = game.CurrentPlayer.Give("Arcane Missiles");

                Cards.FromName("Arcane Missiles").Behaviour.Battlecry = Damage(RandomOpponentHealthyCharacter, 1) * missiles;
                Cards.FromId("GVG_110t").Behaviour.Deathrattle        = Damage(RandomOpponentHealthyMinion, RandomAmount(1, 4));

                // Start timing
                var sw = new Stopwatch();
                sw.Start();

                // Create first layer of nodes underneath the root node
                // and add them to the search queue, then do breadth-first search
                var tree = RandomOutcomeSearch.Build(
                    Game: game,
                    SearchMode: new BreadthFirstActionWalker(),
                    Action: () =>
                {
                    if (BoomBotTest)
                    {
                        var BoomBot = game.CurrentPlayer.Board.First(t => t.Card.Id == "GVG_110t");
                        BoomBot.Hit(1);
                    }

                    if (ArcaneMissilesTest)
                    {
                        ArcaneMissiles.Play();
                    }
                }
                    );

                // Print benchmark results
                Console.WriteLine("{0} branches in {1}ms", tree.NodeCount, sw.ElapsedMilliseconds);
                Console.WriteLine("{0} intermediate clones pruned ({1} unique branches kept)", tree.NodeCount - tree.LeafNodeCount,
                                  tree.LeafNodeCount);

                var uniqueGames = tree.GetUniqueGames();
                sw.Stop();

                Console.WriteLine("{0} unique games found in {1}ms", uniqueGames.Count, sw.ElapsedMilliseconds);
                Console.WriteLine("");
            }
        }
コード例 #6
0
        static void Main(string[] args)
        {
            // Create initial game state
            Console.WriteLine("Initializing game state...");

            var game = new Game(HeroClass.Druid, HeroClass.Druid, PowerHistory: true);

            game.Player1.Deck.Fill();
            game.Player2.Deck.Fill();
            game.Start(FirstPlayer: 1, SkipMulligan: true);

            for (int i = 0; i < MaxMinions - NumBoomBots; i++)
            {
                game.CurrentPlayer.Give(FillMinion).Play();
            }
            for (int i = 0; i < NumBoomBots; i++)
            {
                game.CurrentPlayer.Give("GVG_110t").Play();
            }
            game.EndTurn();
            for (int i = 0; i < MaxMinions - NumBoomBots; i++)
            {
                game.CurrentPlayer.Give(FillMinion).Play();
            }
            for (int i = 0; i < NumBoomBots; i++)
            {
                game.CurrentPlayer.Give("GVG_110t").Play();
            }

            Cards.FromName("Arcane Missiles").Behaviour.Battlecry = Damage(RandomOpponentHealthyCharacter, 1) * 2;
            Cards.FromId("GVG_110t").Behaviour.Deathrattle        = Damage(RandomOpponentHealthyMinion, RandomAmount(1, 4));

            // Start timing
            var sw = new Stopwatch();

            sw.Start();

            // Build search tree
            Console.WriteLine("Building search tree...");

            var tree = RandomOutcomeSearch.Build(
                Game: game,
                SearchMode: new NaiveActionWalker(),
                Action: () => {
                if (BoomBotTest)
                {
                    var BoomBot = game.CurrentPlayer.Board.First(t => t.Card.Id == "GVG_110t");
                    BoomBot.Hit(1);
                }

                if (ArcaneMissilesTest)
                {
                    game.CurrentPlayer.Give("Arcane Missiles").Play();
                }
            }
                );

            // Print intermediate results
            Console.WriteLine("{0} branches in {1}ms", tree.NodeCount, sw.ElapsedMilliseconds);
            Console.WriteLine("{0} leaf node games kept", tree.LeafNodeCount);
            Console.WriteLine("");

            // Find unique games
            Console.WriteLine("Finding unique game states...");

            var uniqueGames = tree.GetUniqueGames();

            sw.Stop();

            foreach (var kv in uniqueGames)
            {
                Console.WriteLine(Math.Round(kv.Value * 100, 2) + "%: ");
                Console.WriteLine("{0:s}", kv.Key);
            }
            Console.WriteLine("{0} unique games found in {1}ms", uniqueGames.Count, sw.ElapsedMilliseconds);
        }