add fly options

This commit is contained in:
Edgar 2022-11-02 15:50:35 +01:00
parent ba7382e410
commit cd1714dac3
No known key found for this signature in database
5 changed files with 54 additions and 20 deletions

BIN
generated.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View file

@ -32,18 +32,33 @@ struct Cli {
#[derive(Subcommand)] #[derive(Subcommand)]
enum Commands { enum Commands {
/// Generate a map for fly techniques. /// Generate a map for fly techniques.
Fly, Fly {
#[arg(long, default_value_t = 3)]
max_fly_width: u16,
/// The output map file.
#[arg(long, default_value_t = 12)]
min_fly_width: u16,
},
/// Generate a maze-like map. /// Generate a maze-like map.
Maze, Maze,
} }
impl Commands { impl Commands {
pub fn print(&self) { pub fn print(&self) {
let name = match self { print!("Selected generator: ");
Self::Fly => "Fly", let data = match self {
Self::Maze => "Maze", Self::Fly {
max_fly_width,
min_fly_width,
} => format!(
"{}, parameters: max_fly_width={}, min_fly_width={}",
"Fly".purple().bold(),
max_fly_width.purple(),
min_fly_width.purple()
),
Self::Maze => format!("{}", "Maze".purple().bold()),
}; };
println!("Selected map generator: {}", name.purple().bold()); println!("{data}");
} }
} }
@ -70,10 +85,15 @@ pub fn run_cli() -> Result<()> {
match cli.command { match cli.command {
Commands::Maze => { Commands::Maze => {
MazeGenerator::save_file(&mut rng, &cli.mapres, cli.width, cli.height, &cli.output) MazeGenerator.save_file(&mut rng, &cli.mapres, cli.width, cli.height, &cli.output)
} }
Commands::Fly => { Commands::Fly {
FlyGenerator::save_file(&mut rng, &cli.mapres, cli.width, cli.height, &cli.output) max_fly_width,
min_fly_width,
} => FlyGenerator {
max_fly_width,
min_fly_width,
} }
.save_file(&mut rng, &cli.mapres, cli.width, cli.height, &cli.output),
} }
} }

View file

@ -2,11 +2,16 @@ use super::*;
use eyre::Result; use eyre::Result;
use ndarray::Array2; use ndarray::Array2;
use rand::Rng; use rand::Rng;
use rand_distr::{Uniform, Distribution};
pub struct FlyGenerator; pub struct FlyGenerator {
pub max_fly_width: u16,
pub min_fly_width: u16,
}
impl MapGenerator for FlyGenerator { impl MapGenerator for FlyGenerator {
fn generate<R: Rng + ?Sized>( fn generate<R: Rng + ?Sized>(
&self,
rng: &mut R, rng: &mut R,
mapres: &Path, mapres: &Path,
width: usize, width: usize,
@ -14,7 +19,7 @@ impl MapGenerator for FlyGenerator {
) -> Result<TwMap> { ) -> Result<TwMap> {
let mut map = create_initial_map(mapres)?; let mut map = create_initial_map(mapres)?;
let mut tiles = Array2::from_shape_simple_fn((height, width), || { let mut game_tiles = Array2::from_shape_simple_fn((height, width), || {
GameTile::new(TILE_EMPTY, TileFlags::empty()) GameTile::new(TILE_EMPTY, TileFlags::empty())
}); });
let mut front_tiles = Array2::from_shape_simple_fn((height, width), || { let mut front_tiles = Array2::from_shape_simple_fn((height, width), || {
@ -26,7 +31,8 @@ impl MapGenerator for FlyGenerator {
let mut freeze_tiles = let mut freeze_tiles =
Array2::from_shape_simple_fn((height, width), || Tile::new(0, TileFlags::empty())); Array2::from_shape_simple_fn((height, width), || Tile::new(0, TileFlags::empty()));
tiles // Create the ceiling and spawn.
game_tiles
.row_mut(height - 2) .row_mut(height - 2)
.iter_mut() .iter_mut()
.for_each(|tile| tile.id = TILE_UNHOOKABLE); .for_each(|tile| tile.id = TILE_UNHOOKABLE);
@ -35,8 +41,9 @@ impl MapGenerator for FlyGenerator {
.iter_mut() .iter_mut()
.for_each(|tile| tile.id = 2); .for_each(|tile| tile.id = 2);
tiles[(height - 3, width / 2)].id = TILE_SPAWN; game_tiles[(height - 3, width / 2)].id = TILE_SPAWN;
// Place the start and finish tiles.
for x in 0..width { for x in 0..width {
front_tiles[(height - 6, x)].id = TILE_START; front_tiles[(height - 6, x)].id = TILE_START;
front_tiles[(10, x)].id = TILE_FINISH; front_tiles[(10, x)].id = TILE_FINISH;
@ -50,25 +57,29 @@ impl MapGenerator for FlyGenerator {
let mut direction_steps: i64 = rng.gen_range((max_steps / 2)..=max_steps); let mut direction_steps: i64 = rng.gen_range((max_steps / 2)..=max_steps);
let mut direction: i64 = rng.gen_range(-1..=1); let mut direction: i64 = rng.gen_range(-1..=1);
let direction_steps_sampler = Uniform::from(1..=10);
let direction_sampler = Uniform::from(-1..=1);
let width_sampler = Uniform::from(-1..=1);
for y in (0..=(height - 3)).rev() { for y in (0..=(height - 3)).rev() {
if direction_steps == 0 { if direction_steps == 0 {
direction_steps = rng.gen_range(1..=10); direction_steps = direction_steps_sampler.sample(rng);
direction = rng.gen_range(-1..=1); direction = direction_sampler.sample(rng);
} }
let width_change: i64 = rng.gen_range(-1..=1); let width_change: i64 = width_sampler.sample(rng);
center += direction; center += direction;
fly_width += width_change; fly_width += width_change;
fly_width = fly_width.clamp(3, 12); fly_width = fly_width.clamp(self.min_fly_width as i64, self.max_fly_width as i64);
center = center.clamp(fly_width, width as i64 - fly_width - 1); center = center.clamp(fly_width, width as i64 - fly_width - 1);
for x in ((center + fly_width) as usize)..width { for x in ((center + fly_width) as usize)..width {
tiles[(y, x)].id = TILE_FREEZE; game_tiles[(y, x)].id = TILE_FREEZE;
freeze_tiles[(y, x)].id = 4; freeze_tiles[(y, x)].id = 4;
} }
for x in 0..=((center - fly_width) as usize) { for x in 0..=((center - fly_width) as usize) {
tiles[(y, x)].id = TILE_FREEZE; game_tiles[(y, x)].id = TILE_FREEZE;
freeze_tiles[(y, x)].id = 4; freeze_tiles[(y, x)].id = 4;
} }
@ -76,7 +87,7 @@ impl MapGenerator for FlyGenerator {
} }
let game_layer = GameLayer { let game_layer = GameLayer {
tiles: CompressedData::Loaded(tiles), tiles: CompressedData::Loaded(game_tiles),
}; };
let front_layer = FrontLayer { let front_layer = FrontLayer {

View file

@ -7,6 +7,7 @@ pub struct MazeGenerator;
impl MapGenerator for MazeGenerator { impl MapGenerator for MazeGenerator {
fn generate<R: Rng + ?Sized>( fn generate<R: Rng + ?Sized>(
&self,
rng: &mut R, rng: &mut R,
mapres: &Path, mapres: &Path,
width: usize, width: usize,

View file

@ -20,6 +20,7 @@ pub const TILE_SPAWN: u8 = 192;
pub trait MapGenerator { pub trait MapGenerator {
fn generate<R: Rng + ?Sized>( fn generate<R: Rng + ?Sized>(
&self,
rng: &mut R, rng: &mut R,
mapres: &Path, mapres: &Path,
width: usize, width: usize,
@ -27,13 +28,14 @@ pub trait MapGenerator {
) -> Result<TwMap>; ) -> Result<TwMap>;
fn save_file<R: Rng + ?Sized>( fn save_file<R: Rng + ?Sized>(
&self,
rng: &mut R, rng: &mut R,
mapres: &Path, mapres: &Path,
width: usize, width: usize,
height: usize, height: usize,
path: &Path, path: &Path,
) -> Result<()> { ) -> Result<()> {
let mut map = Self::generate(rng, mapres, width, height)?; let mut map = self.generate(rng, mapres, width, height)?;
map.save_file(path)?; map.save_file(path)?;
Ok(()) Ok(())
} }