12. 단일목적 - 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; } 이어서
13. 단일목적 - 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")); }
14. 복합 목적 - Goal_FollowPath 목적지까지의 에지 경로를 따라간다. 에지별로 따라가는 동작을 정의한다. Example AB로 이동 할 때에는 수영을 한다. DF로 이동 할 때에는 문을 연다.
15. 복합 목적 - 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; }
16. 복합 목적 - 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; }
19. 전략 평가 구조 평가 함수 Raven_Feature staticdouble Health(Raven_Bot* pBot) staticdoubleDistanceToItem(Raven_Bot* pBot, intItemType) staticdoubleIndividualWeaponStrength(Raven_Bot* pBot, intWeaponType) staticdoubleTotalWeaponStrength(Raven_Bot* pBot)
20. 목적을 어떻게 선택할 것인가? 전략적 요소의 구현 방법 다양한 평가 함수 이용 내가 공격 하는 것이 유리한가? 후퇴하는 것이 유리한가? 목표점으로 이동하는 것이 유리한가? 가장 적절한 전략 공격 평가 점수 0.3 후퇴 평가 점수 0.1 이동 평가 점수 0.7
21. HP아이템 찾기 맵 탐색하기 특정 지역에 무기 얻기 공격 목표 찾기 전략 평가 함수 0.5 or
22. 전략 평가 소스코드 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); }
23. 부산물 개성의 표현 Goal_Evaluator의 subclass에 bias부여 상태 메모리 Stack구조를 이용해 이전 내용 기억함 명령 큐잉 FollowPosition의 Queue로 된 경로점 리스트 스크립트 행동에 큐 사용하기 List구조의 Subgoals를 통하여 절차적인 흐름을 기술 할 수 있다.