マイクラにじさんじ鯖のシード値を特定する
条件
マイクラ配信のアーカイブ動画を見て得られる情報から、シード値を特定する
手法
森の洋館と村の座標を、アーカイブ動画を見て調べる
森の洋館は、正面玄関に赤い絨毯があるので、その先端のチャンク座標を見る
村は井戸のあるチャンク座標を見る
これらの構造物がそのチャンクに出現するかどうかはシード値から判定できるので、全ての既知の構造物についてその位置に出現する判定となるようなシード値を探す
構造物の生成条件
チャンクの座標と、そのチャンクのバイオーム、この 2 つで判定される
チャンク座標の判定
森の洋館の場合はこんな感じ
code:java
boolean canSpawnStructureAtCoords(long seed, int chunkX, int chunkZ) {
int i = chunkX;
int j = chunkZ;
if (chunkX < 0) i = chunkX - 79;
if (chunkZ < 0) j = chunkZ - 79;
int k = i / 80;
int l = j / 80;
Random random = getRandom(seed, k, l, 10387319);
k = k * 80 + (random.nextInt(60) + random.nextInt(60)) / 2;
l = l * 80 + (random.nextInt(60) + random.nextInt(60)) / 2;
return chunkX == k && chunkZ == l;
}
Random getRandom(long worldSeed, int regionX, int regionY, int s) {
long seed = (long)regionX * 341873128712 + (long)regionY * 132897987541 + worldSeed + (long)s;
return new Random(seed);
}
バイオームの判定
森の洋館はチャンクの中心から 32 ブロック四方のバイオームが全て dark_forest または dark_forest_hills の場合に生成される
村はチャンクのバイオームが plains、desert、savanna、または taiga の場合に生成される
計算方法
シード値は 64 bit 整数
チャンク座標についての判定
java の Random を使っているためシード値の上位 16 bit が無視される
計算式が簡単なので高速に計算できる
バイオームについての判定
シード値の 64 bit が全て使われる(おそらく)
チャンク座標の判定に比べて計算が複雑
なので、候補となるシード値の下位 48bit を絞り込んだあとで、上位 16bit を含めてバイオームの判定を行った
実際の計算
森の洋館の座標を 2 つ、村の座標を 4 つ使った
チャンク座標の絞り込み
GPU で計算
AWS の p2.xlarge インスタンス 8 つで計算
1 インスタンスあたり 2 時間ちょっと、のべ約 17 時間
コストは約 27 US$
この時点で候補となるシード値は 47910 個になった(1LL << 48 個中)
バイオームを使った絞り込み
CPU で計算
AWS の c5.9xlarge インスタンス 1 つで計算
計算時間は約 3 時間
コストは約 6 US$
計算結果
シード値が 1 つに絞り込めた
「静凛の家」付近
https://gyazo.com/839426d25e98d284c110e703c6075e82
「ハジメ村」付近
https://gyazo.com/a854cde3d532086080b716698cabe1da
「アズカバン」周辺
https://gyazo.com/6e58657076680a0339180badb66d8575
「しずりんの村」
https://gyazo.com/a3d53762f42815fad9d851a573cd6e68
「いちご大墳墓」入口付近
https://gyazo.com/65d5d9a01bd71d92cfe9a5cb195b91b1
感想
にじさんじのマイクラ配信者と完全に同じワールドで遊べるのはとても助かる
本番の計算は 3600 円くらいで済んだけど、開発中の EC2 のコストは 50000 円弱かかった。財布が痛い
Tesla K80 とても速かった。候補のシード値を stdout に出力する処理を工夫する開発の方が、むしろ時間が掛かった
= GPU を休ませない工夫
シード値の探索は、1μ秒あたり 4500 シード程度の速度が出ていた
boost.compute は単に OpenCL のラッパーとして使ったけど、それだけでも使う価値あると思った
森の洋館の座標が 2 つ分かっていたので助かった。洋館 1 個だけだったら、村の座標をもっと準備しないといけなかったと思う
java の Random の実装が線形合同法で助かった