SeedHack、完結!!

Hack

SeedHack

イカッチャのサーモンランではマッチング開始時に初期シードをホストとクライアント間で同期するのだが、擬似乱数という仕組み上最初のシードを決定すれば残りの乱数も全くおなじになる。

更に、スプラトゥーンのアセンブラを読むことによって生成された乱数からイベントIDと潮の高さを計算する関数が明らかになり、実機で検証せずともプログラム上で初期シードからどんなWAVEになるかを完全先読みすることが可能になった。

container12345氏の功績

すごく大きな成果だと思うのだが、非常にざっくばらんとまとめられている(笑)

サーモンランのイベントと水位の決定 : 記録帳
色々と調べた結果シードからイベントと水位を求めることが可能になった。乱数はこれを参考に残りは言葉で説明しづらいからこんな感じで…#たつじんeventsProbability = tidesProbability = rnd = sead.Ra

これはPythonによる実装なので、C++に書き換えてプログラムを制作した。

簡単なはずなのだが、ここがちょっと苦労した!

初期シードはu32(unsigned int)によって与えられるので、最高で0xFFFFFFFF(4294967295)通りのWAVEの組み合わせがあることになる。

そこで今回はどのWAVEのパターンが最も多いのかを調べることにしました。

WAVE情報の先読み手法

今回はどうやってコンテナ氏がWAVEの先読みに成功したのかを簡単に解説していこうと思います。

getU32()

どのように乱数が生成されているかを司るseadRandomをC++でクラスにしてくれている方がいたのでそれを参考にしました。

これさえあれば実際にイベントIDを見つけるところは別として、生成される乱数を確実に予想することができます。

simontime/Resead
Reverse engineering work of Nintendo's SEAD library. - simontime/Resead

Coop::Setting::reset()

ゲーム開始時に与えられたシードから乱数を生成してイベント情報を決定するサブルーチンです。

まず最初にsead::Random::init()で初期化しています。

実はシードが再設定されるまでこれは何回でも呼び出されて同じ値で初期化されるので、何回乱数が生成されたかということは考えなくて大丈夫なのです。

設定されたシードからgetU32()で32ビットの乱数を生成し、そこからイベントIDを決定します。

ここまでわかればあとはコンテナ氏のコードをC++に移植して実装するだけです。

実際に調べてみた

getU32()が最大42億くらいの値を返すので、理論的に発生しうる全てのWAVEの出現確率を調べてみました。

出現率TOP10

W1W2W3
通常昼通常昼通常昼9.112820%
通常昼満潮昼通常昼3.038162%
通常昼通常昼満潮昼3.037740%
通常昼通常昼干潮昼3.037598%
干潮昼通常昼通常昼3.037588%
満潮昼通常昼通常昼3.037394%
通常昼干潮昼通常昼3.036998%
干潮昼干潮昼通常昼1.012641%
満潮昼通常昼満潮昼1.012639%
満潮昼満潮昼通常昼1.012636%

当たり前と言っては当たり前だが、夜イベントが発生しないWAVEがTOP10のすべてを占めた。

特に、水位も変化しないものが9%近くもあるというのは少しばかり覚えておいたほうが良いかもしれない。

出現率WORST5

満潮ハコビヤ満潮霧干潮ハコビヤ0.000063%
干潮ハコビヤ干潮霧干潮ハコビヤ0.000063%
干潮ハコビヤ満潮霧干潮ハコビヤ0.000063%
満潮霧干潮ハコビヤ満潮霧0.000063%
満潮霧満潮ハコビヤ満潮霧0.000063%
満潮ハコビヤ干潮霧満潮ハコビヤ0.000062%

出現率が低いWAVEは霧とハコビヤの組み合わせでした。

これら二つのイベントは潮が満潮・通常・干潮の全てがありえるので必然的に珍しくなってしまうわけです。

その驚異の出現率は0.000062%なので、150000回バイトをしても一回も出会わない可能性があるくらいレアです。

乱獲に向いていそうなWAVEの出現率

ここからは独断と偏見で乱獲に向いていそうなWAVEを調べました。

全て満潮昼(0.337302%)

昼の中では最も稼ぎやすいと思われる満潮昼ですが、全部満潮にしようと思ったら0.34%くらいしかありません。

二時間やって一回当たるかどうか…という感じでしょうか。

満潮グリル・霧・グリル(0.000101%)

全て満潮でグリル・霧・グリルの順で発生するのはここで一気に下がって0.0001%となります。

リトライ可能であれば最も稼げるのはカンケツセンなのですが、そうでないならグリルが一番安定しそうな気がします。

もはや狙えるような確率ではないので完全に運任せになりますね。

ちなみに夜WAVEの発生確率は基本的には同じなので、以下のものもだいたい同じくらいの発生確率です。

展望

今回、任意のWAVEを発生させる初期シードを見つけることができたのでひとまずSeedHackは一応の解決を見せた。

まさかSeedHackが見つかってから一週間足らずで解決するとは思っていなかったが(笑)

満潮カンケツセン・満潮グリル・満潮カンケツセンというWAVEが全部で5219あるのがわかっているので、理論値追求をするならシードからカンケツセンのアタリの位置を特定する作業が必要になってくるかもしれない。

これができればいよいよSeedHackも完全に終了という気がしてきますね。

コメント

タイトルとURLをコピーしました