1 /* Copyright (C) 2023 Wildfire Games.
2 * This file is part of 0 A.D.
4 * 0 A.D. is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
9 * 0 A.D. is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
27 constexpr unsigned int FSM_INVALID_STATE
{std::numeric_limits
<unsigned int>::max()};
33 using Condition
= bool(void* pContext
);
34 using Action
= bool(void* pContext
, const CFsmEvent
* pEvent
);
36 struct CallbackFunction
42 using StateSet
= std::set
<unsigned int>;
43 using EventMap
= std::map
<unsigned int, CFsmEvent
*>;
44 using TransitionList
= std::vector
<CFsmTransition
*>;
45 using CallbackList
= std::vector
<CallbackFunction
>;
48 * Represents a signal in the state machine that a change has occurred.
49 * The CFsmEvent objects are under the control of CFsm so
50 * they are created and deleted via CFsm.
54 NONCOPYABLE(CFsmEvent
);
57 CFsmEvent(unsigned int type
);
60 unsigned int GetType() const
70 void SetParamRef(void* pParam
);
73 unsigned int m_Type
; // Event type
74 void* m_Param
; // Event paramater
79 * An association of event, condition, action and next state.
83 NONCOPYABLE(CFsmTransition
);
86 CFsmTransition(unsigned int state
);
90 * Registers an action that will be executed when the transition occurs.
91 * @param pAction the function which will be executed.
92 * @param pContext data passed to the function.
94 void RegisterAction(void* pAction
, void* pContext
);
97 * Registers a condition which will be evaluated when the transition occurs.
98 * @param pCondition the predicate which will be executed.
99 * @param pContext data passed to the predicate.
101 void RegisterCondition(void* pCondition
, void* pContext
);
104 * Set event for which transition will occur.
106 void SetEvent(CFsmEvent
* pEvent
);
107 CFsmEvent
* GetEvent() const
113 * Set next state the transition will switch the system to.
115 void SetNextState(unsigned int nextState
);
116 unsigned int GetNextState() const
121 unsigned int GetCurrState() const
126 const CallbackList
& GetActions() const
131 const CallbackList
& GetConditions() const
137 * Evaluates conditions for the transition.
138 * @return whether all the conditions are true.
140 bool ApplyConditions() const;
143 * Executes actions for the transition.
144 * @note If there are no actions, assume true.
145 * @return whether all the actions returned true.
147 bool RunActions() const;
150 unsigned int m_CurrState
;
151 unsigned int m_NextState
;
153 CallbackList m_Actions
;
154 CallbackList m_Conditions
;
158 * Manages states, events, actions and transitions
159 * between states. It provides an interface for advertising
160 * events and track the current state. The implementation is
161 * a Mealy state machine, so the system respond to events
162 * and execute some action.
164 * A Mealy state machine has behaviour associated with state
165 * transitions; Mealy machines are event driven where an
166 * event triggers a state transition.
177 * Constructs the state machine. This method must be overriden so that
178 * connections are constructed for the particular state machine implemented.
180 virtual void Setup();
183 * Clear event, action and condition lists and reset state machine.
188 * Adds the specified state to the internal list of states.
189 * @note If a state with the specified ID exists, the state is not added.
191 void AddState(unsigned int state
);
194 * Adds the specified event to the internal list of events.
195 * @note If an eveny with the specified ID exists, the event is not added.
196 * @return a pointer to the new event.
198 CFsmEvent
* AddEvent(unsigned int eventType
);
201 * Adds a new transistion to the state machine.
202 * @return a pointer to the new transition.
204 CFsmTransition
* AddTransition(unsigned int state
, unsigned int eventType
, unsigned int nextState
);
207 * Adds a new transition to the state machine.
208 * @return a pointer to the new transition.
210 CFsmTransition
* AddTransition(unsigned int state
, unsigned int eventType
, unsigned int nextState
,
211 void* pAction
, void* pContext
);
214 * Looks up the transition given the state, event and next state to transition to.
216 CFsmTransition
* GetTransition(unsigned int state
, unsigned int eventType
) const;
217 CFsmTransition
* GetEventTransition (unsigned int eventType
) const;
220 * Sets the initial state for FSM.
222 void SetFirstState(unsigned int firstState
);
225 * Sets the current state and update the last state to the current state.
227 void SetCurrState(unsigned int state
);
228 unsigned int GetCurrState() const
233 void SetNextState(unsigned int nextState
)
235 m_NextState
= nextState
;
238 unsigned int GetNextState() const
243 const StateSet
& GetStates() const
248 const EventMap
& GetEvents() const
253 const TransitionList
& GetTransitions() const
255 return m_Transitions
;
259 * Updates the FSM and retrieves next state.
260 * @return whether the state was changed.
262 bool Update(unsigned int eventType
, void* pEventData
);
265 * Verifies whether the specified state is managed by the FSM.
267 bool IsValidState(unsigned int state
) const;
270 * Verifies whether the specified event is managed by the FSM.
272 bool IsValidEvent(unsigned int eventType
) const;
275 * Tests whether the state machine has finished its work.
276 * @note This is state machine specific.
278 virtual bool IsDone() const;
282 * Verifies whether state machine has already been updated.
284 bool IsFirstTime() const;
287 unsigned int m_FirstState
;
288 unsigned int m_CurrState
;
289 unsigned int m_NextState
;
292 TransitionList m_Transitions
;