aboutsummaryrefslogtreecommitdiff
path: root/src/libjin/ai/je_state_machine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libjin/ai/je_state_machine.cpp')
-rw-r--r--src/libjin/ai/je_state_machine.cpp407
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