回路のデバッグ
回路を利用すると、複雑な動作をさせることができる。回路の動作は非常に速く、毎秒60回(一回あたり0.017秒)という速さで変化するので、その動作はとても目で追うことはできない。もし想定通りに動かなかった場合、簡単なものならいいが、複雑な回路になると何が起こっているのかを調べることが困難である。factorio のゲーム内で、回路の動作をステップ実行することでデバッグに役立つ仕組みを考案したので紹介する。
エディターでのステップ実行
これを書いた後で知ったのだが、実は簡単にステップ実行する方法がある。
まず /editor コマンド(in game editor) を実行する。キーバインドは Control+Shift+F11。エディターモードに入るとデフォルトでゲームがポーズ状態になる。テンキーの "0" で再開・ポーズを切り替えられる。ポーズ状態でテンキーの "." を入力すると、ステップ実行する。
こんな方法があるなら以下の情報はあまり意味がないが、せっかく書いたので何かの参考になるかも知れないので残しておく。
なお、手っ取り早く使ってみたい方は ステップ実行回路 へ。
スイッチ
実現したいのは、ボタンを押すごとに一段階だけ回路の動作が進み、次にボタンを押すまで一時停止したままになるような仕組みである。そのような操作に役立つ「スイッチ」の回路を紹介する。この回路のBPはこちら

この回路の仕組みは簡単なので、説明は割愛する。使い方は、まず中央に解体プランナーを一つ置く。どんなアイテムでも構わないが、他とかぶらないという意味で、あまりアイテムとしては使用しない解体プランナーを用いた。解体プランナーは画面右下あたりにある赤いXアイコンをクリックすると、素材なしでいくつでも作れる。これを手に持ってzキーでベルトの上に置く。マウスカーソルで中央のベルトを指してrキーを押すと、キーを押すごとにON/OFFを交互に繰り返す。ランプは単にON/OFFを分かりやすくするためのもので、ここからさらに回路に配線して使用する。
ラッチ回路
ラッチ回路は、ある信号(情報)の内容を一定期間保持し、リセット信号によって元に戻す、という働きをする。以下の回路は、ラッチの動作を説明するためのもの。この回路のBPはこちら

条件回路の設定は以下のようになっている。

左側のスイッチには鉄板を一つ置き、右側のスイッチには解体プランナーを一つ置く。先ず、両方のランプが消灯した状態にする。次に、左のスイッチをONにすると、ラッチの入力(赤ケーブル側)に鉄板x1という情報が入力される。次に左のスイッチをOFFにしても、ラッチの出力は鉄板x1のまま維持される。つまり信号の内容を覚えている状態。次に右のスイッチをONすると、情報は消えて元に戻る。
ワンショット回路
上のラッチ回路では信号の種類(どのアイテムか)を覚えることができるが、値は常に1に設定されている。求めている回路は、入力信号の種類だけでなく値も記憶させることである。条件回路の出力を「1」ではなく「入力値」にすれば、値も含めて記憶できるが、それは最初の1tickの間だけで、次のtick以降では前の値との和になるため、期待通りにいかない。
そのため、スイッチをONしたときに1tickの間だけ一瞬ONになって、その後はスイッチをONし続けても出力はOFFになるような回路を作る。この回路のBPはこちら

先ほどと同様に左側のスイッチには鉄板を一つ置き、右側のスイッチには解体プランナーを一つ置く。左側の条件回路の設定は以下のように、単に入力をそのまま出力させるものである。

この条件回路は何もしないが、入力から出力に伝達するまでに1tickの時間がかかる。つまり、入力のON/OFFの変化を出力側にそのまま伝えるが、タイミングが1tick遅れて伝えられる。中央の条件回路の設定を以下に示す。

赤ケーブル(以下Rと示す)の入力は元々のスイッチのON/OFF信号で、緑ケーブル(以下G)は1tickタイミングを遅らせたものである。条件は R:それぞれ≠0 and G:それぞれ=0 としている。「それぞれ」(黄色の三みたいなアイコン)はいろんなアイテムごとに同じ計算をするという意味で、ここでは鉄板しかないので鉄板と読み替えても同じ。スイッチをOFF状態からON状態に変化させると、R側はすぐにONするが、G側は1tick遅れるので、最初の1tickだけ、R側は鉄板≠0で、しかもG側は鉄板=0となり、出力に鉄板x1が出力される。それ以外のタイミングでは信号なしになる。
右側の条件回路は以下のように、ラッチ回路の出力設定を入力数に変えたものである。

中央の回路からは、元の入力信号のうち、最初の1tickだけを切り取ったものが出力されてくるので、これで元の信号を正確に記憶できる。右側のスイッチをONすれば、記憶をクリアして元に戻せる。
改善点
以上でおおむねアイデアを具現化できたが、以下を改善したい。
1. 最終的なステップ実行回路では、元の回路の中で使われているすべての条件回路・算術回路・選別回路をステップ実行型に置き換える。そのため、タイミング信号を作る部分と、ラッチ関連部分を分けて、タイミング信号回路を共通利用することで部品点数を減らしたい。
2. 上の回路では、ステップ実行を指示するための解体プランナーを置いたスイッチを OFF=>ON にしたときにだけ、ステップ実行される。これでは操作しずらいので、OFF=>ON のときと ON=>OFF のときの両方でステップ実行が進むようにする。
3. ステップ実行した結果の出力端子は、他の回路と接続することになるので、他の回路とショートするなどの干渉を避ける仕組みが必要である。
これらの改善点を踏まえた完成形を以下に示す。
ステップ実行回路
ステップ実行回路を以下に示す。左半分がタイミング信号発生回路で、右半分がラッチ回路である。右側の回路は、元の回路のすべての条件回路・算術回路・選別回路について、同じ回路を複数配置して、それらと接続して使用する。この回路のBPはこちら

左のスイッチの中央に解体プランナーを一つ配置するのを忘れずに。上に乗ったアイテムはBPの対象外なので。
左上から下に向かって順に、回路の設定を示す。

一つ目の条件回路は、ステップスイッチの信号を1tick遅らせる。

二つ目の条件回路は、ステップスイッチが OFF=>ON に変化したときと、ON=>OFF に変化したときに1tickの間だけ、レ信号を出力する。一つ目の条件回路と二つ目の条件回路が、既に説明したワンショット回路のためのワンショット信号を生成している。

三つ目の条件回路は、先ほどと真逆のタイミングでレ信号を出力する。この信号はラッチ回路で記憶した情報をクリアするためのクリア信号に利用する。
続いて右上から下に向かって順に、回路の設定を示す。

四つ目の条件回路は、元の回路の出力を、ステップスイッチが変化した瞬間の1tickだけ捉えて出力し、その他のタイミングでは何も出力しない。上のワンショット信号と組み合わせることで、ワンショット回路を実現している。

五つ目の条件回路は、四つ目の条件回路で得られた信号を維持して、同じ信号を出力し続けるラッチ回路である。次にステップスイッチが変化したときに信号をクリアする。ステップスイッチが変化した瞬間、四つ目の条件回路がこの情報を記憶して、そのとき同時に五つ目の条件回路は直前に覚えていた値を消去する。これらが同時に行われて、直後のtickで四つ目の条件回路から五つ目の条件回路に情報が送られてこれを記憶する。

六つ目の条件回路は、何もしないで入力を出力に伝達する。何もしないが、もしこれがないと五つ目の条件回路の出力が他の回路に接続されて、そうするとそちらから五つ目の条件回路の入力側にも信号が逆に流れ込んで来て干渉することになる。これを防ぐために必要である。
これがどうして、回路のステップ実行になるか、ご理解いただけるだろうか。次項のカウンタ回路の例を見ると理解が深まると思う。元の回路では回路の出力が他の回路の入力に接続されることになり、すると 1tick ごとに信号がどんどん伝わって、全体として目まぐるしい速さで変化していく。このステップ実行回路があると、ステップスイッチが変化したときにだけ元の回路の出力を取り込んで、それを他の回路に伝達するので、ステップスイッチを操作しない限り、各回路の出力が変化しないのである。
ステップ実行回路の使用例
使い方を説明するため、以下のカウンタ回路をステップ実行してみる。この回路のBPはこちら

この回路は、定数回路から発生した変数 T=1 を毎tickごとに積算して 0, 1, 2, ... と数え上げる。そして 10tickごとにリセットしてまた0から数え直すという動作をする。ランプは条件として T<5 を設定しているので、1~4の間はランプが光り、その他のタイミングで消灯するので、すばやくピカピカ光る、というものである。
当然、そのままの回路ではステップ実行できない。元の回路を、ステップ実行できる回路に改造する必要がある。改造した後の回路を以下に示す。この回路のBPはこちら

左のスイッチの中央に解体プランナーを一つ配置する。条件回路が全部で7個あるが、右上の条件回路が、改造する前の元の回路に含まれていたものである。回路の設定内容も元の回路とまったく同じである。そして残りの6個の条件回路は、前の節で示したステップ実行回路である。
元の回路をステップ実行型に改造するには、

1. ステップ実行回路のステップスイッチ及びタイミング信号発生回路を配置する。(図の左半分)
2. 元の回路に含まれるすべての条件回路・算術回路・選別回路の下に余白を設ける。
3. それら条件回路等のそれぞれの下に、ステップ実行回路のラッチ回路を配置する。(右の下の3個の条件回路)
4. 図の①に接続されていた配線をすべて、③の端子に配線し直す。ケーブルの色は変えないで、元は①に接続されていた赤ケーブルは代わりに③に赤ケーブルで接続し、同様に緑ケーブルは③に緑ケーブルで接続する。例えば元は①とランプが赤ケーブルで接続されていたが、これを削除して代わりに③とランプの間に赤ケーブルを接続する。
5. 赤ケーブルで、①と②の間を接続する。
6. 緑ケーブルで、④の二本を接続する。
それでは使ってみよう。以下は右上の、元の回路に含まれていた条件回路を開いて詳細を見ているところ。変数Tは初期状態で、T=1 になっている。これは定数回路の出力と等しいので、この直前の条件回路の出力が T=0 だったことを示している。

ステップスイッチの中央でrキーを押すと1ステップだけ回路の処理が進んで、T=2 になる。

以後、何度か繰り返すと、以下のように T=5 になったとき、ランプが消えることが確認できる。

このように、ステップ実行を使用するとステップスイッチを操作するごとに 1tick だけ回路の動作が進んで、その状態で停止する。1tick ずつ進めながら、各部の信号の様子を調べることで、デバッグができる。
ステップ実行のステップ実行
ステップ実行回路は、理屈の上ではあらゆる回路をステップ実行できるはずである。であれば、上で紹介した「カウンタ回路をステップ実行する回路」をステップ実行することも可能なはずである。これを実現した回路を以下に示す。この回路のBPはこちら

左上のスイッチは、全体をステップ実行させるもので、その右は「カウンタ回路をステップ実行する回路」内のステップスイッチである。先ず右のスイッチを操作する(rキーで中央を45度回転する)。すると、カウンタ回路をステップ実行する指示を与えたところだが、この段階では「カウンタ回路をステップ実行する回路」は止まったままなので何も起こらない。しかし各列の一番上の条件回路を開いてその出力を確認すると、次に起こる予定の変化内容を確認できる。次に、左のスイッチを操作する。すると、「カウンタ回路をステップ実行する回路」が 1tick 先に進んで、右のスイッチの変化を検出するが、まだカウンタの値は変化しない。合計3tick分、左のスイッチを操作すると、ようやくカウンタが動作して変数Tの値が変化する。ちょっとややこしいが、想定通りステップ実行できる。
ここで示したのはあまり実用性がないが、どんな回路もステップ実行できることを示すために参考までに掲載した。このように、元の回路の数が約4倍に増えるので、どうしても複雑になるのが欠点である。しかしどんな回路もステップ実行して詳しく調べられることは有用で、役立つツールなので活用してほしい。