Crate big_brain[][src]

big-brain is a Utility AI library for games, built for the Bevy Game Engine

It lets you define complex, intricate AI behaviors for your entities based on their perception of the world. Definitions are heavily data-driven, using plain Rust, and you only need to program Scorers (entities that look at your game world and come up with a Score), and Actions (entities that perform actual behaviors upon the world). No other code is needed for actual AI behavior.

See the documentation for more details.

Features

  • Highly concurrent/parallelizable evaluation.
  • Integrates smoothly with Bevy.
  • Easy AI definition using idiomatic Rust builders. You don’t have to be some genius to define behavior that feels realistic to players.
  • High performance–supports hundreds of thousands of concurrent AIs.
  • Graceful degradation–can be configured such that the less frame time is available, the slower an AI might “seem”, without dragging down framerates, by simply processing fewer events per tick.
  • Proven game AI model.
  • Low code overhead–you only define two types of application-dependent things, and everything else is building blocks!
  • Highly composable and reusable.
  • State machine-style continuous actions/behaviors.
  • Action cancellation.

Example

First, you define actions and considerations, which are just plain old Bevy Components and Systems. As a developer, you write application-dependent code to define Scorers and Actions, and then put it all together like building blocks, using Thinkers that will define the actual behavior.

Scorers

Scorers are entities that look at the world and evaluate into Score values. You can think of them as the “eyes” of the AI system. They’re a highly-parallel way of being able to look at the World and use it to make some decisions later.

They are created by types that implement ScorerBuilder.

use bevy::prelude::*;
use big_brain::prelude::*;

#[derive(Debug, Clone)]
pub struct Thirsty;

impl Thirsty {
    fn build() -> ThirstyBuilder {
        ThirstyBuilder
    }
}

#[derive(Debug, Clone)]
pub struct ThirstyBuilder;

impl ScorerBuilder for ThirstyBuilder {
    fn build(&self, cmd: &mut Commands, scorer: Entity, _actor: Entity) {
        cmd.entity(scorer).insert(Thirsty);
    }
}

pub fn thirsty_scorer_system(
    thirsts: Query<&Thirst>,
    mut query: Query<(&Actor, &mut Score), With<Thirsty>>,
) {
    for (Actor(actor), mut score) in query.iter_mut() {
        if let Ok(thirst) = thirsts.get(*actor) {
            score.set(thirst.thirst);
        }
    }
}

Actions

Actions are the actual things your entities will do. They are connected to ActionStates, and are created by types implementing ActionBuilder.

use bevy::prelude::*;
use big_brain::prelude::*;

#[derive(Debug, Clone)]
pub struct Drink;

impl Drink {
    pub fn build() -> DrinkBuilder {
        DrinkBuilder
    }
}

#[derive(Debug, Clone)]
pub struct DrinkBuilder;

impl ActionBuilder for DrinkBuilder {
    fn build(&self, cmd: &mut Commands, action: Entity, _actor: Entity) {
        cmd.entity(action).insert(Drink);
    }
}

fn drink_action_system(
    mut thirsts: Query<&mut Thirst>,
    mut query: Query<(&Actor, &mut ActionState), With<Drink>>,
) {
    for (Actor(actor), mut state) in query.iter_mut() {
        if let Ok(mut thirst) = thirsts.get_mut(*actor) {
            match *state {
                ActionState::Requested => {
                    thirst.thirst = 10.0;
                    *state = ActionState::Success;
                }
                ActionState::Cancelled => {
                    *state = ActionState::Failure;
                }
                _ => {}
            }
        }
    }
}

Thinkers

Finally, you can use it when define the Thinker, which you can attach as a regular Component:

cmd.spawn().insert(Thirst::new(70.0, 2.0)).insert(
    Thinker::build()
        .picker(FirstToScore { threshold: 80.0 })
        .when(Thirsty::build(), Drink::build()),
);

Contributing

  1. Install the latest Rust toolchain (stable supported).
  2. cargo run --example thirst
  3. Happy hacking!

License

This project is licensed under the Parity License. Third-party contributions are licensed under Apache-2.0 and belong to their respective authors.

The Parity License is a copyleft license that, unlike the GPL family, allows you to license derivative and connected works under permissive licenses like MIT or Apache-2.0. It’s free to use provided the work you do is freely available!

For proprietary use, please contact me, or just sponsor me on GitHub under the appropriate tier to acquire a proprietary-use license! This funding model helps me make my work sustainable and compensates me for the work it took to write this crate!

Modules

actions

Defines Action-related functionality. This module includes the ActionBuilder trait and some Composite Actions for utility.

evaluators

Utilities for turning values of 0.0..=100.0 into different curves.

pickers

Pickers are used by Thinkers to determine which of its Scorers will “win”.

prelude

Convenience module with the core types you’re most likely to use when working with Big Brain. Mean to be used like use big_brain::prelude::*;

scorers

Scorers look at the world and boil down arbitrary characteristics into a range of 0.0..=100.0. This module includes the ScorerBuilder trait and some built-in Composite Scorers.

thinker

Thinkers are the “brain” of an entity. You attach Scorers to it, and the Thinker picks the right Action to run based on the resulting Scores.

Structs

BigBrainPlugin

Core [Plugin] for Big Brain behavior. Required for any of the Thinker-related magic to work.