안녕하세요. 호랑인 입니다.




오늘은 어제에 이어서 이 Yahtzee 란 게임의 AI 를 만들 방법에 대한 기본적인 아이디어를 올려보도록 하겠습니다. 게임의 인공지능을 만드는 방법으로 저는 크게 3 가지를 생각해봤습니다.


1. 하드 코딩 (Hard-coding)

2. 머신 러닝 (Machine Learning)

3. 유전자 알고리즘 (Genetic Algorithms)


- 하드 코딩은 말 그대로 정해진 코드를 통해 확률을 계산하여 다음 행동을 결정하는 방법입니다. 야찌와 같이 확률에 의존하며, 선택할 수 있는 폭이 넓지 않은 경우, 이 방법은 매우 좋은 선택이라 할 수 있습니다. 게임 AI 중에서 하드코딩을 하는 가장 쉬운 예시로는 tic-tac-toe가 있습니다. 사뭇 당연하게 알려져 있는 필승전략: 중앙-꼭짓점-변두리 를 하드 코딩하는 것은 매우 쉽기 때문입니다. 포커도 과거에는 하드 코딩을 통해 가장 효율적인 배팅을 계산해 나았갔습니다.


- 머신 러닝은 가지고 있는 족보를 통해 특정 상황에서 어떤 행동을 해야하는지를 가르치는 방법입니다. 가장 많이 드는 예시는 알파고입니다. (알파고는 정확히 말하자면 DNN을 활용했으며, 이는 나중에 시간이 되면 설명하도록 하겠습니다.) 요즘 tensorflow 라는 라이브러리 때문에 (덕분에?) 더욱 구현이 편리해져 유명해지고 있습니다.


- 유전자 알고리즘은 아주 예엣~날부터 전해져 내려오는 알고리즘으로, 말 그대로 생명체의 유전자처럼 진화해 나아가는 알고리즘입니다. 유투브에 이에 관한 매우 유명한 영상이 있으니 한번 확인해보세요. 바로가기 이외에도 다양한 영상에서 게임의 AI를 만들 때에 사용됩니다. 가끔 RNN을 사용한 경우와 유전자 알고리즘을 사용한 경우를 혼동하시는 경우가 있던데, 부디 그러지 말아주세요.




저는 처음에 1번 방법을 생각해 보았으나, 즐겁게 게임을 하고 싶다는 목표와 달리 수학문제를 푸는 느낌을 강하게 받아서 일단 접어두었습니다. 그리고 2번을 보았으나 2번은 training data가 필요하기 때문에 포기했습니다. 그래서 결국 3번을 활용하여 이 게임을 돌려보기로 마음먹게 되었습니다. 물론 하다가 잘 안되면 1번을 사용하게 될 것 같습니다. 이 포스팅은 다 끝나고 정리하는 것이 아니라 말 그대로 재미로 하는 프로젝트이기 때문에 일 진행과 동시에 포스팅이 올라올 것입니다. 즉, 하다가 망하면 중간에 방향을 틀 수도 있다는 것입니다.




자, 그러면 어떻게 할 것이냐....하면,


우선 input data 를 어떻게 줄 것인지, 이 input data를 통해 몇개의 output data 를 만들 것인지를 결정해야 했습니다. 아래는 제가 결정한 값입니다.



1. 남은 재굴림 횟수 != 0 인 경우:


input : 주사위 5개의 눈금, 13가지 역들의 이전 점수 기록 여부, 현재 몇 라운드에 있는가 => 총 19개

output : 주사위 5개 각각을 고정해야 할지 여부 (값을 반환하고 threshold 를 넘는지 여부로 판단) => 5개


여기에서 현재 몇 라운드에 있는가 하는 input 은 사실 상 13개의 역 중에서 선택할 수 있는 역의 수와 동일하기 때문에 넣을 필요가 없습니다. 하지만 저는 게임을 플레이 해 보면서 이 값 자체가 상당히 중요하다는 것을 느꼈기 때문에 그냥 하나 더 넣었습니다.



2. 남은 재굴림 횟수 == 0:


input : 주사위 5개의 눈금, 13가지 역들의 이전 점수 기록 여부, 현재 몇 라운드에 있는가 => 총 19개

output : 13개의 역 중에서 선택해야 할 것. 이것 또한 값으로 나온 것을 높은 순서대로 실제로 고를 수 있는가와 비교해서 고를 것입니다. => 13개



즉, 크게 두 가지를 만들어야 할 것 같습니다. 하지만 어차피 이 둘(정확히는 셋)이 하나의 gene을 이룰 것이기 때문에 별로 문제는 없습니다.




저는 코딩의 재미를 추가함과 동시에 조금의 예상치 못함?을 추가 하기 위해 중간에 hiddden layer 하나를 삽입하기로 마음 먹었습니다. 물론 이것의 개수는 물론, 각 layer의 node 개수도 본래 생각을 해서 결정해야 하지만, 저는 그냥 쉽고 적당히 node 10개의 단일 hidden layer를 넣기로 했습니다. 이게 학술 논문을 위함도 아니고 말이죠.


실제로 가끔 결과물의 cherry picking 이라던가 이렇게 어물쩍 넘어가는 구간들이 있을 수 있다는 점 미리 알아주시고 양해 바랍니다. 특히 machine learning 쪽의 프로그램들은 제 기량 부족으로 가끔 거의 랜덤에 가까운 결과들이 나오는 경우가 있어, 이들은 아마 따로 묶어서 별도로 올리던가 할 꺼 같습니다;; 일단 최고의 가치인 "재미"를 망치지 않는 선에서 진행하겠습니다.


** 학술 논문과 같은 공식적인 곳에서는 이렇게 하지 않겠습니다.






자 그러면 현재까지 완성된 모양을 한번 봅시다.



1. 남은 재굴림 횟수 == 1,2번


(19개의 input) => (첫 번째 뉴런) => (10개의 node를 가진 hidden layer) => (두 번째 뉴런) => (5개의 output)




2. 남은 재굴림 횟수 == 0번


(19개의 input) => (첫 번째 뉴런) => (10개의 node를 가진 hidden layer) => (두 번째 뉴런) => (13개의 output)



물론 이 사이 사이에 게임의 진행 부분이 있습니다. 예를 들어 1번에서 나온 output을 통해 고정할 주사위를 결정한 뒤에는 주사위를 다시 random (정확히는 randint) 함수를 사용해서 굴리는 과정 등이 있을 것입니다.





그럼 다음 포스팅부터는 본격적으로 만들어 보기 시작하겠습니다.





P.S. 간단하게 필요한 변수 개수를 계산해보니 850개 정도가 나오는 듯 합니다. ㅎㄷㄷ 어차피 제가 계산할 건 아니지만 이런걸 해내는 컴퓨터가 신기할 따름입니다.

+ Recent posts