/// <summary>
        /// Event that fies when the RUN button is clicked.
        /// This is used to run the selected agent and game in search of a solution.
        /// Upon completion a message gox is displayed and the animation of the solution
        /// is played.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_run_Click(object sender, EventArgs e)
        {
            if (cmb_gameSelect.SelectedItem == null || cmb_agentSelect.SelectedItem == null)
            {
                MessageBox.Show("Please Select Game Board and Agent.", "Configuration Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }
            cmb_gameSelect.Enabled  = false;
            cmb_agentSelect.Enabled = false;
            // Setup selected game type
            if (cmb_gameSelect.Text == "Triangle, 5 Row")
            {
                selectedGame = TriangleGames.BasicTriangle(5);
            }
            else if (cmb_gameSelect.Text == "Triangle, 6 Row")
            {
                selectedGame = TriangleGames.BasicTriangle(6);
            }
            else if (cmb_gameSelect.Text == "Triangle, 7 Row")
            {
                selectedGame = TriangleGames.BasicTriangle(7);
            }

            // Setup selected agent type
            if (cmb_agentSelect.Text == "Breadth First")
            {
                selectedAgent = new BreadthFirstAgent(selectedGame);
            }
            else if (cmb_agentSelect.Text == "Depth First")
            {
                selectedAgent = new DepthFirstAgent(selectedGame);
            }
            if (cmb_agentSelect.Text == "Iterative Deepening")
            {
                selectedAgent = new IterativeDeepeningAgent(selectedGame);
            }

            txt_output.Clear();
            movesToWin = selectedAgent.Solve();

            int    moveNumber = 0;
            string lineToAdd;

            foreach (List <List <int> > move in movesToWin)
            {
                moveNumber++;
                lineToAdd = string.Format("Action {0}: ", moveNumber);
                txt_output.AppendText(lineToAdd);
                lineToAdd = string.Format("Move Peg ({0},{1}) to ({2},{3}) and Remove Peg ({4},{5})\n",
                                          move[0][0], move[0][1], move[2][0], move[2][1], move[1][0], move[1][1]);
                txt_output.AppendText(lineToAdd);
            }

            MessageBox.Show("Solution found! See animation to the right.", "Done", MessageBoxButtons.OK, MessageBoxIcon.Information);

            moveIndex = 0;
            animationTimer.Enabled = true;
        }
        /// <summary>
        /// Event that fies when the RUN button is clicked.
        /// This is used to run the selected agent and game in search of a solution.
        /// Upon completion a message gox is displayed and the animation of the solution
        /// is played.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_run_Click(object sender, EventArgs e)
        {
            if (cmb_gameSelect.SelectedItem == null || cmb_agentSelect.SelectedItem == null)
            {
                MessageBox.Show("Please Select Game Board and Agent.", "Configuration Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }
            cmb_gameSelect.Enabled  = false;
            cmb_agentSelect.Enabled = false;
            btn_run.Enabled         = false;
            btn_replay.Hide();
            string messageBoxMesage;

            // Setup selected game type
            if (cmb_gameSelect.Text == "Triangle, 5 Row Basic")
            {
                selectedGame = TriangleGames.BasicTriangle(5);
            }
            else if (cmb_gameSelect.Text == "Triangle, 6 Row Basic")
            {
                selectedGame = TriangleGames.BasicTriangle(6);
            }
            else if (cmb_gameSelect.Text == "Triangle, 7 Row")
            {
                selectedGame = TriangleGames.BasicTriangle(7);
            }
            if (cmb_gameSelect.Text == "Triangle, 5 Row Custom")
            {
                selectedGame = new GameState(customPegMap);
            }

            // Setup selected agent type
            if (cmb_agentSelect.Text == "Breadth First")
            {
                selectedAgent = new BreadthFirstAgent(selectedGame);
            }
            else if (cmb_agentSelect.Text == "Depth First")
            {
                selectedAgent = new DepthFirstAgent(selectedGame);
            }
            else if (cmb_agentSelect.Text == "Iterative Deepening")
            {
                selectedAgent = new IterativeDeepeningAgent(selectedGame);
            }
            else if (cmb_agentSelect.Text == "Q-Learning")
            {
                selectedAgent = new QLearningAgent(selectedGame);
            }

            txt_output.Clear();

            if (!custom)
            {
                resetPegs();
            }

            try
            {
                Cursor.Current = Cursors.WaitCursor;
                startTime      = DateTime.Now;
                setTimeout();
                movesToWin = selectedAgent.Solve(isTimeout, selectedTimeout);
                endTime    = DateTime.Now;
            }
            catch (Exception except)
            {
                string failureMessage = except.ToString();
                if (except.ToString().Contains("No solution exists for this game."))
                {
                    failureMessage = string.Format("No solution exists for this game. {0} states expanded.",
                                                   selectedAgent.getTotalExpandedStates());
                    MessageBox.Show(failureMessage, "No solution found", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
                else if (except.ToString().Contains("timed out."))
                {
                    failureMessage = string.Format("Search time limit reached before a solution was found. {0} states expanded.", selectedAgent.getTotalExpandedStates());
                    MessageBox.Show(failureMessage, "No solution found", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
                else if (except.ToString().Contains("format"))
                {
                    failureMessage = string.Format("Timeout must be a numeric value.");
                    MessageBox.Show(failureMessage, "Invalid timeout entry", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
                Cursor.Current          = Cursors.Default;
                cmb_gameSelect.Enabled  = true;
                cmb_agentSelect.Enabled = true;
                btn_run.Enabled         = true;
                return;
            }

            int    moveNumber = 0;
            string lineToAdd;

            elapsedTime = endTime - startTime;
            lineToAdd   = string.Format("Elapsed Time (h:m:s.ms): {0}:{1}:{2}.{3}\n", elapsedTime.Hours, elapsedTime.Minutes, elapsedTime.Seconds, elapsedTime.Milliseconds);
            txt_output.AppendText(lineToAdd);
            if (cmb_agentSelect.Text != "Q-Learning")
            {
                lineToAdd = string.Format("Expanded {0} states to find solution:\n\n", selectedAgent.getTotalExpandedStates());
                txt_output.AppendText(lineToAdd);
            }

            foreach (List <List <int> > move in movesToWin)
            {
                moveNumber++;
                lineToAdd = string.Format("Action {0}: ", moveNumber);
                txt_output.AppendText(lineToAdd);
                lineToAdd = string.Format("Move Peg ({0},{1}) to ({2},{3}) and Remove Peg ({4},{5})\n",
                                          move[0][0], move[0][1], move[2][0], move[2][1], move[1][0], move[1][1]);
                txt_output.AppendText(lineToAdd);
            }

            Cursor.Current = Cursors.Default;
            if (cmb_agentSelect.Text == "Q-Learning")
            {
                messageBoxMesage = string.Format("Learning sequence complete. See animation to the right.");
            }
            else
            {
                messageBoxMesage = string.Format("Solution Found! {0} states expanded. See animation to the right.", selectedAgent.getTotalExpandedStates());
            }

            MessageBox.Show(messageBoxMesage, "Done", MessageBoxButtons.OK, MessageBoxIcon.Information);
            moveIndex              = 0;
            enableCustom           = false;
            animationTimer.Enabled = true;
        }