diff --git a/rogue_lib/src/cell.rs b/rogue_lib/src/cell.rs index d8e5e26..1e013f7 100644 --- a/rogue_lib/src/cell.rs +++ b/rogue_lib/src/cell.rs @@ -13,7 +13,7 @@ use std::fmt::Display; /// gestisce le varie casistiche. #[derive(Clone, Debug, Deserialize, Serialize)] pub enum Cell { - Entance, + Entrance, Exit, Special(Box), Wall, @@ -46,7 +46,7 @@ impl Cell { /// può essere utilizzata per vedere il valore e mostrarlo a terminale. pub fn as_char(&self) -> char { match self { - Cell::Entance => ' ', + Cell::Entrance => ' ', Cell::Exit => '¤', Cell::Special(effect) => effect.as_char(), Cell::Wall => '█', diff --git a/rogue_lib/src/floor.rs b/rogue_lib/src/floor.rs index db828eb..73ed1b6 100644 --- a/rogue_lib/src/floor.rs +++ b/rogue_lib/src/floor.rs @@ -89,13 +89,13 @@ impl Floor { /// Restituisce la posizione dell'entrata del piano.\ /// Utile come spawn per quando i giocatori arrivano al piano. - pub fn get_entrance(&mut self) -> Position { + pub fn get_entrance(&self) -> Position { self.grid .iter() .enumerate() .find_map(|(x, vec)| { vec.iter().enumerate().find_map(|(y, cell)| { - if let Cell::Entance = cell { + if let Cell::Entrance = cell { Some(Position(x, y)) } else { None diff --git a/rogue_lib/src/generator.rs b/rogue_lib/src/generator.rs index b506db9..52dce27 100644 --- a/rogue_lib/src/generator.rs +++ b/rogue_lib/src/generator.rs @@ -7,6 +7,7 @@ use super::{ }, floor::Floor, }; +use crate::entities::Entity; use rand::{Rng, SeedableRng}; use rand_pcg::Pcg32; use std::{ @@ -69,15 +70,43 @@ impl<'a> Generator<'a> { let index = gen.get_random_room_index(); let exit = gen.get_room_ranges(index); - self.rand_place(&mut grid, Cell::Entance, entrance.0, entrance.1); - self.rand_place(&mut grid, Cell::Exit, exit.0, exit.1); + let pos = self.rand_empty_cell_pos(&mut grid, entrance.0, entrance.1); + grid[pos.0][pos.1] = Cell::Entrance; + let pos = self.rand_empty_cell_pos(&mut grid, exit.0, exit.1); + grid[pos.0][pos.1] = Cell::Exit; + self.rand_place_effects(&mut grid); - Floor::new(self.level, self.rng, vec![], grid) + let entities = self.rand_place_entities(&mut grid); + + Floor::new(self.level, self.rng, entities, grid) } /// todo!() docs - fn rand_place_entities(&mut self, grid: &mut Vec>) { - todo!() + fn rand_place_entities(&mut self, grid: &mut Vec>) -> Vec { + let entities = vec_filter(&self.config.entities, |e| { + e.floors.contains(&self.level).then(|| (e.priority, e)) + }); + + let mut result: Vec = vec![]; + for _ in 0..self.config.entities_total { + let config = vec_get_sample(&entities, &mut self.rng).clone(); + let mut entity = Entity::new( + config.name.clone(), + config.health, + config.attack, + config.behavior.clone(), + ); + + loop { + let pos = self.rand_empty_cell_pos(grid, 0..self.size, 0..self.size); + if !result.iter().any(|e| e.position == pos) { + entity.position = pos; + result.push(entity); + break; + } + } + } + result } /// piazza gli effetti della confgurazione in modo casuale su tutto il piano.\ /// essi vengono piazzati solamente sulle celle Empty @@ -89,15 +118,16 @@ impl<'a> Generator<'a> { for _ in 0..self.config.effects_total { let effect = vec_get_sample(&effects, &mut self.rng).effect.clone(); let cell = Cell::Special(effect); - self.rand_place(grid, cell, 0..self.size, 0..self.size); + let pos = self.rand_empty_cell_pos(grid, 0..self.size, 0..self.size); + grid[pos.0][pos.1] = cell; } } /// piazza una cella in un punto casuale del piano.\ /// il metodo contiuna a provare a piazzare la cella finche non trova una cella Empty. - fn rand_place( + /// todo!() docs + fn rand_empty_cell_pos( &mut self, grid: &mut Vec>, - cell: Cell, range_x: Range, range_y: Range, ) -> Position { @@ -105,7 +135,6 @@ impl<'a> Generator<'a> { let x = self.rng.gen_range(range_x.clone()); let y = self.rng.gen_range(range_y.clone()); if let Cell::Empty = grid[x][y] { - grid[x][y] = cell; return Position(x, y); } } diff --git a/rogue_lib/src/lib.rs b/rogue_lib/src/lib.rs index d91372f..c14a8e8 100644 --- a/rogue_lib/src/lib.rs +++ b/rogue_lib/src/lib.rs @@ -108,7 +108,7 @@ impl ConsoleInput { let mut term = console::Term::stdout(); let _ = term.clear_screen(); let _ = term.write_fmt(format_args!( - "{}{}\n{other}\n", + "{}{}\n{other}", Self::floor_as_string(&floor), Self::entity_as_string(floor.entity), )); diff --git a/rogue_lib/tests/tests.rs b/rogue_lib/tests/tests.rs index ec203fe..e11ab88 100644 --- a/rogue_lib/tests/tests.rs +++ b/rogue_lib/tests/tests.rs @@ -35,7 +35,7 @@ fn test_cell_basic() { assert_eq!(entity.position, Position(10, 10)); assert_eq!(entity.direction, Direction::Up); - Cell::Entance.entity_over(&mut entity); + Cell::Entrance.entity_over(&mut entity); assert_eq!(entity.position, Position(10, 10)); assert_eq!(entity.direction, Direction::Up); @@ -48,7 +48,7 @@ fn test_cell_basic() { assert_eq!(entity.direction, Direction::Down); assert_eq!(Cell::Empty.as_char(), ' '); - assert_eq!(Cell::Entance.as_char(), ' '); + assert_eq!(Cell::Entrance.as_char(), ' '); assert_eq!(Cell::Exit.as_char(), '¤'); assert_eq!(Cell::Wall.as_char(), '█'); } @@ -251,6 +251,97 @@ fn test_entity_basic_action() { assert!(matches!(entity.buffer, Action::DoNothing)); } +#[test] +#[should_panic] +fn test_floor_insert_player_panic() { + let mut floor = get_basic_floor(); + let player = get_basic_entity(); + floor.add_player(player); +} + +#[test] +fn test_floor_entrance_exit_player() { + let mut floor = get_basic_floor(); + assert_eq!(floor.get_level(), 0); + assert_eq!(floor.get_size(), 20); + assert!(matches!(floor.get_player_at_exit(), None)); + + assert!(matches!(floor.get_cell(&Position(10, 10)), Cell::Empty)); + *floor.get_cell_mut(&Position(10, 10)) = Cell::Entrance; + assert!(matches!(floor.get_cell(&Position(10, 10)), Cell::Entrance)); + + let player = get_basic_entity(); + floor.add_player(player); + + assert!(matches!(floor.get_player_at_exit(), None)); + assert!(matches!(floor.get_cell(&Position(10, 10)), Cell::Entrance)); + *floor.get_cell_mut(&Position(10, 10)) = Cell::Exit; + assert!(matches!(floor.get_cell(&Position(10, 10)), Cell::Exit)); + assert!(matches!(floor.get_player_at_exit(), Some(_))); + assert!(matches!(floor.get_player_at_exit(), None)); + assert!(matches!(floor.get_cell(&Position(10, 10)), Cell::Exit)); +} + +#[test] +fn test_floor_entities() { + let rng = Pcg32::seed_from_u64(0); + let entities = vec![ + Entity::new("1".to_string(), 110, 90, Box::new(Immovable)), + Entity::new("2".to_string(), 120, 80, Box::new(Immovable)), + Entity::new("3".to_string(), 130, 70, Box::new(Immovable)), + Entity::new("4".to_string(), 140, 60, Box::new(Immovable)), + ]; + + let floor = Floor::new(0, rng, entities, vec![vec![Cell::Empty; 20]; 20]); + let mut iter = floor.get_all_entities(); + + let entity = iter.next(); + assert!(matches!(entity, Some(_))); + assert_eq!(entity.unwrap().get_name(), &"1"); + assert_eq!(entity.unwrap().get_health(), 110); + assert_eq!(entity.unwrap().get_health_max(), 110); + + let entity = iter.next(); + assert!(matches!(entity, Some(_))); + assert_eq!(entity.unwrap().get_name(), &"2"); + assert_eq!(entity.unwrap().get_health(), 120); + assert_eq!(entity.unwrap().get_health_max(), 120); + + let entity = iter.next(); + assert!(matches!(entity, Some(_))); + assert_eq!(entity.unwrap().get_name(), &"3"); + assert_eq!(entity.unwrap().get_health(), 130); + assert_eq!(entity.unwrap().get_health_max(), 130); + + let entity = iter.next(); + assert!(matches!(entity, Some(_))); + assert_eq!(entity.unwrap().get_name(), &"4"); + assert_eq!(entity.unwrap().get_health(), 140); + assert_eq!(entity.unwrap().get_health_max(), 140); + + let entity = iter.next(); + assert!(matches!(entity, None)); +} + +#[test] +fn test_game_initial_config() { + let mut game = rogue_lib::game::Dungeon::new(); + + assert!(!game.has_players()); + game.add_player("Player".to_string(), Box::new(Immovable)); + assert!(game.has_players()); + + let floor = game.get_floor(0); + assert_eq!(floor.get_level(), 0); + + let player = floor.get_all_entities().next(); + assert!(matches!(player, Some(_))); + assert_eq!(player.unwrap().get_name(), &"Player"); + + let entrance = floor.get_entrance(); + assert_eq!(entrance, player.unwrap().position); +} + #[test] fn test_generator_priority() { let mut vec = vec![(1_u32, &"a"), (3, &"b"), (2, &"c")].into_iter();