aboutsummaryrefslogtreecommitdiff
path: root/internal/admin/api_map.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/admin/api_map.go')
-rw-r--r--internal/admin/api_map.go71
1 files changed, 70 insertions, 1 deletions
diff --git a/internal/admin/api_map.go b/internal/admin/api_map.go
index e546a39..e0476b3 100644
--- a/internal/admin/api_map.go
+++ b/internal/admin/api_map.go
@@ -38,7 +38,76 @@ func (s *AdminServer) handleMap(w http.ResponseWriter, r *http.Request) {
return nil, false
}
return room, true
- }, nil, nil)
+ }, nil, func(gc world.GridConflict) {
+ if gc.Kind == "overlap" {
+ log.Printf("map: grid overlap: room %d wants cell %v already held by %d (via %d->%s)",
+ gc.Target, gc.Want, gc.Occupier, gc.From, gc.Dir)
+ }
+ })
+
+ // Discover all rooms reachable from the seed (including ones dropped by grid overlaps).
+ reachable := map[int]bool{seed: true}
+ queue := []int{seed}
+ for len(queue) > 0 {
+ id := queue[0]
+ queue = queue[1:]
+ room, err := s.world.LoadRoom(id)
+ if err != nil {
+ continue
+ }
+ for _, exit := range room.Exits {
+ if exit.Room > 0 && !reachable[exit.Room] {
+ reachable[exit.Room] = true
+ queue = append(queue, exit.Room)
+ }
+ }
+ }
+
+ // Place any reachable room missing from the grid at a nearby free cell.
+ for id := range reachable {
+ if _, ok := g.Coord[id]; ok {
+ continue
+ }
+ room, err := s.world.LoadRoom(id)
+ if err != nil {
+ continue
+ }
+ // Try adjacent to a connected neighbour already on grid.
+ for _, exit := range room.Exits {
+ if exit.Room <= 0 {
+ continue
+ }
+ nc, ok := g.Coord[exit.Room]
+ if !ok {
+ continue
+ }
+ for dx := -1; dx <= 1; dx++ {
+ for dy := -1; dy <= 1; dy++ {
+ if dx == 0 && dy == 0 {
+ continue
+ }
+ want := [3]int{nc[0] + dx, nc[1] + dy, nc[2]}
+ if _, used := g.RoomAt[want]; !used {
+ g.Coord[id] = want
+ g.RoomAt[want] = id
+ goto placed
+ }
+ }
+ }
+ }
+ // Fallback: scan a generous rectangle for a free cell.
+ for sx := -10; sx <= 10; sx++ {
+ for sy := -10; sy <= 10; sy++ {
+ want := [3]int{sx, sy, z}
+ if _, used := g.RoomAt[want]; !used {
+ g.Coord[id] = want
+ g.RoomAt[want] = id
+ goto placed
+ }
+ }
+ }
+ placed:
+ }
type RoomEntry struct {
ID int `json:"id"`