Linuxカーネル空間で2048で遊ぼう

最近大ヒットしたゲームと言えば2048。上下左右にタイルを動かして数字をくっつけ、2048を作るだけのシンプルなゲームですが、それだけにハマりやすい。
[参考記事: 「2048」:19歳のイタリア人が、ミニゲームでインターネットを征服!|WIRED.jp
2の累乗が大好きなエンジニアの間でももちろん大人気なようです。


そんなわけで、2048をLinuxカーネルの中で動作させてみたいと思います。


といってもそのためにカーネルビルドしたりは面倒なので、SystemTapでランタイムにカーネルにロードすることにしましょう。

動かし方

以下、Fedoraの場合です。他のディストリビューションでの動かしたい方はマニュアル等でSystemTapの動かし方を調べてください。


1. 下記のソースを2048.stpという名前で保存します。
https://gist.github.com/NeoCat/9947862


2. 必要なパッケージとdebuginfoをインストールします。

% sudo yum update
% sudo yum install systemtap
% sudo debuginfo-install kernel

カーネルがアップデートされた場合はrebootしてください。


3. では実行しましょう。

chmod +x 2048.stp
./2048.stp

または

% sudo stap 2048.stp

上下左右キーで操作するだけです。頑張ってタイルの移動や出現のアニメーションも付けました。高速操作にも対応できるよう、動いてる途中で次のキーが押された場合にはアニメーションをスキップするようになっています。


押したキーが端末に表示されると画面が乱れることがあるので、フォーカスを端末から外しておいた方が良いと思います。
もしくは、stty -echo ; sudo stap 2048.stp ; stty +echo などとして、端末への入力文字の表示を抑制すると良いでしょう。*1


なお、残念ながらcolor256に対応した端末以外では色がつきません。そのためLinuxのコンソール(tty0など)では白黒になってしまいます。gnome-terminalなら大丈夫です。


ちなみに、複数の端末で同時に走らせると、1度キーを押すだけで全ての端末のタイルがそれぞれ動きます。全ての端末でクリアを目指すとさらに難易度が上がりますよ!?

Q&Aコーナー

Q1. アニメーションがスムーズじゃないんだけど?

デフォルトだとSystemTapは200msごとにしかカーネルモジュールからのデータを読み込んで表示してくれないようです。
下記のようにして手動でカーネルモジュールをビルドし、staprunコマンドを使えば更新間隔を短く設定できるため、アニメーションがスムーズになります。*2

# カーネルモジュールのビルド
% stap -p4 2048.stp   
/home/neocat/.systemtap/cache/69/stap_698d22858bd5aec36102a998101b3485_7368.ko
 # 保存された*.koをロード. 30ms間隔で更新
% sudo staprun -T 30 /home/neocat/.systemtap/cache/69/stap_698d22858bd5aec36102a998101b3485_7368.ko  
Q2. SSH接続したサーバで動かそうとしたけどキー操作が効かない。

仕様です。キーボードドライバのイベント関数にフックを入れることで動作しているので、本体に接続されたPS/2やUSBのキーボードでないと動きません。

Q3. 全然クリアできない…

仕様です(?)。コツを紹介してくれるページもあるようですから検索してみましょう。AIで自動的に解いてくれるツールもあるので、眺めてみると何か掴めるかもしれませんよ。 http://ov3y.github.io/2048-AI/

Q4. ばぐってるよ。

えいやっと3時間くらいで作ったので勘弁してください。っていうかぜひ直して公開ください。

Q5. ちょっと旬を過ぎちゃってるんじゃない?

2日ほど遅かったですね……。

Q6. そもそもなんでカーネルの中で実行する必要が…?

何でそんなこと聞くんですか? (´・_・`)

*1:./2048.stp で実行すれば自動的に入力抑制します。

*2:./2048.stp で実行すれば自動的に30msに設定します。