diff options
Diffstat (limited to '04-conway/src')
| -rw-r--r-- | 04-conway/src/main.c | 190 | 
1 files changed, 190 insertions, 0 deletions
diff --git a/04-conway/src/main.c b/04-conway/src/main.c new file mode 100644 index 0000000..fd591d9 --- /dev/null +++ b/04-conway/src/main.c @@ -0,0 +1,190 @@ +#include <stdlib.h> +#include <stdbool.h> +#include <stdio.h> +#include <string.h> + +#include <allegro5/allegro5.h> +#include <allegro5/allegro_primitives.h> + +#include <sodium.h> + +#define BUF_W 512 +#define BUF_H 512 + +#define SEED_BITS 4096 + +#define FPS 20.0 + +#define DO_INIT(check, desc) \ +	if (!(check)) { \ +		fprintf(stderr, "err: can't initialise %s\n", desc); \ +		rval = 1; \ +		goto done; \ +	} + +static bool bit_get(uint8_t *bline, unsigned off) +{ +	return (bline[off / 8] >> (off % 8)) & 0x01; +} + +static void bit_set(uint8_t *bline, unsigned off) +{ +	bline[off / 8] = (bline[off / 8] | (0x01 << (off % 8)) ); +} + +int main(int argc, char **argv) +{ +	int rval = 0; + +	uint8_t bits1[BUF_H][BUF_W / 8] = {0}; +	uint8_t bits2[BUF_H][BUF_W / 8] = {0}; + +	uint8_t framerate = 2; +	unsigned goframes = 1; +	unsigned x, y, sum; + +	bool pause = 1; + +	ALLEGRO_DISPLAY *d = NULL; +	ALLEGRO_BITMAP *b = NULL; +	ALLEGRO_TIMER *t = NULL; +	ALLEGRO_EVENT_QUEUE *eq = NULL; +	ALLEGRO_EVENT e; + + +	DO_INIT(sodium_init() >= 0, "sodium"); + +	DO_INIT(al_init(), "allegro"); +	DO_INIT(al_init_primitives_addon(), "primitives"); +	DO_INIT(al_install_keyboard(), "keyboard"); + +	DO_INIT(t = al_create_timer(1.0 / FPS), "timer"); +	DO_INIT(eq = al_create_event_queue(), "event queue"); + +	al_set_new_display_option(ALLEGRO_SINGLE_BUFFER, 1, ALLEGRO_REQUIRE); +	DO_INIT(d = al_create_display(2 * BUF_W, 2 * BUF_H), "display"); +	al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP); +	DO_INIT(b = al_create_bitmap(BUF_W, BUF_H), "buffer"); + +	al_register_event_source(eq, al_get_keyboard_event_source()); +	al_register_event_source(eq, al_get_display_event_source(d)); +	al_register_event_source(eq, al_get_timer_event_source(t)); + + +	al_start_timer(t); + +reset: + +	memset(bits1, 0, sizeof(bits1)); + +	for (x = 0; x < SEED_BITS; x++) { +		bit_set( +			bits1[randombytes_random() % BUF_H], +			randombytes_random() % BUF_W +		); +	} + +	while(true) { +		al_wait_for_event(eq, &e); + +		switch (e.type) { + +		case ALLEGRO_EVENT_DISPLAY_CLOSE: +			goto done; + +		case ALLEGRO_EVENT_KEY_DOWN: +			switch(e.keyboard.keycode) { + +			case ALLEGRO_KEY_1: +				puts("reset"); +				goto reset; + +			case ALLEGRO_KEY_2: +				framerate = (framerate == 1 ? 8 : framerate / 2); +				printf("fps: %.1f\n", FPS / ((float)framerate) ); +				break; + +			case ALLEGRO_KEY_ENTER: +				pause = !pause; +				printf("%s\n", pause ? "pause" : "play"); +				break; + +			default: +				break; + +			} + +			break; + +		case ALLEGRO_EVENT_TIMER: + +			if (goframes > 1) { +				goframes--; +				break; +			} + +			/* step */ + +			if (!pause) { +				memset(bits2, 0, sizeof(bits1)); + +				for (y = 0; y < BUF_H; y++) { +					for (x = 0; x < BUF_W; x++) { +						sum = +							  bit_get(bits1[(y-1) % BUF_H], (x-1) % BUF_W) +							+ bit_get(bits1[(y-1) % BUF_H],  x                ) +							+ bit_get(bits1[(y-1) % BUF_H], (x+1) % BUF_W) +							+ bit_get(bits1[ y                 ], (x-1) % BUF_W) +							+ bit_get(bits1[ y                 ], (x+1) % BUF_W) +							+ bit_get(bits1[(y+1) % BUF_H], (x-1) % BUF_W) +							+ bit_get(bits1[(y+1) % BUF_H],  x                ) +							+ bit_get(bits1[(y+1) % BUF_H], (x+1) % BUF_W) +						; + +						if (sum == 3 || (bit_get(bits1[y], x) && sum == 2)) +							bit_set(bits2[y], x); +					} +				} + +				memcpy(bits1, bits2, sizeof(bits1)); +			} + +			/* draw frame */ + +			al_lock_bitmap(b, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_WRITEONLY); + +			al_set_target_bitmap(b); + +			for (y = 0; y < BUF_H; y++) { +				for (x = 0; x < BUF_W; x++) { +					if (bit_get(bits1[y], x)) +						al_put_pixel(x, y, al_map_rgb(255, 255, 255)); +					else +						al_put_pixel(x, y, al_map_rgb(0, 0, 0)); +				} +			} + +			al_unlock_bitmap(b); + +			al_set_target_backbuffer(d); +			al_draw_scaled_bitmap(b, 0, 0, BUF_W, BUF_H, 0, 0, 2 * BUF_W, 2 * BUF_H, 0); +			al_flip_display(); + +			goframes = framerate; +		} +	} + + +done: + +	if (d) +		al_destroy_display(d); +	if (b) +		al_destroy_bitmap(b); +	if (t) +		al_destroy_timer(t); +	if (eq) +		al_destroy_event_queue(eq); +	 +	return rval; +}  | 
