├── .gitignore ├── GOL.c ├── LICENSE ├── Makefile ├── README.md └── images ├── .DS_Store └── GOLc.gif /.gitignore: -------------------------------------------------------------------------------- 1 | GOL 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /GOL.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | char boardInitState = 'r'; 6 | int i, j; 7 | int counter; 8 | int nRows = 40; 9 | int nCols = 40; 10 | char board[40][40]; 11 | char blankBoard[40][40]; 12 | int evolutions = 100; 13 | int timeBetweenEvolutions = 20000; 14 | int randomSeed = 50; 15 | char cellAscii = 'O'; 16 | 17 | void initBoard(boardInitState){ 18 | // blank board 19 | if (boardInitState == 'b') { 20 | for (i = 0; i < nRows; i++){ 21 | for (j = 0; j < nCols; j++){ 22 | blankBoard[i][j] = ' '; 23 | } 24 | } 25 | } 26 | // board with random cells initiated 27 | else if (boardInitState == 'r') { 28 | srand(randomSeed); 29 | int x; 30 | for (i = 0; i < nRows; i++){ 31 | for (j = 0; j < nCols; j++){ 32 | x = rand() % 2; 33 | if (x == 1) { 34 | board[i][j] = cellAscii; 35 | } 36 | else { 37 | board[i][j] = ' '; 38 | } 39 | } 40 | } 41 | } 42 | // board with just glider gun initiated 43 | else if (boardInitState == 'g') { 44 | for (i = 0; i < nRows; i++){ 45 | for (j = 0; j < nCols; j++){ 46 | board[i][j] = ' '; 47 | } 48 | } 49 | 50 | board[1][25] = cellAscii; 51 | board[2][23] = cellAscii; 52 | board[2][25] = cellAscii; 53 | board[3][13] = cellAscii; 54 | board[3][14] = cellAscii; 55 | board[3][21] = cellAscii; 56 | board[3][22] = cellAscii; 57 | board[3][35] = cellAscii; 58 | board[3][36] = cellAscii; 59 | board[4][12] = cellAscii; 60 | board[4][16] = cellAscii; 61 | board[4][21] = cellAscii; 62 | board[4][22] = cellAscii; 63 | board[4][35] = cellAscii; 64 | board[4][36] = cellAscii; 65 | board[5][1] = cellAscii; 66 | board[5][2] = cellAscii; 67 | board[5][11] = cellAscii; 68 | board[5][17] = cellAscii; 69 | board[5][21] = cellAscii; 70 | board[5][22] = cellAscii; 71 | board[6][1] = cellAscii; 72 | board[6][2] = cellAscii; 73 | board[6][11] = cellAscii; 74 | board[6][15] = cellAscii; 75 | board[6][17] = cellAscii; 76 | board[6][18] = cellAscii; 77 | board[6][23] = cellAscii; 78 | board[6][25] = cellAscii; 79 | board[7][11] = cellAscii; 80 | board[7][17] = cellAscii; 81 | board[7][25] = cellAscii; 82 | board[8][12] = cellAscii; 83 | board[8][16] = cellAscii; 84 | board[9][13] = cellAscii; 85 | board[9][14] = cellAscii; 86 | } 87 | 88 | } 89 | 90 | int _countCellNeighbours(i, j){ 91 | int counter = 0; 92 | 93 | if (i - 1 > 0) { 94 | if (board[i-1][j] == cellAscii) { 95 | counter += 1; 96 | } 97 | if (j - 1 > 0) { 98 | if (board[i-1][j-1] == cellAscii) { 99 | counter += 1; 100 | } 101 | } 102 | if (j + 1 < nCols) { 103 | if (board[i-1][j+1] == cellAscii) { 104 | counter += 1; 105 | } 106 | } 107 | } 108 | 109 | if (i + 1 < nRows) { 110 | if (board[i+1][j] == cellAscii) { 111 | counter += 1; 112 | } 113 | 114 | if (j - 1 > 0) { 115 | if (board[i+1][j-1] == cellAscii) { 116 | counter += 1; 117 | } 118 | } 119 | if (j + 1 < nCols) { 120 | if (board[i+1][j+1] == cellAscii) { 121 | counter += 1; 122 | } 123 | } 124 | } 125 | 126 | 127 | if (j + 1 < nCols) { 128 | if (board[i][j+1] == cellAscii) { 129 | counter += 1; 130 | } 131 | } 132 | 133 | if (j - 1 > 0) { 134 | if (board[i][j-1] == cellAscii) { 135 | counter += 1; 136 | } 137 | } 138 | 139 | return counter; 140 | 141 | } 142 | 143 | void _evolveCell(i, j, counter) { 144 | 145 | if (board[i][j] == cellAscii) { 146 | if (counter < 2) { 147 | blankBoard[i][j] = ' '; 148 | } 149 | else if (counter == 2 || counter == 3) { 150 | blankBoard[i][j] = cellAscii; 151 | } 152 | else { 153 | blankBoard[i][j] = ' '; 154 | } 155 | } 156 | 157 | else { 158 | if (counter == 3) { 159 | blankBoard[i][j] = cellAscii; 160 | } 161 | } 162 | 163 | } 164 | 165 | void evolveBoard() { 166 | for (i = 0; i < nRows; i++){ 167 | for (j = 0; j < nCols; j++){ 168 | counter = _countCellNeighbours(i, j); 169 | _evolveCell(i, j, counter); 170 | } 171 | } 172 | } 173 | 174 | void updateOldBoard() { 175 | for (i = 0; i < nRows; i++){ 176 | for (j = 0; j < nCols; j++){ 177 | board[i][j] = blankBoard[i][j]; 178 | } 179 | } 180 | } 181 | 182 | void printBoardState(evolution) { 183 | printf("\033[H"); // Sets cursor to homestate 184 | for (i = 0; i < nRows; i++){ 185 | for (j = 0; j < nCols; j++){ 186 | printf("%c ", board[i][j]); 187 | } 188 | printf("\n"); 189 | } 190 | 191 | printf("Generation = %i\n", evolution); 192 | } 193 | 194 | int main(int argc, char *argv[]) { 195 | int e; 196 | int opt; 197 | printf("\033c"); // clears the terminal 198 | printf("\033[?25l"); // makes cursor invisible 199 | 200 | while((opt = getopt(argc, argv, ":ge:c:t:s:x")) != -1) 201 | { 202 | switch(opt) 203 | { case 'g': 204 | boardInitState = 'g'; 205 | break; 206 | case 't': 207 | timeBetweenEvolutions = atoi(optarg); 208 | break; 209 | case 'c': 210 | cellAscii = optarg[0]; 211 | break; 212 | case 'e': 213 | evolutions = atoi(optarg); 214 | break; 215 | case 's': 216 | randomSeed = atoi(optarg); 217 | break; 218 | case ':': 219 | printf("option needs a value\n"); 220 | break; 221 | case '?': 222 | printf("unknown option: %c\n", optopt); 223 | break; 224 | } 225 | } 226 | 227 | initBoard(boardInitState); 228 | 229 | for (e=0; e < evolutions; e++) { 230 | usleep(timeBetweenEvolutions); 231 | initBoard('b'); 232 | evolveBoard(); 233 | updateOldBoard(); 234 | printBoardState(e); 235 | } 236 | 237 | printf("\033[?25h"); // makes cursor visible 238 | return 0; 239 | } 240 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Flynn Owen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: GOL 2 | program: 3 | 4 | install: 5 | cp GOL /usr/local/bin/ 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

GOL

2 | 3 |

Manual install:

4 | 5 | ```console 6 | $ git clone https://github.com/FlynnOwen/GOL-C.git 7 | $ cd GOL-C 8 | $ make 9 | $ make install 10 | ``` 11 | 12 | 13 | 14 | ## Usage: 15 | 16 | ```console 17 | $ GOL {optional arguements} 18 | ``` 19 | 20 | ### Possible Optional Arguements 21 | To pass an optional arguement when running GOL-C, simply add the arguement when running the above. 22 | 23 | ```console 24 | -e {Number of evolutions e.g 100} (Number of steps to evolve for (default 100)) 25 | -t {Nanoseconds between evolutions e.g 20000} (Number of seconds between each evolution (default 20000)) 26 | -s {Random seed value e.g 100} (The random seed to use to generate the initial cells (default 1)) 27 | -c {ASCII character e.g B} (The ASCII character used to represent a living cell (default O)) 28 | -g (whether to set the initial state as a glider gun) 29 | ``` 30 | 31 | ## Additional Notes 32 | Conway's Game of Life is a well known problem in the area of cellular automata. 33 | 34 | It was shown to be Turing Complete (meaning it can simulate any Turing Machine) when Paul Rendenll built a Turing Machine using a pre-defined board state in [2001](https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.386.7806&rep=rep1&type=pdf]). 35 | 36 | By regarding Gliders as 'bits' and a collection of patterns (glider guns, glider eaters and more), it's possible to emulate logic gates and memory latches. Try running the application in this repository with the *-g* option to see a glider gun in action! 37 | 38 | ## TODO 39 | - [ ] Allow user to specify initial state 40 | - [ ] Allow user to choose cell colour 41 | - [ ] Allow user to specify board size 42 | - [ ] Use half-block characters or unicode braille to improve quality 43 | - [ ] Improve makefile 44 | -------------------------------------------------------------------------------- /images/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlynnOwen/GOL-C/4f2637ab516ee269010f3ed4c3cb30fe59d4bb77/images/.DS_Store -------------------------------------------------------------------------------- /images/GOLc.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlynnOwen/GOL-C/4f2637ab516ee269010f3ed4c3cb30fe59d4bb77/images/GOLc.gif --------------------------------------------------------------------------------