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