#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;
} else if (y < state->min_y) {
state->min_y = y;
}
+
return 1;
}
#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,
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);
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
640,
- 320,
+ 480,
SDL_WINDOW_SHOWN);
if (!window) {
quit(1);
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
};
}
}
}
+ 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;
}
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,
.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);