emergent/decision_makers/
selector.rs

1//! Runs first state that succeeds (boolean OR operation).
2
3use crate::{condition::*, decision_makers::*, task::*};
4
5/// Defines selector state with task and condition.
6pub struct SelectorState<M = ()> {
7    condition: Box<dyn Condition<M>>,
8    task: Box<dyn Task<M>>,
9}
10
11impl<M> SelectorState<M> {
12    /// Constructs new state with condition and task.
13    pub fn new<C, T>(condition: C, task: T) -> Self
14    where
15        C: Condition<M> + 'static,
16        T: Task<M> + 'static,
17    {
18        Self {
19            condition: Box::new(condition),
20            task: Box::new(task),
21        }
22    }
23
24    /// Constructs new state with condition and task.
25    pub fn new_raw(condition: Box<dyn Condition<M>>, task: Box<dyn Task<M>>) -> Self {
26        Self { condition, task }
27    }
28}
29
30impl<M> std::fmt::Debug for SelectorState<M> {
31    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32        f.debug_struct("SelectorState").finish()
33    }
34}
35
36/// Selector runs at most only one state at any given time.
37///
38/// Selector finds first state that its condition succeed and runs it.
39///
40/// # Example
41/// ```
42/// use emergent::prelude::*;
43///
44/// struct Is(pub bool);
45///
46/// impl Condition<bool> for Is {
47///     fn validate(&self, memory: &bool) -> bool {
48///         *memory == self.0
49///     }
50/// }
51///
52/// struct Set(pub bool);
53///
54/// impl Task<bool> for Set {
55///     fn on_enter(&mut self, memory: &mut bool) {
56///         *memory = self.0
57///     }
58/// }
59///
60/// let mut selector = Selector::new(vec![
61///     SelectorState::new(Is(true), Set(false)),
62///     SelectorState::new(Is(false), Set(true)),
63/// ]);
64/// let mut memory = false;
65/// assert!(selector.process(&mut memory));
66/// assert_eq!(memory, true);
67/// assert!(selector.process(&mut memory));
68/// assert_eq!(memory, false);
69/// ```
70pub struct Selector<M = ()> {
71    states: Vec<SelectorState<M>>,
72    active_index: Option<usize>,
73}
74
75impl<M> Selector<M> {
76    /// Constructs new selector from states.
77    pub fn new(states: Vec<SelectorState<M>>) -> Self {
78        Self {
79            states,
80            active_index: None,
81        }
82    }
83
84    /// Constructs new selector from states.
85    pub fn new_raw(states: Vec<SelectorState<M>>) -> Self {
86        Self {
87            states,
88            active_index: None,
89        }
90    }
91
92    /// Returns currently active state index.
93    pub fn active_index(&self) -> Option<usize> {
94        self.active_index
95    }
96
97    /// Reset currently active state.
98    ///
99    /// By default state won't change if active state is locked, but we can force state change.
100    pub fn reset(&mut self, memory: &mut M, forced: bool) -> bool {
101        if let Some(index) = self.active_index {
102            let state = self.states.get_mut(index).unwrap();
103            if !forced && state.task.is_locked(memory) {
104                return false;
105            }
106            state.task.on_exit(memory);
107            self.active_index = None;
108        }
109        true
110    }
111
112    fn change_active_index(&mut self, index: Option<usize>, memory: &mut M) -> bool {
113        if index == self.active_index {
114            return false;
115        }
116        if let Some(index) = self.active_index {
117            let state = self.states.get_mut(index).unwrap();
118            if state.task.is_locked(memory) {
119                return false;
120            }
121            state.task.on_exit(memory);
122        }
123        if let Some(index) = index {
124            self.states.get_mut(index).unwrap().task.on_enter(memory);
125        }
126        self.active_index = index;
127        true
128    }
129
130    /// Perform decision making.
131    pub fn process(&mut self, memory: &mut M) -> bool {
132        if self.states.is_empty() {
133            return false;
134        }
135        let index = self
136            .states
137            .iter()
138            .position(|state| state.condition.validate(memory));
139        if self.change_active_index(index, memory) {
140            return true;
141        }
142        if let Some(index) = self.active_index {
143            return self.states.get_mut(index).unwrap().task.on_process(memory);
144        }
145        false
146    }
147
148    /// Update currently active state.
149    pub fn update(&mut self, memory: &mut M) {
150        if let Some(index) = self.active_index {
151            self.states.get_mut(index).unwrap().task.on_update(memory);
152        }
153    }
154}
155
156impl<M, K> DecisionMaker<M, K> for Selector<M>
157where
158    K: Default,
159{
160    fn decide(&mut self, memory: &mut M) -> Option<K> {
161        self.process(memory);
162        Some(K::default())
163    }
164
165    fn change_mind(&mut self, _: Option<K>, memory: &mut M) -> bool {
166        self.reset(memory, true)
167    }
168}
169
170impl<M> Task<M> for Selector<M> {
171    fn is_locked(&self, memory: &M) -> bool {
172        if let Some(index) = self.active_index {
173            if let Some(state) = self.states.get(index) {
174                return state.task.is_locked(memory);
175            }
176        }
177        false
178    }
179
180    fn on_enter(&mut self, memory: &mut M) {
181        self.reset(memory, true);
182        self.process(memory);
183    }
184
185    fn on_exit(&mut self, memory: &mut M) {
186        self.reset(memory, true);
187    }
188
189    fn on_update(&mut self, memory: &mut M) {
190        self.update(memory);
191    }
192
193    fn on_process(&mut self, memory: &mut M) -> bool {
194        self.process(memory)
195    }
196}
197
198impl<M> std::fmt::Debug for Selector<M> {
199    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
200        f.debug_struct("Selector")
201            .field("states", &self.states)
202            .field("active_index", &self.active_index)
203            .finish()
204    }
205}