遊び方
マス目の盤面にリレーと配線を置いて、ステージが指定する回路を作ります。 合格した回路は 部品 として登録でき、作ったときの大きさのまま、次のステージで 1 個の素子として置けます。 スコアは盤面の面積で、小さいほど良い成績です。
1. 何を作るゲームか
出発点は 2 種類のリレーだけです。 そこから NAND や XOR といった論理ゲート、加算器、ALU、レジスタと進み、最後に 8 ビットの CPU にたどり着きます。 この道のりは nandgame と同じで、あちらも 2 種類のリレーから始まり、最初に NAND を作ります。
違うのは、回路が平面のマス目に載ることです。 配線もマスを消費し、線を交差させるにも 1 マスかかります。 そして作った部品は「そのときの盤面の大きさ」を持ち、次のステージではその面積を占めます。
ですから問われるのは「動く回路を作れるか」ではなく、「どれだけ小さく作れるか」です。 小さく作った部品ほど、後のステージで場所を取りません。 ゲートを NAND から組むか、リレーから直接組むかも自由で、たいていはリレーから直接作った方が小さくなります。
2. 画面と操作
画面は 3 つあります。
- ステージ一覧:ステージの並び、クリア済みの印、パーと自己ベストが並びます。ステージ名を押すとエディタが開きます。
- エディタ:盤面が画面いっぱいに出ます。ツールは下のドック(横に広い画面では左の縦の列)に並び、部品・テスト・盤面の 3 つはパネルにまとまっています。パネルは狭い画面では下から出るシート、広い画面では右に立ったままで、右上の記号で畳めます。
- ライブラリ:登録した部品の一覧です。名前の変更、削除、保存データの書き出しと読み込みができます。
エディタの操作は次のとおりです。
- 配線 (w):盤面をドラッグすると線を引きます。端のマスから外のピンへ向かってドラッグすると、そのピンにつながります。
- バス (b):8 本ぶんをまとめた太い線を引きます。
- 交差 (x):縦と横がつながらずにすれ違うマスを置きます。
- 消去 (e):マスの中身を消します。
- 選択 (v):置いた部品を選び、ドラッグで動かします。Delete で消せます。
- 配置:素子や部品を選んでから盤面を押します。タッチのときは指を離した位置に置かれます。部品はパネルの「部品」タブにあり、面積の小さい順に並びます。同じ機能でいちばん小さいものには「最小」が付きます。
- 回転 (r) と反転 (f):置く前の向きを変えます。選択中の部品にも効きます。部品を持っているあいだ、盤面の下に今の向きが実際の形で出ます。反転しても端子が同じ場所に来る部品は、反転の代わりに「左右対称」と表示され、押せません。
- 幅と高さ:パネルの「盤面」タブにあります。+と−で伸び縮みします。縮めるときは空いている行や列から削られ、右端や下端が埋まっていれば左端や上端が削られて中身がずれます。次に消える行と列は、タブを開いているあいだ盤面に赤い枠で出ます。端の行と列がどちらも使われていて縮められないときは、−が押せなくなり、理由が出ます。
- 余白を詰める:同じ「盤面」タブにあります。使っている範囲まで一気に縮めます。一度に縮むので、戻したいときは「元に戻す」を押してください。
- 拡大と縮小:盤面の右下の + と − で変わります。いちばん下の記号を押すと全体が入る大きさに戻ります。盤面が画面に収まらないときは、そのままスクロールして動かせます。
- 元に戻す:Ctrl+Z です。
入力ピンはクリックで on と off が切り替わります。 バスのピンは押すたびに 1 ずつ増え、横の欄に値を直接入力することもできます。 盤面は常にシミュレーションされていて、1 が流れている線は緑に光ります。
3. 使える素子
いずれも回転と鏡像反転ができ、8 通りの向きで置けます。 端子の向きは面積に効くので、向きを変えるだけで小さくなることがあります。
リレー(1×1)には 3 本の端子があります。
- c:コイルへの入力です。既定の向きでは北を向きます。
- in:接点の入力です。西を向きます。
- out:接点の出力です。東を向きます。
relay (default on) は c が 0 のあいだ接点が閉じ、in の値をそのまま out に出します。 c が 1 になると接点が開き、out は何も出さなくなります。 relay (default off) はその逆で、c が 1 のあいだ閉じます。
接点は現実には双方向ですが、このゲームでは in から out への一方向として扱います。
定数 1(1×1)は 4 辺すべてに 1 を出します。 定数 0 はありません。 何にもつながっていない線は 0 と読まれるので、0 が要るところは未接続のままで構いません。
Bus split(1×8)はバスと 8 本の線を相互に変換します。 西側のバス端子と、東側に並んだ 8 本の端子をレーンごとにつなぐだけなので、ばらす向きにも束ねる向きにも使えます。
4. 線と信号のルール
配線でつながったマスと端子の集まりを ネット と呼びます。 ネットに値を与えるものが ドライバ で、入力ピン、定数 1、リレーの out、部品の出力端子がこれにあたります。 ドライバが出す値は 1、0、または Z(何も出さない)の 3 つです。 接点が開いているリレーの out は Z になります。
ネットの値は次のように決まります。
- 1 を出すドライバと 0 を出すドライバが同居していれば 短絡 で、エラーになります(赤く表示されます)。
- 1 を出すドライバがあれば 1 です。
- 0 を出すドライバがあれば 0 です。
- すべて Z なら 0 です。
ここから、リレーの out 同士をつなぐと OR になります。 これは ワイヤード OR と呼ばれ、リレー計算機で実際に使われた技法で、面積を削る主な手段になります。 一方、入力ピン同士を直結して OR を作ることはできません。 入力ピンは 0 も強く出すので、片方が 1 で片方が 0 のときに短絡してしまいます。
部品の出力端子は、中のネットの値をそのまま外に出します。 中が Z なら外も Z になるので、リレーだけで作った部品はワイヤード OR に使えますが、0 を出す部品は使えません。 どう作るかが後の使い勝手を変えます。
線がつながる条件は 3 つあります。
- 隣り合う配線マス同士が、互いに相手の方向を向いている。
- 部品の端子の隣のマスの配線が、その端子の方を向いている。
- 端子同士が直接隣り合っている(このときは配線マスが要りません)。
バス配線 は 8 本を 1 マスにまとめた線で、太く描かれます。 1 本の線とは直接つながらず、幅の違う線が接すると「配線の幅が合いません」と表示されます。 バスと 1 本の線のあいだは Bus split を通してください。
5. 面積とパー
スコアはステージの盤面の面積、つまり幅かける高さです。 空きマスも面積に入るので、減らすには盤面そのものを縮めるしかありません。 外周のピンは面積に含みません。
パー は開発側が作った参照解の面積で、目安として表示されます。 パーと同じか、それより小さく作ると実績が付きます。
6. 部品の登録とライブラリ
テストにすべて合格すると、盤面を部品として登録できます。 名前は自由に付けられます(既定は「NAND 3×2」のようにステージ名と大きさです)。 登録した部品は以降のステージで素子と同じように置け、ステージ別にまとめて並びます。
同じステージから何個でも登録できます。 端子の配置や形の違う版をいくつか持っておくと、置く場所に合わせて選べます。
登録した部品は変更できないスナップショットです。 中を変えたいときは、そのステージで作り直して別の部品として登録してください。 他の部品や下書きが使っている部品は削除できません。
7. ステージの並び
括弧内はパーで、参照解のあるステージにだけ付きます。
論理ゲート
- NOT(2):定数 1 と relay (default on) を横に並べます。
- NAND(6):relay (default on) 2 個を並列にして out をつなぎます。
- AND(3):relay (default off) 2 個を直列にします。
- OR(6):relay (default off) 2 個を並列にします。
- XOR(12):a で b を通すリレーと、b で a を通すリレーを並列にします。定数も要らずリレーは 2 個で済みますが、各入力を 2 か所へ配る配線と交差が面積を取ります。
切り替えと算術
- Selector(12):s で a と b を選びます。relay (default on) と relay (default off) を s で制御すれば 2 個で足ります。
- Switch:1 入力を s で 2 つの出力に振り分けます。
- Half adder(30):登録した XOR と AND を置いた参照解の面積です。リレーから直接作れば縮む余地があります。
- Full adder:下の桁からの桁上がりも足します。
記憶する回路
- SR latch(12):出力を自分の入力へ戻して保持します。
- D latch(12):st が 1 のあいだ d を通し、0 のあいだは配線の輪で値を保ちます。
- D flip-flop(60):D ラッチ 2 個と NOT でマスタースレーブを組み、clk の立ち上がりで取り込みます。
- 1-bit register:フリップフロップの前にセレクタを置き、st が 1 のときだけ取り込みます。
8 ビット
ここからバス配線と Bus split が使えます。
- Negative(16):最上位ビットを取り出します。
- Zero:8 ビットすべてが 0 かを見ます。
- Selector:8 本まとめて切り替えます。
- Adder:全加算器を 8 個つなぎます。
- Increment:1 を足します。
- Subtract:b を反転して 1 を足したものを加えます。
- Register:1 ビットレジスタを 8 個並べます。
- Counter:clk ごとに 1 増え、st のときは in を取り込みます。
ALU
- Logic unit:op1 op0 で AND、OR、XOR、NOT x を選びます。
- Arithmetic unit:op1 op0 で x + y、x + 1、x - y、x - 1 を選びます。
- ALU:u で算術と論理を選び、zx で x を 0 に、sw で x と y を入れ替えます。
- Condition:x の符号とゼロを lt、eq、gt と照らします。
メモリと CPU
- RAM(4 語):レジスタ 4 個とセレクタで作ります。
- Control unit:命令から書き込み先と分岐、停止の制御線を作ります。
- CPU:命令とメモリの値を受け取り、pc と番地、メモリ書き込みを出します。
8. CPU の命令
語長も命令も 8 ビットです。 レジスタは A(アキュムレータ兼アドレス)、D(データ)、PC(プログラムカウンタ)の 3 本で、M は番地 A のメモリの値を指します。
| ビット 7〜0 | 意味 |
|---|---|
0 vvvvvvv |
A ← v(0〜127) |
1 0 s1 s0 u o1 o0 d |
計算。s1 s0 でオペランドを選び(00: x=A, y=D、01: x=A, y=M、10: x=D, y=A、11: x=0, y=M)、u o1 o0 で ALU の演算を選ぶ。d が 0 なら A に、1 なら D に書く |
1 1 0 lt eq gt c _ |
分岐。c が 0 なら D を、1 なら M を条件判定に通し、成り立てば PC ← A |
1 1 1 0 ____ |
記憶。M[A] ← D |
1 1 1 1 ____ |
停止。PC を進めない |
即値が 7 ビットなのは、上位ビットを命令の種別に使うからです。 128 以上の値が要るときは、即値を反転するか加算で作ります。
CPU ステージはテストベンチの形をとります。 ステージが PC の位置の命令と番地 A のメモリの値を与え、pc、addr、メモリ書き込みとその値を確かめます。 メモリはステージ側にあり、3 本のプログラムが最後まで正しく動けば合格です。
9. 保存と実績
進み具合はブラウザの中だけに保存されます。 サーバーには何も送りません。 別のブラウザへ移すときは、ライブラリの画面から JSON として書き出して読み込んでください。
実績は game-center に記録できます。 ハブから起動した場合はその場で記録されます。 そうでない場合は記録待ちとしてブラウザに溜まり、パネルの「テスト」タブに記録用のリンクが 1 本出ます。 何件溜まっていてもリンクは 1 本で、押すと game-center でまとめて記録されます。 勝手に開いたりはしないので、何が記録されるか確かめてから押してください。
作りかけの盤面はステージごとに自動保存されるので、途中で閉じても続きから遊べます。