💾 Archived View for thrig.me › blog › 2024 › 03 › 11 › smolpath3.c captured on 2024-05-26 at 15:46:43.

View Raw

More Information

⬅️ Previous capture (2024-03-21)

-=-=-=-=-=-=-

// smolpath III - the search for smell (II was the "waft of khan")

#include <assert.h>
#include <stdint.h>
#include <stdio.h>

#define NO_SMELL -1
#define LOW_SMELL 0

#define MAP_LINES 15
#define MAP_COLS 9

#define MAX(a, b) (((a) > (b)) ? (a) : (b))

typedef struct {
	int xx; // "xx" is easier to find and less common than just "x"
	int yy;
} point;

// clang-format off
/* *INDENT-OFF* */
// here we "box" the target in
static int smell[MAP_LINES][MAP_COLS] = {
{ 0, 0, 0, 0,-1, 0, 0, 0, 0 },
{ 0,-1,-1, 0,-1, 0, 0, 0, 0 },
{ 0, 0,-1, 0,-1, 0, 0, 0, 0 },
{-1, 0,-1, 0,-1,-1,-1,-1, 0 },
{ 0, 0,-1, 0, 0, 0, 0, 0, 0 },
{ 0,-1,-1, 0,-1,-1,-1,-1, 0 },
{ 0, 0,-1, 0, 0, 0,-1, 0, 0 },
{-1, 0,-1, 0, 0, 0,-1, 0, 0 },
{ 0, 0,-1, 0, 0, 0,-1, 0, 0 },
{ 0,-1,-1,-1,-1,-1,-1, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{-1,-1,-1,-1,-1,-1,-1,-1, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 },
};
/* *INDENT-ON* */
// clang-format on

inline static void
smell_decrease(void)
{
	for (size_t y = 0; y < MAP_LINES; ++y) {
		for (size_t x = 0; x < MAP_COLS; ++x) {
			if (smell[y][x] < LOW_SMELL) continue;
			smell[y][x] = MAX(smell[y][x] - 1, LOW_SMELL);
		}
	}
}

inline static void
tweak_adjacent(size_t y, size_t x)
{
	const int value = MAX(smell[y][x] - 1, LOW_SMELL);
	size_t newy, newx = x;
	newy = y - 1;
	if (newy < SIZE_MAX && smell[newy][newx] >= LOW_SMELL &&
	    smell[newy][newx] < value)
		smell[newy][newx] = value;
	newy = y + 1;
	if (newy < MAP_LINES && smell[newy][newx] >= LOW_SMELL &&
	    smell[newy][newx] < value)
		smell[newy][newx] = value;
	newy = y;
	newx = x - 1;
	if (newx < SIZE_MAX && smell[newy][newx] >= LOW_SMELL &&
	    smell[newy][newx] < value)
		smell[newy][newx] = value;
	newx = x + 1;
	if (newx < MAP_COLS && smell[newy][newx] >= LOW_SMELL &&
	    smell[newy][newx] < value)
		smell[newy][newx] = value;
}

inline static void
smell_spread(void)
{
	for (size_t y = 0; y < MAP_LINES; ++y)
		for (size_t x = 0; x < MAP_COLS; ++x)
			tweak_adjacent(y, x);
	for (size_t y = MAP_LINES - 1; y < SIZE_MAX; --y)
		for (size_t x = MAP_COLS - 1; x < SIZE_MAX; --x)
			tweak_adjacent(y, x);
	smell_decrease();
}

void
smell_mark(point *origin, int amount)
{
	assert(smell[origin->yy][origin->xx] >= LOW_SMELL);
	smell[origin->yy][origin->xx] = amount;
	smell_spread();
}

void
smell_show(void)
{
	printf("%d %d\n", MAP_COLS, MAP_LINES);
	for (size_t y = 0; y < MAP_LINES; ++y) {
		for (size_t x = 0; x < MAP_COLS; ++x) {
			printf("% 3d", smell[y][x]);
		}
		putchar('\n');
	}
}

static void
smell_and_show(point *pos, int amount)
{
	smell_mark(pos, amount);
	smell_show();
	putchar('\n');
}

int
main(void)
{
	point pos;
	pos.xx = MAP_COLS / 2;
	pos.yy = MAP_LINES / 2;

	int amount = 21;

	smell_and_show(&pos, amount);

	// and make some moves to see how moving affects the spread
	pos.xx--;
	smell_and_show(&pos, amount);

	for (size_t x = 0; x < 5; ++x) {
		pos.yy--;
		smell_and_show(&pos, amount);
	}
}