2009. 5. 18.

LISP으로 어드벤쳐 게임을... 4장. Floor Plan

4장에서는 실제 지도를 만드는 법에 대해서 살펴본다.



해당하는 이미지는 아래 링크에서 가져올 수 있다.

http://www.atariarchives.org/adventure/picture04-1.gif

그럼 해당하는 지도를 보면..

이런 식이다. 각 방은 지정된 다른 방으로 이동할 수 있는 문이 있다.
이것을 일련의 리스트로 분류해보면 다음과 같다.

1번 방은 동쪽으로 3번, 남쪽으로 2번방과 연결되어 있다. 즉 북/남/동/서에 따른 리스트로 보면..

(0 2 3 0)


이라고 쓸 수 있다. 편의상 0은 막혔다고 가정해본다.
이런 식으로 5번방까지를 모두 리스트로 표시하면

'((0 2 3 0)
(1 0 5 0)
(0 4 0 1)
(3 5 0 0)
(4 0 0 2))

로 표현할 수 있다. 여기에서는 베이직 코드를 가급적 1:1로 LISP으로 변환하는 중이니 일단 딴지는 금물..

이제 각 방과 각 방의 문이 어디로 통해지는지를 LISP코드로 작성하면..


(defvar *map*
'((0 2 3 0)
(1 0 5 0)
(0 4 0 1)
(3 5 0 0)
(4 0 0 2)))

(defun get-room (which)
(cond ((< which 1)
(error "방코드가 1보다 작습니다."))
(t
(nth (- which 1) *map*))))

(defun get-direction (dir)
(cond ((string= dir "north") 0)
((string= dir "south") 1)
((string= dir "east") 2)
((string= dir "west") 3)
(t
(error "지원되지 않는 방향입니다."))))

(defun get-door (room dir)
(nth (get-direction dir) (get-room room)))
이제 기본적인 방을 돌아다닐 수 있다.
개별적인 방의 door를 얻어 이를 문장으로 표현해보면 다음과 같다.



<br />(defun desc-door (door)<br />  (cond ((= door 1) "북쪽으로 가는 문이 있습니다.")<br />		((= door 2) "남쪽으로 가는 문이 있습니다.")<br />		((= door 3) "동쪽으로 나갈 수 있습니다.")<br />		((= door 4) "서쪽으로 가는 문이 열려 있습니다.")))<br /><br />(defun desc-room (room)<br />  (let ((which-room (get-room room)))<br />	(format t "당신은 ~A번 방에 있습니다.~%" room)<br />	(labels ((iter (room)<br />			   (cond ((null room) '())<br />					 (t<br />					  (let ((room_text (desc-door (car room))))<br />						(cond ((not (null room_text))<br />							   (format t "이 방에는 ~A~%" (desc-door (car room))))))<br />					  (iter (cdr room))))))<br />	  (iter which-room))))<br /><br />
이 된다.

이제 마지막으로 방을 돌아다니는 코드를 입력하자.


<br /><br />(defvar *current-room* nil)<br /><br />(defun goto-room ()<br />  (format t "몇번 방으로 가시겠습니까?:")<br />  (setf *current-room* (read))<br />  (desc-room *current-room*))<br /><br />(defun goto-door ()<br />  (format t "어느 방향으로 가시겠습니까?(N[orth]/S[outh]/E[ast]/W[est]:")<br />  (let ((direction (read-char)))<br />	(let ((room (get-door *current-room*<br />						  (cond ((char= direction #\n) "north")<br />								((char= direction #\s) "south")<br />								((char= direction #\e) "east")<br />								((char= direction #\w) "west")))))<br />	  (cond ((= room 0) <br />			 (format t "그쪽은 막혔습니다."))<br />			(t<br />			 (setf *current-room* room))))))<br />


댓글 없음:

댓글 쓰기