내가 원하는 OS의 조건

  1. 입력 형식의 레이아웃을 바꿀 수 있는 워드프로세서 기능이 있을 것 - 현재는 XP+날개셋(세벌식 개조)
  2. Opera 또는 Safari가 문제없이 기동할 것 - 인터넷이 안 되면 곤란
  3. 최소 2개 이상의 프로그램이 동시에 작동 가능할 것 - 음악 들으면서 글을 쓸 수 있어야지

정도일까.
추가하자면, 마비노기, 네이트온, 한글이 작동하면 좋겠어.
HWP 포맷이 공개가 되면 더 좋고.

….이런 거 없나. 돈 주고 안 사도 되는 걸로.

Ubuntu 에서 또 윈도로…

복귀 결정

  1. 네이트온이 제대로 기능하지 않음
  2. 한글을 WINE으로 돌리면 꽤 느림
  3. 이유를 알 수 없는(아마도 하드 에러나 토런트가 원인?) 프리징
  4. 어차피 인터넷 쇼핑을 하려면 버츄어 머신으로 윈도가 깔려 있어야 함

그냥 윈도 7 깔고 버츄어 머신으로 우분투 커맨드라인 모드를 돌리기로 했음.
하아… 하지만 DVD롬이 없으니 내일 사무실 가서 하나 빌려와야…

사실 이거저거 상세하게 수정할 수 있는 우분투쪽이 더 맘에 들긴 하는데, 일단 내가 지금 그런 걸 할 심적 여유가 없고, 일단 돌아 가야 뭘 하지…

윈도에서 USB 메모리에 우분투 설치 씨디 담기

이 사이트의 내용 참고.

준비물 - 7zip
%drive% — drive 문자
format %drive%: /FS:fat32 /V:Ubuntu8 /Q
7z x *.iso -x!bin -x!programs -x!isolinux\isolinux.txt -x![BOOT] -o%drive%:
mkdir %drive%:\syslinux\win32
copy syslinux\win32\*.* %drive%:\syslinux\win32
copy backg.png %drive%:
copy syslinux.cfg %drive%:
copy vesamenu.c32 %drive%:
copy makeboot.bat %drive%:
%drive%:
copy isolinux\*.*
rd isolinux /s/q
del isolinux.bin
call %drive%:\makeboot.bat

번역 하나를 끝냈다.

시작은 2008년 봄이었던 것 같은데, 지금은 2009년 여름이다.
날림이고, 내가 보기에도 엉망이고, 번역 하고도 난 Lisp에 대해 잘 모르겠지만.
일단 하나는 했다.

…의미 없나?

그래도 하는 거지 뭐. 오락하는 데 이유가 어딨어. 그냥 하는 거지.

Lisp로 주문 외기 - 10 - 추가

추가

좋아요. 이제 이 설명서에서 대충 얼버무리고 지나간 것들에 대해 얘기해 봅시다…

무엇보다, Lisp 코드는 컴파일 되기도 하고 종종 실행시간에 번역(interpreted) 되기도 합니다. 같은 프로그램 안에서도 말이죠. 이 때문에, Lisp 환경은 컴파일러라고 불리지 않고, 구현(implementations)이라 불리고 있습니다.
(비록 실행시간에 번역되는 Lisp코드가 보통은 일단 바이트코드로 컴파일되긴 하지만, 그건 일단 다른 얘기고…)

추가로, 언급할 만한 가치가 있는 다른 굉장한 Lisp 구현이 있습니다. Rainer Joswig 와 Bill Clementson가 함께 만든 자세한 목록(링크 깨짐)이 사용 가능하지요.

이 설명서에서 사용한 큰 꼼수 하나는 게임에 쓰인 문장을 기호로 적은 것입니다.

‘(Lisp 사용자는 이렇게 문장을 쓰지 않습니다)

“Lisp 사용자는 문장을 겹따옴표 안에 씁니다”

기호(Symbols)는 Lisp에서 특별한 의미를 띄고, 함수, 변수, 또 다른 것들의 유일한 이름을 저장하기 위해 사용됩니다. 이 때문에, Lisp는 기호를 다루는 방법이 특별합니다. 그래서 문자 메세지를 다루는 것이 어설프지요(몽땅 대문자로 만들어버린다든지…). 문장을 다루기 위해 기호 대신에 문자열(String)을 사용하게 된다면 그런 어설픈 것에 영향을 받지 않겠지요. 하지만 문장을 다루기 위한 더욱 난해한 명령이 필요하게 됩니다. 거기다, 문자열을 다루는 것은 Lisp에서 훨씬 중요한 기호를 다루는 명령을 가르치는 것과는 크게 관련이없습니다.

하나 더 빠프린 것은, 전역 변수를 만들기 위한 명령어인 defparameter입니다. 대신, 변수를 선언하기 위해 그냥 setf를 썼습니다.(돌아는 갑니다만, 좋지 못한 모양새라…)

연관 목록(alists라고도 하는)도 생략해버렸습니다. 숙련된 Lisp사용자에겐 그게 좀 더 효율적이고 격조높기 때문에, 점이 찍힌 목록 형태로 쓰입니다. 이건 초심자를 혼란스럽게 할 수 있습니다. 하지만 여기서 읽을 수 있는 Cons Cell을 이해하기 위해서는 꼭 필요한 개념입니다.

다른 미뤄둔 것은 주문(SPELs)은 더 일반적으로는 “Lisp 진(眞) macros”라 불리고, defmacro 명령으로 만들어진다는 건데, 가르치기엔 좀 헷갈립니다. 왜 다른 이름을 쓰는 것이 좋은가에 대해 쓴 다음 이야기를 읽어주세요. 이제 마지막으로, 주문(SPEL)이 game-action 주문(SPEL)처럼 쓰인다면 일어날 수 있는 이상한 이름 충돌이 있습니다. 더 전문적인 lisp관련 자료를 읽는다면, 아주 자세하게 이게 설명되어 있을 겁니다.

Q. Lisp에 대해 더 공부하기 위해 뭘 더 봐야 할까요?

A.

cliki 사이트에서 볼 수 있는 굉장한 Lisp 책들이 아주 많습니다.(개중 몇은 내려받을 수 있죠).

아주 극도로 이론적인 문서에 관심이 있다면, Paul Graham의 On Lisp의 eBook을 권해드립니다. 그가 쓴 다른 책과 수필은 그의 웹사이트에서 볼 수 있고 상당히 멋져요.

더 실질적인 전략에 관심이 있다면, 많은 Lisp 사용자가 지금 Peter Seibel의 Practical Common Lisp에 환호하고 있습니다. 이 책의 몇 장은 인터넷에서도 볼 수 있어요.

Voices

VOICES (MACROSS PLUS OPENING THEME)

ひとつめの ことばは ゆめ
첫번째 말은 꿈
ねむりの なかから
잠든 가운데서
むねの おくの くらやみを
마음 저 속 어둠을
そっと つれだすの
살짝 데려가버려

ふたつめの ことばは かぜ
두번째 말은 바람
ゆくてを おしえて
나갈 길을 알려주고
かみさまの うでの なかへ
하느님의 품 속으로
つばさを あおるの
날개를 펄럭여

とけていった かなしい ことを
녹아버린 슬픈 일을
かぞえるように
세는 것처럼
きんいろの りんごが
황금색 사과가
また ひとつ おちる
또 하나 떨어진다

みた ことも ない ふうけい
본 적 없는 풍경
そこが かえる ばしょ
거기가 돌아갈 장소
たった ひとつの いのちに
딱 하나의 목숨으으로
たどりつく ばしょ
다다를 장소

ふるい まほうの ほん
낡은 마법서
つきの しずく よるの とばり
달의 물방울 밤의 장막
いつか あえる よかんだけ
언젠가 만날거란 예감 뿐

we can fly
날 수 있어
we have wings
날개가 있으니까
we can touch floating dreams
둥실거리는 꿈에 닿아서
call me from so far
멀리서 나를 불러
through the wind
바람결에
in the light
빛 속에서

みっつめの ことばは ….
세 번째 말은 ….
みみを すましたら
귀를 기울이면
あなたの ふるえる うでを
당신의 떨리는 팔을
そっと ときはなつ
살짝 놓아줘

—————————-
이 노래는 참 좋아한다. 부를 수는 없지만… 마크로스는 전투와 노래의 조화가 좋은 물건이라고 생각.

Lisp로 주문 외기 - 9 -

게임의 특별한 동작 만들기

이제 완성까지 딱 하나만 더 하면 됩니다. 플레이어가 게임을 끝내기 위한 특별한 동작을 좀 더하는 거죠. 첫 번째 명령은 플레이어가 쇠사슬을 다락방에 있던 양동이에 용접하는 게 될 겁니다.

(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

새 명령을 시험해 볼까요.

(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)은 고상하지 못한 걸로 생각하고, 좀 더 난해한 단계들을 더 거쳐서 더 잘 돌아가는 걸 만들테지만, 여기서 신경쓸 일은 아니죠…)

game_action

이 주문(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

다음엔 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)이 코드를 더 쉽게 쓰고 이해하도록 만들어줬습니다.

splash

이제 마법사에게 물을 쏟아붇는 마지막 코드입니다.

(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.))))

donut
텍스트 어드벤처 게임을 완전히 다 만들었습니다!!

게임의 전체 진행을 보려면 여기를 클릭
Lisp프롬프트에 한 번 Copy&Paste 로 끝날 수 있는 소스코드를 보려면 여기를 클릭

이 연습서를 가능한 간단히 만들기 위해, Lisp가 어떻게 작동하는가 하는 많은 세부 사항은 주석 처리되거나 별도 페이지로 넘어갔습니다. 그러니 그 세부 사항이 어떤지 봅시다….

난 명복 못 빌겠다.

자살이라고 믿고 싶지도 않고, 자살이래도 나 잡아갈까봐 차마 이름도 대지 못할 사람들도 살아있는데 왜 죽었나 싶고.
아주 그냥 미래가 없어.
이게 21세기야?

Lisp로 주문 외기 - 8 -

라이센스 - The GNU Free Documentation License
원저자 - Conrad Barski, M.D.
원본 출처 - http://lisperati.com/casting.html

주문(SPEL) 외기

이제 Lisp의 믿을 수 없을 만큼 강력한 기능을 배워 볼 겁니다. 바로 SPEL(주문)만들기지요! SPEL 은 “Semantic Program Enhancement Logic”의 줄임말이고 컴퓨터 코드의 세계 안에서 Lisp언어를 우리 필요에 따라 개조하기 위해 가장 기초적인 수준까지 바꾸는 행동을 만드는 걸 가능케 해 줍니다. - 이게 Lisp에서 가장 마술처럼 보이는 부분이지요. SPEL을 가능하게 하기 위해, 일단 Lisp 컴파일러에서 SPEL을 활성화 할 필요가 있습니다. (이 줄에 대해서 걱정하지 마세요. 더 나은 Lisp프로그래머로 나아가려면 클릭하세요.
(defmacro defspel (&rest rest) `(defmacro ,@rest))
자, 이제 활성화 되었습니다. 첫 번째 주문(spell)을 외워보죠. walk입니다.
(defspel walk (direction)
`(walk-direction ‘,direction))

이 코드가 하는 것은 Lisp컴파일러에 walk라는 단어는 실제로 walk라는 단어가 아니라, walk-direction이고, direction이란 단어는 보이진 않지만 실제로 앞에 작은 따옴표를 가지고 있다는 것을 알려줍니다.
기본적으로 좀 특별한 코드를 프로그램 안에 살짝 넣을 수 있고, 컴파일러는 그게 컴파일 되기 전에 다른 걸로 바꾸게 됩니다.
spel_compile
이 함수가 우리가 길을 묘사하기 위해 사용했던 코드와 얼마나 비슷한지를 주목하세요. Lisp에서, 코드와 데이터가 비슷하게 보일 뿐만 아니라, 코드와 컴파일러에 보내는 특수명령(SPELs)도 비슷하게 보입니다. 아주 일관적이고 깔끔한 모양새지요!
새 주문을 시험해 봅시다!

(walk east)

==> (YOU ARE IN THE LIVING ROOM OF A WIZARD’S HOUSE.THERE IS A WIZARD SNORING LOUDLY ON THE COUCH.THERE IS A DOOR GOING WEST FROM HERE.THERE IS A STAIRWAY GOING UPSTAIRS FROM HERE.YOU SEE A WHISKEY-BOTTLE ON THE FLOOR.YOU SEE A BUCKET ON THE FLOOR)

훨씬 낫군요!

이제 물건을 집어드는 명령을 만들 겁니다.

(defun pickup-object (object)
(cond ((is-at object *location* *object-locations*) (push (list object 'body) *object-locations*)
`(you are now carrying the ,object))
(t '(you cannot get that.))))

이 함수는 현재 위치의 바닥에 물건이 있는지 검사하고- 만일 있다면 새로운 위치(플레이어의 몸)에다 목록을 밀어(push)놓습니다.(민다(push)는 것은 assoc 명령이 새 항목을 발견한다면 목록에 항목을 더하고 나서 지난 위치를 숨긴다는 겁니다.) 그리고 나서 성공했는지 알려주는 문장을 돌려줍니다.
이제 명령을 좀 더 사용하기 쉽게 만드는 다른 주문(SPEL)을 외어 봅시다.

(defspel pickup (object)
`(pickup-object ',object))

이제 새 주문(SPEL)을 써 봅시다!

(pickup whiskey-bottle)

==> (YOU ARE NOW CARRYING THE WHISKEY-BOTTLE)

이제 몇 가지 유용한 명령을 추가해 봅시다. 일단, 지금 들고다니고 있는 물건들을 보는 명령부터.

(defun inventory ()
(remove-if-not (lambda (x)
(is-at x 'body *object-locations*))
*objects*))

이제 어떤 물건을 얻었다면 알려주는 함수.

(defun have (object)
(member object (inventory)))

인터넷이 없는 생활

의외로 할 만은 하다. 십 분만 걸어나오면 컴퓨터와 인터넷이 있으니…
이대로 지내도 괜찮을지도?