Skip to content
Snippets Groups Projects
Unverified Commit f33315c9 authored by Gilbert Röhrbein's avatar Gilbert Röhrbein Committed by GitHub
Browse files

fix(systems): Fix steps, add a test and explicit systems ordering (#27)

Fixes: #26

* add test for steps and fixes
* define system ordering
parent efcbd940
No related branches found
No related tags found
No related merge requests found
...@@ -175,17 +175,16 @@ pub fn steps_system( ...@@ -175,17 +175,16 @@ pub fn steps_system(
) { ) {
use ActionState::*; use ActionState::*;
for (seq_ent, Actor(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(); let active_ent = steps_action.active_ent.0;
let current_state = states.get_mut(seq_ent).unwrap().clone();
match current_state { match current_state {
Requested => { Requested => {
// Begin at the beginning // Begin at the beginning
let mut step_state = states.get_mut(steps_action.active_ent.0).expect("oops"); *states.get_mut(active_ent).unwrap() = Requested;
*step_state = Requested; *states.get_mut(seq_ent).unwrap() = Executing;
let mut current_state = states.get_mut(seq_ent).expect("uh oh");
*current_state = Executing;
} }
Executing => { Executing => {
let mut step_state = states.get_mut(steps_action.active_ent.0).expect("bug"); let mut step_state = states.get_mut(active_ent).unwrap();
match *step_state { match *step_state {
Init => { Init => {
// Request it! This... should not really happen? But just in case I'm missing something... :) // Request it! This... should not really happen? But just in case I'm missing something... :)
...@@ -216,15 +215,18 @@ pub fn steps_system( ...@@ -216,15 +215,18 @@ pub fn steps_system(
let step_builder = steps_action.steps[steps_action.active_step].clone(); let step_builder = steps_action.steps[steps_action.active_step].clone();
let step_ent = step_builder.attach(&mut cmd, *actor); let step_ent = step_builder.attach(&mut cmd, *actor);
cmd.entity(seq_ent).push_children(&[step_ent]); cmd.entity(seq_ent).push_children(&[step_ent]);
let mut step_state = states.get_mut(step_ent).expect("oops"); steps_action.active_ent.0 = step_ent;
*step_state = ActionState::Requested;
} }
} }
} }
Cancelled => { Cancelled => {
// Cancel current action // Cancel current action
let mut step_state = states.get_mut(steps_action.active_ent.0).expect("oops"); let mut step_state = states.get_mut(active_ent).expect("oops");
*step_state = ActionState::Cancelled; if *step_state == Requested || *step_state == Executing {
*step_state = Cancelled;
} else if *step_state == Failure || *step_state == Success {
*states.get_mut(seq_ent).unwrap() = step_state.clone();
}
} }
Init | Success | Failure => { Init | Success | Failure => {
// Do nothing. // Do nothing.
......
...@@ -193,16 +193,31 @@ pub struct BigBrainPlugin; ...@@ -193,16 +193,31 @@ pub struct BigBrainPlugin;
impl Plugin for BigBrainPlugin { impl Plugin for BigBrainPlugin {
fn build(&self, app: &mut AppBuilder) { fn build(&self, app: &mut AppBuilder) {
app.add_system(thinker::thinker_system.system()); use CoreStage::*;
app.add_system(thinker::thinker_component_attach_system.system()); app.add_system_set_to_stage(
app.add_system(thinker::thinker_component_detach_system.system()); First,
app.add_system(thinker::actor_gone_cleanup.system()); SystemSet::new()
app.add_system(actions::steps_system.system()); .with_system(scorers::fixed_score_system.system())
app.add_system(actions::concurrent_system.system()); .with_system(scorers::all_or_nothing_system.system())
app.add_system(scorers::fixed_score_system.system()); .with_system(scorers::sum_of_scorers_system.system())
app.add_system(scorers::all_or_nothing_system.system()); .with_system(scorers::winning_scorer_system.system())
app.add_system(scorers::sum_of_scorers_system.system()); .with_system(scorers::evaluating_scorer_system.system())
app.add_system(scorers::winning_scorer_system.system()); .label("scorers"),
app.add_system(scorers::evaluating_scorer_system.system()); );
app.add_system_to_stage(First, thinker::thinker_system.system().after("scorers"));
app.add_system_set_to_stage(
PreUpdate,
SystemSet::new()
.with_system(actions::steps_system.system())
.with_system(actions::concurrent_system.system())
.label("aggregate-actions"),
);
// run your actions in PreUpdate after aggregate-actions or in a later stage
app.add_system_to_stage(Last, thinker::thinker_component_attach_system.system());
app.add_system_to_stage(Last, thinker::thinker_component_detach_system.system());
app.add_system_to_stage(Last, thinker::actor_gone_cleanup.system());
} }
} }
use bevy::{app::AppExit, prelude::*};
use big_brain::{pickers, prelude::*};
#[test]
fn steps() {
println!("steps test");
App::build()
.add_plugins(MinimalPlugins)
.add_plugin(BigBrainPlugin)
.init_resource::<GlobalState>()
.add_startup_system(setup.system())
.add_system_to_stage(CoreStage::First, no_failure_score.system())
.add_system(action1.system())
.add_system(action2.system())
.add_system(exit_action.system())
.add_system(failure_action.system())
.add_system_to_stage(CoreStage::Last, last.system())
.run();
println!("end");
}
fn setup(mut cmds: Commands) {
cmds.spawn().insert(
Thinker::build()
.picker(pickers::FirstToScore::new(0.5))
.when(NoFailureScore, Steps::build().step(FailureAction))
.otherwise(Steps::build().step(Action1).step(Action2).step(ExitAction)),
);
}
#[derive(Default, Debug, Clone)]
struct Action1;
impl ActionBuilder for Action1 {
fn build(&self, cmd: &mut Commands, action: Entity, _actor: Entity) {
cmd.entity(action)
.insert(self.clone())
.insert(ActionState::Requested);
}
}
fn action1(mut query: Query<(&Actor, &mut ActionState), With<Action1>>) {
for (Actor(_actor), mut state) in query.iter_mut() {
println!("action1 {:?}", state);
if *state == ActionState::Requested {
*state = ActionState::Executing;
}
if *state == ActionState::Executing {
*state = ActionState::Success;
}
}
}
#[derive(Default, Debug, Clone)]
struct Action2;
impl ActionBuilder for Action2 {
fn build(&self, cmd: &mut Commands, action: Entity, _actor: Entity) {
cmd.entity(action)
.insert(self.clone())
.insert(ActionState::Requested);
}
}
fn action2(mut query: Query<(&Actor, &mut ActionState), With<Action2>>) {
for (Actor(_actor), mut state) in query.iter_mut() {
println!("action2 {:?}", state);
if *state == ActionState::Requested {
*state = ActionState::Executing;
}
if *state == ActionState::Executing {
*state = ActionState::Success;
}
}
}
#[derive(Default, Debug, Clone)]
struct ExitAction;
impl ActionBuilder for ExitAction {
fn build(&self, cmd: &mut Commands, action: Entity, _actor: Entity) {
cmd.entity(action)
.insert(self.clone())
.insert(ActionState::Requested);
}
}
fn exit_action(
mut query: Query<(&Actor, &mut ActionState), With<ExitAction>>,
mut app_exit_events: EventWriter<AppExit>,
) {
for (Actor(_actor), mut state) in query.iter_mut() {
println!("exit_action {:?}", state);
if *state == ActionState::Requested {
*state = ActionState::Executing;
}
if *state == ActionState::Executing {
app_exit_events.send(AppExit);
}
}
}
fn last() {
println!();
}
#[derive(Default, Debug, Clone)]
struct FailureAction;
impl ActionBuilder for FailureAction {
fn build(&self, cmd: &mut Commands, action: Entity, _actor: Entity) {
cmd.entity(action)
.insert(self.clone())
.insert(ActionState::Requested);
}
}
fn failure_action(
mut query: Query<(&Actor, &mut ActionState), With<FailureAction>>,
mut global_state: ResMut<GlobalState>,
) {
for (Actor(_actor), mut state) in query.iter_mut() {
println!("failure_action {:?}", state);
if *state == ActionState::Requested {
*state = ActionState::Executing;
}
if *state == ActionState::Executing {
global_state.failure = true;
*state = ActionState::Failure;
}
}
}
#[derive(Default)]
struct GlobalState {
failure: bool,
}
#[derive(Debug, Clone)]
struct NoFailureScore;
impl ScorerBuilder for NoFailureScore {
fn build(&self, cmd: &mut Commands, action: Entity, _actor: Entity) {
cmd.entity(action).insert(self.clone());
}
}
fn no_failure_score(
mut query: Query<(&NoFailureScore, &mut Score)>,
global_state: Res<GlobalState>,
) {
for (_, mut score) in query.iter_mut() {
score.set(if global_state.failure { 0.0 } else { 1.0 });
}
}
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