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

added composite scorers!

Fixes: https://github.com/zkat/big-brain/issues/4
parent a0d3b2a9
No related branches found
No related tags found
No related merge requests found
......@@ -24,7 +24,6 @@ pub fn thirst_system(time: Res<Time>, mut thirsts: Query<&mut Thirst>) {
if thirst.thirst >= 100.0 {
thirst.thirst = 100.0;
}
println!("Thirst: {}", thirst.thirst);
}
}
......@@ -105,6 +104,7 @@ pub fn thirsty_scorer_system(
//
// The score here must be between 0.0 and 100.0.
score.set(thirst.thirst);
println!("Thirst: {}", thirst.thirst);
}
}
}
......
......@@ -140,7 +140,7 @@ impl Default for SigmoidEvaluator {
}
}
fn clamp<T: PartialOrd>(val: T, min: T, max: T) -> T {
pub(crate) fn clamp<T: PartialOrd>(val: T, min: T, max: T) -> T {
let val = if val > max { max } else { val };
if val < min {
min
......
......@@ -23,5 +23,8 @@ pub struct BigBrainPlugin;
impl Plugin for BigBrainPlugin {
fn build(&self, app: &mut AppBuilder) {
app.add_system(thinker_system.system());
app.add_system(fixed_score_system.system());
app.add_system(all_or_nothing_system.system());
app.add_system(sum_of_scorers_system.system());
}
}
......@@ -6,6 +6,9 @@ use crate::ScorerEnt;
pub struct Score(pub(crate) f32);
impl Score {
pub fn get(&self) -> f32 {
self.0
}
pub fn set(&mut self, value: f32) {
if !(0.0..=100.0).contains(&value) {
panic!("Score value must be between 0.0 and 100.0");
......@@ -21,3 +24,155 @@ This trait defines new Scorers. In general, you should use the [derive macro](de
pub trait Scorer: std::fmt::Debug + Sync + Send {
fn build(&self, entity: Entity, cmd: &mut Commands) -> ScorerEnt;
}
#[derive(Debug)]
pub struct FixedScore(f32);
pub fn fixed_score_system(mut query: Query<(&FixedScore, &mut Score)>) {
for (FixedScore(fixed), mut score) in query.iter_mut() {
score.set(*fixed);
}
}
mod fixed_score {
use super::*;
use serde::Deserialize;
#[derive(Debug, Deserialize)]
struct FixedScore(f32);
#[typetag::deserialize]
impl Scorer for FixedScore {
fn build(&self, actor: Entity, cmd: &mut Commands) -> ScorerEnt {
let ent = ScorerEnt(cmd.spawn().id());
cmd.entity(ent.0)
.insert(Score::default())
.insert(super::FixedScore(self.0));
cmd.entity(actor).push_children(&[ent.0]);
ent
}
}
}
#[derive(Debug)]
pub struct AllOrNothing {
threshold: f32,
scorers: Vec<ScorerEnt>,
}
pub fn all_or_nothing_system(query: Query<(Entity, &AllOrNothing)>, mut scores: Query<&mut Score>) {
for (
aon_ent,
AllOrNothing {
threshold,
scorers: children,
},
) in query.iter()
{
let mut sum = 0.0;
for ScorerEnt(child) in children.iter() {
let score = scores.get_mut(*child).expect("where is it?");
if score.0 < *threshold {
sum = 0.0;
break;
} else {
sum += score.0;
}
}
let mut score = scores.get_mut(aon_ent).expect("where did it go?");
score.set(crate::evaluators::clamp(sum, 0.0, 100.0));
}
}
mod all_or_nothing {
use super::*;
use serde::Deserialize;
#[derive(Debug, Deserialize)]
struct AllOrNothing {
threshold: f32,
scorers: Vec<Box<dyn Scorer>>,
}
#[typetag::deserialize]
impl Scorer for AllOrNothing {
fn build(&self, actor: Entity, cmd: &mut Commands) -> ScorerEnt {
let ent = ScorerEnt(cmd.spawn().id());
let scorers: Vec<_> = self
.scorers
.iter()
.map(|scorer| scorer.build(actor, cmd).0)
.collect();
cmd.entity(ent.0)
.insert(Score::default())
.insert(super::AllOrNothing {
threshold: self.threshold,
scorers: scorers.into_iter().map(ScorerEnt).collect(),
});
cmd.entity(actor).push_children(&[ent.0]);
ent
}
}
}
#[derive(Debug)]
pub struct SumOfScorers {
threshold: f32,
scorers: Vec<ScorerEnt>,
}
pub fn sum_of_scorers_system(query: Query<(Entity, &SumOfScorers)>, mut scores: Query<&mut Score>) {
for (
sos_ent,
SumOfScorers {
threshold,
scorers: children,
},
) in query.iter()
{
let mut sum = 0.0;
for ScorerEnt(child) in children.iter() {
let score = scores.get_mut(*child).expect("where is it?");
sum += score.0;
}
if sum < *threshold {
sum = 0.0;
}
let mut score = scores.get_mut(sos_ent).expect("where did it go?");
score.set(crate::evaluators::clamp(sum, 0.0, 100.0));
}
}
mod sum_of_scorers {
use super::*;
use serde::Deserialize;
#[derive(Debug, Deserialize)]
struct SumOfScorers {
threshold: f32,
scorers: Vec<Box<dyn Scorer>>,
}
#[typetag::deserialize]
impl Scorer for SumOfScorers {
fn build(&self, actor: Entity, cmd: &mut Commands) -> ScorerEnt {
let ent = ScorerEnt(cmd.spawn().id());
let scorers: Vec<_> = self
.scorers
.iter()
.map(|scorer| scorer.build(actor, cmd).0)
.collect();
cmd.entity(ent.0)
.insert(Score::default())
.insert(super::AllOrNothing {
threshold: self.threshold,
scorers: scorers.into_iter().map(ScorerEnt).collect(),
});
cmd.entity(actor).push_children(&[ent.0]);
ent
}
}
}
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