#pragma once #include #include "../Messaging/Telegram.h" #include "Goal.h" template class GoalComposite : public Goal { private: typedef std::list*> SubgoalList; protected: // composite goals may have any number of subgoals SubgoalList m_SubGoals; // processes any subgoals that may be present int processSubgoals(); // passes the message to the front-most subgoal bool forwardMessageToFrontMostSubgoal(const Telegram&); public: GoalComposite(entity_type* pE, int type) : Goal(pE, type) {} // when this object is destroyed make sure any subgoals are terminated // and destroyed. virtual ~GoalComposite() { removeAllSubgoals(); } // logic to run when the goal is activated. void Activate() override = 0; // logic to run each update-step. int Process() override = 0; // logic to run prior to the goal's destruction void Terminate() override = 0; void markOwnerWithGoal() override = 0; // if a child class of GoalComposite does not define a message handler // the default behavior is to forward the message to the front-most // subgoal virtual bool handleMessage(const Telegram& msg) { return forwardMessageToFrontMostSubgoal(msg); } // adds a subgoal to the front of the subgoal list void addSubgoal(Goal* g); // this method iterates through the subgoals and calls each one's Terminate // method before deleting the subgoal and removing it from the subgoal list void removeAllSubgoals(); }; //---------------------- removeAllSubgoals ------------------------------------ //----------------------------------------------------------------------------- template void GoalComposite::removeAllSubgoals() { for (typename SubgoalList::iterator it = m_SubGoals.begin(); it != m_SubGoals.end(); ++it) { (*it)->Terminate(); delete *it; } m_SubGoals.clear(); } //-------------------------- ProcessSubGoals ---------------------------------- // // this method first removes any completed goals from the front of the // subgoal list. It then processes the next goal in the list (if there is one) //----------------------------------------------------------------------------- template int GoalComposite::processSubgoals() { // remove all completed and failed goals from the front of the subgoal list while (!m_SubGoals.empty() && (m_SubGoals.front()->isComplete() || m_SubGoals.front()->hasFailed())) { m_SubGoals.front()->Terminate(); delete m_SubGoals.front(); m_SubGoals.pop_front(); } // if any subgoals remain, process the one at the front of the list if (!m_SubGoals.empty()) { // grab the status of the front-most subgoal int StatusOfSubGoals = m_SubGoals.front()->Process(); // we have to test for the special case where the front-most subgoal // reports 'completed' *and* the subgoal list contains additional // goals.When this is the case, to ensure the parent keeps processing // its subgoal list we must return the 'active' status. if (StatusOfSubGoals == Goal::completed && m_SubGoals.size() > 1) { return Goal::active; } return StatusOfSubGoals; } // no more subgoals to process - return 'completed' else { return Goal::completed; } } //----------------------------- addSubgoal ------------------------------------ template void GoalComposite::addSubgoal(Goal* g) { // add the new goal to the front of the list m_SubGoals.push_front(g); } //---------------- forwardMessageToFrontMostSubgoal --------------------------- // // passes the message to the goal at the front of the queue //----------------------------------------------------------------------------- template bool GoalComposite::forwardMessageToFrontMostSubgoal( const Telegram& msg) { if (!m_SubGoals.empty()) { return m_SubGoals.front()->HandleMessage(msg); } // return false if the message has not been handled return false; }