【Minecraft】シード値指定の場所に文字を入れたらどうなるの?
スポンサードリンク
こんにちは。ふぁんたです。
Minecraftというゲームがありますね。
無限に広い世界で、作ったり、潜ったり、戦ったり、生活したりするあのゲームです。
あのゲームに、ワールドを生成するために用いられる「シード値」という物があるのはご存知でしょうか。
シード値を入力せずにゲームを始めると、シード値はランダムでワールドもランダムに生成されますが、
同じシード値から生成されたワールドは、全く同じ形をするという特徴があります。
もちろん、バージョンが違えば同じシード値でも違うワールドが生成される(アルゴリズムが変わる)ので、
バージョンをまたいで同じというわけには行きません。
そんなシード値に、「文字」を入力したら、一体どうなるのでしょう、というところを調べましたので、報告します。
注意
前フリとしてコンピューター内部の数字の持ち方の話をしますが、ここをちょっと長めに話すつもりです。
そんなの知ってるよ、という方は飛ばしてください。
Contents
コンピューター内部での数字の持ち方の話
すいません、この話をしないと、なんでシード値がそうなるのかというところが理解できないので、この話を先にさせてください。
御存知の通り、コンピューターは「0」と「1」しかわかりません。
正確には、「電気が流れてるか」「電気が流れてないか」というような部分の判別しかできません。
それなのに、数字を使った計算なんかがすごいスピードでできてしまうのがコンピューターですよね。
じゃあ、どうやって数字を保存しているのかと言うと、「二進数」というのを使っています。
例えば、0と1の2通りが取れる桁が6つあるとすると。
2×2×2×2×2×2=64パターンの組み合わせがあり、それぞれの状態に、
我々人間が使っている数字を割り当てるという方法で数字を保持しています。
(プログラミングとかの世界では)一般的に、これを「32桁」用意して、1つの数を表します。
32ビット = 0か1の桁が32個 という理解で大丈夫です。
その32桁を使って表すことのできるパターン数は、2^32パターンあります。
(2^m とは、2をm回かけ合わせたものという意味です)
2^32とかくとどれぐらいかわかりにくいのですが、
4294967296。だいたい43億ぐらいです。
で、これらのパターンを人間が使うとき、各パターンに1 ~ 2^32 の数字を…
…割り当てることはしませんでした。
0も使いたいですので。
じゃあ、1だけ左にずらして、0 ~ 2^32-1 としたかというと、そうでもありませんでした。
マイナスも欲しかったのです。
なので、
-2^31 ~ 2^31 – 1 を各状態に割り当てました。
なので、プログラム上では、2^31-1に対して1を足すと、
2^31になるところが、マイナスになってしまいます。
試してみてください。
7行目で2^31を、8行目でそれ+1を出力しようとしています。
結果として、正の数同士を足しているはずなのに、いきなりとってもマイナスな数字が現れたと思います。
後で説明をするのに使うので、
-2^31を【数字の下限】
2^31-1を【数字の上限】
と呼ぶようにします。
確認ですが、2^31がだいたい21億ぐらいになります。
で。
金融の世界とか、桃鉄の世界とか、21億じゃ全然足りないということもあるかと思います。
5000兆円ほしいのが、21億円で限界になってしまいます。
そこで、0と1の桁を32桁でなく、64桁使うというルールも考えました。
これも同様に、2^64パターンを、
-2^63 ~ 0 ~ 2^63 -1
へと割り当てました。
これで、21億では表せない大きさの数字も表すことができるようになりました。
2^64はだいたい1844京(兆の次)なので、5000兆円でも余裕で収まる桁数です。やったね。
これも後の説明で使いたいので、
-2^63を【長い数字の下限】
2^63-1を【長い数字の上限】
と呼ぶようにします。
シード値の話
※確認
この記事では、
-2^31を【数字の下限】(-21億ぐらい)
2^31-1を【数字の上限】(21億ぐらい)
-2^63を【長い数字の下限】(-922京ぐらい)
2^63-1を【長い数字の上限】(922京ぐらい)
と呼ぶようにしています。便宜上。
ようやく本題です。長々とすいません。
実は、ワールドの生成方法には4パターンあります。
1.シード値を指定しない場合
2.【長い数字の下限】から【長い数字の上限】までの数字を指定する場合
3.文字(=数字でないもの)を指定する場合
4.数字ではあるものの、2のパターンに当てはまらないサイズの数字を指定する場合。
それぞれのパターンについて解説します。
1.シード値を指定しない場合
これは、ランダムなシード値が選択されます。
そのランダムの幅は、
【長い数字の下限】から【長い数字の上限】
までになります。(-2^63 ~ 2^63-1)
2.【長い数字の下限】から【長い数字の上限】までの数字を指定する場合
これについても、1.と同じく、
【長い数字の下限】から【長い数字の上限】
までになります。(-2^63 ~ 2^63-1)
つまり、入力したシードの数字が予め決められている範囲に入っていれば、その数字がちゃんと適用されたワールドが生成されるということです。
ここまでは、まあ当たり前というか、直感通りといった感じです。
3.文字(=数字でないもの)を指定する場合
ここからが問題です。
文字を指定した場合、どういった挙動になるでしょう。
シード値が1文字のとき
例えば、シード値を
d
とします。(小文字のDひとつ)
唐突ですが、こちらのページを御覧ください。
Unicodeという文字コードの一覧表になります。
0060と書いた行の、4番目の列に、今の小文字のdがあることがわかります。
つまりこのdは、0064番目の文字だということを表しています。
この0064は16進数なので、10進数に直すと、dは100です。
よって、シード値が100になります。
シード値が2文字以上のとき
次に、2文字以上の時を考えましょう。
d=100ということがわかっているので、今回もdだけで、
シード値を
dd
としましょう。
一番右のdについては、d1文字と同じように処理します。
問題は、一番左のdです。
これについては、
「文字コードの31倍を足す」という計算をします。
シード値の指定がddだと、31*100 + 100=3200 がシード値になります。
同様に、3桁だった場合は、
1桁目は何もかけず足す
2桁目は31をかけた値を足す
3桁目は31×31をかけた値を足す
といった処理でシード値を求めることができます。
公式にすると、
右からi桁目の数字について、「31^(i-1) × その文字のUnicodeの値」 を全部足したもの。
式っぽく書くと、右からi番目の文字をSi、文字CのUnicodeの値をUnicode(C)、シード値の長さをseed.Lengthと置くと、
シード値は上記の式で表されます。
…ですが、計算はこれだけではありません。
これによって計算された数字は、
【数字の下限】~【数字の上限】に入っていなければならない
というルールがあります。(長いほうではない。-2^31 から2^31-1まで)
ですが、31^6なんてすると非常に大きな数字になり、【数字の上限】をかんたんに超えてしまいます。
超えたぶんについては、「ループ」が起こります。
つまり、【数字の上限】+1=【数字の下限】として計算しなければならない、ということになります。
計算によって出てきたシード値が【数字の上限】+30なら、
シード値の計算においては【数字の上限】+1 = 【数字の下限】なので、
実際に生成されるワールドのシード値は【数字の下限】+29 ということになります。
実際に提供された文字シードがどうなるか、計算して確かめてみましょう。
ファイト( ⓛ ω ⓛ *)
*[]不要
[GWエンドラ三昧終盤戦!]— 永久 (@_toowa_) May 7, 2020
[GWエンドラ三昧終盤戦!]というシードの提供がありました。
このシードを例に、シード値を計算していきます。
文字 | 文字コード | 掛け合わせる数字(31^桁数) | かけた結果 |
G | 71 | 787662783788549761 | 55924057648987033031 |
W | 87 | 25408476896404831 | 2210537489987220297 |
エ | 65396 | 819628286980801 | 53600411455396462196 |
ン | 65437 | 26439622160671 | 1730129555327828227 |
ト | 65412 | 852891037441 | 55789308541090692 |
゛ | 65438 | 27512614111 | 1800370442195618 |
ラ | 65431 | 887503681 | 58070253351511 |
三 | 19977 | 28629151 | 571924549527 |
昧 | 26151 | 923521 | 24150997671 |
終 | 32066 | 29791 | 955278206 |
盤 | 30436 | 961 | 29248996 |
戦 | 25126 | 31 | 778906 |
! | 33 | 1 | 33 |
表の一番右の数の和は、113522784495996034911になりました。 この数字は、
113522784495996034911 = 2^31 * 52863165967 + 353427295と分解できます。
ここで、【数字の上限】+ 1 = 【数字の下限】の式を変形し、
(奇数) × (2^31) + a = 【数字の下限】 + a
という式が導けます。
これを用いて、
シード値(113522784495996034911)
=シード値(2^31 * 52863165967 + 353427295)
=シード値(【数字の下限】 + 353427295 )
=-1794056353
が計算できます。
実際にこのシード値をMinecraftで使ってみると、文字を入力した場合と同じシード値でゲームが始まることが確認できます。
計算大変でした。
4.数字ではあるものの、2のパターンに当てはまらないサイズの数字を指定する場合。
数字だけを入力するという制限であっても、その数字が【長い数字の上限】を超えると、急に挙動を変えます。
シード値(9223372036854775806) = 9223372036854775806 (※【長い数字の上限】-1)
シード値(9223372036854775807) = 9223372036854775807 (※【長い数字の上限】)
シード値(9223372036854775808) = -1773151197 (※【長い数字の上限】+1)
シード値(9223372036854775818) = -1773151166 (※【長い数字の上限】+11)
これは、処理できる範囲を超える数字が入ってきた場合、それを文字列として処理する
という仕様になっていることがわかります。
文字列の詳しい処理方法は、3.の節でしっかりやってますので、そちらをご確認ください。
まとめます。
紫の線のエリアが、数字を指定した場合と、何も指定しなかった場合の取りうるシード値。
青い線のエリアが、文字を指定した場合と、紫を出るエリアの数字を指定した場合の取りうるシード値。
対数グラフなので、本当は紫のエリアのほうが、青い線の21億倍長いです。
ホントはこれよりも、ワールド生成アルゴリズムのほうが知りたいです。
スポンサードリンク
ディスカッション
コメント一覧
まだ、コメントがありません