summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@pengaru.com>2018-12-30 17:28:04 -0800
committerVito Caputo <vcaputo@pengaru.com>2018-12-30 17:34:44 -0800
commit5f675b0b7f7b884cf67785462bfe50ab2e8099e3 (patch)
tree737dd083608b7db88019ed5f6586f6b2c118ad3f
parent2436fde1cfe091db740f15665822e18295a7f8de (diff)
modules/submit: add cellular automata game module
This module displays realtime battle for domination simulated as 2D cellular automata. This is just a test of the backend piece for a work-in-progress multiplayer game idea. The visuals were kind of interesting to watch so I figured may as well merge it as a module to share. Enjoy! PS: the results can vary a lot by tweaking the defines in submit.c
-rw-r--r--README1
-rw-r--r--configure.ac1
-rw-r--r--src/Makefile.am2
-rw-r--r--src/modules/Makefile.am2
-rw-r--r--src/modules/submit/Makefile.am3
-rw-r--r--src/modules/submit/submit.c176
-rw-r--r--src/rototiller.c2
7 files changed, 185 insertions, 2 deletions
diff --git a/README b/README
index 98f0950..beb0297 100644
--- a/README
+++ b/README
@@ -5,6 +5,7 @@ rototiller is, rendered entirely in software:
stars: a starfield simulator
plasma: an oldskool "plasma" effect
julia: a morphing Julia set (fractal)
+ submit: a 2D cellular automata game sim
---
diff --git a/configure.ac b/configure.ac
index 3b98877..9cbbfad 100644
--- a/configure.ac
+++ b/configure.ac
@@ -44,5 +44,6 @@ AC_CONFIG_FILES([
src/modules/roto/Makefile
src/modules/sparkler/Makefile
src/modules/stars/Makefile
+ src/modules/submit/Makefile
])
AC_OUTPUT
diff --git a/src/Makefile.am b/src/Makefile.am
index 08546c4..7f0b63f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -4,4 +4,4 @@ rototiller_SOURCES = fb.c fb.h fps.c fps.h rototiller.c rototiller.h sdl_fb.c se
if ENABLE_DRM
rototiller_SOURCES += drm_fb.c
endif
-rototiller_LDADD = modules/julia/libjulia.a modules/plasma/libplasma.a modules/ray/libray.a modules/roto/libroto.a modules/sparkler/libsparkler.a modules/stars/libstars.a libs/ray/libray.a -lm
+rototiller_LDADD = modules/julia/libjulia.a modules/plasma/libplasma.a modules/ray/libray.a modules/roto/libroto.a modules/sparkler/libsparkler.a modules/stars/libstars.a modules/submit/libsubmit.a libs/grid/libgrid.a libs/ray/libray.a -lm
diff --git a/src/modules/Makefile.am b/src/modules/Makefile.am
index f65ba63..8706332 100644
--- a/src/modules/Makefile.am
+++ b/src/modules/Makefile.am
@@ -1 +1 @@
-SUBDIRS = julia plasma ray roto sparkler stars
+SUBDIRS = julia plasma ray roto sparkler stars submit
diff --git a/src/modules/submit/Makefile.am b/src/modules/submit/Makefile.am
new file mode 100644
index 0000000..d8a02e4
--- /dev/null
+++ b/src/modules/submit/Makefile.am
@@ -0,0 +1,3 @@
+noinst_LIBRARIES = libsubmit.a
+libsubmit_a_SOURCES = submit.c
+libsubmit_a_CPPFLAGS = -I@top_srcdir@/src -I@top_srcdir@/src/libs
diff --git a/src/modules/submit/submit.c b/src/modules/submit/submit.c
new file mode 100644
index 0000000..9f26dc8
--- /dev/null
+++ b/src/modules/submit/submit.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2018 - Vito Caputo - <vcaputo@pengaru.com>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "fb.h"
+#include "rototiller.h"
+#include "util.h"
+
+#include "grid/grid.h"
+
+#define NUM_PLAYERS 8
+#define GRID_SIZE 60
+#define TICKS_PER_FRAME 8000
+
+static uint32_t colors[NUM_PLAYERS + 1] = {
+ 0x00000000, /* uninitialized cell starts black, becomes winner colors */
+ 0xffff5000, /* orange */
+ 0xff1020ff, /* blue */
+ 0xffe00000, /* red */
+ 0xff2ad726, /* green */
+ 0xff00e0d0, /* cyan */
+ 0xffd000ff, /* purple */
+ 0xffe7ef00, /* yellow */
+ 0x00000000, /* black */
+};
+
+typedef struct submit_context_t {
+ grid_t *grid;
+ grid_player_t *players[NUM_PLAYERS];
+ uint32_t seq;
+ uint32_t game_winner;
+ fb_fragment_t *fragment;
+ uint32_t cells[GRID_SIZE * GRID_SIZE];
+} submit_context_t;
+
+
+/* TODO: drawing is not optimized at all */
+static void draw_cell(fb_fragment_t *fragment, int x, int y, int w, int h, uint32_t color)
+{
+ for (int yy = 0; yy < h; yy++)
+ for (int xx = 0; xx < w; xx++)
+ fb_fragment_put_pixel_checked(fragment, x + xx, y + yy, color);
+}
+
+
+static void draw_grid(submit_context_t *ctxt, fb_fragment_t *fragment)
+{
+ int w = fragment->width / GRID_SIZE;
+ int h = fragment->height / GRID_SIZE;
+ int xoff = (fragment->width - w * GRID_SIZE) / 2;
+ int yoff = (fragment->height - h * GRID_SIZE) / 2;
+
+ for (int y = 0; y < GRID_SIZE; y++)
+ for (int x = 0; x < GRID_SIZE; x++)
+ draw_cell(fragment, xoff + x * w, yoff + y * h, w, h, colors[ctxt->cells[y * GRID_SIZE + x]]);
+}
+
+
+static void taken(void *ctx, uint32_t x, uint32_t y, unsigned player)
+{
+ submit_context_t *c = ctx;
+
+ assert(player);
+
+ c->cells[y * GRID_SIZE + x] = player;
+}
+
+
+static void won(void *ctx, uint32_t player)
+{
+ submit_context_t *c = ctx;
+
+ c->game_winner = player;
+}
+
+
+static grid_ops_t submit_ops = {
+ .taken = taken,
+ .won = won,
+};
+
+
+static void setup_grid(submit_context_t *ctxt)
+{
+ grid_ops_t *ops = &submit_ops;
+
+ if (ctxt->grid)
+ grid_free(ctxt->grid);
+
+ ctxt->grid = grid_new(NUM_PLAYERS, GRID_SIZE, GRID_SIZE);
+ for (int i = 0; i < NUM_PLAYERS; i++, ops = NULL)
+ ctxt->players[i] = grid_player_new(ctxt->grid, ops, ctxt);
+
+ memset(ctxt->cells, 0, sizeof(ctxt->cells));
+
+ /* this makes the transition between games less visually jarring */
+ colors[0] = colors[ctxt->game_winner];
+
+ ctxt->game_winner = ctxt->seq = 0;
+}
+
+
+static void * submit_create_context(void)
+{
+ submit_context_t *ctxt;
+
+ ctxt = calloc(1, sizeof(submit_context_t));
+ if (!ctxt)
+ return NULL;
+
+ setup_grid(ctxt);
+
+ return ctxt;
+}
+
+
+static void submit_destroy_context(void *context)
+{
+ submit_context_t *ctxt = context;
+
+ grid_free(ctxt->grid);
+ free(ctxt);
+}
+
+
+static void submit_render_fragment(void *context, fb_fragment_t *fragment)
+{
+ submit_context_t *ctxt = context;
+
+ ctxt->fragment = fragment;
+
+ if (ctxt->game_winner)
+ setup_grid(ctxt);
+
+ for (int i = 0; i < NUM_PLAYERS; i++) {
+ int moves = rand() % TICKS_PER_FRAME;
+
+ for (int j = 0; j < moves; j++)
+ grid_player_plan(ctxt->players[i], ctxt->seq++, rand() % GRID_SIZE, rand() % GRID_SIZE);
+ }
+
+ for (int j = 0; j < TICKS_PER_FRAME; j++)
+ grid_tick(ctxt->grid);
+
+ draw_grid(ctxt, fragment);
+}
+
+
+rototiller_module_t submit_module = {
+ .create_context = submit_create_context,
+ .destroy_context = submit_destroy_context,
+ .render_fragment = submit_render_fragment,
+ .name = "submit",
+ .description = "Cellular automata conquest game sim",
+ .author = "Vito Caputo <vcaputo@pengaru.com>",
+ .license = "GPLv3",
+};
diff --git a/src/rototiller.c b/src/rototiller.c
index 45bde84..ad3b215 100644
--- a/src/rototiller.c
+++ b/src/rototiller.c
@@ -38,6 +38,7 @@ extern rototiller_module_t roto64_module;
extern rototiller_module_t ray_module;
extern rototiller_module_t sparkler_module;
extern rototiller_module_t stars_module;
+extern rototiller_module_t submit_module;
static rototiller_module_t *modules[] = {
&roto32_module,
@@ -47,6 +48,7 @@ static rototiller_module_t *modules[] = {
&stars_module,
&plasma_module,
&julia_module,
+ &submit_module,
};
© All Rights Reserved