プログラミングに関連するゲーム3選 (2)
プログラミングに関連するゲーム3選 (2) – TIS-100 と Turing Complete
今日も引き続き、プログラミングに関連するゲームをいくつか紹介する。今回は TIS-100 と Turing Complete だ。
TIS-100

このゲームは、前回紹介したゲーム「A=B」と通じるものがある。
ゲームの内容は、TIS-100 というコンピュータを操作するというものだ。アセンブリ言語に酷似した構文と12個のノードを備えている。各ノードにはレジスタが1つあり、一部のノードは入力や出力として機能する。これは GPIO に近い概念だ。ゲームで用意されているアセンブリ言語は簡略化された構文であり、複雑なアドレッシングモードや割り込みは存在しない。
このゲームでも同様に様々なパズルを解いていくことになるが、アセンブリ言語で書くため、難易度としては次のような感じだ:
- すでにアセンブリ言語の基本概念がある場合:A=B よりも簡単に感じるだろう。何しろ A=B は不自由極まりない構文の中で問題を解く必要があるが、アセンブリ言語ではその必要がないからだ。
- アセンブリ言語の概念がない場合:このゲームはおそらく A=B と同じくらい難しく感じるかもしれない。アセンブリ言語の概念を理解するにはそれなりに時間がかかる。

ゲーム内のあらゆる構文に関する説明は、すべて1つの PDF にまとめられている。
ゲーム内ではコードの実行ステップ数、コードの行数、使用したノード数などが統計として記録されるため、最適解を追求するのが好きなプレイヤーにとっては良い暇つぶしになるはずだ。
このゲームにはチュートリアルがない! プログラミングの基礎がまったくないプレイヤーにとってはかなりハードルが高い。とはいえ、ゲームの仕様自体はかなり簡略化されており、実際に覚えるべき命令や仕様の数は本物のアセンブリ言語よりはるかに少ない。
問題自体はそれほど難しくなく、例えば「入力Aと入力Bを足して出力Aに送る」や「入力Aと入力Bを掛けて出力する」といったものだ。もちろん、アセンブリ言語は決して雲の上の話ではないし、これを学んで全クリできたら、もしかすると世のソフトウェアエンジニアの半分より優れているかもしれない。何しろ、すべてのソフトウェアエンジニアがアセンブリ言語に触れるわけではないのだから。
Turing Complete
これはゼロから CPU を作り上げるゲームだ。
目標は、最も基本的な論理ゲートから始めて、加算器、マルチプレクサ、レジスタなどの基本コンポーネントを経て、一歩一歩 CPU を作り上げることだ。CPU を作ったらそこで終わりではなく、その CPU のための命令セットを設計し、最終的にアセンブリ言語にして、自分が作ったアセンブリ言語でパズルを解いていく。
Steam のトレーラーの中に、僕のとても好きな言葉がある:
If you try to make such projects, unseen by others, as perfect as any human could, you’ll develop skills that other professionals don’t have
もちろん、ゲーム内の CPU はかなり簡略化されたバージョンであり、半導体プロセスにしても回路設計にしても、現実のものはゲームで描かれているような単純なものではない。最も分かりやすい例で言えば、分岐予測(branch prediction)などはゲーム内には実装されていない。しかし、そのことが CPU の動作原理を学ぶ妨げになるわけではない。
関連業界で働いていない限り、CPU が大まかにどう動いているのか、アセンブリ言語をどう読めばいいのかを必ずしも理解していないソフトウェアエンジニアは多い。もし時間をかけてゲーム内の全ステージをクリアすれば、多くのソフトウェアエンジニアが知らないことを確実に学ぶことができる。
ゲームの UI は主に配線を引く操作が中心となっており、1つの論理ゲートコンポーネントを完成させると、それが再利用可能なコンポーネントになり、以降のステージで使えるようになる。

ゲームが進むにつれてコンポーネントはどんどん増えていく。後半のステージの回路はますます複雑になり、必要なコンポーネントや配線の数も増えていく。

チューリング完全
ゲームにおける重要なターニングポイントの1つがチューリング完全だ。WORKING COMPUTER を完成させたとき、これまで苦労して組み立ててきた回路がすべてこの瞬間のためだったのだと気づくはずだ。このステージでは、いくつかの条件を満たすことが求められる:
- バイトコードのビットに基づいて実行する操作(ADD、XOR、OR など)を判定する
- プログラムカウンタ(Program Counter):プログラムがどこまで実行されたかを記録する
- 特定のビットに基づいてジャンプ(指定アドレスへのジャンプ)を実行するかどうかを判定する:6つのケース(大なり、小なり、等しい、always、never)を実装する必要がある
- 5つのレジスタ

ここまでくれば、基本的には素朴ながらも1つの CPU が完成したことになる。完全にソフトウェア上で動いているとはいえ、完成した瞬間の達成感はかなりのものだ。
パズルを解く

次にゲームはアセンブリ言語を書くことを求めてくる。これらのアセンブリ言語は自分で定義でき、最終的には機械語にマッピングされる。その後のステージでは、剰余の計算や迷路探索など、自分で作ったアセンブリ言語を使ってパズルを解いていくことになる。
感想
プログラミングの本質は、いつだって構文そのものではなく、その背後にある思考ロジックだ。
多くの人は「プログラミングとあまり変わらないなら、直接プログラミングをすればいいんじゃないか?」と疑問に思うかもしれない。僕自身の考えとしては、ゲームは視覚的なデザインと簡略化された条件を保ちながら、新しいことを学ばせてくれるツールだ。余計な設定を調整したり、IDE と格闘したり、デバッガの使い方を覚えたりする必要もない。フィードバックサイクルのコストを下げることは、学習において非常に有益なのだ。
関連記事
- 測定が目標になるとき:窓税からPull Request数まで かつて僕は小さなツールを自作し、四半期で自分がどれだけPRに貢献したか、レビューコメントをどれだけ残したか、チケットをどれだけ消化したかを集計して、上司にアウトプットを証明しようとしたことがある。上司は淡々と、評価はアウトプットだけで見るものではないと言った。数年後、僕はようやく理解した――測定が目標になるとき、それはもはや良い測定ではなくなるのだ。英国の窓税、ハノイのネズミ駆除の報奨金から、現代のPR数による開発者評価に至るまで、そのメカニズムはまったく同じだ。
- Cloudflare Images を画像ストレージ・変換ソリューションとして使う ウェブページに画像を1枚置くのはフロントエンドにとって最も簡単なことだが、リサイズや各種フォーマットの生成、さらにはトラフィックの負荷に耐えることまで完璧にやろうとすると、実際には一つの包括的なソリューションが必要になる。僕はその後、すべて Cloudflare Images に任せるようになり、オリジナル画像1枚だけを渡すようにしている。
- もう AWS Access Key を使うのはやめよう Access Key は AWS において見落とされがちなセキュリティリスクだ。OIDC と IAM Role を組み合わせることで、GitHub Actions にシークレットを一切保持させることなく、安全に AWS リソースを操作できるようにする。
- データベース主キー:AUTO_INCREMENT、UUID、そしてUUIDv7 バックエンド開発で度々直面する主キーの決定。auto incrementを使うべきか、それともUUIDか?衝突への懸念は?UUIDv7とcreated_at + インデックスの性能差はどれほどか?実際に2,000万件のデータで検証したベンチマークと設計上の意思決定を解説する。