SlideShare a Scribd company logo
1 of 74
Download to read offline
게임제작론고급1및실습
     DD3440                         Mar. 2, 2010




                       Chapter 2

             상태구동형 에이전트의 디자인



                        박창훈
                      호서대학교 게임공학과




2010년	 3월	 23일	 화요일
2. 상태구동형 에이전트의 디자인
     DD3440                 Mar. 2, 2010




   A. 유한상태 기계란 정확하게 무엇일까?




2010년	 3월	 23일	 화요일
3

     A. 유한상태 기계란 정확하게 무엇일까?
     2. 상태구동형 에이전트의 디자인       Mar. 2, 2010




2010년	 3월	 23일	 화요일
2. 상태구동형 에이전트의 디자인
     DD3440               Mar. 2, 2010




   B. 유한상태기계 구현하기


   B1. 상태 전환표
   B2. 내장된 규칙들




2010년	 3월	 23일	 화요일
5

     2. 상태구동형 에이전트의 디자인
                                                            Mar. 2, 2010




          enum StateType
          {
             RunAway, Patrol, Attack
          };
          void Agent::UpdateState(StateType CurrentState)
          {
             switch (CurrentState)
             {
             case state_RunAway:
                EvadeEnemy();
                if (Safe())
                {
                    ChangeState( state_Patrol);
                }
                break;




2010년	 3월	 23일	 화요일
6

     2. 상태구동형 에이전트의 디자인
                                                           Mar. 2, 2010




               case state_Patrol:
                   FollowPatrolPath();
                   if (Threatened())
                   {
                        if (StrongerThanEnemy())
                        {
                            ChangeState( state_Attack);
                        }
                        else
                        {
                            ChangeState( state_RunAway);
                        }
                 }
                break;




2010년	 3월	 23일	 화요일
7

     2. 상태구동형 에이전트의 디자인
                                                      Mar. 2, 2010




               case state_Attack:
                   if (WeakerThanEnemy())
                   {
                       ChangeState( state_RunAway);
                   }
                   else
                   {
                       BashEnemyOverHead();
                   }
                   break;
              }//end switch
          }




2010년	 3월	 23일	 화요일
8

     B1. 상태 전환표
     2. 상태구동형 에이전트의 디자인   Mar. 2, 2010




2010년	 3월	 23일	 화요일
2. 상태구동형 에이전트의 디자인
     DD3440               Mar. 2, 2010




   B. 유한상태기계 구현하기


   B1. 상태 전환표
   B2. 내장된 규칙들




2010년	 3월	 23일	 화요일
10

     B2. 내장된 규칙들
     2. 상태구동형 에이전트의 디자인                             Mar. 2, 2010




          class State
          {
          public:

            virtual void Execute(Troll* troll)=0;

          };




2010년	 3월	 23일	 화요일
11

     B2. 내장된 규칙들
     2. 상태구동형 에이전트의 디자인                                    Mar. 2, 2010




           class Troll
          {
              /* ATTRIBUTES OMITTED */
              State* m_pCurrentState;
          public:
              /* INTERFACE TO ATTRIBUTES OMITTED */
              void Update()
              {
                  m_pCurrentState->Execute(this;)
              }

                void ChangeState(const State* pNewState)
                {
                   delete m_pCurrentState;
                   m_pCurrentState = pNewState;
                }
           };



2010년	 3월	 23일	 화요일
12

     B2. 내장된 규칙들
     2. 상태구동형 에이전트의 디자인                                           Mar. 2, 2010




           //------------------------------State RunAway
           class State_Runway : public State
           {
           public:
                void Execute(Troll* troll)
                {
                    if(troll->isSafe())
                    {
                         troll->ChangeState(new State_Sleep());
                    }
                    else
                    {
                         troll->MoveAwayFromEnemy();
                    }
                }
           };



2010년	 3월	 23일	 화요일
13

     B2. 내장된 규칙들
     2. 상태구동형 에이전트의 디자인                                            Mar. 2, 2010




           //-----------------------------State_Sleep
           class State_Slepp : public State
           {
                void Execute(Troll* troll)
                {
                    if(troll->isThreatened())
                    {
                         troll->ChangeState(new State_RunAway())
                    }
                    else
                    {
                         troll->Snore();
                    }
                }
           };



2010년	 3월	 23일	 화요일
2. 상태구동형 에이전트의 디자인
     DD3440                     Mar. 2, 2010




   C. West World 프로젝트


   C1. BaseGameEntity 클래스
   C2. Minor 클래스
   C3. Minor 상태들
   C4. 상태 디자인 패턴에 대해 자세히 알아보기




2010년	 3월	 23일	 화요일
15

     C1. BaseGameEntity 클래스
     2. 상태구동형 에이전트의 디자인                          Mar. 2, 2010




            class BaseGameEntity
           {
           private:
             int       m_ID;
             static int m_iNextValidID;
             void SetID(int val);
           public:

             BaseGameEntity(int id)
             {
               SetID(id);
             }
             virtual ~BaseGameEntity(){}
             virtual void Update()=0;
             int       ID()const{return m_ID;}
           };



2010년	 3월	 23일	 화요일
2. 상태구동형 에이전트의 디자인
     DD3440                     Mar. 2, 2010




   C. West World 프로젝트


   C1. BaseGameEntity 클래스
   C2. Minor 클래스
   C3. Minor 상태들
   C4. 상태 디자인 패턴에 대해 자세히 알아보기




2010년	 3월	 23일	 화요일
17

     C2. Minor 클래스
     2. 상태구동형 에이전트의 디자인                              Mar. 2, 2010




           class Miner : public BaseGameEntity
           {
           private:
             State*          m_pCurrentState;
             location_type      m_Location;
             int           m_iGoldCarried;
             int           m_iMoneyInBank;
             int           m_iThirst;
             int           m_iFatigue;
           public:

               Miner(int id);
               void Update();
               void ChangeState(State* new_state);
           }



2010년	 3월	 23일	 화요일
18

     C2. Minor 클래스
     2. 상태구동형 에이전트의 디자인                              Mar. 2, 2010




          void Miner::Update()
          {
             m_iThirst += 1;

               if (m_pCurrentState)
               {
                   m_pCurrentState->Execute(this);
                }
          }




2010년	 3월	 23일	 화요일
2. 상태구동형 에이전트의 디자인
     DD3440                     Mar. 2, 2010




   C. West World 프로젝트


   C1. BaseGameEntity 클래스
   C2. Minor 클래스
   C3. Minor 상태들
   C4. 상태 디자인 패턴에 대해 자세히 알아보기




2010년	 3월	 23일	 화요일
20

     C3. Minor 상태들
     2. 상태구동형 에이전트의 디자인   Mar. 2, 2010




2010년	 3월	 23일	 화요일
2. 상태구동형 에이전트의 디자인
     DD3440                     Mar. 2, 2010




   C. West World 프로젝트


   C1. BaseGameEntity 클래스
   C2. Minor 클래스
   C3. Minor 상태들
   C4. 상태 디자인 패턴에 대해 자세히 알아보기




2010년	 3월	 23일	 화요일
22

     C4. 상태 디자인 패턴에 대해 자세히 알아보기
     2. 상태구동형 에이전트의 디자인                                                      Mar. 2, 2010




           class State
           {
           public:
             virtual ~State(){}

             //this will execute when the state is entered
             virtual void Enter(Miner*)=0;

             //this is the state's normal update function
             virtual void Execute(Miner*)=0;

             //this will execute when the state is exited. (My word, isn't
             //life full of surprises... ;o))
             virtual void Exit(Miner*)=0;
           };



2010년	 3월	 23일	 화요일
23

     C4. 상태 디자인 패턴에 대해 자세히 알아보기
     2. 상태구동형 에이전트의 디자인                                                     Mar. 2, 2010




           void Miner::ChangeState(State* pNewState) {
              //make sure both states are both valid before attempting to
              //call their methods
              assert(m_pCurrentState && pNewState);

                //call the exit method of the existing state
                m_pCurrentState->Exit(this);

                //change state to the new state
                m_pCurrentState = pNewState;

                //call the entry method of the new state
                m_pCurrentState->Enter(this);
           }




2010년	 3월	 23일	 화요일
24

     C4. 상태 디자인 패턴에 대해 자세히 알아보기
     2. 상태구동형 에이전트의 디자인           Mar. 2, 2010




2010년	 3월	 23일	 화요일
25

     C4. 상태 디자인 패턴에 대해 자세히 알아보기
     2. 상태구동형 에이전트의 디자인                                            Mar. 2, 2010




          /* ------------------ MyClass.h ------------------- */
          #ifndef MY_SINGLETON
          #define MY_SINGLETON

          class MyClass
          {
          private:
              int m_iNum;
              MyClass(){}
              MyClass(const MyClass &);
              MyClass& operator=(const MyClass &);

          public:
             ~MyClass();
             int GetVal()const{return m_iNum;}
             static MyClass* Instance();



2010년	 3월	 23일	 화요일
26

     C4. 상태 디자인 패턴에 대해 자세히 알아보기
     2. 상태구동형 에이전트의 디자인                                              Mar. 2, 2010




          /* ------------------ MyClass.h ------------------- */
          public:
              ~MyClass();

               //methods
               int GetVal()const{return m_iNum;}
               static MyClass* Instance();
          };
          #endif

          /* ------------------- MyClass.cpp ------------------ */
          MyClass* MyClass::Instance()
          {
              static MyClass instance;

               return &instance;
          }



2010년	 3월	 23일	 화요일
27

     C4. 상태 디자인 패턴에 대해 자세히 알아보기
     2. 상태구동형 에이전트의 디자인                               Mar. 2, 2010




           int num = MyClass::Instance()->GetVal();

           #define MyCls MyClass::Instance()

           int num = MyCls->GetVal();




2010년	 3월	 23일	 화요일
28

     C4. 상태 디자인 패턴에 대해 자세히 알아보기
     2. 상태구동형 에이전트의 디자인                                    Mar. 2, 2010



       ๏ EnterMineAndDigForNugget

           class EnterMineAndDigForNugget : public State
           {
           private:

             EnterMineAndDigForNugget(){}
             /* copy ctor and assignment op omitted */

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

             virtual void Enter(Miner* miner);
             virtual void Execute(Miner* miner);
             virtual void Exit(Miner* miner);
           };



2010년	 3월	 23일	 화요일
29

     C4. 상태 디자인 패턴에 대해 자세히 알아보기
     2. 상태구동형 에이전트의 디자인                                                       Mar. 2, 2010



       ๏ EnterMineAndDigForNugget


           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)
             {
               SetTextColor(FOREGROUND_RED| FOREGROUND_INTENSITY);
               cout << "n" << GetNameOfEntity(pMiner->ID()) << ": "
                    << "Walkin' to the goldmine";

                   pMiner->ChangeLocation(goldmine);
               }
           }




2010년	 3월	 23일	 화요일
30

     C4. 상태 디자인 패턴에 대해 자세히 알아보기
     2. 상태구동형 에이전트의 디자인                                                      Mar. 2, 2010



       ๏ EnterMineAndDigForNugget
           void EnterMineAndDigForNugget::Execute(Miner* pMiner)
           {
             pMiner->AddToGoldCarried(1);
             pMiner->IncreaseFatigue();

               SetTextColor(FOREGROUND_RED| FOREGROUND_INTENSITY);
               cout << "n" << GetNameOfEntity(pMiner->ID()) << ": "
                     << "Pickin' up a nugget";

               if (pMiner->PocketsFull()) {
                 pMiner->ChangeState(VisitBankAndDepositGold::Instance());
               }

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


2010년	 3월	 23일	 화요일
31

     C4. 상태 디자인 패턴에 대해 자세히 알아보기
     2. 상태구동형 에이전트의 디자인                                                               Mar. 2, 2010



       ๏ EnterMineAndDigForNugget



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




2010년	 3월	 23일	 화요일
2. 상태구동형 에이전트의 디자인
     DD3440                      Mar. 2, 2010




   D. 상태의 기본 클래스 재사용할 수 있게 만들기




2010년	 3월	 23일	 화요일
33

     D. 상태의 기본 클래스 재사용할 수 있게 만들기
     2. 상태구동형 에이전트의 디자인                                 Mar. 2, 2010




           template <class entity_type>
           class State
           {
           public:

                virtual void Enter(entity_type*)=0;

                virtual void Execute(entity_type*)=0;

                virtual void Exit(entity_type*)=0;

                virtual ~State(){}

           };




2010년	 3월	 23일	 화요일
34

     D. 상태의 기본 클래스 재사용할 수 있게 만들기
     2. 상태구동형 에이전트의 디자인                                           Mar. 2, 2010




           class EnterMineAndDigForNugget : public State<Miner>
           {

           public:

                /* OMITTED */
           };




2010년	 3월	 23일	 화요일
2. 상태구동형 에이전트의 디자인
     DD3440               Mar. 2, 2010




   F. 전역 상태 및 상태 블립




2010년	 3월	 23일	 화요일
36

     F. 전역 상태 및 상태 블립
     2. 상태구동형 에이전트의 디자인                                       Mar. 2, 2010




            State<Miner>* m_pGlobalState;

           class Miner : public BaseGameEntity
           {
           private:

                 State<Miner>* m_pCurrentState;
                 State<Miner>* m_pPreviousState;
                 State<Miner>* m_pGlobalState;
                 ...

           public:

                 void ChangeState(State<Miner>* pNewState);
                 void RevertToPreviousState();
                 ...
            };


2010년	 3월	 23일	 화요일
2. 상태구동형 에이전트의 디자인
     DD3440               Mar. 2, 2010




   G. 상태기계 클래스 생성하기




2010년	 3월	 23일	 화요일
38

     G. 상태기계 클래스 생성하기
     2. 상태구동형 에이전트의 디자인                                         Mar. 2, 2010




           template <class entity_type>
           class StateMachine
           {
           private:
             entity_type*     m_pOwner;

             State<entity_type>* m_pCurrentState;
             State<entity_type>* m_pPreviousState;
             State<entity_type>* m_pGlobalState;

           public:
            StateMachine(entity_type* owner):m_pOwner(owner),
                                m_pCurrentState(NULL),
                                m_pPreviousState(NULL),
                                m_pGlobalState(NULL)
            {}



2010년	 3월	 23일	 화요일
39

     G. 상태기계 클래스 생성하기
     2. 상태구동형 에이전트의 디자인                                                            Mar. 2, 2010




             virtual ~StateMachine(){}

             void SetCurrentState(State<entity_type>* s){m_pCurrentState = s;}
             void SetGlobalState(State<entity_type>* s) {m_pGlobalState = s;}
             void SetPreviousState(State<entity_type>* s){m_pPreviousState = s;}

            void Update()const
             {
               if(m_pGlobalState) m_pGlobalState->Execute(m_pOwner);
               if (m_pCurrentState) m_pCurrentState->Execute(m_pOwner);
             }




2010년	 3월	 23일	 화요일
40

     G. 상태기계 클래스 생성하기
     2. 상태구동형 에이전트의 디자인                                                         Mar. 2, 2010




             void ChangeState(State<entity_type>* pNewState)
             {
               assert(pNewState &&
                   "<StateMachine::ChangeState>: trying to change to NULL state");
               m_pPreviousState = m_pCurrentState;
               m_pCurrentState->Exit(m_pOwner);
               m_pCurrentState = pNewState;
               m_pCurrentState->Enter(m_pOwner);
             }

             void RevertToPreviousState()
             {
               ChangeState(m_pPreviousState);
             }




2010년	 3월	 23일	 화요일
41

     G. 상태기계 클래스 생성하기
     2. 상태구동형 에이전트의 디자인                                                            Mar. 2, 2010




             bool isInState(const State<entity_type>& st)const
             {
               return typeid(*m_pCurrentState) == typeid(st);
             }

             State<entity_type>* CurrentState() const{return m_pCurrentState;}
             State<entity_type>* GlobalState() const{return m_pGlobalState;}
             State<entity_type>* PreviousState() const{return m_pPreviousState;}
           };




2010년	 3월	 23일	 화요일
42

     G. 상태기계 클래스 생성하기
     2. 상태구동형 에이전트의 디자인                                                    Mar. 2, 2010




       class Miner : public BaseGameEntity
       {
       private:

         StateMachine<Miner>* m_pStateMachine;
         /* EXTRANEOUS DETAIL OMITTED */

       public:

         Miner(int id):m_Location(shack), m_iGoldCarried(0), m_iMoneyInBank(0),
                  m_iThirst(0), m_iFatigue(0), BaseGameEntity(id)
         {
           m_pStateMachine = new StateMachine<Miner>(this);
           m_pStateMachine->SetCurrentState(GoHomeAndSleepTilRested::Instance());
           m_pStateMachine->SetGlobalState(MinerGloalState::Instance());
         }



2010년	 3월	 23일	 화요일
43

     G. 상태기계 클래스 생성하기
     2. 상태구동형 에이전트의 디자인                                                    Mar. 2, 2010




           ~Miner(){delete m_pStateMachine;}

             void Update()
             {
                ++m_iThirst;
                m_pStateMachine->Update();
             }

             StateMachine<Miner>* GetFSM()const{return m_pStateMachine;}

             /* EXTRANEOUS DETAIL O<ITTED */
           };




2010년	 3월	 23일	 화요일
44

     G. 상태기계 클래스 생성하기
     2. 상태구동형 에이전트의 디자인   Mar. 2, 2010




2010년	 3월	 23일	 화요일
45

     G. 상태기계 클래스 생성하기
     2. 상태구동형 에이전트의 디자인   Mar. 2, 2010




2010년	 3월	 23일	 화요일
2. 상태구동형 에이전트의 디자인
     DD3440               Mar. 2, 2010




   H. Elsa 소개하기




2010년	 3월	 23일	 화요일
47

     H. Elsa 소개하기
     2. 상태구동형 에이전트의 디자인   Mar. 2, 2010




2010년	 3월	 23일	 화요일
2. 상태구동형 에이전트의 디자인
     DD3440               Mar. 2, 2010




   I. FSM 메시지 처리기능 추가하기


   I1. 전보구조
   I2. 광부 Bob과 Elsa의 통신
   I3. 메시지 급송 및 관리
   I4. 메시지 처리하기
   I5. Elsa는 저녁을 준비한다



2010년	 3월	 23일	 화요일
49

     I1. 전보구조
     2. 상태구동형 에이전트의 디자인                   Mar. 2, 2010




           struct Telegram
           {
             int      Sender;

             int      Receiver;

             int      Msg;

             double     DispatchTime;

             void*     ExtraInfo;

             /* CONSTRUCTORS OMITTED */
           };




2010년	 3월	 23일	 화요일
2. 상태구동형 에이전트의 디자인
     DD3440               Mar. 2, 2010




   I. FSM 메시지 처리기능 추가하기


   I1. 전보구조
   I2. 광부 Bob과 Elsa의 통신
   I3. 메시지 급송 및 관리
   I4. 메시지 처리하기
   I5. Elsa는 저녁을 준비한다



2010년	 3월	 23일	 화요일
51

     I2. 광부 Bob과 Elsa의 통신
     2. 상태구동형 에이전트의 디자인       Mar. 2, 2010




       enum message_type
       {
         Msg_HiHoneyImHome,
         Msg_StewReady
       };




2010년	 3월	 23일	 화요일
2. 상태구동형 에이전트의 디자인
     DD3440               Mar. 2, 2010




   I. FSM 메시지 처리기능 추가하기


   I1. 전보구조
   I2. 광부 Bob과 Elsa의 통신
   I3. 메시지 급송 및 관리
   I4. 메시지 처리하기
   I5. Elsa는 저녁을 준비한다



2010년	 3월	 23일	 화요일
53

     I3. 메시지 급송 및 관리
     2. 상태구동형 에이전트의 디자인                                          Mar. 2, 2010




           class EntityManager
           {
           private:

             typedef std::map<int, BaseGameEntity*> EntityMap;

           private:

             EntityMap m_EntityMap;

             EntityManager(){}

             EntityManager(const EntityManager&);
             EntityManager& operator=(const EntityManager&);




2010년	 3월	 23일	 화요일
54

     I3. 메시지 급송 및 관리
     2. 상태구동형 에이전트의 디자인                                                Mar. 2, 2010




           public:

             static EntityManager* Instance();

             void    RegisterEntity(BaseGameEntity* NewEntity);
             BaseGameEntity* GetEntityFromID(int id)const;
             void    RemoveEntity(BaseGameEntity* pEntity);
           };

           #define EntityMgr EntityManager::Instance()

           Miner* Bob = new Miner(ent_Miner_Bob); //enumerated ID
           EntityMgr->RegisterEntity(Bob);

           Entity* pBob = EntityMgr->GetEntityFromID(ent_Miner_Bob);




2010년	 3월	 23일	 화요일
55

     I3. 메시지 급송 및 관리
     2. 상태구동형 에이전트의 디자인                                                          Mar. 2, 2010



       ๏ MessageDispatcher 클래스
            class MessageDispatcher
           {
           private:
             std::set<Telegram> PriorityQ;
             void Discharge(BaseGameEntity* pReceiver, const Telegram& msg);
             MessageDispatcher(){}

           public:
            static MessageDispatcher* Instance();

             void DispatchMessage(double delay, int    sender, int   receiver,
                          int msg, void* ExtraInfo);

             void DispatchDelayedMessages();
           };

            #define Dispatch MessageDispatcher::Instance()


2010년	 3월	 23일	 화요일
56

     I3. 메시지 급송 및 관리
     2. 상태구동형 에이전트의 디자인                                                     Mar. 2, 2010



       ๏ MessageDispatcher 클래스
            void MessageDispatcher::DispatchMessage(double delay,
                                     int sender, int receiver,
                                     int msg, void* ExtraInfo)
           {
                Entity* pReceiver = EntityMgr->GetEntityFromID(receiver);

                  Telegram telegram(0, sender, receiver, msg, ExtraInfo);

                  if (delay <= 0.0f) {
                    Discharge(pReceiver, telegram);
                  }
                  else {
                    double CurrentTime = Clock->GetCurrentTime();
                    telegram.DispatchTime = CurrentTime + delay;
                    PriorityQ.insert(telegram);
                  }
            }


2010년	 3월	 23일	 화요일
57

     I3. 메시지 급송 및 관리
     2. 상태구동형 에이전트의 디자인                                                  Mar. 2, 2010



       ๏ MessageDispatcher 클래스
           void MessageDispatcher::DispatchDelayedMessages()
           {

               double CurrentTime = Clock->GetCurrentTime();

             while( (PriorityQ.begin()->DispatchTime < CurrentTime) &&
                  (PriorityQ.begin()->DispatchTime > 0) )
             {
               Telegram telegram = *PriorityQ.begin();
               BaseGameEntity* pReceiver = EntityMgr->GetEntityFromID
           (telegram.Receiver);
               Discharge(pReceiver, telegram);
               PriorityQ.erase(PriorityQ.begin());
             }

           }



2010년	 3월	 23일	 화요일
2. 상태구동형 에이전트의 디자인
     DD3440               Mar. 2, 2010




   I. FSM 메시지 처리기능 추가하기


   I1. 전보구조
   I2. 광부 Bob과 Elsa의 통신
   I3. 메시지 급송 및 관리
   I4. 메시지 처리하기
   I5. Elsa는 저녁을 준비한다



2010년	 3월	 23일	 화요일
59

     I4. 메시지 처리하기
     2. 상태구동형 에이전트의 디자인                                          Mar. 2, 2010




           class BaseGameEntity
           {

           private:
            int       m_ID;

             /* EXTRANEOUS DETAIL REMOVED FOR CLARITY*/

           public:
            virtual bool HandleMessage(const Telegram& msg)=0;

             /* EXTRANEOUS DETAIL REMOVED FOR CLARITY*/
           };




2010년	 3월	 23일	 화요일
60

     I4. 메시지 처리하기
     2. 상태구동형 에이전트의 디자인                                                 Mar. 2, 2010




           template <class entity_type>
           class State
           {
           public:

             virtual bool OnMessage(entity_type*, const Telegram&)=0;

             /* EXTRANEOUS DETAIL REMOVED FOR CLARITY*/
           };




2010년	 3월	 23일	 화요일
61

     I4. 메시지 처리하기
     2. 상태구동형 에이전트의 디자인                                                      Mar. 2, 2010




             bool StateMachine::HandleMessage(const Telegram& msg)const
             {
               if (m_pCurrentState && m_pCurrentState->OnMessage(m_pOwner, msg))
               {
                 return true;
               }

                 if (m_pGlobalState && m_pGlobalState->OnMessage(m_pOwner, msg))
                 {
                   return true;
                 }

                 return false;
             }




2010년	 3월	 23일	 화요일
62

     I4. 메시지 처리하기
     2. 상태구동형 에이전트의 디자인                                    Mar. 2, 2010




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




2010년	 3월	 23일	 화요일
63

     I4. 메시지 처리하기
     2. 상태구동형 에이전트의 디자인   Mar. 2, 2010




2010년	 3월	 23일	 화요일
64

     I4. 메시지 처리하기
     2. 상태구동형 에이전트의 디자인   Mar. 2, 2010




2010년	 3월	 23일	 화요일
65

     I3. 메시지 급송 및 관리
     2. 상태구동형 에이전트의 디자인                                                Mar. 2, 2010




           public:

             static EntityManager* Instance();

             void    RegisterEntity(BaseGameEntity* NewEntity);
             BaseGameEntity* GetEntityFromID(int id)const;
             void    RemoveEntity(BaseGameEntity* pEntity);
           };

           #define EntityMgr EntityManager::Instance()

           Miner* Bob = new Miner(ent_Miner_Bob); //enumerated ID
           EntityMgr->RegisterEntity(Bob);

           Entity* pBob = EntityMgr->GetEntityFromID(ent_Miner_Bob);




2010년	 3월	 23일	 화요일
66

     I3. 메시지 급송 및 관리
     2. 상태구동형 에이전트의 디자인                                                          Mar. 2, 2010



       ๏ MessageDispatcher 클래스
            class MessageDispatcher
           {
           private:
             std::set<Telegram> PriorityQ;
             void Discharge(BaseGameEntity* pReceiver, const Telegram& msg);
             MessageDispatcher(){}

           public:
            static MessageDispatcher* Instance();

             void DispatchMessage(double delay, int    sender, int   receiver,
                          int msg, void* ExtraInfo);

             void DispatchDelayedMessages();
           };

            #define Dispatch MessageDispatcher::Instance()


2010년	 3월	 23일	 화요일
67

     I3. 메시지 급송 및 관리
     2. 상태구동형 에이전트의 디자인                                                     Mar. 2, 2010



       ๏ MessageDispatcher 클래스
            void MessageDispatcher::DispatchMessage(double delay,
                                     int sender, int receiver,
                                     int msg, void* ExtraInfo)
           {
                Entity* pReceiver = EntityMgr->GetEntityFromID(receiver);

                  Telegram telegram(0, sender, receiver, msg, ExtraInfo);

                  if (delay <= 0.0f) {
                    Discharge(pReceiver, telegram);
                  }
                  else {
                    double CurrentTime = Clock->GetCurrentTime();
                    telegram.DispatchTime = CurrentTime + delay;
                    PriorityQ.insert(telegram);
                  }
            }


2010년	 3월	 23일	 화요일
68

     I3. 메시지 급송 및 관리
     2. 상태구동형 에이전트의 디자인                                                  Mar. 2, 2010



       ๏ MessageDispatcher 클래스
           void MessageDispatcher::DispatchDelayedMessages()
           {

               double CurrentTime = Clock->GetCurrentTime();

             while( (PriorityQ.begin()->DispatchTime < CurrentTime) &&
                  (PriorityQ.begin()->DispatchTime > 0) )
             {
               Telegram telegram = *PriorityQ.begin();
               BaseGameEntity* pReceiver = EntityMgr->GetEntityFromID
           (telegram.Receiver);
               Discharge(pReceiver, telegram);
               PriorityQ.erase(PriorityQ.begin());
             }

           }



2010년	 3월	 23일	 화요일
2. 상태구동형 에이전트의 디자인
     DD3440               Mar. 2, 2010




   I. FSM 메시지 처리기능 추가하기


   I1. 전보구조
   I2. 광부 Bob과 Elsa의 통신
   I3. 메시지 급송 및 관리
   I4. 메시지 처리하기
   I5. Elsa는 저녁을 준비한다



2010년	 3월	 23일	 화요일
70

     I5. Elsa는 저녁을 준비한다
     2. 상태구동형 에이전트의 디자인                                                       Mar. 2, 2010



       ๏ 첫번째 단계
            void GoHomeAndSleepTilRested::Enter(Miner* pMiner)
           {
             if (pMiner->Location() != shack)
             {
               cout << "n" << 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);
                }
            }


2010년	 3월	 23일	 화요일
71

     I5. Elsa는 저녁을 준비한다
     2. 상태구동형 에이전트의 디자인                                                              Mar. 2, 2010



       ๏ 두번째 단계
           bool WifesGlobalState::OnMessage(MinersWife* wife, const Telegram& msg)
           {
             switch(msg.Msg)
             {
             case Msg_HiHoneyImHome:
              {
                 cout << "nMessage handled by " << GetNameOfEntity(wife->ID()) <<
            " at time: "
                 << Clock->GetCurrentTime();

                 cout << "n" << 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;
           }




2010년	 3월	 23일	 화요일
72

     I5. Elsa는 저녁을 준비한다
     2. 상태구동형 에이전트의 디자인                                                  Mar. 2, 2010



       ๏ 세번째 단계
            void CookStew::Enter(MinersWife* wife)
           {
             //if not already cooking put the stew in the oven
             if (!wife->Cooking())
             {
               cout << "n" << GetNameOfEntity(wife->ID()) <<
            ": Putting the stew in 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);
                }
            }


2010년	 3월	 23일	 화요일
73

     I5. Elsa는 저녁을 준비한다
     2. 상태구동형 에이전트의 디자인                                                                    Mar. 2, 2010



         ๏ 네번째 단계
     bool CookStew::OnMessage(MinersWife* wife, const Telegram& msg)
     {
       switch(msg.Msg) {
        case Msg_StewReady: {
         cout << "nMessage received by " << GetNameOfEntity(wife->ID()) << " at time: "
              << Clock->GetCurrentTime();
         SetTextColor(FOREGROUND_GREEN|FOREGROUND_INTENSITY);
         cout << "n" << GetNameOfEntity(wife->ID()) << ": StewReady! Lets eat";

           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;
     }



2010년	 3월	 23일	 화요일
74

     I5. Elsa는 저녁을 준비한다
     2. 상태구동형 에이전트의 디자인                                                Mar. 2, 2010



         ๏ 다섯 번째 단계

     bool GoHomeAndSleepTilRested::OnMessage(Miner* pMiner, const Telegram& msg)
     {
       switch(msg.Msg)
       {
       case Msg_StewReady:
         cout << "nMessage handled by " << GetNameOfEntity(pMiner->ID())
         << " at time: " << Clock->GetCurrentTime();
         cout << "n" << 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
     }



2010년	 3월	 23일	 화요일

More Related Content

Featured

How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental Health
ThinkNow
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie Insights
Kurio // The Social Media Age(ncy)
 

Featured (20)

Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage Engineerings
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental Health
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
 
Skeleton Culture Code
Skeleton Culture CodeSkeleton Culture Code
Skeleton Culture Code
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie Insights
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search Intent
 
How to have difficult conversations
How to have difficult conversations How to have difficult conversations
How to have difficult conversations
 
Introduction to Data Science
Introduction to Data ScienceIntroduction to Data Science
Introduction to Data Science
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best Practices
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project management
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
 
Unlocking the Power of ChatGPT and AI in Testing - A Real-World Look, present...
Unlocking the Power of ChatGPT and AI in Testing - A Real-World Look, present...Unlocking the Power of ChatGPT and AI in Testing - A Real-World Look, present...
Unlocking the Power of ChatGPT and AI in Testing - A Real-World Look, present...
 
12 Ways to Increase Your Influence at Work
12 Ways to Increase Your Influence at Work12 Ways to Increase Your Influence at Work
12 Ways to Increase Your Influence at Work
 

Dd3440.04

  • 1. 게임제작론고급1및실습 DD3440 Mar. 2, 2010 Chapter 2 상태구동형 에이전트의 디자인 박창훈 호서대학교 게임공학과 2010년 3월 23일 화요일
  • 2. 2. 상태구동형 에이전트의 디자인 DD3440 Mar. 2, 2010 A. 유한상태 기계란 정확하게 무엇일까? 2010년 3월 23일 화요일
  • 3. 3 A. 유한상태 기계란 정확하게 무엇일까? 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 2010년 3월 23일 화요일
  • 4. 2. 상태구동형 에이전트의 디자인 DD3440 Mar. 2, 2010 B. 유한상태기계 구현하기 B1. 상태 전환표 B2. 내장된 규칙들 2010년 3월 23일 화요일
  • 5. 5 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 enum StateType { RunAway, Patrol, Attack }; void Agent::UpdateState(StateType CurrentState) { switch (CurrentState) { case state_RunAway: EvadeEnemy(); if (Safe()) { ChangeState( state_Patrol); } break; 2010년 3월 23일 화요일
  • 6. 6 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 case state_Patrol: FollowPatrolPath(); if (Threatened()) { if (StrongerThanEnemy()) { ChangeState( state_Attack); } else { ChangeState( state_RunAway); } } break; 2010년 3월 23일 화요일
  • 7. 7 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 case state_Attack: if (WeakerThanEnemy()) { ChangeState( state_RunAway); } else { BashEnemyOverHead(); } break; }//end switch } 2010년 3월 23일 화요일
  • 8. 8 B1. 상태 전환표 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 2010년 3월 23일 화요일
  • 9. 2. 상태구동형 에이전트의 디자인 DD3440 Mar. 2, 2010 B. 유한상태기계 구현하기 B1. 상태 전환표 B2. 내장된 규칙들 2010년 3월 23일 화요일
  • 10. 10 B2. 내장된 규칙들 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 class State { public: virtual void Execute(Troll* troll)=0; }; 2010년 3월 23일 화요일
  • 11. 11 B2. 내장된 규칙들 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 class Troll { /* ATTRIBUTES OMITTED */ State* m_pCurrentState; public: /* INTERFACE TO ATTRIBUTES OMITTED */ void Update() { m_pCurrentState->Execute(this;) } void ChangeState(const State* pNewState) { delete m_pCurrentState; m_pCurrentState = pNewState; } }; 2010년 3월 23일 화요일
  • 12. 12 B2. 내장된 규칙들 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 //------------------------------State RunAway class State_Runway : public State { public: void Execute(Troll* troll) { if(troll->isSafe()) { troll->ChangeState(new State_Sleep()); } else { troll->MoveAwayFromEnemy(); } } }; 2010년 3월 23일 화요일
  • 13. 13 B2. 내장된 규칙들 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 //-----------------------------State_Sleep class State_Slepp : public State { void Execute(Troll* troll) { if(troll->isThreatened()) { troll->ChangeState(new State_RunAway()) } else { troll->Snore(); } } }; 2010년 3월 23일 화요일
  • 14. 2. 상태구동형 에이전트의 디자인 DD3440 Mar. 2, 2010 C. West World 프로젝트 C1. BaseGameEntity 클래스 C2. Minor 클래스 C3. Minor 상태들 C4. 상태 디자인 패턴에 대해 자세히 알아보기 2010년 3월 23일 화요일
  • 15. 15 C1. BaseGameEntity 클래스 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 class BaseGameEntity { private: int m_ID; static int m_iNextValidID; void SetID(int val); public: BaseGameEntity(int id) { SetID(id); } virtual ~BaseGameEntity(){} virtual void Update()=0; int ID()const{return m_ID;} }; 2010년 3월 23일 화요일
  • 16. 2. 상태구동형 에이전트의 디자인 DD3440 Mar. 2, 2010 C. West World 프로젝트 C1. BaseGameEntity 클래스 C2. Minor 클래스 C3. Minor 상태들 C4. 상태 디자인 패턴에 대해 자세히 알아보기 2010년 3월 23일 화요일
  • 17. 17 C2. Minor 클래스 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 class Miner : public BaseGameEntity { private: State* m_pCurrentState; location_type m_Location; int m_iGoldCarried; int m_iMoneyInBank; int m_iThirst; int m_iFatigue; public: Miner(int id); void Update(); void ChangeState(State* new_state); } 2010년 3월 23일 화요일
  • 18. 18 C2. Minor 클래스 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 void Miner::Update() { m_iThirst += 1; if (m_pCurrentState) { m_pCurrentState->Execute(this); } } 2010년 3월 23일 화요일
  • 19. 2. 상태구동형 에이전트의 디자인 DD3440 Mar. 2, 2010 C. West World 프로젝트 C1. BaseGameEntity 클래스 C2. Minor 클래스 C3. Minor 상태들 C4. 상태 디자인 패턴에 대해 자세히 알아보기 2010년 3월 23일 화요일
  • 20. 20 C3. Minor 상태들 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 2010년 3월 23일 화요일
  • 21. 2. 상태구동형 에이전트의 디자인 DD3440 Mar. 2, 2010 C. West World 프로젝트 C1. BaseGameEntity 클래스 C2. Minor 클래스 C3. Minor 상태들 C4. 상태 디자인 패턴에 대해 자세히 알아보기 2010년 3월 23일 화요일
  • 22. 22 C4. 상태 디자인 패턴에 대해 자세히 알아보기 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 class State { public: virtual ~State(){} //this will execute when the state is entered virtual void Enter(Miner*)=0; //this is the state's normal update function virtual void Execute(Miner*)=0; //this will execute when the state is exited. (My word, isn't //life full of surprises... ;o)) virtual void Exit(Miner*)=0; }; 2010년 3월 23일 화요일
  • 23. 23 C4. 상태 디자인 패턴에 대해 자세히 알아보기 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 void Miner::ChangeState(State* pNewState) { //make sure both states are both valid before attempting to //call their methods assert(m_pCurrentState && pNewState); //call the exit method of the existing state m_pCurrentState->Exit(this); //change state to the new state m_pCurrentState = pNewState; //call the entry method of the new state m_pCurrentState->Enter(this); } 2010년 3월 23일 화요일
  • 24. 24 C4. 상태 디자인 패턴에 대해 자세히 알아보기 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 2010년 3월 23일 화요일
  • 25. 25 C4. 상태 디자인 패턴에 대해 자세히 알아보기 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 /* ------------------ MyClass.h ------------------- */ #ifndef MY_SINGLETON #define MY_SINGLETON class MyClass { private: int m_iNum; MyClass(){} MyClass(const MyClass &); MyClass& operator=(const MyClass &); public: ~MyClass(); int GetVal()const{return m_iNum;} static MyClass* Instance(); 2010년 3월 23일 화요일
  • 26. 26 C4. 상태 디자인 패턴에 대해 자세히 알아보기 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 /* ------------------ MyClass.h ------------------- */ public: ~MyClass(); //methods int GetVal()const{return m_iNum;} static MyClass* Instance(); }; #endif /* ------------------- MyClass.cpp ------------------ */ MyClass* MyClass::Instance() { static MyClass instance; return &instance; } 2010년 3월 23일 화요일
  • 27. 27 C4. 상태 디자인 패턴에 대해 자세히 알아보기 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 int num = MyClass::Instance()->GetVal(); #define MyCls MyClass::Instance() int num = MyCls->GetVal(); 2010년 3월 23일 화요일
  • 28. 28 C4. 상태 디자인 패턴에 대해 자세히 알아보기 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 ๏ EnterMineAndDigForNugget class EnterMineAndDigForNugget : public State { private: EnterMineAndDigForNugget(){} /* copy ctor and assignment op omitted */ public: //this is a singleton static EnterMineAndDigForNugget* Instance(); virtual void Enter(Miner* miner); virtual void Execute(Miner* miner); virtual void Exit(Miner* miner); }; 2010년 3월 23일 화요일
  • 29. 29 C4. 상태 디자인 패턴에 대해 자세히 알아보기 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 ๏ EnterMineAndDigForNugget 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) { SetTextColor(FOREGROUND_RED| FOREGROUND_INTENSITY); cout << "n" << GetNameOfEntity(pMiner->ID()) << ": " << "Walkin' to the goldmine"; pMiner->ChangeLocation(goldmine); } } 2010년 3월 23일 화요일
  • 30. 30 C4. 상태 디자인 패턴에 대해 자세히 알아보기 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 ๏ EnterMineAndDigForNugget void EnterMineAndDigForNugget::Execute(Miner* pMiner) { pMiner->AddToGoldCarried(1); pMiner->IncreaseFatigue(); SetTextColor(FOREGROUND_RED| FOREGROUND_INTENSITY); cout << "n" << GetNameOfEntity(pMiner->ID()) << ": " << "Pickin' up a nugget"; if (pMiner->PocketsFull()) { pMiner->ChangeState(VisitBankAndDepositGold::Instance()); } if (pMiner->Thirsty()) { pMiner->ChangeState(QuenchThirst::Instance()); } } 2010년 3월 23일 화요일
  • 31. 31 C4. 상태 디자인 패턴에 대해 자세히 알아보기 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 ๏ EnterMineAndDigForNugget void EnterMineAndDigForNugget::Exit(Miner* pMiner) { SetTextColor(FOREGROUND_RED| FOREGROUND_INTENSITY); cout << "n" << GetNameOfEntity(pMiner->ID()) << ": " << "Ah'm leavin' the goldmine with mah pockets full o' sweet gold"; } 2010년 3월 23일 화요일
  • 32. 2. 상태구동형 에이전트의 디자인 DD3440 Mar. 2, 2010 D. 상태의 기본 클래스 재사용할 수 있게 만들기 2010년 3월 23일 화요일
  • 33. 33 D. 상태의 기본 클래스 재사용할 수 있게 만들기 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 template <class entity_type> class State { public: virtual void Enter(entity_type*)=0; virtual void Execute(entity_type*)=0; virtual void Exit(entity_type*)=0; virtual ~State(){} }; 2010년 3월 23일 화요일
  • 34. 34 D. 상태의 기본 클래스 재사용할 수 있게 만들기 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 class EnterMineAndDigForNugget : public State<Miner> { public: /* OMITTED */ }; 2010년 3월 23일 화요일
  • 35. 2. 상태구동형 에이전트의 디자인 DD3440 Mar. 2, 2010 F. 전역 상태 및 상태 블립 2010년 3월 23일 화요일
  • 36. 36 F. 전역 상태 및 상태 블립 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 State<Miner>* m_pGlobalState; class Miner : public BaseGameEntity { private: State<Miner>* m_pCurrentState; State<Miner>* m_pPreviousState; State<Miner>* m_pGlobalState; ... public: void ChangeState(State<Miner>* pNewState); void RevertToPreviousState(); ... }; 2010년 3월 23일 화요일
  • 37. 2. 상태구동형 에이전트의 디자인 DD3440 Mar. 2, 2010 G. 상태기계 클래스 생성하기 2010년 3월 23일 화요일
  • 38. 38 G. 상태기계 클래스 생성하기 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 template <class entity_type> class StateMachine { private: entity_type* m_pOwner; State<entity_type>* m_pCurrentState; State<entity_type>* m_pPreviousState; State<entity_type>* m_pGlobalState; public: StateMachine(entity_type* owner):m_pOwner(owner), m_pCurrentState(NULL), m_pPreviousState(NULL), m_pGlobalState(NULL) {} 2010년 3월 23일 화요일
  • 39. 39 G. 상태기계 클래스 생성하기 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 virtual ~StateMachine(){} void SetCurrentState(State<entity_type>* s){m_pCurrentState = s;} void SetGlobalState(State<entity_type>* s) {m_pGlobalState = s;} void SetPreviousState(State<entity_type>* s){m_pPreviousState = s;} void Update()const { if(m_pGlobalState) m_pGlobalState->Execute(m_pOwner); if (m_pCurrentState) m_pCurrentState->Execute(m_pOwner); } 2010년 3월 23일 화요일
  • 40. 40 G. 상태기계 클래스 생성하기 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 void ChangeState(State<entity_type>* pNewState) { assert(pNewState && "<StateMachine::ChangeState>: trying to change to NULL state"); m_pPreviousState = m_pCurrentState; m_pCurrentState->Exit(m_pOwner); m_pCurrentState = pNewState; m_pCurrentState->Enter(m_pOwner); } void RevertToPreviousState() { ChangeState(m_pPreviousState); } 2010년 3월 23일 화요일
  • 41. 41 G. 상태기계 클래스 생성하기 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 bool isInState(const State<entity_type>& st)const { return typeid(*m_pCurrentState) == typeid(st); } State<entity_type>* CurrentState() const{return m_pCurrentState;} State<entity_type>* GlobalState() const{return m_pGlobalState;} State<entity_type>* PreviousState() const{return m_pPreviousState;} }; 2010년 3월 23일 화요일
  • 42. 42 G. 상태기계 클래스 생성하기 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 class Miner : public BaseGameEntity { private: StateMachine<Miner>* m_pStateMachine; /* EXTRANEOUS DETAIL OMITTED */ public: Miner(int id):m_Location(shack), m_iGoldCarried(0), m_iMoneyInBank(0), m_iThirst(0), m_iFatigue(0), BaseGameEntity(id) { m_pStateMachine = new StateMachine<Miner>(this); m_pStateMachine->SetCurrentState(GoHomeAndSleepTilRested::Instance()); m_pStateMachine->SetGlobalState(MinerGloalState::Instance()); } 2010년 3월 23일 화요일
  • 43. 43 G. 상태기계 클래스 생성하기 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 ~Miner(){delete m_pStateMachine;} void Update() { ++m_iThirst; m_pStateMachine->Update(); } StateMachine<Miner>* GetFSM()const{return m_pStateMachine;} /* EXTRANEOUS DETAIL O<ITTED */ }; 2010년 3월 23일 화요일
  • 44. 44 G. 상태기계 클래스 생성하기 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 2010년 3월 23일 화요일
  • 45. 45 G. 상태기계 클래스 생성하기 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 2010년 3월 23일 화요일
  • 46. 2. 상태구동형 에이전트의 디자인 DD3440 Mar. 2, 2010 H. Elsa 소개하기 2010년 3월 23일 화요일
  • 47. 47 H. Elsa 소개하기 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 2010년 3월 23일 화요일
  • 48. 2. 상태구동형 에이전트의 디자인 DD3440 Mar. 2, 2010 I. FSM 메시지 처리기능 추가하기 I1. 전보구조 I2. 광부 Bob과 Elsa의 통신 I3. 메시지 급송 및 관리 I4. 메시지 처리하기 I5. Elsa는 저녁을 준비한다 2010년 3월 23일 화요일
  • 49. 49 I1. 전보구조 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 struct Telegram { int Sender; int Receiver; int Msg; double DispatchTime; void* ExtraInfo; /* CONSTRUCTORS OMITTED */ }; 2010년 3월 23일 화요일
  • 50. 2. 상태구동형 에이전트의 디자인 DD3440 Mar. 2, 2010 I. FSM 메시지 처리기능 추가하기 I1. 전보구조 I2. 광부 Bob과 Elsa의 통신 I3. 메시지 급송 및 관리 I4. 메시지 처리하기 I5. Elsa는 저녁을 준비한다 2010년 3월 23일 화요일
  • 51. 51 I2. 광부 Bob과 Elsa의 통신 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 enum message_type { Msg_HiHoneyImHome, Msg_StewReady }; 2010년 3월 23일 화요일
  • 52. 2. 상태구동형 에이전트의 디자인 DD3440 Mar. 2, 2010 I. FSM 메시지 처리기능 추가하기 I1. 전보구조 I2. 광부 Bob과 Elsa의 통신 I3. 메시지 급송 및 관리 I4. 메시지 처리하기 I5. Elsa는 저녁을 준비한다 2010년 3월 23일 화요일
  • 53. 53 I3. 메시지 급송 및 관리 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 class EntityManager { private: typedef std::map<int, BaseGameEntity*> EntityMap; private: EntityMap m_EntityMap; EntityManager(){} EntityManager(const EntityManager&); EntityManager& operator=(const EntityManager&); 2010년 3월 23일 화요일
  • 54. 54 I3. 메시지 급송 및 관리 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 public: static EntityManager* Instance(); void RegisterEntity(BaseGameEntity* NewEntity); BaseGameEntity* GetEntityFromID(int id)const; void RemoveEntity(BaseGameEntity* pEntity); }; #define EntityMgr EntityManager::Instance() Miner* Bob = new Miner(ent_Miner_Bob); //enumerated ID EntityMgr->RegisterEntity(Bob); Entity* pBob = EntityMgr->GetEntityFromID(ent_Miner_Bob); 2010년 3월 23일 화요일
  • 55. 55 I3. 메시지 급송 및 관리 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 ๏ MessageDispatcher 클래스 class MessageDispatcher { private: std::set<Telegram> PriorityQ; void Discharge(BaseGameEntity* pReceiver, const Telegram& msg); MessageDispatcher(){} public: static MessageDispatcher* Instance(); void DispatchMessage(double delay, int sender, int receiver, int msg, void* ExtraInfo); void DispatchDelayedMessages(); }; #define Dispatch MessageDispatcher::Instance() 2010년 3월 23일 화요일
  • 56. 56 I3. 메시지 급송 및 관리 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 ๏ MessageDispatcher 클래스 void MessageDispatcher::DispatchMessage(double delay, int sender, int receiver, int msg, void* ExtraInfo) { Entity* pReceiver = EntityMgr->GetEntityFromID(receiver); Telegram telegram(0, sender, receiver, msg, ExtraInfo); if (delay <= 0.0f) { Discharge(pReceiver, telegram); } else { double CurrentTime = Clock->GetCurrentTime(); telegram.DispatchTime = CurrentTime + delay; PriorityQ.insert(telegram); } } 2010년 3월 23일 화요일
  • 57. 57 I3. 메시지 급송 및 관리 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 ๏ MessageDispatcher 클래스 void MessageDispatcher::DispatchDelayedMessages() { double CurrentTime = Clock->GetCurrentTime(); while( (PriorityQ.begin()->DispatchTime < CurrentTime) && (PriorityQ.begin()->DispatchTime > 0) ) { Telegram telegram = *PriorityQ.begin(); BaseGameEntity* pReceiver = EntityMgr->GetEntityFromID (telegram.Receiver); Discharge(pReceiver, telegram); PriorityQ.erase(PriorityQ.begin()); } } 2010년 3월 23일 화요일
  • 58. 2. 상태구동형 에이전트의 디자인 DD3440 Mar. 2, 2010 I. FSM 메시지 처리기능 추가하기 I1. 전보구조 I2. 광부 Bob과 Elsa의 통신 I3. 메시지 급송 및 관리 I4. 메시지 처리하기 I5. Elsa는 저녁을 준비한다 2010년 3월 23일 화요일
  • 59. 59 I4. 메시지 처리하기 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 class BaseGameEntity { private: int m_ID; /* EXTRANEOUS DETAIL REMOVED FOR CLARITY*/ public: virtual bool HandleMessage(const Telegram& msg)=0; /* EXTRANEOUS DETAIL REMOVED FOR CLARITY*/ }; 2010년 3월 23일 화요일
  • 60. 60 I4. 메시지 처리하기 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 template <class entity_type> class State { public: virtual bool OnMessage(entity_type*, const Telegram&)=0; /* EXTRANEOUS DETAIL REMOVED FOR CLARITY*/ }; 2010년 3월 23일 화요일
  • 61. 61 I4. 메시지 처리하기 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 bool StateMachine::HandleMessage(const Telegram& msg)const { if (m_pCurrentState && m_pCurrentState->OnMessage(m_pOwner, msg)) { return true; } if (m_pGlobalState && m_pGlobalState->OnMessage(m_pOwner, msg)) { return true; } return false; } 2010년 3월 23일 화요일
  • 62. 62 I4. 메시지 처리하기 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 bool Miner::HandleMessage(const Telegram& msg) { return m_pStateMachine->HandleMessage(msg); } 2010년 3월 23일 화요일
  • 63. 63 I4. 메시지 처리하기 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 2010년 3월 23일 화요일
  • 64. 64 I4. 메시지 처리하기 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 2010년 3월 23일 화요일
  • 65. 65 I3. 메시지 급송 및 관리 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 public: static EntityManager* Instance(); void RegisterEntity(BaseGameEntity* NewEntity); BaseGameEntity* GetEntityFromID(int id)const; void RemoveEntity(BaseGameEntity* pEntity); }; #define EntityMgr EntityManager::Instance() Miner* Bob = new Miner(ent_Miner_Bob); //enumerated ID EntityMgr->RegisterEntity(Bob); Entity* pBob = EntityMgr->GetEntityFromID(ent_Miner_Bob); 2010년 3월 23일 화요일
  • 66. 66 I3. 메시지 급송 및 관리 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 ๏ MessageDispatcher 클래스 class MessageDispatcher { private: std::set<Telegram> PriorityQ; void Discharge(BaseGameEntity* pReceiver, const Telegram& msg); MessageDispatcher(){} public: static MessageDispatcher* Instance(); void DispatchMessage(double delay, int sender, int receiver, int msg, void* ExtraInfo); void DispatchDelayedMessages(); }; #define Dispatch MessageDispatcher::Instance() 2010년 3월 23일 화요일
  • 67. 67 I3. 메시지 급송 및 관리 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 ๏ MessageDispatcher 클래스 void MessageDispatcher::DispatchMessage(double delay, int sender, int receiver, int msg, void* ExtraInfo) { Entity* pReceiver = EntityMgr->GetEntityFromID(receiver); Telegram telegram(0, sender, receiver, msg, ExtraInfo); if (delay <= 0.0f) { Discharge(pReceiver, telegram); } else { double CurrentTime = Clock->GetCurrentTime(); telegram.DispatchTime = CurrentTime + delay; PriorityQ.insert(telegram); } } 2010년 3월 23일 화요일
  • 68. 68 I3. 메시지 급송 및 관리 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 ๏ MessageDispatcher 클래스 void MessageDispatcher::DispatchDelayedMessages() { double CurrentTime = Clock->GetCurrentTime(); while( (PriorityQ.begin()->DispatchTime < CurrentTime) && (PriorityQ.begin()->DispatchTime > 0) ) { Telegram telegram = *PriorityQ.begin(); BaseGameEntity* pReceiver = EntityMgr->GetEntityFromID (telegram.Receiver); Discharge(pReceiver, telegram); PriorityQ.erase(PriorityQ.begin()); } } 2010년 3월 23일 화요일
  • 69. 2. 상태구동형 에이전트의 디자인 DD3440 Mar. 2, 2010 I. FSM 메시지 처리기능 추가하기 I1. 전보구조 I2. 광부 Bob과 Elsa의 통신 I3. 메시지 급송 및 관리 I4. 메시지 처리하기 I5. Elsa는 저녁을 준비한다 2010년 3월 23일 화요일
  • 70. 70 I5. Elsa는 저녁을 준비한다 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 ๏ 첫번째 단계 void GoHomeAndSleepTilRested::Enter(Miner* pMiner) { if (pMiner->Location() != shack) { cout << "n" << 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); } } 2010년 3월 23일 화요일
  • 71. 71 I5. Elsa는 저녁을 준비한다 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 ๏ 두번째 단계 bool WifesGlobalState::OnMessage(MinersWife* wife, const Telegram& msg) { switch(msg.Msg) { case Msg_HiHoneyImHome: { cout << "nMessage handled by " << GetNameOfEntity(wife->ID()) << " at time: " << Clock->GetCurrentTime(); cout << "n" << 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; } 2010년 3월 23일 화요일
  • 72. 72 I5. Elsa는 저녁을 준비한다 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 ๏ 세번째 단계 void CookStew::Enter(MinersWife* wife) { //if not already cooking put the stew in the oven if (!wife->Cooking()) { cout << "n" << GetNameOfEntity(wife->ID()) << ": Putting the stew in 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); } } 2010년 3월 23일 화요일
  • 73. 73 I5. Elsa는 저녁을 준비한다 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 ๏ 네번째 단계 bool CookStew::OnMessage(MinersWife* wife, const Telegram& msg) { switch(msg.Msg) { case Msg_StewReady: { cout << "nMessage received by " << GetNameOfEntity(wife->ID()) << " at time: " << Clock->GetCurrentTime(); SetTextColor(FOREGROUND_GREEN|FOREGROUND_INTENSITY); cout << "n" << GetNameOfEntity(wife->ID()) << ": StewReady! Lets eat"; 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; } 2010년 3월 23일 화요일
  • 74. 74 I5. Elsa는 저녁을 준비한다 2. 상태구동형 에이전트의 디자인 Mar. 2, 2010 ๏ 다섯 번째 단계 bool GoHomeAndSleepTilRested::OnMessage(Miner* pMiner, const Telegram& msg) { switch(msg.Msg) { case Msg_StewReady: cout << "nMessage handled by " << GetNameOfEntity(pMiner->ID()) << " at time: " << Clock->GetCurrentTime(); cout << "n" << 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 } 2010년 3월 23일 화요일