docker と gotty で cloud な nethack プレイ環境を構築

nethack 3.6.0 がリリースされました。
http://www.nethack.org/index.html
実に12年ぶりの更新だそうです。

懐かしいですね nethack。自宅で PC *nix が動いたことで自宅で遊べるようになったこととか、ノートPCで持ち運べるようになったときとか、いろいろな思い出があります。
懐かしさからビルドして遊んでみようと思ったのですが、どうせやるなら今どきの環境っぽくしてみましょう。

# 目的
サーバー上で nethack を動作させて、WEBブラウザ上から遊べるようにします。
WEBブラウザさえあれば遊べますし、ローカルにインストールする必要もなくなりセーブ中断したデータが別の場所で続きを遊べるようになります。

WEBブラウザ経由のリモートターミナルとしては gotty を利用します。
https://github.com/yudai/gotty

それら nethack と gotty を Docker コンテナ化して、docker engine が動作しているところならどこでもサーバー化できるようにします。

# 準備
以下のものを用意します。

1. docker engine が動作しているサーバー
2. Sourceforge からダウンロード済みの nethack ソースコード (nethack-360-src.tgz)
3. 下記 Dockerfile

## 実際のファイル 
以下のファイルを　Dockerfile という名前でローカルに保存します。

```Dockerfile
FROM debian
MAINTAINER rerofumi

RUN echo 'deb http://ftp.jp.debian.org/debian/ jessie main' > /etc/apt/sources.list
RUN echo 'deb http://security.debian.org/ jessie/updates main' >> /etc/apt/sources.list

ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update; \
    apt-get -y upgrade; \
    apt-get -y dist-upgrade; \
    apt-get -y install build-essential libncurses5-dev bison flex; \
    apt-get -y install golang git; \
    apt-get clean

RUN cd /root
ADD nethack-360-src.tgz /root
RUN cd /root/nethack-3.6.0/sys/unix; \
    ./setup.sh hints/linux; \
	cd /root/nethack-3.6.0; \
	make -j 4; \
	make install; \
	make clean; \
	rm -rf /root/nethack-3.6.0; \
	ln -s /root/nh/install/games/nethack /usr/local/bin/nethack

RUN mkdir /root/go
ENV GOPATH /root/go
RUN go get github.com/yudai/gotty; \
    cp /root/go/bin/gotty /usr/local/bin/gotty; \
	rm -rf /root/go

EXPOSE 8080
CMD ["/usr/local/bin/gotty", "-c", "loginuser:passwd", "-p", "8080", "--title-format", "\"GoTTY - nethack\"", "-w", "/usr/local/bin/nethack"]
```

最後の行で gotty のオプション指定をしていますが、"-c" オプションの "loginuser:passwd" 部分がアクセスした際の BASIC認証になります。ご自分の名前とパスワードに書き換えて最低限の認証を施してください。
もちろん "-c" オプションを削ると認証なしでのアクセスになります、ローカルでの利用時など利用者を限定しないで済む場合はそれでもよいでしょう。

Dockerfile　と同じディレクトリにソースコードのアーカイブである nethack-360-src.tgz を置いてください。
今のところパブリックな git リポジトリがまだ提供されていないので Sourceforge からのダウンロードになるのですが、Sourceforge からのダウンロードはスクリプト化しにくいのでこのような手順となっています。

# コンテナ構築

Dockerfile と nethack-360-src.tgz の両方が置いてあるディレクトリで以下のコマンドを入力して Docker コンテナを build します

```
 $ docker built -t nethack-gotty .
```

構築中に必要なパッケージをインストールしたり、gotty をダウンロードしたりするためネットワークが有効になっている必要があります。
"nethack-gotty" は Docker image 名ですので、任意の名前をつけてください。

# サーバー実行

上記で build した image を実行することで nethack 配信サーバーが起動します。

```
 $ docker run -it -d -p 8080:8080 nethack-gotty
```

"-d" はバックグラウンド実行ですが必要に応じて付与してください。
gotty でコンソールをサーブするので "-it" オプションでのコンソール入出力追加指定が必要です忘れないようにしてください。
"-p" は Docker コンテナ内から 8080 で提供されているサーバーをホスト側の IP にフォワードするスイッチです。必要であれば左辺のホスト側ポートを変更してください。

![nethack-play.png](https://qiita-image-store.s3.amazonaws.com/0/50737/b4e21b98-279b-56a4-29cc-ae6e21875f1a.png)

これでブラウザからアクセスすると nethack にアクセスできます。

え、グラフィック版じゃないのかって？テキスト版だから良いのですよ。

# セッションについて

gotty はブラウザで開かれるたびにコマンドを実行して新しいターミナルとしてスタートしますので、ブラウザで複数開いた場合別の nethack が起動されて新しいゲームが始まります。(プレイヤー名はぶつからないようにしてください)

ゲームオーバーや中断による終了でターミナルが終了します。
再び遊びたいときは別のブラウザビュー(ウィンドウなりタブなり)を開いてアクセスし直します。

セーブ終了した場合、ターミナルが終了します。
プレイ再開は別ブラウザビューで起動し、前回とプレイヤー名を入力するとセーブデータがロードされプレイの続きが行えます。

ブラウザを閉じるなどして強制終了した場合はターミナル切断でセッションが切れた状態になります。この場合セーブ中断と同等ですので再プレイ時にユーザー名を入力することで続きから遊べます。

# 終わりに

ブラウザ経由でのターミナルというと tty.js などがありますが、gotty は実行するコマンドを指定する形のため Docker と組み合わせると非常に面白い使い方ができそうです。

それでは、良い nethack ライフを！