#include <cstdio>
#include <bitset>
using namespace std;
template<typename T>
class State
{
public:
virtual void enter(T&)=0;
virtual void execute(T&)=0;
virtual void exit(T&)=0;
};
template<typename T>
class StateMachine
{
public:
StateMachine(T& owner)
: owner_(owner)
, current_(0)
{
}
void change(State<T>* state) {
if (current_) current_->exit(owner_);
current_ = state;
if (current_) current_->enter(owner_);
}
void update() {
if (current_) current_->execute(owner_);
}
private:
T& owner_;
State<T>* current_;
};
class Person;
class StandState : public State<Person>
{
public:
virtual void enter(Person& person){ printf("StandState::enter\n"); }
virtual void execute(Person& person);
virtual void exit(Person& person){ printf("StandState::exit\n"); }
};
class MoveState : public State<Person>
{
virtual void enter(Person& person){ printf("MoveState::enter\n"); }
virtual void execute(Person& person){ printf("MoveState::execute\n"); }
virtual void exit(Person& person){ printf("MoveState::exit\n"); }
};
class JumpState : public State<Person>
{
virtual void enter(Person& person){ printf("JumpState::enter\n"); }
virtual void execute(Person& person){ printf("JumpState::execute\n"); }
virtual void exit(Person& person){ printf("JumpState::exit\n"); }
};
class Person
{
StandState standState_;
MoveState moveState_;
JumpState jumpState_;
StateMachine<Person> fsm_;
enum {
kStand,
kMove,
kJump,
kMax
};
std::bitset<3> flags_;
public:
Person()
: fsm_(*this)
, next_(0)
{
fsm_.change(&standState_);
}
void update() { fsm_.update(); }
void setStand(bool enable) { flags_.reset(); flags_[kStand] = enable; }
void setMove(bool enable) { flags_.reset(); flags_[kMove] = enable; }
void setJump(bool enable) { flags_.reset(); flags_[kJump] = enable; }
bool isStand() { return flags_[kStand]; }
bool isMove() { return flags_[kMove]; }
bool isJump() { return flags_[kJump]; }
bool action();
bool checkNextState();
void setNextState(State<Person>* state) { next_ = state; }
bool needChange() { return next_; }
State<Person>* nextState() { State<Person>* next = next_; next_=0; return next; }
void changeState() { assert(needChange()); fsm_.change(nextState()); }
private:
State<Person>* next_;
};
bool Person::checkNextState()
{
bool result = false;
if (isStand()) {
setNextState(&standState_);
result = true;
} else if (isMove()) {
setNextState(&moveState_);
result = true;
} else if (isJump()) {
setNextState(&jumpState_);
result = true;
}
return result;
}
bool Person::action()
{
bool result = false;
if (needChange()) {
changeState();
result = true;
}
return result;
}
void StandState::execute(Person& person)
{
printf("StandState::execute\n");
person.setJump(true);
if (person.checkNextState()) {
person.action();
}
}
int main()
{
Person* person = new Person();
for (int i = 0; i < 3; ++i) {
person->update();
}
delete person;
return 0;
}