|
@@ -3,8 +3,10 @@ use rltk::{ RGB, RandomNumberGenerator };
|
|
|
extern crate specs;
|
|
|
use specs::prelude::*;
|
|
|
use super::{CombatStats, Player, Renderable, Name, Position, Viewshed, Monster, BlocksTile, Rect, Item,
|
|
|
- Consumable, Ranged, ProvidesHealing, map::MAPWIDTH, InflictsDamage, AreaOfEffect, Confusion, SerializeMe};
|
|
|
+ Consumable, Ranged, ProvidesHealing, map::MAPWIDTH, InflictsDamage, AreaOfEffect, Confusion, SerializeMe,
|
|
|
+ random_table::RandomTable};
|
|
|
use crate::specs::saveload::{MarkedBuilder, SimpleMarker};
|
|
|
+use std::collections::HashMap;
|
|
|
|
|
|
/// Spawns the player and returns his/her entity object.
|
|
|
pub fn player(ecs : &mut World, player_x : i32, player_y : i32) -> Entity {
|
|
@@ -26,84 +28,59 @@ pub fn player(ecs : &mut World, player_x : i32, player_y : i32) -> Entity {
|
|
|
}
|
|
|
|
|
|
const MAX_MONSTERS : i32 = 4;
|
|
|
-const MAX_ITEMS : i32 = 2;
|
|
|
+
|
|
|
+fn room_table(map_depth: i32) -> RandomTable {
|
|
|
+ RandomTable::new()
|
|
|
+ .add("Goblin", 10)
|
|
|
+ .add("Orc", 1 + map_depth)
|
|
|
+ .add("Health Potion", 7)
|
|
|
+ .add("Fireball Scroll", 2 + map_depth)
|
|
|
+ .add("Confusion Scroll", 2 + map_depth)
|
|
|
+ .add("Magic Missile Scroll", 4)
|
|
|
+}
|
|
|
|
|
|
/// Fills a room with stuff!
|
|
|
-pub fn spawn_room(ecs: &mut World, room : &Rect) {
|
|
|
- let mut monster_spawn_points : Vec<usize> = Vec::new();
|
|
|
- let mut item_spawn_points : Vec<usize> = Vec::new();
|
|
|
+#[allow(clippy::map_entry)]
|
|
|
+pub fn spawn_room(ecs: &mut World, room : &Rect, map_depth: i32) {
|
|
|
+ let spawn_table = room_table(map_depth);
|
|
|
+ let mut spawn_points : HashMap<usize, String> = HashMap::new();
|
|
|
|
|
|
// Scope to keep the borrow checker happy
|
|
|
{
|
|
|
let mut rng = ecs.write_resource::<RandomNumberGenerator>();
|
|
|
- let num_monsters = rng.roll_dice(1, MAX_MONSTERS + 2) - 3;
|
|
|
- let num_items = rng.roll_dice(1, MAX_ITEMS + 2) - 3;
|
|
|
+ let num_spawns = rng.roll_dice(1, MAX_MONSTERS + 3) + (map_depth - 1) - 3;
|
|
|
|
|
|
- for _i in 0 .. num_monsters {
|
|
|
+ for _i in 0 .. num_spawns {
|
|
|
let mut added = false;
|
|
|
- while !added {
|
|
|
+ let mut tries = 0;
|
|
|
+ while !added && tries < 20 {
|
|
|
let x = (room.x1 + rng.roll_dice(1, i32::abs(room.x2 - room.x1))) as usize;
|
|
|
let y = (room.y1 + rng.roll_dice(1, i32::abs(room.y2 - room.y1))) as usize;
|
|
|
let idx = (y * MAPWIDTH) + x;
|
|
|
- if !monster_spawn_points.contains(&idx) {
|
|
|
- monster_spawn_points.push(idx);
|
|
|
- added = true;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- for _i in 0 .. num_items {
|
|
|
- let mut added = false;
|
|
|
- while !added {
|
|
|
- let x = (room.x1 + rng.roll_dice(1, i32::abs(room.x2 - room.x1))) as usize;
|
|
|
- let y = (room.y1 + rng.roll_dice(1, i32::abs(room.y2 - room.y1))) as usize;
|
|
|
- let idx = (y * MAPWIDTH) + x;
|
|
|
- if !item_spawn_points.contains(&idx) {
|
|
|
- item_spawn_points.push(idx);
|
|
|
+ if !spawn_points.contains_key(&idx) {
|
|
|
+ spawn_points.insert(idx, spawn_table.roll(&mut rng));
|
|
|
added = true;
|
|
|
+ } else {
|
|
|
+ tries += 1;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// Actually spawn the monsters
|
|
|
- for idx in monster_spawn_points.iter() {
|
|
|
- let x = *idx % MAPWIDTH;
|
|
|
- let y = *idx / MAPWIDTH;
|
|
|
- random_monster(ecs, x as i32, y as i32);
|
|
|
- }
|
|
|
-
|
|
|
- // Actually spawn the items
|
|
|
- for idx in item_spawn_points.iter() {
|
|
|
- let x = *idx % MAPWIDTH;
|
|
|
- let y = *idx / MAPWIDTH;
|
|
|
- random_item(ecs, x as i32, y as i32);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-fn random_monster(ecs: &mut World, x: i32, y: i32) {
|
|
|
- let roll :i32;
|
|
|
- {
|
|
|
- let mut rng = ecs.write_resource::<RandomNumberGenerator>();
|
|
|
- roll = rng.roll_dice(1, 2);
|
|
|
- }
|
|
|
- match roll {
|
|
|
- 1 => { orc(ecs, x, y) }
|
|
|
- _ => { goblin(ecs, x, y) }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-fn random_item(ecs: &mut World, x: i32, y: i32) {
|
|
|
- let roll :i32;
|
|
|
- {
|
|
|
- let mut rng = ecs.write_resource::<RandomNumberGenerator>();
|
|
|
- roll = rng.roll_dice(1, 4);
|
|
|
- }
|
|
|
- match roll {
|
|
|
- 1 => { health_potion(ecs, x, y) }
|
|
|
- 2 => { fireball_scroll(ecs, x, y) }
|
|
|
- 3 => { confusion_scroll(ecs, x, y) }
|
|
|
- _ => { magic_missile_scroll(ecs, x, y) }
|
|
|
+ for spawn in spawn_points.iter() {
|
|
|
+ let x = (*spawn.0 % MAPWIDTH) as i32;
|
|
|
+ let y = (*spawn.0 / MAPWIDTH) as i32;
|
|
|
+
|
|
|
+ match spawn.1.as_ref() {
|
|
|
+ "Goblin" => goblin(ecs, x, y),
|
|
|
+ "Orc" => orc(ecs, x, y),
|
|
|
+ "Health Potion" => health_potion(ecs, x, y),
|
|
|
+ "Fireball Scroll" => fireball_scroll(ecs, x, y),
|
|
|
+ "Confusion Scroll" => confusion_scroll(ecs, x, y),
|
|
|
+ "Magic Missile Scroll" => magic_missile_scroll(ecs, x, y),
|
|
|
+ _ => {}
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|