Skip to content
Snippets Groups Projects
Unverified Commit 7050c761 authored by Kat Marchán's avatar Kat Marchán
Browse files

stop leaking Scorers and Actions?

Fixes: https://github.com/zkat/big-brain/issues/12

I *think* this fixes it, but I need to test it more
thoroughly and make sure everything is actually ok
parent 01270a4f
No related branches found
No related tags found
No related merge requests found
......@@ -78,9 +78,9 @@ fn drink_action_system(
// usually happen because the target action changed (due to a different
// Scorer winning). But you can also cancel the actions yourself by
// setting the state in the Action system.
mut query: Query<(&Parent, &mut ActionState), With<Drink>>,
mut query: Query<(&Actor, &mut ActionState), With<Drink>>,
) {
for (Parent(actor), mut state) in query.iter_mut() {
for (Actor(actor), mut state) in query.iter_mut() {
// Use the drink_action's actor to look up the corresponding Thirst.
if let Ok(mut thirst) = thirsts.get_mut(*actor) {
match *state {
......@@ -128,9 +128,9 @@ impl ScorerBuilder for ThirstyBuilder {
pub fn thirsty_scorer_system(
thirsts: Query<&Thirst>,
// Same dance with the Parent here, but now Big Brain has added a Score component!
mut query: Query<(&Parent, &mut Score), With<Thirsty>>,
mut query: Query<(&Actor, &mut Score), With<Thirsty>>,
) {
for (Parent(actor), mut score) in query.iter_mut() {
for (Actor(actor), mut score) in query.iter_mut() {
if let Ok(thirst) = thirsts.get(*actor) {
// This is really what the job of a Scorer is. To calculate a
// generic Utility value that the Big Brain engine will compare
......@@ -153,13 +153,15 @@ pub fn init_entities(mut cmd: Commands) {
let actor = cmd.spawn().insert(Thirst::new(70.0, 2.0)).id();
// And finally, we put all the pieces together!
Thinker::build()
let thinker = Thinker::build()
.picker(FirstToScore { threshold: 80.0 })
// Note that what we pass in are _builders_, not components!
.when(Thirsty::build(), Drink::build())
// .attach will do all the necessary work of attaching this component
// and hooking it up to the AI system.
.attach(&mut cmd, actor);
// TODO: this is a footgun and a pita. Please ignore.
cmd.entity(actor).push_children(&[thinker]);
}
fn main() {
......
......@@ -2,7 +2,7 @@ use std::sync::Arc;
use bevy::prelude::*;
use crate::ActionEnt;
use crate::{ActionEnt, Actor};
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum ActionState {
......@@ -42,8 +42,7 @@ pub trait ActionBuilder: std::fmt::Debug + Send + Sync {
fn build(&self, cmd: &mut Commands, action: Entity, actor: Entity);
fn attach(&self, cmd: &mut Commands, actor: Entity) -> Entity {
let action_ent = ActionEnt(cmd.spawn().id());
cmd.entity(action_ent.0).insert(ActionState::new());
cmd.entity(actor).push_children(&[action_ent.0]);
cmd.entity(action_ent.0).insert(ActionState::new()).insert(Actor(actor));
self.build(cmd, action_ent.0, actor);
action_ent.0
}
......@@ -68,7 +67,7 @@ impl ActionBuilder for StepsBuilder {
active_step: 0,
active_ent: ActionEnt(child_action),
steps: self.steps.clone(),
});
}).push_children(&[child_action]);
}
}
#[derive(Debug)]
......@@ -86,11 +85,11 @@ impl Steps {
pub fn steps_system(
mut cmd: Commands,
mut steps_q: Query<(Entity, &Parent, &mut Steps)>,
mut steps_q: Query<(Entity, &Actor, &mut Steps)>,
mut states: Query<&mut ActionState>,
) {
use ActionState::*;
for (seq_ent, Parent(actor), mut steps_action) in steps_q.iter_mut() {
for (seq_ent, Actor(actor), mut steps_action) in steps_q.iter_mut() {
let current_state = states.get_mut(seq_ent).expect("uh oh").clone();
match current_state {
Requested => {
......@@ -131,6 +130,7 @@ pub fn steps_system(
steps_action.active_step += 1;
let step_builder = steps_action.steps[steps_action.active_step].clone();
let step_ent = step_builder.attach(&mut cmd, *actor);
cmd.entity(seq_ent).push_children(&[step_ent]);
let mut step_state = states.get_mut(step_ent).expect("oops");
*step_state = ActionState::Requested;
}
......
......@@ -36,7 +36,9 @@ impl ChoiceBuilder {
}
}
pub fn build(&self, cmd: &mut Commands, actor: Entity) -> Choice {
pub fn build(&self, cmd: &mut Commands, actor: Entity, parent: Entity) -> Choice {
let scorer_ent = self.when.attach(cmd, actor);
cmd.entity(parent).push_children(&[scorer_ent]);
Choice {
scorer: ScorerEnt(self.when.attach(cmd, actor)),
action: ActionBuilderWrapper::new(self.then.clone()),
......
......@@ -2,7 +2,7 @@ use std::sync::Arc;
use bevy::prelude::*;
use crate::ScorerEnt;
use crate::{Actor, ScorerEnt};
#[derive(Debug, Clone, Default)]
pub struct Score(pub(crate) f32);
......@@ -23,8 +23,9 @@ pub trait ScorerBuilder: std::fmt::Debug + Sync + Send {
fn build(&self, cmd: &mut Commands, scorer: Entity, actor: Entity);
fn attach(&self, cmd: &mut Commands, actor: Entity) -> Entity {
let scorer_ent = cmd.spawn().id();
cmd.entity(scorer_ent).insert(Score::default());
cmd.entity(actor).push_children(&[scorer_ent]);
cmd.entity(scorer_ent)
.insert(Score::default())
.insert(Actor(actor));
self.build(cmd, scorer_ent, actor);
scorer_ent
}
......@@ -114,6 +115,7 @@ impl ScorerBuilder for AllOrNothingBuilder {
.collect();
cmd.entity(scorer)
.insert(Score::default())
.push_children(&scorers[..])
.insert(super::AllOrNothing {
threshold: self.threshold,
scorers: scorers.into_iter().map(ScorerEnt).collect(),
......
......@@ -12,6 +12,9 @@ use crate::{
scorers::{Score, ScorerBuilder},
};
#[derive(Debug, Clone, Copy)]
pub struct Actor(pub Entity);
#[derive(Debug, Clone, Copy)]
pub struct ActionEnt(pub Entity);
......@@ -74,7 +77,7 @@ impl ActionBuilder for ThinkerBuilder {
let choices = self
.choices
.iter()
.map(|choice| choice.build(cmd, actor))
.map(|choice| choice.build(cmd, actor, action_ent))
.collect();
cmd.entity(action_ent)
.insert(Thinker {
......@@ -116,12 +119,12 @@ impl Default for ThinkerIterations {
pub fn thinker_system(
mut cmd: Commands,
mut iterations: Local<ThinkerIterations>,
mut thinker_q: Query<(Entity, &Parent, &mut Thinker, &ActiveThinker)>,
mut thinker_q: Query<(Entity, &Actor, &mut Thinker, &ActiveThinker)>,
utilities: Query<&Score>,
mut action_states: Query<&mut actions::ActionState>,
) {
let start = Instant::now();
for (thinker_ent, Parent(actor), mut thinker, active_thinker) in
for (thinker_ent, Actor(actor), mut thinker, active_thinker) in
thinker_q.iter_mut().skip(iterations.index)
{
iterations.index += 1;
......@@ -189,7 +192,7 @@ pub fn thinker_system(
actions::ActionState::Init
| actions::ActionState::Success
| actions::ActionState::Failure => {
cmd.entity(current.0 .0).despawn_recursive();
cmd.entity(current.0.0).despawn_recursive();
thinker.current_action = None;
}
_ => {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment