Lisp로 주문 외기 - 9 -
2009-05-25게임의 특별한 동작 만들기
이제 완성까지 딱 하나만 더 하면 됩니다. 플레이어가 게임을 끝내기 위한 특별한 동작을 좀 더하는 거죠. 첫 번째 명령은 플레이어가 쇠사슬을 다락방에 있던 양동이에 용접하는 게 될 겁니다.
(setf chain-welded nil)
(defun weld (subject object) (cond ((and (eq location ‘attic) (eq subject ‘chain) (eq object ‘bucket) (have ‘chain) (have ‘bucket) (not chain-welded)) (setf chain-welded ’t) ‘(the chain is now securely welded to the bucket.)) (t ‘(you cannot weld like that.))))
그러니 일단 이미 행동을 했는지 안했는지 알려주는 새 전역변수를 만듭시다. 다음에, 용접할 수 있는 상황인지 확인하고 용접할 수 있게 해 주는 용접 함수를 만들어 봅시다.
새 명령을 시험해 볼까요.
(weld ‘chain ‘bucket)
==> (YOU CANNOT WELD LIKE THAT.)
이런… 양동이나 쇠사슬이 없군요. 그렇죠? 근처에 용접기도 없구요. …아 그래요..
그럼 이제 쇠사슬과 양동이를 우물에 집어넣는 명령을 만들어 볼까요?
(setf *bucket-filled* nil)
(defun dunk (subject object)
(cond ((and (eq location ‘garden)
(eq subject ‘bucket)
(eq object ‘well)
(have ‘bucket)
chain-welded)
(setf bucket-filled ’t) ‘(the bucket is now full of water))
(t ‘(you cannot dunk like that.))))
주의를 기울였다면 이제, 이 명령이 용접 명령과 흡사하다는 걸 알아챘을 겁니다. 두 명령은 위치, 대상, 조건을 검사할 필요가 있습니다. 하지만 둘은 다른 점이 충분히 많아서, 비슷한 부분을 하나로 묶을 수가 없습니다. 슬프군요…
…하지만 이건 Lisp니까, 그냥 함수를 쓰는 것보단 더 많은 일을 할 수 있어요. 주문(SPEL)을 욀 수 있죠! 아래의 주문(SPEL)을 만들어 봅시다.
(defspel game-action (command subj obj place &rest rest)
`(defspel ,command (subject object)
`(cond ((and (eq *location* ',',place)
(eq ',subject ',',subj)
(eq ',object ',',obj)
(have ',',subj))
,@',rest)
(t '(i cant ,',command like that.)))))
이 주문 (SPEL)이 얼마나 흥미로운 복합체인가 보세요. 무지 많은 이상한 따옴표, 역 따옴표, 콤마, 다른 이상한 기호들이 있지요. 이건 보통 주문이 아니라 실제로 다른 주문(SPEL)을 외는 주문이에요! 숙련된 Lisp 프로그래머라도 이런 괴물 같은 걸 만들어내려면 좀 생각을 해야 합니다. (그리고 사실 이런 주문(SPEL)은 고상하지 못한 걸로 생각하고, 좀 더 난해한 단계들을 더 거쳐서 더 잘 돌아가는 걸 만들테지만, 여기서 신경쓸 일은 아니죠…)
이 주문(SPEL)의 요점은 여러분이 이런 주문들을 다룰 수 있다면, 얼마나 교육받았고 똑똑한지 알려줄 수 있다는 겁니다. 거기다, 이걸 단 한번만 쓰고서, 더 큰 어드벤처 게임을 위한 몇 백개의 명령을 한 번에 만들 수 있다면, 모양새 나쁜 건 문제가 아니죠.
자, 그럼 새 주문(SPEL)으로 전에 만든 볼품없는 weld명령을 대체해 볼까요.
(game-action weld chain bucket attic
(cond ((and (have 'bucket) (setf *chain-welded* 't))
'(the chain is now securely welded to the bucket.))
(t '(you do not have a bucket.))))
명령을 얼마나 이해하기 쉬워졌는지 한 번 보세요 -game-action 주문(SPEL)은 기름기없이 정확히 말하고 싶은 것만 쓰게 해 줍니다- 거의 게임 명령을 만들기 위한 컴퓨터 언어를 만든 것이나 다름 없어요. SPEL로 개별 의사 언어를 만드는 것은 특정 도메인 언어 프로그래밍(Domain Specific Language Programming)이라 불리는데, 프로그램을 아주 빠르고 우아하게 짤 수 있는 방법입니다.
(weld chain bucket)
==> (YOU DO NOT HAVE THE CHAIN.)
...아직도 용접하기엔 적합한 상황이 아니군요, 하지만 명령은 제대로 돌아가고 있어요.
다음엔 dunk 명령을 새로 짜 봅시다.
(game-action dunk bucket well garden
(cond (chain-welded (setf bucket-filled ’t) ‘(the bucket is now full of water))
(t ‘(the water level is too low to reach.))))
용접(weld)명령이 어떻게 용접할 물체를 가지고 있는지 검사했는지에 주목하세요, 하지만 dunk 명령은 이 단계를 건너뜁니다. - 새 game-action 주문(SPEL)이 코드를 더 쉽게 쓰고 이해하도록 만들어줬습니다.
이제 마법사에게 물을 쏟아붇는 마지막 코드입니다.
(game-action splash bucket wizard living-room
(cond ((not bucket-filled) ‘(the bucket has nothing in it.))
((have ‘frog) ‘(the wizard awakens and sees that you stole his frog.
he is so upset he banishes you to the
netherworlds- you lose! the end.))
(t ‘(the wizard awakens from his slumber and greets you warmly.
he hands you the magic low-carb donut- you win! the end.))))
게임의 전체 진행을 보려면 여기를 클릭 Lisp프롬프트에 한 번 Copy&Paste 로 끝날 수 있는 소스코드를 보려면 여기를 클릭
이 연습서를 가능한 간단히 만들기 위해, Lisp가 어떻게 작동하는가 하는 많은 세부 사항은 주석 처리되거나 별도 페이지로 넘어갔습니다. 그러니 그 세부 사항이 어떤지 봅시다….
-
Tag
- casting-spels
- 번역
- 결과물
- 공부
- LISP