From: Maximilian Friedersdorff Date: Wed, 5 Apr 2017 15:56:21 +0000 (+0100) Subject: First working implementation X-Git-Url: https://git.friedersdorff.com/?p=max%2Fgol.git;a=commitdiff_plain;h=cbeb216c0642d5774e3684ffee6cfa1c4c8cfd00 First working implementation --- diff --git a/array.c b/array.c index c70c570..751bdfb 100644 --- a/array.c +++ b/array.c @@ -1,34 +1,42 @@ #include #include +#include #include #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 4cbadce..dad89ba 100644 --- 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 ebdbba0..a0c5705 100644 --- 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 07cc195..db98e7d 100644 --- 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);