use crate::city::{Rectangle, HOUSE_RANGE, House, HouseLayout, City}; pub struct Subcity { city: City, bought_houses: Vec, x_offset: usize, y_offset: usize } impl Subcity { pub fn city(&self) -> &City { &self.city } pub fn bought_houses(&self) -> &Vec { &self.bought_houses } pub fn x_offset(&self) -> usize { self.x_offset } pub fn y_offset(&self) -> usize { self.y_offset } pub fn to_full_houses(&self, subcity_houses: &Vec) -> Vec { let mut full_houses: Vec = Vec::new(); for house in subcity_houses { full_houses.push(House::new(house.x + self.x_offset, house.y + self.y_offset)) } for house in &self.bought_houses { full_houses.push(*house) } full_houses } } /// Creates a new city that is a subset of the original city. /// The provided houses and houses they cover are removed. If there is an empty margin /// around uncovered houses, it is removed - this may result in a smaller city. pub fn build_subcity(city: &City, bought_houses: &[House]) -> Subcity { let mut covered = vec![false; city.width() * city.height()]; for house in bought_houses { assert!(city.is_house(*house)); let range_rect = house.range_rectangle(city); for y in range_rect.top..=range_rect.bottom { for x in range_rect.left..=range_rect.right { covered[y as usize * city.width() + x as usize] = true; } } } // Inclusive bounds for uncovered houses in the new subcity let mut min_x = None; let mut min_y = None; let mut max_x = None; let mut max_y = None; for y in 0..city.height() { for x in 0..city.width() { if !covered[y * city.width() + x] && city.is_house_xy(x, y) { min_x = Some(min_x.unwrap_or(usize::MAX).min(x)); min_y = Some(min_y.unwrap_or(usize::MAX).min(y)); max_x = Some(max_x.unwrap_or(usize::MIN).max(x)); max_y = Some(max_x.unwrap_or(usize::MIN).max(y)); } } } if min_x.is_none() { assert!(min_y.is_none()); assert!(max_x.is_none()); assert!(max_y.is_none()); return Subcity { city: City::new(Vec::new(), 0, 0), bought_houses: bought_houses.iter().map(|&h| h).collect(), x_offset: 0, y_offset: 0, }; } let min_x = min_x.unwrap(); let min_y = min_y.unwrap(); let max_x = max_x.unwrap(); let max_y = max_y.unwrap(); let width = max_x - min_x + 1; let height = max_y - min_y + 1; let mut prices = vec![0; height * width]; for y in 0..height { for x in 0..width { let original_x = min_x + x; let original_y = min_y + y; // Copy prices for uncovered tiles, the covered tiles default to 0 - non-houses. if !covered[original_y * city.width() + original_x] { prices[y * width + x] = city.get_price_xy(original_x, original_y) } } } Subcity { city: City::new(prices, width, height), bought_houses: bought_houses.iter().map(|&h| h).collect(), x_offset: min_x, y_offset: min_y } }