FactorioのRNGを解析して完全攻略する方法
Reversing Factorio's RNG
Reversing Factorio's RNG
Factorioの乱数生成(RNG)をリバースエンジニアリングして、挙動を解明する方法についての議論です。ゲーム内の決定論的なシミュレーションを逆手に取り、乱数シードを特定することで、特定のイベント(アイテム生成や汚染の拡散など)を意図的に制御するための知見がまとめられています。
めっちゃいいじゃん。
変態だな。最高。
大学の入門クラスでこれの簡易版やったことあるわ。じゃんけんが絡むコンペがあったんだけど、あいこはランダムで決まる仕組みだったんだ。JavaのPRNG(疑似乱数生成器)をいじって、あいこを全部勝てるようにしたよ。
そのPRNGは最初の呼び出し時のマイクロ秒単位の時間でシード値が決まる仕様だったから、乱数を何度も空打ちしてエントロピーを回収しつつ、ありそうな時間を総当たりしてシードを特定した。で、PRNGを仕込んであいこに全部勝てるようにしたんだ。
正直、実装が間違ってた可能性もあるけど、理論としては成立してたw
素晴らしい成果だね!
Stardew Valleyには2種類の乱数シードがあるよね。一つは普通のキャラクタシード、もう一つはマルチプレイヤーIDで、こっちはセーブファイルを解析すれば特定できる。
ただ、Switchだとセーブファイルにアクセスしにくいし、PC版と乱数生成器が違うんだよね。Switchには行商人の在庫リストからキャラクタシードを計算するシードクラッカーがあるけど、もう一つのシードを解析するツールは見つかってないし、自分で作る時間もないんだ。
ジオードの中身を調べていけば、マルチプレイヤーIDを特定して、PC版のプレイヤーが過去10年やってきたみたいにSwitchでも乱数イベントを予測できるようになるはず。
ゲームのC#コードは公開されてるし、SwitchのRNG(乱数生成器)も分かってるから手探りってわけじゃない。やることは3つ。まず通常のシードを使ってSwitch側のRNG実装が正しいか確認する。次にPC版のRNGでジオード用のRNG実装を確認する。最後にSwitchのRNGをジオード関数に適用して、観測した結果と一致するシードを絞り込むんだ。
あと、関連する疑問が2つある。最初のジオードじゃなくて、途中のジオードから始めても同じ速度で解けるのか?あと、RNGはいずれループするから、一意のシーケンスさえ観測できればマルチプレイヤーID自体は何でもいいってことになるの?
このゲームに関しては今まで見た中で一番の黒魔術だわ。
自分はFactorioそこそこ中級者で、ベルトのバランサーとか線路の交差点以外は自力で設計する派だけど、これはどうやってるのか全く検討もつかない。
boostのジェネレーターの中で一番速いからという理由でtaus88を選んだ
それ1996年のRNGだよ。最近のC++標準もboostも、もっと高速でテストスイートの通過性能も高い現代的なPRNGのことは知らないみたいだね。
追記:上の引用は2014年のものだったわ。boostも今は少しは理解してるみたいだな! https://www.boost.org/doc/libs/latest/doc/html/boost_random/
ランダムに見えるものでも、裏の仕組みを理解すれば予測可能になるっていう素晴らしい例だね。
いいね!LFSR(線形帰還シフトレジスタ)についての詳細情報はここにあるよ: https://www.embeddedrelated.com/showarticle/1309.php
こういうこだわり最高。これでようやく、マップを何度も作り直さなくても最初の資源配置を最適化できるぞ!