use crate::{ EntityMoved, Map, Position, TakingTurn, Telepath, Viewshed, WantsToFlee }; use bracket_lib::prelude::*; use specs::prelude::*; pub struct FleeAI {} impl<'a> System<'a> for FleeAI { #[allow(clippy::type_complexity)] type SystemData = ( WriteStorage<'a, TakingTurn>, WriteStorage<'a, WantsToFlee>, WriteStorage<'a, Position>, WriteExpect<'a, Map>, WriteStorage<'a, Viewshed>, WriteStorage<'a, Telepath>, WriteStorage<'a, EntityMoved>, Entities<'a>, ); fn run(&mut self, data: Self::SystemData) { let ( mut turns, mut wants_to_flee, mut positions, mut map, mut viewsheds, mut telepaths, mut entity_moved, entities, ) = data; let mut turn_done: Vec = Vec::new(); for (entity, _turn, mut pos, fleeing, mut viewshed) in ( &entities, &turns, &mut positions, &wants_to_flee, &mut viewsheds, ).join() { turn_done.push(entity); let my_idx = map.xy_idx(pos.x, pos.y); map.populate_blocked(); let flee_map = DijkstraMap::new( map.width as usize, map.height as usize, &fleeing.indices, &*map, 100.0 ); let flee_target = DijkstraMap::find_highest_exit(&flee_map, my_idx, &*map); if let Some(flee_target) = flee_target { if !crate::spatial::is_blocked(flee_target as usize) { crate::spatial::move_entity(entity, my_idx, flee_target); viewshed.dirty = true; if let Some(is_telepath) = telepaths.get_mut(entity) { is_telepath.dirty = true; } pos.x = (flee_target as i32) % map.width; pos.y = (flee_target as i32) / map.width; entity_moved .insert(entity, EntityMoved {}) .expect("Unable to insert EntityMoved"); } } } wants_to_flee.clear(); for done in turn_done.iter() { turns.remove(*done); } } }