Tour de IOCCC: 1994/westley
#if O
main(){}
#else
#if rop&onut&((own&rain)|warf)
#include " The orc scrambles to the drain, trying to get the donut; you run out the door and escape! The End "
#else
#if escribe
#if ocument
#include " It reads: Depress Dotted Dog "
#else
#if oor
#include " The door is decorated with relief figures of various dog breeds "
#else
#if rain
#include " Through the drain you see a dwarf in another cell "
#else
#if warf
#include " The gnarled dwarf looks thirsty "
#else
#if ungeon|ebris
#include " You notice a desk, a phone, and a phone directory among the clutter "
#else
#if esk
#include " There are some dimes on the desk "
#else
#if irectory
#include " It reads: Pixie's Pub - instant service - Dial DUNgeon0614 "
#else
#include " You notice nothing unusual "
#endif
#endif
#endif
#endif
#endif
#endif
#endif
#else
#if ial&UNgeon0614
#include " Pixie takes your order, and magically, the room is filled with banana daiquiris "
#endif
#if rink&aiquiri
#include " As you drink, a voice from below says 'Could you drop one down here?' "
#endif
#if rop&aiquiri
#if warf|own
#include " The dwarf eagerly accepts the drink. 'Thanks! Here, I found this, but I can't understand it.' He hands you a document "
#else
#include " You drop the drink on the floor "
#endif
#endif
#if epress&(almatian|almation)
#include " As you press the dalmatian figure, the door opens - only to reveal a menacing orc by a vending machine (with a sign reading 'DEPOSIT MONEY') "
#endif
#if eposit&(ime|imes)
#include " Donuts spill out; you get some, the orc hungrily eats the rest "
#endif
#if rop&onut
#include " The orc quickly eats the donut; he still bars the way "
#endif
#if rop+epress+ime+eposit+rink+aiquiri+onut==1
#include " Be more specific "
#endif
#include " You are in a debris-filled dungeon; a door bars the way, and sludge trickles into a floor drain "
#endif
#endif
#endif
심사 위원이 힌트에 써 놓았듯이, 모든 컴파일 에러가 나쁜 건 아닙니다.
뭘 하는 프로그램인가?
먼저 사용하고 있는 터미널의 가로 크기를 80칸으로 바꾸고, 혹시 탭 크기를 수동으로 설정할 수 있다면 8칸으로 고칩니다. 이것은 이 프로그램을 즐기기 위해 꼭 필요합니다. (뭐 설정하지 않아도 내용은 볼 수 있지만 보기 그렇게 좋진 않습니다.)
먼저 이 프로그램을 컴파일해 봅니다.
$ gcc westley.c
westley.c:87:195: error:
You are in a debris-filled
dungeon; a door bars the
way, and sludge trickles into
a floor drain
: No such file or directory
...웬 메시지랍니까? 무슨 파일이 없다는 건 확실한데 어떤 파일인지는 모르겠고 뭔가 메시지가 튀어 나왔네요. 해석하면,
당신은 파편(debris)들로 차 있는 지하 감옥(dungeon)에 있습니다. 나가는 길은 문(door)으로 막혀 있고 진창이 바닥의 배수구(drain)로 떨어져 내리고 있습니다.
뭔지 감을 못 잡으신 분을 위해서 다른 옵션으로 컴파일해 보겠습니다. 이 프로그램은 매크로를 통해 소통합니다.
$ gcc westley.c -Describe -Door
westley.c:36:132: error:
The door is decorated with relief
figures of various dog breeds
: No such file or directory
해석하면,
문(door)은 다양한 개(dog) 모양이 새겨져 장식되어 있습니다.
바로 텍스트 어드벤처 게임입니다! "문을 설명하여라"(Describe Door) 같은 식으로 키워드를 넣으면 거기에 따라 반응하는 것입니다. 키워드를 넣을 때 사용하는 -D...
는 매크로를 선언하는 컴파일러 옵션으로, 다른 말로 하면 모든 키워드는 모두 D로 시작하게 됩니다.
어떻게 동작하는가?
이 프로그램의 구조는 간단합니다. 매크로가 설정된 방법에 따라서 서로 다른 #include
문을 수행하고, 그 와중에 에러가 나는 것이지요.
-Door
와 같이 선언된 매크로의 기본 값은 1
입니다. (이 때 주의할 점은 이 매크로의 "이름"은 oor
이라는 것입니다.) 한편 if
에서 선언되지 않은 매크로를 참조하려고 할 경우 그 값은 0
이 됩니다. 따라서 예를 들어 -Drop -Donut -Dwarf
같은 옵션을 줬을 경우, 다음 #if
문은:
#if rop&onut&((own&rain)|warf)
rop
이 1, onut
이 1, own
과 rain
이 0, warf
가 1로 평가되어, 최종적으로 전체 조건은 1이 됩니다. 매크로가 없다고 에러가 나는 게 아닙니다. (한편, 이렇게 할 경우 "0으로 선언된" 매크로와 선언되지 않은 매크로를 구분할 수 없다는 문제도 있습니다. 이를 위해서 defined x
수식은 선언된 매크로에 대해 항상 1을 반환합니다.)
한편 #include
문은 80칸에 맞춰서 쓰여진 텍스트입니다. 예를 들어 위 #if
바로 뒤에 있는 문장은 다음과 같습니다. (탭은 »
로 표기했습니다.) 아 이거 스포일러인가요?
#include "»»»»»» »»»»»»»»»» The orc scrambles to the drain,»»»»» trying to get the donut; you»»»»»» run out the door and escape!»»»»»»» »»»»»»»»»» » The End»»»»»»»» »»»»»»»»»» "
혹시나 이런 이름의 파일을 만들 수 있다면 이 프로그램은 좀 더 황당한 결과를 낼 수 있을 지도 모릅니다만... 설마 없을 거라 생각합니다.
그럼 한 가지 의문이 남습니다. 사용자로부터 컴파일 도중 프로그램을 입력받도록 하는 1988/spinellis 이후로 컴파일은 기본적으로 자동으로 가능해야 한다는 조항이 추가되었습니다. 이 프로그램은 1994년 출품작인데 어떻게 컴파일되지 않는 프로그램이 수상한 걸까요? 사실 이 코드는 맨 위에 다음과 같은 main 함수를 포함하고 있습니다.
#if O
main(){}
#else
/* ... */
#endif
이 코드는 -DO
옵션을 주었을 때만 컴파일되고, 아무 일도 하지 않습니다. 물론 Makefile에도 -DO
옵션이 들어 있지요. 은근슬쩍 규칙을 지키는 셈입니다.
스포일러!
영어로 되어 있어서 이 게임을 즐기기가 좀 뭐하신 분을 위해서 한 번 제가 직접 플레이해 봤습니다. 스포일러니까 직접 해 보실 분은 보지 마세요.
$ gcc westley.c
westley.c:87:195: error:
You are in a debris-filled
dungeon; a door bars the
way, and sludge trickles into
a floor drain
: No such file or directory
당신은 파편(debris)들로 차 있는 지하 감옥(dungeon)에 있습니다. 나가는 길은 문(door)으로 막혀 있고 진창이 바닥의 배수구(drain)로 떨어져 내리고 있습니다.
$ gcc westley.c -Describe -Door
westley.c:36:132: error:
The door is decorated with relief
figures of various dog breeds
: No such file or directory
문(door)은 다양한 개(dog) 모양이 새겨져 장식되어 있습니다.
$ gcc westley.c -Describe -Dog
westley.c:53:79: error:
You notice nothing unusual
: No such file or directory
아무 이상한 점도 찾을 수 없습니다.
$ gcc westley.c -Describe -Drain
westley.c:39:119: error:
Through the drain you see a dwarf
in another cell
: No such file or directory
배수구(drain)를 살펴 보니 난쟁이(dwarf)가 다른 방에 있는 게 보입니다.
$ gcc westley.c -Describe -Dwarf
westley.c:42:92: error:
The gnarled dwarf looks thirsty
: No such file or directory
쭈글쭈글한 난쟁이(dwarf)는 목 말라 보입니다.
$ gcc westley.c -Describe -Debris
westley.c:45:133: error:
You notice a desk, a phone, and
a phone directory among the clutter
: No such file or directory
당신은 어질러진 잔해 중에 책상(desk), 전화, 전화번호부(phone directory)가 있는 걸 알아 챕니다.
$ gcc westley.c -Describe -Desk
westley.c:48:84: error:
There are some dimes on the desk
: No such file or directory
책상(desk) 위에 10센트짜리 동전(dime) 몇 개가 있습니다.
$ gcc westley.c -Describe -Dime
westley.c:53:79: error:
You notice nothing unusual
: No such file or directory
아무 이상한 점도 찾을 수 없습니다.
$ gcc westley.c -Describe -Directory
westley.c:51:159: error:
It reads:
Pixie's Pub -
instant service -
Dial DUNgeon0614
: No such file or directory
전화번호부에 쓰여 있길: 픽시 펍 - 즉석 서비스 - DUNgeon0614로 전화 주세요
미국 등에서는 전화번호를 각 숫자에 배당된 문자(예를 들어 1은 a/b/c라거나)로 해석해서 홍보하는 경우가 적잖게 있습니다.
$ gcc westley.c -Dial -DUNgeon0614
westley.c:63:156: error:
Pixie takes your order, and
magically, the room is filled
with banana daiquiris
: No such file or directory
westley.c:87:195: error:
You are in a debris-filled
dungeon; a door bars the
way, and sludge trickles into
a floor drain
: No such file or directory
픽시가 주문을 받자, 마법으로 방에 바나나 다이키리(daiquiri, 칵테일의 일종)가 채워집니다.
그 다음 메시지는 처음에 시작했을 때의 메시지와 같은데, 이건 컴파일러에 따라서 #include
가 실패해도 계속 다음 문장을 해석하려 하기 때문에 나타나는 현상입니다. 해당하는 부분의 번역은 생략합니다.
$ gcc westley.c -Drink -Daiquiri
westley.c:66:153: error:
As you drink, a voice from
below says 'Could you drop
one down here?'
: No such file or directory
westley.c:87:195: error:
You are in a debris-filled
dungeon; a door bars the
way, and sludge trickles into
a floor drain
: No such file or directory
다이키리를 마시자(drink) 아래에서 "한 방울만 여기로 떨어뜨려(drop) 주실 수 없나요?"라는 목소리가 들려 옵니다.
$ gcc westley.c -Drop -Daiquiri
westley.c:72:102: error:
You drop the drink
on the floor
: No such file or directory
westley.c:87:195: error:
You are in a debris-filled
dungeon; a door bars the
way, and sludge trickles into
a floor drain
: No such file or directory
당신은 음료수(drink)를 바닥에 떨어뜨립니다(drop).
땅바닥이 아니라 난쟁이에게 떨어뜨리려면 어떻게 해야 할까요?
$ gcc westley.c -Drop -Dwarf -Daiquiri
westley.c:70:220: error:
The dwarf eagerly accepts
the drink. 'Thanks! Here,
I found this, but I can't
understand it.' He hands
you a document
: No such file or directory
westley.c:87:195: error:
You are in a debris-filled
dungeon; a door bars the
way, and sludge trickles into
a floor drain
: No such file or directory
난쟁이는 열심히 음료수(drink)를 받아 먹습니다. "고맙습니다! 여기서 이런 걸 찾았는데, 이게 뭔지는 모르겠어요." 그는 당신에게 문서(document)를 넘겨 줍니다.
$ gcc westley.c -Describe -Document
westley.c:33:102: error:
It reads:
Depress Dotted Dog
: No such file or directory
문서에 쓰여 있길: 점박이(dotted) 개(dog)를 누르시오(depress).
$ gcc westley.c -Depress -Dotted -Dog
westley.c:85:70: error:
Be more specific
: No such file or directory
westley.c:87:195: error:
You are in a debris-filled
dungeon; a door bars the
way, and sludge trickles into
a floor drain
: No such file or directory
좀 더 자세히 말해 주세요.
이런, 점박이 개가 여러 마리 있나 봅니다. 점박이 개 중에서 D로 시작하는 게 있을까요?
$ gcc westley.c -Depress -Dalmatian
westley.c:76:239: error:
As you press the dalmatian
figure, the door opens - only
to reveal a menacing orc by
a vending machine (with a
sign reading 'DEPOSIT MONEY')
: No such file or directory
westley.c:85:70: error:
Be more specific
: No such file or directory
westley.c:87:195: error:
You are in a debris-filled
dungeon; a door bars the
way, and sludge trickles into
a floor drain
: No such file or directory
달마시안(dalmatian) 상을 누르자 문(door)이 열렸지만, 나타난 것은 ("돈을 넣으시오(deposit)"라고 쓰여진) 자판기와 위협스런 오크 뿐이었습니다.
처음에 잔해 사이에 있던 동전을 기억하시나요?
$ gcc westley.c -Deposit -Dime
westley.c:79:147: error:
Donuts spill out; you get
some, the orc hungrily eats
the rest
: No such file or directory
westley.c:87:195: error:
You are in a debris-filled
dungeon; a door bars the
way, and sludge trickles into
a floor drain
: No such file or directory
도넛(donut)들이 떨어져 내립니다. 당신이 몇 개를 가져간 사이, 오크가 허겁지겁 나머지를 다 먹어 버립니다.
오크가 배가 고팠던 모양이군요. 어떻게 하면 오크의 시선을 피해서 도망칠 수 있을까요?
$ gcc westley.c -Drop -Donut
westley.c:82:139: error:
The orc quickly eats the
donut; he still bars the
way
: No such file or directory
westley.c:87:195: error:
You are in a debris-filled
dungeon; a door bars the
way, and sludge trickles into
a floor drain
: No such file or directory
오크가 재빨리 도넛(donut)을 먹습니다. 그는 여전히 길을 지키고 있습니다.
앞에서 -Drop -Daiquiri
라고 했을 때와 마찬가지로 도넛은 땅바닥에 떨어져 내린 것입니다. 그럼 난쟁이에게 떨어뜨려 주면 어떨까요?
$ gcc westley.c -Drop -Dwarf -Donut
westley.c:29:208: error:
The orc scrambles to the drain,
trying to get the donut; you
run out the door and escape!
The End
: No such file or directory
오크가 도넛(donut)을 잡으려고 배수구(drain)로 기어 들어 갑니다. 당신은 문 바깥으로 나가서 탈출합니다! - 끝 -
지하 감옥을 빠져 나오는 데 성공했습니다! 사실 텍스트 어드벤쳐는 예상치 못 한 키워드를 찾는 것이 묘미긴 하지만 이 게임의 경우 소스 코드에 그냥 박혀-_-; 있기 때문에 약간 김이 빠지는 게 사실입니다. (심지어 키워드를 쓰는 순서도 의미가 없고요.) 그리고 사실은 위에 보인 메시지들이 소스 코드에 있는 모든 메시지고요. 하지만 컴파일러 에러로 게임을 한다니, 좀 기발하지 않습니까?