updates
This commit is contained in:
parent
d77afc920b
commit
6b62b29233
3 changed files with 164 additions and 80 deletions
27
src/conf.h
27
src/conf.h
|
@ -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 },
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//====================
|
//====================
|
||||||
|
|
213
src/main.c
213
src/main.c
|
@ -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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
12
src/main.h
12
src/main.h
|
@ -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;
|
||||||
|
|
Loading…
Add table
Reference in a new issue