veloren_rtsim/ai/
mod.rs

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