98 lines
No EOL
2.9 KiB
Rust
98 lines
No EOL
2.9 KiB
Rust
use crate::city::{Rectangle, HOUSE_RANGE, House, HouseLayout, City};
|
|
|
|
pub struct Subcity {
|
|
city: City,
|
|
bought_houses: Vec<House>,
|
|
x_offset: usize,
|
|
y_offset: usize
|
|
}
|
|
|
|
impl Subcity {
|
|
pub fn city(&self) -> &City {
|
|
&self.city
|
|
}
|
|
pub fn bought_houses(&self) -> &Vec<House> {
|
|
&self.bought_houses
|
|
}
|
|
pub fn x_offset(&self) -> usize {
|
|
self.x_offset
|
|
}
|
|
pub fn y_offset(&self) -> usize {
|
|
self.y_offset
|
|
}
|
|
}
|
|
|
|
/// 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
|
|
}
|
|
} |