drunkard, and prefabs
This commit is contained in:
parent
35f8e4cc73
commit
fae5608d91
78
src/map_builder/drunkard.rs
Normal file
78
src/map_builder/drunkard.rs
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
use super::MapArchitect;
|
||||||
|
use crate::prelude::*;
|
||||||
|
pub struct DrunkardsWalkArchitect {}
|
||||||
|
|
||||||
|
const STAGGER_DISTANCE: usize = 400;
|
||||||
|
const NUM_TILES: usize = (SCREEN_HEIGHT * SCREEN_WIDTH) as usize;
|
||||||
|
const DESIRED_FLOOR: usize = NUM_TILES / 3;
|
||||||
|
|
||||||
|
impl MapArchitect for DrunkardsWalkArchitect {
|
||||||
|
fn new(&mut self, rng: &mut RandomNumberGenerator) -> MapBuilder {
|
||||||
|
let mut mb = MapBuilder {
|
||||||
|
map: Map::new(),
|
||||||
|
rooms: Vec::new(),
|
||||||
|
monster_spawns: Vec::new(),
|
||||||
|
player_start: Point::zero(),
|
||||||
|
amulet_start: Point::zero(),
|
||||||
|
};
|
||||||
|
mb.fill(TileType::Wall);
|
||||||
|
let center = Point::new(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);
|
||||||
|
self.drunkard(¢er, rng, &mut mb.map);
|
||||||
|
while mb
|
||||||
|
.map
|
||||||
|
.tiles
|
||||||
|
.iter()
|
||||||
|
.filter(|t| **t == TileType::Floor)
|
||||||
|
.count()
|
||||||
|
< DESIRED_FLOOR
|
||||||
|
{
|
||||||
|
self.drunkard(
|
||||||
|
&Point::new(rng.range(0, SCREEN_WIDTH), rng.range(0, SCREEN_HEIGHT)),
|
||||||
|
rng,
|
||||||
|
&mut mb.map,
|
||||||
|
);
|
||||||
|
let dijkstra_map = DijkstraMap::new(
|
||||||
|
SCREEN_WIDTH,
|
||||||
|
SCREEN_HEIGHT,
|
||||||
|
&vec![mb.map.point2d_to_index(center)],
|
||||||
|
&mb.map,
|
||||||
|
1024.0,
|
||||||
|
);
|
||||||
|
dijkstra_map
|
||||||
|
.map
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter(|(_, distance)| *distance > &2000.0)
|
||||||
|
.for_each(|(idx, _)| mb.map.tiles[idx] = TileType::Wall);
|
||||||
|
}
|
||||||
|
|
||||||
|
mb.monster_spawns = mb.spawn_monsters(¢er, rng);
|
||||||
|
mb.player_start = center;
|
||||||
|
mb.amulet_start = mb.find_most_distant();
|
||||||
|
mb
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DrunkardsWalkArchitect {
|
||||||
|
fn drunkard(&mut self, start: &Point, rng: &mut RandomNumberGenerator, map: &mut Map) {
|
||||||
|
let mut drunkard_pos = start.clone();
|
||||||
|
let mut distance_staggered = 0;
|
||||||
|
loop {
|
||||||
|
let drunk_idx = map.point2d_to_index(drunkard_pos);
|
||||||
|
map.tiles[drunk_idx] = TileType::Floor;
|
||||||
|
match rng.range(0, 4) {
|
||||||
|
0 => drunkard_pos.x -= 1,
|
||||||
|
1 => drunkard_pos.x += 1,
|
||||||
|
2 => drunkard_pos.y -= 1,
|
||||||
|
_ => drunkard_pos.y += 1,
|
||||||
|
}
|
||||||
|
if !map.in_bounds(drunkard_pos) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
distance_staggered += 1;
|
||||||
|
if distance_staggered > STAGGER_DISTANCE {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,15 @@
|
|||||||
mod automata;
|
mod automata;
|
||||||
|
mod drunkard;
|
||||||
mod empty;
|
mod empty;
|
||||||
|
mod prefab;
|
||||||
mod rooms;
|
mod rooms;
|
||||||
|
|
||||||
use automata::AutomataArchitect;
|
use automata::AutomataArchitect;
|
||||||
|
use drunkard::DrunkardsWalkArchitect;
|
||||||
use empty::EmptyArchitect;
|
use empty::EmptyArchitect;
|
||||||
use rooms::RoomsArchitect;
|
use rooms::RoomsArchitect;
|
||||||
|
|
||||||
|
use crate::map_builder::prefab::apply_prefab;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
trait MapArchitect {
|
trait MapArchitect {
|
||||||
@ -23,9 +27,16 @@ pub struct MapBuilder {
|
|||||||
|
|
||||||
impl MapBuilder {
|
impl MapBuilder {
|
||||||
pub fn new(rng: &mut RandomNumberGenerator) -> Self {
|
pub fn new(rng: &mut RandomNumberGenerator) -> Self {
|
||||||
let mut architecht = AutomataArchitect {};
|
let mut architect: Box<dyn MapArchitect> = match rng.range(0, 3) {
|
||||||
|
0 => Box::new(DrunkardsWalkArchitect {}),
|
||||||
|
1 => Box::new(RoomsArchitect {}),
|
||||||
|
_ => Box::new(AutomataArchitect {}),
|
||||||
|
};
|
||||||
|
|
||||||
architecht.new(rng)
|
let mut mb = architect.new(rng);
|
||||||
|
apply_prefab(&mut mb, rng);
|
||||||
|
|
||||||
|
mb
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fill(&mut self, tile: TileType) {
|
fn fill(&mut self, tile: TileType) {
|
||||||
|
78
src/map_builder/prefab.rs
Normal file
78
src/map_builder/prefab.rs
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
const FORTRESS: (&str, i32, i32) = (
|
||||||
|
"
|
||||||
|
------------
|
||||||
|
---######---
|
||||||
|
---#----#---
|
||||||
|
---#-M--#---
|
||||||
|
-###----###-
|
||||||
|
--M---------
|
||||||
|
-###----###-
|
||||||
|
---#----#---
|
||||||
|
---#----#---
|
||||||
|
---######---
|
||||||
|
------------
|
||||||
|
",
|
||||||
|
12,
|
||||||
|
11,
|
||||||
|
);
|
||||||
|
|
||||||
|
pub fn apply_prefab(mb: &mut MapBuilder, rng: &mut RandomNumberGenerator) {
|
||||||
|
let mut placement = None;
|
||||||
|
let dijkstra_map = DijkstraMap::new(
|
||||||
|
SCREEN_WIDTH,
|
||||||
|
SCREEN_HEIGHT,
|
||||||
|
&vec![mb.map.point2d_to_index(mb.player_start)],
|
||||||
|
&mb.map,
|
||||||
|
1024.0,
|
||||||
|
);
|
||||||
|
let mut attempts = 0;
|
||||||
|
while placement.is_none() && attempts < 10 {
|
||||||
|
let dimensions = Rect::with_size(
|
||||||
|
rng.range(0, SCREEN_WIDTH - FORTRESS.1),
|
||||||
|
rng.range(0, SCREEN_HEIGHT - FORTRESS.2),
|
||||||
|
FORTRESS.1,
|
||||||
|
FORTRESS.2,
|
||||||
|
);
|
||||||
|
let mut can_place = false;
|
||||||
|
dimensions.for_each(|pt| {
|
||||||
|
let idx = mb.map.point2d_to_index(pt);
|
||||||
|
let distance = dijkstra_map.map[idx];
|
||||||
|
if distance < 2000.0 && distance > 20.0 && mb.amulet_start != pt {
|
||||||
|
can_place = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if can_place {
|
||||||
|
placement = Some(Point::new(dimensions.x1, dimensions.y1));
|
||||||
|
let points = dimensions.point_set();
|
||||||
|
mb.monster_spawns.retain(|pt| !points.contains(pt));
|
||||||
|
}
|
||||||
|
attempts += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(placement) = placement {
|
||||||
|
let string_vec: Vec<char> = FORTRESS
|
||||||
|
.0
|
||||||
|
.chars()
|
||||||
|
.filter(|a| *a != '\r' && *a != '\n')
|
||||||
|
.collect();
|
||||||
|
let mut i = 0;
|
||||||
|
for ty in placement.y..placement.y + FORTRESS.2 {
|
||||||
|
for tx in placement.x..placement.x + FORTRESS.1 {
|
||||||
|
let idx = map_idx(tx, ty);
|
||||||
|
let c = string_vec[i];
|
||||||
|
match c {
|
||||||
|
'M' => {
|
||||||
|
mb.map.tiles[idx] = TileType::Floor;
|
||||||
|
mb.monster_spawns.push(Point::new(tx, ty));
|
||||||
|
}
|
||||||
|
'-' => mb.map.tiles[idx] = TileType::Floor,
|
||||||
|
'#' => mb.map.tiles[idx] = TileType::Wall,
|
||||||
|
_ => println!("No idea what to do with [{}]", c),
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user