Skip to content

Instantly share code, notes, and snippets.

@selfawaresoup
Last active April 4, 2024 19:26
Show Gist options
  • Save selfawaresoup/e1fefabee1222048b07824261dc5759e to your computer and use it in GitHub Desktop.
Save selfawaresoup/e1fefabee1222048b07824261dc5759e to your computer and use it in GitHub Desktop.
Game of Life in C
#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