Leaf Rogueを2016年のNetBSD上で動かしてみる。

遅ればせながら[NetBSD Advent Calendar 2016](http://qiita.com/advent-calendar/2016/netbsd)、24日目の記事です。

(もう過ぎちゃったけど)12/24はクリスマス。ふと[Linux Advent Calendar 2016](http://qiita.com/advent-calendar/2016/linux)を見ると「[クリスマスncursesアプリ特集2016](http://qiita.com/otakuto/items/13536fcc2e6baa2acbb5)」という記事が。

そこでふと"Leaf Rogue"という[Rogue](https://ja.wikipedia.org/wiki/%E3%83%AD%E3%83%BC%E3%82%B0)の実装系で敵キャラのメッセージとかを外部ファイルで切り替えられるようにしたバージョンがあったことを思い出し、さっそくNetBSDでもビルドしてみようと考えてみました。

## Leaf Rogueのファイルを入手する

Leaf Rogueは以下のURLから入手できます。別途必要なメッセージ分離型Rogueのソースコードもここから入手できます。

 * [Leaf Rogue サポートページ](http://games.roguelife.org/leaf/)

以下のファイルを展開します。

```
$ tar zxvf rogue_s.tar.gz
$ tar zxvf lfrog072.tar.gz
```

Lead RogueのメッセージはEUC-JPまたはSJISで提供されているので、おもむろにUTF-8に変換します。

```
$ cd lf_rogue
$ iconv -f euc-jp -t utf8 leaf.msg > tmp.msg && mv tmp.msg leaf.msg
```

メッセージの内容は以下のような感じです。(手元での動作は確認できていますが)これちゃんとUTF8対応しないとハマりそうな気がしますね。

特に「文字列の長さは最大79バイトです。」のあたり、UTF8で必要バイト数が3倍くらいになる感じなのでちょっとマズイかも...。

```
$ cat leaf.msg
                  リーフ・ローグ メッセージファイル
                               Ver0.72
                      by 風の谷のガンダルフ＆Ｋ

                       本メッセージファイルは、
            「雫」「痕」「さおりんといっしょ」「To Heart」
                  「初音のないしょ」「White Album」
                               (C)Leaf
                       の内容を元にしています。


漢字コードは EUC(UNIX), Shift-JIS(MS-DOS, HUMAN) である必要があります。
エスケープシーケンスなどのコントロールコードを含めることはできません。
文字列の長さは最大 79 バイトです。


メッセージのバージョン(play.c)
1       "Leaf version Ver0.72 (by ohno@tutics.tut.ac.jp, tsumura@kuis.kyoto-u.ac.jp)"
持ちものの種類
2       "ヤックシェーク"
3       "巻きもの"
4       "弁当"
5       "モップ"
```

## Leaf Rogueのビルド

Leaf Rogueのビルド、といっても、実際はメッセージ分離型Rogueをビルドし、実行時にLead Rogueのメッセージファイルを読み込ませる形になります。

メッセージ分離型Rogueのソースコードは古い時代のままなので、2016年の現代のNetBSD環境(たぶん他の環境でも)ではソースコードの修正が必要になります。

とりあえずビルドが通るように修正した差分は以下のようになります。

```diff
diff -ur rogue_s/Makefile.nix rogue_s.DEVEL/Makefile.nix
--- rogue_s/Makefile.nix	1992-09-13 23:36:02.000000000 +0900
+++ rogue_s.DEVEL/Makefile.nix	2016-12-26 03:55:29.000000000 +0900
@@ -11,8 +11,8 @@
 	trap.o use.o zap.o
 
 # for BSD (Japanese, using my own CURSES)	by Yasha
-CC	= gcc -traditional-cpp
-CFLAGS	= -O -g -DUNIX -DUNIX_BSD4_2 -DCURSES -DJAPAN -DEUC -DTOPSCO
+CC	= gcc
+CFLAGS	= -O -g -DUNIX -DUNIX_BSD4_2 -DCURSES -DJAPAN -DEUC -DTOPSCO -DUNIX_386BSD
 LIBS	=
 
 # for 386BSD (Japanese, using my own CURSES)	by Yasha
@@ -26,8 +26,8 @@
 #ADDHEADER = jcurses.h
 
 # for BSD
-#CFLAGS	= -O -DUNIX -DUNIX_BSD4_2
-#LIBS	= -lcurses -ltermcap
+CFLAGS	= -O -DUNIX -DUNIX_BSD4_2
+LIBS	= -lcurses -ltermcap
 
 # for BSD (with COLOR, using my own CURSES)
 #CFLAGS	= -O -DUNIX -DUNIX_BSD4_2 -DCURSES -DCOLOR
Only in rogue_s.DEVEL/: Makefile.nix.ORIG
diff -ur rogue_s/machdep.c rogue_s.DEVEL/machdep.c
--- rogue_s/machdep.c	1992-09-14 14:40:12.000000000 +0900
+++ rogue_s.DEVEL/machdep.c	2016-12-26 03:56:15.000000000 +0900
@@ -278,10 +278,13 @@
 #ifdef UNIX_386BSD
 	fpurge(stdin);
 #else
+	fpurge(stdin);
+/*
 	ln += stdin->_cnt;
 	for (; ln > 0; ln--) {
 		(void) getchar();
 	}
+*/
 #endif /*386BSD*/
 #endif /* UNIX */
 
diff -ur rogue_s/message.c rogue_s.DEVEL/message.c
--- rogue_s/message.c	1992-09-14 14:40:12.000000000 +0900
+++ rogue_s.DEVEL/message.c	2016-12-26 03:56:38.000000000 +0900
@@ -283,7 +283,7 @@
 		case '\032':
 			/* putstr(CL); */
 			fflush(stdout);
-			tstp();
+			//tstp();
 #if defined(NeXT) && !defined(CURSES)   /* by Yasha (till "#endif") */
                         getyx(stdscr, y, x);
                         move(0, 0);
Only in rogue_s.DEVEL/: rogue.core
diff -ur rogue_s/rogue.h rogue_s.DEVEL/rogue.h
--- rogue_s/rogue.h	1992-09-13 16:36:59.000000000 +0900
+++ rogue_s.DEVEL/rogue.h	2016-12-26 03:54:19.000000000 +0900
@@ -24,6 +24,9 @@
 #define	fflush(p)
 #endif
 
+#include <string.h>
+#include <signal.h>
+
 #if 0
 #ifndef ORIGINAL
 typedef unsigned char	uchar;
```

`make -f Makefile.nix`でビルドします。

```
$ make -f Makefile.nix
gcc -O -DUNIX -DUNIX_BSD4_2  -c curses.c
gcc -O -DUNIX -DUNIX_BSD4_2  -c hit.c
gcc -O -DUNIX -DUNIX_BSD4_2  -c init.c
gcc -O -DUNIX -DUNIX_BSD4_2  -c invent.c
gcc -O -DUNIX -DUNIX_BSD4_2  -c level.c
gcc -O -DUNIX -DUNIX_BSD4_2  -c machdep.c
machdep.c: In function 'md_heed_signals':
machdep.c:403:2: warning: passing argument 2 of 'signal' from incompatible pointer type [enabled by default]
  signal(SIGINT, onintr);
...
gcc -O -DUNIX -DUNIX_BSD4_2  -c zap.c
gcc -o rogue curses.o hit.o init.o invent.o level.o  machdep.o main.o message.o monster.o move.o  object.o pack.o play.o random.o ring.o  room.o save.o score.o spechit.o throw.o  trap.o use.o zap.o -lcurses -ltermcap
```

warningは取り除いてしまいたいのですが、まずは動作するかを先に確認したいので今はこのままで。とりあえず実行バイナリは生成されています。

```
$ file rogue
rogue: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for NetBSD 7.0.2, not stripped
```

## Leaf Rogueを実行する

メッセージファイルを指定してLeaf Rogueを実行します。

```
$ ./rogue ../lf_rogue/leaf.msg
```

無事に葉っぱの洞窟での冒険が始まりました。

![スクリーンショット 2016-12-25 19.27.27.png](https://qiita-image-store.s3.amazonaws.com/0/61137/8e77e3cc-81e3-1e09-54cc-cb78a7130b4c.png)

が、2階くらいでツッコミに負けてGAME OVER...。あと何やらAAが崩れている感じ。

![スクリーンショット 2016-12-25 19.28.07.png](https://qiita-image-store.s3.amazonaws.com/0/61137/641b6f0d-3db9-18c2-de63-e7741b061bb1.png)

## まとめ

Leaf RogueをNetBSDでビルドしてみました。メッセージ分離型Rogueのコードが古いままということもあってか、ビルドを通すためには若干の修正が必要でした。こういった少し手直しすれば現代の環境で動作するようになるアプリとかは他にもありそうなので、GitHub上でforkする等、フォローアップしておけるようにしたいものです。