#include "Base.h" #include "AIStateMachine.h" #include "AIAgent.h" #include "AIMessage.h" #include "Game.h" namespace gameplay { AIStateMachine::AIStateMachine(AIAgent* agent) : _agent(agent) { GP_ASSERT(agent); if (AIState::_empty) AIState::_empty->addRef(); else AIState::_empty = new AIState(""); _currentState = AIState::_empty; } AIStateMachine::~AIStateMachine() { // Release all states for (std::list::iterator itr = _states.begin(); itr != _states.end(); ++itr) { (*itr)->release(); } SAFE_RELEASE(AIState::_empty); } AIAgent* AIStateMachine::getAgent() const { return _agent; } AIState* AIStateMachine::addState(const char* id) { AIState* state = AIState::create(id); _states.push_back(state); return state; } void AIStateMachine::addState(AIState* state) { state->addRef(); _states.push_back(state); } void AIStateMachine::removeState(AIState* state) { std::list::iterator itr = std::find(_states.begin(), _states.end(), state); if (itr != _states.end()) { _states.erase(itr); state->release(); } } AIState* AIStateMachine::getState(const char* id) const { GP_ASSERT(id); AIState* state; for (std::list::const_iterator itr = _states.begin(); itr != _states.end(); ++itr) { state = (*itr); if (strcmp(id, state->getId()) == 0) return state; } return NULL; } AIState* AIStateMachine::getActiveState() const { return _currentState; } bool AIStateMachine::hasState(AIState* state) const { GP_ASSERT(state); return (std::find(_states.begin(), _states.end(), state) != _states.end()); } AIState* AIStateMachine::setState(const char* id) { AIState* state = getState(id); if (state) sendChangeStateMessage(state); return state; } bool AIStateMachine::setState(AIState* state) { if (hasState(state)) { sendChangeStateMessage(state); return true; } return false; } void AIStateMachine::sendChangeStateMessage(AIState* newState) { AIMessage* message = AIMessage::create(0, _agent->getId(), _agent->getId(), 1); message->_messageType = AIMessage::MESSAGE_TYPE_STATE_CHANGE; message->setString(0, newState->getId()); Game::getInstance()->getAIController()->sendMessage(message); } void AIStateMachine::setStateInternal(AIState* state) { GP_ASSERT(hasState(state)); // Fire the exit event for the current state _currentState->exit(this); // Set the new state _currentState = state; // Fire the enter event for the new state _currentState->enter(this); } void AIStateMachine::update(float elapsedTime) { _currentState->update(this, elapsedTime); } }