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(""); } }
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); }
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); }