BWAPI
|
00001 #pragma once 00002 #include "../../Scheduler/SchedulerTask.h" 00003 #include "../EventHandler.h" 00004 #include "../Logger.h" 00005 #include "Condition.h" 00006 00007 // Macro to create transitions? 00008 00013 class TransitionAction 00014 { 00015 }; 00016 00020 class NoTransitionAction : public TransitionAction 00021 { 00022 public: 00023 void execute() const {} 00024 template <class Arguments> 00025 void execute(const Arguments& args) const {} 00026 }; 00027 00039 template <class OriginState, class Condition, class TransitionAction, class DestinationState, class EventHandlerType = EventHandler> 00040 class Transition : public EventHandlerType 00041 { 00042 public: 00043 typedef typename EventHandlerType::arguments Arguments; 00053 Transition(OriginState& originState, Condition condition, TransitionAction action, 00054 DestinationState& destinationState) 00055 : EventHandlerType(originState) 00056 , m_originState(originState) 00057 , m_condition(condition) 00058 , m_action(action) 00059 , m_destinationState(destinationState) 00060 { 00061 } 00062 00063 virtual ~Transition() {} 00064 00071 virtual void onEvent(void*, Arguments& args) 00072 { 00073 testTransition(args); 00074 } 00075 00081 bool testTransition(Arguments& args) 00082 { 00083 const size_t frameNumber = BWAPI::Broodwar->getFrameCount(); 00084 bool activation = false; 00085 // Check whether another transition has already been activated in this frame 00086 if (m_originState.getEarliestNextTransitionFrame() != frameNumber + 1) 00087 { 00088 if (ExpandArguments<Arguments>::evaluate(m_condition, args)) 00089 { 00090 m_originState.setEarliestNextTransitionFrame(frameNumber + 1); 00091 activate(args); 00092 activation = true; 00093 } 00094 } 00095 return activation; 00096 } 00097 00098 protected: 00099 template <class Arguments> 00100 struct ExpandArguments {}; 00101 00102 template <> 00103 struct ExpandArguments<boost::tuple<>> { 00104 static bool evaluate(Condition& condition, boost::tuple<>&) { 00105 return condition.evaluate(); 00106 } 00107 static void execute(TransitionAction& action, boost::tuple<>&) { 00108 action.execute(); 00109 } 00110 }; 00111 template <class T1> 00112 struct ExpandArguments<boost::tuple<T1>> { 00113 static bool evaluate(Condition& condition, boost::tuple<T1>& args) { 00114 return condition.evaluate(args.get<0>()); 00115 } 00116 static void execute(TransitionAction& action, boost::tuple<T1>& args) { 00117 action.execute(args.get<0>()); 00118 } 00119 }; 00120 template <class T1,class T2> 00121 struct ExpandArguments<boost::tuple<T1,T2>> { 00122 static bool evaluate(Condition& condition, boost::tuple<T1,T2>& args) { 00123 return condition.evaluate(args.get<0>(), args.get<1>()); 00124 } 00125 static void execute(TransitionAction& action, boost::tuple<T1,T2>& args) { 00126 action.execute(args.get<0>(), args.get<1>()); 00127 } 00128 }; 00129 template <class T1,class T2,class T3> 00130 struct ExpandArguments<boost::tuple<T1,T2,T3>> { 00131 static bool evaluate(Condition& condition, boost::tuple<T1,T2,T3>& args) { 00132 return condition.evaluate(args.get<0>(), args.get<1>(), args.get<2>()); 00133 } 00134 static void execute(TransitionAction& action, boost::tuple<T1,T2,T3>& args) { 00135 action.execute(args.get<0>(), args.get<1>(), args.get<2>()); 00136 } 00137 }; 00138 template <class T1,class T2,class T3,class T4> 00139 struct ExpandArguments<boost::tuple<T1,T2,T3,T4>> { 00140 static bool evaluate(Condition& condition, boost::tuple<T1,T2,T3,T4>& args) { 00141 return condition.evaluate(args.get<0>(), args.get<1>(), args.get<2>(), args.get<3>()); 00142 } 00143 static void execute(TransitionAction& action, boost::tuple<T1,T2,T3,T4>& args) { 00144 action.execute(args.get<0>(), args.get<1>(), args.get<2>(), args.get<3>()); 00145 } 00146 }; 00147 template <class T1,class T2,class T3,class T4,class T5> 00148 struct ExpandArguments<boost::tuple<T1,T2,T3,T4,T5>> { 00149 static bool evaluate(Condition& condition, boost::tuple<T1,T2,T3,T4,T5>& args) { 00150 return condition.evaluate(args.get<0>(), args.get<1>(), args.get<2>(), args.get<3>(), args.get<4>()); 00151 } 00152 static void execute(TransitionAction& action, boost::tuple<T1,T2,T3,T4,T5>& args) { 00153 action.execute(args.get<0>(), args.get<1>(), args.get<2>(), args.get<3>(), args.get<4>()); 00154 } 00155 }; 00156 00166 void activate(Arguments& args) 00167 { 00168 assert(&m_originState.getBehavior() == &m_destinationState.getBehavior()); 00169 const IBehavior& behavior = m_originState.getBehavior(); 00170 00171 SPAR_LOG(LogTypes::LAYER_1_DECISION, "Behavior \"%s\": transition from state \"%s\" to state \"%s\"", 00172 behavior.getName().c_str(), 00173 m_originState.getName().c_str(), 00174 m_destinationState.getName().c_str()); 00175 00176 m_originState.onExit(); 00177 if (!behavior.isTerminated()) 00178 { 00179 ExpandArguments<Arguments>::execute(m_action, args); 00180 if (!behavior.isTerminated()) 00181 m_destinationState.onEnter(); 00182 } 00183 } 00184 00188 OriginState& m_originState; 00192 Condition m_condition; 00196 TransitionAction m_action; 00200 DestinationState& m_destinationState; 00201 };