• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
목적이 부여된 에이전트 행동
 

목적이 부여된 에이전트 행동

on

  • 910 views

 

Statistics

Views

Total Views
910
Views on SlideShare
871
Embed Views
39

Actions

Likes
1
Downloads
2
Comments
0

5 Embeds 39

http://parkpd.egloos.com 18
http://www.andstudy.com 9
http://andstudy.com 7
http://soomong.net 3
http://www.slideshare.net 2

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    목적이 부여된 에이전트 행동 목적이 부여된 에이전트 행동 Presentation Transcript

    • 목적이 부여된 에이전트 행동
      전효성
    • 에이전트의 행동 기술 방법
      FSM기반 아키텍처
      에이전트 행동 = 상태 + 상태 전이 조건
      목적 기반 아키텍처
      에이전트의 행동 = 목적(Goal)들의 집합
    • 목적
      단일 목적
      직접 엔티티 요소를 제어
      단일 임무, 행위, 행동을 정의
      예, 위치 찾기, 무기 재장전
      복합 목적
      여러 부목적을 순차적 / 선택적으로 수행
      몇 개의 부 목적으로 구성
      예, 후퇴하여 엄폐물 찾기
    • 목적 기반 계획
      상위 레벨 추상 목적 선택
      목적을 추상적으로 분해하여 행동계획 만듬
      순차적
      선택적 목적
      예, “극장에 간다”라는 복합 목적의 구조
    • Dragon Slayer2의 사례
    • 구현 – 기본 개념
      Stack을 이용한 Subgoal관리
      Composite 디자인 패턴
    • 구현 – 최종 디자인
    • Goal_Composite::ProcessSubgoals()
      template <classentity_type>
      intGoal_Composite<entity_type>::ProcessSubgoals()
      {
      while (!m_SubGoals.empty() &&
      (m_SubGoals.front()->isComplete() || m_SubGoals.front()->hasFailed())) //실패한 goal이나 성공한 goal제거
      {
      m_SubGoals.front()->Terminate();
      deletem_SubGoals.front();
      m_SubGoals.pop_front();
      }
      if (!m_SubGoals.empty())
      {
      intStatusOfSubGoals = m_SubGoals.front()->Process(); //스택의top에 해당하는 goal을 실행
      if (StatusOfSubGoals == completed && m_SubGoals.size() > 1)
      {
      return active;
      }
      returnStatusOfSubGoals;
      }
      else
      {
      return completed;
      }
      }
    • Goal_Composite:: RemoveAllSubgoals()
      template <classentity_type>
      voidGoal_Composite<entity_type>::RemoveAllSubgoals()
      {
      for (SubgoalList::iterator it = m_SubGoals.begin();
      it != m_SubGoals.end();
      ++it)
      {
      (*it)->Terminate();
      delete *it;
      }
      m_SubGoals.clear();
      }
    • Raven Bot에서 사용되는 목적들
    • 단일목적 - Goal_Wander
      voidGoal_Wander::Activate()
      {
      m_iStatus = active;
      m_pOwner->GetSteering()->WanderOn();
      }
      intGoal_Wander::Process()
      {
      //if status is inactive, call Activate()
      ActivateIfInactive();
      returnm_iStatus;
      }
      voidGoal_Wander::Terminate()
      {
      m_pOwner->GetSteering()->WanderOff();
      }
    • 단일목적 - Goal_TraverseEdge(1/2)
      //record the time the bot starts this goal
      m_dStartTime = Clock->GetCurrentTime();
      //calculate the expected time required to reach the this waypoint. This value
      //is used to determine if the bot becomes stuck
      m_dTimeExpected = m_pOwner->CalculateTimeToReachPosition(m_Edge.Destination());
      //factor in a margin of error for any reactive behavior
      staticconstdoubleMarginOfError = 2.0;
      m_dTimeExpected += MarginOfError;
      //set the steering target
      m_pOwner->GetSteering()->SetTarget(m_Edge.Destination());
      //Set the appropriate steering behavior. If this is the last edge in the path
      //the bot should arrive at the position it points to, else it should seek
      if (m_bLastEdgeInPath)
      {
      m_pOwner->GetSteering()->ArriveOn();
      }
      else
      {
      m_pOwner->GetSteering()->SeekOn();
      }
      voidGoal_TraverseEdge::Activate()
      {
      m_iStatus = active;
      //the edge behavior flag may specify a type of movement that necessitates a change in the bot's max possible speed as it follows this edge
      switch(m_Edge.Behavior())
      {
      caseNavGraphEdge::swim:
      {
      m_pOwner->SetMaxSpeed(script->GetDouble("Bot_MaxSwimmingSpeed"));
      }
      break;
      caseNavGraphEdge::crawl:
      {
      m_pOwner->SetMaxSpeed(script->GetDouble("Bot_MaxCrawlingSpeed"));
      }
      break;
      }
      이어서
    • 단일목적 - Goal_TraverseEdge(2/2)
      intGoal_TraverseEdge::Process()
      {
      //if status is inactive, call Activate()
      ActivateIfInactive();
      //if the bot has become stuck return failure
      if (isStuck())
      {
      m_iStatus = failed;
      }
      //if the bot has reached the end of the edge return completed
      else
      {
      if (m_pOwner->isAtPosition(m_Edge.Destination()))
      {
      m_iStatus = completed;
      }
      }
      returnm_iStatus;
      }
      voidGoal_TraverseEdge::Terminate()
      {
      //turn off steering behaviors.
      m_pOwner->GetSteering()->SeekOff();
      m_pOwner->GetSteering()->ArriveOff();
      //return max speed back to normal
      m_pOwner->SetMaxSpeed(script->GetDouble("Bot_MaxSpeed"));
      }
    • 복합 목적 - Goal_FollowPath
      목적지까지의 에지 경로를 따라간다.
      에지별로 따라가는 동작을 정의한다.
      Example
      AB로 이동 할 때에는 수영을 한다.
      DF로 이동 할 때에는 문을 연다.
    • 복합 목적 - Goal_FollowPath
      voidGoal_FollowPath::Activate()
      {
      m_iStatus = active;
      //get a reference to the next edge
      PathEdge edge = m_Path.front();
      //remove the edge from the path
      m_Path.pop_front();
      switch(edge.Behavior())
      {
      caseNavGraphEdge::normal:
      {
      AddSubgoal(newGoal_TraverseEdge(m_pOwner, edge, m_Path.empty()));
      }
      break;
      caseNavGraphEdge::goes_through_door:
      {
      //also add a goal that is able to handle opening the door
      AddSubgoal(newGoal_NegotiateDoor(m_pOwner, edge, m_Path.empty()));
      }
      break;
      caseNavGraphEdge::jump:
      {
      //add subgoal to jump along the edge
      }
      break;
      default:
      throw std::runtime_error("<Goal_FollowPath::Activate>: Unrecognized edge type");
      }
      }
      intGoal_FollowPath::Process()
      {
      //if status is inactive, call Activate()
      ActivateIfInactive();
      m_iStatus = ProcessSubgoals();
      if (m_iStatus == completed && !m_Path.empty())
      {
      Activate();
      }
      returnm_iStatus;
      }
    • 복합 목적 - Goal_MoveToPosition
      voidGoal_MoveToPosition::Activate()
      {
      m_iStatus = active;
      //make sure the subgoal list is clear.
      RemoveAllSubgoals();
      if (m_pOwner->GetPathPlanner()->RequestPathToPosition(m_vDestination))
      {
      AddSubgoal(newGoal_SeekToPosition(m_pOwner, m_vDestination));
      }
      }
      intGoal_MoveToPosition::Process()
      {
      //if status is inactive, call Activate()
      ActivateIfInactive();
      //process the subgoals
      m_iStatus = ProcessSubgoals();
      //if any of the subgoals have failed then this goal re-plans
      ReactivateIfFailed();
      returnm_iStatus;
      }
      boolGoal_MoveToPosition::HandleMessage(const Telegram& msg)
      {
      //first, pass the message down the goal hierarchy
      boolbHandled = ForwardMessageToFrontMostSubgoal(msg);
      //if the msg was not handled, test to see if this goal can handle it
      if (bHandled == false)
      {
      switch(msg.Msg)
      {
      caseMsg_PathReady:
      //clear any existing goals
      RemoveAllSubgoals();
      AddSubgoal(newGoal_FollowPath(m_pOwner, m_pOwner->GetPathPlanner()->GetPath()));
      returntrue; //msg handled
      caseMsg_NoPathAvailable:
      m_iStatus = failed;
      returntrue; //msg handled
      default: returnfalse;
      }
      }
      returntrue;
      }
    • 복합 목적 - Goal_AttackTarget
      voidGoal_AttackTarget::Activate()
      {
      m_iStatus = active;
      RemoveAllSubgoals();
      if (!m_pOwner->GetTargetSys()->isTargetPresent())
      {
      m_iStatus = completed;
      return;
      }
      if (m_pOwner->GetTargetSys()->isTargetShootable())
      {
      Vector2D dummy;
      if (m_pOwner->canStepLeft(dummy) || m_pOwner->canStepRight(dummy))
      {
      AddSubgoal(newGoal_DodgeSideToSide(m_pOwner));
      }
      else
      {
      AddSubgoal(newGoal_SeekToPosition(m_pOwner, m_pOwner->GetTargetBot()->Pos()));
      }
      }
      else
      {
      AddSubgoal(newGoal_HuntTarget(m_pOwner));
      }
      }
      intGoal_AttackTarget::Process()
      {
      ActivateIfInactive();
      m_iStatus = ProcessSubgoals();
      ReactivateIfFailed();
      returnm_iStatus;
      }
    • 목적중재 (Goal_Think)
      Goal_Think를 통하여 가장 적절한 전략을 선택
      선택 가능한 전략들
      무기 얻기 - 로켓 발사기
      무기 얻기 - 샷건
      무기 얻기 - 레일건
      목표 공격하기
      건강 얻기
      탐험하기
    • 전략 평가 구조
      평가 함수
      Raven_Feature
      staticdouble Health(Raven_Bot* pBot)
      staticdoubleDistanceToItem(Raven_Bot* pBot, intItemType)
      staticdoubleIndividualWeaponStrength(Raven_Bot* pBot, intWeaponType)
      staticdoubleTotalWeaponStrength(Raven_Bot* pBot)
    • 목적을 어떻게 선택할 것인가?
      전략적 요소의 구현 방법
      다양한 평가 함수 이용
      내가 공격 하는 것이 유리한가?
      후퇴하는 것이 유리한가?
      목표점으로 이동하는 것이 유리한가?
      가장 적절한 전략
      공격 평가 점수
      0.3
      후퇴 평가 점수
      0.1
      이동 평가 점수
      0.7
    • HP아이템 찾기
      맵 탐색하기
      특정 지역에 무기 얻기
      공격 목표 찾기
      전략 평가 함수
      0.5
      or
    • 전략 평가 소스코드
      voidGoal_Think::Arbitrate()
      {
      double best = 0;
      Goal_Evaluator* MostDesirable = 0;
      //iterate through all the evaluators to see which produces the highest score
      GoalEvaluators::iteratorcurDes = m_Evaluators.begin();
      for (curDes; curDes != m_Evaluators.end(); ++curDes)
      {
      doubledesirabilty = (*curDes)->CalculateDesirability(m_pOwner);
      if (desirabilty >= best)
      {
      best = desirabilty;
      MostDesirable = *curDes;
      }
      }
      assert(MostDesirable && "<Goal_Think::Arbitrate>: no evaluator selected");
      MostDesirable->SetGoal(m_pOwner);
      }
    • 부산물
      개성의 표현
      Goal_Evaluator의 subclass에 bias부여
      상태 메모리
      Stack구조를 이용해 이전 내용 기억함
      명령 큐잉
      FollowPosition의 Queue로 된 경로점 리스트
      스크립트 행동에 큐 사용하기
      List구조의 Subgoals를 통하여 절차적인 흐름을 기술 할 수 있다.