-
Notifications
You must be signed in to change notification settings - Fork 3
Add binary space partition and random room placement algorithms for procedural generation #3
Conversation
src/binary_space_partition.rs
Outdated
| if map_subsection_min_size < map_subsection_min_room_width || map_subsection_min_size < map_subsection_min_room_height{ | ||
| map_subsection_min_size = cmp::max(map_subsection_min_room_width, map_subsection_min_room_height) + 1 | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trying to understand this logic. So if the map_subsection_min_size is less than map_subsection_min_room_width or map_subsection_min_room_width it'll be set to whatever is highest + 1.
From the sounds of it it seems like you want map_subsection_min_size to always be atleast 1 more than map_subsection_min_room_width and map_subsection_min_room_height
If that is the case then I think you might have a bug, you should be using <= not < or else you could end up in the scenario of map_subsection_min_size being equal to map_subsection_min_size
and you could also simplify this to
| if map_subsection_min_size < map_subsection_min_room_width || map_subsection_min_size < map_subsection_min_room_height{ | |
| map_subsection_min_size = cmp::max(map_subsection_min_room_width, map_subsection_min_room_height) + 1 | |
| } | |
| let map_subsection_min_size = cmp::max( | |
| map_subsection_min_size_as_str.parse::<i32>()?, | |
| cmp::max(map_subsection_min_room_width, map_subsection_min_room_height) + 1 | |
| ) |
and avoid using a mutable variable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gotcha about the mut, and updated to use your double cmp method over the if then cmp 👍
src/binary_space_partition.rs
Outdated
| let mut string = String::new(); | ||
| for room in &level.all_rooms { | ||
| let serialized = serde_json::to_string(&room).unwrap(); | ||
| let _ = write!(string, "{}", serialized); | ||
| //println!("serialized = {}", serialized); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this leftover debug code? I don't see where the string value is used!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you're right my b, got rid of it
src/binary_space_partition.rs
Outdated
| //println!("serialized = {}", serialized); | ||
| } | ||
|
|
||
| Ok(format!("{}",serde_json::to_string(&level.all_rooms)?)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| Ok(format!("{}",serde_json::to_string(&level.all_rooms)?)) | |
| serde_json::to_string(&level.all_rooms) |
serde_json::to_string already returns a Result<String>, maybe you can just return that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately just trying to return the serde_json::to_string gives me
mismatched types serde_json::Error and error::Error have similar names, but are actually distinct types
but wrapping it in an Ok()? converts the error into the appropriate error rust-g is expecting
AshCorr
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mightt be worth reviewing all your commented code and either removing it or uncommenting it! Makes it a little confusing to know whats what.
src/random_room_placement.rs
Outdated
| let max_rooms = desired_room_count as usize; | ||
| let max_attempts = 15; | ||
| let mut attempts = 0; | ||
| while self.level.all_rooms.iter().filter(|&rm| rm.room_type == 3).count() <= max_rooms && attempts <= max_attempts { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rm.room_type == 3
Could we maybe use some kind of enum for room_type? hard to know what 3 is supposed to mean!
| } | ||
|
|
||
| fn place_rooms_random(&mut self, desired_room_count: i32, rng: &mut StdRng) { | ||
| let max_rooms = desired_room_count as usize; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could you not make place_rooms_Random take a usize ? or just use an i32?
src/random_room_placement.rs
Outdated
| map.level | ||
| } | ||
|
|
||
| fn place_rooms_random(&mut self, desired_room_count: i32, rng: &mut StdRng) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tbh is it worth just making place_rooms_random a function of Level instead of creating an entirely different RandomRoomLevel struct?
src/random_room_placement.rs
Outdated
| board: Vec<Vec<i32>>, | ||
| all_rooms: Vec<Room>, | ||
| increment: i32, | ||
| //hash: String, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
still need this?
src/random_room_placement.rs
Outdated
| for _ in 0..self.height { | ||
| let space_tile = 0; | ||
| //let wall_tile = 1; | ||
| let floor_tile = 5; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe you could have a TileType enum?
src/random_room_placement.rs
Outdated
| let gen_floor_first = true; | ||
|
|
||
| let mut row = vec![floor_tile; self.width as usize]; | ||
| if !gen_floor_first { | ||
| row = vec![space_tile; self.width as usize]; | ||
| } | ||
| // if gen_floor_first { | ||
| // if index == 0 || index == self.height - 1 { | ||
| // row = vec![wall_tile; self.width as usize]; | ||
| // } | ||
|
|
||
| // row[0] = wall_tile; | ||
| // row[self.width as usize - 1] = wall_tile; | ||
| // } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like you meant to do something with gen_floor_first here?
src/random_room_placement.rs
Outdated
| let height: i32; | ||
| match *self { | ||
| RoomDimensions::Maint3x3 => height = 3, | ||
| RoomDimensions::Maint3x5 => height = 5, | ||
| RoomDimensions::Maint5x3 => height = 3, | ||
| RoomDimensions::Maint5x4 => height = 4, | ||
| RoomDimensions::Maint10x5 => height = 5, | ||
| RoomDimensions::Maint10x10 => height = 10, | ||
| } | ||
| return height + 2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| let height: i32; | |
| match *self { | |
| RoomDimensions::Maint3x3 => height = 3, | |
| RoomDimensions::Maint3x5 => height = 5, | |
| RoomDimensions::Maint5x3 => height = 3, | |
| RoomDimensions::Maint5x4 => height = 4, | |
| RoomDimensions::Maint10x5 => height = 5, | |
| RoomDimensions::Maint10x10 => height = 10, | |
| } | |
| return height + 2 | |
| match *self { | |
| RoomDimensions::Maint3x3 => 3, | |
| RoomDimensions::Maint3x5 => 5, | |
| RoomDimensions::Maint5x3 => 3, | |
| RoomDimensions::Maint5x4 => 4, | |
| RoomDimensions::Maint10x5 => 5, | |
| RoomDimensions::Maint10x10 => 10, | |
| } + 2 |
src/random_room_placement.rs
Outdated
| let width: i32; | ||
| match *self { | ||
| RoomDimensions::Maint3x3 => width = 3, | ||
| RoomDimensions::Maint3x5 => width = 3, | ||
| RoomDimensions::Maint5x3 => width = 5, | ||
| RoomDimensions::Maint5x4 => width = 5, | ||
| RoomDimensions::Maint10x5 => width = 10, | ||
| RoomDimensions::Maint10x10 => width = 10, | ||
| } | ||
| return width + 2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| let width: i32; | |
| match *self { | |
| RoomDimensions::Maint3x3 => width = 3, | |
| RoomDimensions::Maint3x5 => width = 3, | |
| RoomDimensions::Maint5x3 => width = 5, | |
| RoomDimensions::Maint5x4 => width = 5, | |
| RoomDimensions::Maint10x5 => width = 10, | |
| RoomDimensions::Maint10x10 => width = 10, | |
| } | |
| return width + 2; | |
| match *self { | |
| RoomDimensions::Maint3x3 => width = 3, | |
| RoomDimensions::Maint3x5 => width = 3, | |
| RoomDimensions::Maint5x3 => width = 5, | |
| RoomDimensions::Maint5x4 => width = 5, | |
| RoomDimensions::Maint10x5 => width = 10, | |
| RoomDimensions::Maint10x10 => width = 10, | |
| } + 2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might also want a comment for what the + 2 is for!
simplify is_leaf Co-authored-by: Ashleigh Carr <[email protected]>
I hope I'm doing this right. This is the code I've been testing with and it compiles using the default
cargo build --release --target i686-pc-windows-msvcfrom the readme so I assume that means it will work and won't destroy the server
Adds rust functions for binary space partitioning and random room placement. Currently just for my procedural maintenance generation code, but can be applied to more than that in the future, should anyone else want to use it
Binary Space Partitioning:
Basically cutting a shape in half, then that half in half, recursively until all subsections are equal to a minimum given size, or further cuts would reduce the size beneath the desired minimum

Random Room Placement:
Given an area of specified dimensions, will create rooms of varying dimensions and place them randomly in the area. The only logic applied is that the rooms fit within the boundaries of the area and don't overlap one another
Credit to https://www.jamesbaum.co.uk/blether/procedural-level-generation-rust/ for getting me started with the code I needed to make this work