I need to implement a Finite State Machine for a graphic aplication, so looking for info on documents and so on... i found a few ways to implement it. The easiest, a switch sentence to select a case for each state
, but it is a dirty solution and very hard to mantain. Reading some documents i found with the book Programming Game by a Example / Mat Buckland. Here the author describes a tecnique called Embedded Rules, wich define a class State who contains the logic about transition states. I paste the book´s section to understand this interesting method
Embedded Rules
An alternative approach is to embed the rules for the state transitions
within the states themselves. Applying this concept to Robo-Kitty, the state
transition chip can be dispensed with and the rules moved directly into the
cartridges. For instance, the cartridge for “play with string” can monitor
the kitty’s level of hunger and instruct it to switch cartridges for the “eat
fish” cartridge when it senses hunger rising. In turn the “eat fish” cartridge
can monitor the kitten’s bowel and instruct it to switch to the “poo on carpet”
cartridge when it senses poo levels are running dangerously high.
Although each cartridge may be aware of the existence of any of the
other cartridges, each is a self-contained unit and not reliant on any external
logic to decide whether or not it should allow itself to be swapped for
an alternative. As a consequence, it’s a straightforward matter to add states
or even to swap the whole set of cartridges for a completely new set
(maybe ones that make little Kitty behave like a raptor). There’s no need to
take a screwdriver to the kitten’s head, only to a few of the cartridges
themselves.
Let’s take a look at how this approach is implemented within the context
of a video game. Just like Kitty’s cartridges, states are encapsulated as
objects and contain the logic required to facilitate state transitions. In addition,
all state objects share a common interface: a pure virtual class named
State. Here’s a version that provides a simple interface:
Code: Select all
class State
{
public:
virtual void Execute (Troll* troll) = 0;
};
health, anger, stamina, etc., and an interface allowing a client to query and
adjust those values. A Troll can be given the functionality of a finite state
machine by adding a pointer to an instance of a derived object of the State
class, and a method permitting a client to change the instance the pointer is
pointing to.
Code: Select all
class Troll
{
/* ATTRIBUTES OMITTED */
State* m_pCurrentState;
public:
/* INTERFACE TO ATTRIBUTES OMITTED */
void Update()
{
m_pCurrentState->Execute(this);
}
void ChangeState(const State* pNewState)
{
delete m_pCurrentState;
m_pCurrentState = pNewState;
}
};
method of the current state type with the this pointer. The current state
may then use the Troll interface to query its owner, to adjust its owner’s
attributes, or to effect a state transition. In other words, how a Troll
behaves when updated can be made completely dependent on the logic in
its current state. This is best illustrated with an example, so let’s create a
couple of states to enable a troll to run away from enemies when it feels
threatened and to sleep when it feels safe.
Code: Select all
//----------------------------------State_RunAway
class State_RunAway : public State
{
public:
void Execute(Troll* troll)
{
if (troll->isSafe())
{
troll->ChangeState(new State_Sleep());
}
else
{
troll->MoveAwayFromEnemy();
}
}
};
//----------------------------------State_Sleep
class State_Sleep : public State
{
public:
void Execute(Troll* troll)
{
if (troll->isThreatened())
{
troll->ChangeState(new State_RunAway())
}
else
{
troll->Snore();
}
}
};
As you can see, when updated, a troll will behave differently depending on
which of the states m_pCurrentState points to. Both states are encapsulated
as objects and both provide the rules effecting state transition. All very neat
and tidy.
This architecture is known as the state design pattern and provides an
elegant way of implementing state-driven behavior. Although this is a
departure from the mathematical formalization of an FSM, it is intuitive,
simple to code, and easily extensible. It also makes it extremely easy to add
enter and exit actions to each state; all you have to do is create Enter and
Exit methods and adjust the agent’s ChangeState method accordingly.
You’ll see the code that does exactly this very shortly.
ok, the method is undrstood perfectly, but at the moment to get it to implement, i have a dependence fail. Becose, if i declare the class State and then declare the class Troll, it do not reconize the Troll class at virtual void Execute (Troll* troll) = 0. And if i declare the class Troll and then the
class State, it do not reconize the State* m_pCurrentState member.
How do i solve this dependence problem without modify the own nature of the solution???
Thx in advance
and sorry for a too long post