Example #1
0
        public void TestKaboomBotTriggeringDeathrattle()
        {
            List <BattlegroundCard> playerCards   = new List <BattlegroundCard>();
            List <BattlegroundCard> opponentCards = new List <BattlegroundCard>();
            // Kaboom bot is a 2/2 that damages a random opponent card by 4.
            BattlegroundCard kaboomBotCard = Utils.CreateBattlegroundCard(Utils.GetCardFromName("Kaboom Bot"));

            kaboomBotCard.hasTaunt = true;
            playerCards.Add(kaboomBotCard);
            playerCards.Add(new BattlegroundCard(2, 4));

            // Selfless  hero is a 2/1 that grants divine shield.
            BattlegroundCard selflessHeroCard = Utils.CreateBattlegroundCard(Utils.GetCardFromName("Selfless Hero"));

            opponentCards.Add(new BattlegroundCard(2, 2));
            opponentCards.Add(selflessHeroCard);
            opponentCards.Add(new BattlegroundCard(2, 1));

            // There is a chance for the kaboom bot proc to hit the selfless hero, triggering another deathrattle from its own deathrattle.
            BattlegroundBoard      board      = new BattlegroundBoard(playerCards, opponentCards);
            BattlegroundSimulation simulation = new BattlegroundSimulation(board);

            // Win: 2/2 hits kaboom bot. Kaboom bot hits 2/1. Selfless hero procs on nothing. 2/4 Remains alive.
            Assert.AreEqual(1, simulation.simulationStats.totalWon);
            // Draw: 2/2 hits kaboom bot. Deathrattle hits selfless hero. Sefless hero triggers divine shield on 2/1. 2/1 ties with 2/4.
            Assert.AreEqual(1, simulation.simulationStats.totalDrawn);
            Assert.AreEqual(0, simulation.simulationStats.totalLost);
        }
 /**
  * Removes a card from the playerCards list.
  *
  * This should be called when a card is dead rather than removing directly from the list.
  */
 public void RemovePlayerCard(BattlegroundCard card)
 {
     if (playerCards.Remove(card))
     {
         deadPlayerCards.Add(card);
     }
 }
 /**
  * Removes a card from the opponentCards list.
  *
  * This should be called when a card is dead rather than removing directly from the list.
  */
 public void RemoveOpponentCard(BattlegroundCard card)
 {
     if (opponentCards.Remove(card))
     {
         deadOpponentCards.Add(card);
     }
 }
 /** Maybe adds a card to the list of cards. Enforces space limitations of Battlegrounds. */
 private static void MaybeAddCard(List <BattlegroundCard> cards, BattlegroundCard card, int cardIndex)
 {
     // Make sure the cardIndex is still within bounds after cards were removed.
     cardIndex = Math.Min(cards.Count, cardIndex);
     if (cards.Count < BattlegroundBoard.MaxBoardSize)
     {
         cards.Insert(cardIndex, card);
     }
 }
        /** Returns a clone of the cards list. */
        private List <BattlegroundCard> CloneBattlegroundCards(List <BattlegroundCard> cards)
        {
            List <BattlegroundCard> cardsClone = new List <BattlegroundCard>();

            foreach (BattlegroundCard card in cards)
            {
                cardsClone.Add(BattlegroundCard.CloneBattlegroundCard(card));
            }
            return(cardsClone);
        }
Example #6
0
        public void TestPilotedShredderCard()
        {
            List <BattlegroundCard> playerCards   = new List <BattlegroundCard>();
            List <BattlegroundCard> opponentCards = new List <BattlegroundCard>();
            // Piloted Shredder is a complicated case since it spawns so many deathrattle outcomes. For sanity, we derive case where we
            // expect to ALWAYS lose unless it spawns a kindly grandmother. In this case, it can do a max of 8 damage.
            BattlegroundCard pilotedShredderCard = Utils.CreateBattlegroundCard(Utils.GetCardFromName("Piloted Shredder"));

            playerCards.Add(pilotedShredderCard);

            opponentCards.Add(new BattlegroundCard(9, 8, false, false, false, false, Race.INVALID, ""));
            BattlegroundBoard      board      = new BattlegroundBoard(playerCards, opponentCards);
            BattlegroundSimulation simulation = new BattlegroundSimulation(board);

            Assert.AreEqual(0, simulation.simulationStats.totalWon);
            Assert.AreEqual(2, simulation.simulationStats.totalDrawn);
            Assert.AreEqual(18, simulation.simulationStats.totalLost);
        }
Example #7
0
        public void TestKaboomBot()
        {
            List <BattlegroundCard> playerCards   = new List <BattlegroundCard>();
            List <BattlegroundCard> opponentCards = new List <BattlegroundCard>();
            // Kaboom bot is a 2/2 that damages a random opponent card by 4.
            BattlegroundCard kaboomBotCard = Utils.CreateBattlegroundCard(Utils.GetCardFromName("Kaboom Bot"));

            playerCards.Add(kaboomBotCard);

            opponentCards.Add(new BattlegroundCard(1, 5));
            opponentCards.Add(new BattlegroundCard(2, 2));

            BattlegroundBoard      board      = new BattlegroundBoard(playerCards, opponentCards);
            BattlegroundSimulation simulation = new BattlegroundSimulation(board);

            Assert.AreEqual(0, simulation.simulationStats.totalWon);
            Assert.AreEqual(1, simulation.simulationStats.totalDrawn);
            Assert.AreEqual(2, simulation.simulationStats.totalLost);
        }
Example #8
0
        public void TestTheBeastCard()
        {
            List <BattlegroundCard> playerCards   = new List <BattlegroundCard>();
            List <BattlegroundCard> opponentCards = new List <BattlegroundCard>();
            // The beast is a 9/7 that summons a 3/3 Finkle Einhorn for the opponent on its deathrattle.
            BattlegroundCard theBeastCard = Utils.CreateBattlegroundCard(Utils.GetCardFromName("The Beast"));

            // The following configuration should always result in a draw.
            playerCards.Add(theBeastCard);
            playerCards.Add(new BattlegroundCard(3, 3));

            opponentCards.Add(new BattlegroundCard(9, 7, true, false, false, false, Race.INVALID, ""));
            BattlegroundBoard      board      = new BattlegroundBoard(playerCards, opponentCards);
            BattlegroundSimulation simulation = new BattlegroundSimulation(board);

            Assert.AreEqual(0, simulation.simulationStats.totalWon);
            // Player goes first due to priority, only one possible outcome.
            Assert.AreEqual(1, simulation.simulationStats.totalDrawn);
            Assert.AreEqual(0, simulation.simulationStats.totalLost);
        }
Example #9
0
        public void TestSneedsCard()
        {
            // Sneeds is a very complicated card to test. We give it a case where it loses always
            // unless a Foe Reaper is spawned.
            List <BattlegroundCard> playerCards       = new List <BattlegroundCard>();
            List <BattlegroundCard> opponentCards     = new List <BattlegroundCard>();
            BattlegroundCard        sneedsOldShredder = Utils.CreateBattlegroundCard(Utils.GetCardFromName("Sneed's Old Shredder"));

            playerCards.Add(sneedsOldShredder);

            opponentCards.Add(new BattlegroundCard(8, 6));
            opponentCards.Add(new BattlegroundCard(8, 6));

            BattlegroundBoard      board      = new BattlegroundBoard(playerCards, opponentCards);
            BattlegroundSimulation simulation = new BattlegroundSimulation(board);

            // There are two win scenarios. Both are when sneed's spawns a foe reaper.
            Assert.AreEqual(2, simulation.simulationStats.totalWon);
            Assert.AreEqual(0, simulation.simulationStats.totalDrawn);
            Assert.AreEqual(22, simulation.simulationStats.totalLost);
        }
Example #10
0
        public void TestRatPack()
        {
            List <BattlegroundCard> playerCards   = new List <BattlegroundCard>();
            List <BattlegroundCard> opponentCards = new List <BattlegroundCard>();
            BattlegroundCard        ratPackCard   = Utils.CreateBattlegroundCard(Utils.GetCardFromName("Rat Pack"));

            ratPackCard.attack = 3;
            ratPackCard.health = 1;
            playerCards.Add(ratPackCard);

            for (int i = 0; i < 4; i++)
            {
                opponentCards.Add(new BattlegroundCard(1, 1));
            }

            BattlegroundBoard      board      = new BattlegroundBoard(playerCards, opponentCards);
            BattlegroundSimulation simulation = new BattlegroundSimulation(board);

            Assert.AreEqual(0, simulation.simulationStats.totalWon);
            Assert.AreEqual(6, simulation.simulationStats.totalDrawn);
            Assert.AreEqual(0, simulation.simulationStats.totalLost);
        }
Example #11
0
        public void TestNadinaCard()
        {
            List <BattlegroundCard> playerCards   = new List <BattlegroundCard>();
            List <BattlegroundCard> opponentCards = new List <BattlegroundCard>();
            // Nadina is a 7/4 granting divine shield to all dragons on deathrattle.
            BattlegroundCard nadinaCard = Utils.CreateBattlegroundCard(Utils.GetCardFromName("Nadina the Red"));

            playerCards.Add(nadinaCard);
            playerCards.Add(new BattlegroundCard(1, 1, false, false, false, false, Race.DRAGON, ""));
            playerCards.Add(new BattlegroundCard(1, 1, false, false, false, false, Race.DRAGON, ""));

            opponentCards.Add(new BattlegroundCard(4, 7, true, false, false, false, Race.INVALID, ""));
            opponentCards.Add(new BattlegroundCard(4, 4));

            // The following should always result in a draw.
            BattlegroundBoard      board      = new BattlegroundBoard(playerCards, opponentCards);
            BattlegroundSimulation simulation = new BattlegroundSimulation(board);

            Assert.AreEqual(0, simulation.simulationStats.totalWon);
            Assert.AreEqual(3, simulation.simulationStats.totalDrawn);
            Assert.AreEqual(0, simulation.simulationStats.totalLost);
        }
Example #12
0
        public void TestKangors()
        {
            // Kangors is a 3/6 that summons the first two mechs that died in combat.
            List <BattlegroundCard> playerCards   = new List <BattlegroundCard>();
            List <BattlegroundCard> opponentCards = new List <BattlegroundCard>();
            BattlegroundCard        kangorsCard   = Utils.CreateBattlegroundCard(Utils.GetCardFromName("Kangor's Apprentice"));

            for (int i = 0; i < 3; i++)
            {
                playerCards.Add(new BattlegroundCard(1, 1, true, false, false, false, Race.MECHANICAL, "Micro Machine"));
            }
            playerCards.Add(kangorsCard);

            opponentCards.Add(new BattlegroundCard(10, 8));
            // We expect to always draw with this configuration.
            BattlegroundBoard      board      = new BattlegroundBoard(playerCards, opponentCards);
            BattlegroundSimulation simulation = new BattlegroundSimulation(board);

            Assert.AreEqual(0, simulation.simulationStats.totalWon);
            Assert.AreEqual(2, simulation.simulationStats.totalDrawn);
            Assert.AreEqual(0, simulation.simulationStats.totalLost);
        }
Example #13
0
        public void TestUnstableGhoul()
        {
            List <BattlegroundCard> playerCards       = new List <BattlegroundCard>();
            List <BattlegroundCard> opponentCards     = new List <BattlegroundCard>();
            BattlegroundCard        unstableGhoulCard = Utils.CreateBattlegroundCard(Utils.GetCardFromName("Unstable Ghoul"));

            playerCards.Add(unstableGhoulCard);
            playerCards.Add(new BattlegroundCard(2, 1));

            for (int i = 0; i < 7; i++)
            {
                opponentCards.Add(new BattlegroundCard(3, 1));
            }

            // Should always result in a draw.
            BattlegroundBoard      board      = new BattlegroundBoard(playerCards, opponentCards);
            BattlegroundSimulation simulation = new BattlegroundSimulation(board);

            Assert.AreEqual(0, simulation.simulationStats.totalWon);
            Assert.AreEqual(1, simulation.simulationStats.totalDrawn);
            Assert.AreEqual(0, simulation.simulationStats.totalLost);
        }
Example #14
0
        public void TestSpawnOfNzothCard()
        {
            List <BattlegroundCard> playerCards   = new List <BattlegroundCard>();
            List <BattlegroundCard> opponentCards = new List <BattlegroundCard>();
            // Spawn is a 2/2.
            BattlegroundCard spawnOfNzothCard = Utils.CreateBattlegroundCard(Utils.GetCardFromName("Spawn Of N'zoth"));

            spawnOfNzothCard.hasTaunt = true;
            playerCards.Add(spawnOfNzothCard);
            playerCards.Add(new BattlegroundCard(1, 1));
            playerCards.Add(new BattlegroundCard(1, 1));

            opponentCards.Add(new BattlegroundCard(2, 2));
            opponentCards.Add(new BattlegroundCard(2, 2));
            opponentCards.Add(new BattlegroundCard(2, 2));

            BattlegroundBoard      board      = new BattlegroundBoard(playerCards, opponentCards);
            BattlegroundSimulation simulation = new BattlegroundSimulation(board);

            Assert.AreEqual(0, simulation.simulationStats.totalWon);
            Assert.AreEqual(8, simulation.simulationStats.totalDrawn);
            Assert.AreEqual(0, simulation.simulationStats.totalLost);
        }
Example #15
0
        public void TestSelflessHeroCard()
        {
            List <BattlegroundCard> playerCards   = new List <BattlegroundCard>();
            List <BattlegroundCard> opponentCards = new List <BattlegroundCard>();
            // Selfless hero is a 2/1. The following configuration should result in a win only if the 3/1 is divine shielded
            // on the selfless hero's deathrattle.
            BattlegroundCard selflessHeroCard = Utils.CreateBattlegroundCard(Utils.GetCardFromName("Selfless Hero"));

            playerCards.Add(selflessHeroCard);
            playerCards.Add(new BattlegroundCard(3, 1));
            playerCards.Add(new BattlegroundCard(1, 1));
            opponentCards.Add(new BattlegroundCard(1, 8, false, false, false, false, Race.INVALID, ""));
            BattlegroundBoard      board      = new BattlegroundBoard(playerCards, opponentCards);
            BattlegroundSimulation simulation = new BattlegroundSimulation(board);

            // win:
            // 2/1 -> 1/8 (divine shield 3/1); 1/8 -> 3/1; 3/1 -> 1/8. Win with 1/1 leftover.
            Assert.AreEqual(1, simulation.simulationStats.totalWon);
            // draw:
            // 2/1 -> 1/8 (divine shield 3/1); 1/8 -> 1/1; 3/1 -> 1/8; 1/8 -> 3/1.
            Assert.AreEqual(1, simulation.simulationStats.totalDrawn);
            Assert.AreEqual(2, simulation.simulationStats.totalLost);
        }
Example #16
0
        public void TestFiendishServantCard()
        {
            List <BattlegroundCard> playerCards         = new List <BattlegroundCard>();
            List <BattlegroundCard> opponentCards       = new List <BattlegroundCard>();
            BattlegroundCard        fiendishServantCard = Utils.CreateBattlegroundCard(Utils.GetCardFromName("Fiendish Servant"));

            playerCards.Add(fiendishServantCard);
            fiendishServantCard.attack = 5;
            fiendishServantCard.health = 1;
            playerCards.Add(new BattlegroundCard(1, 2));
            playerCards.Add(new BattlegroundCard(1, 1));

            opponentCards.Add(new BattlegroundCard(1, 17, true, false, false, false, Race.INVALID, ""));
            // Win: Fiendish buffs 1/2. The new 6/1 hits 1/17. 1/17 hits 6/1.
            // Draw: Fiendish buffs 1/2. The new 6/1 hits 1/17. 1/17 hits 1/1. 6/1 hits 1/17.
            // Loss: All other cases.
            BattlegroundBoard      board      = new BattlegroundBoard(playerCards, opponentCards);
            BattlegroundSimulation simulation = new BattlegroundSimulation(board);

            Assert.AreEqual(1, simulation.simulationStats.totalWon);
            Assert.AreEqual(1, simulation.simulationStats.totalDrawn);
            Assert.AreEqual(2, simulation.simulationStats.totalLost);
        }
Example #17
0
        public void TestGoldrinnCard()
        {
            List <BattlegroundCard> playerCards   = new List <BattlegroundCard>();
            List <BattlegroundCard> opponentCards = new List <BattlegroundCard>();
            // Goldrinn is a 4/4 granting +4/+4 to beasts.
            BattlegroundCard goldrinnCard = Utils.CreateBattlegroundCard(Utils.GetCardFromName("Goldrinn, the Great Wolf"));

            playerCards.Add(goldrinnCard);
            playerCards.Add(new BattlegroundCard(1, 1, false, false, false, false, Race.BEAST, ""));
            playerCards.Add(new BattlegroundCard(1, 1));

            opponentCards.Add(new BattlegroundCard(5, 9));

            // This will always result in either a win or a draw.
            BattlegroundBoard      board      = new BattlegroundBoard(playerCards, opponentCards);
            BattlegroundSimulation simulation = new BattlegroundSimulation(board);

            // Win: Goldrinn dies, grants +4/+4 to the beast. The 5/5 beast attacks the 5/9, killing it.
            Assert.AreEqual(1, simulation.simulationStats.totalWon);
            // Draw: Goldrinn dies, then the 1/1 attacks the 5/9. The 5/5 then attacks the 5/9.
            Assert.AreEqual(1, simulation.simulationStats.totalDrawn);
            Assert.AreEqual(0, simulation.simulationStats.totalLost);
        }
Example #18
0
        public void TestKingBagurgleCard()
        {
            List <BattlegroundCard> playerCards   = new List <BattlegroundCard>();
            List <BattlegroundCard> opponentCards = new List <BattlegroundCard>();
            // King Bagurgle is a 6/3 that grants +2/+2 on deathrattle to murlocs.
            BattlegroundCard kingBagurgleCard = Utils.CreateBattlegroundCard(Utils.GetCardFromName("King Bagurgle"));

            playerCards.Add(kingBagurgleCard);
            playerCards.Add(new BattlegroundCard(1, 1, false, false, false, false, Race.MURLOC, ""));
            playerCards.Add(new BattlegroundCard(1, 1));

            opponentCards.Add(new BattlegroundCard(3, 9));

            // This will always result in either a win or a draw.
            BattlegroundBoard      board      = new BattlegroundBoard(playerCards, opponentCards);
            BattlegroundSimulation simulation = new BattlegroundSimulation(board);

            // Win: Bagurgle dies, grants +2/+2 to the murloc making it a 3/3. The 3/9 then attacks the 3/3.
            Assert.AreEqual(1, simulation.simulationStats.totalWon);
            // Draw: Bagurgle dies, grants +2/+2 to the murloc making it a 3/3. The 3/9 then attacks the 1/1. The 3/3 then attacks the 3/9.
            Assert.AreEqual(1, simulation.simulationStats.totalDrawn);
            Assert.AreEqual(0, simulation.simulationStats.totalLost);
        }
        private SimulationStats SimulationHelper(BattlegroundBoard originalBoard)
        {
            // Base-case. Draw, win, or loss.
            if (originalBoard.IsDraw())
            {
                return(new SimulationStats(0, 0, 1));
            }
            if (originalBoard.IsWin())
            {
                return(new SimulationStats(1, 0, 0));
            }
            if (originalBoard.IsLoss())
            {
                return(new SimulationStats(0, 1, 0));
            }

            // Go through every possible iteration.
            List <BattlegroundCard> opponentCards = originalBoard.playerTurn ? originalBoard.opponentCards : originalBoard.playerCards;
            int playerIndex = originalBoard.playerTurn ? originalBoard.playerIndex : originalBoard.opponentIndex;

            SimulationStats simulationStats = new SimulationStats(0, 0, 0);

            // Look for attackable opponent cards.
            List <int> opponentCardIndices = new List <int>();
            List <int> tauntedIndices      = new List <int>();

            for (int i = 0; i < opponentCards.Count; i++)
            {
                if (opponentCards[i].hasTaunt)
                {
                    tauntedIndices.Add(i);
                }
                opponentCardIndices.Add(i);
            }
            if (tauntedIndices.Count > 0)
            {
                opponentCardIndices = tauntedIndices;
            }
            foreach (int index in opponentCardIndices)
            {
                BattlegroundBoard boardClone = new BattlegroundBoard(originalBoard);

                // Update playerCards and opponentCards with our new cloned board.
                List <BattlegroundCard> playerCards = boardClone.playerTurn ? boardClone.playerCards : boardClone.opponentCards;
                opponentCards = boardClone.playerTurn ? boardClone.opponentCards : boardClone.playerCards;

                BattlegroundCard playerCard = playerCards[playerIndex];

                List <int> attackableOpponentIndices            = new List <int>();
                List <BattlegroundCard> attackableOpponentCards = new List <BattlegroundCard>();
                if (playerCard.hasCleave)
                {
                    if (index > 0)
                    {
                        attackableOpponentIndices.Add(index - 1);
                        attackableOpponentCards.Add(opponentCards[index - 1]);
                    }
                    attackableOpponentIndices.Add(index);
                    attackableOpponentCards.Add(opponentCards[index]);
                    if (index < opponentCardIndices.Count - 1)
                    {
                        attackableOpponentIndices.Add(index + 1);
                        attackableOpponentCards.Add(opponentCards[index + 1]);
                    }
                }
                else
                {
                    attackableOpponentIndices.Add(index);
                    attackableOpponentCards.Add(opponentCards[index]);
                }

                List <Deathrattle> deathrattles = new List <Deathrattle>();
                if (playerCard.hasDivineShield)
                {
                    playerCard.hasDivineShield = false;
                }
                else
                {
                    if (opponentCards[index].hasPoison)
                    {
                        playerCard.health = 0;
                    }
                    else
                    {
                        playerCard.health -= opponentCards[index].attack;
                    }
                    if (playerCard.health <= 0 && playerCard is DeathrattleBattlegroundCard)
                    {
                        // Note that the "playerCard" is actually the opponent when isPlayerTurn is false.
                        // TODO: Rename playerCard and opponentCard in this instance.
                        deathrattles.Add(new Deathrattle((DeathrattleBattlegroundCard)playerCard, boardClone, boardClone.playerTurn, playerIndex));
                    }
                }
                foreach (int opponentIndex in attackableOpponentIndices)
                {
                    BattlegroundCard opponentCard = opponentCards[opponentIndex];
                    if (opponentCard.hasDivineShield)
                    {
                        opponentCard.hasDivineShield = false;
                    }
                    else
                    {
                        if (playerCard.hasPoison)
                        {
                            opponentCard.health = 0;
                        }
                        else
                        {
                            opponentCard.health -= playerCard.attack;
                        }
                        if (opponentCard.health <= 0 && opponentCard is DeathrattleBattlegroundCard)
                        {
                            deathrattles.Add(new Deathrattle((DeathrattleBattlegroundCard)opponentCard, boardClone, !boardClone.playerTurn, opponentIndex));
                        }
                    }
                }
                if (playerCard.health <= 0)
                {
                    if (boardClone.playerTurn)
                    {
                        boardClone.RemovePlayerCard(playerCard);
                    }
                    else
                    {
                        boardClone.RemoveOpponentCard(playerCard);
                    }
                }
                foreach (BattlegroundCard opponentCard in attackableOpponentCards)
                {
                    if (opponentCard.health <= 0)
                    {
                        if (boardClone.playerTurn)
                        {
                            boardClone.RemoveOpponentCard(opponentCard);
                        }
                        else
                        {
                            boardClone.RemovePlayerCard(opponentCard);
                        }
                    }
                }
                List <BattlegroundBoard> boards = new List <BattlegroundBoard>();
                while (deathrattles.Count > 0)
                {
                    foreach (Deathrattle deathrattle in deathrattles)
                    {
                        List <BattlegroundBoard> deathrattleBoards = deathrattle.ApplyDeathrattle();
                        if (deathrattleBoards != null)
                        {
                            foreach (BattlegroundBoard deathrattleBoard in deathrattleBoards)
                            {
                                boards.Add(deathrattleBoard);
                            }
                        }
                    }
                    deathrattles.Clear();
                    // Deathrattles could trigger other deathrattles (e.g. Kaboom Bot killing another card). We must now look for dead cards and reapply deathrattles.
                    // TODO: Modulate this logic with the logic from above.
                    List <BattlegroundBoard> boardsToRemove = new List <BattlegroundBoard>();

                    foreach (BattlegroundBoard board in boards)
                    {
                        bool triggeredDeathrattles = false;
                        List <BattlegroundCard> playerCardsToRemove   = new List <BattlegroundCard>();
                        List <BattlegroundCard> opponentCardsToRemove = new List <BattlegroundCard>();
                        DeathrattleChain        deathrattleChain      = new DeathrattleChain(board);
                        for (int j = 0; j < board.playerCards.Count; j++)
                        {
                            if (board.playerCards[j].health <= 0)
                            {
                                playerCardsToRemove.Add(board.playerCards[j]);
                                if (board.playerCards[j] is DeathrattleBattlegroundCard)
                                {
                                    triggeredDeathrattles = true;
                                    deathrattleChain.AddDeathrattle(new Deathrattle((DeathrattleBattlegroundCard)board.playerCards[j], board, true, j));
                                }
                            }
                        }
                        for (int j = 0; j < board.opponentCards.Count; j++)
                        {
                            if (board.opponentCards[j].health <= 0)
                            {
                                opponentCardsToRemove.Add(board.opponentCards[j]);
                                if (board.opponentCards[j] is DeathrattleBattlegroundCard)
                                {
                                    triggeredDeathrattles = true;
                                    deathrattleChain.AddDeathrattle(new Deathrattle((DeathrattleBattlegroundCard)board.opponentCards[j], board, false, j));
                                }
                            }
                        }
                        foreach (BattlegroundCard card in playerCardsToRemove)
                        {
                            board.RemovePlayerCard(card);
                        }
                        foreach (BattlegroundCard card in opponentCardsToRemove)
                        {
                            board.RemoveOpponentCard(card);
                        }
                        if (triggeredDeathrattles)
                        {
                            deathrattles.Add(deathrattleChain);
                            boardsToRemove.Add(board);
                        }
                    }
                    // Remove any boards that are going to be handled by the newly triggered deathrattles.
                    foreach (BattlegroundBoard board in boardsToRemove)
                    {
                        boards.Remove(board);
                    }
                }
                // Continue on with the deathrattle boards, or the original boardClone if there were no deathrattles.
                if (boards.Count == 0)
                {
                    boards.Add(boardClone);
                }
                foreach (BattlegroundBoard board in boards)
                {
                    if (board.playerTurn && playerCard.health > 0)
                    {
                        board.playerIndex = board.playerCards.Count > 0 ? ++board.playerIndex : 0;
                    }
                    if (!board.playerTurn && playerCard.health > 0)
                    {
                        board.opponentIndex = board.opponentCards.Count > 0 ? ++board.opponentIndex : 0;
                    }
                    if (board.playerCards.Count > 0)
                    {
                        board.playerIndex %= board.playerCards.Count;
                    }
                    if (board.opponentCards.Count > 0)
                    {
                        board.opponentIndex %= board.opponentCards.Count;
                    }
                    board.playerTurn = !board.playerTurn;
                    simulationStats.Merge(SimulationHelper(board));
                }
            }

            return(simulationStats);
        }
        public void TestCopyConstructor()
        {
            // Verify the copy constructor creates an identical board.
            BattlegroundBoard board = new BattlegroundBoard(TestPlayerCards, TestOpponentCards);

            board.RemovePlayerCard(TestPlayerCards[0]);
            board.RemoveOpponentCard(TestOpponentCards[0]);
            BattlegroundBoard boardCopy = new BattlegroundBoard(board);

            Assert.AreEqual(board.playerTurn, boardCopy.playerTurn);
            Assert.AreEqual(board.playerIndex, boardCopy.playerIndex);
            Assert.AreEqual(board.opponentIndex, boardCopy.opponentIndex);

            // The cards should be cloned and not the same instance.
            Assert.AreNotEqual(board.playerCards, boardCopy.playerCards);
            Assert.AreNotEqual(board.opponentCards, boardCopy.opponentCards);
            Assert.AreNotEqual(board.deadPlayerCards, boardCopy.deadPlayerCards);
            Assert.AreNotEqual(board.deadOpponentCards, boardCopy.deadOpponentCards);

            Assert.AreEqual(1, board.playerCards.Count);
            Assert.AreEqual(1, board.opponentCards.Count);
            Assert.AreEqual(1, board.deadPlayerCards.Count);
            Assert.AreEqual(1, board.deadOpponentCards.Count);

            Assert.AreEqual(board.playerCards.Count, boardCopy.playerCards.Count);
            Assert.AreEqual(board.opponentCards.Count, boardCopy.opponentCards.Count);
            Assert.AreEqual(board.deadPlayerCards.Count, boardCopy.deadPlayerCards.Count);
            Assert.AreEqual(board.deadOpponentCards.Count, boardCopy.deadOpponentCards.Count);

            for (int i = 0; i < board.playerCards.Count; i++)
            {
                BattlegroundCard a = board.playerCards[i];
                BattlegroundCard b = boardCopy.playerCards[i];
                Assert.AreEqual(a.attack, b.attack);
                Assert.AreEqual(a.health, b.health);
            }

            for (int i = 0; i < board.opponentCards.Count; i++)
            {
                BattlegroundCard a = board.opponentCards[i];
                BattlegroundCard b = boardCopy.opponentCards[i];
                Assert.AreEqual(a.attack, b.attack);
                Assert.AreEqual(a.health, b.health);
            }

            for (int i = 0; i < board.deadPlayerCards.Count; i++)
            {
                BattlegroundCard a = board.deadPlayerCards[i];
                BattlegroundCard b = boardCopy.deadPlayerCards[i];
                Assert.AreEqual(a.attack, b.attack);
                Assert.AreEqual(a.health, b.health);
            }

            for (int i = 0; i < board.deadOpponentCards.Count; i++)
            {
                BattlegroundCard a = board.deadOpponentCards[i];
                BattlegroundCard b = boardCopy.deadOpponentCards[i];
                Assert.AreEqual(a.attack, b.attack);
                Assert.AreEqual(a.health, b.health);
            }
        }