├── .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
--------------------------------------------------------------------------------