· KLDP.org · KLDP.net · KLDP Wiki · KLDP BBS ·
Real Time Battle

프로그래밍 학습 도구로서 게임 : Real Time Battle


2005.6.7 현재 RealTimeBattle은 1.0.7으로 판올림되어 있으며 RealTimeBattle Team에 의해서 꾸준히 개선되어가고 있는 중입니다. [http]홈페이지의 Latest News를 참고하시기 바랍니다.



이 글은 리눅스매거진 2002년 7월호에 실린 기사입니다. 기사를 위키로 정리하면서 이때 왜 이렇게 글을 썼는지 부끄러운 마음이 앞서더군요. 2002년 기사를 정리한 것이라서 2004년 12월 현재 RTB 프로젝트가 어디까지 와 있는지, 아직도 활발히 개발이 이루어지고 있는지에 대해서는 전혀 알지 못합니다. 프로젝트에 관심있는 분이 계시다면 이 기사를 더욱 알차게 보완해 주시리라 믿어 의심치 않습니다.

한가지 더! 프로그래밍 실력이 아직 미숙하기 때문에 질문에 대해 원하시는 답변을 해드릴 수 있을지 걱정이됩니다. 형식적으로나마 문서 끝에 질문/답변이 이루어질 수 있는 공간을 마련해 두었습니다.


비전공자로서 프로그래밍에 관심이 많은 독자는 얼마나 될까? 이 중에는 특별히 제2의 도약을 꿈꾸며 프로그래밍을 준비하는 분들도 있겠지만 생계와는 상관없이 순수한 지적 욕구로 프로그래밍을 공부하고 싶어하는 분들도 꽤 있을 것이라는 기대를 해 본다. 정규 교육과정을 통해 배울 수 없는 욕구를 독학으로 채우고 싶어하는 멋진 그대, 그대는 어떻게 공부하고 있는가? 여기 리눅스에서 할 수 있는 프로그래밍 학습 방법으로 그대가 공부하는 방식과는 조금 다른 내용을 소개하고자 한다.

필자 : 신재훈(gunsmoke.shin at gmail.com)

필자, 특별히 프로그래밍을 잘 하는 것도 아니고 프로그래밍으로 밥 먹고 살 일도 없는 것이 사실이다. 하지만 지금 이 글을 보고 있는 독자 여러분들과 마찬가지로 필자는 언제나 배고픈 프로그래머를 꿈꾸며 산다. 나만의 세계를 창조한다는 것, 그만큼 매력적인 일임에 틀림없다. 그러나 지금도 책장에는 아직 다 읽지 않은 프로그래밍 서적들이 줄지어 있고 지난달에 배달된 리눅스 매거진은 아직도 책상 위에서 뒹굴고 있는 신세이다. 이번에 이 일만 끝나면, 초저녁에 잤다가 새벽에 일어나면 꼭 읽어야지 각오를 다지지만 이 험한 세상 하루하루 먹고사는 것도 쉽지가 않다.

1.1. 짧은 예제를 많이 코딩하면 프로그래밍 실력이 향상된다?


게임을 즐기면서 ‘나도 이런 게임을 만들어 봐야지!’하는 맘으로 프로그래밍에 입문한 사람들은 얼마나 많은가? 어릴 적부터 이런 맘을 가지고 아예 전공을 이쪽으로 택했다면 어쩔 수 없지만 비전공자로서 독학으로 야무진 각오를 가지고 프로그래밍 입문서를 샀다면 책에서 제공하는 짤막한 예제부터 코딩하는 것이 시작이다. ‘백견이 불여일타’라는 유명한 얘기도 있지 않은가? ‘Hello World' 문자열 출력하기를 시작으로 구구단 출력하기, 윤달이 섞인 달력 프로그램 만들기, 비디오 대여점에서나 쓸만한 고객관리 프로그램 만들기 등등....

K&R의 ‘C Programming’이 독자 여러분이 지금 보고 있는 리눅스 매거진 정도의 두께밖에 되지 않았음을 생각할 때 800~900 페이지 심지어 1,000 페이지를 거뜬하게 넘는 프로그래밍 입문서의 분량을 차지하게된 주범은 이런 예제들이라는 결론을 내릴 수 있다. 이렇게 짧은 예제를 코딩하면서 프로그래밍을 배울 수 있다는 주장은 마치 영어를 공부할 때 단문 독해를 강요하는 것과 비슷하다. 단문 독해의 맹점은 영어로 생각할 여지를 제공해 주지 않는데 있다. 문맥을 통해 영문을 파악하는 것이 아니라 단어와 단어의 의미만 가지고 해석을 시도하기 때문에 독해력을 키워주는 데에는 한계가 있다. 프로그래밍 입문서가 강요하는 짧은 예제 또한 같은 문제를 가진다.

많이 코딩해 보면 프로그래밍을 더 잘할 수 있다는 주장이 틀린 것은 아니지만 여기에는 프로그래밍을 하기 전에 논리적으로 사고하는 버릇을 들여야 한다는 핵심적인 내용이 생략되어 있다. 물론 이런 부분은 책과 같은 텍스트를 통해서 독자에게 쉽게 전달할 수 없는 것이 사실이다. 프로그래밍 학습에 있어서 무엇보다 중요한 것은 논리적으로 사고하는 습관이다. 어떤 코드를 작성하기 전에 앞서서 이 프로그램이 어떻게 동작할지 머리 속에 그려보는 습관이 무엇보다 중요한 것이다. 당장은 실력이 부족하고 개선하는데 시간이 걸려 답답할지 모르나 논리적으로 사고함으로서 결국 프로그래밍 실력을 향상시킬 수 있으며 결과로 만들어지는 코드의 질을 높일 수 있다.

또한 이러한 류의 예제들은 대부분 여러분을 프로그래밍에 미칠 수 있는 흥미를 제공해 주지는 않는다. 흥미가 없는 학습이라, 독자 여러분의 고3 시절이 어떠했는지에 대해서 더 이상 설명할 필요가 없을 것 같다. Hello World라는 문자열을 모니터에 출력함으로서 ‘와~ 컴퓨터는 굉장히 신기한 기계네! 내가 이렇게 출력하라고 명령하니까 그대로 하잖아!'하며 감탄하던 세대는 이미 지나갔다. 국내/해외의 컴퓨터 산업의 중심에 있는 분들이 바로 그들이다. 여러분은 이미 역치 값이 올라갈 대로 올라가서 3D 화면에 현실을 그대로 재현한 게임쯤 해야 ‘나도 이런 게임이나 프로그래밍 할 수 있으면 좋겠다’고 생각할 것이다.

프로그래밍 학습에 크게 도움이 되지 못하고, 재미없고 따분한 예제들 대신 여러분의 프로그래밍 실력으로 전투용 로봇을 동작하도록 해 보는 것은 어떠한가? 수많은 로봇이 치고 박고 싸우는 Arena(투기장)에서 홀로 살아남아 챔피언이 될 수 있도록 최고의 로봇을 프로그래밍 해 보는 것도 재미있지 않을까?

1.2. 실시간 로봇 전투 게임 : Real Time Battle


전산 전공자를 제외하고 필자처럼 단순 호기심 때문에 리눅스를 설치한 사람들이 가장 먼저 하는 일은 당연히 게임일 것이다. 그러나 X에서 제공하는 기본 게임은 정말로 재미없다! 그렇다고 패키지 게임을 하자니 리눅스용 패키지 게임을 쉽게 구할 수 있는 것도 아니고 이런 게임을 하기 위해 최고급 사양의 머신을 사용하는 것은 낭비라고 밖에 생각할 수 없다.

여기 ‘Real Time Battle’(이하 RTB)이라는 게임이 있다. <그림 1>의 스크린 샷을 보아하니 게임 퀼리티는 X의 기본 게임들이나 그다지 다를 게 없다. 이쯤 와서 ‘뭐야?! 고작 이런 게임이야?!’하고 실망하는 독자들의 원성이 하나 둘씩 들리기 시작한다.

screenshot.jpg
[JPG image (104.77 KB)]

<그림 1> RTB 스크린 샷 ‘이 정도 게임쯤이야~’라고 얕보지 말길

앞서 설명한 바와 같이 RTB는 프로그래밍 게임이다. 사용자가 로봇의 동작을 프로그래밍해서 상대방 로봇을 파괴시키는 단순한 것 같으면서도 결코 단순하지만은 않은(?) 게임이라고 할 수 있다. 여기서 독자들이 오해해서는 안 되는 것이 사용자가 직접 키보드나 마우스를 통해서 로봇의 동작을 컨트롤하는 것이 아니라 프로그래밍 된 대로 움직인다는 사실이다. 따라서 실제 게임이 시작되면 독자가 할 일은 거의 없는 것이나 다름없다. 내가 프로그래밍 한 로봇이 프로그래밍한 대로 잘 싸우고 있는지, 아니면 멍청하게 서 있다가 남의 포탄이나 얻어맞고 있는지 지켜볼 뿐이다. 물론 로봇이 의도한대로 동작하지 않는다면 이를 유심히 관찰했다가 로봇 프로그램을 다시 수정해야할 것이다.

로봇은 캐터필러를 이용해서 이동하고 각각 캐논과 레이더를 장비하고 있다. 대충 <그림 2>와 같은 로봇들이 서로 치고 박고 싸우는 것을 상상하면 된다. 레이더를 사용해 주변 환경을 관찰하며 캐논을 이용해 상대방을 공격하는 형태로 전투가 진행된다. 랜덤 하게 나타나는 지뢰를 피해야 (실재 게임에서는 빨간 점으로 표시된다.) 하고 로봇의 에너지를 올려주는 쿠키를 (실재 게임에서는 푸른 점으로 표시된다.) 먹어야 한다. 사람이 먹는 쿠키를 어떻게 로봇이 먹는지에 대해서는 논의에서 제외한다.

rmv-1-02.jpg
[JPG image (29.01 KB)]

ms-06v.jpg
[JPG image (35.42 KB)]

<그림 2> RTB에 등장하는 로봇들 (이 정도 상상력은 되어야 당신도 로봇 과학자!)

1.3. RTB 설치

RTB의 홈페이지를 방문하면 2000년 10월에 릴리즈 된 1.0.5 버전의 RTB tar볼을 다운받을 수 있다. <그림 3> 벌써 2년이나 지났는데 2.0 버전이 릴리즈 되지 않는 것을 보면 어느 정도 개발이 중지되었을 것이라는 생각도 해 본다. 하지만 그런 게 뭐 대수인가? 이걸 가지고 재미있게 즐길 수만 있으면 되는 것이니...

homepage.jpg
[JPG image (109.1 KB)]

<그림 3> RTB의 홈페이지 (http://realtimebattle.sourceforge.net)

정기적으로 RealTimeBattle Championships 같은 대회도 열리나 보다. 홈페이지의 Competition 메뉴를 클릭하면 2000년 2월에 열린 First Official RealTimeBattle Competition을 시작으로 몇 번의 대회가 있었던 사실이 기록되어 있다. 국내에서도 어느 정도 매니아들이 생긴다면 서로의 로봇을 대전시키는 이벤트 정도는 기대할 수 있을 것 같다.

왼쪽 메뉴의 Download 링크를 클릭하면 RTB를 다운받을 수 있는 페이지로 이동한다. tar.gz 형태와 tar.bz2 형태의 파일 중 편한 것을 다운 받자. tar볼에 SPEC 파일이 포함되어 있으므로 RPM 패키지를 작성하는 것은 가능하지만 홈페이지에서 RPM 패키지를 배포하고 있지는 않다. (데비안 패키지의 경우는 http://packages.debian.org/unstable/games/realtimebattle.html에서 제공하고 있다.)

파일을 다운받았으면 압축을 해제하고 일반적인 빌드 순서에 따라 ./configure → make → make install 명령을 차례로 내리면 된다. 실험 결과 펜티엄 셀러론 300M급 머신에서 담배 한 대 피우는 시간이면 빌드가 끝나는 것을 확인할 수 있었다.
$ tar zxvf RealTimeBattle-1.0.5.tar.gz
$ cd RealTimeBattle-1.0.5
$ ./configure
$ make
# make install

다른 배포판에서는 빌드와 인스톨 과정에서 어떤 문제가 발생할지 잘 모르겠지만 레드햇 리눅스 7.2를 사용하는 필자의 경우는 make 과정에서 문제가 생겼다. 역시나 말도 많고 탈도 많은 gcc 2.96 때문에 이런 것인지 잘 모르겠다. 어쨌든 큰 문제는 아니므로 필자가 해결한 방법을 공개한다. 에러 메시지는 seek_and_destroy.cc 파일에서 strcmp 함수를 사용하는 데서 발생하고 있다.
$ make
...
In file included from seek_and_destroy.cc:22:
../../src/Messagetypes.h:213:8: warning: extra tokens at end of #endif directive
seek_and_destroy.cc: In function `message_to_robot_type 
name2msg_to_robot_type (char *)':
seek_and_destroy.cc:45: `strcmp' undeclared (first use this function)
seek_and_destroy.cc:45: (Each undeclared identifier is reported only 
once for each function it appears in.)
make[3]: *** [seek_and_destroy.o] 오류 1
make[3]: 나감 `/home/GunSmoke/RealTimeBattle-1.0.5/Robots/seek_and_destroy' 디렉토리
make[2]: *** [all-recursive] 오류 1
make[2]: 나감 `/home/GunSmoke/RealTimeBattle-1.0.5/Robots' 디렉토리
make[1]: *** [all-recursive] 오류 1
make[1]: 나감 `/home/GunSmoke/RealTimeBattle-1.0.5' 디렉토리
make: *** [all-recursive-am] 오류 2
$ 

RealTimeBattle-1.0.5/Robots 디렉토리에 있는 같은 기능을 하는 다른 파일을 분석해 본 결과 소스 내에 strcmp 함수를 사용하는데 필요한 string.h 파일을 include 하지 않았음을 발견할 수 있었다. 개발자들도 이런 실수를 하는가 보다.

RealTimeBattle-1.0.5/Robots/seek_and_destroy 디렉토리의 seek_and_destroy.cc 파일을 열어서 다음과 같이 한 줄을 삽입하자.
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <iostream.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
...

같은 방법으로 해결해야할 파일이 두 개 더 있는데 RealTimeBattle-1.0.5/src 디렉토리의 ArenaBase.h 파일과 Robot.h 파일에도 위와 같이 ‘#include <string.h>’를 적당한 위치에 삽입해야 한다. 그런 다음에 RealTimeBattle-1.0.5 디렉토리에서 make를 다시 해 주고 root 권한으로 전환한 뒤 make install 명령을 완료한다. RTB는 기본적으로 /usr/local/games/RealTimeBattle 디렉토리에 설치된다.
$ vi ArenaBase.h
$ vi Robot.h

$ make
# make install

ArenaBase.cc 파일과 Robot.cc 파일이 아닌 ArenaBase.h 파일과 Robot.h 파일을 수정해야한다. 앞의 파일을 수정해 버리면 RTB를 실행할 때 무시무시한 세그멘테이션 오류가 기다리고 있으므로 주의할 것!

1.4. Battle Tournament의 시작

설치가 모두 끝났다면 RTB를 시작해 보자. 터미널에서 ‘RealTimeBattle &'(1.0.7 : realtimebattle)라고 입력하면 RTB 컨트롤 윈도우가 나타난다. 컨트롤 윈도우의 각 버튼에 대한 설명은 <그림 4>와 같다.

controlWW.jpg
[JPG image (9.91 KB)]
<그림 4> RTB의 메인 인터페이스인 컨트롤 윈도우

Options 버튼을 클릭하면 토너먼트가 진행되는 환경을 설정할 수 있다. <그림 5> 이 또한 RTB의 매력 중의 하나로 생각하는데, 옵션을 통해서 전투에 대해 굉장히 다양한 설정을 해 줄 수 있는 것이 재미있다. 로봇의 초기 에너지나 가속도를 설정하는 것부터 시작해서 로봇의 움직임에 영향을 미치는 중력이나 공기저항, 마찰까지 마치 게임을 개발하는데 필요한 물리학 법칙은 몽땅 다 적용해 볼 수 있는 것이다.

지면상 모든 옵션을 다 설명할 수는 없으므로 <그림 5>의 각 탭에 대해 간단한 설명을 하는 것으로 그친다.

Environment : 중력, 공기저항, 마찰력 등 전투 시 환경에 대한 설정을 조절한다. Robot : 로봇에 대한 기본적인 설정을 조절한다. Shot : 사격 반경, 탄환의 속도 등 캐논에 대한 설정을 조절한다. Extra : 쿠키와 지뢰에 대한 설정을 한다. Time : 한 경기 당 소요 시간 등을 설정한다. Windows size : 각 윈도우의 창 크기를 설정한다. Miscellaneous : 그 외 잡다한 설정들을 해 준다.

optionWW01.jpg
[JPG image (32.22 KB)]

<그림 5> 눈이 휘둥그레지는 RTB의 옵션 창. 더욱 재미있는 전투 환경을 만들어 보라

RTB에서는 드래곤볼에 나오는 천하제일 무도회와 같이 로봇끼리 토너먼트 형식으로 전투를 하게 된다. 준비가 되었다면 ‘New Tournament’ 버튼을 클릭하여 로봇들의 배틀 토너먼트를 시작하자. 그러면 토너먼트의 조건을 설정하는 토너먼트 윈도우가 나타난다. <그림 6> 이 창에서 토너먼트에 참여시킬 로봇과 전투의 배경이 되는 Arena를 결정할 수 있다. 가운데 있는 버튼을 이용해서 로봇과 Arena를 추가한다.

RTB에서 로봇 파일은 /usr/local/games/RealTimeBattle/Robot 디렉토리에 위치하는데 컴파일된 파일로서 ‘*.robot’이라는 확장자를 갖는다. rotate_and_fire 로봇과 seek_and_destroy 로봇이 기본적으로 제공되는 로봇이다. 또한 로봇이 전투를 벌이는 Arena 파일은 /usr/local/games/RealTimeBattle/Arena 디렉토리에 ‘*.arena’라는 이름으로 저장된다. 직접 확인해 보라.

tournamentWW.jpg
[JPG image (50.92 KB)]

<그림 6> 선수입장! 토너먼트 윈도우에서는 로봇과 전투를 벌일 Arena을 결정한다.

독자 여러분들은 토너먼트 윈도우의 아래에 있는 Game per sequence 등이 궁금할 것이다. 여기서 sequence란 로봇끼리 한번 싸우는 라운드라고 생각하면 된다. 즉 Game per sequence는 한 라운드에 대한 게임 수를 지정하는 것이고 Robot per sequence는 한 라운드에 싸우는 로봇의 수, Number of sequence는 토너먼트 전체의 라운드 수를 가리킨다. 토너먼트를 시작할 준비가 되었다면 Start 버튼을 클릭한다.

1.5. RTB의 인터페이스


토너먼트가 시작되면 각 라운드의 게임이 순서대로 시작된다. 이때 기본적으로 세 개의 창이 뜨는데 이것이 RTB의 인터페이스의 전부이다. 게임이 시작되면 로봇이 전투를 벌이는 장면을 지켜보고 있다가 원하는 대로 로봇이 움직이지 않으면 수정할 내용을 메모해 두는 정도가 독자 여러분이 해야할 일 일 것이다. (필자와 같이 아케이드 게임에 능숙하지 못한 독자도 복잡한 키 조작이 필요 없다.)

<그림 7>은 Arena 윈도우이다. 실시간으로 벌어지는 로봇의 전투 과정을 지켜볼 수 있다. Zoom 버튼을 이용해서 전투 장면을 확대해서 볼 수도 있다. 앞에서 잠깐 언급한 바와 같이 로봇은 캐터필러를 이용해서 움직이며 주변의 정보를 파악하기 위한 레이더와 적의 로봇을 파괴하기 위한 캐논을 장비하고 있다. (확대해서 보면 더 잘 볼 수 있다.) 로봇은 레이더를 이용해서 랜덤 하게 등장하는 지뢰를 (붉은 점) 피하고 쿠키를 먹어서 (푸른 점) 에너지를 회복한다. 로봇의 상태는 에너지로 표시되는데 당연히 적의 포격을 받으면 에너지가 감소하고 또한 상대방 로봇과 충돌했을 때, 벽에 부딪쳤을 때, 지뢰를 밟았을 때에도 에너지가 줄어든다.

arenaWW.jpg
[JPG image (16.22 KB)]

<그림 7> Arena 윈도우, 캐논과 레이더를 사용하는 로봇의 더욱 자세한 모습을 보고 싶다면 Zoom 버튼으로 화면을 확대해 보라.

<그림 8>은 메시지 윈도우이다. 전투가 시작되거나 종료되었을 때, 적에게 포격 당하고 있을 때, 쿠키를 먹거나 지뢰를 밟았을 때 등 Arena에서 벌어지는 전투 장면이 실시간으로 기록된다.

messageWW.jpg
[JPG image (13.5 KB)]

<그림 8> 메시지 윈도우

마지막으로 <그림 9>은 스코어 윈도우이다. 스코어 윈도우에서 로봇의 에너지를 확인할 수 있는데 로봇의 에너지가 0이 되면 로봇은 파괴된다. Arena에 남아있는 로봇이 1대도 남지 않았을 때, 스코어 윈도우에서 확인할 수 있는 제한된 시간이 경과되었을 때 그 게임은 종료된다. 승리한 로봇은 1포인트가 가산되어 최종 토너먼트에 기록이 반영된다.

scoreWW.jpg
[JPG image (12.27 KB)]

이상 Arena 윈도우와 메시지 윈도우, 스코어 윈도우가 실제 전투가 진행되는 동안 독자가 지켜봐야 하는 메인 윈도우이며 한 전투가 종료되면 컨트롤 윈도우에서 Statistics 버튼을 클릭해서 전투 결과를 다양한 관점에서 정리한 정보를 확인할 수 있다. <그림 10>은 정보를 보여주는 statistic 윈도우이다.

statistWW.jpg
[JPG image (22.04 KB)]

<그림 10> statistic 윈도우 한 경기의 결과를 총체적으로 정리해서 보여준다.

1.6. 최강의 전투로봇을 당신이 직접 프로그래밍 하라


사실 RTB에서 기본으로 제공되는 로봇의 전투를 바라보는 것만으로는 RTB의 즐거움을 절반도 이해하기 힘들다. 역시 RTB의 백미는 직접 전투 로봇을 프로그래밍 해보는 것이다. RTB를 소개하면서 자꾸 로봇 과학자를 언급한 것은 이 때문이다.

로봇 프로그램은 RTB에서 자식 프로세스로 실행되어 표준 입출력 (stdin/stdout)을 통해 RTB 본체와 메시지를 교환하는 방식으로 동작한다. 이것은 마치 네트워크 모델에서 서버 머신과 클라이언트 머신간에 통신하는 방법과 비슷하다. RTB 메인 프로그램은 서버 머신에 해당하며 로봇 프로그램은 클라이언트 머신에 해당한다고 할 수 있다. <그림 11>

howtocom.jpg
[JPG image (16.93 KB)]

<그림 11> RTB 메인 프로그램과 로봇 프로그램이 동작하는 원리

RTB 메인 프로그램과 로봇 프로그램간에 메시지를 교환하는 방식이기 때문에 표준 입출력을(stdin/stdout) 통해서 전달되는 메시지의 형식만 제대로 갖춘다면 로봇 프로그램은 어떠한 프로그래밍 언어를 사용해서 프로그래밍 하는 것이 가능하다. C, C++이나 Java는 물론 Perl이나 PHP 같은 스크립트 언어를 사용해서 로봇을 프로그래밍 할 수도 있다.

메시지 종류나 메시지의 송수신 방법, 기타 로봇을 프로그래밍 하는데 필요한 매뉴얼은 RTB의 홈페이지에 상세히 소개되어 있다. (http://www.lysator.liu.se/realtimebattle/Documentation/RealTimeBattle-4.html) 아쉽지만 지면 관계상 본 기사에서는 매뉴얼의 내용을 모두 소개하지는 않는다. 대신 RTB의 메인 프로그램과 여러분이 제작하는 로봇 사이에 교환되는 메시지를 간단히 살펴본 후, 실제 로봇의 소스에는 메시지가 어떻게 활용되고 있는지 확인하기로 한다. 이를 통해 로봇이 동작하는 방식을 이해하도록 하자.

메시지의 송수신 방법은 표준 입출력을 통해서 이루어진다. 표준 입출력이란 무엇인가? 보통 C에서는 stdin, stdout, stderr 같은 표준 입력, 표준 출력, 표준 에러 파일을 읽기, 쓰기 위해 미리 열어서 제공한다. 이러한 파일을 표준 파일이라고 한다. 데이터를 하나 또는 그 이상의 물리적(스크린이나 프린터, 플로터 등의 컴퓨터에 연결될 수 있는 모든)장치로 지향되는 스트림(stream)의 형태로 나타낸 것이 바로 표준 입출력 파일인 것이다. 스트림을 이용한 표준 입출력 장치는 이들을 처리하는 stdio.h 헤더에 정의되어 있다.

 #define stdin   (&_streams[0])
 #define stdout  (&_streams[1])
 #define stderr  (&_streams[2])

stdin은 표준 입력 장치로 입력을 받아들일 때 파일을 사용하지 않고 scanf()나 getchar() 등을 사용하여 입력을 받아들인다. 이는 보통 사용하고 있는 컴퓨터의 키보드가 된다. 반면에 stdout은 표준 출력 장치로 printf()나 putchar()를 사용하여 출력했을 때 그 출력이 나가는 곳을 의미하며, 이는 일반적으로 사용하고 있는 컴퓨터의 화면이 된다.

결국 로봇의 메시지를 처리하는 것은 fgets() 함수 등을 이용하여 RTB의 메인 프로그램에서 전달되는 메시지를 표준 입력을 통해 받아들이는 일과 printf() 함수 등을 이용하여 로봇이 RTB 메인 프로그램에게 전달할 메시지를 표준 출력을 통해 보내는 일, 이 두 가지로 집약된다. 표준 입출력을 통해 메시지를 처리한다는 말은 바로 이 것을 의미한다.

RTB 홈페이지에 소개된 영문 매뉴얼도 그렇게 어려운 영어로 쓰여있는 것이 아니기 때문에 로봇을 프로그래밍 하기 전에 반드시 읽어볼 것을 권한다.

먼저 RTB 메인 프로그램으로부터 로봇 프로그램에게 전달되는 메시지는 다음과 같다. <표 1> 각 메시지의 옵션에 대한 설명은 생략하니 매뉴얼을 참고하라. 로봇을 프로그래밍 하는 여러분의 입장에서는 RTB로부터 로봇에게 전달되는 문자열을 비교해서 그에 알맞은 처리를 해 주면 된다.

table01.jpg
[JPG image (67.09 KB)]

<표 1> RTB 메인 프로그램으로부터 로봇에게 전달되는 메시지

다음은 로봇으로부터 RTB에 전달되는 메시지이다. <표 2> RTB가 전달하는 메시지에 대해서 이벤트를 설정하고 각 이벤트에 대응하는 동작을 수행하라는 식으로 프로그래밍 한다. 프로그래밍 된 동작을 RTB에 <표 2>와 같은 메시지를 통해서 전달하면 된다.

table02.jpg
[JPG image (42.69 KB)]

<표 2> 로봇으로부터 RTB 메인 프로그램에 전달되는 메시지

메시지의 전체를 소개한 것은 아니지만 이 정도의 메시지를 가지고 충분히 로봇의 동작을 프로그래밍 할 수 있을 것이다.

1.7. Trinity 로봇과 함께 하는 로봇 해부학 실습!!

RTB에서는 로봇을 프로그래밍 하기 위해서 미리 Empty라는 로봇이 준비되어 있다. 이 녀석은 말 그대로 아무것도 프로그래밍 되어 있지 않은 깡통 로봇, 백지와도 같아서 처음 RTB의 로봇을 프로그래밍 하는 우리에게는 부담이 될 수밖에 없다. 무에서 유를 바로 창조하기보다는 이미 만들어져 있는 것을 모방함으로서 기본을 키우는 것이 필요하다고 본다. 그래서 모방은 창조의 어머니라 했던가. 해부학 실습을 하는 마음으로 남이 잘 만들어 놓은 로봇 프로그램을 분석해 보자.

RTB 게임 내에 기본적으로 포함되어 있는 로봇은 모두 C++을 이용해서 제작되었기 때문에 다수의 독자를 고려하여 C를 이용해서 제작된 로봇을 찾아봤다. RTB 홈페이지에 링크되어 있는 Dr. Frost의 로봇 데이터베이스에는 <그림 12> C++, C, JAVA, Perl, PHP 등으로 코딩된 다양한 로봇 프로그램을 확인할 수 있다. 이 중에서 Trinity라는 로봇과 Olivaw라는 로봇이 C로 제작되어 있는데 필자는 ‘어느 로봇이 더 강한가?’의 기준이 아니라 ‘어느 로봇이 더 보기 쉽게 코딩되어 있는가?’의 기준으로 주석이 많이 달려 있고 가독성이 좋게 코딩된 Trinity 로봇을 선정하여 독자 여러분께 소개한다.

mrfrostdatabase.jpg
[JPG image (93.68 KB)]

Trinity 로봇은 아직 부족한 사항이 많다. 목표를 지정하고 그 곳으로 이동하는 알고리즘도 형성되어있지 않고 개발자가 RTB에서 로봇에게 전달되는 모든 메시지를 분석해서 로봇에 적용하고 있는 것도 아니다. (그래서 그런지 실제 전투에서 Trinity가 이기는 꼴을 한번도 못 봤다.) 그러나 Trinity의 코드는 개발자가 코드 하나하나에 주석을 집어넣어 자세한 설명을 해주고 있으며 뒤죽박죽 마구잡이로 코딩되어 있지 않기 때문에 가독성이 좋다. 자세한 설명과 가독성이 높은 코드로 개선의 여지가 많다는 것, 이것이야말로 가장 좋은 프로그래밍 습관일 것이니 프로그래밍을 공부하는 독자 여러분들도 필히 이를 본받도록!

Dr.Frost의 로봇 데이터베이스에서 Trinity.tar.gz 파일을 다운받았다면 적당한 위치에 압축을 해제한다. ‘Trinity.c’ 파일은 Trinity 로봇의 소스 파일이고 ‘Trinity.robot’은 컴파일된 로봇 파일이다. vi나 emacs 등 적절한 에디터를 이용해서 Trinity.c 파일을 분석하라.

Trinity의 소스는 다음과 같이 4개의 함수로 이루어져 있다. 이중 get_angle() 함수는 각도를 구하기 위해서 따로 만들어 놓은 함수에 불과하며 Trinity 로봇의 동작을 제어하는데 사용되는 가장 중요한 함수는 get_message()와 sighandler()이다.

get_angle(){
...
}
get_message(){
...
}
sighandler(){
...
}
main(){
...
}


우선 sighandler() 함수를 살펴보자. 이 함수는 메시지를 처리하는 함수로서 Trinity 로봇의 핵심이 되는 부분이다. RTB 메인 프로그램에서 Trinity 로봇에게 전달되는 메시지를 표준 입력을(stdin) 통해 전달받으면 이 메시지를 get_message() 함수를 호출하여 분석한다. get_message() 함수는 이 메시지를 분석해서 결과 값을 리턴 하는데 이 값을 가지고 그 상황에 적절한 행동을 수행한다. 적절한 행동이란 다름 아닌 Trinity 로봇이 RTB에게 표준 출력을(stdout) 통해 적절한 메시지를 보내는 것을 의미한다. Trinity 소스의 ‘printf("Shoot %f\n",SHOT_MAX_ENERGY/3);’라는 출력 구문은 곧 Trinity 로봇이 사격하는 동작을 RTB 메인 프로그램에게 알리는 문장이 된다.

void sighandler(int sig)
{
...
  while(feof(stdin)==0)
  {
...
    fgets(str,80,stdin);
    /* stdin을 통해서 RTB 메인 프로그램으로부터 전달되는 메시지를 str이라는 배열에 저장한다.
    str 배열에 저장된 메시지는  get_message() 함수를 통해 분석된다.*/
...
    message=get_message(str);
    /*get_message() 함수의 처리 결과 값을 가지고 switch 문을 통해 각 상황에 알맞은 동작을 하도록 한다.*/
...
    switch (message)
    {
      case 10:  /* Robot Info : 2 other robots energy, 0-enemy <> 1-friend */
        if(arg2==0)
        {
'''
          printf("Shoot %f\n",SHOT_MAX_ENERGY/3);
...
          fflush(stdout);
           /*printf()를 이용해서 RTB 메인 프로그램에게 메시지를 전달한 후, fflush(stdout) 함수를 이용해서
           표준 출력 버퍼에 남아있는 메시지를 깨끗이 제거해 주는 것은
           로봇이 메시지를 전달하기 위해 가장 중요한 체크 포인트!*/

        }
        break;
...

get_message() 함수는 RTB 메인 프로그램으로부터 Trinity 로봇에게 전달되는 메시지를 분석하여 결과 값을 sighandler() 함수에 리턴 한다. RTB로부터 RobotInfo 라는 메시지가 포함된 문자열이 전달되면 표준 함수 strtok()을 이용해서 그 문자열을 ‘RobotInfo’와 arg1과 arg2 형식으로 분리한다. 이때 분리된 arg1과 arg2의 값은 곧 RobotInfo 메시지의 옵션 값이 되는 것이다.
int get_message(char *msg)
/*strstr()를 이용해서 문자열 내에 ‘RobotInfo’라는 메시지가 포함되어 있는 지 확인한다.*/
{
  if(strstr(msg,"RobotInfo"))
  {
    strtok(msg," ");
    /*strtok()를 이용해서 문자열을 메시지와 옵션으로 분리한다.
    분리한 옵션의 내용은 arg1과 arg2로 저장된다.*/
    arg1=strtod(strtok(NULL," "),NULL);
    arg2=strtod(strtok(NULL," "),NULL);
    return 10;
  }

이렇게 해서 다시 sighandler() 함수로 리턴된 값은 switch문에 의해서 특정 상황에 대해 동작하게 되는 것이다. sighandler() 함수의 case 5, 즉 Radar 메시지에 대해서 동작하는 코드를 보라. Trinity 로봇은 Radar 메시지를 통해서 레이더의 동작을 정의한다. 레이더의 동작에 대해서 취하는 동작을 정의하기 위해 다시 조건문 if를 사용한 것을 확인할 수 있다.
void sighandler(int sig)
...
      case 5:   /* Radar : 3 distance, object, radar angle */
                /* -> Object: 0 robot, 1 shot, 2 wall, 3 cookie, 4 mine */
                  /*Radar 메시지의 arg1은 로봇과 레이더로 확인된 물체와의 거리,
                  arg2는 레이더로 확인된 물체, arg3는 레이더의 각도를 의미한다.*/
...
/* mine ahead -> activate emp and destroy it */
        if((arg2==4)&&(arg1<5.0)&&(arg3<0.3)&&(arg3>-0.3))
        {
          printf("Shoot %f\n",SHOT_MIN_ENERGY);
          printf("Print Activate EMP\n");
          fflush(stdout);
          break;
        }
...


주석에 나와있는 대로 이 if 문은 지뢰가 접근하고 있을 때 Trinity 로봇이 지뢰를 캐논을 이용해서 파괴하는 동작을 정의한다. if 문의 조건 절은 다음과 같은 문장으로 쓰였다.
        if((arg2==4)&&(arg1<5.0)&&(arg3<0.3)&&(arg3>-0.3))


즉, 레이더로 파악한 물체가 지뢰인 경우(arg2 == 4), 지뢰와 Trinity 로봇간의 거리가 5.0 미만일 때(arg < 5.0), 레이더의 각도가 -0.3 radian에서 0.3 radian 사이일 때 ((arg3 < 0.3) && (arg3 > -0.3)) Trinity 로봇은 지뢰를 사격할 수 있는 상태가 된다. 지뢰를 사격할 수 있는 적정 거리, 적정 각도에 해당한다면 Trinity 로봇은 곧바로 캐논을 이용해서 지뢰를 사격해 버린다. 놀랍지 않은가?

RTB에서 각도는 우리가 일반적으로 알고 있는 Degree 각이 아닌 Radian 각을 사용한다. Radian = Degree * Pi / 360 (여기서 Pi = 3.141592654)

즉, RTB의 로봇은 메시지를 통해서 로봇에게 발생한 이벤트를 파악하고 각 이벤트에 대해 적절한 반응을 프로그래밍 함으로서 동작을 취하게 된다. 그러므로 더욱 다양한 상황에서 다양한 반응을 입력하면 훨씬 똑똑한 로봇, 더욱 강한 로봇을 만들어낼 수 있다.

어떤가? 혹, 자신의 프로그래밍 실력에 비해 로봇 파일의 소스 길이가 너무 부담이 되는가? 앞에서 언급했듯이 필자는 이것 또한 단문독해의 폐해라고 생각한다. 매번 10~20, 30 라인 되는 소스만 코딩하는 단문독해의 한계는 여기까지다. 어느 정도 입문서를 마스터했다면 최소 이 정도의 소스는 무리 없이 분석할 수 있어야 하지 않을까?

덧붙여 리눅스에서 코딩한 소스를 컴파일 하는 방법에 대해서 간단히 설명한다. -o 옵션을 사용해서 *.robot이라는 파일명으로 컴파일하면 다음 경기 때 여러분의 로봇을 Arena에 올릴 수 있다. 로봇 파일이 있어야 할 디렉토리의 위치는 /usr/local/games/RealTimeBattle/Robot 이다. 예를 들어 GunSmoke.c라는 소스를 만들었으면 다음과 같이 컴파일하면 된다.

$ gcc GunSmoke.c -o GunSmoke.robot
$ cp GunSmoke.robot /usr/local/games/RealTimeBattle/Robot

1.8. 고뇌하는 로봇 과학자들을 위하여

로봇을 Arena에 올려 전투를 시작해 보자. 어떤가? 당신이 의도한 바대로 로봇이 움직이는 것을 확인할 수 있는가? 그렇지 않다면 또다시 프로그램을 수정하자. 아, 그전에 반드시 ‘이번에는 이렇게 코딩해 봐야지’하고 생각을 하기 바란다.

책을 통해서 프로그래밍을 익히는 이들이 흔히 저지르는 실수는 아무 생각 없이 예제를 코딩하기만 하는 것이다. 주어진 예제를 충실하게 치기만 해서는 아무 도움도 되지 않는다. 이 예제에서 특별히 주의해서 봐야할 것은 무엇인지, 필자는 무슨 의도로 이 예제를 책에 삽입했는지, 나아가 이 예제를 내 스스로 개선해보는 노력이 반드시 필요하다. 이러한 비판적인 사고의 과정을 통해서야 비로소 당신의 프로그래밍 실력은 향상될 수 있다.

필자도 Trinity 로봇을 수정해서 로봇을 만들어 보았다. 그 중의 하나는 사격할 때에 스타 크래프트의 시즈 탱크처럼 반드시 정지하고서 발사하는 녀석이 있지 않은가 하면 아예 사격을 하지 않는 녀석, 무슨 생각을 하는 것인지 벽 근처에만 가면 계속 회전하면서 나올 생각을 하지 않는 녀석도 있다. 이러한 실수는 RTB의 사격 메커니즘을 제대로 이해하지 못한 데서 비롯된 것이라고 생각한다. 필자 역시 사격 메커니즘에 있어서는 아무 생각 없이 코딩한 듯하다. (단순히 Shoot 메시지를 통해서 쏘면 되는 것이라고 생각했기 때문이다.)

로봇이 제대로 동작한다고 거기서 프로그래밍을 끝내는 것은 부족한 상상력을 가지고 푸념하는 것일 뿐이다. 상대방 로봇을 레이더로 발견하면 사격할 생각은 하지 않고 무조건 도망가는 로봇을 만들어 보는 것은 어떠한가? 혹은 수많은 로봇이 한 Arena에서 집단 난투극을 벌이는 배틀 로얄과 같은 대전을 위해 360。로 회전하며 사격하는 로봇을 만들어 보는 것은 어떠한가? 개선의 여지는 얼마든지 있다.

반드시 전투 과정을 점검하고 원하는 동작을 수행하지 않는 경우, 이를 어떻게 수정해야할 것인지 논리적으로 생각할 것! 그리고 상상력을 동원하여 더욱 강력한 로봇을 만들 것! 이것이야말로 RTB를 통해서 프로그래밍을 학습하는데 꼭 필요한 자세일 것이다.

독자들 중 대부분은 신의 장난감이라고 불리는 레고 블록을 한번쯤은 가지고 놀아봤던 경험을 가지고 있을 줄 안다. 최근에 레고 시리즈 중 Mind Storm 시리즈가 출시되었다. <그림 13> 레고 블록을 가지고 로봇을 만들고 사용자가 직접 컨트롤러를 직접 프로그래밍 해서 동작하게 만든 시리즈로, 로봇 과학자를 꿈꾸는 어린이들의 동심을 자극하는 흥미로운 물건이다. 필자 역시 경제적인 여건이 허락한다면 구입하고 싶다.

mindstrom2.jpg
[JPG image (8.25 KB)]

RTB는 Mind Storm 시리즈와 비슷한 면을 가지고 있다. 둘 다 프로그래밍을 학습하는데 좋은 학습도구가 될 수 있을 것이다. 단지 Mind Storm은 현실에서 로봇을 움직여 보는 것이고 RTB는 모니터 속에 추상화된 로봇을 지켜봐야 하는 점이 다를 뿐이다. 그러나 필자는 현실에서 동작하는 로봇을 프로그래밍 하는데 따르는 어느 정도의 제약이 따르기 때문에 RTB가 더욱 재미있을 것이라고 생각한다. 그만큼 RTB를 통해서 무한한 프로그래밍의 상상의 나래를 펼 수 있다.

프로그래밍은 물론 어떠한 것을 학습하는데 가장 중요한 것은 학습자의 흥미이다. 교육계에 종사하는 필자가(아직 예비교사에 불과하지만) 프로그래밍을 학습하는데 RTB와 같이 창의적이고 흥미 있는 학습도구를 사용하는 것은 기존의 프로그래밍 학습 패러다임을 뒤엎는 놀라운 일이라고 생각한다. 프로그래밍을 처음 시작한다면 재미없는 남의 예제만 죽어라 코딩하다가 지쳐버리지 말고 위와 같은 것으로 재미를 느낄 수 있기 바란다.

Arena에서 살아남는 최고의 로봇을 C, JAVA, C++ 같은 다양한 프로그래밍 언어로 코딩해 보라. 어느새 한 걸음 성장한 여러분의 프로그래밍 실력을 느낄 수 있을 것이다.

1.9. 질문? 그리고 답변

여기에! 기사와 관련해서 질문해 주세요 -- GunSmoke

오. 이런것이 있었군요. 그런데.. 배틀 서버로 접속할 수 없나요? infiniterun -- infiniterun 2004-12-29

올리시느라 고생많이 하셨겠네요.... 고맙습니다.... -- Tolchi 2004-12-29

이런것도 있었군요..ㅎㅎ당장해봐야겠당!!~ㅎㅎ수고하셨습니다. -- root84 2005-07-03

database에서 다른 사람들이 만든 robot프로그램 좀 받아 보려했더니, 없던데..;;; 혹시 아시는 분?? -- mosaick 2005-07-05

와 재밌는게 있네요. 게임의 중독으로 무장했지만 프로그래밍에 대한 흥미를 유발시키는군요. 영어가 안되다 보니 음...좀 힘드네요 ㅠ -- 그냥 2005-10-27

captcha
Username:

ID
Password
Join
Don't be overly suspicious where it's not warranted.


sponsored by andamiro
sponsored by cdnetworks
sponsored by HP

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2005-10-27 11:39:37
Processing time 0.0133 sec