diff --git a/src/interact/add_delete.rs b/src/interact/add_delete.rs index 2db9b10..2ddd565 100644 --- a/src/interact/add_delete.rs +++ b/src/interact/add_delete.rs @@ -572,12 +572,11 @@ pub fn add_door_at_edge( } let corridor_cells = corridor_cells(layout, app.settings.cols, app.settings.rows); - let a_room = room_index_at_cell(&layout.rooms, edge.0); - let b_room = room_index_at_cell(&layout.rooms, edge.1); let a_in_corridor = corridor_cells.contains(&edge.0); let b_in_corridor = corridor_cells.contains(&edge.1); + let is_boundary = layout::is_room_boundary_edge(&layout.rooms, edge.0, edge.1); - if !manual_door_edge_allowed(a_room, b_room, a_in_corridor, b_in_corridor) { + if !manual_door_edge_allowed(is_boundary, a_in_corridor, b_in_corridor) { return false; } @@ -597,18 +596,11 @@ pub fn add_door_at_edge( // Checks whether manual door edge allowed. pub fn manual_door_edge_allowed( - a_room: Option, - b_room: Option, + is_room_boundary: bool, a_in_corridor: bool, b_in_corridor: bool, ) -> bool { - if matches!((a_room, b_room), (Some(a), Some(b)) if a == b) { - return false; - } - - let a_is_feature = a_room.is_some() || a_in_corridor; - let b_is_feature = b_room.is_some() || b_in_corridor; - a_is_feature || b_is_feature + is_room_boundary || a_in_corridor || b_in_corridor } // Draws add overlay. diff --git a/src/layout/utils.rs b/src/layout/utils.rs index e5cdf0a..b34c92c 100644 --- a/src/layout/utils.rs +++ b/src/layout/utils.rs @@ -201,6 +201,41 @@ pub fn shared_opening_width(a: &Room, b: &Room, span: usize, default_width: usiz default_width.max(1).min(span).min(max_width.max(1)) } +// Returns true if the edge between cell a and cell b is on the perimeter of at least one room. +pub fn is_room_boundary_edge(rooms: &[Room], a: (usize, usize), b: (usize, usize)) -> bool { + for room in rooms { + let rx_start = room.x; + let rx_end = room.x + room.width; + let ry_start = room.y; + let ry_end = room.y + room.height; + + // But since we have overlapping rooms, we check if this specific edge is one of the 4 perimeters of THIS room. + + let horizontal = a.1 == b.1 && a.0.abs_diff(b.0) == 1; + let vertical = a.0 == b.0 && a.1.abs_diff(b.1) == 1; + if horizontal { + let left = a.0.min(b.0); + let right = a.0.max(b.0); + let y = a.1; + if y >= ry_start && y < ry_end { + if right == rx_start || left == rx_end - 1 { + return true; + } + } + } else if vertical { + let top = a.1.min(b.1); + let bottom = a.1.max(b.1); + let x = a.0; + if x >= rx_start && x < rx_end { + if bottom == ry_start || top == ry_end - 1 { + return true; + } + } + } + } + false +} + // Compute the shortest grid path between two cells using BFS. pub fn shortest_path_cells( start: (usize, usize),