BWAPI
SPAR/AIModule/SparAIModule/Utils/FSM/Transition.h
Go to the documentation of this file.
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 };
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines