あの伝説の不思議なダンジョン系ゲーム「jnethack」をUbuntu19.10にインストールしようとしたら、そっちはそっちで大冒険だった
「sshでサーバにログインしたら、シェルじゃなくてゲームが始まったら楽しくね?」
と言ういまいちよく分からない欲求が爆発して、ターミナルで動くゲームを色々物色してました。
有名なゲームは大体実装されている印象。
しかしながらアクション系は再描画の頻度が激しすぎててチラつきとか動作に引っかかりがあったりで割とイマイチ。
なので、ここは定番のCUI RPG。Rogueにしようかなと思った次第です。
あ、そういえばRogue派生の「NetHack」ってやったことないなぁ。
確かJNetHackって言う日本語版もあるんだよね。aptにはなさげ。じゃあコンパイルしますか。
と言うことでJNetHackのコンパイルにチャレンジしてみました。
時は2020年。物語の舞台はUbuntu 19.10 Serverです。
ゲーム本編と同様、結構な数の罠が待ち構えていたので攻略のポイントを書いておこうと思います。
ライブラリ・ツールのインストール
まずはapt-getで以下のパッケージをインストールします。
- build-essential
- libncurses-dev
- bison
- flex
なんでかプログラミング言語を作るときの必須ツールであるyaccとlexを要求されます。
こいつら、そのものずばりの名前じゃなくてbisonとflexと言うパッケージになっています。第一の罠ですね。
ソースコードの展開とパッチの適用
$ tar xvzf NetHack-3.6.2_Release.tar.gz $ gzip -d jnethack-3.6.2-0.1.diff.gz $ cd NetHack-NetHack-3.6.2_Release/ $ patch -p1 < ../jnethack-3.6.2-0.1.diff
patchコマンドの-pオプションの数字がいまだに謎で手が止まるのと、差分ファイルをリダイレクトで渡さないといけないのが地味なハマりポイントです。第二の罠ですね。
Linux用のMakefileの作成
$ sh sys/unix/setup.sh sys/unix/hint/linux
常識を疑わず./configureを探し続けてしまう呪いでまたハマり。
シェルスクリプトでMakefileを錬成します。第三の罠。
gccにSJISなソースを解釈させるためのおまじないを追加する
ここが最大の難関でした。
JNetHackはどんな歴史的経緯かわかりませんが、ソースコード内の日本語がSJISコードで書かれています。
UTF-8を基本としている最近の?gccだとこのソースをそのままコンパイルすることができません。
具体的には、SJISコードには2バイト目が\な文字がいくつかあり(「表」とか)、それが入ると後続の文字がエスケープされてしまします。
このせいで、良くてメッセージ内の「表」の文字が文字化け。
最悪は文字列のダブルクォートをエスケープしてコンパイルエラーになってしまいます。
/* 「表」の2バイト目に含まれる\のせいで後続のダブルクォートがエスケープされて「文字列がダブルクォートで囲まれてへんぞ!」エラーになる。 */ char *str = "表";
じゃあ、ソースコードをUTF-8にあらかじめ変換すればいいかと言うとそうでもなくて、JNetHackはLinuxで動くときはSJISのメッセージをUTF-8に変換して出力していたり、SJISコードらしい16進数を抱えてたりするので、なんとかSJISのままでコンパイルを通さないと不味そうです。
幸い、gccにはUTF-8以外のソースコードをgccの内部コードUTF-8に変換するオプション「-finput-charset」と、逆に内部コードのUTF-8をそれ以外のコードに変換してバイナリを作る「-fexec-charset」ってオプションがあるので、それをMakefileに組み込むことにします。
src/Makefile:27
CFLAGS=-g -O -I../include -DNOTPARMDECL -DDLB -finput-charset=cp932 -fexec-charset=cp932