faction-based visible ai, initial commit
This commit is contained in:
parent
bb8cf69b86
commit
b95f0cc1ad
4 changed files with 115 additions and 1 deletions
|
|
@ -1,5 +1,4 @@
|
||||||
use crate::{raws::Reaction, Faction, Map, Position, TakingTurn, WantsToMelee};
|
use crate::{raws::Reaction, Faction, Map, Position, TakingTurn, WantsToMelee};
|
||||||
use rltk::prelude::*;
|
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
pub struct AdjacentAI {}
|
pub struct AdjacentAI {}
|
||||||
|
|
|
||||||
|
|
@ -14,3 +14,5 @@ mod monster_ai_system;
|
||||||
pub use monster_ai_system::MonsterAI;
|
pub use monster_ai_system::MonsterAI;
|
||||||
mod adjacent_ai_system;
|
mod adjacent_ai_system;
|
||||||
pub use adjacent_ai_system::AdjacentAI;
|
pub use adjacent_ai_system::AdjacentAI;
|
||||||
|
mod visible_ai_system;
|
||||||
|
pub use visible_ai_system::VisibleAI;
|
||||||
|
|
|
||||||
111
src/ai/visible_ai_system.rs
Normal file
111
src/ai/visible_ai_system.rs
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
use crate::{
|
||||||
|
raws::Reaction, Faction, Map, Mind, Position, TakingTurn, Telepath, Viewshed, WantsToApproach, WantsToFlee,
|
||||||
|
};
|
||||||
|
use specs::prelude::*;
|
||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
pub struct VisibleAI {}
|
||||||
|
|
||||||
|
impl<'a> System<'a> for VisibleAI {
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
|
type SystemData = (
|
||||||
|
WriteStorage<'a, TakingTurn>,
|
||||||
|
ReadStorage<'a, Faction>,
|
||||||
|
ReadStorage<'a, Position>,
|
||||||
|
ReadExpect<'a, Map>,
|
||||||
|
WriteStorage<'a, WantsToApproach>,
|
||||||
|
WriteStorage<'a, WantsToFlee>,
|
||||||
|
Entities<'a>,
|
||||||
|
ReadExpect<'a, Entity>,
|
||||||
|
ReadStorage<'a, Viewshed>,
|
||||||
|
ReadStorage<'a, Telepath>,
|
||||||
|
ReadStorage<'a, Mind>,
|
||||||
|
);
|
||||||
|
|
||||||
|
fn run(&mut self, data: Self::SystemData) {
|
||||||
|
let (
|
||||||
|
mut turns,
|
||||||
|
factions,
|
||||||
|
positions,
|
||||||
|
map,
|
||||||
|
mut wants_to_approach,
|
||||||
|
mut wants_to_flee,
|
||||||
|
entities,
|
||||||
|
player,
|
||||||
|
viewsheds,
|
||||||
|
telepaths,
|
||||||
|
minds,
|
||||||
|
) = data;
|
||||||
|
|
||||||
|
for (entity, _turn, faction, pos, viewshed) in (&entities, &turns, &factions, &positions, &viewsheds).join() {
|
||||||
|
if entity == *player {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let this_idx = map.xy_idx(pos.x, pos.y);
|
||||||
|
let mut reactions: Vec<(usize, Reaction)> = Vec::new();
|
||||||
|
let mut flee: Vec<usize> = Vec::new();
|
||||||
|
let mut idxs: HashSet<usize> = HashSet::new();
|
||||||
|
for visible_tile in viewshed.visible_tiles.iter() {
|
||||||
|
let idx = map.xy_idx(visible_tile.x, visible_tile.y);
|
||||||
|
if this_idx != idx {
|
||||||
|
evaluate(idx, &map, &factions, &faction.name, &mut reactions, None);
|
||||||
|
idxs.insert(idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(is_telepath) = telepaths.get(entity) {
|
||||||
|
for telepath_tile in is_telepath.telepath_tiles.iter() {
|
||||||
|
let idx = map.xy_idx(telepath_tile.x, telepath_tile.y);
|
||||||
|
// If we didn't already evaluate this idx (if it's not contained in the HashSet),
|
||||||
|
// and it's not the idx we're standing on, then evaluate here w/ minds taken into
|
||||||
|
// account.
|
||||||
|
if this_idx != idx && idxs.contains(&idx) {
|
||||||
|
evaluate(idx, &map, &factions, &faction.name, &mut reactions, Some(&minds));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut done = false;
|
||||||
|
for reaction in reactions.iter() {
|
||||||
|
match reaction.1 {
|
||||||
|
Reaction::Attack => {
|
||||||
|
wants_to_approach
|
||||||
|
.insert(entity, WantsToApproach { idx: reaction.0 as i32 })
|
||||||
|
.expect("Error inserting WantsToApproach");
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
Reaction::Flee => {
|
||||||
|
flee.push(reaction.0);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !done && !flee.is_empty() {
|
||||||
|
wants_to_flee.insert(entity, WantsToFlee { indices: flee }).expect("Unable to insert");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn evaluate(
|
||||||
|
idx: usize,
|
||||||
|
map: &Map,
|
||||||
|
factions: &ReadStorage<Faction>,
|
||||||
|
this_faction: &str,
|
||||||
|
reactions: &mut Vec<(usize, Reaction)>,
|
||||||
|
minds: Option<&ReadStorage<Mind>>,
|
||||||
|
) {
|
||||||
|
for other_entity in map.tile_content[idx].iter() {
|
||||||
|
// If minds are passed, we assume we're using telepathy here,
|
||||||
|
// so if the other entity is mindless, we skip it.
|
||||||
|
if minds.is_some() {
|
||||||
|
if minds.unwrap().get(*other_entity).is_none() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(faction) = factions.get(*other_entity) {
|
||||||
|
reactions.push((
|
||||||
|
idx,
|
||||||
|
crate::raws::faction_reaction(this_faction, &faction.name, &crate::raws::RAWS.lock().unwrap()),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -97,6 +97,7 @@ impl State {
|
||||||
let mut turn_status_system = ai::TurnStatusSystem {};
|
let mut turn_status_system = ai::TurnStatusSystem {};
|
||||||
let mut quip_system = ai::QuipSystem {};
|
let mut quip_system = ai::QuipSystem {};
|
||||||
let mut adjacent_ai = ai::AdjacentAI {};
|
let mut adjacent_ai = ai::AdjacentAI {};
|
||||||
|
let mut visible_ai = ai::VisibleAI {};
|
||||||
let mut mob = ai::MonsterAI {};
|
let mut mob = ai::MonsterAI {};
|
||||||
let mut bystanders = ai::BystanderAI {};
|
let mut bystanders = ai::BystanderAI {};
|
||||||
let mut trigger_system = trigger_system::TriggerSystem {};
|
let mut trigger_system = trigger_system::TriggerSystem {};
|
||||||
|
|
@ -118,6 +119,7 @@ impl State {
|
||||||
turn_status_system.run_now(&self.ecs);
|
turn_status_system.run_now(&self.ecs);
|
||||||
quip_system.run_now(&self.ecs);
|
quip_system.run_now(&self.ecs);
|
||||||
adjacent_ai.run_now(&self.ecs);
|
adjacent_ai.run_now(&self.ecs);
|
||||||
|
visible_ai.run_now(&self.ecs);
|
||||||
mob.run_now(&self.ecs);
|
mob.run_now(&self.ecs);
|
||||||
bystanders.run_now(&self.ecs);
|
bystanders.run_now(&self.ecs);
|
||||||
trigger_system.run_now(&self.ecs);
|
trigger_system.run_now(&self.ecs);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue