Skip to main content

veloren_rtsim/ai/
mod.rs

1pub mod predicate;
2
3use predicate::Predicate;
4use rand::RngExt;
5
6use crate::data::{
7    Data, ReportId, Sentiments,
8    actor::{Actor, ActorId, Controller, Npc},
9};
10use common::{
11    comp::{self, gizmos::RtsimGizmos},
12    resources::{Time, TimeOfDay},
13    rtsim::NpcInput,
14    shared_server_config::ServerConstants,
15    uid::IdMaps,
16    weather::WeatherGrid,
17};
18use hashbrown::HashSet;
19use itertools::Either;
20use rand_chacha::ChaChaRng;
21use specs::{ReadExpect, ReadStorage, SystemData, WriteExpect, WriteStorage, shred};
22use std::{any::Any, collections::VecDeque, marker::PhantomData, ops::ControlFlow, sync::Mutex};
23use world::{IndexRef, World};
24
25pub trait State: Clone + Send + Sync + 'static {}
26
27impl<T: Clone + Send + Sync + 'static> State for T {}
28
29#[derive(Clone, Copy)]
30struct Resettable<T> {
31    original: T,
32    current: T,
33}
34
35impl<T: Clone> From<T> for Resettable<T> {
36    fn from(value: T) -> Self {
37        Self {
38            original: value.clone(),
39            current: value,
40        }
41    }
42}
43
44impl<T: Clone> Resettable<T> {
45    fn reset(&mut self) { self.current = self.original.clone(); }
46}
47
48impl<T> std::ops::Deref for Resettable<T> {
49    type Target = T;
50
51    fn deref(&self) -> &Self::Target { &self.current }
52}
53
54impl<T> std::ops::DerefMut for Resettable<T> {
55    fn deref_mut(&mut self) -> &mut Self::Target { &mut self.current }
56}
57
58/// The context provided to an [`Action`] while it is being performed. It should
59/// be possible to access any and all important information about the game world
60/// through this struct.
61pub struct NpcCtx<'a, 'd> {
62    pub data: &'a Data,
63    pub world: &'a World,
64    pub index: IndexRef<'a>,
65
66    pub time_of_day: TimeOfDay,
67    pub time: Time,
68
69    pub actor_id: ActorId,
70    pub actor: &'a Actor,
71    pub npc: &'a Npc,
72    pub controller: &'a mut Controller,
73    pub inbox: &'a mut VecDeque<NpcInput>, // TODO: Allow more inbox items
74    pub sentiments: &'a mut Sentiments,
75    pub known_reports: &'a mut HashSet<ReportId>,
76    pub gizmos: Option<&'a mut Vec<comp::gizmos::Gizmos>>,
77
78    /// The delta time since this npcs ai was last ran.
79    pub dt: f32,
80    pub rng: ChaChaRng,
81    pub system_data: &'a ActorSystemData<'d>,
82
83    /// Used to determine the current action priority. Lower priority actions
84    /// may be overridden by higher priority actions in a different part of
85    /// the behaviour tree.
86    pub current_action_priority: u32,
87}
88
89fn discrete_chance(dt: f64, chance_per_second: f64) -> f64 {
90    if dt <= 1.0 {
91        (dt * chance_per_second).clamp(0.0, 1.0)
92    } else {
93        let n_chance = 1.0 - chance_per_second.clamp(0.0, 1.0);
94        1.0 - n_chance.powf(dt)
95    }
96}
97
98#[test]
99fn test_discrete_chance() {
100    // 0.2 chance per second over 10 seconds = ~89%
101    let p = discrete_chance(10.0, 0.2);
102    assert!((p - 0.89).abs() < 0.005);
103}
104
105impl NpcCtx<'_, '_> {
106    /// Chance for something to happen each second.
107    pub fn chance(&mut self, chance: f64) -> bool {
108        let p = discrete_chance(self.dt as f64, chance);
109        self.rng.random_bool(p)
110    }
111
112    pub fn gizmos(&mut self, gizmos: comp::gizmos::Gizmos) {
113        if let Some(gizmos_buffer) = self.gizmos.as_mut() {
114            gizmos_buffer.push(gizmos);
115        }
116    }
117}
118
119#[derive(SystemData)]
120pub struct ActorSystemData<'a> {
121    pub positions: ReadStorage<'a, comp::Pos>,
122    pub id_maps: ReadExpect<'a, IdMaps>,
123    pub server_constants: ReadExpect<'a, ServerConstants>,
124    pub weather_grid: ReadExpect<'a, WeatherGrid>,
125    pub rtsim_gizmos: WriteExpect<'a, RtsimGizmos>,
126    pub ability_map: ReadExpect<'a, comp::tool::AbilityMap>,
127    pub msm: ReadExpect<'a, comp::item::MaterialStatManifest>,
128    pub inventories: Mutex<WriteStorage<'a, comp::Inventory>>,
129}
130
131/// A trait that describes 'actions': long-running tasks performed by rtsim
132/// NPCs. These can be as simple as walking in a straight line between two
133/// locations or as complex as taking part in an adventure with players or
134/// performing an entire daily work schedule.
135///
136/// Actions are built up from smaller sub-actions via the combinator methods
137/// defined on this trait, and with the standalone functions in this module.
138/// Using these combinators, in a similar manner to using the [`Iterator`] API,
139/// it is possible to construct arbitrarily complex actions including behaviour
140/// trees (see [`choose`] and [`watch`]) and other forms of moment-by-moment
141/// decision-making.
142///
143/// On completion, actions may produce a value, denoted by the type parameter
144/// `R`. For example, an action may communicate whether it was successful or
145/// unsuccessful through this completion value.
146///
147/// You should not need to implement this trait yourself when writing AI code.
148/// If you find yourself wanting to implement it, please discuss with the core
149/// dev team first.
150pub trait Action<S = (), R = ()>: Any + Send + Sync {
151    /// Generate a backtrace for the action. The action should recursively push
152    /// all of the tasks it is currently performing.
153    fn backtrace(&self, bt: &mut Vec<String>);
154
155    /// Reset the action to its initial state such that it can be repeated.
156    fn reset(&mut self);
157
158    /// Perform logic when the event gets unexpectedly cancelled.
159    ///
160    /// This function should be invoked recursively, with inner actions being
161    /// invoked before later ones.
162    fn on_cancel(&mut self, ctx: &mut NpcCtx, state: &mut S);
163
164    /// Perform the action for the current tick.
165    fn tick(&mut self, ctx: &mut NpcCtx, state: &mut S) -> ControlFlow<R>;
166
167    /// Create an action that chains together two sub-actions, one after the
168    /// other.
169    ///
170    /// # Example
171    ///
172    /// ```ignore
173    /// // Walk toward an enemy NPC and, once done, attack the enemy NPC
174    /// goto(enemy_npc).then(attack(enemy_npc))
175    /// ```
176    #[must_use]
177    fn then<A1: Action<S, R1>, R1>(self, other: A1) -> Then<Self, A1, R>
178    where
179        Self: Sized,
180    {
181        Then {
182            a0: self,
183            a0_finished: false,
184            a1: other,
185            phantom: PhantomData,
186        }
187    }
188
189    /// Like `Action::then`, except the second action may be configured by the
190    /// output of the first.
191    ///
192    /// # Example
193    ///
194    /// ```ignore
195    /// ask_question("Is it sunny?").and_then(|response| match response {
196    ///     true => say("Good, I like sunshine"),
197    ///     false => say("Shame, I'll get my coat"),
198    /// })
199    /// ```
200    #[must_use]
201    fn and_then<F, A1: Action<S, R1>, R1>(self, f: F) -> AndThen<Self, F, A1, R>
202    where
203        Self: Sized,
204    {
205        AndThen {
206            a0: self,
207            f,
208            a1: None,
209            phantom: PhantomData,
210        }
211    }
212
213    /// Create an action that repeats a sub-action indefinitely.
214    ///
215    /// # Example
216    ///
217    /// ```ignore
218    /// // Endlessly collect flax from the environment
219    /// find_and_collect(TerrainResource::Flax).repeat()
220    /// ```
221    #[must_use]
222    fn repeat(self) -> Repeat<Self, R>
223    where
224        Self: Sized,
225    {
226        Repeat(self, PhantomData)
227    }
228
229    /// Stop the sub-action suddenly if a condition is reached.
230    ///
231    /// # Example
232    ///
233    /// ```ignore
234    /// // Keep going on adventures until your 111th birthday
235    /// go_on_an_adventure().repeat().stop_if(|ctx| ctx.npc.age > 111.0)
236    /// ```
237    #[must_use]
238    fn stop_if<P: Predicate + Clone>(self, p: P) -> StopIf<Self, P>
239    where
240        Self: Sized,
241    {
242        StopIf(self, p.into())
243    }
244
245    /// Perform some logic if the action is cancelled early.
246    #[must_use]
247    fn when_cancelled<F: Fn(&mut NpcCtx) + Send + Sync + 'static>(
248        self,
249        f: F,
250    ) -> WhenCancelled<Self, F>
251    where
252        Self: Sized,
253    {
254        WhenCancelled(self, f)
255    }
256
257    /// Pause an action to possibly perform another action.
258    ///
259    /// # Example
260    ///
261    /// ```ignore
262    /// // Keep going on adventures until your 111th birthday
263    /// walk_to_the_shops()
264    ///     .interrupt_with(|ctx| if ctx.npc.is_hungry() {
265    ///         Some(eat_food())
266    ///     } else {
267    ///         None
268    ///     })
269    /// ```
270    #[must_use]
271    fn interrupt_with<
272        A1: Action<S, R1>,
273        R1,
274        F: Fn(&mut NpcCtx, &mut S) -> Option<A1> + Send + Sync + 'static,
275    >(
276        self,
277        f: F,
278    ) -> InterruptWith<Self, F, A1, R1>
279    where
280        Self: Sized,
281    {
282        InterruptWith {
283            a0: self,
284            f,
285            a1: None,
286            phantom: PhantomData,
287        }
288    }
289
290    /// Map the completion value of this action to something else.
291    #[must_use]
292    fn map<F: Fn(R, &mut S) -> R1, R1>(self, f: F) -> Map<Self, F, R>
293    where
294        Self: Sized,
295    {
296        Map(self, f, PhantomData)
297    }
298
299    /// Box the action. Often used to perform type erasure, such as when you
300    /// want to return one of many actions (each with different types) from
301    /// the same function.
302    ///
303    /// Note that [`Either`] can often be used to unify mismatched types without
304    /// the need for boxing.
305    ///
306    /// # Example
307    ///
308    /// ```ignore
309    /// // Error! Type mismatch between branches
310    /// if npc.is_too_tired() {
311    ///     goto(npc.home)
312    /// } else {
313    ///     go_on_an_adventure()
314    /// }
315    ///
316    /// // All fine
317    /// if npc.is_too_tired() {
318    ///     goto(npc.home).boxed()
319    /// } else {
320    ///     go_on_an_adventure().boxed()
321    /// }
322    /// ```
323    #[must_use]
324    fn boxed(self) -> Box<dyn Action<S, R>>
325    where
326        Self: Sized,
327    {
328        Box::new(self)
329    }
330
331    /// Set the state for child actions.
332    ///
333    /// Note that state is reset when repeated.
334    ///
335    /// # Example
336    ///
337    /// ```ignore
338    /// just(|_, state: &mut i32| *state += 2)
339    ///     // Outputs 5
340    ///     .then(just(|_, state: &mut i32| println!("{state}")))
341    ///     .with_state(3)
342    /// ```
343    #[must_use]
344    fn with_state<S0>(self, s: S) -> WithState<Self, S, S0>
345    where
346        Self: Sized,
347        S: Clone,
348    {
349        WithState(self, s.into(), PhantomData)
350    }
351
352    /// Map the current state for child actions, this map expects the return
353    /// value to have the same lifetime as the input state.
354    ///
355    /// # Example
356    ///
357    /// ```ignore
358    /// // Goes forward 5 steps
359    /// just(|_, state: &mut i32| go_forward(*state))
360    ///     .map_state(|state: &mut (i32, i32)| &mut state.1)
361    ///     .with_state((14, 5))
362    /// ```
363    #[must_use]
364    fn map_state<S0, F>(self, f: F) -> MapState<Self, F, S, S0>
365    where
366        F: Fn(&mut S0) -> &mut S,
367        Self: Sized,
368    {
369        MapState(self, f, PhantomData)
370    }
371
372    /// Add debugging information to the action that will be visible when using
373    /// the `/npc_info` command.
374    ///
375    /// # Example
376    ///
377    /// ```ignore
378    /// goto(npc.home).debug(|| "Going home")
379    /// ```
380    #[must_use]
381    fn debug<F, T>(self, mk_info: F) -> Debug<Self, F, T>
382    where
383        Self: Sized,
384    {
385        Debug(self, mk_info, PhantomData)
386    }
387
388    #[must_use]
389    fn l<Rhs>(self) -> Either<Self, Rhs>
390    where
391        Self: Sized,
392    {
393        Either::Left(self)
394    }
395
396    #[must_use]
397    fn r<Lhs>(self) -> Either<Lhs, Self>
398    where
399        Self: Sized,
400    {
401        Either::Right(self)
402    }
403
404    /// Specify that the given action has at least the provided priority over
405    /// others, preventing actions with a lower priority from overriding it
406    /// in certain cases.
407    #[must_use]
408    fn with_priority(self, priority: u32) -> WithPriority<Self>
409    where
410        Self: Sized,
411    {
412        WithPriority(self, priority)
413    }
414
415    /// Specify that the given action has important priority. See
416    /// [`Action::with_priority`].
417    #[must_use]
418    fn with_important_priority(self) -> WithPriority<Self>
419    where
420        Self: Sized,
421    {
422        self.with_priority(PRIORITY_IMPORTANT)
423    }
424}
425
426impl<S: State, R: 'static> Action<S, R> for Box<dyn Action<S, R>> {
427    fn backtrace(&self, bt: &mut Vec<String>) { (**self).backtrace(bt) }
428
429    fn reset(&mut self) { (**self).reset(); }
430
431    fn on_cancel(&mut self, ctx: &mut NpcCtx, state: &mut S) { (**self).on_cancel(ctx, state) }
432
433    fn tick(&mut self, ctx: &mut NpcCtx, state: &mut S) -> ControlFlow<R> {
434        (**self).tick(ctx, state)
435    }
436}
437
438impl<S: State, R: 'static, A: Action<S, R>, B: Action<S, R>> Action<S, R> for Either<A, B> {
439    fn backtrace(&self, bt: &mut Vec<String>) {
440        match self {
441            Either::Left(x) => x.backtrace(bt),
442            Either::Right(x) => x.backtrace(bt),
443        }
444    }
445
446    fn reset(&mut self) {
447        match self {
448            Either::Left(x) => x.reset(),
449            Either::Right(x) => x.reset(),
450        }
451    }
452
453    fn on_cancel(&mut self, ctx: &mut NpcCtx, state: &mut S) {
454        match self {
455            Either::Left(x) => x.on_cancel(ctx, state),
456            Either::Right(x) => x.on_cancel(ctx, state),
457        }
458    }
459
460    fn tick(&mut self, ctx: &mut NpcCtx, state: &mut S) -> ControlFlow<R> {
461        match self {
462            Either::Left(x) => x.tick(ctx, state),
463            Either::Right(x) => x.tick(ctx, state),
464        }
465    }
466}
467
468// Now
469
470/// See [`now`].
471#[derive(Copy, Clone)]
472pub struct Now<F, A>(F, Option<A>);
473
474impl<
475    S: State,
476    R: Send + Sync + 'static,
477    F: FnOnce(&mut NpcCtx, &mut S) -> A + Clone + Send + Sync + 'static,
478    A: Action<S, R>,
479> Action<S, R> for Now<F, A>
480{
481    fn backtrace(&self, bt: &mut Vec<String>) {
482        if let Some(action) = &self.1 {
483            action.backtrace(bt);
484        } else {
485            bt.push("<thinking>".to_string());
486        }
487    }
488
489    fn reset(&mut self) { self.1 = None; }
490
491    fn on_cancel(&mut self, ctx: &mut NpcCtx, state: &mut S) {
492        if let Some(x) = &mut self.1 {
493            x.on_cancel(ctx, state);
494        }
495    }
496
497    fn tick(&mut self, ctx: &mut NpcCtx, state: &mut S) -> ControlFlow<R> {
498        (self.1.get_or_insert_with(|| (self.0.clone())(ctx, state))).tick(ctx, state)
499    }
500}
501
502/// Start a new action based on the state of the world (`ctx`) at the moment the
503/// action is started.
504///
505/// If you're in a situation where you suddenly find yourself needing `ctx`, you
506/// probably want to use this.
507///
508/// # Example
509///
510/// ```ignore
511/// // An action that makes an NPC immediately travel to its *current* home
512/// now(|ctx| goto(ctx.npc.home))
513/// ```
514pub fn now<S, R, F, A: Action<S, R>>(f: F) -> Now<F, A>
515where
516    F: FnOnce(&mut NpcCtx, &mut S) -> A + Clone + Send + Sync + 'static,
517{
518    Now(f, None)
519}
520
521// Until
522
523/// See [`now`].
524#[derive(Copy, Clone)]
525pub struct Until<F, A, R, R1>(F, Option<A>, PhantomData<(R, R1)>);
526
527impl<
528    S: State,
529    R: Send + Sync + 'static,
530    F: Fn(&mut NpcCtx, &mut S) -> ControlFlow<R1, A> + Send + Sync + 'static,
531    A: Action<S, R>,
532    R1: Send + Sync + 'static,
533> Action<S, R1> for Until<F, A, R, R1>
534{
535    fn backtrace(&self, bt: &mut Vec<String>) {
536        if let Some(action) = &self.1 {
537            action.backtrace(bt);
538        } else {
539            bt.push("<thinking>".to_string());
540        }
541    }
542
543    fn reset(&mut self) { self.1 = None; }
544
545    fn on_cancel(&mut self, ctx: &mut NpcCtx, state: &mut S) {
546        if let Some(x) = &mut self.1 {
547            x.on_cancel(ctx, state);
548        }
549    }
550
551    fn tick(&mut self, ctx: &mut NpcCtx, state: &mut S) -> ControlFlow<R1> {
552        let action = match &mut self.1 {
553            Some(action) => action,
554            None => match (self.0)(ctx, state) {
555                ControlFlow::Continue(action) => self.1.insert(action),
556                ControlFlow::Break(b) => return ControlFlow::Break(b),
557            },
558        };
559
560        match action.tick(ctx, state) {
561            ControlFlow::Continue(()) => ControlFlow::Continue(()),
562            ControlFlow::Break(_) => {
563                self.1 = None;
564                ControlFlow::Continue(())
565            },
566        }
567    }
568}
569
570pub fn until<S, F, A: Action<S, R>, R, R1>(f: F) -> Until<F, A, R, R1>
571where
572    F: Fn(&mut NpcCtx, &mut S) -> ControlFlow<R1, A>,
573{
574    Until(f, None, PhantomData)
575}
576
577// Just
578
579/// See [`just`].
580#[derive(Copy, Clone)]
581pub struct Just<F, R = ()>(F, PhantomData<R>);
582
583impl<S: State, R: Send + Sync + 'static, F: Fn(&mut NpcCtx, &mut S) -> R + Send + Sync + 'static>
584    Action<S, R> for Just<F, R>
585{
586    fn backtrace(&self, _bt: &mut Vec<String>) {}
587
588    fn reset(&mut self) {}
589
590    fn on_cancel(&mut self, _ctx: &mut NpcCtx, _state: &mut S) {}
591
592    fn tick(&mut self, ctx: &mut NpcCtx, state: &mut S) -> ControlFlow<R> {
593        ControlFlow::Break((self.0)(ctx, state))
594    }
595}
596
597/// An action that executes some code just once when performed.
598///
599/// If you want to execute this code on every tick, consider combining it with
600/// [`Action::repeat`].
601///
602/// # Example
603///
604/// ```ignore
605/// // Make the current NPC say 'Hello, world!' exactly once
606/// just(|ctx| ctx.controller.say("Hello, world!"))
607/// ```
608pub fn just<S: State, F, R: Send + Sync + 'static>(f: F) -> Just<F, R>
609where
610    F: Fn(&mut NpcCtx, &mut S) -> R + Send + Sync + 'static,
611{
612    Just(f, PhantomData)
613}
614
615// Finish
616
617/// See [`finish`].
618#[derive(Copy, Clone)]
619pub struct Finish;
620
621impl<S: State> Action<S, ()> for Finish {
622    fn backtrace(&self, _bt: &mut Vec<String>) {}
623
624    fn reset(&mut self) {}
625
626    fn on_cancel(&mut self, _ctx: &mut NpcCtx, _state: &mut S) {}
627
628    fn tick(&mut self, _ctx: &mut NpcCtx, _state: &mut S) -> ControlFlow<()> {
629        ControlFlow::Break(())
630    }
631}
632
633/// An action that immediately finishes without doing anything.
634///
635/// This action is useless by itself, but becomes useful when combined with
636/// actions that make decisions.
637///
638/// # Example
639///
640/// ```ignore
641/// now(|ctx| {
642///     if ctx.npc.is_tired() {
643///         sleep().boxed() // If we're tired, sleep
644///     } else if ctx.npc.is_hungry() {
645///         eat().boxed() // If we're hungry, eat
646///     } else {
647///         finish().boxed() // Otherwise, do nothing
648///     }
649/// })
650/// ```
651#[must_use]
652pub fn finish() -> Finish { Finish }
653
654// Tree
655
656const PRIORITY_URGENT: u32 = 100;
657const PRIORITY_IMPORTANT: u32 = 50;
658const PRIORITY_CASUAL: u32 = 0;
659
660/// See [`choose`] and [`watch`].
661pub struct Tree<S, F, R> {
662    next: F,
663    current: Option<(Box<dyn Action<S, R>>, u32, u32)>,
664}
665
666pub struct Consider<'a, S, R> {
667    current: &'a mut Option<(Box<dyn Action<S, R>>, u32, u32)>,
668    to_cancel: &'a mut Vec<Box<dyn Action<S, R>>>,
669}
670
671impl<'a, S: State, R: 'static> Consider<'a, S, R> {
672    pub fn action(&mut self, priority: u32, action: impl Action<S, R>) {
673        // Replace the current action, unless the current action has a >= priority
674        if !matches!(&mut self.current, Some((_, base_priority, override_priority)) if (*base_priority).max(*override_priority) >= priority)
675            && let Some((old, _, _)) = self.current.replace((Box::new(action), priority, 0))
676        {
677            self.to_cancel.push(old);
678        }
679    }
680
681    pub fn urgent(&mut self, action: impl Action<S, R>) { self.action(PRIORITY_URGENT, action); }
682
683    pub fn important(&mut self, action: impl Action<S, R>) {
684        self.action(PRIORITY_IMPORTANT, action);
685    }
686
687    pub fn casual(&mut self, action: impl Action<S, R>) { self.action(PRIORITY_CASUAL, action); }
688}
689
690impl<S: State, F: Fn(&mut NpcCtx, &mut S, &mut Consider<S, R>) + Send + Sync + 'static, R: 'static>
691    Action<S, R> for Tree<S, F, R>
692{
693    fn backtrace(&self, bt: &mut Vec<String>) {
694        if let Some((current, _, _)) = &self.current {
695            current.backtrace(bt);
696        } else {
697            bt.push("<thinking>".to_string());
698        }
699    }
700
701    fn reset(&mut self) { self.current = None; }
702
703    fn on_cancel(&mut self, ctx: &mut NpcCtx, state: &mut S) {
704        if let Some((current, _, _)) = &mut self.current {
705            current.on_cancel(ctx, state);
706        }
707    }
708
709    fn tick(&mut self, ctx: &mut NpcCtx, state: &mut S) -> ControlFlow<R> {
710        let mut to_cancel = Vec::new();
711        (self.next)(ctx, state, &mut Consider {
712            current: &mut self.current,
713            to_cancel: &mut to_cancel,
714        });
715        for mut to_cancel in to_cancel {
716            to_cancel.on_cancel(ctx, state);
717        }
718
719        let Some((current, _, override_priority)) = self.current.as_mut() else {
720            // If no action is available to perform, do nothing
721            return ControlFlow::Continue(());
722        };
723
724        let old_priority = ctx.current_action_priority;
725        ctx.current_action_priority = 0;
726        let ret = match current.tick(ctx, state) {
727            ControlFlow::Continue(()) => {
728                *override_priority = ctx.current_action_priority;
729                ControlFlow::Continue(())
730            },
731            ControlFlow::Break(r) => {
732                self.current = None;
733                ControlFlow::Break(r)
734            },
735        };
736        ctx.current_action_priority = old_priority;
737        ret
738    }
739}
740
741/// An action that allows implementing a decision tree, with action
742/// prioritisation.
743///
744/// The inner function will be run every tick to decide on an action. When an
745/// action is chosen, it will be performed until completed *UNLESS* an action
746/// with a more urgent priority is chosen in a subsequent tick. [`choose`] tries
747/// to commit to actions when it can: only more urgent actions will interrupt an
748/// action that's currently being performed.
749///
750/// # Example
751///
752/// ```ignore
753/// .choose_mut(|ctx| {
754///     if ctx.npc.is_being_attacked() {
755///         urgent(combat()) // If we're in danger, do something!
756///     } else if ctx.npc.is_hungry() {
757///         important(eat()) // If we're hungry, eat
758///     } else {
759///         casual(idle()) // Otherwise, do nothing
760///     }
761/// })
762/// ```
763#[must_use]
764pub fn choose<S: State, R: 'static, F>(f: F) -> Tree<S, F, R>
765where
766    F: Fn(&mut NpcCtx, &mut S, &mut Consider<S, R>) + Send + Sync + 'static,
767{
768    Tree {
769        next: f,
770        current: None,
771    }
772}
773
774// WithPriority
775
776/// See [`Action::with_priority`].
777#[derive(Copy, Clone)]
778pub struct WithPriority<A>(A, u32);
779
780impl<S: State, R: Send + Sync + 'static, A: Action<S, R>> Action<S, R> for WithPriority<A> {
781    fn backtrace(&self, bt: &mut Vec<String>) { self.0.backtrace(bt); }
782
783    fn reset(&mut self) { self.0.reset(); }
784
785    fn on_cancel(&mut self, ctx: &mut NpcCtx, state: &mut S) { self.0.on_cancel(ctx, state); }
786
787    fn tick(&mut self, ctx: &mut NpcCtx, state: &mut S) -> ControlFlow<R> {
788        ctx.current_action_priority = ctx.current_action_priority.max(self.1);
789        self.0.tick(ctx, state)
790    }
791}
792
793// Then
794
795/// See [`Action::then`].
796#[derive(Copy, Clone)]
797pub struct Then<A0, A1, R0> {
798    a0: A0,
799    a0_finished: bool,
800    a1: A1,
801    phantom: PhantomData<R0>,
802}
803
804impl<
805    S: State,
806    A0: Action<S, R0>,
807    A1: Action<S, R1>,
808    R0: Send + Sync + 'static,
809    R1: Send + Sync + 'static,
810> Action<S, R1> for Then<A0, A1, R0>
811{
812    fn backtrace(&self, bt: &mut Vec<String>) {
813        if self.a0_finished {
814            self.a1.backtrace(bt);
815        } else {
816            self.a0.backtrace(bt);
817        }
818    }
819
820    fn reset(&mut self) {
821        self.a0.reset();
822        self.a0_finished = false;
823        self.a1.reset();
824    }
825
826    fn on_cancel(&mut self, ctx: &mut NpcCtx, state: &mut S) {
827        if !self.a0_finished {
828            self.a0.on_cancel(ctx, state)
829        } else {
830            self.a1.on_cancel(ctx, state);
831        }
832    }
833
834    fn tick(&mut self, ctx: &mut NpcCtx, state: &mut S) -> ControlFlow<R1> {
835        if !self.a0_finished {
836            match self.a0.tick(ctx, state) {
837                ControlFlow::Continue(()) => return ControlFlow::Continue(()),
838                ControlFlow::Break(_) => self.a0_finished = true,
839            }
840        }
841        self.a1.tick(ctx, state)
842    }
843}
844
845// AndThen
846
847/// See [`Action::and_then`].
848#[derive(Copy, Clone)]
849pub struct AndThen<A0, F, A1, R0> {
850    a0: A0,
851    f: F,
852    a1: Option<A1>,
853    phantom: PhantomData<R0>,
854}
855
856impl<
857    S: State,
858    A0: Action<S, R0>,
859    A1: Action<S, R1>,
860    R0: Send + Sync + 'static,
861    R1: Send + Sync + 'static,
862    F: FnOnce(R0) -> A1 + Clone + Send + Sync + 'static,
863> Action<S, R1> for AndThen<A0, F, A1, R0>
864{
865    fn backtrace(&self, bt: &mut Vec<String>) {
866        if let Some(a1) = &self.a1 {
867            a1.backtrace(bt);
868        } else {
869            self.a0.backtrace(bt);
870        }
871    }
872
873    fn reset(&mut self) {
874        self.a0.reset();
875        self.a1 = None;
876    }
877
878    fn on_cancel(&mut self, ctx: &mut NpcCtx, state: &mut S) {
879        if let Some(a1) = &mut self.a1 {
880            a1.on_cancel(ctx, state);
881        } else {
882            self.a0.on_cancel(ctx, state);
883        }
884    }
885
886    fn tick(&mut self, ctx: &mut NpcCtx, state: &mut S) -> ControlFlow<R1> {
887        let a1 = match &mut self.a1 {
888            None => match self.a0.tick(ctx, state) {
889                ControlFlow::Continue(()) => return ControlFlow::Continue(()),
890                ControlFlow::Break(r) => self.a1.insert((self.f.clone())(r)),
891            },
892            Some(a1) => a1,
893        };
894        a1.tick(ctx, state)
895    }
896}
897
898// InterruptWith
899
900/// See [`Action::then`].
901#[derive(Copy, Clone)]
902pub struct InterruptWith<A0, F, A1, R1> {
903    a0: A0,
904    f: F,
905    a1: Option<A1>,
906    phantom: PhantomData<R1>,
907}
908
909impl<
910    S: State,
911    A0: Action<S, R0>,
912    A1: Action<S, R1>,
913    F: Fn(&mut NpcCtx, &mut S) -> Option<A1> + Send + Sync + 'static,
914    R0: Send + Sync + 'static,
915    R1: Send + Sync + 'static,
916> Action<S, R0> for InterruptWith<A0, F, A1, R1>
917{
918    fn backtrace(&self, bt: &mut Vec<String>) {
919        if let Some(a1) = &self.a1 {
920            // TODO: Find a way to represent interrupts in backtraces
921            bt.push("<interrupted>".to_string());
922            a1.backtrace(bt);
923        } else {
924            self.a0.backtrace(bt);
925        }
926    }
927
928    fn reset(&mut self) {
929        self.a0.reset();
930        self.a1 = None;
931    }
932
933    fn on_cancel(&mut self, ctx: &mut NpcCtx, state: &mut S) {
934        if let Some(x) = &mut self.a1 {
935            x.on_cancel(ctx, state);
936        }
937        self.a0.on_cancel(ctx, state);
938    }
939
940    fn tick(&mut self, ctx: &mut NpcCtx, state: &mut S) -> ControlFlow<R0> {
941        if self.a1.is_none()
942            && let Some(new_a1) = (self.f)(ctx, state)
943        {
944            self.a1 = Some(new_a1);
945        }
946
947        if let Some(a1) = &mut self.a1 {
948            match a1.tick(ctx, state) {
949                ControlFlow::Continue(()) => return ControlFlow::Continue(()),
950                ControlFlow::Break(_) => self.a1 = None,
951            }
952        }
953
954        self.a0.tick(ctx, state)
955    }
956}
957
958// Repeat
959
960/// See [`Action::repeat`].
961#[derive(Copy, Clone)]
962pub struct Repeat<A, R = ()>(A, PhantomData<R>);
963
964impl<S: State, R: Send + Sync + 'static, A: Action<S, R>> Action<S, !> for Repeat<A, R> {
965    fn backtrace(&self, bt: &mut Vec<String>) { self.0.backtrace(bt); }
966
967    fn reset(&mut self) { self.0.reset(); }
968
969    fn on_cancel(&mut self, ctx: &mut NpcCtx, state: &mut S) { self.0.on_cancel(ctx, state); }
970
971    fn tick(&mut self, ctx: &mut NpcCtx, state: &mut S) -> ControlFlow<!> {
972        match self.0.tick(ctx, state) {
973            ControlFlow::Continue(()) => ControlFlow::Continue(()),
974            ControlFlow::Break(_) => {
975                self.0.reset();
976                ControlFlow::Continue(())
977            },
978        }
979    }
980}
981
982// Sequence
983
984/// See [`seq`].
985#[derive(Copy, Clone)]
986pub struct Sequence<I, A, R = ()>(Resettable<I>, Option<A>, PhantomData<R>);
987
988impl<
989    S: State,
990    R: Send + Sync + 'static,
991    I: Iterator<Item = A> + Clone + Send + Sync + 'static,
992    A: Action<S, R>,
993> Action<S, ()> for Sequence<I, A, R>
994{
995    fn backtrace(&self, bt: &mut Vec<String>) {
996        if let Some(action) = &self.1 {
997            action.backtrace(bt);
998        } else {
999            bt.push("<thinking>".to_string());
1000        }
1001    }
1002
1003    fn reset(&mut self) {
1004        self.0.reset();
1005        self.1 = None;
1006    }
1007
1008    fn on_cancel(&mut self, ctx: &mut NpcCtx, state: &mut S) {
1009        if let Some(x) = &mut self.1 {
1010            x.on_cancel(ctx, state);
1011        }
1012    }
1013
1014    fn tick(&mut self, ctx: &mut NpcCtx, state: &mut S) -> ControlFlow<()> {
1015        let item = if let Some(prev) = &mut self.1 {
1016            prev
1017        } else {
1018            match self.0.next() {
1019                Some(next) => self.1.insert(next),
1020                None => return ControlFlow::Break(()),
1021            }
1022        };
1023
1024        if let ControlFlow::Break(_) = item.tick(ctx, state) {
1025            self.1 = None;
1026        }
1027
1028        ControlFlow::Continue(())
1029    }
1030}
1031
1032/// An action that consumes and performs an iterator of actions in sequence, one
1033/// after another.
1034///
1035/// # Example
1036///
1037/// ```ignore
1038/// // A list of enemies we should attack in turn
1039/// let enemies = vec![
1040///     ugly_goblin,
1041///     stinky_troll,
1042///     rude_dwarf,
1043/// ];
1044///
1045/// // Attack each enemy, one after another
1046/// seq(enemies
1047///     .into_iter()
1048///     .map(|enemy| attack(enemy)))
1049/// ```
1050#[must_use]
1051pub fn seq<S, I, A, R>(iter: I) -> Sequence<I, A, R>
1052where
1053    I: Iterator<Item = A> + Clone,
1054    A: Action<S, R>,
1055{
1056    Sequence(iter.into(), None, PhantomData)
1057}
1058
1059// StopIf
1060
1061/// See [`Action::stop_if`].
1062#[derive(Copy, Clone)]
1063pub struct StopIf<A, P>(A, Resettable<P>);
1064
1065impl<S: State, A: Action<S, R>, P: Predicate + Clone + Send + Sync + 'static, R>
1066    Action<S, Option<R>> for StopIf<A, P>
1067{
1068    fn backtrace(&self, bt: &mut Vec<String>) { self.0.backtrace(bt); }
1069
1070    fn reset(&mut self) {
1071        self.0.reset();
1072        self.1.reset();
1073    }
1074
1075    fn on_cancel(&mut self, ctx: &mut NpcCtx, state: &mut S) { self.0.on_cancel(ctx, state); }
1076
1077    fn tick(&mut self, ctx: &mut NpcCtx, state: &mut S) -> ControlFlow<Option<R>> {
1078        if self.1.should(ctx) {
1079            self.0.on_cancel(ctx, state);
1080            ControlFlow::Break(None)
1081        } else {
1082            self.0.tick(ctx, state).map_break(Some)
1083        }
1084    }
1085}
1086
1087// WhenCancelled
1088
1089/// See [`Action::when_cancelled`].
1090#[derive(Copy, Clone)]
1091pub struct WhenCancelled<A, F>(A, F);
1092
1093impl<S: State, A: Action<S, R>, F: Fn(&mut NpcCtx) + Clone + Send + Sync + 'static, R> Action<S, R>
1094    for WhenCancelled<A, F>
1095{
1096    fn backtrace(&self, bt: &mut Vec<String>) { self.0.backtrace(bt); }
1097
1098    fn reset(&mut self) { self.0.reset(); }
1099
1100    fn on_cancel(&mut self, ctx: &mut NpcCtx, state: &mut S) {
1101        self.0.on_cancel(ctx, state);
1102        (self.1)(ctx);
1103    }
1104
1105    fn tick(&mut self, ctx: &mut NpcCtx, state: &mut S) -> ControlFlow<R> {
1106        self.0.tick(ctx, state)
1107    }
1108}
1109
1110// Map
1111
1112/// See [`Action::map`].
1113#[derive(Copy, Clone)]
1114pub struct Map<A, F, R>(A, F, PhantomData<R>);
1115
1116impl<
1117    S: State,
1118    A: Action<S, R>,
1119    F: Fn(R, &mut S) -> R1 + Send + Sync + 'static,
1120    R: Send + Sync + 'static,
1121    R1,
1122> Action<S, R1> for Map<A, F, R>
1123{
1124    fn backtrace(&self, bt: &mut Vec<String>) { self.0.backtrace(bt); }
1125
1126    fn reset(&mut self) { self.0.reset(); }
1127
1128    fn on_cancel(&mut self, ctx: &mut NpcCtx, state: &mut S) { self.0.on_cancel(ctx, state); }
1129
1130    fn tick(&mut self, ctx: &mut NpcCtx, state: &mut S) -> ControlFlow<R1> {
1131        self.0.tick(ctx, state).map_break(|t| (self.1)(t, state))
1132    }
1133}
1134
1135// Debug
1136
1137/// See [`Action::debug`].
1138#[derive(Copy, Clone)]
1139pub struct Debug<A, F, T>(A, F, PhantomData<T>);
1140
1141impl<
1142    S: 'static,
1143    A: Action<S, R>,
1144    F: Fn() -> T + Send + Sync + 'static,
1145    R: Send + Sync + 'static,
1146    T: Send + Sync + std::fmt::Display + 'static,
1147> Action<S, R> for Debug<A, F, T>
1148{
1149    fn backtrace(&self, bt: &mut Vec<String>) {
1150        bt.push((self.1)().to_string());
1151        self.0.backtrace(bt);
1152    }
1153
1154    fn reset(&mut self) { self.0.reset(); }
1155
1156    fn on_cancel(&mut self, ctx: &mut NpcCtx, state: &mut S) { self.0.on_cancel(ctx, state); }
1157
1158    fn tick(&mut self, ctx: &mut NpcCtx, state: &mut S) -> ControlFlow<R> {
1159        self.0.tick(ctx, state)
1160    }
1161}
1162
1163#[derive(Copy, Clone)]
1164pub struct WithState<A, S, S0>(A, Resettable<S>, PhantomData<S0>);
1165
1166impl<S0: State, S: State, R, A: Action<S, R>> Action<S0, R> for WithState<A, S, S0> {
1167    fn backtrace(&self, bt: &mut Vec<String>) { self.0.backtrace(bt) }
1168
1169    fn reset(&mut self) {
1170        self.0.reset();
1171        self.1.reset();
1172    }
1173
1174    fn on_cancel(&mut self, ctx: &mut NpcCtx, _state: &mut S0) {
1175        self.0.on_cancel(ctx, &mut self.1.current);
1176    }
1177
1178    fn tick(&mut self, ctx: &mut NpcCtx, _state: &mut S0) -> ControlFlow<R> {
1179        self.0.tick(ctx, &mut self.1.current)
1180    }
1181}
1182
1183#[derive(Copy, Clone)]
1184pub struct MapState<A, F, S, S0>(A, F, PhantomData<(S, S0)>);
1185
1186impl<S0: State, S: State, R, A: Action<S, R>, F: Fn(&mut S0) -> &mut S + Send + Sync + 'static>
1187    Action<S0, R> for MapState<A, F, S, S0>
1188{
1189    fn backtrace(&self, bt: &mut Vec<String>) { self.0.backtrace(bt) }
1190
1191    fn reset(&mut self) { self.0.reset(); }
1192
1193    fn on_cancel(&mut self, ctx: &mut NpcCtx, state: &mut S0) {
1194        self.0.on_cancel(ctx, (self.1)(state));
1195    }
1196
1197    fn tick(&mut self, ctx: &mut NpcCtx, state: &mut S0) -> ControlFlow<R> {
1198        self.0.tick(ctx, (self.1)(state))
1199    }
1200}