並列駅の回路制御
前回の記事で搬入駅の回路についてあまり詳しく書かなかった&不完全だったので、今回は複数の列車をうまく制御するための回路をどう考えて組んだかについて書きます。
Q.回路は必要?
A.生産ラインを繋ぐ上では不要です。回路によってできることは、大抵は効率化だけかと思います。
例えば、以下のやつです。
したがって、一応動くけどもうちょっと思い通り動いてほしいな~、というときに回路を使って解決します。
問題を設定・洗練する
とりあえず問題設定
論理回路は難しいので、最初にやりたいことを明確にしたほうがいいと思います。
以下の具体例を考えます。
画像のような複数並列させた搬入駅において、次のことを実現させたいとします。(もう実装済みだけど)
- 鉄板が足りていない駅に優先的に列車が入るようにする。
列車の行き先の操作には、信号を赤にする他に、駅の有効/無効を制御する方法があります。これを使ってもう少し具体的にすると、
- 鉄板が不足している駅のみを有効にし、十分な駅を無効にする。
となります。
しかし前回の記事でも書いた通り、このまま実装してしまうと、全駅のバッファが十分になるとすべての駅が無効になってしまい、機能しなくなります。したがって、さらに条件を追加します。
- 鉄板が不足している駅のみを有効にし、十分な駅を無効にする。
- すべての駅が無効となるとき、すべての駅を有効にする。
ここまでは前回書きました。
バグから仕様変更する
しかししかし、この回路を組んで動かしてみて気づいたのですが、
- 鉄板が不足している駅すべてに列車が停まっており、列車の停まっていないすべての駅に十分な鉄板があってその駅が無効化されているとき、新しい列車が使用中の駅に侵入しようとしてしまう。
- 列車が駅に進入している途中で、(他駅の鉄板が消費されて足りなくなり、有効/無効が切り替わるなどして)向かっている駅が突然無効化されてデッドロックが起きる。
という2つの欠陥がありました。特に2つ目の欠陥は致命的です。1の欠陥は使用中の駅を無効にすることで、2の欠陥は列車が進入中の(信号が緑でない)ときにその駅を有効にすることで解決できそうです。よって最終的には要件を以下のようにします。条件は上から優先されます。
- すべての駅が無効化されようとするとき、すべての駅を有効化する。
- 以下のいずれかを満たすとき、駅を無効化する。
・列車が停車している
・鉄板が足りていてかつ信号が緑である(侵入中の列車が存在しない)
式を立てる
ここからは、いわゆるブール代数で立式します。今回エンティティから拾う欲しい情報は以下の項目です。n個の駅を想定します。
- k番目の駅への信号が緑であること(緑[k]とします)
- k番目の駅の鉄板が足りていること(足[k])
- k番目の駅に列車が停車していること(T[k])*1
k番目の駅を有効にすることをX[k]とすると、X[k]は以下の式で表されます。式変形の際は各式をひとつの算術回路か条件回路で表現できる程度に分解します。("<"とか"≧"は不等号?ではなく二項演算子です。)
これをもとに実際に駅を作ってテストしてみます。
実装してみた。
駅の数は4つ、鉄板不足の条件を鉄板200枚未満に設定してみました。右から2、4番の駅に225枚の鉄板を入れたので、駅が無効になっているのが分かると思います。(駅のライトが黄色ではなく赤色になっています。)
次の画像の通り列車を一本自動で走らせてみたところ、1番の駅に入り、1番の駅が無効になりました。
もう一本走らせると、予定では3番の駅に入って3番も無効化され、これによりすべての駅が無効になろうとするのですべての駅が有効となります。次の画像で確認しましょう。
たしかにすべての駅に黄色いランプが点いています。次にさらに列車を走らせ、2番への進入中に4番の鉄板を減らしてみます。以前であれば2番の駅が進入中に無効となり、デッドロックが起こっていましたが、改善されてるかな?
画像では2番の駅のブロックが予約済みになっているため、信号が黄色になり、駅が有効になっているのが分かります。これでデッドロックも起こらなさそうです。よかった。
現在僕の工場は全部この回路を使って動かしていますが、今のところデッドロックは起こっていません。
まとめ
Factorioの基本アイテムはデフォルトでとても優秀なアルゴリズムで動いているので、そのままでも十分使えると思います。ただ、生産性や効率性を限界まで追求するためには、回路による制御は必要不可欠です。
ぼくもやっと最近触り出したばかりなので、こういうところに回路をこう使えば便利などといった知恵があればまた記事にすると思います。次回の内容はなににしようかな。
*1:二値ではなく列車のID(正の整数)で代用しています。
鉄道と工場デザイン
しばらく放置してましたが最近また復帰したので、久しぶりに更新します。
今回は遠距離運送の基本となる鉄道ネットワークらへんについて考えます。(試行錯誤中なのでまだまだ変わると思いますが。)画像が多くなってしまいましたすみません。
碁盤型vs直通型
工場の規模が大きくなるにつれて、アイテムの運送は列車で行うのが主になります。
線路の敷き方には大きく分けて、幹線を張り巡らせる方法(碁盤型など)と、列車を往来させる工場同士を直接結ぶ方法(直通型)の二通りがあります。
それぞれのメリットとデメリットについて考えてみました。
碁盤型
メリット
- 拡張性がある
- 美しい
- 計画しやすい
- 迂回ルートが多くある
- 同時走行できる列車の容量が大きい
デメリット
- 交差点が増える
- 巨大なスペースが必要
- 無駄な線路が多い
直通型
メリット
- 往来が早い
- 交差点が少ない
- 省スペース
デメリット
- 見た目が汚い
- 同時走行できる列車の容量が小さい
- 拡張性があまりない
往来の遅さは本数を増やすことでカバーできるので、ぼくは碁盤型の工場を作っています。
汚くてごめんなさい。でかいのはソーラーパネルです。
幹線のデザイン
幹線は上下線それぞれ2車線で十分かなと思います。(勘です)
通常思いつく線路の向きは左側2本が上り、右側2本が下りといったデザインですが、左から順に上り、下り、上り、下りというように、交互にしたほうが交差点で進行を妨害する数が少なくなるみたいなのでそうしました。(その代わり交差点以外での車線変更時に別の車線を跨ぐ必要があります)
工場の形
各工場はひとマスの中でひとつのアイテムを製作するように作っています。集積回路みたいなイメージ?なんですが。
列車の混雑を避けるために、別の工場の出入り口がぶつからないよう工場を回転させて配置させているので、同じ形の工場でも向きが違ったりします。
また燃料を積んだ列車を一本、各工場の搬入口に走らせ、すべての列車が工場の搬入駅でついでに燃料補給ができるようにしています。
搬入口のデザイン
搬入口は荷卸し駅及び、それと同じ数の待機駅、燃料駅からなります。搬入口にやってきた列車はまず待機駅に入り、折り返して荷卸し駅へ、空になると荷物を補給しに別の場所へ向かいます。
列車の細かい制御には回路を使っています。以下はその説明。
回路を使わないと困ること
- いちばん近い駅に入ろうとするので奥の駅のチェスト(バッファ)の残量がなくなりやすい。
- 待機駅まですべて列車で埋まっているのに、新たな列車がこの工場に侵入しようとしてしまうことがある。
これら(主に2番)をどのように解決すればよいかを考えるために、次のことを調べました。
列車の経路選択アルゴリズム
Factorioの列車の経路探索のあれこれは思ってたよりも複雑でした。今回の記事で参照した仕様について一部ピックアップします。(間違ってるかも)出典は公式ウィキです。*1
経路探索では、まずスケジュール中の名前にマッチする無効でない駅を列挙し、A*アルゴリズムにより最もコストが小さい経路を選出します。
- 基本コストは駅までの道のり。(レールの中央線の長さ)
- 別の列車があるブロックには 2*(ブロック長)/(そのブロックまでの距離) のペナルティコストを加算(つまり、遠い場所にある場合はほとんど影響がない)
- 回路により赤信号に設定されているブロックには1000のペナルティコストを加算
- 別の列車が停車している駅が経路に含まれる場合、500のペナルティコストを加算
つまり、待機所が埋まっているのに新しく列車が来てしまうのは、別の空いている待機所が遠すぎて、近くの空いていない待機所のほうがコストが小さいせいだということのようです。待機所がフルの時になるべくペナルティコストが課されるように回路で制御すれば、別の空いている同名駅へ向かってくれるというわけです。
回路で実現していること
簡単に説明すると、次のように回路を組んでだいたい解決しました。
- チェスト(バッファ)の残量が多い(荷卸し)駅を無効にし、少ない駅に優先的に入るようにする。すべての駅が無効になると、すべての駅を有効にする。
- 待機駅がすべて列車で埋まったとき、信号を赤に変えて新たな列車の侵入を禁止する。(+1000ペナルティ)ただし、燃料補給列車が近づくと信号を青に変えて侵入を許可する。さらに待機している列車は荷卸し駅が空くまで発車しないようにする。(+500ペナルティ)
具体的にどう回路を組んでるかは説明すると逆にややこしくなりそうなので、画像だけてきとうにポポポンと貼っておきます。がんばって解読してください。
追記:しばらくこの構造を使っていたのですが、工場を大きくしていくうちにペナルティに対して距離が大きくなりすぎてうまく働かなくなりました。代わりに、「停車中の待機駅を無効化するだけでよくない??」ってことに気づき、今はそれに置き換えています。(簡単に解決できました。)
現状思いつく問題点
現在、荷卸し駅+待機駅の数だけ列車を走らせてるのですが、例えば4つの荷卸し駅のうち3つが無効化されていて、有効な1つに列車が停車、待機駅が満車の場合、満車にもかかわらずこれらの駅にいない3つの列車がここに向かってしまうという問題があります。解決するには、1の解決策を次のように改変する必要があります。
- チェスト(バッファ)の残量が多い(荷卸し)駅を無効にし、少ない駅に優先的に入るようにする。列車が停車していないすべての駅が無効になると、すべての駅を有効にする。
追記:次回の記事にて少し異なる方法で解決しています。
搬出口のデザイン
搬出口もだいたい搬入口と同じですが、燃料の補給は行わないのでいくらか簡単です。
こちらの積み込み駅では、荷卸し駅とは逆に一定以下のバッファしかない場合に駅を無効化しています。
まとめ
最初は戸惑う信号の仕様とかすっ飛ばして経路探索アルゴリズムのこととか書いてしまいました。信号の置き方とかも記事にしようかなと思ったんですが、使っていくうちに理解できるんじゃないでしょうかどうなんだろう。
公式ウィキを読んで鉄道のいろいろを理解するのが鉄道ネットワークマスターへの近道だと思います。(鉄道のページは日本語訳されていますが、残念ながら経路探索アルゴリズムのページの日本語版はまだないです)
次またネタがあれば更新します。モチベにもなるしネタにもできるので良ければコメントくださいませ。
生産力とは?
最初の記事は生産力について書くって決めていました。
挙げているコンセプトの中に
-
サイエンスパックの生産力の向上を目指す
と書きましたが、この''生産力"について基本的なことをまとめておきたいと思います。
生産力とは?
最初このゲームを始めた時は生産ラインをつなげていくことで精一杯でしたが、より沢山の生産品が必要になってきてたところで、いかに(時間的な意味で)効率的に多く生産ができるかについて考えるようになりました。
そこでぼくがこのブログで使う"生産力"は次のように定義します。
-
単位時間当たりの生産個数(/s)
注意しておきたいのは、単位資源から得られる生産個数ではないということです。
バニラでやってる方はもちろんいかに限られた資源で多く作るかという課題もありますが、生産力を上げる課題に集中するためにぼくは無限資源modを導入しています。
したがって、いかに超高速運送ベルトをアイテムで埋められるかがメインの課題となります。
生産力を上げるには?
生産力を上げるには、以下の項目によって実現できます。
-
同じ生産ラインを並べる
-
組立機や炉などのグレードを上げたり、生産速度モジュールを使うことで製作速度倍率を上げる
-
生産力モジュールを使用する
しかし生産力が落ちる原因として、次の項目が考えられます。
-
十分な素材資源が確保できていない。
-
アイテム運送能力が追い付いていない。
基本的にはこの二つだけです。
例えば鉄鉱石から鉄板を生産するラインを考えた時、
多くの炉を並べたり、電気炉を使ったり、生産力モジュールを使うことでより多くの鉄の生産能力が得られますが、炉にくべる鉄鉱石を消費速度と同じ速さで採掘できていなければいけません。
また鉄板を取り出すインサータの動きが遅かったり、入出力の運送ベルトの運搬能力が不十分だと、鉄鉱石が足りなくなったり鉄板が詰まったりして生産力が落ちてしまいます。
したがって、設置した工場が最大生産力を発揮するためには、入力資源の確保と、十分なアイテム運送能力の確保が必要になり、そのためには運送ネットワークの各アイテムの能力を知る必要があります。
具体例を考える
生産力を最大化する具体例を考えます。
1.目標の生産力を決める
例えば
-
鉄板から鉄の歯車を毎秒5個生産したい
と定めます。鉄の歯車は通常「鉄板2枚から0.5秒で1個」製作できます。
2.必要な組立機の個数を計算
手で製作した場合、1秒あたり2個製作できます。今回組立機1を使用するとすると、組立機1の能力は製作速度0.5なので、手で作るよりも0.5倍の速度でしか製作できません。
したがって組立機1の個数をn個とすると、目標を満たすためには次の不等式が成り立ちます。
0.5×2×n ≧ 5
n ≧ 5
すなわち最低5個の組立機1が必要となることが分かります。
3.必要な入出力装置を選ぶ
ここは難しいので失敗例を次に紹介します。
生産力が落ちる失敗例と改善例
たとえばこのように配置したとします。このまま経過を観察すると、奥のほうの組立機が動いてくれません。その原因についてみていきます。
原因1: 入力搬送ベルト
その原因の一つに、右側の搬送ベルトの能力が不十分であることが考えられます。
今回の例では毎秒5個の鉄の歯車を製作するため、毎秒10個の鉄板を消費します。
搬送ベルトの運送能力は毎秒13.33個と書かれていますが、これは両側に最大限敷きつめた状態での能力値です。
写真の配置ではインサータはベルトの右側にしかアイテムを流さないため、実質最大運送能力が毎秒6.665個となり、毎秒10個の鉄板をさばけていない状態なわけです。
原因2: 積み下ろしインサータ
ここで原因1から右の運送ベルトを、片側の最大運送能力が13.34/sである赤ベルトに差し替えれば解決できると思いきや、じつはまだうまく最大能力が発揮できません。
それは右下のチェストから鉄板を取り出すインサータの能力が原因です。
具体的な取り出し能力はゲーム中には出てきませんが、独自に計測してみたところ、赤ベルトに対する高速インサータの運送能力は6.02/sほどみたいです。(もちろんインサータ容量ボーナスによりますが今回はインサータ容量3としています。)
これをスタックインサータ(赤ベルトに対する運送能力10.17/s)に交換すると、運送能力が十分になり、無事毎秒5個の鉄の歯車の生産に成功しました。
以上のように入出力装置は、どれか一つでも能力が低いと、生産力がその分しか発揮できなくなります。全体のスループットを上げるには、すべての装置の能力が相応のものでないといけないというわけです。
まだまだ改善の余地はたくさんあるのですが、キリがいいので今回はここまでにします。次回からは実際にプレイで役立つ記事を書きたい。
Factorioブログ始めました
Factorioブログ始めました。
理由は主に3点。
-
メモ用
-
技術的な攻略の供給がすくない
-
日本でFactorioもっと流行ってほしい
一番最初の記事なので方針とかついてまとめます。
Factorioとは
Factorioを知らない人が見ているかどうかわかりませんが、方針の前にその人用に一応紹介しておきます。
Factorioは特に産業に重点を置いた2Dストラテジー・サバイバル(?)系ゲームです。
道の惑星に不時着したプレイヤーが、惑星に住む生物バイターからの襲撃に対応しながら、惑星資源を使ってロケットを打ち上げるまでがんばる、といった設定になっています。
何が面白いかっていうと、
-
序盤はできることが少なくて手作業が多いが、そこから研究を行うことで効率の上昇や製作の自動化が進み、できることが各段に増える。
-
後半は生産ラインの効率化を進めていけばいくほど奥が深くなり、ロケット打ち上げ後も工場の拡大という楽しみがある。
ぼくはこういうゲームを黙々としてしまうタイプなので同じようなタイプの人はこのゲーム好きだと思います。
この記事を書いた時点ではバージョン0.16が最新版で、公式HPおよびSteamにて3,000円で購入できます。なんでもこの4月(2018)に正式版発表に向けて値上げしたんだとか(永遠のベータ版脱出?)。
無料のデモ版も置いてあるので気になった方はぜひやってみてください。
ブログ方針
このブログではぼくがFactorioをやるうえで(もしほかにやってる人がいるなら)共有したいなと思ったアイデアや考察をメインに、自由に記事を書こうと思います。
コンセプトとして
-
各サイエンスパックの生産力の向上を主に目指し
-
なるべく理論的に、万人にわかりやすく
-
各種アイテムやモジュールの考察を行う
を挙げておきます。
ほとんどの記事は、(ロケット打ち上げをゴールとすると)ゲーム終盤か、ゲームクリア後に役立つ(かもしれない)内容になってしまうと思います。
たまに初心に帰って 、序盤中盤の工場長の参考になるような記事もできれば書きたいと思っている所存です。
ただし、ぼくのゲーム内では無限資源modを利用しているという前提で考察するので、資源枯渇したらどうするんだ?って疑問が起こらないようご注意ください。
では以降よろしくお願いします。ばいばい。