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 // Edit the definitions in this file to configure the turmite
// size of the window (pixels) // size of the window (pixels)
#define SCR_SIZE 800 #define SCR_SIZE 960
// size of grid cells // size of grid cells
#define CELL_SIZE 8 #define CELL_SIZE 16
// target FPS // target FPS
#define TARGET_FPS 60 #define TARGET_FPS 60
// enable showcase mode - randomly cycle through // enable showcase mode - randomly cycle through
// turmites given N_STATES and N_COLORS // turmites given N_STATES and N_COLORS
#define DO_SHOWCASE 0 #define DO_SHOWCASE 1
// number of ticks to simulate each turmite for // number of ticks to simulate each turmite for
#define SHOWCASE_TIME 120 #define SHOWCASE_TIME 1800
// frames to freeze for after each showcase // frames to freeze for after each showcase
#define FREEZE_FRAMES 60 #define FREEZE_FRAMES 90
// turmite iterations per frame // turmite iterations per frame
#define TICKS_PER_FRAME 10 #define TICKS_PER_FRAME 5
// initial turmite facing // initial turmite facing
#define INIT_DIR DIR_N #define INIT_DIR DIR_N
// number of states // number of states
#define N_STATES 2 #define N_STATES 3
// number of colors // number of colors
#define N_COLORS 2 #define N_COLORS 3
// turmite colors // turmite colors
#define TURMITE_ALPHA 0xff #define TURMITE_ALPHA 0xff
static uint32_t turmite_colors[N_STATES] = { static uint32_t turmite_colors[N_STATES] = {
0xff2222, 0x3366ff, //0x00ff11, 0x00ddee, 0xdd11ee, 0xffff00, 0xff2222, 0x3366ff, 0x00ff11, //0x00ddee, 0xdd11ee, 0xffff00,
}; };
// grid colors // grid colors
static uint32_t colors[N_COLORS] = { static uint32_t colors[N_COLORS] = {
0xffffff, 0xffffff,
0x000000, 0x000000,
0x888888,
}; };
// transition table (not used in showcase mode) // transition table (not used in showcase mode)
static struct transition trans_table[N_STATES][N_COLORS] = { 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 "main.h"
#include "conf.h" #include "conf.h"
#include "raylib.h" #include <raylib.h>
#include <assert.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -9,23 +10,28 @@
#define GRID_SIZE (2 * VIEW_SIZE) #define GRID_SIZE (2 * VIEW_SIZE)
#define OFFSET ((GRID_SIZE - VIEW_SIZE) / 2) #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) { int grid_eq(struct grid *g1, struct grid *g2) {
return grid[x + y * GRID_SIZE]; return 0 == memcmp(g1->grid, g2->grid, sizeof(g2->grid));
} }
void grid_set(int x, int y, uint8_t val) { uint8_t grid_get(struct grid *g, int x, int y) {
grid[x + y * GRID_SIZE] = val; 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 x = 0; x < VIEW_SIZE; x++) {
for (int y = 0; y < VIEW_SIZE; y++) { for (int y = 0; y < VIEW_SIZE; y++) {
int px = x * CELL_SIZE; int px = x * CELL_SIZE;
int py = y * 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); Color col = GetColor(colors[colno] << 8 | 0xff);
DrawRectangle(px, py, CELL_SIZE, CELL_SIZE, col); DrawRectangle(px, py, CELL_SIZE, CELL_SIZE, col);
} }
@ -38,7 +44,7 @@ void print_table(void) {
printf("\t{\n"); printf("\t{\n");
for (int c = 0; c < N_COLORS; c++) { for (int c = 0; c < N_COLORS; c++) {
struct transition tr = trans_table[s][c]; struct transition tr = trans_table[s][c];
char turn; char turn = '?';
switch (tr.turn) { switch (tr.turn) {
case N: turn = 'N'; break; case N: turn = 'N'; break;
case R: turn = 'R'; 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) { int turmite_eq(struct turmite *t1, struct turmite *t2) {
uint8_t read = grid_get(t->x, t->y); 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]; 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; t->dir = (t->dir + tr.turn) % 4;
switch (t->dir) { switch (t->dir) {
case DIR_N: t->y -= 1; break; case DIR_N: t->y -= 1; break;
@ -89,13 +116,8 @@ void update_turmite(struct turmite *t) {
t->state = tr.state; t->state = tr.state;
} }
void reset_turmite(struct turmite *t) { void clear_grid(struct grid *g) {
memset(grid, 0, sizeof(grid)); memset(g->grid, 0, sizeof(g->grid));
t->x = OFFSET + VIEW_SIZE/2;
t->y = OFFSET + VIEW_SIZE/2;
t->state = 0;
t->dir = INIT_DIR;
} }
void draw_turmite(struct turmite *t) { 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_N: oy = -CELL_SIZE*0.4; break;
case DIR_E: ox = 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_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 v1 = { x + ox, y + oy };
Vector2 v2 = { x - ox + oy, y - ox - 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)); 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(); BeginDrawing();
ClearBackground(GetColor(colors[0] << 8 | 0xff)); ClearBackground(GetColor(colors[0] << 8 | 0xff));
draw_grid(); draw_grid(g);
draw_turmite(t); draw_turmite(t);
DrawFPS(10, 10); DrawFPS(10, 10);
char counter[16]; char counter[16];
snprintf(counter, 15, "t=%d", tick_count); snprintf(counter, 15, "t=%d", tick_count);
DrawText(counter, 10, SCR_SIZE-30, 20, GetColor(colors[1] << 8 | 0xff)); DrawText(counter, 10, SCR_SIZE-30, 20, GetColor(colors[1] << 8 | 0xff));
DrawText(msg, 100, 10, 20, GetColor(colors[1] << 8 | 0xff));
EndDrawing(); EndDrawing();
} }
int main(void) { int is_oob(struct turmite *t) {
InitWindow(SCR_SIZE, SCR_SIZE, "turmites"); return t->x < 0 || t->y < 0 || t->x >= GRID_SIZE || t->y >= GRID_SIZE;
SetTargetFPS(TARGET_FPS);
printf("\n===== turmites =====\n");
struct turmite t;
reset_turmite(&t);
int reset_timer = DO_SHOWCASE ? 0 : -1;
int tick_count = 0;
if (!DO_SHOWCASE) {
print_table();
} }
while (!WindowShouldClose()) { void run_showcase() {
draw_frame(tick_count, &t); struct grid g;
struct grid g_hare;
clear_grid(&g);
clear_grid(&g_hare);
if (reset_timer == 0) { struct turmite t;
printf("\n===== reset =====\n"); struct turmite t_hare;
reset_turmite(&t); reset_turmite(&t);
reset_turmite(&t_hare);
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, msg, &g, &t);
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(); rand_table();
print_table(); print_table();
running_hare = 1;
tick_count = 0; tick_count = 0;
reset_timer = -1; found_cycle = 0;
continue; msg = "Running";
} else if (reset_timer > 0) {
reset_timer--;
continue;
} else if (reset_timer == -2) {
continue;
} }
for (int i = 0; i < TICKS_PER_FRAME; i++) { 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++; 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)) { if (tick_count >= SHOWCASE_TIME) {
reset_timer = FREEZE_FRAMES; msg = "Timeout";
wait_timer = FREEZE_FRAMES;
break; 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; 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(); CloseWindow();
return 0; return 0;
} }

View file

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