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
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
//! Behavior tree builder.

use crate::{
    condition::*,
    decision_makers::{parallelizer::*, selector::*, sequencer::*},
    task::*,
};

/// Wrapper around task produced by [`BehaviorTree`] builder.
pub struct BehaviorTreeTask<M = ()>(pub Box<dyn Task<M>>);

impl<M> Task<M> for BehaviorTreeTask<M> {
    fn is_locked(&self, memory: &M) -> bool {
        self.0.is_locked(memory)
    }

    fn on_enter(&mut self, memory: &mut M) {
        self.0.on_enter(memory);
    }

    fn on_exit(&mut self, memory: &mut M) {
        self.0.on_exit(memory);
    }

    fn on_update(&mut self, memory: &mut M) {
        self.0.on_update(memory);
    }

    fn on_process(&mut self, memory: &mut M) -> bool {
        self.0.on_process(memory)
    }
}

impl<M> std::fmt::Debug for BehaviorTreeTask<M> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("BehaviorTreeTask").finish()
    }
}

/// Builds hierarchy of decision makers that work together just as behavior tree.
///
/// Behavior trees are commonly used AI technique that alows to organize AI choices and sequences
/// of tasks that agent has to perform in a tree manner. Tree is always executed from the top-left
/// to the bottom-right, which means it starts at the root and when finds branching (sequence or
/// selector) it will try to execute each children in a set from first to last.
///
/// - __Sequence__ (equivalent of boolean AND operation):
///
///   Runs its children one by one until one fails and sequence stops there.
///
/// - __Selector__ (equivalent of boolean OR operation):
///
///   Will always run only one child node at a time, first one that's condition returns true.
///
/// It's worth noting that sequences and selectors won't switch their nodes as long as currently
/// running node reports [`Task::is_locked`] true (this means node is running and nothing should
/// interrupt its work).
///
/// How it works
/// ---
/// Imagine you have tree like this:
/// - selector:
///   - sequence (is hungry?):
///     - Find food (is there food nearby?)
///     - Eat (is found food edible?)
///   - sequence (is low energy?):
///     - Find safe place (is there a cave nearby?)
///     - Sleep (is there no bear nearby?)
///   - Do nothing (always succeeds)
///
/// We are gonna run this tree against initial memory state:
/// - hungry: false
/// - food nearby: true
/// - edible food: true
/// - low energy: false
/// - cave nearby: false
/// - bear nearby: true
///
/// Starting from the root selector we get two options to test their conditions, first one won't run
/// because agent is not hungry, then second one also won't run because agent doesn't have low energy.
/// What's left is __do nothing__ which always secceeds.
///
/// Now we change our state:
/// - hungry: false
/// - food nearby: true
/// - edible food: true
/// - __low energy: true__
/// - cave nearby: false
/// - bear nearby: true
///
/// We again start at selector and test its children conditions: first node won't run because agent
/// still isn't hungry, but we will run second node because agent __has low energy__.
/// Now since we have activated sleeping sequence we try to run each child node as long as they
/// succeed: we can't find safe place since there is no cave nearby, and because that node has
/// failed it ended the sequence, so we won't try to sleep.
///
/// We change our state again:
/// - __hungry: true__
/// - food nearby: true
/// - edible food: true
/// - low energy: true
/// - cave nearby: false
/// - bear nearby: true
///
/// We are gonna run forst sequence since agent __is hungry__, in that sequence we __find food nearby__
/// and we __eat it__ since it is edible, and that has completed the sequence.
///
/// See: [https://en.wikipedia.org/wiki/Behavior_tree_(artificial_intelligence,_robotics_and_control)](https://en.wikipedia.org/wiki/Behavior_tree_(artificial_intelligence,_robotics_and_control))
///
/// # Example
/// ```
/// use emergent::prelude::*;
///
/// struct Memory {
///     mode: bool,
///     counter: usize,
/// }
///
/// struct Countdown(pub usize);
///
/// impl Task<Memory> for Countdown {
///     fn is_locked(&self, memory: &Memory) -> bool {
///         memory.counter > 0
///     }
///
///     fn on_enter(&mut self, memory: &mut Memory) {
///         memory.counter = self.0;
///     }
///
///     fn on_update(&mut self, memory: &mut Memory) {
///         memory.counter = memory.counter.max(1) - 1;
///     }
/// }
///
/// struct FlipMode;
///
/// impl Task<Memory> for FlipMode {
///     fn on_enter(&mut self, memory: &mut Memory) {
///         memory.mode = !memory.mode;
///     }
/// }
///
/// struct IsMode(pub bool);
///
/// impl Condition<Memory> for IsMode {
///     fn validate(&self, memory: &Memory) -> bool {
///         memory.mode == self.0
///     }
/// }
///
/// // we define a tree that will perform ping-pong with delay:
/// // first we wait 2 turns, flip memory state, then wait 1 turn and flip back memory state.
/// let mut tree = BehaviorTree::selector(true)
///     .node(
///         BehaviorTree::sequence(IsMode(true))
///             .node(BehaviorTree::state(true, Countdown(2)))
///             .node(BehaviorTree::state(true, FlipMode)),
///     )
///     .node(
///         BehaviorTree::sequence(IsMode(false))
///             .node(BehaviorTree::state(true, Countdown(1)))
///             .node(BehaviorTree::state(true, FlipMode)),
///     )
///     .build();
///
/// let mut memory = Memory {
///     mode: true,
///     counter: 0,
/// };
///
/// assert_eq!(tree.on_process(&mut memory), true);
/// assert_eq!(memory.mode, true);
/// assert_eq!(memory.counter, 2);
///
/// assert_eq!(tree.on_process(&mut memory), false);
/// tree.on_update(&mut memory);
/// assert_eq!(memory.mode, true);
/// assert_eq!(memory.counter, 1);
///
/// assert_eq!(tree.on_process(&mut memory), false);
/// tree.on_update(&mut memory);
/// assert_eq!(memory.mode, true);
/// assert_eq!(memory.counter, 0);
///
/// assert_eq!(tree.on_process(&mut memory), true);
///
/// assert_eq!(tree.on_process(&mut memory), true);
/// assert_eq!(memory.mode, false);
/// assert_eq!(memory.counter, 1);
///
/// assert_eq!(tree.on_process(&mut memory), false);
/// tree.on_update(&mut memory);
/// assert_eq!(memory.mode, false);
/// assert_eq!(memory.counter, 0);
///
/// assert_eq!(tree.on_process(&mut memory), true);
/// assert_eq!(memory.mode, true);
/// ```
pub enum BehaviorTree<M = ()> {
    /// Sequence node runs its children as long as they succeed (boolean AND operation).
    ///
    /// It locks changes of higher nodes as long as its running child node is locked.
    Sequence {
        condition: Box<dyn Condition<M>>,
        nodes: Vec<BehaviorTree<M>>,
    },
    /// Selector node runs its first children that succeeds (boolean OR operation).
    ///
    /// It locks changes of higher nodes as long as its running child node is locked.
    Selector {
        condition: Box<dyn Condition<M>>,
        nodes: Vec<BehaviorTree<M>>,
    },
    /// Parallel node runs all its children at the same time.
    ///
    /// It locks changes of higher nodes as long as any of its running children nodes is locked.
    Parallel {
        condition: Box<dyn Condition<M>>,
        nodes: Vec<BehaviorTree<M>>,
    },
    /// State runs certain task.
    ///
    /// it locks changes of higher nodes as long as its task is locked.
    State {
        condition: Box<dyn Condition<M>>,
        task: Box<dyn Task<M>>,
    },
}

impl<M> BehaviorTree<M> {
    /// Constructs sequence node with condition.
    pub fn sequence<C>(condition: C) -> Self
    where
        C: Condition<M> + 'static,
    {
        Self::Sequence {
            condition: Box::new(condition),
            nodes: vec![],
        }
    }

    /// Constructs sequence node with condition and child nodes.
    pub fn sequence_nodes<C>(condition: C, nodes: Vec<BehaviorTree<M>>) -> Self
    where
        C: Condition<M> + 'static,
    {
        Self::Sequence {
            condition: Box::new(condition),
            nodes,
        }
    }

    /// Constructs selector node with condition.
    pub fn selector<C>(condition: C) -> Self
    where
        C: Condition<M> + 'static,
    {
        Self::Selector {
            condition: Box::new(condition),
            nodes: vec![],
        }
    }

    /// Constructs selector node with condition and child nodes.
    pub fn selector_nodes<C>(condition: C, nodes: Vec<BehaviorTree<M>>) -> Self
    where
        C: Condition<M> + 'static,
    {
        Self::Selector {
            condition: Box::new(condition),
            nodes,
        }
    }

    /// Constructs parallel node with condition.
    pub fn parallel<C>(condition: C) -> Self
    where
        C: Condition<M> + 'static,
    {
        Self::Parallel {
            condition: Box::new(condition),
            nodes: vec![],
        }
    }

    /// Constructs parallel node with condition and child nodes.
    pub fn parallel_nodes<C>(condition: C, nodes: Vec<BehaviorTree<M>>) -> Self
    where
        C: Condition<M> + 'static,
    {
        Self::Selector {
            condition: Box::new(condition),
            nodes,
        }
    }

    /// Constructs state node with condition and task.
    pub fn state<C, T>(condition: C, task: T) -> Self
    where
        C: Condition<M> + 'static,
        T: Task<M> + 'static,
    {
        Self::State {
            condition: Box::new(condition),
            task: Box::new(task),
        }
    }

    /// Adds child node to this branch (when called on state node it does nothing).
    pub fn node(mut self, node: BehaviorTree<M>) -> Self {
        match &mut self {
            Self::Sequence { nodes, .. } => nodes.push(node),
            Self::Selector { nodes, .. } => nodes.push(node),
            Self::Parallel { nodes, .. } => nodes.push(node),
            Self::State { .. } => {}
        }
        self
    }

    /// Consumes this builder and builds final tree as a task.
    pub fn build(self) -> BehaviorTreeTask<M>
    where
        M: 'static,
    {
        BehaviorTreeTask(self.consume().1)
    }

    /// Consumes this builder and returns its rot condition and root task.
    pub fn consume(self) -> (Box<dyn Condition<M>>, Box<dyn Task<M>>)
    where
        M: 'static,
    {
        match self {
            Self::Sequence { condition, nodes } => {
                let states = nodes
                    .into_iter()
                    .map(|node| {
                        let (condition, task) = node.consume();
                        SequencerState::new_raw(condition, task)
                    })
                    .collect();
                let sequencer = Sequencer::new(states, false, false);
                (condition, Box::new(sequencer))
            }
            Self::Selector { condition, nodes } => {
                let states = nodes
                    .into_iter()
                    .enumerate()
                    .map(|(index, node)| {
                        let (condition, task) = node.consume();
                        (index, SelectorState::new_raw(condition, task))
                    })
                    .collect();
                let selector = Selector::new(OrderedSelectorStatePicker::First, states);
                (condition, Box::new(selector))
            }
            Self::Parallel { condition, nodes } => {
                let states = nodes
                    .into_iter()
                    .map(|node| {
                        let (condition, task) = node.consume();
                        ParallelizerState::new_raw(condition, task)
                    })
                    .collect();
                let selector = Parallelizer::new(states);
                (condition, Box::new(selector))
            }
            Self::State { condition, task } => (condition, task),
        }
    }
}

impl<M> std::fmt::Debug for BehaviorTree<M> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::Sequence { nodes, .. } => {
                f.debug_struct("Sequence").field("nodes", &nodes).finish()
            }
            Self::Selector { nodes, .. } => {
                f.debug_struct("Selector").field("nodes", &nodes).finish()
            }
            Self::Parallel { nodes, .. } => {
                f.debug_struct("Parallel").field("nodes", &nodes).finish()
            }
            Self::State { .. } => f.debug_struct("State").finish(),
        }
    }
}