summaryrefslogtreecommitdiff
path: root/life.c
diff options
context:
space:
mode:
Diffstat (limited to 'life.c')
-rwxr-xr-xlife.c142
1 files changed, 142 insertions, 0 deletions
diff --git a/life.c b/life.c
new file mode 100755
index 0000000..de8e1b8
--- /dev/null
+++ b/life.c
@@ -0,0 +1,142 @@
+#define SDL_DISABLE_IMMINTRIN_H
+#include <stdlib.h>
+#include <time.h>
+#include "SDL2/SDL.h"
+
+#define HEIGHT 80
+#define WIDTH 130
+#define SPF 1000 / 30
+
+void wrap(int *a, int w) {
+ if (*a < 0) *a = w - 1;
+ else if (*a > w - 1) *a = 0;
+}
+
+int place(int x, int y) {
+ wrap(&x, WIDTH);
+ wrap(&y, HEIGHT);
+ return x + y * WIDTH;
+}
+
+int neighbors(char *cells, int x, int y) {
+ int count = 0;
+ for (int i = -1; i <= 1; i++)
+ for (int j = -1; j <= 1; j++) {
+ if (i == 0 && j == 0) continue;
+ if (cells[place(i + x, j + y)] & 2) count++;
+ }
+ return count;
+}
+
+int resize(SDL_Renderer *r) {
+ int w, h;
+ SDL_GetRendererOutputSize(r, &w, &h);
+ return w / WIDTH < h / HEIGHT ? w / WIDTH : h / HEIGHT;
+}
+
+char inside(int n, char *v) {
+ char result = 0;
+ if (n >= 0 && n <= 8)
+ for (int i = 0; i < strlen(v); i++) {
+ result |= (n == v[i] - 48);
+ }
+ return result;
+}
+
+void init(char *cells, char random) {
+ for (int x = 0; x < WIDTH; x++) {
+ for (int y = 0; y < HEIGHT; y++) {
+ if (random) cells[place(x, y)] ^= 3 * (rand() % 2);
+ else cells[place(x, y)] = 0;
+ }
+ }
+}
+
+int main(int argc, char **argv) {
+ if (argc != 3) exit(1);
+ srand(time(0));
+ SDL_Init(SDL_INIT_VIDEO);
+ SDL_Window *w = SDL_CreateWindow(argv[0], 0, 0, 800, 600, SDL_WINDOW_RESIZABLE);
+ SDL_Renderer *r = SDL_CreateRenderer(w, -1, SDL_RENDERER_ACCELERATED);
+ int cellsize = resize(r);
+ int oldtime = 0;
+ int newtime = 0;
+ char paused = 0;
+ char grid = 1;
+ int symtime = 0;
+ int rendertime = 0;
+ char cells[WIDTH * HEIGHT];
+ init(cells, 1);
+ SDL_Event e;
+ while (e.type != SDL_QUIT) {
+ SDL_Delay(SPF);
+ while (SDL_PollEvent(&e)) {
+ if (e.window.event == SDL_WINDOWEVENT_RESIZED)
+ cellsize = resize(r);
+ if (e.key.state == SDL_PRESSED) {
+ if (e.key.keysym.sym == SDLK_BACKSPACE)
+ init(cells, 0);
+ if (e.key.keysym.sym == SDLK_RETURN)
+ init(cells, 1);
+ if (e.key.keysym.sym == SDLK_SPACE)
+ paused ^= 1;
+ if (e.key.keysym.sym == SDLK_PERIOD) {
+ paused = 1;
+ symtime = SPF + 1;
+ }
+ if (e.key.keysym.sym == SDLK_g) {
+ grid ^= 1;
+ }
+ }
+ int mx, my;
+ int mstate = SDL_GetMouseState(&mx, &my);
+ if (mstate & SDL_BUTTON(SDL_BUTTON_RIGHT)) {
+ cells[place(mx / cellsize, my / cellsize)] = 0;
+ paused = 1;
+ } else if (mstate & SDL_BUTTON(SDL_BUTTON_LEFT)) {
+ cells[place(mx / cellsize, my / cellsize)] = 3;
+ paused = 1;
+ }
+ };
+ oldtime = newtime;
+ newtime = SDL_GetTicks();
+ if (!paused) symtime += newtime - oldtime;
+ if (symtime > SPF) {
+ symtime = 0;
+ for (int x = 0; x < WIDTH; x++)
+ for (int y = 0; y < HEIGHT; y++) {
+ int n = neighbors(cells, x, y);
+ if (inside(n, argv[1]) && ~cells[place(x, y)] & 2)
+ cells[place(x, y)] |= 1; // Birth
+ if (!inside(n, argv[2]) && cells[place(x, y)] & 2)
+ cells[place(x, y)] &= 2; // Death
+ }
+ for (int i = 0; i < WIDTH * HEIGHT; i++)
+ cells[i] = cells[i] & 1 ? 3 : 0;
+ }
+ rendertime += newtime - oldtime;
+ if (rendertime > SPF) {
+ rendertime = 0;
+ SDL_SetRenderDrawColor(r, 160, 160, 160, 255);
+ SDL_RenderClear(r);
+ for (int x = 0; x < WIDTH; x++)
+ for (int y = 0; y < HEIGHT; y++) {
+ SDL_Rect rect = { x * cellsize, y * cellsize, cellsize, cellsize };
+ if (grid && cellsize > 1) {
+ rect.x += 1;
+ rect.y += 1;
+ rect.w -= 1;
+ rect.h -= 1;
+ }
+ if (cells[place(x, y)]) SDL_SetRenderDrawColor(r, 0, 0, 0, 255);
+ else SDL_SetRenderDrawColor(r, 255, 255, 255, 255);
+ SDL_RenderFillRect(r, &rect);
+ }
+ SDL_RenderPresent(r);
+ }
+ }
+ SDL_DestroyRenderer(r);
+ SDL_DestroyWindow(w);
+ SDL_Quit();
+ return 0;
+}