aboutsummaryrefslogtreecommitdiffstats
path: root/04-conway
diff options
context:
space:
mode:
Diffstat (limited to '04-conway')
-rw-r--r--04-conway/Makefile29
-rw-r--r--04-conway/screenshot.pngbin0 -> 1658 bytes
-rw-r--r--04-conway/src/main.c190
3 files changed, 219 insertions, 0 deletions
diff --git a/04-conway/Makefile b/04-conway/Makefile
new file mode 100644
index 0000000..d892887
--- /dev/null
+++ b/04-conway/Makefile
@@ -0,0 +1,29 @@
+CFLAGS+=-Wall -O2 $(shell pkg-config --cflags allegro-5 allegro_primitives-5 libsodium)
+CFLAGSDEBUG=-Wall -ggdb3 -O0 -DDEBUG $(shell pkg-config --cflags allegro-5 allegro_primitives-5)
+LDFLAGS+=-Wall -O2 $(shell pkg-config --libs allegro-5 allegro_primitives-5 libsodium)
+LDFLAGSDEBUG=-Wall -ggdb3 -O0 -DDEBUG $(shell pkg-config --libs allegro-5 allegro_primitives-5)
+SRCDIR=./src
+OBJDIR=./build
+SRC=$(wildcard $(SRCDIR)/*.c)
+OBJ=$(patsubst $(SRCDIR)%.c,$(OBJDIR)%.o,$(SRC))
+BIN=conway
+
+all: $(OBJ)
+ $(CC) $(LDFLAGS) -o $(BIN) $^
+
+$(OBJ): | $(OBJDIR)
+
+$(OBJDIR)/%.o: $(SRCDIR)/%.c
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+$(OBJDIR):
+ mkdir -p $(OBJDIR)
+
+clean:
+ rm -rf $(OBJDIR) $(BIN)
+
+debug: CFLAGS=$(CFLAGSDEBUG)
+debug: LDFLAGS=$(LDFLAGSDEBUG)
+debug: all
+
+new: clean all
diff --git a/04-conway/screenshot.png b/04-conway/screenshot.png
new file mode 100644
index 0000000..f262070
--- /dev/null
+++ b/04-conway/screenshot.png
Binary files differ
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;
+}