글 수 56

FSM을 사용한 인공지능 구현 예제

조회 수 1317 추천 수 0 2017.04.13 03:36:01


유한 상태 기계(Finite State Machine)는 게임에서 가장 대표적으로 쓰이는 인공지능입니다. 게임속에서 동작하는 캐릭터들의 행동을 결정하기 위해서 사용하는데 아주 쉽고 직관적이면서도 상당히 좋은 결과를 보여줍니다. '실용적 예제로 본 게임 인공지능'이라는 책에 나와 있는 예제 프로그램을 앞으로 3회에 걸쳐 소개해보도록 하겠습니다. 텍스트로만 구현되는 아주 간단한 프로그램인데 금을 채굴하는 광부의 행동을 FSM로 구현하였습니다.

 

 

 

광부의 상태 종류

 

mine.jpg

 

광부는 상태는 위의 도표처럼 4가지가 있습니다. 그리고 광부가 각각의 행동을 할때마다 내부의 파라미터 값이 변경되고 그에 따라 현재 상태에서 다음 상태로 전환할지 결정합니다. 파라미터에는 갖고 있는 금의 개수, 은행에 예금한 금의 개수, 목마름, 피로도 등이 있습니다.

 

'집에서 휴식' 상태에서는 피로도가 높으면 잠을 자고 피로도를 1 감소합니다. 피로도가 낮으면 '광산에서 금덩어리 채굴' 상태로 변경합니다.

 

'광산에서 금덩어리 채굴' 상태에서는 금덩어리를 하나 캐고 금이 1 증가, 피로도가 1 증가합니다. 주머니가 가득 차면 '은행에 금 예금' 상태로 변경합니다. 목이 마르면 '갈증을 해소' 상태로 변경합니다.

 

'은행에 금 예금' 상태에서는 갖고 있는 금의 개수는 0이 되고 은행에 예금한 금의 개수는 그만큼 증가합니다. 은행에 예금한 금의 개수가 일정 이상이 되면 '집에서 휴식' 상태로 변경합니다. 그렇지 않으면 '광산에서 금덩어리 채굴' 상태로 변경합니다.

 

'갈증을 해소' 상태에서는 술집에서 술을 마시고 목마름은 0이 되지만 은행의 금의 개수가 2 감소합니다. 그리고 다시 '광산에서 금덩어리 채굴' 상태로 변경합니다.

 

 

 

소스 코드

 

https://github.com/deepseasw/WestWorld

 

Src 폴더에 여러개의 파일이 있는데 가중 중요한 것은 main, Miner, MinerOwnedStates 3가지 입니다.

 

 

 

메인 함수 - main.cpp

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int main()
{
  //create a miner
  Miner miner(ent_Miner_Bob);
 
  //simply run the miner through a few Update calls
  for (int i=0; i<20++i)
  { 
    miner.Update();
 
    Sleep(2000);
  }
 
  //wait for a keypress before exiting
  PressAnyKeyToContinue();
 
  return 0;
}
cs

 

먼저 광부 Miner 클래스 인스턴스를 생성합니다. 그리고 miner.Update()를 20번 실행하는데 시간에 따라 광부의 행동을 연속적으로 처리한다고 보시면 됩니다. 메인 함수에서는 이게 전부입니다.

 

 

 

광부 클래스 - Miner.cpp

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Miner : public BaseGameEntity
{
private:
 
  State*                m_pCurrentState;
  
  location_type         m_Location;
 
  int                   m_iGoldCarried;
 
  int                   m_iMoneyInBank;
 
  int                   m_iThirst;
 
  int                   m_iFatigue;
 
...
 
}
cs

 

Miner 클래스의 멤버변수는 위와 같은데 m_pCurrentState는 현재 상태, m_Location은 현재 위치를 나태냅니다. 그리고 아래 4개의 변수는 파라미터인데 m_iGoldCarried는 가지고 있는 금, m_iMoneyInBank는 은행에 예금한 금, m_iThirst는 목마름, m_iFatigue는 피로도입니다.

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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);
}
cs

 

ChangeState() 함수는 상태를 변경시키는 역할을 수행합니다. 먼저 이전 상태의 Exit() 함수를 실행하고 현재 상태를 새로운 상태로 설정합니다. 그리고 새로운 상태의 Enter() 함수를 실행합니다.

 

 

 

1
2
3
4
5
6
7
8
9
void Miner::Update()
{
  m_iThirst += 1;
  
  if (m_pCurrentState)
  {
    m_pCurrentState->Execute(this);
  }
}
cs

 

메인함수에서 반복적으로 실행하던 업데이트 함수입니다. 목마름을 1 증가시키고 현재 상태의 싱글턴 인스턴스에서 Execute() 함수를 실행합니다.

 

 

 

광부 상태 클래스 - MinerOwnedStates.cpp

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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);
};
cs

 

MinerOwnedStates 파일에는 총 4개의 상태 클래스가 정의되어 있습니다. '광산에서 금덩어리 채굴' 상태 클래스는 위와 같은데 하나의 싱글턴으로 구현되었습니다. 그래서 별도로 인스턴스를 생성하지 않고 바로 사용가능합니다. 클래스에는 크게 3개의 함수가 있는데 Enter(), Exit()는 상태에 진입하고 나갈때 각각 실행합니다. 그리고 Execute()는 현재 상태에서의 행동을 결정합니다.

 

 

 

실행 결과

 

K-001.png

 

Miner 클래스의 update()를 한번씩 할때마다 광부를 현재 상태의 행동을 수행합니다. 이 예제에서는 텍스트로만 구현이 되었지만 2D나 3D에서의 캐릭터도 마찬가지로 FSM을 적용할 수 있습니다. 다음번에는 여러개의 캐릭터를 동시에 실행하는 방법을 알아보도록 하겠습니다.

 

 

 

< 인공지능 개발자 모임 >

- 페이스북 그룹에 가입하시면 인공지능에 대한 최신 정보를 쉽게 받으실 수 있습니다.

https://www.facebook.com/groups/AIDevKr/

 


사지방컴

2017.10.03 23:55:37
*.206.130.1

결국 계속 일만 하는 사람에 대한 이야기이군요 흨흨 ㅠ

List of Articles
제목 글쓴이 날짜 조회 수
A* 알고리즘 데모 file 깊은바다 2018-08-18 287
FPS 전투가 가능한 인공지능 [4] 사지방컴 2018-05-13 368
블레이드 앤 소울과 게임 AI [1] 깊은바다 2018-03-14 358
인공지능과 게임 file 깊은바다 2018-03-02 342
FSM를 활용한 FPS게임 [2] 사지방컴 2017-10-02 521
넷마블 AI Lab 인터뷰 깊은바다 2017-09-29 387
강화학습 기반 NPC AI 깊은바다 2017-09-11 365
온라인 게임 속 로봇 경제와 내몰리는 인간 [1] 깊은바다 2017-05-16 197
딥러닝으로 게임 콘텐츠 제작하기 file 깊은바다 2017-05-11 545
유용한 게임 AI 기법 정리 깊은바다 2017-05-04 1967
다가오는 4차 산업혁명 시대의 게임개발 깊은바다 2017-04-27 175
초보자를 위한 A* 알고리즘 file 깊은바다 2017-04-16 618
딥러닝으로 스타크래프트 유닛 컨트롤 학습 깊은바다 2017-04-14 502
FSM을 사용한 인공지능 구현 예제 file [1] 깊은바다 2017-04-13 1317
실용적 예제로 본 게임 인공지능 소스코드 및 PDF 파일 깊은바다 2017-03-31 1174