Derive Macro big_brain_derive::Consideration [−][src]
#[derive(Consideration)] { // Attributes available to this derive: #[consideration] }
Consideration
s in big-brain
are defined through this derive macro. Once defined,
they can be freely used in a .ron file. While Action
s define behaviors,
Consideration
s are used to determine whether to execute a certain action.
Consideration
s are responsible for determining a specific Utility
, or score,
in Utility AI terms. This score is what sets Utility AI apart from plain old
Behavior Trees.
Like anything else in an Entity system, considerations and their behaviors
consist of a Component
and an associated System
.
Definition Example
ⓘ
use specs::{Component, Entity, ReadStorage, System, WriteStorage}; use big_brain::{Consideration, Utility}; // These are your game's components. use crate::components; // `Consideration`s are defined by deriving them -- they MUST be Components. #[derive(Debug, Component, Consideration)] pub struct Hunger { // All considerations **must** have a public `actor` field. This will be populated // with the actual actor considering the world around it The `Entity` associated with // the `Consideration` itself is distinct from the actor. pub actor: Entity, // `default` fields will be populated using default::Default() when the // Consideration is instantiated. These cannot be used as params. #[consideration(default)] pub evaluator: PowerEvaluator, // `param` fields will be populated using the value passed in through the // `.ron` file. #[consideration(param)] pub weight: f32, } pub struct ConsiderHunger; impl<'a> System<'a> for ConsiderHunger { type SystemData = ( ReadStorage<'a, components::Hunger>, // This is the actual `Consideration` component. WriteStorage<'a, Hunger>, // The `Utility` component associated with this `Consideration` holds // the current calculated score for that consideration. WriteStorage<'a, Utility>, ); fn run(&mut self, (hungers, mut considerers, mut utilities): Self::SystemData) { // Join the considerations with the utilities -- they share an `Entity`. for (conser, util) in (&mut considerers, &mut utilities).join() { // Any actor-related components must be fetched separately, based on // the consideration's `actor`. if let Some(hunger) = hungers.get(conser.actor.clone()) { *util = Utility { // values and weights can be arbitrary numbers. The final // score is based on combining these two values. // // Utilities with weight `0.0` are not used. // // For the formula, refer to the docs on `WeightedMeasure`. value: conser.evaluator.evaluate(hunger.hunger), weight: conser.weight, }; } } } }
Usage Example
ⓘ
( picker: {"FirstToScore": ()}, choices: [( // Considerations to use are defined using the `consider` param in choices. // A choice can have zero or more considerations. consider: [{"Hunger": (weight: 1.0)}], // This is the action that will be executed if this choice "wins". then: {"Eat": ()}, )] )