swapped over to bracket-lib geometry's Rects, improved feature spawning

This commit is contained in:
Llywelwyn 2023-08-31 20:07:15 +01:00
parent 5a8114ec7e
commit fcb2bd2815
15 changed files with 217 additions and 107 deletions

View file

@ -1,8 +1,14 @@
use super::{ BuilderMap, MetaMapBuilder, Rect, TileType };
use crate::tile_walkable;
use crate::data::messages::{ FEATURE_TREANTS, FEATURE_BARRACKS_GOBLIN, FEATURE_BARRACKS_KOBOLD, FEATURE_BARRACKS_ORC };
use crate::data::messages::{
FEATURE_TREANTS,
FEATURE_BARRACKS_GOBLIN,
FEATURE_BARRACKS_KOBOLD,
FEATURE_BARRACKS_ORC,
};
use crate::raws;
use rltk::RandomNumberGenerator;
use std::collections::HashSet;
pub enum Theme {
Grass,
@ -12,6 +18,7 @@ pub enum Theme {
pub struct ThemeRooms {
pub theme: Theme,
pub percent: i32,
pub min_size: i32,
}
impl MetaMapBuilder for ThemeRooms {
@ -22,24 +29,40 @@ impl MetaMapBuilder for ThemeRooms {
impl ThemeRooms {
#[allow(dead_code)]
pub fn grass(percent: i32) -> Box<ThemeRooms> {
return Box::new(ThemeRooms { theme: Theme::Grass, percent });
pub fn grass(percent: i32, min_size: i32) -> Box<ThemeRooms> {
return Box::new(ThemeRooms { theme: Theme::Grass, percent, min_size });
}
pub fn barracks(percent: i32) -> Box<ThemeRooms> {
return Box::new(ThemeRooms { theme: Theme::Barrack, percent });
pub fn barracks(percent: i32, min_size: i32) -> Box<ThemeRooms> {
return Box::new(ThemeRooms { theme: Theme::Barrack, percent, min_size });
}
fn grassify(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap, room: &Rect) {
fn grassify(
&mut self,
rng: &mut RandomNumberGenerator,
build_data: &mut BuilderMap,
room: &Rect
) {
let (var_x, var_y) = (rng.roll_dice(1, 3), rng.roll_dice(1, 3));
let x1 = if room.x1 - var_x > 0 { room.x1 - var_x } else { room.x1 };
let x2 = if room.x2 + var_x < build_data.map.width - 1 { room.x2 + var_x } else { room.x2 };
let y1 = if room.y1 - var_y > 0 { room.y1 - var_y } else { room.y1 };
let y2 = if room.y2 + var_y < build_data.map.height - 1 { room.y2 + var_y } else { room.y2 };
let y2 = if room.y2 + var_y < build_data.map.height - 1 {
room.y2 + var_y
} else {
room.y2
};
for x in x1..x2 {
for y in y1..y2 {
let idx = build_data.map.xy_idx(x, y);
if tile_walkable(build_data.map.tiles[idx]) && build_data.map.tiles[idx] != TileType::DownStair {
let tar = if x < room.x1 || x > room.x2 || y < room.y1 || y > room.y2 { 45 } else { 90 };
if
tile_walkable(build_data.map.tiles[idx]) &&
build_data.map.tiles[idx] != TileType::DownStair
{
let tar = if x < room.x1 || x > room.x2 || y < room.y1 || y > room.y2 {
45
} else {
90
};
let roll = rng.roll_dice(1, 100);
if roll <= tar {
match rng.roll_dice(1, 6) {
@ -63,13 +86,21 @@ impl ThemeRooms {
build_data.map.messages.insert(FEATURE_TREANTS.to_string());
}
fn place_barracks(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap, room: &Rect) {
fn place_barracks(
&mut self,
rng: &mut RandomNumberGenerator,
build_data: &mut BuilderMap,
room: &Rect
) {
let mut possible: Vec<usize> = Vec::new();
let (x1, x2, y1, y2) = (room.x1 + 1, room.x2 - 1, room.y1 + 1, room.y2 - 1);
for x in x1..x2 {
for y in y1..y2 {
let idx = build_data.map.xy_idx(x, y);
if tile_walkable(build_data.map.tiles[idx]) && build_data.map.tiles[idx] != TileType::DownStair {
if
tile_walkable(build_data.map.tiles[idx]) &&
build_data.map.tiles[idx] != TileType::DownStair
{
possible.push(idx);
}
}
@ -113,15 +144,39 @@ impl ThemeRooms {
panic!("RoomCornerRounding requires a builder with rooms.");
}
for room in rooms.iter() {
if rng.roll_dice(1, 100) < self.percent {
match self.theme {
Theme::Grass => self.grassify(rng, build_data, room),
Theme::Barrack => self.place_barracks(rng, build_data, room),
_ => {}
let count = roll_until_fail(rng, self.percent);
let mut used: HashSet<usize> = HashSet::new();
for _i in 0..count {
let mut attempts = 0;
while attempts < 20 {
let room = rng.random_slice_entry(&rooms).unwrap();
let (w, h) = (room.width(), room.height());
let idx = build_data.map.xy_idx(room.x1, room.y1);
if !used.contains(&idx) && w * h >= self.min_size {
used.insert(idx);
match self.theme {
Theme::Grass => self.grassify(rng, build_data, &room),
Theme::Barrack => self.place_barracks(rng, build_data, &room),
}
build_data.take_snapshot();
break;
}
build_data.take_snapshot();
attempts += 1;
}
}
}
}
fn roll_until_fail(rng: &mut RandomNumberGenerator, target: i32) -> i32 {
let mut accumulator = 0;
loop {
if rng.roll_dice(1, 100) <= target - accumulator {
accumulator += 1;
rltk::console::log(accumulator);
} else {
break;
}
}
return accumulator;
}