From 1a1d5b3d17d96a51084418128f0bfebe0ad8c702 Mon Sep 17 00:00:00 2001 From: alexander <alexanderpaullozada@gmail.com> Date: Wed, 28 Apr 2021 23:47:10 -0500 Subject: [PATCH] feat(scorers): Added EvaluatingScorer (#24) * Added EvaluatingScorer * fixed doc issue Co-authored-by: doomy <2640792-_doomy@users.noreply.gitlab.com> --- src/lib.rs | 1 + src/scorers.rs | 76 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 796c021..c4465f0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -201,5 +201,6 @@ impl Plugin for BigBrainPlugin { app.add_system(scorers::all_or_nothing_system.system()); app.add_system(scorers::sum_of_scorers_system.system()); app.add_system(scorers::winning_scorer_system.system()); + app.add_system(scorers::evaluating_scorer_system.system()); } } diff --git a/src/scorers.rs b/src/scorers.rs index b49b02b..eaa0843 100644 --- a/src/scorers.rs +++ b/src/scorers.rs @@ -6,7 +6,10 @@ use std::{cmp::Ordering, sync::Arc}; use bevy::prelude::*; -use crate::thinker::{Actor, ScorerEnt}; +use crate::{ + evaluators::Evaluator, + thinker::{Actor, ScorerEnt}, +}; /** Score value between `0.0..=1.0` associated with a Scorer. @@ -357,3 +360,74 @@ impl ScorerBuilder for WinningScorerBuilder { }); } } + +/** +Composite scorer that takes a `ScorerBuilder` and applies an `Evaluator`. Note that +unlike other composite scorers, `EvaluatingScorer` only takes one scorer upon building. + +### Example + +```ignore +Thinker::build() + .when( + EvaluatingScorer::build(MyScorer, MyEvaluator), + MyAction::build()); +``` + */ +#[derive(Debug, Clone)] +pub struct EvaluatingScorer { + scorer: ScorerEnt, + evaluator: Arc<dyn Evaluator>, +} + +impl EvaluatingScorer { + pub fn build( + scorer: impl ScorerBuilder + 'static, + evaluator: impl Evaluator + 'static, + ) -> EvaluatingScorerBuilder { + EvaluatingScorerBuilder { + evaluator: Arc::new(evaluator), + scorer: Arc::new(scorer), + } + } +} + +pub fn evaluating_scorer_system( + query: Query<(Entity, &EvaluatingScorer)>, + mut scores: QuerySet<(Query<&Score>, Query<&mut Score>)>, +) { + for (sos_ent, eval_scorer) in query.iter() { + // Get the inner score + let inner_score = scores + .q0() + .get(eval_scorer.scorer.0) + .expect("where did it go?") + .get(); + // Get composite score + let mut score = scores.q1_mut().get_mut(sos_ent).expect("where did it go?"); + score.set(crate::evaluators::clamp( + eval_scorer.evaluator.evaluate(inner_score), + 0.0, + 1.0, + )); + } +} + +#[derive(Debug, Clone)] +pub struct EvaluatingScorerBuilder { + pub scorer: Arc<dyn ScorerBuilder>, + pub evaluator: Arc<dyn Evaluator>, +} + +impl ScorerBuilder for EvaluatingScorerBuilder { + fn build(&self, cmd: &mut Commands, scorer: Entity, actor: Entity) { + let inner_scorer = self.scorer.attach(cmd, actor); + cmd.entity(scorer) + .insert(Transform::default()) + .insert(GlobalTransform::default()) + .insert(EvaluatingScorer { + evaluator: self.evaluator.clone(), + scorer: ScorerEnt(inner_scorer), + }); + } +} -- GitLab