veloren_rtsim/ai/
mod.rs

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