gizmo_ai/
behavior_tree.rs1use gizmo_core::World;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum BtStatus {
6 Success,
7 Failure,
8 Running,
9}
10
11pub trait BtNode: Send + Sync {
13 fn tick(&mut self, entity: u32, world: &mut World, dt: f32) -> BtStatus;
15}
16
17pub struct Sequence {
20 children: Vec<Box<dyn BtNode>>,
21 current_idx: usize,
22}
23
24impl Sequence {
25 pub fn new(children: Vec<Box<dyn BtNode>>) -> Self {
26 Self {
27 children,
28 current_idx: 0,
29 }
30 }
31}
32
33impl BtNode for Sequence {
34 fn tick(&mut self, entity: u32, world: &mut World, dt: f32) -> BtStatus {
35 while self.current_idx < self.children.len() {
36 let status = self.children[self.current_idx].tick(entity, world, dt);
37 match status {
38 BtStatus::Success => {
39 self.current_idx += 1; }
41 BtStatus::Failure => {
42 self.current_idx = 0; return BtStatus::Failure;
44 }
45 BtStatus::Running => {
46 return BtStatus::Running;
47 }
48 }
49 }
50 self.current_idx = 0; BtStatus::Success
52 }
53}
54
55pub struct Selector {
58 children: Vec<Box<dyn BtNode>>,
59 current_idx: usize,
60}
61
62impl Selector {
63 pub fn new(children: Vec<Box<dyn BtNode>>) -> Self {
64 Self {
65 children,
66 current_idx: 0,
67 }
68 }
69}
70
71impl BtNode for Selector {
72 fn tick(&mut self, entity: u32, world: &mut World, dt: f32) -> BtStatus {
73 while self.current_idx < self.children.len() {
74 let status = self.children[self.current_idx].tick(entity, world, dt);
75 match status {
76 BtStatus::Success => {
77 self.current_idx = 0; return BtStatus::Success;
79 }
80 BtStatus::Failure => {
81 self.current_idx += 1; }
83 BtStatus::Running => {
84 return BtStatus::Running;
85 }
86 }
87 }
88 self.current_idx = 0; BtStatus::Failure
90 }
91}
92
93pub struct Inverter {
95 child: Box<dyn BtNode>,
96}
97
98impl Inverter {
99 pub fn new(child: Box<dyn BtNode>) -> Self {
100 Self { child }
101 }
102}
103
104impl BtNode for Inverter {
105 fn tick(&mut self, entity: u32, world: &mut World, dt: f32) -> BtStatus {
106 match self.child.tick(entity, world, dt) {
107 BtStatus::Success => BtStatus::Failure,
108 BtStatus::Failure => BtStatus::Success,
109 BtStatus::Running => BtStatus::Running,
110 }
111 }
112}
113
114pub struct Action<F>
116where
117 F: FnMut(u32, &mut World, f32) -> BtStatus + Send + Sync,
118{
119 func: F,
120}
121
122impl<F> Action<F>
123where
124 F: FnMut(u32, &mut World, f32) -> BtStatus + Send + Sync,
125{
126 pub fn new(func: F) -> Self {
127 Self { func }
128 }
129}
130
131impl<F> BtNode for Action<F>
132where
133 F: FnMut(u32, &mut World, f32) -> BtStatus + Send + Sync,
134{
135 fn tick(&mut self, entity: u32, world: &mut World, dt: f32) -> BtStatus {
136 (self.func)(entity, world, dt)
137 }
138}
139
140pub struct Condition<F>
142where
143 F: FnMut(u32, &mut World) -> bool + Send + Sync,
144{
145 func: F,
146}
147
148impl<F> Condition<F>
149where
150 F: FnMut(u32, &mut World) -> bool + Send + Sync,
151{
152 pub fn new(func: F) -> Self {
153 Self { func }
154 }
155}
156
157impl<F> BtNode for Condition<F>
158where
159 F: FnMut(u32, &mut World) -> bool + Send + Sync,
160{
161 fn tick(&mut self, entity: u32, world: &mut World, _dt: f32) -> BtStatus {
162 if (self.func)(entity, world) {
163 BtStatus::Success
164 } else {
165 BtStatus::Failure
166 }
167 }
168}
169
170pub struct BehaviorTree {
172 pub root: Option<Box<dyn BtNode>>,
173}
174
175impl gizmo_core::component::Component for BehaviorTree {}
176
177impl Clone for BehaviorTree {
178 fn clone(&self) -> Self {
179 panic!("BehaviorTree cannot be cloned!");
180 }
181}
182
183impl BehaviorTree {
184 pub fn new(root: Box<dyn BtNode>) -> Self {
185 Self { root: Some(root) }
186 }
187
188 pub fn tick(&mut self, entity: u32, world: &mut World, dt: f32) -> BtStatus {
189 if let Some(root) = &mut self.root {
190 root.tick(entity, world, dt)
191 } else {
192 BtStatus::Failure
193 }
194 }
195}
196
197pub fn behavior_tree_system(world: &mut World, dt: f32) {
199 let entities: Vec<u32> = {
200 let trees = world.borrow_mut::<BehaviorTree>();
201 trees.entities().collect()
202 };
203
204 for entity in entities {
205 let mut root_opt = None;
206 if let Some(mut tree) = world.borrow_mut::<BehaviorTree>().get_mut(entity) {
207 root_opt = tree.root.take();
208 }
209
210 if let Some(mut root) = root_opt {
211 root.tick(entity, world, dt);
212
213 if let Some(mut tree) = world.borrow_mut::<BehaviorTree>().get_mut(entity) {
214 tree.root = Some(root);
215 }
216 }
217 }
218}