Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

Project : West World With Messaging Language : C++ Source was made with Visual Studio 2010, on a machine running Windows Vista. This is old

Project : West World With Messaging

Language : C++

Source was made with Visual Studio 2010, on a machine running Windows Vista. This is old source code.. End product should work in Visual Studio 2015.

This source has multiple working state machines, simply add an additional character that interacts with the other two character state machines. Be sure to note within the source where alterations had been made, and all code should include complete explanation via comments within the source code.

Please add a mouse character that interacts with the miners wife. Have the mouse wake up when the miner leaves home and states he is heading out (He already states he is leaving in the source code), and go back to his hole to sleep when he returns. Have the wife cut cheese and leave it on a counter when the mouse is awake and she should say "I should prepare a snack for later." Then have the mouse respond to the message saying "Squeak!" and steal / eat the cheese that was prepared by the wife.

*************************** BaseGameEntity.h *************************** #ifndef ENTITY_H #define ENTITY_H //------------------------------------------------------------------------ // // Name: BaseGameEntity.h // // Desc: Base class for a game object // // Author: Mat Buckland 2002 (fup@ai-junkie.com) // //------------------------------------------------------------------------ #include

#include "messaging/Telegram.h"

class BaseGameEntity {

private:

//every entity must have a unique identifying number int m_ID;

//this is the next valid ID. Each time a BaseGameEntity is instantiated //this value is updated static int m_iNextValidID;

//this must be called within the constructor to make sure the ID is set //correctly. It verifies that the value passed to the method is greater //or equal to the next valid ID, before setting the ID and incrementing //the next valid ID void SetID(int val);

public:

BaseGameEntity(int id) { SetID(id); }

virtual ~BaseGameEntity(){}

//all entities must implement an update function virtual void Update()=0;

//all entities can communicate using messages. They are sent //using the MessageDispatcher singleton class virtual bool HandleMessage(const Telegram& msg)=0;

int ID()const{return m_ID;} };

#endif

*************************** EntityManager.h

*************************** #ifndef ENTITYMANAGER_H #define ENTITYMANAGER_H #pragma warning (disable:4786) //------------------------------------------------------------------------ // // Name: EntityManager.h // // Desc: Singleton class to handle the management of Entities. // // Author: Mat Buckland 2002 (fup@ai-junkie.com) // //------------------------------------------------------------------------ #include #include #include

class BaseGameEntity;

//provide easy access #define EntityMgr EntityManager::Instance()

class EntityManager { private:

typedef std::map EntityMap;

private:

//to facilitate quick lookup the entities are stored in a std::map, in which //pointers to entities are cross referenced by their identifying number EntityMap m_EntityMap;

EntityManager(){}

//copy ctor and assignment should be private EntityManager(const EntityManager&); EntityManager& operator=(const EntityManager&);

public:

static EntityManager* Instance();

//this method stores a pointer to the entity in the std::vector //m_Entities at the index position indicated by the entity's ID //(makes for faster access) void RegisterEntity(BaseGameEntity* NewEntity);

//returns a pointer to the entity with the ID given as a parameter BaseGameEntity* GetEntityFromID(int id)const;

//this method removes the entity from the list void RemoveEntity(BaseGameEntity* pEntity); };

#endif

*************************** EntityNames.h

*************************** #ifndef NAMES_H #define NAMES_H

#include

enum { ent_Miner_Bob,

ent_Elsa };

inline std::string GetNameOfEntity(int n) { switch(n) { case ent_Miner_Bob:

return "Miner Bob";

case ent_Elsa: return "Elsa";

default:

return "UNKNOWN!"; } }

#endif

*************************** Locations.h

*************************** #ifndef LOCATIONS_H #define LOCATIONS_H

enum location_type { shack, goldmine, bank, saloon };

//uncomment this to send the output to a text file //#define TEXTOUTPUT

#endif

*************************** MessageDispatcher.h

*************************** #ifndef MESSAGE_DISPATCHER_H #define MESSAGE_DISPATCHER_H //------------------------------------------------------------------------ // // Name: MessageDispatcher.h // // Desc: A message dispatcher. Manages messages of the type Telegram. // Instantiated as a singleton. // // Author: Mat Buckland 2002 (fup@ai-junkie.com) // //------------------------------------------------------------------------ #pragma warning (disable:4786)

#include

#include "misc/ConsoleUtils.h" #include "messaging/Telegram.h"

class BaseGameEntity;

//to make code easier to read const double SEND_MSG_IMMEDIATELY = 0.0f; const int NO_ADDITIONAL_INFO = 0;

//to make life easier... #define Dispatch MessageDispatcher::Instance()

class MessageDispatcher { private: //a std::set is used as the container for the delayed messages //because of the benefit of automatic sorting and avoidance //of duplicates. Messages are sorted by their dispatch time. std::set PriorityQ;

//this method is utilized by DispatchMessage or DispatchDelayedMessages. //This method calls the message handling member function of the receiving //entity, pReceiver, with the newly created telegram void Discharge(BaseGameEntity* pReceiver, const Telegram& msg);

MessageDispatcher(){}

//copy ctor and assignment should be private MessageDispatcher(const MessageDispatcher&); MessageDispatcher& operator=(const MessageDispatcher&);

public:

//this class is a singleton static MessageDispatcher* Instance();

//send a message to another agent. Receiving agent is referenced by ID. void DispatchMessage(double delay, int sender, int receiver, int msg, void* ExtraInfo);

//send out any delayed messages. This method is called each time through //the main game loop. void DispatchDelayedMessages(); };

#endif

*************************** MessageTypes.h

*************************** #ifndef MESSAGE_TYPES #define MESSAGE_TYPES

#include

enum message_type { Msg_HiHoneyImHome, Msg_StewReady, };

inline std::string MsgToStr(int msg) { switch (msg) { case Msg_HiHoneyImHome: return "HiHoneyImHome";

case Msg_StewReady: return "StewReady";

default:

return "Not recognized!"; } }

#endif

***************************

Miner.h

*************************** #ifndef MINER_H #define MINER_H //------------------------------------------------------------------------ // // Name: Miner.h // // Desc: A class defining a goldminer. // // Author: Mat Buckland 2002 (fup@ai-junkie.com) // //------------------------------------------------------------------------ #include #include #include

#include "BaseGameEntity.h" #include "Locations.h" #include "misc/ConsoleUtils.h" #include "MinerOwnedStates.h" #include "fsm/StateMachine.h"

template class State; //pre-fixed with "template " for vs8 compatibility

struct Telegram;

//the amount of gold a miner must have before he feels he can go home const int ComfortLevel = 5; //the amount of nuggets a miner can carry const int MaxNuggets = 3; //above this value a miner is thirsty const int ThirstLevel = 5; //above this value a miner is sleepy const int TirednessThreshold = 5;

class Miner : public BaseGameEntity { private:

//an instance of the state machine class StateMachine* m_pStateMachine; location_type m_Location;

//how many nuggets the miner has in his pockets int m_iGoldCarried;

int m_iMoneyInBank;

//the higher the value, the thirstier the miner int m_iThirst;

//the higher the value, the more tired the miner int m_iFatigue;

public:

Miner(int id):m_Location(shack), m_iGoldCarried(0), m_iMoneyInBank(0), m_iThirst(0), m_iFatigue(0), BaseGameEntity(id) { //set up state machine m_pStateMachine = new StateMachine(this); m_pStateMachine->SetCurrentState(GoHomeAndSleepTilRested::Instance());

/* NOTE, A GLOBAL STATE HAS NOT BEEN IMPLEMENTED FOR THE MINER */ }

~Miner(){delete m_pStateMachine;}

//this must be implemented void Update();

//so must this virtual bool HandleMessage(const Telegram& msg);

StateMachine* GetFSM()const{return m_pStateMachine;}

//-------------------------------------------------------------accessors location_type Location()const{return m_Location;} void ChangeLocation(location_type loc){m_Location=loc;} int GoldCarried()const{return m_iGoldCarried;} void SetGoldCarried(int val){m_iGoldCarried = val;} void AddToGoldCarried(int val); bool PocketsFull()const{return m_iGoldCarried >= MaxNuggets;}

bool Fatigued()const; void DecreaseFatigue(){m_iFatigue -= 1;} void IncreaseFatigue(){m_iFatigue += 1;}

int Wealth()const{return m_iMoneyInBank;} void SetWealth(int val){m_iMoneyInBank = val;} void AddToWealth(int val);

bool Thirsty()const; void BuyAndDrinkAWhiskey(){m_iThirst = 0; m_iMoneyInBank-=2;}

};

#endif

*************************** MinerOwnedStates.h

*************************** #ifndef MINER_OWNED_STATES_H #define MINER_OWNED_STATES_H //------------------------------------------------------------------------ // // Name: MinerOwnedStates.h // // Desc: All the states that can be assigned to the Miner class. // Note that a global state has not been implemented. // // Author: Mat Buckland 2002 (fup@ai-junkie.com) // //------------------------------------------------------------------------ #include "fsm/State.h"

class Miner; struct Telegram;

//------------------------------------------------------------------------ // // In this state the miner will walk to a goldmine and pick up a nugget // of gold. If the miner already has a nugget of gold he'll change state // to VisitBankAndDepositGold. If he gets thirsty he'll change state // to QuenchThirst //------------------------------------------------------------------------ class EnterMineAndDigForNugget : public State { private: EnterMineAndDigForNugget(){}

//copy ctor and assignment should be private EnterMineAndDigForNugget(const EnterMineAndDigForNugget&); EnterMineAndDigForNugget& operator=(const EnterMineAndDigForNugget&); public:

//this is a singleton static EnterMineAndDigForNugget* Instance();

virtual void Enter(Miner* miner);

virtual void Execute(Miner* miner);

virtual void Exit(Miner* miner);

virtual bool OnMessage(Miner* agent, const Telegram& msg);

};

//------------------------------------------------------------------------ // // Entity will go to a bank and deposit any nuggets he is carrying. If the // miner is subsequently wealthy enough he'll walk home, otherwise he'll // keep going to get more gold //------------------------------------------------------------------------ class VisitBankAndDepositGold : public State { private: VisitBankAndDepositGold(){}

//copy ctor and assignment should be private VisitBankAndDepositGold(const VisitBankAndDepositGold&); VisitBankAndDepositGold& operator=(const VisitBankAndDepositGold&); public:

//this is a singleton static VisitBankAndDepositGold* Instance();

virtual void Enter(Miner* miner);

virtual void Execute(Miner* miner);

virtual void Exit(Miner* miner);

virtual bool OnMessage(Miner* agent, const Telegram& msg); };

//------------------------------------------------------------------------ // // miner will go home and sleep until his fatigue is decreased // sufficiently //------------------------------------------------------------------------ class GoHomeAndSleepTilRested : public State { private: GoHomeAndSleepTilRested(){}

//copy ctor and assignment should be private GoHomeAndSleepTilRested(const GoHomeAndSleepTilRested&); GoHomeAndSleepTilRested& operator=(const GoHomeAndSleepTilRested&); public:

//this is a singleton static GoHomeAndSleepTilRested* Instance();

virtual void Enter(Miner* miner);

virtual void Execute(Miner* miner);

virtual void Exit(Miner* miner);

virtual bool OnMessage(Miner* agent, const Telegram& msg); };

//------------------------------------------------------------------------ // // miner changes location to the saloon and keeps buying Whiskey until // his thirst is quenched. When satisfied he returns to the goldmine // and resumes his quest for nuggets. //------------------------------------------------------------------------ class QuenchThirst : public State { private: QuenchThirst(){}

//copy ctor and assignment should be private QuenchThirst(const QuenchThirst&); QuenchThirst& operator=(const QuenchThirst&); public:

//this is a singleton static QuenchThirst* Instance();

virtual void Enter(Miner* miner);

virtual void Execute(Miner* miner);

virtual void Exit(Miner* miner);

virtual bool OnMessage(Miner* agent, const Telegram& msg); };

//------------------------------------------------------------------------ // // this is implemented as a state blip. The miner eats the stew, gives // Elsa some compliments and then returns to his previous state //------------------------------------------------------------------------ class EatStew : public State { private: EatStew(){}

//copy ctor and assignment should be private EatStew(const EatStew&); EatStew& operator=(const EatStew&); public:

//this is a singleton static EatStew* Instance();

virtual void Enter(Miner* miner);

virtual void Execute(Miner* miner);

virtual void Exit(Miner* miner);

virtual bool OnMessage(Miner* agent, const Telegram& msg); };

#endif

*************************** MinersWife.h

*************************** #ifndef MINERSWIFE_H #define MINERSWIFE_H //------------------------------------------------------------------------ // // Name: MinersWife.h // // Desc: class to implement Miner Bob's wife. // // Author: Mat Buckland 2003 (fup@ai-junkie.com) // //------------------------------------------------------------------------

#include

#include "fsm/State.h" #include "BaseGameEntity.h" #include "Locations.h" #include "MinersWifeOwnedStates.h" #include "misc/ConsoleUtils.h" #include "Miner.h" #include "fsm/StateMachine.h" #include "misc/Utils.h"

class MinersWife : public BaseGameEntity { private:

//an instance of the state machine class StateMachine* m_pStateMachine;

location_type m_Location;

//is she presently cooking? bool m_bCooking;

public:

MinersWife(int id):m_Location(shack), m_bCooking(false), BaseGameEntity(id) { //set up the state machine m_pStateMachine = new StateMachine(this);

m_pStateMachine->SetCurrentState(DoHouseWork::Instance());

m_pStateMachine->SetGlobalState(WifesGlobalState::Instance()); }

~MinersWife(){delete m_pStateMachine;}

//this must be implemented void Update();

//so must this virtual bool HandleMessage(const Telegram& msg);

StateMachine* GetFSM()const{return m_pStateMachine;}

//----------------------------------------------------accessors location_type Location()const{return m_Location;} void ChangeLocation(location_type loc){m_Location=loc;}

bool Cooking()const{return m_bCooking;} void SetCooking(bool val){m_bCooking = val;} };

#endif

***************************

MinersWifeOwnedStates.h

*************************** #ifndef MINERSWIFE_OWNED_STATES_H #define MINERSWIFE_OWNED_STATES_H //------------------------------------------------------------------------ // // Name: MinersWifeOwnedStates.h // // Desc: All the states that can be assigned to the MinersWife class // // Author: Mat Buckland 2002 (fup@ai-junkie.com) // //------------------------------------------------------------------------ #include "fsm/State.h"

class MinersWife;

//------------------------------------------------------------------------ //

//------------------------------------------------------------------------ class WifesGlobalState : public State { private: WifesGlobalState(){}

//copy ctor and assignment should be private WifesGlobalState(const WifesGlobalState&); WifesGlobalState& operator=(const WifesGlobalState&); public:

//this is a singleton static WifesGlobalState* Instance(); virtual void Enter(MinersWife* wife){}

virtual void Execute(MinersWife* wife);

virtual void Exit(MinersWife* wife){}

virtual bool OnMessage(MinersWife* wife, const Telegram& msg); };

//------------------------------------------------------------------------ //

//------------------------------------------------------------------------ class DoHouseWork : public State { private:

DoHouseWork(){} //copy ctor and assignment should be private DoHouseWork(const DoHouseWork&); DoHouseWork& operator=(const DoHouseWork&);

public:

//this is a singleton static DoHouseWork* Instance(); virtual void Enter(MinersWife* wife);

virtual void Execute(MinersWife* wife);

virtual void Exit(MinersWife* wife); virtual bool OnMessage(MinersWife* wife, const Telegram& msg);

};

//------------------------------------------------------------------------ //

//------------------------------------------------------------------------ class VisitBathroom : public State { private: VisitBathroom(){}

//copy ctor and assignment should be private VisitBathroom(const VisitBathroom&); VisitBathroom& operator=(const VisitBathroom&); public:

//this is a singleton static VisitBathroom* Instance(); virtual void Enter(MinersWife* wife);

virtual void Execute(MinersWife* wife);

virtual void Exit(MinersWife* wife);

virtual bool OnMessage(MinersWife* wife, const Telegram& msg);

};

//------------------------------------------------------------------------ //

//------------------------------------------------------------------------ class CookStew : public State { private: CookStew(){}

//copy ctor and assignment should be private CookStew(const CookStew&); CookStew& operator=(const CookStew&); public:

//this is a singleton static CookStew* Instance(); virtual void Enter(MinersWife* wife);

virtual void Execute(MinersWife* wife);

virtual void Exit(MinersWife* wife);

virtual bool OnMessage(MinersWife* wife, const Telegram& msg); };

#endif

*************************** BaseGameEntity.cpp

*************************** #include "BaseGameEntity.h" #include

int BaseGameEntity::m_iNextValidID = 0;

//----------------------------- SetID ----------------------------------------- // // this must be called within each constructor to make sure the ID is set // correctly. It verifies that the value passed to the method is greater // or equal to the next valid ID, before setting the ID and incrementing // the next valid ID //----------------------------------------------------------------------------- void BaseGameEntity::SetID(int val) { //make sure the val is equal to or greater than the next available ID assert ( (val >= m_iNextValidID) && ": invalid ID");

m_ID = val; m_iNextValidID = m_ID + 1; }

*************************** EntityManager.cpp

*************************** #include "EntityManager.h" #include "BaseGameEntity.h"

//--------------------------- Instance ---------------------------------------- // // this class is a singleton //----------------------------------------------------------------------------- EntityManager* EntityManager::Instance() { static EntityManager instance;

return &instance; }

//------------------------- GetEntityFromID ----------------------------------- //----------------------------------------------------------------------------- BaseGameEntity* EntityManager::GetEntityFromID(int id)const { //find the entity EntityMap::const_iterator ent = m_EntityMap.find(id);

//assert that the entity is a member of the map assert ( (ent != m_EntityMap.end()) && ": invalid ID");

return ent->second; }

//--------------------------- RemoveEntity ------------------------------------ //----------------------------------------------------------------------------- void EntityManager::RemoveEntity(BaseGameEntity* pEntity) { m_EntityMap.erase(m_EntityMap.find(pEntity->ID())); }

//---------------------------- RegisterEntity --------------------------------- //----------------------------------------------------------------------------- void EntityManager::RegisterEntity(BaseGameEntity* NewEntity) { m_EntityMap.insert(std::make_pair(NewEntity->ID(), NewEntity)); }

*************************** main.cpp

*************************** #include #include

#include "Locations.h" #include "Miner.h" #include "MinersWife.h" #include "EntityManager.h" #include "MessageDispatcher.h" #include "misc/ConsoleUtils.h" #include "EntityNames.h"

std::ofstream os;

int main() { //define this to send output to a text file (see locations.h) #ifdef TEXTOUTPUT os.open("output.txt"); #endif

//seed random number generator srand((unsigned) time(NULL));

//create a miner Miner* Bob = new Miner(ent_Miner_Bob);

//create his wife MinersWife* Elsa = new MinersWife(ent_Elsa);

//register them with the entity manager EntityMgr->RegisterEntity(Bob); EntityMgr->RegisterEntity(Elsa);

//run Bob and Elsa through a few Update calls for (int i=0; i<30; ++i) { Bob->Update(); Elsa->Update();

//dispatch any delayed messages Dispatch->DispatchDelayedMessages();

Sleep(800); }

//tidy up delete Bob; delete Elsa;

//wait for a keypress before exiting PressAnyKeyToContinue();

return 0; }

***************************

MessageDispatcher.cpp

*************************** #include "MessageDispatcher.h" #include "BaseGameEntity.h" #include "Time/CrudeTimer.h" #include "EntityManager.h" #include "Locations.h" #include "MessageTypes.h" #include "EntityNames.h"

#include using std::cout;

using std::set;

#ifdef TEXTOUTPUT #include extern std::ofstream os; #define cout os #endif

//------------------------------ Instance -------------------------------------

MessageDispatcher* MessageDispatcher::Instance() { static MessageDispatcher instance;

return &instance; }

//----------------------------- Dispatch --------------------------------- // // see description in header //------------------------------------------------------------------------ void MessageDispatcher::Discharge(BaseGameEntity* pReceiver, const Telegram& telegram) { if (!pReceiver->HandleMessage(telegram)) { //telegram could not be handled cout << "Message not handled"; } }

//---------------------------- DispatchMessage --------------------------- // // given a message, a receiver, a sender and any time delay , this function // routes the message to the correct agent (if no delay) or stores // in the message queue to be dispatched at the correct time //------------------------------------------------------------------------ void MessageDispatcher::DispatchMessage(double delay, int sender, int receiver, int msg, void* ExtraInfo) { SetTextColor(BACKGROUND_RED|FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE);

//get pointers to the sender and receiver BaseGameEntity* pSender = EntityMgr->GetEntityFromID(sender); BaseGameEntity* pReceiver = EntityMgr->GetEntityFromID(receiver);

//make sure the receiver is valid if (pReceiver == NULL) { cout << " Warning! No Receiver with ID of " << receiver << " found";

return; } //create the telegram Telegram telegram(0, sender, receiver, msg, ExtraInfo); //if there is no delay, route telegram immediately if (delay <= 0.0f) { cout << " Instant telegram dispatched at time: " << Clock->GetCurrentTime() << " by " << GetNameOfEntity(pSender->ID()) << " for " << GetNameOfEntity(pReceiver->ID()) << ". Msg is "<< MsgToStr(msg);

//send the telegram to the recipient Discharge(pReceiver, telegram); }

//else calculate the time when the telegram should be dispatched else { double CurrentTime = Clock->GetCurrentTime();

telegram.DispatchTime = CurrentTime + delay;

//and put it in the queue PriorityQ.insert(telegram);

cout << " Delayed telegram from " << GetNameOfEntity(pSender->ID()) << " recorded at time " << Clock->GetCurrentTime() << " for " << GetNameOfEntity(pReceiver->ID()) << ". Msg is "<< MsgToStr(msg); } }

//---------------------- DispatchDelayedMessages ------------------------- // // This function dispatches any telegrams with a timestamp that has // expired. Any dispatched telegrams are removed from the queue //------------------------------------------------------------------------ void MessageDispatcher::DispatchDelayedMessages() { SetTextColor(BACKGROUND_RED|FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE); //get current time double CurrentTime = Clock->GetCurrentTime();

//now peek at the queue to see if any telegrams need dispatching. //remove all telegrams from the front of the queue that have gone //past their sell by date while( !PriorityQ.empty() && (PriorityQ.begin()->DispatchTime < CurrentTime) && (PriorityQ.begin()->DispatchTime > 0) ) { //read the telegram from the front of the queue const Telegram& telegram = *PriorityQ.begin();

//find the recipient BaseGameEntity* pReceiver = EntityMgr->GetEntityFromID(telegram.Receiver);

cout << " Queued telegram ready for dispatch: Sent to " << GetNameOfEntity(pReceiver->ID()) << ". Msg is " << MsgToStr(telegram.Msg);

//send the telegram to the recipient Discharge(pReceiver, telegram);

//remove it from the queue PriorityQ.erase(PriorityQ.begin()); } }

***************************

Miner.cpp

*************************** #include "Miner.h"

bool Miner::HandleMessage(const Telegram& msg) { return m_pStateMachine->HandleMessage(msg); }

void Miner::Update() { SetTextColor(FOREGROUND_RED| FOREGROUND_INTENSITY);

m_iThirst += 1; m_pStateMachine->Update(); }

void Miner::AddToGoldCarried(const int val) { m_iGoldCarried += val;

if (m_iGoldCarried < 0) m_iGoldCarried = 0; }

void Miner::AddToWealth(const int val) { m_iMoneyInBank += val;

if (m_iMoneyInBank < 0) m_iMoneyInBank = 0; }

bool Miner::Thirsty()const { if (m_iThirst >= ThirstLevel){return true;}

return false; }

bool Miner::Fatigued()const { if (m_iFatigue > TirednessThreshold) { return true; }

return false; }

*************************** MinerOwnedStates.cpp

*************************** #include "MinerOwnedStates.h" #include "fsm/State.h" #include "Miner.h" #include "Locations.h" #include "messaging/Telegram.h" #include "MessageDispatcher.h" #include "MessageTypes.h" #include "Time/CrudeTimer.h" #include "EntityNames.h"

#include using std::cout;

#ifdef TEXTOUTPUT #include extern std::ofstream os; #define cout os #endif

//------------------------------------------------------------------------methods for EnterMineAndDigForNugget EnterMineAndDigForNugget* EnterMineAndDigForNugget::Instance() { static EnterMineAndDigForNugget instance;

return &instance; }

void EnterMineAndDigForNugget::Enter(Miner* pMiner) { //if the miner is not already located at the goldmine, he must //change location to the gold mine if (pMiner->Location() != goldmine) { cout << " " << GetNameOfEntity(pMiner->ID()) << ": " << "Walkin' to the goldmine";

pMiner->ChangeLocation(goldmine); } }

void EnterMineAndDigForNugget::Execute(Miner* pMiner) { //Now the miner is at the goldmine he digs for gold until he //is carrying in excess of MaxNuggets. If he gets thirsty during //his digging he packs up work for a while and changes state to //gp to the saloon for a whiskey. pMiner->AddToGoldCarried(1);

pMiner->IncreaseFatigue();

cout << " " << GetNameOfEntity(pMiner->ID()) << ": " << "Pickin' up a nugget";

//if enough gold mined, go and put it in the bank if (pMiner->PocketsFull()) { pMiner->GetFSM()->ChangeState(VisitBankAndDepositGold::Instance()); }

if (pMiner->Thirsty()) { pMiner->GetFSM()->ChangeState(QuenchThirst::Instance()); } }

void EnterMineAndDigForNugget::Exit(Miner* pMiner) { cout << " " << GetNameOfEntity(pMiner->ID()) << ": " << "Ah'm leavin' the goldmine with mah pockets full o' sweet gold"; }

bool EnterMineAndDigForNugget::OnMessage(Miner* pMiner, const Telegram& msg) { //send msg to global message handler return false; }

//------------------------------------------------------------------------methods for VisitBankAndDepositGold

VisitBankAndDepositGold* VisitBankAndDepositGold::Instance() { static VisitBankAndDepositGold instance;

return &instance; }

void VisitBankAndDepositGold::Enter(Miner* pMiner) { //on entry the miner makes sure he is located at the bank if (pMiner->Location() != bank) { cout << " " << GetNameOfEntity(pMiner->ID()) << ": " << "Goin' to the bank. Yes siree";

pMiner->ChangeLocation(bank); } }

void VisitBankAndDepositGold::Execute(Miner* pMiner) { //deposit the gold pMiner->AddToWealth(pMiner->GoldCarried()); pMiner->SetGoldCarried(0);

cout << " " << GetNameOfEntity(pMiner->ID()) << ": " << "Depositing gold. Total savings now: "<< pMiner->Wealth();

//wealthy enough to have a well earned rest? if (pMiner->Wealth() >= ComfortLevel) { cout << " " << GetNameOfEntity(pMiner->ID()) << ": " << "WooHoo! Rich enough for now. Back home to mah li'lle lady"; pMiner->GetFSM()->ChangeState(GoHomeAndSleepTilRested::Instance()); }

//otherwise get more gold else { pMiner->GetFSM()->ChangeState(EnterMineAndDigForNugget::Instance()); } }

void VisitBankAndDepositGold::Exit(Miner* pMiner) { cout << " " << GetNameOfEntity(pMiner->ID()) << ": " << "Leavin' the bank"; }

bool VisitBankAndDepositGold::OnMessage(Miner* pMiner, const Telegram& msg) { //send msg to global message handler return false; } //------------------------------------------------------------------------methods for GoHomeAndSleepTilRested

GoHomeAndSleepTilRested* GoHomeAndSleepTilRested::Instance() { static GoHomeAndSleepTilRested instance;

return &instance; }

void GoHomeAndSleepTilRested::Enter(Miner* pMiner) { if (pMiner->Location() != shack) { cout << " " << GetNameOfEntity(pMiner->ID()) << ": " << "Walkin' home";

pMiner->ChangeLocation(shack);

//let the wife know I'm home Dispatch->DispatchMessage(SEND_MSG_IMMEDIATELY, //time delay pMiner->ID(), //ID of sender ent_Elsa, //ID of recipient Msg_HiHoneyImHome, //the message NO_ADDITIONAL_INFO); } }

void GoHomeAndSleepTilRested::Execute(Miner* pMiner) { //if miner is not fatigued start to dig for nuggets again. if (!pMiner->Fatigued()) { cout << " " << GetNameOfEntity(pMiner->ID()) << ": " << "All mah fatigue has drained away. Time to find more gold!";

pMiner->GetFSM()->ChangeState(EnterMineAndDigForNugget::Instance()); }

else { //sleep pMiner->DecreaseFatigue();

cout << " " << GetNameOfEntity(pMiner->ID()) << ": " << "ZZZZ... "; } }

void GoHomeAndSleepTilRested::Exit(Miner* pMiner) { }

bool GoHomeAndSleepTilRested::OnMessage(Miner* pMiner, const Telegram& msg) { SetTextColor(BACKGROUND_RED|FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE);

switch(msg.Msg) { case Msg_StewReady:

cout << " Message handled by " << GetNameOfEntity(pMiner->ID()) << " at time: " << Clock->GetCurrentTime();

SetTextColor(FOREGROUND_RED|FOREGROUND_INTENSITY);

cout << " " << GetNameOfEntity(pMiner->ID()) << ": Okay Hun, ahm a comin'!";

pMiner->GetFSM()->ChangeState(EatStew::Instance()); return true;

}//end switch

return false; //send message to global message handler }

//------------------------------------------------------------------------QuenchThirst

QuenchThirst* QuenchThirst::Instance() { static QuenchThirst instance;

return &instance; }

void QuenchThirst::Enter(Miner* pMiner) { if (pMiner->Location() != saloon) { pMiner->ChangeLocation(saloon);

cout << " " << GetNameOfEntity(pMiner->ID()) << ": " << "Boy, ah sure is thusty! Walking to the saloon"; } }

void QuenchThirst::Execute(Miner* pMiner) { pMiner->BuyAndDrinkAWhiskey();

cout << " " << GetNameOfEntity(pMiner->ID()) << ": " << "That's mighty fine sippin' liquer";

pMiner->GetFSM()->ChangeState(EnterMineAndDigForNugget::Instance()); }

void QuenchThirst::Exit(Miner* pMiner) { cout << " " << GetNameOfEntity(pMiner->ID()) << ": " << "Leaving the saloon, feelin' good"; }

bool QuenchThirst::OnMessage(Miner* pMiner, const Telegram& msg) { //send msg to global message handler return false; }

//------------------------------------------------------------------------EatStew

EatStew* EatStew::Instance() { static EatStew instance;

return &instance; }

void EatStew::Enter(Miner* pMiner) { cout << " " << GetNameOfEntity(pMiner->ID()) << ": " << "Smells Reaaal goood Elsa!"; }

void EatStew::Execute(Miner* pMiner) { cout << " " << GetNameOfEntity(pMiner->ID()) << ": " << "Tastes real good too!";

pMiner->GetFSM()->RevertToPreviousState(); }

void EatStew::Exit(Miner* pMiner) { cout << " " << GetNameOfEntity(pMiner->ID()) << ": " << "Thankya li'lle lady. Ah better get back to whatever ah wuz doin'"; }

bool EatStew::OnMessage(Miner* pMiner, const Telegram& msg) { //send msg to global message handler return false; }

*************************** MinersWife.cpp

*************************** #include "MinersWife.h"

bool MinersWife::HandleMessage(const Telegram& msg) { return m_pStateMachine->HandleMessage(msg); }

void MinersWife::Update() { //set text color to green SetTextColor(FOREGROUND_GREEN | FOREGROUND_INTENSITY); m_pStateMachine->Update(); }

*************************** MinersWifeOwnedStates.cpp

***************************

#include "MinersWifeOwnedStates.h" #include "MinerOwnedStates.h" #include "MinersWife.h" #include "Locations.h" #include "Time/CrudeTimer.h" #include "MessageDispatcher.h" #include "MessageTypes.h" #include "EntityNames.h"

#include using std::cout;

#ifdef TEXTOUTPUT #include extern std::ofstream os; #define cout os #endif

//-----------------------------------------------------------------------Global state

WifesGlobalState* WifesGlobalState::Instance() { static WifesGlobalState instance;

return &instance; }

void WifesGlobalState::Execute(MinersWife* wife) { //1 in 10 chance of needing the bathroom (provided she is not already //in the bathroom) if ( (RandFloat() < 0.1) && !wife->GetFSM()->isInState(*VisitBathroom::Instance()) ) { wife->GetFSM()->ChangeState(VisitBathroom::Instance()); } }

bool WifesGlobalState::OnMessage(MinersWife* wife, const Telegram& msg) { SetTextColor(BACKGROUND_RED|FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE);

switch(msg.Msg) { case Msg_HiHoneyImHome: { cout << " Message handled by " << GetNameOfEntity(wife->ID()) << " at time: " << Clock->GetCurrentTime();

SetTextColor(FOREGROUND_GREEN|FOREGROUND_INTENSITY);

cout << " " << GetNameOfEntity(wife->ID()) << ": Hi honey. Let me make you some of mah fine country stew";

wife->GetFSM()->ChangeState(CookStew::Instance()); }

return true;

}//end switch

return false; }

//-------------------------------------------------------------------------DoHouseWork

DoHouseWork* DoHouseWork::Instance() { static DoHouseWork instance;

return &instance; }

void DoHouseWork::Enter(MinersWife* wife) { cout << " " << GetNameOfEntity(wife->ID()) << ": Time to do some more housework!"; }

void DoHouseWork::Execute(MinersWife* wife) { switch(RandInt(0,2)) { case 0:

cout << " " << GetNameOfEntity(wife->ID()) << ": Moppin' the floor";

break;

case 1:

cout << " " << GetNameOfEntity(wife->ID()) << ": Washin' the dishes";

break;

case 2:

cout << " " << GetNameOfEntity(wife->ID()) << ": Makin' the bed";

break; } }

void DoHouseWork::Exit(MinersWife* wife) { }

bool DoHouseWork::OnMessage(MinersWife* wife, const Telegram& msg) { return false; }

//------------------------------------------------------------------------VisitBathroom

VisitBathroom* VisitBathroom::Instance() { static VisitBathroom instance;

return &instance; }

void VisitBathroom::Enter(MinersWife* wife) { cout << " " << GetNameOfEntity(wife->ID()) << ": Walkin' to the can. Need to powda mah pretty li'lle nose"; }

void VisitBathroom::Execute(MinersWife* wife) { cout << " " << GetNameOfEntity(wife->ID()) << ": Ahhhhhh! Sweet relief!";

wife->GetFSM()->RevertToPreviousState(); }

void VisitBathroom::Exit(MinersWife* wife) { cout << " " << GetNameOfEntity(wife->ID()) << ": Leavin' the Jon"; }

bool VisitBathroom::OnMessage(MinersWife* wife, const Telegram& msg) { return false; }

//------------------------------------------------------------------------CookStew

CookStew* CookStew::Instance() { static CookStew instance;

return &instance; }

void CookStew::Enter(MinersWife* wife) { //if not already cooking put the stew in the oven if (!wife->Cooking()) { cout << " " << GetNameOfEntity(wife->ID()) << ": Putting the stew in the oven"; //send a delayed message myself so that I know when to take the stew //out of the oven Dispatch->DispatchMessage(1.5, //time delay wife->ID(), //sender ID wife->ID(), //receiver ID Msg_StewReady, //msg NO_ADDITIONAL_INFO);

wife->SetCooking(true); } }

void CookStew::Execute(MinersWife* wife) { cout << " " << GetNameOfEntity(wife->ID()) << ": Fussin' over food"; }

void CookStew::Exit(MinersWife* wife) { SetTextColor(FOREGROUND_GREEN|FOREGROUND_INTENSITY); cout << " " << GetNameOfEntity(wife->ID()) << ": Puttin' the stew on the table"; }

bool CookStew::OnMessage(MinersWife* wife, const Telegram& msg) { SetTextColor(BACKGROUND_RED|FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE);

switch(msg.Msg) { case Msg_StewReady: { cout << " Message received by " << GetNameOfEntity(wife->ID()) << " at time: " << Clock->GetCurrentTime();

SetTextColor(FOREGROUND_GREEN|FOREGROUND_INTENSITY); cout << " " << GetNameOfEntity(wife->ID()) << ": StewReady! Lets eat";

//let hubby know the stew is ready Dispatch->DispatchMessage(SEND_MSG_IMMEDIATELY, wife->ID(), ent_Miner_Bob, Msg_StewReady, NO_ADDITIONAL_INFO);

wife->SetCooking(false);

wife->GetFSM()->ChangeState(DoHouseWork::Instance()); }

return true;

}//end switch

return false; }

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

Machine Learning And Knowledge Discovery In Databases European Conference Ecml Pkdd 2016 Riva Del Garda Italy September 19 23 2016 Proceedings Part 3 Lnai 9853

Authors: Bettina Berendt ,Bjorn Bringmann ,Elisa Fromont ,Gemma Garriga ,Pauli Miettinen ,Nikolaj Tatti ,Volker Tresp

1st Edition

3319461303, 978-3319461304

More Books

Students also viewed these Databases questions

Question

Classify compounds I-IV by their acid/base character

Answered: 1 week ago