use crate::{ raws::Reaction, Faction, HasAncestry, Map, Position, TakingTurn, WantsToMelee }; use specs::prelude::*; pub struct AdjacentAI {} impl<'a> System<'a> for AdjacentAI { #[allow(clippy::type_complexity)] type SystemData = ( WriteStorage<'a, TakingTurn>, ReadStorage<'a, Faction>, ReadStorage<'a, HasAncestry>, ReadStorage<'a, Position>, ReadExpect<'a, Map>, WriteStorage<'a, WantsToMelee>, Entities<'a>, ReadExpect<'a, Entity>, ); fn run(&mut self, data: Self::SystemData) { let (mut turns, factions, ancestries, positions, map, mut want_melee, entities, player) = data; let mut turn_done: Vec = Vec::new(); for (entity, _turn, pos) in (&entities, &turns, &positions).join() { if entity != *player { let mut reactions: Vec<(Entity, Reaction)> = Vec::new(); let idx = map.xy_idx(pos.x, pos.y); let w = map.width; let h = map.height; // Add possible reactions to adjacents for each direction if pos.x > 0 { evaluate(entity, idx - 1, &ancestries, &factions, &mut reactions); } if pos.x < w - 1 { evaluate(entity, idx + 1, &ancestries, &factions, &mut reactions); } if pos.y > 0 { evaluate(entity, idx - (w as usize), &ancestries, &factions, &mut reactions); } if pos.y < h - 1 { evaluate(entity, idx + (w as usize), &ancestries, &factions, &mut reactions); } if pos.y > 0 && pos.x > 0 { evaluate(entity, idx - (w as usize) - 1, &ancestries, &factions, &mut reactions); } if pos.y > 0 && pos.x < w - 1 { evaluate(entity, idx - (w as usize) + 1, &ancestries, &factions, &mut reactions); } if pos.y < h - 1 && pos.x > 0 { evaluate(entity, idx + (w as usize) - 1, &ancestries, &factions, &mut reactions); } if pos.y < h - 1 && pos.x < w - 1 { evaluate(entity, idx + (w as usize) + 1, &ancestries, &factions, &mut reactions); } let mut done = false; for reaction in reactions.iter() { if let Reaction::Attack = reaction.1 { want_melee.insert(entity, WantsToMelee { target: reaction.0 }).expect("Error inserting melee"); done = true; } } if done { turn_done.push(entity); } } } // Remove turn marker for those that are done for done in turn_done.iter() { turns.remove(*done); } } } /// Evaluates all possible reactions between this faction and all entities on a given tile idx. fn evaluate( entity: Entity, idx: usize, ancestries: &ReadStorage, factions: &ReadStorage, reactions: &mut Vec<(Entity, Reaction)> ) { crate::spatial::for_each_tile_content(idx, |other_entity| { let result = crate::raws::get_reactions( entity, other_entity, &factions, &ancestries, &crate::raws::RAWS.lock().unwrap() ); reactions.push((other_entity, result)); }); }