티스토리 뷰

이글은 KGDA의 nairrti 이 올리신 글입니다. 상당히 좋은 글이라 생각되어 일단 블로그로 가져왔습니다. 하지만 허락을 받지 않았기 때문에 문제가 된다면 삭제 하겠습니다.

나아진 인공지능에 대해서 (1) – 조셉 스윙  

A Better Monster AI - Joseph Swing


더 나아진 인공지능에 대해서 (1) 조셉 스윙

2002년 09월 30일, 저자로부터의 허락을 받아 번역 및 주석을 달았음.

김 종 득(Nairrti@mail.com)

(문서에 대한 역자의 설명 이 문서는 Roguelike 게임에 대한 AI의 개선방안에 대해서 이야기하고 있으며, 매우 간단하고 계산이 비교적 복잡하지 않은 형태의 AI를 구현하기 위한 것입니다. 그러나, 이것은 일반적인 RPG 혹은 MMORPG까지도 확장할 수 있을 만큼 강력한 AI의 기본이라고 불릴 정도의 내용을 포함하고 있습니다. 대체로 게임에서의 AI는 실제의 인공지능만큼 복잡하기 보다는 유저가 느끼기에 좀 더 사실적인 형태의 AI를 갖도록 하는 데에 목적을 두고 있기 때문이겠습니다.

이 문서는 원 저자가 공개된(public) 형태로 만든 문서이므로 한글 번역된 내용도 똑같이 공개되어 있습니다. 내용의 수정을 제외한 주석을 달거나 인용하는 것에 대해서 아무런 제제가 없습니다.

문서는 처음 원 저자가 올린 글을 번역할 것이고, 1 2편으로 나누어서 올리도록 할 것입니다. 그리고, 역자가 원 저자에게 문의한 내용과 그의 추가된 내용에 대해서도 첨가하여 3편을 만들 예정입니다.)

이 문서는 좀 더 흥미로운 몬스터의 인공지능에 대한 이야기들을 정리했습니다. 이 글은 기본적으로 어떻게 하면 몬스터가 주변의 상황을 인지하도록 하는가에 대한 것입니다. 관련 내용에 대해서 누군가가 제안한 내용이나 더 나은 모델을 제시했던 경우에는 (*)를 붙여서 내용을 첨부했습니다. 그리고, 이에 대해서 도움을 준 rec.games.rogulikes.misc 그룹에서 활동하시는 분들께 감사를 드립니다.

대개의 RL게임들은 아래와 예와 같은 간단한 AI를 사용합니다.

(주1 - RL게임이란 Rogue Like 게임을 말함)

            if (ISeeHero) then (MoveToAttackHero)

            else (DoNothing)

(주2 이 것은 간단한 프로그래밍의 구문이며 만약(if) 몬스터를 발견하면(then) 공격하기 위해서 접근한다 아니면(else) 그냥 있는다.라는 뜻임.)

놀랍게도, 이것은 아주 잘 먹힙니다. 하지만, 이제 몬스터에게 약간의 개성을 주어서 이 내용들을 확장해 보려고 합니다.

JSwing의 가이드라인

1)      다른 종의 몬스터는 원하는 것도 다르다.

2)      몬스터는 주변의 다른 몬스터나 사물를 인지하고, 이들과 교감(interact)하며, 이것은 주인공(hero)에게도 똑같이 적용한다.

3)      각 몬스터의 행동은 독립적이다.

4)      집단(group)을 구성하고 있는 몬스터는 그들 전체를 ‘집단’으로 인지한다.

5)      개발자(you)는 이 것들을 좀 더 기교적으로 만들 수 있겠지만, 우리가 원하는 것은 완벽한 AI가 아니다. 우리는 몬스터들이 좀 더 흥미롭게 활동하는 것처럼 보이기를 원할 뿐이다. RL에서 평균적인 몬스터의 수명은 100턴이고, 이 중 10%정도 만이 화면에 보이는 시간이다.

몬스터의 행동은 5가지 정도의 목적을 가지고 있는 것으로 정한다.

[요구사항(desire)] - 몬스터는 금은보화(golds), 먹을것, 무기류 등의 물건(들)을 원한다.

[공포심(fear)] 몬스터는 특정 대상(다른 몬스터나 영웅)으로부터 도망친다.

[공격성향(aggression)] 몬스터는 다른 몬스터(또는 영웅)를 공격한다.

[배회성향(wander)] 목적없이 위치를 바꾸며 돌아다닌다.

[기타(misc)] 특정 장소에 머무르거나 경비를 서는 등의 행동을 한다.

목적이 행동을 결정한다.

각각의 몬스터는 위에 열거된 5가지의 판단 기준을 가지고 있습니다. 만약 이 값이 0면 몬스터는 그 판단 기준을 무시하고 행동하게 됩니다. 몬스터는 엘프를 싫어한다거나 금은보화를 원한다거나 하는 등의 하나 혹은 그 이상의 개성적인 목적을 가지고 있는 것으로 합니다. 이것들은 각각 세기(strength)나 추가적인 다른 목적들과 서로 관계를 가질 수 있습니다. 몬스터가 [요구사항]을 가지고 있기 위해서는, 특정 종류를 원한다던가 하는 것을 설정해 주어야 합니다.

[공포심]이나 [공격성향]이 작동하기 위해서는 몬스터는 자신의 전투능력(combat strength)과 그가 판단의 대상으로 하는 몬스터(지금 눈에 보이는)의 전투능력을 연관 지어야 합니다.

(주3 몬스터는 상대방의 절대적인 수치를 이미 알고 있다고 가정한다는 뜻임)

(*) 가능성: 몬스터는 강하기(strength)와 관련된 [영리]하거나 [멍청]하거나 라는 2개의 능력을 가질 수 있겠습니다. 멍청한 몬스터에게는 인간 농부(human peasant)나 인간 마법사(human wizard)나 별반 차이가 없게 보이지만, 영리한 몬스터는 그 둘을 구분지어서 볼 수 있을 것입니다.

(*) 가능성: 대상의 강하기는 상처를 입었을 경우에 약화시켜서 간주해도 좋겠습니다. 예를 들어서 if(HP<(MaxHP/2)) CombatSTR--라고 말입니다.

(주4 만약 현재 HP가 최대 HP의 절반이면 전투능력을 감쇄한다.)

몬스터는 아군 몬스터들의 목록이 필요할 것입니다. 이것은 많은 가능성을 만들 수 있지 않을까 합니다. 예를 들어서 (주5 - 집단 생활을 하는) 오크는 다른 오크들을 아군으로 보기 때문에 오크 전사(orc warrior)나 오크 성직자(orc priest)를 친구로 생각하게 합니다.

(*) 가능성: 이 친구 아니면 적이라는 이분법적인 구조를 확장하여 관계성에 대한 세기를 두면, ‘매우 미움’이나 ‘절대적 신봉’같은 것들도 만들 수 있을 것입니다.

[요구사항]이 동작하기 위해서는 몬스터는 요구의 대상을 물건(goods)이나 돈(전리품, loots)등으로 정해주어야 합니다. 각각의 목적들 모두 이런 대상이 필요하고, 그런 대상물들은 일반적으로 가치를 가지는 것들이 좋겠습니다.

몬스터는 아래의 상황에서 판단을 시작합니다.

1) 주변을 둘러보고 무엇이 있는가를 확인합니다. 몬스터는 8방향을 볼 수 있으며, 찾은 물건이나 몬스터에 대해서 그는 목적에 따른 판단을 결정합니다.

2) 발견한 대상이 아군 몬스터인 경우 몬스터는 자신의 전투 능력을 증가시킵니다.

(Monstr str +1 distance) (주6 몬스터의 전투 능력 +1 거리)

아군 몬스터는 이 후 함께 행동하기 시작합니다.

3) 발견한 몬스터가 아군이 아닌 경우, 적으로 간주합니다. 여기서 약간 복잡해지는데, 목적을 ‘무언가를 죽이고 싶다’고 설정된 경우 대상의 전투 능력과 거리를 인지하게 됩니다. 그리고, 어느 방향에 있던지 가장 가까운 대상의 방향 쪽으로 이동합니다. 하지만, 이 결과가 다른 몬스터를 통과해서 지나가게 되어서는 안되며, 집단(group)을 형성한 몬스터에 대해서도 계산되어야 할 것입니다.

일단 방향이 결정되면, 공격성향의 값은 (my str(자신의 전투 능력)+my buddies str(동료 몬스터의 전투 능력)[per step 2(거리 2당)])x(6-nearest enemy distance(가장 가까운 곳에 있는 적과의 거리))+2x(basic aggressive value(기본 공격 성향 수치)+any special hates(얼마나 싫어하는 가 하는 정도))가 됩니다. 몬스터는 주변을 둘러보는 계산이 끝나기 전에는 얼마나 많은 동료가 주변에 있는지를 알지 못합니다. 이것은 우리가 다른 몬스터들을 찾기 위해서는 (주7 - 위 공식에서) 보정 해주는 어떤 값이 필요하다는 것을 의미하고, 특정 방향에서부터 가장 가까이에 있는 적을 찾기 시작하면 결국 실제 값은 수정되어야 할 것입니다.

4) *각각의* ‘동료가 아닌’ 몬스터들이 추가될 때 마다, 공포심에 대한 계산을 다시 해야합니다. 이것은 (targets perceived str(눈대중으로 봤을 때 겉으로 보여지는 타겟의 전투 능력))x(6-targets distance(타겟과의 거리))+2x(any special fears(공포의 대상으로 지정된 경우 추가되는 공포심))(주8 즉, 가까운 거리에 있는 몬스터의 공격력은 실제보다 높게 나타나며, 공포의 대상으로 당 몬스터에게 설정된 경우에는 공포의 값이 2배가 된다는 뜻)로 계산해야 할 것입니다. 그리고 이 계산을 각각의 특정 방향에 있는 몬스터에 대해서 계산하면 대강의 값을 추측할 수 있을 것입니다. 이는 집단을 형성한 몬스터들이 개별적으로 계산되는 것이 아니라 집단 전체를 하나의 몬스터로 간주하는 것이 맞다고 생각합니다.

만약 집단 안에 공포심에 대해서 0이 아닌 값을 가지고 있는 어떤 몬스터가 있다고 하면, 우리는 그 방향에 대해서 +2x(my base fear(기본 공포 수치))를 추가해 주어야 합니다. 이 방법은 기본 공포 수치가 각 8방향에 따라 유동적이라는 것이며, 몬스터들의 숫자에 영향받지 않습니다. 또한, 공포심의 총 합을 현재 보고있는 반대 방향에 더해줌으로써 이 몬스터는 현재의 공포심에 대해서 반대 방향으로 도망치고 싶어하게 됩니다. 이는 결국에는 정상적인 상태로 돌아가게 됩니다. (주9 몬스터는 현재의 공포에 의해서 반대 방향으로 도망을 치게 되지만, 거리가 멀어지면 멀어질수록 공포심은 감소하게 되고 평상시의 상태로 돌아가게 됨을 뜻함)

5) 각각의 대상물이나 몬스터에 대해서 가능한 요구사항은 모두 표현해 줍니다. 만약 몬스터가 금은보화나 장신구를 찾아서 돌아다니는 경우라면, 타겟 몬스터에 대해서 금은보화의 가치를 알도록 해 주어야 하고, 원하는 것이 음식이라면 시체의 배고픔을 채워주는 값(주10 RL게임에서는 일반적으로 몬스터등 타인의 시체를 먹음으로써 배고픔을 해결할 수 있음... 사족을 덧붙이면 이 시체들의 특성에 따라서 눈이 멀거나 저주를 받거나 뱀파이어가 되거나 하는 등의 특수 효과가 나타나기도 함. 또한, RL의 주 무대가 되는 던전 안에서는 음식일반적으로 ration-이 매우 부족하게 등장하므로 시체를 먹지 않을 수 없게 만드는 경우가 많음)에 의해서 자신의 욕구를 채우도록 해주어야 합니다. 땅바닥에 떨어진 물건들도 물론 같은 방법으로 계산 합니다. 특정 방향에 대한 총 욕구 수치(the total desire)는 (물건의 가치)+(6-거리)+(기본 욕구 수치)+(특정 대상에 대한 욕구 수치)가 됩니다. 이 값은 더해질 수 있지만 곱해지지 않음을 주의하여 주시기를 바랍니다.(주11 이 부분에서 왜 note this라는 말을 썼는지는 잘 이해가 안됩니다만, 추측하기로는, 공포심은 스스로 살기위해서 필사적으로 도망쳐야 하는 것에 비해서 욕구에 의한 경우는 단지 덧셈으로만 해도 표현이 되는 것이 아닐까 합니다...만 역시 정확히는 모르겠습니다)

6) 기타 항목에는 위에 이야기한 것들 외에 쓸만한 다른 뭔가가 있을 때 그에 대한 값을 적용하기를 바랍니다.(주12 필자는 이 요구 사항에 대한 것들이 위에 나열한 것 외에 더 많은 것들이 있을 것이라고 생각하여, 추가의 여지를 두는 것이며, 그 가능성에 대해서 많은 기대를 하고 있는 듯 합니다) 예를 들어서 이 항목은 사원(altar)근처에서 경비를 서도록 한다던가 주인공과 대화를 하기 위해서 다가오도록 한다던가 하는 것들이 가능할 것입니다.

(*) Aidan Ryder의 제안: 아마도 사원은 몬스터들의 사원으로 만들어질 수도 있을 것이며 그 몬스터의 공포심 수치를 줄여줄 수도 있을 것입니다.

7) 배회성향에서 기본 배회성향 수치(basic wander value)를 1비트씩 왼쪽으로 이동하다가, 몬스터가 혼란(confused)했을 때는 2비트씩 왼쪽으로 이동시키도록 합니다(주13 원문에는 이 문장을 1 << basic wander value)라고 표현했음, 다음 문장도 마찬가지. 프로그래밍에서 메모리를 1비트씩 쉬프트 시키는 뜻으로 사용하는 것임. 오른쪽으로 1비트씩 이동하는 경우에는 /2가 되고 왼쪽으로 이동하는 경우에는 *2가 됨). 기본 배회성향 수치는 낮아야 하지만, 몬스터가 제자리에 서 있거나 원래 서 있던 자리로 돌아오게 되는 경우에는 증가시킵니다. 이것은 갖히는(stuck) 것을 방지하기 위함입니다. 몬스터가 이전의 방향으로 움직이거나 제자리에 서 있게 되면, 몬스터의 템플릿에 있는 배회성향 값을 몬스터의 최소값까지 감소시킵니다. 만약 몬스터가 한 턴 이상이 소요되는 어떤 행동(잠을 자는 것 같은 류의)을 하고 있는 경우라면 이 값을 변화시키지 않습니다.

(*) Aidan Rydar의 제안: 몬스터가 먹고 있을 경우에 음식을 먹는데 소모되는 시간은 먹고있는 대상의 무게와 같게 하고, 먹고 있는 동안은 시야를 1~2칸으로 좁힙니다. 그러면 이 몬스터를 죽이기 위해서 좀 더 쉽게 접근하는 것도 가능할 것 같습니다.

8) 끝으로, 공격성향을 다시 한 번 보겠습니다. 가장 가까이에 있는 대상물의 거리를 기억하고 있는 방향이 있다면, (주14 - 그 방향 쪽의 값... 몹은 이미 8방향에 대해서 값을 가지고 자신의 방향을 결정한다고 앞에서 이야기를 했습니다) 그 값을 1로 하고, 없으면 0으로 놓습니다. 다른 대상물이 있다면 이제 총 전투 능력의 합(주변의 모든 동료들의 것들을 합친)을 가지고 있을 것이고, 이것을 공격성향의 값으로 변환할 수도 있을 것입니다.

9) 수치들의 값을 조정할 필요가 있습니다. 몬스터가 가지고 있는 각 벡터의 X와 Y(또는 Z가 있다면 Z의 값까지)를 노멀라이즈 하십시오(주15 공업수학에 나온다는 노멀벡터(normalized vector)랍니다. 뭔 말인지 어려워서 헤메다가 수소문 끝에 알아내었네요... ;;; 각각의 벡터들의 값을 절대값으로 나눠서 방향성만 남게 하고, 이것들을 합치고 합치다 보면 하나의 방향이 나오게 됩니다. 이 노멀벡터는 AI에서 많이 사용하는 것이라고 하는군요). 이것이 몬스터가 가고 싶어하는 방향입니다. 또한 이것은 위에 열거된 다섯 가지 요구사항 중에서 가장 중요한 모티브로 작용하는 것으로 간주하고, 이것을 몬스터의 행동으로 정합니다. 이것은 몬스터가 장거리 무기를 가지고 있을 경우, 그 것을 사용해서 공격하게 할 수 있을 것입니다.

(*) 아래에 있는 길찾기를 참고하십시오.

10) 모든 몬스터의 AI 값은 이동하기 전 한 턴 안에 계산하도록 하십시오. 이것은 집단을 구성한 몬스터들이 함께 행동하도록 할 것입니다.

(2편으로 계속)

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/03   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
글 보관함