삼목놀이용 인터프리터는 다음과 같이 구성되어 있습니다.
㉮ 메모리
36개의 bool변수 배열을 사용합니다. 이중 0~26부분은 현재 보드 상태를 입력하는데 사용합니다.
Set이나 Reset, If 등 메모리를 참조하는 연산은, [해당 명령의 arg % 36]의 메모리를 참조합니다.
㉯ 출력
출력은 9채널의 float배열을 사용합니다. 마찬가지로 [Stream 명령의 arg % 9]의 배열에 출력합니다.
0 | 1 | 2 |
3 | 4 | 5 |
6 | 7 | 8 |
만약 5번출력이 10, 7번출력이 30이라면 25% 확률로 5번칸에, 75%확률로 7번에 돌을 놓습니다. 물론 모든 출력이 0 이하라면 아무 곳에도 돌을 놓지 않습니다.
㉰ 프로그램
초기 프로그램의 길이는 1024개 길이로 랜덤의 Instructor와 Argument로 구성합니다.
이와 같은 Interpreter 4096개를 만든 후 그들 사이에 가상의 삼목게임을 반복합니다.
㉱ 적응도 계산
적응도 계산에는 승패보다 먼저 규칙습득을 우선했습니다. 돌을 어디에 놓을지 결정 못하거나(모든 Stream채널 0 이하) 이미 돌이 놓인 곳에 다시 돌을 놓는다면 1000점 감점(적당한 곳에 놓는다면 1000점 가산), 그리고 승패가 나면 100점 가산/감산을 하도록 했습니다.
㉲ 재생산
적응도에 따라 앞에서 설명한 교차와 돌연변이를 통해 새로운 세대를 만듦니다.
㉳ 결과
삼목놀이란 것이 원래 승패가 없는 게임입니다. 제대로 놓는다면 무승부가 나올 수밖에 없는 게임이죠.
이와 같은 식으로 약 400세대 진행시켜본 결과입니다(실은 실수로 컴퓨터를 끄는 바람에 중간에 멈췄어요...ㅜㅜ)
매 세대마다 편차가 심해, 알아보기 쉽도록 적당히 보정한 그래프입니다.
보시다시피 No Decide(어디에 둘지 결정 못함)는 전체적으로 거의 없습니다. 왜냐하면 Stream명령어를 다른 명령어보다 많이 넣었거든요.
하지만 DoubleStone(이미 돌이 있는 곳에 또 놓음)은 서서히 줄어듧니다. 마찬가지로 Win/Lose 역시 증가하다가 감소하죠.
결국 세대가 증가할수록 제대로된 AI가 만들어짐을 알 수 있습니다.
다만 삼목처럼 손으로 만들면 1,20분이면 될 AI도, 제대로 만들어지려면 며칠이 걸린다는 것이 함정...ㅡㅡ
댓글 없음:
댓글 쓰기