private void button2_Click(object sender, EventArgs e)
        {
            List <HearthstoneBoard> res = new List <HearthstoneBoard>();
            int sims = 0;

            try
            {
                sims = int.Parse(textBox1.Text);
            } catch (Exception) { MessageBox.Show("Simulations must be a number"); return; }
            try
            {
                res = board.simulateResults(sims);
            }
            catch (ExceptionWithMessageWhyDoesntCSharpHaveItDeafaultComeOne ex)
            {
                MessageBox.Show("Exception encountered on board simulation: " + ex.Message);
                return;
            }

            var dmgdist = StatisticsManager.calculateDmgDistributions(res);

            StatisticsManager.printReadableResult(dmgdist);

            var dmgdist2 = StatisticsManager.calculateAverageWins(res);

            StatisticsManager.printReadableResult(dmgdist2);
            GUI gui = new GUI(null);

            gui.hideRealTimeLabels();
            gui.Show();

            gui.drawChart(dmgdist);
            gui.setLabels(dmgdist2, "");
            var wAndB = StatisticsManager.findWorstAndBest(res);

            worstValues     = wAndB[1].recievedRandomValues;
            bestValues      = wAndB[0].recievedRandomValues;
            button4.Enabled = true;
            button5.Enabled = true;
            button6.Enabled = true;
        }
        public void startRound(string newvalue, string opponent, string opponentHeroPWR)
        {
            if (waitingForStart)
            {
                round++;
                Console.WriteLine("Finished building enemy board. (tavern tier: " + newvalue + ")");
                //Looking for effects in power file. Like reborn buffs
                lookForEffects();

                //Set up board using the correct positions
                Card[] cards = new Card[board.p1Board.Count];
                foreach (Card c in board.p1Board)
                {
                    cards[c.BoardPosition - 1] = c;
                }
                board.p1Board = new BoardSide();
                for (int i = 0; i < cards.Length; i++)
                {
                    if (cards[i] != null)
                    {
                        board.p1Board.Add(cards[i]);
                    }
                }

                board.p1Board.tavernTier = taverntier;
                board.p2Board.heroOwner  = opponentHeroPWR;
                board.p2Board.tavernTier = int.Parse(newvalue);

                //Extra hack for special hero abilities
                if (playerIsIllidan)
                {
                    board.illidanPlayer = 1;
                }
                if (opponentHeroPWR.Equals(HeroPower.Illidan))
                {
                    board.illidanPlayer = 2;
                }
                if (playerIsDW)
                {
                    board.DeathwingPlayer = 1;
                }
                if (opponentHeroPWR.Equals(HeroPower.Deathwing))
                {
                    board.DeathwingPlayer = 2;
                }

                board.printState();
                board.recievedRandomValues = new List <int>();
                board.makeUpForReaderError();

                //Save opponent boardstate to disk
                if (saveBoards && !opponent.Equals("Kel'Thuzad"))
                {
                    BoardEditor.autoSave(board.p2Board, round);
                }
                List <HearthstoneBoard> res = new List <HearthstoneBoard>();
                double ranking = -1;
                try
                {
                    Console.Write("Simulating board results ");
                    Thread t = new Thread(() => res = board.simulateResults(simulationCount));
                    t.Start();
                    while (board.currentProgression < board.currentProgressionMax)
                    {
                        if (board.currentProgressionMax != simulationCount)
                        {
                            board.currentProgressionMax = simulationCount;
                        }
                        Console.SetCursorPosition(25, Console.CursorTop);
                        Console.Write(board.currentProgression + "/" + board.currentProgressionMax + " (" + Math.Round(((double)board.currentProgression * 100 / (double)board.currentProgressionMax), 0) + "%)                 ");
                        Thread.Sleep(100);
                    }
                    Console.SetCursorPosition(25, Console.CursorTop);
                    Console.Write(board.currentProgression + "/" + board.currentProgressionMax + " (100%)                ");
                    Console.WriteLine();

                    var roundBoards = BoardEditor.loadAllRoundSides(round);

                    if (!(roundBoards.Count == 0))
                    {
                        int   totalSims     = strengthSimuls;
                        int   eachSim       = strengthSimuls / roundBoards.Count;
                        int   totalfinished = 0;
                        var   sims          = new List <HearthstoneBoard>();
                        int   score         = roundBoards.Count;
                        int[] scoreChanges  = new int[] { 0, 1, -1 };
                        Console.Write("Simulating ranking results ");
                        foreach (BoardSide b in roundBoards)
                        {
                            HearthstoneBoard h = new HearthstoneBoard();
                            h.p1Board = board.p1Board.copy();
                            h.p2Board = b.copy();
                            switch (b.heroOwner)
                            {
                            case HeroNames.Nefarian:
                            case HeroPower.Nefarian:
                                h.NefarianPlayer = 2; break;

                            case HeroNames.Illidan:
                            case HeroPower.Illidan:
                                h.illidanPlayer = 2; break;

                            case HeroNames.Deathwing:
                            case HeroPower.Deathwing:
                                h.DeathwingPlayer = 2; break;
                            }
                            if (playerIsIllidan)
                            {
                                h.illidanPlayer = 1;
                            }
                            if (playerIsDW)
                            {
                                h.DeathwingPlayer = 1;
                            }
                            Thread t2 = new Thread(() => sims = h.simulateResults(eachSim));
                            t2.Start();
                            while (h.currentProgression < h.currentProgressionMax)
                            {
                                if (totalSims != strengthSimuls)
                                {
                                    totalSims = strengthSimuls;
                                    eachSim   = strengthSimuls / roundBoards.Count;
                                    h.currentProgressionMax = eachSim;
                                }
                                Console.SetCursorPosition(27, Console.CursorTop);
                                Console.Write(totalfinished + h.currentProgression + "/" + totalSims + " (" + Math.Round(((double)(totalfinished + h.currentProgression) * 100 / (double)totalSims), 0) + "%)                 ");
                                Thread.Sleep(100);
                            }
                            score         += scoreChanges[StatisticsManager.expectedResult(StatisticsManager.calculateAverageWins(sims))];
                            totalfinished += eachSim;
                        }
                        ranking = (double)score / (double)(roundBoards.Count * 2);
                        ranking = Math.Round(ranking * 100, 1);
                        Console.WriteLine();
                    }
                } catch (ExceptionWithMessageWhyDoesntCSharpHaveItDeafaultComeOne e)
                {
                    Console.WriteLine("Exception encountered on board simulation: " + e.Message);
                    Console.WriteLine("Press any key to continue");
                    Console.ReadKey();
                    waitingForStart = false;
                    while (pause)
                    {
                        Thread.Sleep(100);
                    }
                    return;
                }
                while (pause)
                {
                    Thread.Sleep(100);
                }
                //Calculate and print all damage distribution percentages
                var dmgdist = StatisticsManager.calculateDmgDistributions(res);
                StatisticsManager.printReadableResult(dmgdist);

                //Calculate and print win/loss chances
                var dmgdist2 = StatisticsManager.calculateAverageWins(res);
                StatisticsManager.printReadableResult(dmgdist2);

                //If gui has not been initilized then wait
                while (gui == null)
                {
                    Thread.Sleep(100);                //Find worst and best boards
                }
                var wAndB = StatisticsManager.findWorstAndBest(res);

                //Calculate most likely game damage outcome and set expected health
                int likelydmg = StatisticsManager.mostLikelyOutcome(dmgdist);
                if (likelydmg < 0)
                {
                    expectedHealth += likelydmg;
                }

                //Set expected outcome, used for lucky win/unlucky loss
                if (dmgdist2[2] > 0.5)
                {
                    expectedLoss = true;
                }
                else
                {
                    expectedLoss = false;
                }
                StatisticsManager.printExpectedResult(dmgdist2);
                waitingForStart = false;

                //Calculate the chance to die
                double deathchance = StatisticsManager.chanceForDamageOrMore(-actualHealth, dmgdist);

                //Update the GUI to the new boardstate
                GUIstate currentState = new GUIstate(dmgdist, dmgdist2, board, wAndB[1].recievedRandomValues, wAndB[0].recievedRandomValues, expectedHealth, opponent, deathchance, ranking);
                gui.addGUIstate(currentState);

                //Remove temporary reborn buffs (Lich King)
                foreach (Card c in board.p1Board)
                {
                    if (c.tempReborn)
                    {
                        c.removeReborn();
                    }
                }
            }
        }