room accretion - initial
This commit is contained in:
parent
fa3b906dce
commit
1fa7432dfe
3 changed files with 273 additions and 0 deletions
|
|
@ -1,6 +1,8 @@
|
||||||
use super::{ spawner, Map, Position, Rect, TileType };
|
use super::{ spawner, Map, Position, Rect, TileType };
|
||||||
use bracket_lib::prelude::*;
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
|
mod room_accretion;
|
||||||
|
use room_accretion::RoomAccretionBuilder;
|
||||||
mod bsp_dungeon;
|
mod bsp_dungeon;
|
||||||
use bsp_dungeon::BspDungeonBuilder;
|
use bsp_dungeon::BspDungeonBuilder;
|
||||||
mod bsp_interior;
|
mod bsp_interior;
|
||||||
|
|
|
||||||
110
src/map_builders/room_accretion/consts.rs
Normal file
110
src/map_builders/room_accretion/consts.rs
Normal file
|
|
@ -0,0 +1,110 @@
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
use bracket_lib::prelude::*;
|
||||||
|
|
||||||
|
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<CellRules>> = vec![
|
||||||
|
vec![
|
||||||
|
CellRules::new(1, 1, Operator::GreaterThanEqualTo, 5),
|
||||||
|
CellRules::new(0, 1, Operator::LessThan, 2)
|
||||||
|
],
|
||||||
|
vec![CellRules::new(1, 1, Operator::GreaterThanEqualTo, 5)]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
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 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<Self::Item> {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
161
src/map_builders/room_accretion/mod.rs
Normal file
161
src/map_builders/room_accretion/mod.rs
Normal file
|
|
@ -0,0 +1,161 @@
|
||||||
|
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<RoomAccretionBuilder> {
|
||||||
|
Box::new(RoomAccretionBuilder {})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn grid_with_dimensions(h: usize, w: usize, value: i32) -> Vec<Vec<i32>> {
|
||||||
|
let mut grid = Vec::with_capacity(h);
|
||||||
|
for _ in 0..h {
|
||||||
|
let row = vec![value; w];
|
||||||
|
grid.push(row);
|
||||||
|
}
|
||||||
|
grid
|
||||||
|
}
|
||||||
|
|
||||||
|
fn in_bounds(x: i32, y: i32, build_data: &BuilderMap) -> bool {
|
||||||
|
x > 0 && x < build_data.height && y > 0 && y < build_data.width
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_continuous_shape_on_grid(
|
||||||
|
room: &Vec<Vec<i32>>,
|
||||||
|
top_offset: usize,
|
||||||
|
left_offset: usize,
|
||||||
|
grid: &mut Vec<Vec<i32>>
|
||||||
|
) {
|
||||||
|
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<Coordinate>, grid: &mut Vec<Vec<i32>>) {
|
||||||
|
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<Vec<i32>>,
|
||||||
|
row: usize,
|
||||||
|
col: usize,
|
||||||
|
h: usize,
|
||||||
|
w: usize
|
||||||
|
) -> Vec<i32> {
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
neighbours
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_ca_room(rng: &mut RandomNumberGenerator) -> Vec<Vec<i32>> {
|
||||||
|
let width = rng.range(5, 10);
|
||||||
|
let height = rng.range(5, 10);
|
||||||
|
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>| -> 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..height {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
cells
|
||||||
|
}
|
||||||
|
|
||||||
|
fn direction_of_door(
|
||||||
|
grid: Vec<Vec<i32>>,
|
||||||
|
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_col, new_row, &build_data) &&
|
||||||
|
in_bounds(new_col, new_row, &build_data) &&
|
||||||
|
grid[opp_row as usize][opp_col as usize] != 0
|
||||||
|
{
|
||||||
|
solution = dir;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return solution;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue