From 30697a98bb4b4bbe3188f42ea75206929dbf22ba Mon Sep 17 00:00:00 2001 From: Llywelwyn Date: Sat, 15 Jun 2024 16:43:17 +0100 Subject: [PATCH] rm room_accretion for now --- src/map_builders/mod.rs | 11 +- src/map_builders/room_accretion/consts.rs | 127 ------- src/map_builders/room_accretion/mod.rs | 397 ---------------------- 3 files changed, 1 insertion(+), 534 deletions(-) delete mode 100644 src/map_builders/room_accretion/consts.rs delete mode 100644 src/map_builders/room_accretion/mod.rs diff --git a/src/map_builders/mod.rs b/src/map_builders/mod.rs index b9dcbfe..7b38efe 100644 --- a/src/map_builders/mod.rs +++ b/src/map_builders/mod.rs @@ -1,8 +1,6 @@ use super::{ spawner, Map, Position, Rect, TileType }; use bracket_lib::prelude::*; -mod room_accretion; -use room_accretion::RoomAccretionBuilder; mod bsp_dungeon; use bsp_dungeon::BspDungeonBuilder; mod bsp_interior; @@ -447,7 +445,7 @@ pub fn level_builder( initial_player_level: i32 ) -> BuilderChain { match id { - ID_OVERMAP => room_accretion(), + ID_OVERMAP => overmap_builder(), ID_TOWN => town_builder(id, rng, width, height, 0, initial_player_level), ID_TOWN2 => forest_builder(id, rng, width, height, 1, initial_player_level), ID_TOWN3 => @@ -492,10 +490,3 @@ pub fn level_builder( fn diff(branch_id: i32, lvl_id: i32) -> i32 { return lvl_id - branch_id; } - -fn room_accretion() -> BuilderChain { - let mut builder = BuilderChain::new(false, 110, 64, 64, 0, "room_accretion", "accretion", 0, 1); - builder.start_with(RoomAccretionBuilder::new()); - builder.with(AreaStartingPosition::new(XStart::CENTRE, YStart::CENTRE)); - builder -} diff --git a/src/map_builders/room_accretion/consts.rs b/src/map_builders/room_accretion/consts.rs deleted file mode 100644 index 8c10d16..0000000 --- a/src/map_builders/room_accretion/consts.rs +++ /dev/null @@ -1,127 +0,0 @@ -use lazy_static::lazy_static; -use bracket_lib::prelude::*; - -pub const HEIGHT: usize = 64; -pub const WIDTH: usize = 64; -pub const HALLWAY_CHANCE: f32 = 0.5; -pub const VERTICAL_CORRIDOR_MIN_LENGTH: i32 = 2; -pub const VERTICAL_CORRIDOR_MAX_LENGTH: i32 = 9; -pub const HORIZONTAL_CORRIDOR_MIN_LENGTH: i32 = 5; -pub const HORIZONTAL_CORRIDOR_MAX_LENGTH: i32 = 15; - -pub enum Operator { - LessThan, - GreaterThan, - LessThanEqualTo, - GreaterThanEqualTo, - EqualTo, -} - -impl Operator { - pub fn eval(&self, a: i32, b: i32) -> bool { - match self { - Operator::LessThan => a < b, - Operator::GreaterThan => a > b, - Operator::LessThanEqualTo => a <= b, - Operator::GreaterThanEqualTo => a >= b, - Operator::EqualTo => a == b, - } - } - pub fn string(&self) -> &str { - match self { - Operator::LessThan => "<", - Operator::GreaterThan => ">", - Operator::LessThanEqualTo => "<=", - Operator::GreaterThanEqualTo => ">=", - Operator::EqualTo => "==", - } - } -} - -pub struct CellRules { - pub adjacent_type: i32, - pub into: i32, - pub operator: Operator, - pub n: i32, -} - -impl CellRules { - const fn new(adjacent_type: i32, into: i32, operator: Operator, n: i32) -> CellRules { - CellRules { - adjacent_type, - into, - operator, - n, - } - } -} - -lazy_static! { - pub static ref CA: Vec> = vec![ - vec![CellRules::new(1, 1, Operator::GreaterThanEqualTo, 4)], - vec![ - CellRules::new(0, 0, Operator::GreaterThanEqualTo, 5), - CellRules::new(1, 0, Operator::LessThan, 2) - ] - ]; -} - -#[derive(Debug, Copy, Clone, PartialEq)] -pub enum Direction { - NoDir = -1, - North = 0, - East = 1, - South = 2, - West = 3, -} - -impl Direction { - pub fn transform(&self) -> Point { - match self { - Direction::NoDir => unreachable!("Direction::NoDir should never be transformed"), - Direction::North => Point::new(0, -1), - Direction::East => Point::new(1, 0), - Direction::South => Point::new(0, 1), - Direction::West => Point::new(-1, 0), - } - } - pub fn opposite_dir(&self) -> Direction { - match self { - Direction::NoDir => unreachable!("Direction::NoDir has no opposite."), - Direction::North => Direction::South, - Direction::East => Direction::West, - Direction::South => Direction::North, - Direction::West => Direction::East, - } - } -} - -pub struct DirectionIterator { - current: Direction, -} - -impl DirectionIterator { - pub fn new() -> DirectionIterator { - DirectionIterator { - current: Direction::North, - } - } -} - -impl Iterator for DirectionIterator { - type Item = Direction; - fn next(&mut self) -> Option { - use Direction::*; - let next_direction = match self.current { - North => East, - East => South, - South => West, - West => { - return None; - } - NoDir => unreachable!("Direction::NoDir should never be iterated over."), - }; - self.current = next_direction; - Some(next_direction) - } -} diff --git a/src/map_builders/room_accretion/mod.rs b/src/map_builders/room_accretion/mod.rs deleted file mode 100644 index 13f729b..0000000 --- a/src/map_builders/room_accretion/mod.rs +++ /dev/null @@ -1,397 +0,0 @@ -use super::{ BuilderMap, Map, InitialMapBuilder, TileType, Point }; -use bracket_lib::prelude::*; - -mod consts; -use consts::*; - -/// Room Accretion map builder. -pub struct RoomAccretionBuilder {} - -impl InitialMapBuilder for RoomAccretionBuilder { - #[allow(dead_code)] - fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) { - self.build(rng, build_data); - } -} - -impl RoomAccretionBuilder { - /// Constructor for Room Accretion. - pub fn new() -> Box { - Box::new(RoomAccretionBuilder {}) - } - - fn build(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) { - accrete_rooms(rng, build_data); - } -} - -fn grid_with_dimensions(h: usize, w: usize, value: i32) -> Vec> { - vec![vec![value; w]; h] -} - -fn in_bounds(row: i32, col: i32, build_data: &BuilderMap) -> bool { - row > 0 && row < build_data.height && col > 0 && col < build_data.width -} - -fn draw_continuous_shape_on_grid( - room: &Vec>, - top_offset: usize, - left_offset: usize, - grid: &mut Vec> -) { - for row in 0..room.len() { - for col in 0..room[0].len() { - if room[row][col] != 0 { - let target_row = row + top_offset; - let target_col = col + left_offset; - if target_row < grid.len() && target_col < grid[0].len() { - grid[target_row][target_col] = room[row][col]; - } - } - } - } -} - -struct Coordinate { - pub location: Point, - pub value: i32, -} - -fn draw_individual_coordinates_on_grid(coordinates: &Vec, grid: &mut Vec>) { - for c in coordinates { - let x = c.location.x as usize; - let y = c.location.y as usize; - if y < grid.len() && x < grid[0].len() { - grid[y][x] = c.value; - } - } -} - -fn get_cell_neighbours( - cells: &Vec>, - row: usize, - col: usize, - h: usize, - w: usize -) -> Vec { - let mut neighbours = Vec::new(); - for x in row.saturating_sub(1)..=std::cmp::min(row + 1, h - 1) { - for y in col.saturating_sub(1)..=std::cmp::min(col + 1, w - 1) { - if x != row || y != col { - neighbours.push(cells[x][y]); - } - } - } - console::log(&format!("neighbours: {:?}", neighbours)); - neighbours -} - -fn make_ca_room(rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) -> Vec> { - let width = rng.range(5, 12); - let height = rng.range(5, 12); - let mut cells = grid_with_dimensions(height, width, 0); - cells = cells - .into_iter() - .map(|row| { - row.into_iter() - .map(|_| if rng.roll_dice(1, 2) == 1 { 1 } else { 0 }) - .collect() - }) - .collect(); - - let transform_cell = |state: i32, neighbours: &Vec| -> i32 { - let rules: &[CellRules] = &CA[state as usize]; - let mut new_state = state; - for rule in rules { - let n_neighbours = neighbours - .iter() - .filter(|&&neighbour| neighbour == rule.adjacent_type) - .count(); - if rule.operator.eval(n_neighbours as i32, rule.n) { - new_state = rule.into; - } - } - new_state - }; - - for _ in 0..5 { - let mut new_cells = vec![vec![0; width]; height]; - for row in 0..height { - for col in 0..width { - let neighbours = get_cell_neighbours(&cells, row, col, height, width); - let new_state = transform_cell(cells[row][col], &neighbours); - new_cells[row][col] = new_state; - } - } - cells = new_cells; - } - // TODO: Floodfill to keep largest contiguous blob - cells -} - -fn room_fits_at( - hyperspace: Vec>, - top_offset: usize, - left_offset: usize, - build_data: &BuilderMap -) -> bool { - let mut x_dungeon: usize; - let mut y_dungeon: usize; - for y in 0..HEIGHT { - for x in 0..WIDTH { - if hyperspace[y][x] != 2 { - y_dungeon = y + top_offset; - x_dungeon = x + left_offset; - for i in y_dungeon.saturating_sub(1)..=std::cmp::min(y_dungeon + 1, WIDTH - 1) { - for j in x_dungeon.saturating_sub(1)..=std::cmp::min( - x_dungeon + 1, - HEIGHT - 1 - ) { - let pt = build_data.map.xy_idx(i as i32, j as i32); - if - !in_bounds(i as i32, j as i32, &build_data) || - !(build_data.map.tiles[pt] == TileType::Wall) || - build_data.spawn_list.contains(&(pt, "door".to_string())) - { - return false; - } - } - } - } - } - } - return true; -} - -fn direction_of_door( - grid: &Vec>, - row: usize, - col: usize, - build_data: &BuilderMap -) -> Direction { - if grid[row][col] != 0 { - return Direction::NoDir; - } - let mut solution = Direction::NoDir; - let mut dir_iter = DirectionIterator::new(); - for dir in &mut dir_iter { - let new_col = (col as i32) + dir.transform().x; - let new_row = (row as i32) + dir.transform().y; - let opp_col = (col as i32) - dir.transform().x; - let opp_row = (row as i32) - dir.transform().y; - if - in_bounds(new_row, new_col, &build_data) && - in_bounds(opp_row, opp_col, &build_data) && - grid[opp_row as usize][opp_col as usize] != 0 - { - solution = dir; - } - } - return solution; -} - -#[derive(Debug, Copy, Clone, PartialEq)] -pub struct DoorSite { - pub x: i32, - pub y: i32, - pub dir: Direction, -} - -fn choose_random_door_site( - room: Vec>, - rng: &mut RandomNumberGenerator, - build_data: &BuilderMap -) -> Vec> { - let mut grid = grid_with_dimensions(HEIGHT, WIDTH, 0); - let mut door_sites: Vec = Vec::new(); - const LEFT_OFFSET: usize = ((WIDTH as f32) / 2.0) as usize; - const TOP_OFFSET: usize = ((HEIGHT as f32) / 2.0) as usize; - draw_continuous_shape_on_grid(&room, TOP_OFFSET, LEFT_OFFSET, &mut grid); - for row in 0..HEIGHT { - for col in 0..WIDTH { - if grid[row][col] == 0 { - let door_dir = direction_of_door(&grid, row, col, &build_data); - if door_dir == Direction::NoDir { - continue; - } - let mut door_failed = false; - let (mut trace_row, mut trace_col) = ( - (row as i32) + door_dir.transform().y, - (col as i32) + door_dir.transform().x, - ); - let mut i = 0; - while i < 10 && in_bounds(trace_row, trace_col, &build_data) && !door_failed { - if grid[trace_row as usize][trace_col as usize] != 0 { - door_failed = true; - } - trace_col += door_dir.transform().x; - trace_row += door_dir.transform().y; - i += 1; - } - if !door_failed { - // May need more information here. - door_sites.push(DoorSite { - x: col as i32, - y: row as i32, - dir: door_dir, - }); - } - } - } - } - let mut chosen_doors: Vec> = vec![None; 4]; - let mut dir_iter = DirectionIterator::new(); - for dir in &mut dir_iter { - let doors_facing_this_dir: Vec<&DoorSite> = door_sites - .iter() - .filter(|&door| door.dir == dir) - .collect(); - if !doors_facing_this_dir.is_empty() { - let index = rng.range(0, doors_facing_this_dir.len()); - chosen_doors[dir as usize] = Some(*doors_facing_this_dir[index]); - } - } - chosen_doors -} - -fn shuffle(list: &mut Vec, rng: &mut RandomNumberGenerator) { - let len = list.len(); - for i in (1..len).rev() { - let j = rng.range(0, i + 1); - list.swap(i, j); - } -} - -fn clamp(x: T, min: T, max: T) -> T { - if x < min { min } else if x > max { max } else { x } -} - -fn attach_hallway_to( - door_sites: &mut Vec>, - hyperspace: &mut Vec>, - rng: &mut RandomNumberGenerator, - build_data: &BuilderMap -) { - let mut directions = vec![Direction::North, Direction::East, Direction::South, Direction::West]; - shuffle(&mut directions, rng); - let mut hallway_dir: Direction = Direction::NoDir; - for i in 0..4 { - hallway_dir = directions[i]; - if - door_sites[hallway_dir as usize].is_some() && - in_bounds( - door_sites[hallway_dir as usize].unwrap().y + - hallway_dir.transform().y * VERTICAL_CORRIDOR_MAX_LENGTH, - door_sites[hallway_dir as usize].unwrap().x + - hallway_dir.transform().x * HORIZONTAL_CORRIDOR_MAX_LENGTH, - &build_data - ) - { - break; - } - } - let transform = hallway_dir.transform(); - let hallway_len: i32 = match hallway_dir { - Direction::NoDir => { - return; - } - Direction::North | Direction::South => - rng.range(VERTICAL_CORRIDOR_MIN_LENGTH, VERTICAL_CORRIDOR_MAX_LENGTH + 1), - Direction::East | Direction::West => - rng.range(HORIZONTAL_CORRIDOR_MIN_LENGTH, HORIZONTAL_CORRIDOR_MAX_LENGTH + 1), - }; - let mut x = door_sites[hallway_dir as usize].unwrap().x; - let mut y = door_sites[hallway_dir as usize].unwrap().y; - for _i in 0..hallway_len { - if in_bounds(y, x, &build_data) { - hyperspace[y as usize][x as usize] = 1; // Dig out corridor. - } - x += transform.x; - y += transform.y; - } - - y = clamp(y - transform.y, 0, (HEIGHT as i32) - 1); - x = clamp(x - transform.x, 0, (WIDTH as i32) - 1); - - let mut dir_iter = DirectionIterator::new(); - for dir in &mut dir_iter { - if dir != hallway_dir.opposite_dir() { - let door_y = y + dir.transform().y; - let door_x = x + dir.transform().x; - door_sites[dir as usize] = Some(DoorSite { - x: door_x, - y: door_y, - dir, - }); - } else { - door_sites[dir as usize] = None; - } - } - console::log(&format!("door_sites: {:?}", door_sites)); -} - -fn design_room_in_hyperspace( - rng: &mut RandomNumberGenerator, - build_data: &mut BuilderMap -) -> Vec> { - // Project onto hyperspace - let mut hyperspace = grid_with_dimensions(HEIGHT, WIDTH, 0); - let room_type = rng.range(0, 1); - let room = match room_type { - 0 => make_ca_room(rng, build_data), - _ => unreachable!("Invalid room type."), - }; - draw_continuous_shape_on_grid(&room, HEIGHT / 2, WIDTH / 2, &mut hyperspace); - let mut door_sites = choose_random_door_site(room, rng, &build_data); - let roll: f32 = rng.rand(); - if roll < HALLWAY_CHANCE { - attach_hallway_to(&mut door_sites, &mut hyperspace, rng, &build_data); - } - let coords: Vec = door_sites - .iter() - .filter(|&door| door.is_some()) - .map(|&door| Coordinate { - location: Point::new(door.unwrap().x, door.unwrap().y), - value: 2, - }) - .collect(); - draw_individual_coordinates_on_grid(&coords, &mut hyperspace); - hyperspace -} - -fn map_i32_to_tiletype(val: i32, build_data: &mut BuilderMap) -> TileType { - match val { - 0 => TileType::Wall, - 1 => TileType::Floor, - 2 => TileType::Floor, // With door. - _ => unreachable!("Unknown TileType"), - } -} - -fn flatten_hyperspace_into_dungeon( - hyperspace: Vec>, - build_data: &mut BuilderMap -) -> Vec { - let flattened_hyperspace: Vec = hyperspace.into_iter().flatten().collect(); - flattened_hyperspace - .into_iter() - .enumerate() - .map(|(idx, cell)| { - if cell != 0 { - match cell { - 2 => build_data.spawn_list.push((idx, "door".to_string())), - _ => {} - } - map_i32_to_tiletype(cell, build_data) - } else { - build_data.map.tiles[idx % (build_data.map.width as usize)] - } - }) - .collect() -} - -fn accrete_rooms(rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) { - let hyperspace = design_room_in_hyperspace(rng, build_data); - build_data.map.tiles = flatten_hyperspace_into_dungeon(hyperspace, build_data); - build_data.take_snapshot(); -}