Last active
April 4, 2024 19:26
-
-
Save selfawaresoup/e1fefabee1222048b07824261dc5759e to your computer and use it in GitHub Desktop.
Game of Life in C
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <ncurses.h> | |
#include <signal.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
void handle_sigint(int sig) { | |
endwin(); | |
exit(0); | |
} | |
struct State { | |
int c; | |
int width; | |
int height; | |
int size; | |
unsigned int* buffer; | |
}; | |
struct State empty(struct State s) { | |
for (int i = 0 ; i < s.size; i++) { | |
s.buffer[i] = 0; | |
} | |
return s; | |
} | |
struct State initState(int width, int height) { | |
struct State s; | |
s.c = 0; | |
s.width = width; | |
s.height = height; | |
s.size = width * height; | |
s.buffer = malloc(s.size * sizeof(unsigned int)); | |
s = empty(s); | |
return s; | |
} | |
struct State fillRandom(struct State s, int seed) { | |
srand(seed); | |
for (int i = 0 ; i < s.size; i++) { | |
s.buffer[i] = rand() % 2 > 0; | |
} | |
return s; | |
} | |
struct State gliderCannon(struct State s) { | |
// Gosper's Glider Gun | |
s.buffer[1 * s.width + 26] = 1; | |
s.buffer[2 * s.width + 24] = 1; | |
s.buffer[2 * s.width + 26] = 1; | |
s.buffer[3 * s.width + 14] = 1; | |
s.buffer[3 * s.width + 15] = 1; | |
s.buffer[3 * s.width + 22] = 1; | |
s.buffer[3 * s.width + 23] = 1; | |
s.buffer[3 * s.width + 36] = 1; | |
s.buffer[3 * s.width + 37] = 1; | |
s.buffer[4 * s.width + 13] = 1; | |
s.buffer[4 * s.width + 17] = 1; | |
s.buffer[4 * s.width + 22] = 1; | |
s.buffer[4 * s.width + 23] = 1; | |
s.buffer[4 * s.width + 36] = 1; | |
s.buffer[4 * s.width + 37] = 1; | |
s.buffer[5 * s.width + 2] = 1; | |
s.buffer[5 * s.width + 3] = 1; | |
s.buffer[5 * s.width + 12] = 1; | |
s.buffer[5 * s.width + 18] = 1; | |
s.buffer[5 * s.width + 22] = 1; | |
s.buffer[5 * s.width + 23] = 1; | |
s.buffer[6 * s.width + 2] = 1; | |
s.buffer[6 * s.width + 3] = 1; | |
s.buffer[6 * s.width + 12] = 1; | |
s.buffer[6 * s.width + 16] = 1; | |
s.buffer[6 * s.width + 18] = 1; | |
s.buffer[6 * s.width + 19] = 1; | |
s.buffer[6 * s.width + 24] = 1; | |
s.buffer[6 * s.width + 26] = 1; | |
s.buffer[7 * s.width + 12] = 1; | |
s.buffer[7 * s.width + 18] = 1; | |
s.buffer[7 * s.width + 26] = 1; | |
s.buffer[8 * s.width + 13] = 1; | |
s.buffer[8 * s.width + 17] = 1; | |
s.buffer[9 * s.width + 14] = 1; | |
s.buffer[9 * s.width + 15] = 1; | |
return s; | |
} | |
struct State simpleOscillator(struct State s) { | |
s.buffer[4 * s.width + 2] = 1; | |
s.buffer[4 * s.width + 3] = 1; | |
s.buffer[4 * s.width + 4] = 1; | |
return s; | |
} | |
struct State tick(struct State s0, struct State s1) { | |
int offsets[] = { | |
-s0.width - 1, -s0.width, -s0.width + 1, | |
-1, 1, | |
s0.width - 1, s0.width, s0.width + 1 | |
}; | |
for (int i = 0; i < s0.size; i++) { | |
int alive = 0; | |
for (int o = 0; o < 8; o++) { | |
int n = (i + offsets[o]) % s0.size; | |
if (n < 0) { continue; } | |
if (s0.buffer[n]) { | |
alive++; | |
} | |
} | |
if (s0.buffer[i]) { | |
if (alive < 2) { s1.buffer[i] = 0; continue; } | |
if (alive < 4) { s1.buffer[i] = 1; continue; } | |
s1.buffer[i] = 0; | |
} else { | |
if (alive == 3) { s1.buffer[i] = 1; continue; } | |
s1.buffer[i] = 0; | |
} | |
} | |
return s1; | |
} | |
void draw(struct State s) { | |
clear(); | |
for (int i = 0; i < s.size; i++) { | |
if (s.buffer[i]) { | |
mvprintw(i / s.width, i % s.width, "#"); | |
} | |
} | |
refresh(); | |
} | |
struct State loop(struct State s0, struct State s1) { | |
draw(s0); | |
s1 = tick(s0, s1); | |
s0.c++; | |
return s1; | |
} | |
int main(int argc, char* argv[]) { | |
signal(SIGINT, handle_sigint); | |
initscr(); | |
curs_set(0); | |
int xmax, ymax; | |
getmaxyx(stdscr, ymax, xmax); | |
struct State s0 = initState(xmax, ymax); | |
struct State s1 = initState(xmax, ymax); | |
//s0 = fillRandom(s0, 3); | |
s0 = gliderCannon(s0); | |
//s0 = simpleOscillator(s0); | |
while(true) { | |
s1 = loop(s0, s1); | |
struct State temp = s0; | |
s0 = s1; | |
s1 = temp; | |
usleep(20000); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment