]> git.friedersdorff.com Git - max/gol.git/commitdiff
First working implementation master
authorMaximilian Friedersdorff <max@friedersdorff.com>
Wed, 5 Apr 2017 15:56:21 +0000 (16:56 +0100)
committerMaximilian Friedersdorff <max@friedersdorff.com>
Wed, 5 Apr 2017 15:56:21 +0000 (16:56 +0100)
array.c
array.h
gol.c
tick.c

diff --git a/array.c b/array.c
index c70c5707a08a295a5ed600f43073bfdaadd52e18..751bdfbe8a40646bc983184f3a56b6f357227450 100644 (file)
--- a/array.c
+++ b/array.c
@@ -1,34 +1,42 @@
 #include <stddef.h>
 #include <stdlib.h>
+#include <stdio.h>
 #include <string.h>
 #include "array.h"
 
 /*
  * Implements a linear search.
  */
-int gol_is_live(struct gol_board *const state, int_least32_t x, int_least32_t y)
+int gol_is_live(struct gol_board *const state, int_least32_t x, int_least32_t y,
+       char *is_live)
 {
        for (unsigned int i = 0; i < state->n; i += 2) {
                if (state->live_cells[i] == x &&
                        state->live_cells[i+1] == y) {
+                       *is_live = 1;
                        return 1;
                }
        }
-       return 0;
+       *is_live = 0;
+       return 1;
 }
 
+/*
+ *  Return values of 0 represent irrecoverable errors. 1 is a success.
+ */
 int gol_vivify(struct gol_board *const state, int_least32_t x, int_least32_t y)
 {
        int_least32_t *tmp_cells = NULL;
        size_t tmp_size = 0;
+
        if (state->n == state->size) {
                tmp_size = 2 * state->size;
-               tmp_cells = malloc(tmp_size * sizeof(typeof(tmp_cells)));
+               tmp_cells = malloc(tmp_size * sizeof(int_least32_t));
                if (!tmp_cells) {
-                       return 1;
+                       return 0;
                }
                memcpy(tmp_cells, state->live_cells,
-                       tmp_size * sizeof(typeof(tmp_cells)));
+                       state->size * sizeof(int_least32_t));
                state->size = tmp_size;
                free(state->live_cells);
                state->live_cells = tmp_cells;
@@ -50,5 +58,6 @@ int gol_vivify(struct gol_board *const state, int_least32_t x, int_least32_t y)
        } else if (y < state->min_y) {
                state->min_y = y;
        }
+
        return 1;
 }
diff --git a/array.h b/array.h
index 4cbadce0680b4ac767a303e9997fa86e266e59f0..dad89ba3c9bcdd88aa82ab33efb836436d027dc9 100644 (file)
--- a/array.h
+++ b/array.h
@@ -23,7 +23,7 @@ struct gol_board {
 /*
  * Check that a cell located at (x,y) in the game board is live.
  */
-int gol_is_live(struct gol_board *state, int_least32_t x, int_least32_t y);
+int gol_is_live(struct gol_board *state, int_least32_t x, int_least32_t y, char *is_live);
 
 /*
  * Append the coordinates of the live cell to the array.
diff --git a/gol.c b/gol.c
index ebdbba0cb680f24a1e2cbf9628b3a54a2edee443..a0c570534572251613531d82579374c82a997d74 100644 (file)
--- a/gol.c
+++ b/gol.c
@@ -3,23 +3,31 @@
 #include "array.h"
 #include "tick.h"
 
+const int ZOOM_LEVELS[10] = {1, 2, 3, 5, 8, 12, 20, 30};
+const unsigned int MAX_ZOOM_LEVEL = 7;
+
+struct viewport {
+       int origin_x;
+       int origin_y;
+       int zoom_level;
+};
+
 void quit(int e_st)
 {
        SDL_Quit();
        exit(e_st);
 }
 
-void simulate(struct gol_board *state, SDL_Surface *screen, SDL_Window *window);
+int redraw_screen(struct gol_board *state, SDL_Surface *screen, struct viewport viewport);
 
-int redraw_screen(struct gol_board *state, SDL_Surface *screen, int ppc,
-       int origin_x, int origin_y);
+int handle_mousedown(struct gol_board *state, struct viewport viewport, SDL_Event e);
 
 int main(int argc, char* args[])
 {
        struct gol_board state = {
                .live_cells = NULL,
                .n = 0,
-               .size = 0,
+               .size = 10,
                .max_x = 0,
                .min_x = 0,
                .max_y = 0,
@@ -29,21 +37,21 @@ int main(int argc, char* args[])
        SDL_Surface *screen = NULL;
 
        char finished = 0;
+       char tick = 0;
        char redraw = 1;
 
        // The coordinates of the cell to draw in the bottom left corner of the
        // canvas
-       int origin_x = 0;
-       int origin_y = 0;
-
-       int ppc = 10;
+       struct viewport viewport = {0, 0, 4};
 
        SDL_Event e;
 
-       //state.live_cells = malloc(10 * sizeof(typeof(*state.live_cells)));
-       //if (!state.live_cells) {
-       //      return 1;
-       //}
+       state.live_cells = malloc(10 * sizeof(int_least32_t));
+       if (!state.live_cells) {
+               return 1;
+       }
+
+       gol_vivify(&state, 10, 10);
        
        if (SDL_Init(SDL_INIT_EVERYTHING) < 0) {
                quit(1);
@@ -53,7 +61,7 @@ int main(int argc, char* args[])
                                  SDL_WINDOWPOS_UNDEFINED,
                                  SDL_WINDOWPOS_UNDEFINED,
                                  640,
-                                 320,
+                                 480,
                                  SDL_WINDOW_SHOWN);
        if (!window) {
                quit(1);
@@ -77,68 +85,64 @@ int main(int argc, char* args[])
                                        break;
                                case SDLK_PLUS:
                                case SDLK_EQUALS:
-                                       ppc *= 1.2;
+                                       if (viewport.zoom_level != MAX_ZOOM_LEVEL)
+                                               viewport.zoom_level++;
                                        redraw = 1;
                                        break;
                                case SDLK_MINUS:
                                case SDLK_UNDERSCORE:
-                                       ppc /= 1.2;
+                                       if (viewport.zoom_level != 0)
+                                               viewport.zoom_level--;
                                        redraw = 1;
                                        break;
+                               case SDLK_SPACE:
+                                       tick = 1;
                                default:
                                        break;
                                }
+                       } else if (e.type == SDL_MOUSEBUTTONDOWN) {
+                               handle_mousedown(&state, viewport, e);
+                               redraw = 1;
                        }
                }
+               if (tick) {
+                       tick = 0;
+                       gol_tick(&state);
+                       redraw = 1;
+               }
                if (redraw) {
-                       redraw_screen(&state, screen, ppc, origin_x, origin_y);
+                       redraw = 0;
+                       redraw_screen(&state, screen, viewport);
+                       SDL_UpdateWindowSurface(window);
                }
        }
 
-       // Main loop
-       // simulate(&state, screen, window);
-       
-
        SDL_DestroyWindow(window);
        quit(0);
 }
 
 
-void simulate(struct gol_board *state, SDL_Surface *screen, SDL_Window *window)
-{
-       SDL_Rect cell;
-       double ppc_x;
-       double ppc_y;
-       for (unsigned int i = 0; i < 1000; ++i) {
-               printf("Generation %d\n", i);
-               ppc_x = SCREEN_WIDTH/(state->max_x - state->min_x);
-               ppc_y = SCREEN_HEIGHT/(state->max_y - state->min_y);
-               for (unsigned int j = 0; j < state->n; j += 2) {
-                       printf("(%d, %d)\n", state->live_cells[j],
-                               state->live_cells[j + 1]);
-                       
-               }
-               printf("\n");
-               if (!gol_tick(state)) {
-                       return;
-               }
-               SDL_UpdateWindowSurface(window);
-       }
-}
-
 int redraw_screen(struct gol_board *state, SDL_Surface *screen,
-       int ppc, int origin_x, int origin_y)
+       struct viewport viewport)
 {
        SDL_Rect rect;
-       int i, j;
+       int i, j, ppc;
+       char is_live;
+
+       ppc = ZOOM_LEVELS[viewport.zoom_level];
+
+       SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 255, 255, 255));
 
-       SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0xFF, 0xFF, 0xFF));
-       for (i = origin_x; i < (screen->w/ppc) + origin_x; ++i) {
-               for (j = origin_y; j < (screen->h/ppc) + origin_y; ++j) {
-                       if (gol_is_live(state, i, j)) {
+       for (i = viewport.origin_x;
+            i < (screen->w/ppc) + viewport.origin_x;
+            ++i) {
+               for (j = viewport.origin_y;
+                    j < (screen->h/ppc) + viewport.origin_y;
+                    ++j) {
+                       if (gol_is_live(state, i, j, &is_live) && is_live) {
                                rect = (SDL_Rect) {
-                                       ((i - origin_x) * ppc),
-                                       ((j - origin_y) * ppc),
+                                       ((i - viewport.origin_x) * ppc),
+                                       ((j - viewport.origin_y) * ppc),
                                        ppc,
                                        ppc
                                };
@@ -147,4 +151,19 @@ int redraw_screen(struct gol_board *state, SDL_Surface *screen,
                        }
                }
        }
+       return 0;
+}
+
+int handle_mousedown(struct gol_board *state, struct viewport viewport, SDL_Event e)
+{
+       int x, y;
+       char is_live;
+       x = e.button.x/ZOOM_LEVELS[viewport.zoom_level] - viewport.origin_x;
+       y = e.button.y/ZOOM_LEVELS[viewport.zoom_level] - viewport.origin_y;
+
+       gol_is_live(state, x, y, &is_live);
+       if (!is_live)
+               gol_vivify(state, x, y);
+
+       return 1;
 }
diff --git a/tick.c b/tick.c
index 07cc19575d6ac8b26e93479813acd3b209ed4d8d..db98e7d9eb930524e88e08b83a61d8edac00cf4d 100644 (file)
--- a/tick.c
+++ b/tick.c
@@ -5,8 +5,12 @@
 int gol_tick(struct gol_board *state)
 {
        struct gol_board tmp_state;
+       char is_live;
+       unsigned char n_live_adj;
+       int i, j;
+
        tmp_state = (struct gol_board ) {
-               .live_cells = malloc(10 * sizeof(typeof(*tmp_state.live_cells))),
+               .live_cells = malloc(10 * sizeof(int_least32_t)),
                .n = 0,
                .size = 10,
                .max_x = 0,
@@ -14,33 +18,46 @@ int gol_tick(struct gol_board *state)
                .max_y = 0,
                .min_y = 0
        };
+
        if (!tmp_state.live_cells) {
                return 0;
        }
-       unsigned char n_live_adj;
-       for (int i = state->min_x; i < state->max_x; ++i) {
-               for (int j = state->min_y; j < state->max_y; ++j) {
-                       n_live_adj = gol_is_live(state, i - 1, j - 1) +
-                               gol_is_live(state, i, j - 1) +
-                               gol_is_live(state, i + 1, j - 1) +
-                               gol_is_live(state, i - 1, j) +
-                               gol_is_live(state, i + 1, j) +
-                               gol_is_live(state, i - 1 , j + 1) +
-                               gol_is_live(state, i, j + 1) +
-                               gol_is_live(state, i + 1, j + 1);
-                               
+
+       for (i = state->min_x - 1; i <= state->max_x + 1; ++i) {
+               for (j = state->min_y - 1; j <= state->max_y + 1; ++j) {
+                       n_live_adj = 0;
+                       gol_is_live(state, i - 1, j - 1, &is_live);
+                       n_live_adj += is_live;
+                       gol_is_live(state, i, j - 1, &is_live);
+                       n_live_adj += is_live;
+                       gol_is_live(state, i + 1, j - 1, &is_live);
+                       n_live_adj += is_live;
+                       gol_is_live(state, i - 1, j, &is_live);
+                       n_live_adj += is_live;
+                       gol_is_live(state, i + 1, j, &is_live);
+                       n_live_adj += is_live;
+                       gol_is_live(state, i - 1 , j + 1, &is_live);
+                       n_live_adj += is_live;
+                       gol_is_live(state, i, j + 1, &is_live);
+                       n_live_adj += is_live;
+                       gol_is_live(state, i + 1, j + 1, &is_live);
+                       n_live_adj += is_live;
+
                        switch (n_live_adj) {
                        case (3):
-                               gol_vivify(&tmp_state, i, j);
+                               if(!gol_vivify(&tmp_state, i, j)) {
+                                       return 0;
+                               }
+
                                break;
                        case(2):
-                               if (gol_is_live(state, i, j)) {
+                               if (gol_is_live(state, i, j, &is_live) && is_live) {
                                        gol_vivify(&tmp_state, i, j);
                                }
+                               break;
                        default:
                                break;
                        }
-                       
                }
        }
        free(state->live_cells);