아주 어릴 적에 슈퍼마리오를 플레이한 적이 있다.
당시에는 그저 빠르게 깨는 방법에만 몰두해서 각종 비밀 루트를 꿰고 다녔었다.
1탄 -> 4탄 -> 8탄으로 가는 루트는 아직도 기억이 난다.
각설하고, 슈퍼마리오1은 닌텐도에서 만든 고전 명작 게임이라고 할 수 있다.
준비물: VirtualNES, Super Mario 1 ROM, CheatEngine, Pycharm
슈퍼마리오를 플레이하는 AI를 만들 수 있을 까?
아직은 잘 모르겠다.
전처리에 기하는 노력과 인공지능의 복잡도는 반비례관계라고 할 수 있다.
전처리를 열심히 하면, 간단한 네트워크만으로도 인공지능을 만들 수 있다.
반면, 전처리 없이 raw 데이터를 가지고 네트워크를 만들어야한다면 네트워크 구조와 깊이가 상당히 복잡해야한다.
고전 컴퓨터 비전에서는 전처리에 상당한 노력을 기울였으나, 딥러닝의 발전으로 대부분 raw 이미지를 처리할 수 있도록 하는 것이 요즘 유행이다.
하지만, 나는 전처리를 열심히 하는 편이다. 인공지능을 딥러닝으로 복잡하게 짜는 것은 좋지만 간지도 안나고 학습도 매우 오래걸리기 때문이다.
아, 추가적으로 딥러닝이 만능은 아닌게, 너무 많은 데이터를 대령해야한다. 이건 좀 귀찮다.
전처리를 시작해보기전 플레이를 한번 해보자.
어떻게하면 가장 간단하게 이 씬을 압축할 수 있을까???
화면은 256x240 으로 딥러닝으로 이미지 처리하기에는 적당한 싸이즈이긴 하다.
하지만 실제 이미지와 달리 이미지 자체가 매우 단순한 구조로 이루어져 있기 때문에 256x240 을 인풋으로 사용하기엔 아쉽다.
더 줄여보자.
고전게임의 재밌는 특성 중 하나는, 게임의 용량이 극단적으로 작다는 점이다.
과거에는 게임 저장 장치의 용량이 매우 작았으므로 저장효율을 극대화하여 게임 코드 및 이미지들을 저장해야했다.
대표적인 방법으로는, 팔레트를 사용하는 방법과, 패턴을 이용하는 방법이 있다.
1. 팔레트
NES 게임에서는 이미지의 각 픽셀을 RGB로 저장하지 않는다. (물론 다른 고전 게임들도)
대신, 특정 색상들의 조합인 팔레트를 이용하여, 팔레트를 미리 지정해놓고 특정 색상을 팔레트에서 가져오면 된다.
예를 들어, RGB 값(124,54,39)라는 색상을 가져올 때, 1번 팔레트의 5번 색상을 지정하는 식으로 가져올 수 있는 것이다.
위와 같이, NES 에서는 한 화면을 구성하는 모든 색깔을 32개의 색상을 가진 팔레트에서 가져온다. 팔레트의 색상 자체는 달라질 수 있다.
2. 패턴
이미지들을 조각으로 나누어 최대한 재활용한다.
자주쓰이는 이미지 조각들을 패턴으로 저장하고 이를 조합하여 하나의 완성된 캐릭터, 배경, 물체 그림들을 완성한다.
위 처럼, 한 화면은 수십개의 패턴 조합으로 이루어져 있음을 알 수 있다.
약간의 뇌피셜이 조금 첨가되어있지만, 대체로 맞을 거라고 확신한다.
VirtualNES에서는 위와 같이 패턴과 팔레트 뷰어를 제공한다. 하지만 우리가 원하는 씬의 정보는 한낱 픽셀의 색상 정보같은 것이 아닌 실제 캐릭터의 위치, 장애물, 몬스터의 위치, 땅의 위치라고 볼 수 있다.
운이 좋게도, VirtualNES에서는 메모리 뷰어라는 것을 제공한다.
메모리뷰어는 VirtualNES 프로그램이 RAM에 할당되는 영역을 보여준다
모든 프로그램은 프로세스라는 형태가 되어, 가상메모리에 할당된다.
알다시피 프로그램은 이진수로 이루어져있고, 각 주소에 바이트라는 단위로 저장된다.
메모리 뷰어에서는 각 주소에 할당 되어있는 값들을 16진수로 보여주고, 오른쪽에는 해당 값을 ASCII 코드 문자로 변환한 것을 보여준다.
치트 엔진에서는 메모리내의 어떤 주소 값이 어떻게 변화하였는 지를 검색하게 해서 특정 값들의 주소를 찾아 준다.
원하는 값들의 주소를 찾게되면, 목숨을 무한개로 만드는 건 식은 죽 먹기다.
지금부터 할 일은 그런 허접한 단일 값 주소 찾기 놀이가 아니다. (물론 필요하지만)
창을 크게 해서 많은 메모리를 한번에 보도록 하자.
수많은 숫자들의 향연에 정신을 잃을 것 같으니 관심법(?)을 쓰도록 하자..
짐이 보아하니 주소 0800이후로는 숫자들이 변하지 않네...
0800 이후로는 게임 코드와 패턴, 팔레트 등 정적 정보를 저장하고 있을 것이고 0800 이전 영역은 게임을 플레이함에 따라 빠르게 변화하고 있을 것이니 동적 할당이 된 힙 영역일 것이야...!
우리가 원하는 부분은 게임의 씬을 가져오는 것.. 게임의 씬은 계속 변하니까 힙영역(0800 이전)에 있겠지??
숫자 54 두 줄로 이루어진 영역이 수상하다..
게임 씬에서도 두줄로 이루어진 게 있을까?
!!!
땅을 이루는 블럭이 두 줄이니까 54가 땅을 뜻하고 저기 주변의 메모리값은 현재 화면 상태를 보여주는 것이 확실해!!(뇌피셜)
마리오가 점프하거나 몬스터가 기어다닐때 해당영역의 값들은 전혀 변하지 않았다. 따라서, 땅, 벽돌 등 변하지 않는 정적 정보를 저장하는 부분인 것이다.
VirtualNES에서 제공하는 네임테이블 뷰어라는 걸 보면 마리오와 움직이는 물체들은 보이지 않는다.
네임테이블 뷰어가 위 메모리 영역을 참조하는 것 같다.
정적 정보도 중요하지만 마리오의 현재 위치는 어디고 돌아다니는 물체들의 위치는 또 어딘지 알고 싶다.
2부에서 계속...
'기타 잡 코딩' 카테고리의 다른 글
슈퍼마리오 1을 플레이하는 AI를 만드는 방법(4) (1) | 2021.07.11 |
---|---|
슈퍼마리오 1을 플레이하는 AI를 만드는 방법(3) (0) | 2021.07.10 |
슈퍼마리오 1을 플레이하는 AI를 만드는 방법(2) (0) | 2021.07.09 |
폴란드 테트리스를 플레이하는 AI를 만드는 방법(2) (0) | 2021.07.06 |
폴란드 테트리스를 플레이하는 AI를 만드는 방법 (0) | 2021.07.04 |