diff --git a/src/bystander_ai_system.rs b/src/bystander_ai_system.rs new file mode 100644 index 0000000..1e6bee0 --- /dev/null +++ b/src/bystander_ai_system.rs @@ -0,0 +1,71 @@ +use ::rltk::RandomNumberGenerator; +use specs::prelude::*; + +use super::{Map, RunState}; +use crate::components::{Bystander, EntityMoved, Position, Viewshed}; + +pub struct BystanderAI {} + +impl<'a> System<'a> for BystanderAI { + #[allow(clippy::type_complexity)] + type SystemData = ( + WriteExpect<'a, Map>, + ReadExpect<'a, RunState>, + Entities<'a>, + WriteStorage<'a, Viewshed>, + ReadStorage<'a, Bystander>, + WriteStorage<'a, Position>, + WriteStorage<'a, EntityMoved>, + WriteExpect<'a, RandomNumberGenerator>, + ); + + fn run(&mut self, data: Self::SystemData) { + let ( + mut map, + runstate, + entities, + mut viewshed, + bystander, + mut position, + mut entity_moved, + mut rng, + ) = data; + + if *runstate != RunState::MonsterTurn { + return; + } + + for (entity, mut viewshed, _bystander, mut pos) in + (&entities, &mut viewshed, &bystander, &mut position).join() + { + // Try to move randomly + let mut x = pos.x; + let mut y = pos.y; + match rng.roll_dice(1, 5) { + 1 => x -= 1, + 2 => x += 1, + 3 => y -= 1, + 4 => y += 1, + _ => {} + } + + if x > 0 && x < map.width - 1 && y > 0 && y < map.height - 1 { + let dest_idx = map.xy_idx(x, y); + + if !map.blocked[dest_idx] { + let idx = map.xy_idx(pos.x, pos.y); + map.blocked[idx] = false; + + pos.x = x; + pos.y = y; + entity_moved + .insert(entity, EntityMoved {}) + .expect("Unable to insert moved flag component"); + + map.blocked[dest_idx] = true; + viewshed.dirty = true; + } + } + } + } +} diff --git a/src/main.rs b/src/main.rs index cf015b2..0901f78 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +mod bystander_ai_system; pub mod camera; mod components; mod damage_system; @@ -27,6 +28,7 @@ extern crate lazy_static; use ::rltk::{GameState, Point, RandomNumberGenerator, Rltk}; use ::specs::prelude::*; use ::specs::saveload::{SimpleMarker, SimpleMarkerAllocator}; +use bystander_ai_system::BystanderAI; use components::*; use damage_system::DamageSystem; pub use game_log::GameLog; @@ -111,6 +113,9 @@ impl State { let mut mapindex = MapIndexingSystem {}; mapindex.run_now(&self.ecs); + let mut bystander = BystanderAI {}; + bystander.run_now(&self.ecs); + let mut melee = MeleeCombatSystem {}; melee.run_now(&self.ecs);