veloren_rtsim/ai/
mod.rs

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