BWAPI
SPAR/AIModule/SparAIModule/Utils/FSM/FSMState.h
Go to the documentation of this file.
00001 #pragma once
00002 #include "IFSMState.h"
00003 #include "Transition.h"
00004 #include "FSM.h"
00005 #include <boost/tuple/tuple.hpp>
00006 
00013 template <class FSM, class DerivedState>
00014 class FSMState : public IFSMState
00015 {
00016 public:
00017   FSMState(FSM &context)
00018     : m_context(context)
00019     , m_earliestNextTransitionFrame(0)
00020   {
00021   }
00022 
00023   virtual ~FSMState()
00024   {
00025   }
00026 
00027   std::string getName() const
00028   {
00029     // Could be done during compilation ;-)
00030     std::string fullName(typeid(DerivedState).name());
00031     size_t begin = fullName.find_last_of("::");
00032     if (begin == std::string::npos)
00033       begin = 0;
00034     else
00035       ++begin;
00036     return fullName.substr(begin);
00037   }
00038 
00044   virtual void externalTerminate()
00045   {
00046     onExit();
00047   }
00048 
00052   void onEnter()
00053   {
00054     m_context.setCurrentState(this);
00055 
00056     static_cast<DerivedState*>(this)->onEnterImpl();
00057 
00058     if (m_context.isExecuting())
00059     {
00060       enableTransitions();
00061     }
00062   }
00063 
00069   void onExit()
00070   {
00071     assert(m_context.m_currentState != NULL);
00072 
00073     static_cast<DerivedState*>(this)->onExitImpl();
00074 
00075     disableTransitions();
00076 
00077     m_context.onExitState();
00078 
00079 #ifdef _DEBUG_COMPONENT
00080     verifyPendingSubscriptions("ERROR FSMState::onExit(): Make sure to unsubscribe EventHandler \"%s\" from event \"%s\" when the FSM switches states.");
00081 
00082     verifyPendingTasks("ERROR FSMState::onExit(): Make sure to deactivate task \"%s\" when the FSM switches states.");
00083 #endif
00084 
00085     m_stateExitEvent.raise();
00086   }
00087 
00088   size_t getEarliestNextTransitionFrame() const
00089   {
00090     return m_earliestNextTransitionFrame;
00091   }
00092 
00093   void setEarliestNextTransitionFrame(size_t earliestAllowedFrameNumber)
00094   {
00095     m_earliestNextTransitionFrame = earliestAllowedFrameNumber;
00096   }
00097 
00098 protected:
00102   template <size_t size>
00103   struct EventsHelper
00104   {
00105     static void activate(const FSMState& state)
00106     {
00107       boost::get<size-1>(static_cast<const DerivedState&>(state).m_events).activate();
00108       EventsHelper<size-1>::activate(state);
00109     }
00110     static void deactivate(const FSMState& state)
00111     {
00112       boost::get<size-1>(static_cast<const DerivedState&>(state).m_events).deactivate();
00113       EventsHelper<size-1>::deactivate(state);
00114     }
00115   };
00119   template <>
00120   struct EventsHelper<0>
00121   {
00122     static void activate(const FSMState&) {}
00123     static void deactivate(const FSMState&) {}
00124   };
00125 
00129   void enableTransitions()
00130   {
00131     EventsHelper<boost::tuples::length<DerivedState::Events>::value>::activate(*this);
00132   }
00133 
00137   void disableTransitions()
00138   {
00139     EventsHelper<boost::tuples::length<DerivedState::Events>::value>::deactivate(*this);
00140   }
00141 
00142   // Problem: "Events m_events" and "Transitions m_transitions" cannot be stored in here as DerivedType is
00143   // not yet defined in FSMState<DerivedState> (so they must be defined in derived classes instead).
00144 
00148   FSM &m_context;
00149 
00155   size_t m_earliestNextTransitionFrame;
00156 
00157 private:
00158   FSMState(const FSMState& other);
00159 };
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines