diff options
Diffstat (limited to 'src/libjin/ai/je_state_machine.cpp')
-rw-r--r-- | src/libjin/ai/je_state_machine.cpp | 407 |
1 files changed, 380 insertions, 27 deletions
diff --git a/src/libjin/ai/je_state_machine.cpp b/src/libjin/ai/je_state_machine.cpp index 3a8cd0d..2d82a0a 100644 --- a/src/libjin/ai/je_state_machine.cpp +++ b/src/libjin/ai/je_state_machine.cpp @@ -1,5 +1,7 @@ #include "je_state_machine.h" +#include "../utils/je_log.h" + using namespace std; namespace JinEngine @@ -7,120 +9,471 @@ namespace JinEngine namespace AI { - StateMachine::StateMachine() + StateMachine::StateMachine(Mode mode, void* userdata) + : mCurrentState("Empty") + , mUserData(userdata) + , mMode(mode) { - + addState("Empty"); } StateMachine::~StateMachine() { + } + void StateMachine::invokeCallback(const string& from, const string& to) + { + if (mExitCallback != nullptr) + mExitCallback(from, mUserData); + if (mTraslateCallback != nullptr) + mTraslateCallback(from, to, mUserData); + if (mEnterCallback != nullptr) + mEnterCallback(to, mUserData); + map<string, StateChangeCallback*>::iterator it = mOnExitState.find(from); + if (it != mOnExitState.end()) + it->second(mUserData); + map<pair<string, string>, StateTranslateCallback*>::iterator transItr + = mOnStateTranslate.find(pair<string, string>(from, to)); + if (transItr != mOnStateTranslate.end()) + transItr->second(mUserData); + it = mOnEnterState.find(to); + if (it != mOnEnterState.end()) + it->second(mUserData); } - void StateMachine::onUpdate() + void StateMachine::stepwiseProcess() { + map<string, State>::iterator it = mStates.find(mCurrentState); + if (it == mStates.end()) + { + jin_log_error("The state %s is not exist.", mCurrentState); + return; + } + State& state = it->second; + for (int i = 0; i < state.transitions.size(); ++i) + { + if (processCondition(state.transitions[i].condition)) + { + // Traslate + mCurrentState = state.transitions[i].state; + invokeCallback(state.name, mCurrentState); + return; + } + } + } + void StateMachine::iterativeProcess() + { + map<string, State>::iterator it = mStates.find(mCurrentState); + if (it == mStates.end()) + { + jin_log_error("The state %s is not exist.", mCurrentState); + return; + } + State& state = it->second; + for (int i = 0; i < state.transitions.size(); ++i) + { + if (processCondition(state.transitions[i].condition)) + { + // Traslate + mCurrentState = state.transitions[i].state; + invokeCallback(state.name, mCurrentState); + return iterativeProcess(); + } + } } - const string& StateMachine::getCurrentState() + void StateMachine::setMode(Mode mode) { + mMode = mode; + } + //ģʽ״̬ + void StateMachine::update() + { + switch (mMode) + { + case Mode::Iterative: iterativeProcess(); break; + case Mode::Stepwise: stepwiseProcess(); break; + } } - void StateMachine::addParameteri(const std::string& name) + bool StateMachine::processCondition(const Condition& condition) { + map<string, Parameter>::iterator it = mParameters.find(condition.parameter); + if (it == mParameters.end()) + { + jin_log_error("The parameter %s is not exist", condition.parameter); + return false; + } + Parameter& p = it->second; + switch (p.type) + { + case ParameterType::Int: return p.value._int == condition.value._int; + case ParameterType::Float: return p.value._float == condition.value._float; + case ParameterType::Bool: return p.value._bool == condition.value._bool; + case ParameterType::Trigger: + { + bool trigger = p.value._int == true; + if (trigger) p.value._int = false; + return trigger; + } + } + return false; + } + const string& StateMachine::getCurrentState() + { + return mCurrentState; } - void StateMachine::addParameterf(const std::string& name) + void StateMachine::addParameteri(const std::string& name) { + if (mParameters.find(name) != mParameters.end()) + { + jin_log_error("The parameter %s is already exist.", name); + return; + } + Parameter p; + p.type = ParameterType::Int; + p.value._int = 0; + mParameters.insert(pair<string, Parameter>(name, p)); + } + void StateMachine::addParameterf(const std::string& name) + { + if (mParameters.find(name) != mParameters.end()) + { + jin_log_error("The parameter %s is already exist.", name); + return; + } + Parameter p; + p.type = ParameterType::Float; + p.value._float = 0.0f; + mParameters.insert(pair<string, Parameter>(name, p)); } void StateMachine::addParameterb(const std::string& name) { - + if (mParameters.find(name) != mParameters.end()) + { + jin_log_error("The parameter %s is already exist.", name); + return; + } + Parameter p; + p.type = ParameterType::Bool; + p.value._bool = false; + mParameters.insert(pair<string, Parameter>(name, p)); } void StateMachine::addParametert(const std::string& name) { - + if (mParameters.find(name) != mParameters.end()) + { + jin_log_error("The parameter %s is already exist.", name); + return; + } + Parameter p; + p.type = ParameterType::Trigger; + p.value._trigger = false; + mParameters.insert(pair<string, Parameter>(name, p)); } void StateMachine::addState(const std::string& name) { + if (mStates.find(name) != mStates.end()) + { + jin_log_error("The state %s is already exist.", name); + return; + } + State state; + state.name = name; + mStates.insert(pair<string, State>(name, state)); + } + const char* StateMachine::parameterTypeString(ParameterType type) + { + switch (type) + { + case ParameterType::Int: return "int"; + case ParameterType::Float: return "float"; + case ParameterType::Bool: return "bool"; + case ParameterType::Trigger: return "trigger"; + } } void StateMachine::addTransitioni(const std::string& stateFrom, const std::string& stateTo, const std::string& name, int value) { - + map<string, State>::iterator it; + it = mStates.find(stateFrom); + if (it == mStates.end()) + { + jin_log_error("The state %s is not exist.", stateFrom); + return; + } + State& from = it->second; + it = mStates.find(stateTo); + if (it == mStates.end()) + { + jin_log_error("The state %s is not exist.", stateTo); + return; + } + State& to = it->second; + map<string, Parameter>::iterator itp; + itp = mParameters.find(name); + if (itp == mParameters.end()) + { + jin_log_error("The parameter is not exist.", name); + return; + } + Parameter& parameter = itp->second; + if (parameter.type != ParameterType::Int) + { + jin_log_error("The type of parameter called %s is %s, but the transition gives a int value.", name, parameterTypeString(parameter.type)); + return; + } + Transition trasition; + trasition.condition.parameter = name; + trasition.condition.value._int = value; + trasition.state = stateTo; + from.transitions.push_back(trasition); } void StateMachine::addTransitionf(const std::string& stateFrom, const std::string& stateTo, const std::string& name, float value) { - + map<string, State>::iterator it; + it = mStates.find(stateFrom); + if (it == mStates.end()) + { + jin_log_error("The state %s is not exist.", stateFrom); + return; + } + State& from = it->second; + it = mStates.find(stateTo); + if (it == mStates.end()) + { + jin_log_error("The state %s is not exist.", stateTo); + return; + } + State& to = it->second; + map<string, Parameter>::iterator itp; + itp = mParameters.find(name); + if (itp == mParameters.end()) + { + jin_log_error("The parameter is not exist.", name); + return; + } + Parameter& parameter = itp->second; + if (parameter.type != ParameterType::Float) + { + jin_log_error("The type of parameter called %s is %s, but the transition gives a float value.", name, parameterTypeString(parameter.type)); + return; + } + Transition trasition; + trasition.condition.parameter = name; + trasition.condition.value._float = value; + trasition.state = stateTo; + from.transitions.push_back(trasition); } void StateMachine::addTransitionb(const std::string& stateFrom, const std::string& stateTo, const std::string& name, bool value) { - + map<string, State>::iterator it; + it = mStates.find(stateFrom); + if (it == mStates.end()) + { + jin_log_error("The state %s is not exist.", stateFrom); + return; + } + State& from = it->second; + it = mStates.find(stateTo); + if (it == mStates.end()) + { + jin_log_error("The state %s is not exist.", stateTo); + return; + } + State& to = it->second; + map<string, Parameter>::iterator itp; + itp = mParameters.find(name); + if (itp == mParameters.end()) + { + jin_log_error("The parameter is not exist.", name); + return; + } + Parameter& parameter = itp->second; + if (parameter.type != ParameterType::Bool) + { + jin_log_error("The type of parameter called %s is %s, but the transition gives a bool value.", name, parameterTypeString(parameter.type)); + return; + } + Transition trasition; + trasition.condition.parameter = name; + trasition.condition.value._bool = value; + trasition.state = stateTo; + from.transitions.push_back(trasition); } void StateMachine::addTransitiont(const std::string& stateFrom, const std::string& stateTo, const std::string& name) { - + map<string, State>::iterator it; + it = mStates.find(stateFrom); + if (it == mStates.end()) + { + jin_log_error("The state %s is not exist.", stateFrom); + return; + } + State& from = it->second; + it = mStates.find(stateTo); + if (it == mStates.end()) + { + jin_log_error("The state %s is not exist.", stateTo); + return; + } + State& to = it->second; + map<string, Parameter>::iterator itp; + itp = mParameters.find(name); + if (itp == mParameters.end()) + { + jin_log_error("The parameter is not exist.", name); + return; + } + Parameter& parameter = itp->second; + if (parameter.type != ParameterType::Trigger) + { + jin_log_error("The type of parameter called %s is %s, but the transition gives a trigger value.", name, parameterTypeString(parameter.type)); + return; + } + Transition trasition; + trasition.condition.parameter = name; + trasition.condition.value._trigger = true; + trasition.state = stateTo; + from.transitions.push_back(trasition); } void StateMachine::setParameteri(const std::string& name, int value) { - + map<string, Parameter>::iterator it = mParameters.find(name); + if (it == mParameters.end()) + { + jin_log_error("The state %s is not exist.", name); + return; + } + Parameter& p = it->second; + if (p.type != ParameterType::Int) + { + jin_log_error("The type of parameter called %s is %s, but try to assign a int value to it", name, parameterTypeString(p.type)); + return; + } + p.value._int = value; } void StateMachine::setParameterf(const std::string& name, float value) { - + map<string, Parameter>::iterator it = mParameters.find(name); + if (it == mParameters.end()) + { + jin_log_error("The state %s is not exist.", name); + return; + } + Parameter& p = it->second; + if (p.type != ParameterType::Float) + { + jin_log_error("The type of parameter called %s is %s, but try to assign a float value to it", name, parameterTypeString(p.type)); + return; + } + p.value._float = value; } void StateMachine::setParameterb(const std::string& name, bool value) { - + map<string, Parameter>::iterator it = mParameters.find(name); + if (it == mParameters.end()) + { + jin_log_error("The state %s is not exist.", name); + return; + } + Parameter& p = it->second; + if (p.type != ParameterType::Bool) + { + jin_log_error("The type of parameter called %s is %s, but try to assign a bool value to it", name, parameterTypeString(p.type)); + return; + } + p.value._bool = value; } void StateMachine::setParametert(const std::string& name) { - + map<string, Parameter>::iterator it = mParameters.find(name); + if (it == mParameters.end()) + { + jin_log_error("The state %s is not exist.", name); + return; + } + Parameter& p = it->second; + if (p.type != ParameterType::Trigger) + { + jin_log_error("The type of parameter called %s is %s, but try to assign a trigger value to it", name, parameterTypeString(p.type)); + return; + } + p.value._trigger = true; } - void StateMachine::trigger(const std::string& name) + void StateMachine::forceToState(const std::string& name) { - + if (mStates.find(name) == mStates.end()) + { + jin_log_error("The state %s is not exist.", name); + return; + } + mCurrentState = name; } - void StateMachine::forceToState(const std::string& name) + void StateMachine::addEnterListener(const std::string& state, StateChangeCallback* callback) { - + if (mOnEnterState.find(state) != mOnEnterState.end()) + { + jin_log_error("The enter listener of %s is already exist.", state); + return; + } + mOnEnterState.insert(pair<string, StateChangeCallback*>(state, callback)); } - void StateMachine::reset() + void StateMachine::addExitListener(const std::string& state, StateChangeCallback* callback) { - + if (mOnExitState.find(state) != mOnExitState.end()) + { + jin_log_error("The exit listener of %s is already exist.", state); + return; + } + mOnExitState.insert(pair<string, StateChangeCallback*>(state, callback)); } - void StateMachine::addEnterListener(SingleStateCallback callback) + void StateMachine::addTranslateListener(const std::string& from, const std::string& to, StateChangeCallback* callback) { - + if (mOnStateTranslate.find(pair<string, string>(from, to)) != mOnStateTranslate.end()) + { + jin_log_error("The traslate listener of %s to %s is already exist.", from, to); + return; + } + pair<string, string> key(from, to); + mOnStateTranslate.insert(pair<pair<string, string>, StateTranslateCallback*>(key, callback)); } - void StateMachine::addExitListener(SingleStateCallback callback) + void StateMachine::setEnterListener(SingleStateCallback* callback) { - + mEnterCallback = callback; } - void StateMachine::addTranslateListener(DoubleStateCallback callback) + void StateMachine::setExitListener(SingleStateCallback* callback) { + mExitCallback = callback; + } + void StateMachine::setTranslateListener(DoubleStateCallback* callback) + { + mTraslateCallback = callback; } + } // namespace AI } // namespace JinEngine
\ No newline at end of file |