1 /* Copyright (C) 2024 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/>.
23 #include <unordered_map>
26 constexpr unsigned int FSM_INVALID_STATE
{std::numeric_limits
<unsigned int>::max()};
31 using Action
= bool(void* pContext
, CFsmEvent
* pEvent
);
33 struct CallbackFunction
35 Action
* pFunction
{nullptr};
36 void* pContext
{nullptr};
38 bool operator()(CFsmEvent
& event
) const
40 return !pFunction
|| pFunction(pContext
, &event
);
44 using StateSet
= std::set
<unsigned int>;
47 * Represents a signal in the state machine that a change has occurred.
48 * The CFsmEvent objects are under the control of CFsm so
49 * they are created and deleted via CFsm.
53 NONCOPYABLE(CFsmEvent
);
56 CFsmEvent(unsigned int type
, void* pParam
);
59 unsigned int GetType() const
70 unsigned int m_Type
; // Event type
71 void* m_Param
; // Event paramater
75 * Manages states, events, actions and transitions
76 * between states. It provides an interface for advertising
77 * events and track the current state. The implementation is
78 * a Mealy state machine, so the system respond to events
79 * and execute some action.
81 * A Mealy state machine has behaviour associated with state
82 * transitions; Mealy machines are event driven where an
83 * event triggers a state transition.
94 * Constructs the state machine. This method must be overriden so that
95 * connections are constructed for the particular state machine implemented.
100 * Clear event, transition lists and reset state machine.
105 * Adds the specified state to the internal list of states.
106 * @note If a state with the specified ID exists, the state is not added.
108 void AddState(unsigned int state
);
111 * Adds a new transistion to the state machine.
113 void AddTransition(unsigned int state
, unsigned int eventType
, unsigned int nextState
,
114 Action
* pAction
= nullptr, void* pContext
= nullptr);
117 * Sets the initial state for FSM.
119 void SetFirstState(unsigned int firstState
);
122 * Sets the current state and update the last state to the current state.
124 void SetCurrState(unsigned int state
);
125 unsigned int GetCurrState() const
130 void SetNextState(unsigned int nextState
)
132 m_NextState
= nextState
;
135 unsigned int GetNextState() const
140 const StateSet
& GetStates() const
146 * Updates the FSM and retrieves next state.
147 * @return whether the state was changed.
149 bool Update(unsigned int eventType
, void* pEventData
);
152 * Verifies whether the specified state is managed by the FSM.
154 bool IsValidState(unsigned int state
) const;
157 * Tests whether the state machine has finished its work.
158 * @note This is state machine specific.
160 virtual bool IsDone() const;
165 using UnderlyingType
= unsigned int;
166 UnderlyingType state
;
167 UnderlyingType eventType
;
171 size_t operator()(const TransitionKey
& key
) const noexcept
173 static_assert(sizeof(UnderlyingType
) <= sizeof(size_t) / 2);
174 return (static_cast<size_t>(key
.state
) <<
175 ((sizeof(size_t) / 2) * std::numeric_limits
<unsigned char>::digits
)) +
176 static_cast<size_t>(key
.eventType
);
180 friend bool operator==(const TransitionKey
& lhs
, const TransitionKey
& rhs
) noexcept
182 return lhs
.state
== rhs
.state
&& lhs
.eventType
== rhs
.eventType
;
188 CallbackFunction action
;
189 unsigned int nextState
;
192 using TransitionMap
= std::unordered_map
<TransitionKey
, const Transition
, TransitionKey::Hash
>;
195 * Verifies whether state machine has already been updated.
197 bool IsFirstTime() const;
200 unsigned int m_FirstState
;
201 unsigned int m_CurrState
;
202 unsigned int m_NextState
;
204 TransitionMap m_Transitions
;