BW乱数調整解説 乱数の仕組み

ポケットモンスターBWにおける乱数の仕組みについて書きます。

・-1.ツール類
・0.用語
・1.BWにおける乱数
・2.ゲーム起動時の共通初項(初期SEED)の決定方法
・3.性格値乱数列の決定方法
・4.性格値乱数列の乱数消費契機
・5.個体値乱数列の決定方法
・6.Cギア起動時の個体値乱数列の再計算
・7.個体値乱数列の乱数消費契機

-1.ツール類

乱数調整に関連したツールを作ったのでよかったら使ってください。
・BW個体値乱数調整
・BW性格値乱数調整

0.用語

とりあえず、性格値・個体値・裏ID・16進数・疑似乱数ぐらいは知っていること前提で。
実際の定義とか割と無視で思ったように使っているのでご容赦を。
seed

前のseedによって求められ、次のseedを求める際使われる数値。

乱数

seedから計算して得られる、実際の計算に使われる値。
例えばseedの上位16bit等。

乱数列

ゲーム中ではリアルタイムに計算されているとしても、疑似乱数は数列として扱う。

seedの位置

ある時点でメモリ内のseed格納用のアドレスに格納されている値のseed数列の位置 「seedの位置が[n]」であるときに生成される乱数は[n+1]の位置のseedが使われる。

乱数の消費

seedの位置を数列の次の項にし、更新後の値から乱数を得ること。

1.BWにおける乱数

BWでは、野生ポケモンと遭遇(エンカウント)、ボルトロス・トルネロスの徘徊開始イベント、タマゴの受け取り等の時、
そのポケモンの性格値・個体値が決められるのに乱数が使われる。
ただし性格値・性格と個体値の乱数は別の計算方法で数列化されており、前者を性格値乱数列、後者を個体値乱数列と呼ぶことにする。
性格値乱数列のseed1個は64bit、個体値乱数列は32bitで、性格値乱数列は項の上位32bitが乱数として使われる。
この実際使われる性格値乱数の数列を{r1[n]}、個体値乱数の数列を{r2[n]}、とする。
また、r1[n],r2[n]を作るseedをS1[n],S2[n]とする。

2.ゲーム起動時の共通初項(初期seed)の決定方法

性格値乱数列と個体値乱数列の初項は共通で、ゲームを起動した瞬間(=ソフトリセットした瞬間)に決定される。
これはある52byteのデータをSHA-1でハッシュ化した64bitの値である。
ハッシュ化する前の52byteの決定方法は以下のようになっている。
nazoAABBCCDD謎の値。バージョン毎に固有
ブラックだと0x2215f10、ホワイトだと0x2215f30
AA'BB'CC'DD'nazo+0xfc
AA''BB''CC''DD''nazo+0xfc+0x4c
VCountEEFFVertical Counter(現在描画中の走査線番号)。バージョン毎に固有
ブラックだと0x60、ホワイトだと0x5f
Timer0GGHHDSに内蔵する4つのタイマーのうちの1つ。バージョン毎に2通りからランダムで変動?
ブラックだと0x0c79または0xc7a、ホワイトだと0xc68または0xc69
GxStat^FrameIIJJKKLLGxStat:Geometry Engine Status Register。0x6000000
Frame:何らかのフレーム?本体の種類依存。初代DSだと8、DSLiteだと6
これら2つをXORしたもの。
MACアドレスM1-M2-M3-M4-M5-M6「Wi-Fi設定」→「オプション」→「本体情報」で見れる値
M1'M1^LL
M2'M2^KK
M3'M3^JJ
M4'M4^II
起動日時起動時の内部時計に関する情報。使われるのはDSLite以前のメニューでソフトを選択してから1秒後ぐらい。
全て12月→0x12等、10進表記をそのまま16進数にしたもの。
yy年の下2桁
mm
dd
NN曜日。日曜0〜土曜6
hh時。12時以降だと+0x40
mi
ss
キー入力OOPP起動時のキー入力の状態。
何も押されていないと0x2fff、Aボタンだけ押されていると0x2ffe
※「バージョン毎に固有」や具体的な値は現時点(2011/01/27)のものです。今後出荷されるROM等では違う可能性もあります。

これらの値を使い、
000102030405060708090A0B0C0D0E0F
00DDCCBBAADD'CC'BB'AA'DD'CC'BB'AA'DD''CC''BB''AA''
10DD''CC''BB''AA''HHGGFFEE0000M5M6M1'M2'M3'M4'
20yymmddNNhhmiss000000000000000000
30PPOO0000
をメッセージデータとしてSHA-1ハッシュ化が行われる。
ハッシュ化については→http://www14.ocn.ne.jp/~bkclass/doc_sha1.html

3.性格値乱数列の決定方法(線形合同法)

性格値seed列{S1[n]}は

S1[n+1] = S1[n] * 0x5D588B656C078965 + 0x269EC3

となる。ただしS1[0]=初期seedで、65bit以上は切り捨て。

乱数r1[n]はS1[n]の上位32bitとなるが、メモリの初期値はS1[0]であり、
上に書いたように最初に使われる乱数はS1[0]ではなくS1[1]の上位32bitなので、実際の乱数として使われるのはr1[1]から。

4.性格値乱数列の乱数消費契機

レポートを書く

レポートを書くと1消費。ポケモンを持っていないゲーム開始時でも有効。

ペラップ

「おしゃべり」を録音したペラップのステータス画面を開く毎に1消費

歩き回る

揺れる草むらの出現判定・タマゴの生成判定等に使われる。

トレーナーIDの決定

名前入力の時点での次に使われる乱数をr1[n]とすると、
r1[n]×0xFFFFFFFFの上位32bitがトレーナーIDとなる。
アララギ博士の確認に対し「いいえ」と答えると1個消費し別の値になる。

出現ポケモンの決定

歩いている時やあまいかおり・あまいミツを使った時など、野生ポケモンの出現時に出現ポケモンの種類が決定されるのに使われる。
データはポケモンの友のエンカウントテーブルを参照。
次に使われる乱数をr1[n]とすると、

・X = (r1[n]*1600)>>32、テーブルのデータを左から順に0,1,…として
X出現ポケモン
0〜3200
321〜6401
641〜8002
801〜9603
961〜11204
1121〜12805
1281〜13606
1361〜14407
1441〜15048
1505〜15689
1569〜158410
1585〜159911
で決定。

性格値・性格の決定(固定シンボル・野生)

御三家受け取りや固定シンボルエンカウント・野生ポケモンの出現時に、性格値と性格が決定されるのに使われる。
次に使われる乱数をr1[n]とすると、

・(r1[n]*2)>>32でシンクロ判定
・r1[n+1]^0x00010000が性格値(r1[n+1]^0x80010000の場合もある)
・シンクロ不発の場合、(r1[n+2]*25)>>32が性格

となる。3個消費。ただしシンクロの効かない御三家受け取り・化石復元の場合、シンクロ判定はスキップされる。

性格値・性格の決定(徘徊)

ボルトロス・トルネロスのイベント終了時に、性格値と性格が決定されるのに使われる。
次に使われる乱数をr1[n]とすると、

・r1[n]が性格値
・(r1[n+1]*25)>>32が性格

となる。2個消費。ただし雨の演出によりこの他に大量に消費されているので注意。

性格値・性格の決定(タマゴ)

タマゴが出来ている時、そだてやじいさんとの会話終了時に、性格値・性格・遺伝箇所等が決定されるのに使われる。
次に使われる乱数をr1[n]とすると、


・(r1[n]*25)>>32が性格
・どちらかの親がかわらずのいしを持っている場合(r1[n+1]*2)>>32で性格遺伝判定
※以下、かわらずのいしを持っている場合。(持っていない場合、全て1つ前の乱数が使われる)
・親が♂と♀で、♀が夢特性の場合(r1[n+2]*5)>>32が2以上なら夢特性遺伝
※夢特性でない場合でもr1[n+2]は消費される。
・親にメタモンが含まれる場合1個消費
※以下、メタモンが含まれる場合。(含まれない場合、全て1つ前の乱数が使われる。かわらずのいしと合わせて最大2つ前にずれる。)
・m=n+4とし、
☆:(r1[m]*6)>>32をステータス(HABCDS:012345)、r1[m+1]>>31を親(1:後)として遺伝箇所決定
片方の親がパワー系アイテムを持っている場合、予めその箇所は遺伝確定。
ステータスが重複した場合スキップで、遺伝箇所が3箇所決まるまでmを2増やして☆を再度実行。
・(r1[m+2]*0xffffffff)>>32が性格値
性格値を256で割った余りが性別、性格値>>16の下位1bitが特性。

NPC

主人公と同エリア上のNPCが移動したり方向転換したりするときに消費。
移動も方向転換もしないNPCは消費しない。

5.個体値乱数列の決定方法(メルセンヌ・ツイスタ)

624項の数列{t[n]}があり、t[0]から順に消費され、t[623]が消費されたとき{t[n]}が更新され、またt[0]に戻る。
t[n]の値を使う順に並べたものが、タマゴ乱数列{S2[n]}となる。
更新する処理がm回行われた後の{t[n]}を第mテーブルと呼ぶことにし、S2[(m-1)*624+n]は第mテーブルのt[n]と等しい。
最初に1回更新されるので、第0テーブルはSEEDとしては使われず第1テーブルの計算のみに使われる。

第0テーブルの決定
・t[0] = S1[1]の上位32bit
・t[n] = ((t[n-1]の上位2bit) xor t[n-1])*0x6c078965 +n

n:1〜623であり小数点以下は出る度に切り捨て。

テーブルの更新(第m+1テーブルの決定)

k[0],k[1]を32bitまで保持する変数として

・k[0] = (t[A] and 0x80000000) or (t[B] and 0x7fffffff)
・k[1] = (k[0]/2) xor t[C]
・k[0]が奇数のときt[A] = k[1]xor0x9908b0df、偶数のときt[A] = k[1]

この処理がA,B,Cが以下の順として行われる。

・A=n、B=n+1、C=n+397 (n:0〜226)
・A=n、B=n+1、C=n-227 (n:227〜622)
・A=623、B=0、C=396

6.Cギア起動時の個体値乱数列の再計算

Cギアを起動すると個体値乱数列のみが再計算される
この時初期SEEDとして使われるのは時刻依存の値(raw初期SEEDとする)にMACアドレス下位3byte(01-23-45-67-89-ABの場合0x6789AB)を加算したものとなる。
raw初期SEEDを0xABCDEFGHとすると

AB:(秒+分+月*日) and 0xff
CD:時
EFGH:年-2000+ゲーム起動時からの経過時間

となる。年月日時分秒はDS内部時計の値。
再計算後に個体値乱数を2個消費。

7.個体値乱数列の乱数消費契機

個体値決定

個体値乱数列のSEEDをEとすると、k[0~3]を32bitまで保持する変数として

・k[0] = (E/0x800) xor E
・k[1] = ((k[0]*0x80) and 0x9d2c5680) xor k[0]
・k[2] = ((k[1]*0x8000) and 0xefc60000) xor k[1]
・k[3] = (k[2]/0x40000) xor k[2]
・個体値 = k[3]/0x8000000

小数点以下は出る度に切り捨て。

野生ポケモン・固定シンボル・化石復元の場合

次に使われるSEEDをS2[n]とすると、S2[n]〜S2[n+5]から上記の方法で個体値を計算し、それをHABCDSの個体値とする。
戦闘によりさらに個体値乱数が大量に消費される。

タマゴの場合

次に使われるSEEDをS2[n]とすると、S2[n+7]〜S2[n+12]から同様に個体値を計算し、それをHABCDSの個体値とする。
その後個体値乱数とは無関係な乱数を用いて遺伝箇所が決定され両親の個体値で上書きされる。
13個消費

徘徊ポケモンの場合

小屋から出てボルトロス・トルネロスと初めて出会った瞬間に個体値が決定される。
また、一度撃破して殿堂入りすると再計算されるが詳細は不明。
次に使われるSEEDをS2[n]とすると、S2[n+1]〜S2[n+6]から上記の方法で個体値を計算し、それをHABDSCの個体値とする。

トップへ  次へ