aboutsummaryrefslogtreecommitdiffstats
path: root/03-wolfrand/src
diff options
context:
space:
mode:
Diffstat (limited to '03-wolfrand/src')
-rw-r--r--03-wolfrand/src/main.c180
1 files changed, 180 insertions, 0 deletions
diff --git a/03-wolfrand/src/main.c b/03-wolfrand/src/main.c
new file mode 100644
index 0000000..5bf9578
--- /dev/null
+++ b/03-wolfrand/src/main.c
@@ -0,0 +1,180 @@
+#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 DISP_WIDTH 640
+#define DISP_HEIGHT 480
+
+#define FPS 3.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)) );
+}
+
+static void bit_toggle(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 bits[DISP_HEIGHT][DISP_WIDTH / 8];
+
+ uint8_t automaton = 0;
+ unsigned x, y;
+
+ bool pause = 0;
+
+ ALLEGRO_DISPLAY* d = 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(DISP_WIDTH, DISP_HEIGHT), "display");
+
+ 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);
+
+ al_clear_to_color(al_map_rgb(0, 0, 0));
+
+ 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_UP:
+ automaton += 10;
+ printf("%d\n", automaton);
+ break;
+
+ case ALLEGRO_KEY_DOWN:
+ automaton -= 10;
+ printf("%d\n", automaton);
+ break;
+
+ case ALLEGRO_KEY_LEFT:
+ automaton -= 1;
+ printf("%d\n", automaton);
+ break;
+
+ case ALLEGRO_KEY_RIGHT:
+ automaton += 1;
+ printf("%d\n", automaton);
+ break;
+
+ case ALLEGRO_KEY_ENTER:
+ pause = !pause;
+ printf("%s\n", pause ? "pause" : "play");
+ break;
+
+ default:
+ break;
+
+ }
+
+ break;
+
+ case ALLEGRO_EVENT_TIMER:
+
+ if (pause)
+ break;
+
+ /* seed bits */
+
+ memset(bits[1], 0, (DISP_HEIGHT - 1) * DISP_WIDTH / 8);
+
+ for (x = 1; x < DISP_WIDTH - 1; x++) {
+ if (randombytes_random() < 0x80000000)
+ bit_toggle(bits[0], x);
+ }
+
+ /* propagate */
+
+ for (y = 0; y < DISP_HEIGHT - 1; y++) {
+ for (x = 1; x < DISP_WIDTH - 2; x++) {
+ if (
+ bit_get(&automaton,
+ bit_get(bits[y], x + 2)
+ + bit_get(bits[y], x + 1) * 2
+ + bit_get(bits[y], x) * 4
+ )
+ ) {
+ bit_set(bits[y + 1], x + 1);
+ }
+ }
+ }
+
+ /* draw frame */
+
+ al_clear_to_color(al_map_rgb(0, 0, 0));
+
+ for (y = 0; y < DISP_HEIGHT; y++) {
+ for (x = 0; x < DISP_WIDTH; x++) {
+ if (bit_get(bits[y], x)) {
+ al_draw_filled_rectangle(
+ (float)x, (float)y,
+ (float)(x + 1), (float)(y + 1),
+ al_map_rgb(255, 255, 255)
+ );
+ }
+ }
+ }
+
+ al_flip_display();
+ }
+ }
+
+
+done:
+
+ if (d)
+ al_destroy_display(d);
+ if (t)
+ al_destroy_timer(t);
+ if (eq)
+ al_destroy_event_queue(eq);
+
+ return rval;
+}