石橋を叩いて壊すページ

ゼロから始めるFactorioの回路構築(累積回路編)

前回の記事では回路から「現在の」状態を取得していろいろな判断をする回路をご紹介した。
この記事では、「過去に」入力された信号を全て累積する累積回路を使った回路をご紹介する。
ちなみに「累積回路」という名前は今決めた。軽く調べたが、適当な名前がなさそうだったからこう呼ぶことにする。

基本編 > 入力・出力・混合編 > 定数・算術回路編 > 条件回路編 > 実践例編 > 累積回路編

累積回路とは

累積回路には、今までに入力された信号を累積(合計)する機能がある。
例えばインサータには「掴んだアイテムの数」の信号を出力する機能があるが、 累積回路を組み合わせることで「今までに掴んだアイテムの数」の信号を出力できるようになる。
これにより、例えば「今までに1500個のアイテムを取り出した」という情報を得たり、 「アイテムを1000個入れるごとに列車を1回発車させる」といった回路が組めるようになる。

累積回路は、累積回路というアイテムがゲームにあるのではなく、算術回路にひと工夫して作ることが出来る。
① 算術回路を1つ設置し、その入力と出力をレッドケーブルでつなぐ。
② 算術回路に「それぞれ+0をそれぞれ出力」という式を設定する。
たったこれだけである。


完成した累積回路。算術回路1個とレッドワイヤー1本で簡単に作れる。
ちなみに算術回路には電気が要るので、別途電柱を置いて電力を供給してほしい。

それでは実際に「今までに掴んだアイテムの数」を数えてみよう。
ベルトとインサータを円を描くように配置する。
近くに累積回路を設置し、インサータとレッドワイヤーで繋いでおく。
インサータの回路設定を開き「✅掴んでいるアイテムを取得する、読み取りモード:パルス、動作モード:なし」と設定する。

あとは、ベルトに適当なアイテムを載せれば実験はスタートだ。
インサータがアイテムを掴むたびに「今掴んだアイテムの数」の信号が回路に流れ、 それを累積回路が「今までに掴んだアイテムの数」として累積し続ける様子が確認できるだろう。


インサータがアイテムを掴むと掴んだアイテムの信号が回路に出力され、累積回路に累積されていく。
算術回路にマウスを当てると、画像右上のように算術回路が累積している情報を表示できる。
この画像では、このインサータは今までに鉄板を69枚、銅板を48枚、鋼鉄を24本掴んだことがわかる。
累積回路が正しく動いていれば、インサータがアイテムを掴むたびに掴んだ分だけ信号が増えていくはずである。
なお、もし掴んだアイテムの数と信号の増え方が一致しない場合は、インサータの読み取りモードが「パルス」になっているか確認しよう。
読み取りモード「パルス」ではインサータはアイテムを掴んだ瞬間に1度だけ信号を出力するので、 足し算も1度だけとなり、掴んだアイテムの数が正しく累積回路に累積される。
読み取りモード「ホールド」ではインサータはアイテムを掴んでいる間ずっと信号を出し続けるため、 累積回路はその間ずっと足し算を繰り返してしまい、実際に掴んだアイテムの数十倍の数を累積してしまう。

累積回路の仕組みは実に簡単である。
算術回路には「それぞれ+ゼロをそれぞれ出力」という式が設定されているから、 算術回路に入力された信号は元の数字+0、つまり元の数字のまま算術回路から出力される。
そして算術回路の出力がレッドワイヤーを介して算術回路の入力に繋がっているから、出力された信号は結局算術回路に戻ってくる。 これにより同じ信号がループし続けるので、信号が維持されるわけである。
そして以前の記事で説明した通り、ひとつの回路に複数の出力があると信号は足し算されるので、 「算術回路の出力」と「それ以外の出力」が混ざると2つの信号が合計され、その結果が「算術回路に入力」されるので、 算術回路以外から入力された値が算術回路にどんどん合計されていく仕組みである。

式に「それぞれ」が使われているので、 上記画像のように鉄板と銅板と鋼鉄など複数のアイテムの信号が入力された場合はアイテムごとにそれぞれ累積が行われる。
それぞれ」を使わず、例えば「鉄板+ゼロを鉄板として出力」のような具体的なアイテムの式を設定すれば、 鉄板の枚数だけを累積しそれ以外は無視する累積回路を作ることもできるので、特定のアイテムだけを数えたい場合はこちらがおすすめである。

累積値をゼロに戻したい場合は、いったん算術回路を撤去し直後に「元に戻す」(キーボードの場合CTRL+Z)で再設置すると楽である。
停電が起きた場合、停電中の算術回路は停電前の信号を出力し続け、かつ入力信号を無視する動作をする。 そのため停電しても累積値が消えてしまう心配はないが、その代わり停電中に新しい信号が来ても累積してくれないので注意しよう。

以上が、累積回路の基本的な説明である。
以下では、この回路を便利に使うテクニックをご紹介したい。

これまでに打ち上げたロケットの数を数える

ある程度ゲームに慣れてきた工場長は、ロケットを1発打ち上げただけでは満足せず、2発も3発も打ち上げるはずである。
ただ、これが100発、1000発となってくると、だんだん数え切れなくなってくる。
そんなときこそ累積回路の出番である。早速、いままでに打ち上げたロケットの数を数える回路を作ってみよう。

残念ながら、ロケット発射台には「ロケットを発射したとき信号を出す」ような機能は存在しないので、 厳密な意味で「ロケットが発射された回数を数える」ことは出来ない。
ただし「組立機で人工衛星を組み立てた回数」であれば、 組立機から衛星を取り出すインサータに回路を繋げば衛星を掴んだ瞬間に信号を出力させることができるので、 正しい言い方をするなら「今までに組立機から取り出した人工衛星の数」を数える回路を作ることにしよう。

やることは簡単で、既に上記でお見せした通り累積回路とインサータを繋ぐだけである。


人工衛星を作る組立機の取り出し用インサータにレッドワイヤーを繋ぎ、累積回路に繋ぐ。
インサータには「動作モード:なし、掴んでいるアイテムを取得する:✅、読み取りモード:パルス」を設定する。
そうすれば、組立機から衛星が出てくるたびにインサータから「人工衛星が1」という信号が出力され、 それが累積回路で合計されることで、今までに組み立てられた人工衛星の数がわかる。
数を知りたい時は累積回路にマウスを合わせれば、回路に記憶された衛星の数が画面右の情報ウィンドウに表示される。
上記画像の場合は、今までに37発の人工衛星を作ったことがわかる。

数を数えるだけなら、たったこれだけでOKである。

数字を7セグで表示する

上記で数を数えることができたが、これだけだと味気ないので、せっかくだから7セグ表示も追加してみよう。
7セグというのは「日」の字の形で0から9までの数字を表示する、いわゆる「デジタル数字」のことである。
点いたり消えたりする棒(セグメント)が7本あるので7セグと呼ばれている。


実際の工場での運用風景と、その簡略図。いままでに約5万発のロケットを打ち上げたことがわかる。
これだけ打ち上げたら、そろそろ地球から救助船が来てもいいころだと思うのだが…。もしかして地球滅んでる?
簡略図に合わせた建設計画はこちら

数値を7セグで表示するには、まず数値をそれぞれの位ごとに分ける必要がある。
例えば「52586」を表示したいなら、万の位は5、千の位は2、百の位は5、十の位は8、一の位は6、という具合である。

数値の位分けは、算術回路の「%」(割り算の余り)の出番である。
例えば「52586」という数字の一の位は「6」だが、これは52586を10で割った答えの「余り6」として算出できる。
よって算術回路としては、「衛星の数%10」を計算すれば一の位を得ることができる。
十の位の8は、52586をいったん10で割って「5258」とし、これを10で割ると「余り8」が得られるから、算術回路を2台使えば計算できるとわかる。
百の位の5は、同様に52586をいったん100で割って「525」とし、これを10で割ると「余り5」が得られる。千、万の位も同様である。
ちなみに、算術回路による割り算は小数点以下切り捨てなので、端数が出る心配はない。


簡略図を再掲。この図の左半分には、6台の算術回路が書かれている。
一番左の1台は累積回路で、これまでに製造された衛星の数を数えるためのもの。
その右の最上段の算術回路は、「衛星の数÷10000をという特殊アイテム信号として出力」している。
その下の算術回路は「衛星の数÷1000をという特殊アイテム信号として出力」している。 以下、も同様である。
(ちなみに一の位は1で割る必要はない。1で割っても元のままだから、累積回路の衛星の数をそのまま使えばいい。)
そして最下段の算術回路は「それぞれ」を使い、上記した信号それぞれを10で割った余りに変換している。
こうすれば、例えば衛星の数が「52586」であったなら、は5、は2、は5、は8、衛星は6、という位ごとの数値が得られることになる。

次は、これをセグメント(直線)ごとの点灯/消灯信号に変換してみよう。これには定数回路を使う。
説明の前に、まず7セグのそれぞれのセグメントに名前を付けておこう。
ここでは、「 日 」の形の一番上の横線「  ̄ 」をセグメントAと呼ぶ。そこから時計周りに外周の各直線をセグメントB~Fと呼ぶ。
(デジタル数字の縦棒は上半分と下半分の2セグメントに分かれていることに注意。)
真ん中の横線「 ― 」はセグメントGと呼ぶ。

簡略図中央の定数回路には、からまでそれぞれ以下表のとおり信号を出力させる。

定数回路の設定
-1,212,153,856
-104,857,600
-541,065,216
-1,228,931,072
-1,568,669,696
-1,900,019,712
1,052,770,304

まるで暗号のようだが、これらの数字はなんだろうか。
電気に詳しくない人でも、「コンピューターの中では、すべてが1か0かで表される」という話は聞いたことがあると思う。
上記の値は、A~Gの各セグメントを「光らせる」ときは「1」、「光らせない」ときは「0」で表したデータを、 7セグに表示させたい0から9までの10文字分つなげた数字である。
これ以上詳しい説明は省くが、重要なのはこれらの数字を「7セグに表示させたい数字」の分だけ左ビットシフトすると、 その値がマイナス値かどうかで各セグメントを「光らせるか、光らせないか」がわかる点である。
例えば「5」を表示させたい場合、の「-1,212,153,856」を左に5ビットシフトすると「-134,217,728」になるのだが、 これはマイナス値なので、「5を表示する場合、セグメントA(一番上の横棒)は光らせる」という具合である。
B~Gまでのセグメントも同様に、それぞれの信号を表示したい数字の分だけビットシフトした結果がマイナスかどうかで、光らせる/光らせないを判断できる。
ちなみに「0」を表示させたい場合は各数値を左に0ビットシフトする。 その場合各数値は何も変動しないのだが、 上記表を見るとまではマイナス値でだけがマイナスではないから、 よってセグメントA~F(=外周全部)を光らせ、セグメントG(真ん中の横線)は光らせなければよいとわかる。 7セグで外周全部だけが光ったらどんな数字が表示されるかを考えれば、仕組みにご納得いただけるだろう。
なお左ビットシフトは算術回路の「<<」演算子で計算できる。


再び簡略図。
万の位の各セグメント点灯計算では「それぞれ」を使い、からまでの各信号をそれぞれ万の位に表示させたいの値で左ビットシフトしている。
「日」の字に配置された各ランプは、それぞれ自身のセグメントの信号がマイナスなら光るよう点灯条件を設定しているので、計算結果に基づいてランプが光る。
ちなみにランプに色を付けたい場合は、定数回路に色信号を追加し、各ランプの「色の使用」に✅を入れておこう。

これで、今までに打ち上げたロケットの数をデカデカと表示することが可能になる。
もちろんロケット以外の数字も表示できるので、例えば蓄電池の電池残量を1%刻みで表示し、20%を切ったら数字が赤くなるようにしたりすると、 最高にドキドキする夜を過ごすことができるだろう。


せっかく思いついたので実際やってみた。電池残量50%以下で黄色、20%以下で赤になる。
色の切り替え方法は前回の記事に書いた一灯式残量表示器の応用。
ちなみに百の位は電池残量が100の時だけ光ればいいので条件回路で「電池残量=100」を判定させて手抜きした。
10%未満の時は十の位が光らないおまけつき。建設計画

寿司ベルトでアイテムを混在させて送る

累積回路の有用な使い方のもうひとつが通称“寿司ベルト”。 これは回転寿司の要領で、1本のベルトに複数のアイテムを混在させて送る技術である。

ベルトにアイテムを流すとき、量が多すぎると詰まって流れが悪くなり、少なすぎると途中で消費されて、 どちらにしてもうまく行き渡らない、といった現象は熟練の工場長なら容易に想像がつくだろう。
ではどうすればよいか。ちょうどいい数のアイテムを流せばいい。そんな時に役立つのが累積回路である。

例えば、ベルトにアイテムを3個載せたときは「+3」、ベルトからアイテムを1個取ったときは「-1」という信号を出力させる。
累積回路は今までに入力された信号をすべて累積するので、3個載せた、1個取ったという今までの増減履歴を全部累積していくことで、 現在のベルト上のアイテムは(+3)+(-1)、つまり2個である、というようなリアルタイムの在庫数把握が可能になる。
あとはその数が「ちょうどいい在庫数」より少ないときだけアイテムをベルトに載せる、要するに在庫を補充してやれば、 ベルトの上の在庫をちょうどいい数に自動で保てるというのが寿司ベルトの考え方である。

実際の例を見てみよう。以下の図は、研究所に寿司ベルトを使った場合の例である。


ここでは1本の寿司ベルトに7種類のサイエンスパックを混載している。
寿司ベルトにパックを載せる際は、たとえば「赤パックが+3」のような信号をインサータが出力するので、 これを累積回路(画像の算術回路2)に足し算する。
寿司ベルトからパックを降ろす際は、インサータは「赤パックが+1」のような信号を出力するが、 これは画像左の算術回路1にて-1を掛けられて符号反転されるため、 「赤パックが-1」というマイナス値に変換されたうえで累積回路に足し算されることで在庫の減少が把握され、 寿司ベルト上の現在のパック数がリアルタイムで把握可能になる。
補充側のインサータには作動条件として「現在のパック数<ちょうどいいパック数」が設定されているので、 この条件がYESになったときだけ補充が行われることで寿司ベルト上のパックがちょうどいい量に保たれる。
ビーコンをなくして小さめにした寿司ベルトサンプルの建設計画はこちら

研究所は最大7種類のサイエンスパックを消費するので、通常であればベルトが4本必要になるのだが、 寿司ベルトなら1本のベルト上に7種類のパックを同時に送れるのでベルトを節約でき、見た目もシンプルにできる。
ちなみに上図で補充側のインサータが横一列ではなくジグザグに並んでいるのは、ベルトの左右にアイテムを分散させるためである。
インサータはベルトの自分から遠い側にアイテムを置くため、補充用インサータを横一列に整列させてしまうとベルトの片側に7種全部のパックが載ってしまう。 ジグザグに配置することでベルトの両側をバランスよく使うことが可能になる。
またこの仕組みなら同じ色のパックは常にベルトの同じ側に並ぶので、ベルトの両側に7色のパックがぐちゃぐちゃに混ざって流れる場合に比べれば見た目のカオス度が多少和らぐ効果もある。

なお寿司ベルトにおける「ちょうどいい数」は、ベルトの速さや長さ、そしてアイテムの消費速度が影響するので一概には言い難い。
実際に寿司ベルトを運用してみて、補充したアイテムの一部がベルトを1周して戻ってくる量を見極めよう。
全く戻ってこないなら足りていないし、ほとんど戻ってくるようなら多すぎる。
どんどん補充してもほとんど戻ってこないようなら、ベルトの速度を上げるかプラントの規模を小さくすることを考えよう。
いずれにせよ、プラントの稼働開始直後は大量にアイテムを消費するし、安定稼働に入れば消費速度は低下するし、 プラントが一斉に動き出した場合はあるタイミングでアイテムが一斉に消費されるなど減り方にムラがあるかもしれないので、 短期的な見た目ではなく様子を見ながらゆっくり寄せていく感じで調整するのがよいだろう。

注意点として、工場長は寿司ベルトから直接アイテムを拾わないようにしよう。
インサータと違って工場長はレッドワイヤーに繋がれていないので、 工場長がアイテムを拾っても「赤パックが-1」のような信号が発生せず、在庫の減少が累積回路に把握されないので、 拾ったアイテムの数は在庫誤差として永久に残ってしまう。


ちなみにこの画像の左側のように、インサータを使わずベルトだけで寿司ベルトを作ることもできる。
ただしこれには、停電時に正しく動作しなくなるという欠点がある。
停電が起きると算術回路が計算をしなくなるので、たまたま補充中(ベルトが稼働中)に停電が起きると復電までベルトが動きつづけて補充が続いてしまい、ベルトにアイテムが溢れかえってしまう。
インサータでアイテムを補充する場合は停電するとインサータ自体が止まるので、アイテムが溢れることはない
ちなみにベルトを使う場合、アイテムを補充するベルト(動く/止まるを切り替えるベルト)と、補充されたアイテムの数を数えるベルトを共用ないし隣接させるとカウントが正しく行われないようで、 時間と共にだんだん数字がずれていってやはりアイテムが溢れかえるため、上記画像ではこれらを1マス開けた別のベルトで行う対応を取っている。

おまけ:次期バージョンで追加される回路機能(2023/11/18追記)

累積回路の話題から逸れるが、ゲームの開発者ブログにおいてFactorioの今後のバージョンアップについての 情報が公開されたので最後に少しご紹介。
(以下すべて限られた情報からの推測。)
次期バージョンではいろいろな機能がいま以上に洗練され、さらにSelector combinator(選択型計算回路?)という装置が追加されるらしい。
これは算術回路と同じように入力と出力を持ち、以下6種のうち選択した計算を行いその結果を出力してくれるようだ。

入力信号を並び替えてn番目を取り出す
何を基準に並び替えるのかは不明だが、昇順か降順か・そのうち何番目を取り出すかを指定できる。
ちなみに「アイテムリスト順の1番目を取り出す」であれば条件回路の頁で書いた通り 「いずれかが≠0ならいずれかの入力数」を使えば現在のバージョンでも可能。
入力信号の数を取り出す
例えば鉄板と銅板とプラスチックの信号があれば結果は3。
これも条件回路の頁で書いた通り 「それぞれが≠0なら木材が1」を使えば現在のバージョンでも可能。
入力信号のうちランダムなひとつを取り出す
一定時間おきに再抽選される。
これは例えばタクシーの例のように、 1つの要求チェストから複数のアイテムを積み込む際に、まだ要求チェストにないアイテムをスキップして別のアイテムの積み込みを試みるときに便利だろう。
スタックフィルター(白)インサータはアイテムフィルターを1種類しか指定できないが、 複数のアイテムリストから高速で再抽選を繰り返せば疑似的に複数のアイテムフィルターを設定した白インサータが作れるかもしれない。
プログラミングでよくある「n以上m未満の乱数を生成」という要件には直接の答えにはならないのかな。
やるなら定数回路にn以上m未満の信号をすべて定義してランダムなひとつを取り出して算術回路で 「+0を木材」して値を木材に集約するノリだろうか。定数の定義が大変だ。
入力信号をスタック数に変換する
例えば鉄板は100枚で1スタックなので、101枚あればスタック数は2になる。
1スタックの量はアイテムによって異なるため、今までアイテムの量からスタック数を簡単には計算できなかったが、これが改善される。
列車の貨車は荷物を1両40スタック積めるので、「荷物が40スタック貯まったら積み込みを開始する」といった使い方が考えられる。
入力信号を重さに変換する
次期バージョンではロケットの積載枠が複数になり、代わりに最大積載重量が設定されるようなので、 荷物が一定量貯まったら自動でロケットに積み込んで発射したりできるかもしれない。
入力信号を品質値に変換する
次期バージョンではアイテムに通常品質~高品質の品質値がランダムに付与されるらしいのでそれに関する何かだろう。

実際のバージョンアップは当面先のことだろうが、興味があれば上記機能を使ってどんな新しいことが可能になるか、想いを馳せて待つといいだろう。
その他の回路系バージョンアップ情報: 2024/1/293/17

基本編 > 入力・出力・混合編 > 定数・算術回路編 > 条件回路編 > 実践例編 > 累積回路編

この記事を評価

この記事にコメント

  1. ...

【この記事にコメント】
お名前:
コメント:

Menu