This commit is contained in:
trimill 2025-01-25 00:56:46 -05:00
parent d77afc920b
commit 6b62b29233
3 changed files with 164 additions and 80 deletions

View file

@ -4,53 +4,46 @@
// Edit the definitions in this file to configure the turmite
// size of the window (pixels)
#define SCR_SIZE 800
#define SCR_SIZE 960
// size of grid cells
#define CELL_SIZE 8
#define CELL_SIZE 16
// target FPS
#define TARGET_FPS 60
// enable showcase mode - randomly cycle through
// turmites given N_STATES and N_COLORS
#define DO_SHOWCASE 0
#define DO_SHOWCASE 1
// number of ticks to simulate each turmite for
#define SHOWCASE_TIME 120
#define SHOWCASE_TIME 1800
// frames to freeze for after each showcase
#define FREEZE_FRAMES 60
#define FREEZE_FRAMES 90
// turmite iterations per frame
#define TICKS_PER_FRAME 10
#define TICKS_PER_FRAME 5
// initial turmite facing
#define INIT_DIR DIR_N
// number of states
#define N_STATES 2
#define N_STATES 3
// number of colors
#define N_COLORS 2
#define N_COLORS 3
// turmite colors
#define TURMITE_ALPHA 0xff
static uint32_t turmite_colors[N_STATES] = {
0xff2222, 0x3366ff, //0x00ff11, 0x00ddee, 0xdd11ee, 0xffff00,
0xff2222, 0x3366ff, 0x00ff11, //0x00ddee, 0xdd11ee, 0xffff00,
};
// grid colors
static uint32_t colors[N_COLORS] = {
0xffffff,
0x000000,
0x888888,
};
// transition table (not used in showcase mode)
static struct transition trans_table[N_STATES][N_COLORS] = {
{
{ 1, R, 0 },
{ 1, N, 1 },
},
{
{ 1, U, 1 },
{ 0, L, 0 },
},
};
//====================

View file

@ -1,6 +1,7 @@
#include "main.h"
#include "conf.h"
#include "raylib.h"
#include <raylib.h>
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
@ -9,23 +10,28 @@
#define GRID_SIZE (2 * VIEW_SIZE)
#define OFFSET ((GRID_SIZE - VIEW_SIZE) / 2)
struct grid {
uint8_t grid[GRID_SIZE * GRID_SIZE];
};
uint8_t grid[GRID_SIZE * GRID_SIZE];
uint8_t grid_get(int x, int y) {
return grid[x + y * GRID_SIZE];
int grid_eq(struct grid *g1, struct grid *g2) {
return 0 == memcmp(g1->grid, g2->grid, sizeof(g2->grid));
}
void grid_set(int x, int y, uint8_t val) {
grid[x + y * GRID_SIZE] = val;
uint8_t grid_get(struct grid *g, int x, int y) {
return g->grid[x + y * GRID_SIZE];
}
void draw_grid(void) {
void grid_set(struct grid *g, int x, int y, uint8_t val) {
g->grid[x + y * GRID_SIZE] = val;
}
void draw_grid(struct grid *g) {
for (int x = 0; x < VIEW_SIZE; x++) {
for (int y = 0; y < VIEW_SIZE; y++) {
int px = x * CELL_SIZE;
int py = y * CELL_SIZE;
uint8_t colno = grid_get(x + OFFSET, y + OFFSET);
uint8_t colno = grid_get(g, x + OFFSET, y + OFFSET);
Color col = GetColor(colors[colno] << 8 | 0xff);
DrawRectangle(px, py, CELL_SIZE, CELL_SIZE, col);
}
@ -38,7 +44,7 @@ void print_table(void) {
printf("\t{\n");
for (int c = 0; c < N_COLORS; c++) {
struct transition tr = trans_table[s][c];
char turn;
char turn = '?';
switch (tr.turn) {
case N: turn = 'N'; break;
case R: turn = 'R'; break;
@ -72,13 +78,34 @@ void rand_table(void) {
}
}
struct turmite {
int x;
int y;
uint8_t state;
enum dir dir;
};
void update_turmite(struct turmite *t) {
uint8_t read = grid_get(t->x, t->y);
int turmite_eq(struct turmite *t1, struct turmite *t2) {
return t1->x == t2->x
&& t1->y == t2->y
&& t1->state == t2->state
&& t1->dir == t2->dir;
}
void reset_turmite(struct turmite *t) {
t->x = OFFSET + VIEW_SIZE/2;
t->y = OFFSET + VIEW_SIZE/2;
t->state = 0;
t->dir = INIT_DIR;
}
void update_turmite(struct grid *g, struct turmite *t) {
uint8_t read = grid_get(g, t->x, t->y);
struct transition tr = trans_table[t->state][read];
grid_set(t->x, t->y, tr.write);
grid_set(g, t->x, t->y, tr.write);
t->dir = (t->dir + tr.turn) % 4;
switch (t->dir) {
case DIR_N: t->y -= 1; break;
@ -89,13 +116,8 @@ void update_turmite(struct turmite *t) {
t->state = tr.state;
}
void reset_turmite(struct turmite *t) {
memset(grid, 0, sizeof(grid));
t->x = OFFSET + VIEW_SIZE/2;
t->y = OFFSET + VIEW_SIZE/2;
t->state = 0;
t->dir = INIT_DIR;
void clear_grid(struct grid *g) {
memset(g->grid, 0, sizeof(g->grid));
}
void draw_turmite(struct turmite *t) {
@ -107,7 +129,7 @@ void draw_turmite(struct turmite *t) {
case DIR_N: oy = -CELL_SIZE*0.4; break;
case DIR_E: ox = CELL_SIZE*0.4; break;
case DIR_S: oy = CELL_SIZE*0.4; break;
case DIR_W: ox = -CELL_SIZE*0.; break;
case DIR_W: ox = -CELL_SIZE*0.4; break;
}
Vector2 v1 = { x + ox, y + oy };
Vector2 v2 = { x - ox + oy, y - ox - oy };
@ -115,70 +137,151 @@ void draw_turmite(struct turmite *t) {
DrawTriangle(v1, v2, v3, GetColor(col));
}
void draw_frame(int tick_count, struct turmite *t) {
void draw_frame(int tick_count, char *msg, struct grid *g, struct turmite *t) {
BeginDrawing();
ClearBackground(GetColor(colors[0] << 8 | 0xff));
draw_grid();
draw_grid(g);
draw_turmite(t);
DrawFPS(10, 10);
char counter[16];
snprintf(counter, 15, "t=%d", tick_count);
DrawText(counter, 10, SCR_SIZE-30, 20, GetColor(colors[1] << 8 | 0xff));
DrawText(msg, 100, 10, 20, GetColor(colors[1] << 8 | 0xff));
EndDrawing();
}
int main(void) {
InitWindow(SCR_SIZE, SCR_SIZE, "turmites");
int is_oob(struct turmite *t) {
return t->x < 0 || t->y < 0 || t->x >= GRID_SIZE || t->y >= GRID_SIZE;
}
SetTargetFPS(TARGET_FPS);
printf("\n===== turmites =====\n");
void run_showcase() {
struct grid g;
struct grid g_hare;
clear_grid(&g);
clear_grid(&g_hare);
struct turmite t;
struct turmite t_hare;
reset_turmite(&t);
int reset_timer = DO_SHOWCASE ? 0 : -1;
int tick_count = 0;
reset_turmite(&t_hare);
if (!DO_SHOWCASE) {
print_table();
}
int wait_timer = 1;
int tick_count = 0;
int running_hare = 1;
int found_cycle = 0;
char *msg = "Running";
while (!WindowShouldClose()) {
draw_frame(tick_count, &t);
draw_frame(tick_count, msg, &g, &t);
if (reset_timer == 0) {
printf("\n===== reset =====\n");
if (wait_timer > 0) {
wait_timer -= 1;
if (wait_timer != 0) {
continue;
}
printf("\n(%s)", msg);
printf("\n===== Reset =====\n");
clear_grid(&g);
clear_grid(&g_hare);
reset_turmite(&t);
reset_turmite(&t_hare);
rand_table();
print_table();
running_hare = 1;
tick_count = 0;
reset_timer = -1;
continue;
} else if (reset_timer > 0) {
reset_timer--;
continue;
} else if (reset_timer == -2) {
continue;
found_cycle = 0;
msg = "Running";
}
for (int i = 0; i < TICKS_PER_FRAME; i++) {
update_turmite(&t);
update_turmite(&g, &t);
for (int i = 0; i < 2; i++) {
if (running_hare) {
update_turmite(&g_hare, &t_hare);
if (is_oob(&t_hare)) {
running_hare = 0;
}
}
}
tick_count++;
int oob = t.x < 0 || t.y < 0 || t.x >= GRID_SIZE || t.y >= GRID_SIZE;
if (DO_SHOWCASE && (oob || tick_count >= SHOWCASE_TIME)) {
reset_timer = FREEZE_FRAMES;
if (tick_count >= SHOWCASE_TIME) {
msg = "Timeout";
wait_timer = FREEZE_FRAMES;
break;
} else if (oob) {
printf("\n===== out of bounds =====\n");
reset_timer = -2;
}
if (is_oob(&t)) {
msg = "Out of bounds";
wait_timer = FREEZE_FRAMES;
break;
}
if (turmite_eq(&t, &t_hare) && grid_eq(&g, &g_hare)) {
if (found_cycle) {
msg = "Cycle detected";
wait_timer = FREEZE_FRAMES;
break;
} else {
found_cycle = 1;
running_hare = 0;
}
}
}
}
}
void run_through() {
struct grid g;
clear_grid(&g);
struct turmite t;
reset_turmite(&t);
int tick_count = 0;
int halted = 0;
print_table();
while (!WindowShouldClose()) {
draw_frame(tick_count, "", &g, &t);
if (halted) continue;
for (int i = 0; i < TICKS_PER_FRAME; i++) {
update_turmite(&g, &t);
tick_count++;
if (is_oob(&t)) {
printf("\n===== Out of bounds =====\n");
halted = 1;
break;
}
}
}
}
int main(void) {
InitWindow(SCR_SIZE, SCR_SIZE, "Turmites");
SetTargetFPS(TARGET_FPS);
printf("\n===== Turmites =====\n");
if (DO_SHOWCASE) {
run_showcase();
} else {
run_through();
}
CloseWindow();
return 0;
}

View file

@ -13,18 +13,6 @@ enum turn {
L = 3,
};
enum mode {
ENDLESS,
SHOWCASE,
};
struct turmite {
int x;
int y;
uint8_t state;
enum dir dir;
};
struct transition {
uint8_t write;
enum turn turn;