package world import ( "thehouseoficarus/internal/behavior" ) // RewriteRoomIDs remaps every genuine room-ID reference in this room per idMap // (oldID -> newID): exit targets; every Step.Teleport and Step.SpawnMob // .DespawnRooms inside on_enter/on_exit/ // on_traverse/on_use/on_look/on_kill blocks; every Condition.Room anywhere in // the room (exits, descriptions, trigger conditions, per-step conditions, // including nested all_of/any_of); and mob WanderRooms. It does NOT touch // author-chosen set_flags/set_player_flags values or condition `value:` fields // — those are not structural room references. // // idMap is assumed to be a bijection (each old ID maps to a distinct new ID); // this holds for both swap (A<->B) and rename-to-unused (A->B). Returns // whether any field was changed. func (r *Room) RewriteRoomIDs(idMap map[int]int) bool { if r == nil || len(idMap) == 0 { return false } changed := false // Exit targets + their on_traverse steps + exit/desc conditions. for dir, exit := range r.Exits { var exitChanged bool if remapInt(idMap, &exit.Room) { exitChanged = true } if remapTriggers(idMap, exit.OnTraverse) { exitChanged = true } if exit.Condition != nil && remapCondition(idMap, exit.Condition) { exitChanged = true } if exitChanged { r.Exits[dir] = exit changed = true } } // Every trigger-shaped block on the room shares the Step list + Condition // structure. Remap their steps and conditions uniformly. for i := range r.OnEnter { c := false if remapStepList(idMap, r.OnEnter[i].Steps) { c = true } if remapCondition(idMap, r.OnEnter[i].Condition) { c = true } changed = changed || c } for i := range r.OnExit { c := false if remapStepList(idMap, r.OnExit[i].Steps) { c = true } if remapCondition(idMap, r.OnExit[i].Condition) { c = true } changed = changed || c } // Conditional room descriptions carry a Condition. for i := range r.Description { if remapCondition(idMap, r.Description[i].Condition) { changed = true } } // Per-room local objects: on_use/on_look steps + object desc conditions. for i := range r.Objects { if r.Objects[i].Local != nil { loc := r.Objects[i].Local if remapTriggers(idMap, loc.OnUse) { changed = true } if remapTriggers(idMap, loc.OnLook) { changed = true } for j := range loc.Description { if remapCondition(idMap, loc.Description[j].Condition) { changed = true } } } } for i := range r.Mobs { if remapIntSlice(idMap, r.Mobs[i].WanderRooms) { changed = true } } return changed } // remapTriggers remaps step fields across a []behavior.Trigger (each trigger's // Steps + per-step Condition + trigger-level Condition). func remapTriggers(idMap map[int]int, list []behavior.Trigger) bool { changed := false for i := range list { c := false if remapStepList(idMap, list[i].Steps) { c = true } if remapCondition(idMap, list[i].Condition) { c = true } changed = changed || c } return changed } // remapStepList remaps Step.Teleport and Step.SpawnMob.DespawnRooms plus every // step's per-step Condition.Room across a single Trigger's Steps. func remapStepList(idMap map[int]int, steps []behavior.Step) bool { changed := false for i := range steps { s := &steps[i] if remapInt(idMap, &s.Teleport) { changed = true } if s.SpawnMob != nil && remapIntSlice(idMap, s.SpawnMob.DespawnRooms) { changed = true } if remapCondition(idMap, s.Condition) { changed = true } } return changed } // remapCondition walks a Condition tree and remaps any Room field (a // structural room reference) it finds, recursing into AllOf/AnyOf. func remapCondition(idMap map[int]int, c *behavior.Condition) bool { if c == nil { return false } changed := false if c.Room != 0 && remapInt(idMap, &c.Room) { changed = true } for i := range c.AllOf { if remapCondition(idMap, &c.AllOf[i]) { changed = true } } for i := range c.AnyOf { if remapCondition(idMap, &c.AnyOf[i]) { changed = true } } return changed } func remapInt(idMap map[int]int, n *int) bool { if newID, ok := idMap[*n]; ok && newID != *n { *n = newID return true } return false } func remapIntSlice(idMap map[int]int, slice []int) bool { changed := false for i := range slice { if remapInt(idMap, &slice[i]) { changed = true } } return changed }