rusted-coil old blog

はてなダイアリー上で書かれていた旧東方錆恋録 ~Slipping Rusted Magnemite~のデータをそのままインポートしたブログです。リダイレクト先を変える前に気づいたらダイアリーがサービス終了していたので、とりあえずリンク切れを防ぐため公開しています。

プラチナループタマゴ版 platroop 解説前編 乱数の仕組み

思いつきで真面目に乱数の話でもしてみる。暇だったら後編 実用的方法について書くかも
性格値、個体値、裏ID、16進数、疑似乱数ぐらいは知ってること前提で。
適当に思いついた用語連発なので使い方間違ってたら言って

0.用語の確認

とりあえずここでは、疑似乱数は(ゲーム中ではリアルタイムに次の項が計算されているとしても)初項が決まれば得られる無限に続く数列とする。(乱数列)
乱数列の決定に使われる値をseedと呼ぶ。(seedは大抵既に決定された乱数列の値である)
ゲームのメモリには「次に使われる乱数の値」が記録されているアドレスがあり、この「乱数の値が乱数列でのn項分先の値になること」を「乱数がn個消費される」と呼ぶ。

1.DPtにおける乱数

DPtでは、野生ポケモンと遭遇(エンカウント)したときにその野生ポケモンの性格値・個体値が決められるのに乱数が使われる。
また、タマゴの性格値が決定される瞬間(爺さんが横を向く瞬間)にも、その性格値が決められるため乱数が使われる。
ただしこの2つの乱数は別の計算方法で数列化されており、前者を遭遇乱数列({r[n]})、後者をタマゴ乱数列({e[n]})と呼ぶことにする。
どちらも乱数1個は32bit。

2.乱数の消費契機

それぞれの乱数列について、現在判明している乱数消費契機は以下の通り。

遭遇乱数列
  • 128歩毎

(手持ちポケモン数)個消費

  • 「ぼうけんノート」で「○○を倒した」「○○を捕まえた」と書かれているページを開く

2個消費

戦闘中に消費した乱数は戦闘終了後、相手ポケモンの性格値・個体値が決定された後の状態まで戻ると思われる。
その時点での乱数を乱数列での第n項とすると出現するポケモンの性格・性格値・個体値
r[n]の上位2バイト/0xa3eで性格を決定
m=n+1
※r[m]の上位16bitが性格値の下位16bit、r[m+1]の上位16bitで仮性格値計算
このとき最初に決めた性格と一致しなかったらmを+2して※を繰り返し
r[n+2]の上位16bitが下位から5bitずつHAB、r[n+3]の上位16bitが下位から5bitずつSCDとなる。

  • ポケモンが出現しうるマスであまいかおり・あまいミツ

草むらで使った場合1個、洞窟・水上で使った場合2個消費

  • ポケモンが出現しうるマスで移動・方向転換

その時点での乱数を乱数列での第n項とすると


r[n]の上位16bit/0x290が謎の値より小さければ次へ。そうでないなら終了。1個消費
r[n+1]の上位16bit/0x290がエンカウント率より小さければポケモン出現。ここまでで2個消費


これが移動で1回、方向転換したらさらに1回行われる。

  • NPCの方向転換・移動

詳細不明。方向転換・移動可能性無しのNPCは消費しない。


今のところ信頼性が高いのは128歩毎とぼうけんノートによる消費

タマゴ乱数列
  • タマゴの性格値決定

1個消費。その時点での乱数を乱数項での第n項とするとe[n]を元にある計算をされた32bitの値が性格値となる。
かわらずのいしが働いていた場合は不明。国際結婚の場合は性格値の計算自体は繰り返される場合があるが、乱数消費数は変わらない。

  • ポケッチアプリ「なつきチェッカー」

このアプリを開くor画面を素早く2回タッチしたとき(ポケモンがジャンプする)、(手持ちポケモン数)*2個消費

コイントスを1回する毎に1個消費

3.乱数決定方法

どちらの乱数列も、初項が決まればその後の項は無限に決まる。ただしこの2数列には決定方法に違いがある。
初項r[0],e[0]は同じ値だが、r[n+1]は常に前の項r[n]のみがseedとなるのに対し、e[n]は624項単位で、624項の値がseedとなり次の624項が決まる。

初項r[0]、e[0](両乱数列共通)

セーブデータの画面で「つづきからはじめる」を押した瞬間に決定される。値を0xABCDEFとすると

  • AB:(秒+分+月*日)&0xff
  • CD:時間(0x00~0x18)
  • EFGH:年-2000

がまず代入され、最後にゲーム起動からの経過時間による値を足す。Aボタン連打でつづきからはじめるを押した場合、0x256程度。
ここで使われる年月日時分秒は決定される瞬間のDS内部時計から取得されるもの。

遭遇乱数列

r[n+1] = r[n] * 0x41c64e6d + 6073
(但し33bit以上は保持されない)

タマゴ乱数列

624項の数列{t[n]}があり、t[0]から順に消費され、t[623]が消費されたときt[0]〜t[623]を使いt[0]〜t[623]を更新する。
次の乱数はt[0]に戻り、これを使う順に並べたものがタマゴ乱数列である。
更新する処理がm回行われたときの{t[n]}を第mテーブルと呼び、第mテーブルのt[n]=e[(m-1)*624+n]である。

  • 第0テーブルの決定(第1テーブルの決定にのみ使われる)

t[0] = e[0](共通初項)
t[n] = ((t[n-1]>>30)^t[n-1])*0x6c078965+n
(n:1〜623)

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

A,B,Cをt[n]のある項とする。
k[0]・k[1]を32bitまで保持する変数として
  k[0] = (A&0x80000000)|(B&0x7fffffff)
  k[1] = (k[0]>>1)^C
  k[0]の下位1bitが1(k[0]が奇数)のときA = k[1]^0x9908b0df
              奇数ではないときA=k[1]


この処理はABCを以下として順に行われる
・n=0〜226としてA=t[n]、B=t[n+1]、C=t[n+397]
・n=227〜622としてA=t[n]、B=t[n+1]、C=t[n-227]
・A=t[623]、B=t[0]、C=t[396]

タマゴ乱数列からの性格値生成

使う乱数をe[n]としたとき
k[0][1][2]を32bitまで保持する変数として
  k[0] = (e[n]>>11)^e[n]
  k[1] = ((k[0]<<7)&0x9d2c5680)^k[0]
  k[2] = ((k[1]<<15)&0xefc60000)^k[1]
  性格値 = (k[2]>>18)^k[2]

国際結婚時の処理

両親の国籍が違った場合、通常の性格値生成による性格値をPとして
  P = P*0x6c078965+1
  Pの性格値で色違いになるかチェック
  色違いだったら処理を終了
の3つが最大4回実行される。(最初の性格値は必ず変更される)