bgen/src/gen/dijkstra.c
saarsena@gmail.com e45f121fb9 init
2026-04-16 21:04:50 -04:00

63 lines
2 KiB
C

#include "dijkstra.h"
#include <stddef.h>
static int passable(uint8_t t) {
return t == T_FLOOR || t == T_CORRIDOR || t == T_DOOR || t == T_BRIDGE
|| t == T_STAIRS_UP || t == T_STAIRS_DOWN;
}
void bfs_from(grid_t g, int sx, int sy, dist_map_t dist,
int extra_passable_x, int extra_passable_y) {
for (int y = 0; y < DROWS; y++)
for (int x = 0; x < DCOLS; x++)
dist[y][x] = DIST_UNREACHABLE;
if (!grid_in_bounds(sx, sy)) return;
static const int dx4[4] = {1, -1, 0, 0};
static const int dy4[4] = {0, 0, 1, -1};
int qx[DCOLS * DROWS];
int qy[DCOLS * DROWS];
int head = 0, tail = 0;
dist[sy][sx] = 0;
qx[tail] = sx; qy[tail] = sy; tail++;
while (head < tail) {
int cx = qx[head], cy = qy[head]; head++;
int16_t d = dist[cy][cx];
for (int i = 0; i < 4; i++) {
int nx = cx + dx4[i], ny = cy + dy4[i];
if (!grid_in_bounds(nx, ny)) continue;
int is_extra = (nx == extra_passable_x && ny == extra_passable_y);
if (!is_extra && !passable(g[ny][nx].terrain)) continue;
if (dist[ny][nx] <= d + 1) continue;
dist[ny][nx] = d + 1;
qx[tail] = nx; qy[tail] = ny; tail++;
}
}
}
int is_connected(grid_t g, int *out_unreached) {
int sx = -1, sy = -1, total = 0;
for (int y = 0; y < DROWS; y++) {
for (int x = 0; x < DCOLS; x++) {
if (passable(g[y][x].terrain)) {
if (sx < 0) { sx = x; sy = y; }
total++;
}
}
}
if (total == 0) { if (out_unreached) *out_unreached = 0; return 1; }
static dist_map_t dist;
bfs_from(g, sx, sy, dist, -1, -1);
int reached = 0;
for (int y = 0; y < DROWS; y++)
for (int x = 0; x < DCOLS; x++)
if (passable(g[y][x].terrain) && dist[y][x] != DIST_UNREACHABLE)
reached++;
if (out_unreached) *out_unreached = total - reached;
return reached == total;
}