aboutsummaryrefslogtreecommitdiff
path: root/internal/game/cmd_room_insert.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/game/cmd_room_insert.go')
-rw-r--r--internal/game/cmd_room_insert.go91
1 files changed, 23 insertions, 68 deletions
diff --git a/internal/game/cmd_room_insert.go b/internal/game/cmd_room_insert.go
index 988cd08..b72591f 100644
--- a/internal/game/cmd_room_insert.go
+++ b/internal/game/cmd_room_insert.go
@@ -65,53 +65,42 @@ func (g *Game) roomInsert(sess *net.Session, args []string) {
oppositeDir := world.OppositeExit[dir]
- if delta3D, ok := world.DirectionDeltas3D[dir]; ok {
- coord, roomAt := g.buildGridFrom(p.RoomID)
-
- sSet := g.bfsReachable(targetID, func(_ int, _ world.ExitDir, target int) bool {
- return target == p.RoomID
- })
+ newID, err := findNextRoomID(curPath)
+ if err != nil {
+ sess.WriteLine("Error scanning room directory.")
+ return
+ }
- withoutEdge := g.bfsReachable(p.RoomID, func(rid int, d world.ExitDir, target int) bool {
- return rid == p.RoomID && d == dir && target == targetID
- })
- for rid := range sSet {
- if withoutEdge[rid] {
- room, _ := g.World.LoadRoom(rid)
- conflictName := fmt.Sprintf("#%d", rid)
+ conflicts := world.InsertGridConflicts(p.RoomID, dir, targetID, newID, func(id int) (*world.Room, bool) {
+ r, err := g.World.LoadRoom(id)
+ if err != nil {
+ return nil, false
+ }
+ return r, true
+ })
+ if len(conflicts) > 0 {
+ for _, c := range conflicts {
+ switch c.Kind {
+ case "twist":
+ room, _ := g.World.LoadRoom(c.Target)
+ conflictName := fmt.Sprintf("#%d", c.Target)
if room != nil {
- conflictName = fmt.Sprintf("#%d (%s)", rid, room.Name)
+ conflictName = fmt.Sprintf("#%d (%s)", c.Target, room.Name)
}
sess.WriteLine(fmt.Sprintf(
"Cannot insert: room %s would have an ambiguous grid position after insertion (reachable via an alternate path from here).",
conflictName))
- return
- }
- }
-
- for rid := range sSet {
- if _, inGrid := coord[rid]; !inGrid {
- continue
- }
- oldPos := coord[rid]
- newPos := [3]int{oldPos[0] + delta3D[0], oldPos[1] + delta3D[1], oldPos[2] + delta3D[2]}
- if occupier, ok := roomAt[newPos]; ok && !sSet[occupier] {
- occRoom, _ := g.World.LoadRoom(occupier)
- occName := fmt.Sprintf("#%d", occupier)
+ case "overlap":
+ occRoom, _ := g.World.LoadRoom(c.Occupier)
+ occName := fmt.Sprintf("#%d", c.Occupier)
if occRoom != nil {
- occName = fmt.Sprintf("#%d (%s)", occupier, occRoom.Name)
+ occName = fmt.Sprintf("#%d (%s)", c.Occupier, occRoom.Name)
}
sess.WriteLine(fmt.Sprintf(
"Cannot insert: pushing %s would cause grid collision with %s.",
targetName, occName))
- return
}
}
- }
-
- newID, err := findNextRoomID(curPath)
- if err != nil {
- sess.WriteLine("Error scanning room directory.")
return
}
@@ -228,37 +217,3 @@ func (g *Game) roomInsert(sess *net.Session, args []string) {
g.runEnterSteps(sess, newID)
g.checkAggro(sess)
}
-
-// bfsReachable returns the set of rooms reachable from startID over the room
-// exit graph, restricted to known rooms. skipEdge, when non-nil, prunes an
-// individual directed exit (the edge from rid via dir to target) from the walk.
-func (g *Game) bfsReachable(startID int, skipEdge func(rid int, dir world.ExitDir, target int) bool) map[int]bool {
- roomIndex := g.World.RoomIndex()
- visited := map[int]bool{startID: true}
- queue := []int{startID}
-
- for len(queue) > 0 {
- rid := queue[0]
- queue = queue[1:]
- room, err := g.World.LoadRoom(rid)
- if err != nil {
- continue
- }
- for _, ed := range world.ExitOrder {
- exit, ok := room.Exits[ed]
- if !ok || exit.Room <= 0 || !roomIndex[exit.Room] {
- continue
- }
- target := exit.Room
- if skipEdge != nil && skipEdge(rid, ed, target) {
- continue
- }
- if visited[target] {
- continue
- }
- visited[target] = true
- queue = append(queue, target)
- }
- }
- return visited
-}