fix: corridor visibility flood-fill so connected rooms appear linked
Long L-shaped corridors had invisible middle sections because corridorVisible only checked 8 adjacent tiles for room proximity. Replace with flood-fill from room edges along corridor tiles so the entire path between connected rooms is visible. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -59,33 +59,66 @@ func roomOwnership(floor *Floor) [][]int {
|
|||||||
return owner
|
return owner
|
||||||
}
|
}
|
||||||
|
|
||||||
// corridorVisibility determines if a corridor tile should be visible.
|
// buildCorridorVisibility flood-fills corridor visibility from visible/visited rooms.
|
||||||
// A corridor is visible if it's adjacent to a visible or visited room.
|
// Returns a map of (y,x) → Visibility for all corridor tiles.
|
||||||
func corridorVisible(floor *Floor, owner [][]int, x, y int) Visibility {
|
func buildCorridorVisibility(floor *Floor, owner [][]int) [][]Visibility {
|
||||||
best := Hidden
|
vis := make([][]Visibility, floor.Height)
|
||||||
// Check neighboring tiles for room ownership
|
for y := 0; y < floor.Height; y++ {
|
||||||
for dy := -1; dy <= 1; dy++ {
|
vis[y] = make([]Visibility, floor.Width)
|
||||||
for dx := -1; dx <= 1; dx++ {
|
}
|
||||||
ny, nx := y+dy, x+dx
|
|
||||||
if ny >= 0 && ny < floor.Height && nx >= 0 && nx < floor.Width {
|
// Seed: corridor tiles adjacent to visible/visited rooms
|
||||||
ri := owner[ny][nx]
|
type pos struct{ y, x int }
|
||||||
if ri >= 0 {
|
queue := []pos{}
|
||||||
v := GetRoomVisibility(floor, ri)
|
|
||||||
if v > best {
|
for y := 0; y < floor.Height; y++ {
|
||||||
best = v
|
for x := 0; x < floor.Width; x++ {
|
||||||
|
if floor.Tiles[y][x] != TileCorridor {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
best := Hidden
|
||||||
|
for dy := -1; dy <= 1; dy++ {
|
||||||
|
for dx := -1; dx <= 1; dx++ {
|
||||||
|
ny, nx := y+dy, x+dx
|
||||||
|
if ny >= 0 && ny < floor.Height && nx >= 0 && nx < floor.Width {
|
||||||
|
ri := owner[ny][nx]
|
||||||
|
if ri >= 0 {
|
||||||
|
v := GetRoomVisibility(floor, ri)
|
||||||
|
if v > best {
|
||||||
|
best = v
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if best > Hidden {
|
||||||
|
vis[y][x] = best
|
||||||
|
queue = append(queue, pos{y, x})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flood-fill along corridor tiles (4-directional)
|
||||||
|
dirs := [4][2]int{{-1, 0}, {1, 0}, {0, -1}, {0, 1}}
|
||||||
|
for len(queue) > 0 {
|
||||||
|
cur := queue[0]
|
||||||
|
queue = queue[1:]
|
||||||
|
for _, d := range dirs {
|
||||||
|
ny, nx := cur.y+d[0], cur.x+d[1]
|
||||||
|
if ny >= 0 && ny < floor.Height && nx >= 0 && nx < floor.Width {
|
||||||
|
if floor.Tiles[ny][nx] == TileCorridor && vis[ny][nx] < vis[cur.y][cur.x] {
|
||||||
|
vis[ny][nx] = vis[cur.y][cur.x]
|
||||||
|
queue = append(queue, pos{ny, nx})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Also check along the corridor path: if this corridor connects two rooms,
|
|
||||||
// it should be visible if either room is visible/visited.
|
return vis
|
||||||
// The adjacency check above handles most cases.
|
|
||||||
return best
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// wallVisibility determines if a wall tile should be shown based on adjacent rooms.
|
// wallVisibility determines if a wall tile should be shown based on adjacent rooms/corridors.
|
||||||
func wallVisible(floor *Floor, owner [][]int, x, y int) Visibility {
|
func wallVisible(floor *Floor, owner [][]int, corrVis [][]Visibility, x, y int) Visibility {
|
||||||
best := Hidden
|
best := Hidden
|
||||||
for dy := -1; dy <= 1; dy++ {
|
for dy := -1; dy <= 1; dy++ {
|
||||||
for dx := -1; dx <= 1; dx++ {
|
for dx := -1; dx <= 1; dx++ {
|
||||||
@@ -101,9 +134,8 @@ func wallVisible(floor *Floor, owner [][]int, x, y int) Visibility {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if floor.Tiles[ny][nx] == TileCorridor {
|
if floor.Tiles[ny][nx] == TileCorridor {
|
||||||
cv := corridorVisible(floor, owner, nx, ny)
|
if corrVis[ny][nx] > best {
|
||||||
if cv > best {
|
best = corrVis[ny][nx]
|
||||||
best = cv
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -155,6 +187,9 @@ func RenderFloor(floor *Floor, currentRoom int, showFog bool) string {
|
|||||||
playerPos = [2]int{r.Y + r.H/2, r.X + r.W/2}
|
playerPos = [2]int{r.Y + r.H/2, r.X + r.W/2}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pre-compute corridor visibility via flood-fill
|
||||||
|
corrVis := buildCorridorVisibility(floor, owner)
|
||||||
|
|
||||||
buf := make([]byte, 0, floor.Width*floor.Height*4)
|
buf := make([]byte, 0, floor.Width*floor.Height*4)
|
||||||
|
|
||||||
for y := 0; y < floor.Height; y++ {
|
for y := 0; y < floor.Height; y++ {
|
||||||
@@ -173,9 +208,9 @@ func RenderFloor(floor *Floor, currentRoom int, showFog bool) string {
|
|||||||
vis = Hidden
|
vis = Hidden
|
||||||
}
|
}
|
||||||
case TileCorridor:
|
case TileCorridor:
|
||||||
vis = corridorVisible(floor, owner, x, y)
|
vis = corrVis[y][x]
|
||||||
case TileWall:
|
case TileWall:
|
||||||
vis = wallVisible(floor, owner, x, y)
|
vis = wallVisible(floor, owner, corrVis, x, y)
|
||||||
default:
|
default:
|
||||||
vis = Hidden
|
vis = Hidden
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user