Exemplo n.º 1
0
        /// <summary>
        /// Cycles through the game starting at generation 0 up to the number of generations set in the Settings
        /// </summary>
        public void CycleThroughGame()
        {
            SetInitialState();
            grid.InitializeWindow();
            Stopwatch watch = new Stopwatch();

            for (int i = 0; i <= settings.Generations; i++)
            {
                grid.SetFootnote($"Generation: {i}");

                // Only need to create a new generation from i = 1 onwards
                if (i != 0)
                {
                    statusArray = CreateNextGeneration();
                }
                UpdateCellStatus();
                int matchIndex = CompareToMemory();

                // Only need to compare to memory from i = 1 onwards
                if (i != 0)
                {
                    if (matchIndex != -1)
                    {
                        periodicity = i - generationInMemory[matchIndex];
                        steadyState = true;
                        // Break out of loop to end game
                        break;
                    }
                }
                AddToMemory(statusArray, i);
                grid.Render();
                watch.Restart();

                // User cycles through 1 generation at a time by pressing space if step mode enabled
                if (settings.StepMode)
                {
                    CheckForSpace(writeMsg: false);
                }
                // Otherwise game cycles through at the update rate specified in Settings
                else
                {
                    while (watch.ElapsedMilliseconds < ((1 / settings.UpdateRate) * 1000))
                    {
                        ;
                    }
                }
            }

            // Write final array to file if valid output file path specified
            if (settings.OutputFile != null)
            {
                WriteToFile();
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Main method, which runs the entire program and calls external methods found above and below Main.
        /// </summary>
        /// <author>Zac Wolter</author>
        /// <date>September 2020</date>
        static void Main(string[] args)
        {
            int periodicity = 0;

            // Check for command line arguments...
            Console.WriteLine("Interpreting command line arguments...");
            if (args.Length == 0)
            {
                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine("[SUCCESS] No command line arguments found.");
                Console.ForegroundColor = ConsoleColor.White;
                Console.WriteLine("The program will use the following default settings.");

                //Call the WriteValues method with no parameters, hence printing default set values
                WriteFinalValues();
            }
            // If command line arguments exist, perform the for loop to check each value
            else if (args.Length > 0)
            {
                for (int i = 0; i < args.Length; i++)
                {
                    // Check if the current value contains the dimensions flag
                    if (args[i].Contains("--dimensions"))
                    {
                        DimensionArgCheck(args);
                    }

                    // Check if the current value contains the survival flag
                    else if (args[i].Contains("--survival"))
                    {
                        SurvivalArgCheck(args);
                    }

                    // Check if the current value contains the survival flag
                    else if (args[i].Contains("--birth"))
                    {
                        BirthArgCheck(args);
                    }

                    //Check for periodic behaviour boolean
                    else if (args[i].Contains("--periodic"))
                    {
                        PerioidicArgCheck();
                    }

                    //Check for Random Factor double
                    else if (args[i].Contains("--random"))
                    {
                        RandomArgCheck(args, i);
                    }

                    // Check for seed argument
                    else if (args[i].Contains("--seed"))
                    {
                        SeedFileCheck(args, i);
                    }

                    // Check for generations argument
                    else if (args[i].Contains("--generations"))
                    {
                        GenerationArgCheck(args, i);
                    }

                    // Check for maximum update rate
                    else if (args[i].Contains("--max-update"))
                    {
                        MaxUpdateArgCheck(args, i);
                    }

                    // Check for step mode value
                    else if (args[i].Contains("--step"))
                    {
                        StepArgCheck();
                    }

                    // Check for neighbourhood value
                    else if (args[i].Contains("--neighbour"))
                    {
                        NeighourhoodCheck(args, i, currentValues.Rows, currentValues.Columns);
                    }

                    // Check for memory value
                    else if (args[i].Contains("--memory"))
                    {
                        MemoryArgCheck(args, i);
                    }

                    // Check for ghost mode value
                    else if (args[i].Contains("--ghost"))
                    {
                        GhostArgCheck();
                    }

                    // Check for output file value
                    else if (args[i].Contains("--output"))
                    {
                        OutputFileCheck(args, i);
                    }
                }

                // Check that the given survival and birth values supplied by the user are less than or equal to the number
                // of neighbourhing cells depending on the neighbourhood type
                CheckSurvivalAndBirthValues(currentValues);

                // Check that the given neighbourhood order supplied by the user is less than or equal to half the shortest
                // grid dimension
                NeighbourhoodOrderCheck(currentValues.NeighbourhoodSize, currentValues.Rows, currentValues.Columns);

                WriteFinalValues();
            }

            CLA paramValues = storedValues();

            // Wait until the user presses the spacebar before beginning the simulation
            Console.WriteLine("Press Spacebar to begin.");
            WaitForSpacebarPress();

            int[,,] currentCells = new int[currentValues.Rows, currentValues.Columns, currentValues.Memory];
            int[,,] newCells     = new int[currentValues.Rows, currentValues.Columns, 1];

            // HOW THE NEW 3D ARRAY WILL WORK:
            // EACH CELL: { x, y, z}
            // Where:
            // x = x coordinate
            // y = y coordinate
            // z = generation

            // Seed file initialisation or random seed generation
            if (currentValues.InputFile == "N/A")
            {
                currentCells = GenerateRandomGrid(currentValues.Probability, currentCells, currentValues.Rows,
                                                  currentValues.Columns);
            }
            else
            {
                currentCells = CheckAndInitialiseInputFile(currentValues.InputFilePath, currentCells, currentValues.Rows, currentValues.Columns);
            }

            // Construct grid...
            Grid grid = new Grid(currentValues.Rows, currentValues.Columns);

            // Initialize the grid window (this will resize the window and buffer)
            grid.InitializeWindow();

            // Set the footnote (appears in the bottom left of the screen).
            grid.SetFootnote($"Generation: 0");

            Stopwatch watch = new Stopwatch();

            // Initialise cells
            InitialiseFirstGen(grid, currentCells);

            // Render updates to the console window...
            grid.Render();

            // Integer to keep track of the number of iterations
            int iterations = Convert.ToInt32(currentValues.Generations);
            int passes     = 0;

            // Calculate speed of simulation (applies only if step mode is off)
            int updateTime = 1000 / Convert.ToInt32(currentValues.MaxRefreshRate);

            // Run the simulation
            while (passes < iterations)
            {
                watch.Restart();

                grid.SetFootnote($"Generation: {passes}");
                grid.Render();

                passes++;

                // Check all x layers for any similarities against all other layers
                periodicity = steadyStateCheck(currentCells);

                if (periodicity != -1)
                {
                    steadyStateCompletion(grid, periodicity, currentCells);
                    break;
                }

                // Method that checks every cell in the grid for alive neighbours, decides if each cell is alive or
                // dead in the next generation, and updates the display based on if ghost mode is activated or not
                SimulateNextGen(currentValues.GhostMode, currentCells, grid, newCells);

                // Generates a new array of cells with the previous layers moved forward 1 layer
                // First layer [0] is empty
                currentCells = RotateMemory(currentCells, newCells);

                // Check if step mode is enabled, if so, wait for key press
                if (currentValues.StepMode == true)
                {
                    while (Console.ReadKey(true).Key != ConsoleKey.Spacebar)
                    {
                        ;
                    }
                }
                else
                {
                    // Update timer if required...
                    while (watch.ElapsedMilliseconds < updateTime)
                    {
                        ;
                    }
                }
            }

            grid.SetFootnote("Press Space to Exit");

            // Set complete marker as true
            grid.IsComplete = true;

            // Render updates to the console window (grid should now display COMPLETE)...
            grid.Render();

            // Wait for user to press a key...
            while (true)
            {
                var keyPress = Console.ReadKey(true);
                if (keyPress.Key == ConsoleKey.Spacebar)
                {
                    break;
                }
            }

            // Revert grid window size and buffer to normal
            grid.RevertWindow();

            // Tell user that no steady-state was detected (this code will only execute if the number of generations
            // is reached before a steady-state occurs)
            Console.WriteLine("Steady-state not detected...");

            if (currentValues.OutputFile != "N/A")
            {
                GenerateOutputFile(currentValues.OutputFile, currentValues.Rows, currentValues.Columns, currentCells);
            }

            Console.WriteLine("Press spacebar to close program...");

            // Wait for user to press spacebar...
            while (true)
            {
                var keyPress = Console.ReadKey(true);
                if (keyPress.Key == ConsoleKey.Spacebar)
                {
                    break;
                }
            }

            // Close the program here
            Environment.Exit(0);
        }
Exemplo n.º 3
0
        static void Main(string[] args)
        {
            Options options = ArgumentProcessor.Process(args);

            int[,] universe = InitializeUniverse(options);
            Grid grid                    = new Grid(options.Rows, options.Columns);
            var  universeList            = new List <int[, ]>();
            bool isSteadyState           = false;
            bool successfullyWroteToFile = false;



            Logging.Message("Press spacebar to begin the game...");
            WaitSpacebar();

            grid.InitializeWindow();


            Stopwatch stopwatch = new Stopwatch();

            int iteration = 0;

            while (iteration <= options.Generations)
            {
                stopwatch.Restart();

                if (iteration != 0)
                {
                    universe = EvolveUniverse(universe, options.Periodic, options.NeighbourOrder, options.NeighbourhoodType, options.CentreCount, options.BirthRate, options.SurvivalRate);
                }

                if (universeList.Count == options.GenerationalMemory) //Remove the first item in the list if the list capacity is reached (Capacity is the generationalMemory)
                {
                    universeList.RemoveAt(0);
                }

                UpdateGrid(grid, universe);

                grid.SetFootnote($"Generation: {iteration++}");
                grid.Render();
                isSteadyState = CheckSteadyState(universeList, options, universe); //Check if the current universe have reached a steady state
                if (isSteadyState)
                {
                    break; //If a steady state is found then stop the next generation from happening
                }
                universeList.Add(universe);

                if (options.StepMode)
                {
                    WaitSpacebar();
                }
                else
                {
                    while (stopwatch.ElapsedMilliseconds < 1000 / options.UpdateRate)
                    {
                        ;
                    }
                }
            }

            grid.IsComplete = true;
            grid.Render();

            if (!string.IsNullOrEmpty(options.OutputFile))
            {
                using StreamWriter writer = new StreamWriter(options.OutputFile);
                writer.WriteLine("#version=2.0");
                OutputToFile(options, universeList, writer);
                writer.Close();
                successfullyWroteToFile = true;
            }
            WaitSpacebar();

            grid.RevertWindow();


            if (isSteadyState && options.IsAllDead == false)
            {
                Logging.Message($"Steady-state detected... periodicity = {iteration - 1}");
            }
            if (isSteadyState && options.IsAllDead == true)
            {
                Logging.Message($"Steady-state detected... periodicity = N/A");
            }
            if (successfullyWroteToFile)
            {
                Logging.Success($": Final generation written to file: {options.OutputFile}");
            }
            Logging.Message("Press spacebar to exit program...");
            WaitSpacebar();
        }
Exemplo n.º 4
0
        /// <summary >
        /// Starts the simulation by running the main loop of the program
        /// This method calls other methods to collect the information required to use the Display API.
        /// </ summary >
        /// <param name =" grid " > Used to display the Cell matrix in the console </ param >
        public int start(Grid grid)
        {
            Stopwatch watch = new Stopwatch();                                              //initialise time

            CellState[,] state = new CellState[getRows, getColumns];                        //set state for each cell
            CellState[] ghostState = { CellState.Dark, CellState.Medium, CellState.Light }; //ghost states

            for (int g = 0; g <= getGenerations; g++)                                       //loop per generation
            {
                watch.Restart();

                for (int r = 0; r < getRows; r++) // For each of the cells...
                {
                    for (int c = 0; c < getColumns; c++)
                    {
                        state[r, c] = CellState.Blank;                                                    //clear cell state

                        int ghosts = (previousGenerations.Count > 2) ? 2 : previousGenerations.Count - 1; //ghost count

                        ghosts = (ghostMode) ? ghosts : -1;                                               //turn on : off ghost mode

                        for (int gh = ghosts; gh >= 0; gh--)
                        {
                            state[r, c] = (previousGenerations[gh][r, c] == alive) ? ghostState[gh] : state[r, c]; //set ghosts
                        }

                        state[r, c] = (cells[r, c] == alive) ? CellState.Full : state[r, c]; //get new generation states

                        grid.UpdateCell(r, c, state[r, c]);                                  // Update grid
                    }
                }

                while (watch.ElapsedMilliseconds < (1 / getMaxUpdate * 1000))
                {
                    ;                                 //Timer
                }
                grid.SetFootnote("Generation: " + g); //prints current generation

                grid.Render();                        // Render updates to the console window...

                period = steadyState(cells);          //get period

                if (period > -1)                      //steady state? End game if true
                {
                    if (getOutputPath != String.Empty)
                    {
                        outputSeed(cells);                               //output seed
                    }
                    return(period);
                }

                cells = this.mutation(cells); //MUTATION, following the Conways game of life...

                if (stepMode)
                {
                    space();           //Step Mode
                }
            }

            if (getOutputPath != String.Empty)
            {
                outputSeed(cells);                                //output seed
            }
            return(period);
        }
        /// <summary>
        /// Main Function which contains all code that wasn't put into methods
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            // Declaring the variables
            int    Rows               = 16;    // Default: 16. Change as required for testing.
            int    Columns            = 16;    // Default: 16. Change as required for testing.
            bool   PeriodicBehaviour  = false; // Default: false. Change as required for testing
            double RandFactor         = 0.5;   // Default: 0.5. Change as required for testing
            string InputFile          = "";    // Default: NO input. Change as required for testing
            int    Generations        = 50;    // Default: 50. Change as required fo testing
            double MaxUpdateRate      = 5;     // Default: 5. Change as required for testing
            bool   StepMode           = false; // Default: NOT step mode. Change as required for testing
            bool   CheckAllConditions = true;  //Checking all the parameters

            //To count the number of generations
            int GenCount = 0;

            Stopwatch watch = new Stopwatch();


            // Checking the user input
            for (int count = 0; count < args.Length; count++)
            {
                //Checking the dimensions of the game
                CheckDimensions(ref args, ref count, ref Rows, ref Columns, ref CheckAllConditions);

                //Checking if the game will have periodic behaviour
                CheckPeriodic(ref args, ref count, ref PeriodicBehaviour);

                //Checking Random factor
                CheckRandomFactor(ref args, ref count, ref RandFactor, ref CheckAllConditions);

                //Checking the input file
                CheckSeedfile(ref args, ref count, ref InputFile, ref CheckAllConditions);

                //Checking the generations
                GenerationMethod(ref args, ref count, ref Generations, ref CheckAllConditions);

                //Checking the max update rate
                MaxUpdaterate(ref args, ref count, ref MaxUpdateRate, ref CheckAllConditions);

                //Checking step mode
                StepModeMethod(ref args, ref count, ref StepMode);
            }

            //Game array which stores the cell coordinates
            int[,] GameArray = new int[Rows, Columns];

            //Temporary Array to store the neighbours
            int[,] TempArray = new int[Rows, Columns];

            // Construct grid...
            Grid grid = new Grid(Rows, Columns);


            //Checking randomness
            RandomnessMethod(ref InputFile, ref Columns, ref Rows, ref GameArray, ref RandFactor);

            //Displaying user uput
            DispUserInput(ref CheckAllConditions, ref InputFile, ref Generations, ref MaxUpdateRate, ref PeriodicBehaviour,
                          ref Rows, ref Columns, ref StepMode, ref RandFactor);

            // Wait for user to press a key...
            Console.WriteLine("Press any key to start...");
            Console.ReadKey();


            // Game
            // Initialize the grid window (this will resize the window and buffer
            grid.InitializeWindow();

            // Set the footnote (appears in the bottom left of the screen).
            grid.SetFootnote("Life " + GenCount);

            // Declaring variable to see if neighbouring cells are active for next generation
            int ThreeCount = 0;

            // For each of the cells...
            for (int i = 0; i < GameArray.GetLength(0); i++)
            {
                for (int j = 0; j < GameArray.GetLength(1); j++)
                {
                    if (GameArray[i, j] == 1)
                    {
                        // Update grid with a new cell...
                        grid.UpdateCell(i, j, CellState.Full);
                    }
                    else
                    {
                        grid.UpdateCell(i, j, CellState.Blank);
                    }
                }
            }

            // Timer for Life game
            watch.Restart();
            while (watch.ElapsedMilliseconds < (1000 / MaxUpdateRate))
            {
                ;
            }

            grid.Render();

            //Increasing the generations
            while (Generations >= GenCount)
            {
                //Checking the neighbours of the cells
                ActualGame(ref Rows, ref Columns, ref GameArray, ref ThreeCount, ref PeriodicBehaviour, ref TempArray);

                //Step function holding answer till space is pressed
                if (StepMode == true)
                {
                    while (Console.ReadKey().Key != ConsoleKey.Spacebar)
                    {
                        ;
                    }
                }
                grid.SetFootnote("Life " + GenCount);

                // For each of the cells...
                for (int i = 0; i < GameArray.GetLength(0); i++)
                {
                    for (int j = 0; j < GameArray.GetLength(1); j++)
                    {
                        if (TempArray[i, j] == 1)
                        {
                            // Update grid with a new cell...
                            grid.UpdateCell(i, j, CellState.Full);
                            GameArray[i, j] = TempArray[i, j];
                        }
                        else
                        {
                            grid.UpdateCell(i, j, CellState.Blank);
                            GameArray[i, j] = 0;
                        }
                        TempArray[i, j] = 0;
                    }
                }

                // Timer for Life Game
                watch.Restart();
                while (watch.ElapsedMilliseconds < (1000 / MaxUpdateRate))
                {
                    ;
                }
                // Render updates to the console window...
                grid.Render();
                GenCount++;
            }

            // Set complete marker as true
            grid.IsComplete = true;

            grid.Render();

            Console.ReadKey();

            grid.RevertWindow();
        }