So I have this binary spaced partition leaf:
#[derive(Clone)]
pub struct Leaf {
container: Rect,
left: Option<Box<Leaf>>,
right: Option<Box<Leaf>>,
room: Option<Rect>,
split_vertical: Option<bool>,
}
impl Leaf {
fn new(container: Rect) -> Leaf {
Leaf {
container,
left: None,
right: None,
room: None,
split_vertical: None,
}
}
fn split(
&mut self,
grid: Vec<Vec<i32>>,
mut random_generator: StdRng,
min_container_size: i32,
debug_game: bool,
) -> bool {
if self.left.is_some() && self.right.is_some() {
return false;
}
let mut split_vertical: bool = random_generator.gen::<bool>();
if (self.container.width > self.container.height)
&& ((self.container.width.unwrap() / self.container.height.unwrap()) as f64 >= 1.25)
{
split_vertical = true;
} else if (self.container.height > self.container.width)
&& ((self.container.height.unwrap() / self.container.width.unwrap()) as f64 >= 1.25)
{
split_vertical = false;
}
let max_size: i32 = if split_vertical {
self.container.width.unwrap() - min_container_size
} else {
self.container.height.unwrap() - min_container_size
};
if max_size <= min_container_size {
return false;
}
let mut pos: i32 = random_generator.gen_range(min_container_size..max_size);
if split_vertical {
pos += self.container.top_left.x;
if debug_game {
println!("split vertical debug");
}
self.left = Option::from(Box::new(Leaf {
container: Rect {
top_left: Point {
x: self.container.top_left.x,
y: self.container.top_left.y,
},
bottom_right: Point {
x: pos - 1,
y: self.container.bottom_right.y,
},
center: None,
width: None,
height: None,
},
left: None,
right: None,
room: None,
split_vertical: None,
}));
self.right = Option::from(Box::new(Leaf {
container: Rect {
top_left: Point {
x: pos + 1,
y: self.container.top_left.y,
},
bottom_right: Point {
x: self.container.bottom_right.x,
y: self.container.bottom_right.y,
},
center: None,
width: None,
height: None,
},
left: None,
right: None,
room: None,
split_vertical: None,
}))
} else {
pos += self.container.top_left.y;
if debug_game {
println!("split horizontal debug");
}
self.left = Option::from(Box::new(Leaf {
container: Rect {
top_left: Point {
x: self.container.top_left.x,
y: self.container.top_left.y,
},
bottom_right: Point {
x: self.container.bottom_right.x,
y: pos - 1,
},
center: None,
width: None,
height: None,
},
left: None,
right: None,
room: None,
split_vertical: None,
}));
self.right = Option::from(Box::new(Leaf {
container: Rect {
top_left: Point {
x: self.container.top_left.x,
y: pos - 1,
},
bottom_right: Point {
x: self.container.bottom_right.x,
y: self.container.bottom_right.y,
},
center: None,
width: None,
height: None,
},
left: None,
right: None,
room: None,
split_vertical: None,
}))
}
self.split_vertical = Option::from(split_vertical);
return true;
}
fn create_room(
&mut self,
grid: Vec<Vec<i32>>,
mut random_generator: StdRng,
min_room_size: i32,
room_ratio: f32,
) -> bool {
if self.left.is_some() && self.right.is_some() {
return false;
}
let width: i32 = random_generator.gen_range(min_room_size..self.container.width.unwrap());
let height: i32 = random_generator.gen_range(min_room_size..self.container.height.unwrap());
let x_pos: i32 = random_generator
.gen_range(self.container.top_left.x..self.container.bottom_right.x - width);
let y_pos: i32 = random_generator
.gen_range(self.container.top_left.y..self.container.bottom_right.y - height);
let rect: Rect = Rect {
top_left: Point { x: x_pos, y: y_pos },
bottom_right: Point {
x: x_pos + width - 1,
y: y_pos + height - 1,
},
center: None,
width: None,
height: None,
};
if ((min(rect.width.unwrap(), rect.height.unwrap()) as f32)
/ (max(rect.width.unwrap(), rect.height.unwrap()) as f32))
< room_ratio
{
return false;
}
rect.place_rect(grid);
self.room = Option::from(rect);
return true;
}
}
And the Point
and Rect
structs:
#[derive(PartialEq, Eq, Hash, Clone, Copy)]
pub struct Point {
pub x: i32,
pub y: i32,
}
impl Point {
fn new(x: i32, y: i32) -> Point {
Point { x, y }
}
pub fn sum(&self, other: &Point) -> (i32, i32) {
(self.x + other.x, self.y + other.y)
}
pub fn abs_diff(&self, other: &Point) -> (i32, i32) {
((self.x - other.x).abs(), (self.y - other.y).abs())
}
}
#[derive(Clone)]
pub struct Rect {
pub top_left: Point,
pub bottom_right: Point,
pub center: Option<Point>,
pub width: Option<i32>,
pub height: Option<i32>,
}
impl Rect {
fn new(top_left: Point, bottom_right: Point) -> Rect {
let sum: (i32, i32) = top_left.sum(&bottom_right);
let diff: (i32, i32) = bottom_right.abs_diff(&top_left);
Rect {
top_left,
bottom_right,
center: Option::from(Point {
x: ((sum.0 as f32) / 2.0).round() as i32,
y: ((sum.1 as f32) / 2.0).round() as i32,
}),
width: Option::from(diff.0),
height: Option::from(diff.1),
}
}
pub fn get_distance_to(&self, other: &Rect) -> i32 {
return max(
(self.center.unwrap().x - other.center.unwrap().x).abs(),
(self.center.unwrap().y - other.center.unwrap().y).abs(),
);
}
pub fn place_rect(&self, grid: Vec<Vec<i32>>) {}
}
However, I'm fairly new to Rust and am not sure how to optimise this further than I already have. I know there's some repetition (especially with creating the child leafs) and wanted to know if there was a way to simplify it, speed it up, and make it more idiomatic?