Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
//! `big-brain` is a [Utility
//! AI](https://en.wikipedia.org/wiki/Utility_system) library for implementing
//! rich, complex artificial intelligence mainly in video games using the
//! [`specs`](https://docs.rs/specs) ECS system.
//!
//! `big-brain` not only allows you to define these complex behaviors, but it
//! allows you to define them in a data-oriented format, such as
//! [`RON`](https://docs.rs/ron), potentially allowing non-programmers to
//! define many of these behaviors themselves.
//!
//! In general, the only things that need to be programmed are
//! [Actions](derive.Action.html) and
//! [Considerations](derive.Consideration.html). Everything else is included
//! with `big-brain`.
//!
//! For example, this is what a basic thinker might look like:
//!
//! ```ignore
//! // basic_needs.ron
//! (
//! // The first Choice to score above the threshold will be executed.
//! picker: {"FirstToScore": (threshold: 80.0)},
//! // A list of choices, with their considerations evaluated in order,
//! // and picked using the Picker.
//! choices: [(
//! consider: [{"Bladder": ()}],
//! then: {"Pee": ()},
//! ), (
//! consider: [{"Hunger": ()}],
//! // Thinkers are also actions, so you can nest them indefinitely.
//! then: {"Thinker": (
//! picker: {"FirstToScore": (threshold: 80.0)},
//! choices: [(
//! consider: [{"FoodInRange": (range: 10.0)}],
//! then: {"EatFood": (range: 10.0)}
//! ), (
//! consider: [{"FoodNearby": (range: 1000.0)}],
//! then: {"WalkToFood": (range: 1000.0)}
//! )]
//! )},
//! )],
//! // If no Choice goes over the threshold, we just... wander around
//! otherwise: Some({"Meander": ()})
//! )
//! ```
//!
//! You would then load up the component into a `specs` entity like so:
//!
//! ```no_run
//! use big_brain::ThinkerBuilder;
//! use specs::{Entities, Entity, LazyUpdate, World, WorldExt};
//! let mut world = World::new();
//! let entity = world.create_entity().build();
//! world.exec(|(entities, lazy): (Entities, Read<LazyUpdate>)| {
//! ThinkerBuilder::load_from("./path/to/basic.ron").build(entity, &entities, &lazy);
//! });
//! ```
use specs::{World, WorldExt};
pub use big_brain_derive::*;
pub use serde;
pub use specs as ecs;
pub use typetag;
pub use actions::*;
pub use choices::*;
pub use considerations::*;
pub use thinker::*;
pub mod evaluators;
pub mod measures;
pub mod pickers;
mod actions;
mod choices;
mod considerations;
mod stopwatch;
mod thinker;
pub fn register(world: &mut World) {
world.register::<Utility>();
world.register::<ActionState>();
world.register::<ActionManagerWrapper>();
world.register::<ActiveThinker>();
world.register::<Thinker>();
}