パワポケシリーズ乱数とそのPythonでの実装による観測

パワポケシリーズは起動時間をもとにした初期乱数から線形合同法で次の乱数を生成するため、起動時間と乱数消費回数が同じならば常に、その乱数を消費して起こるランダム要素を伴うイベントの内容を同一にすることが可能なため、調査によって「乱数調整」「状況再現」をすることが可能となる。 

 

筆者はパワポケシリーズの乱数調整に最近Pythonを使うようになって、Python上でパワポケ乱数を実装することで簡単に11裏ハタ人間編、12裏秘密結社編の合成で、短時間で簡単にMP装備を作ったり、10裏で高性能の主砲を粘ったりすることが可能になったので進捗を書いておく。誰か時間に余裕がある人これで最強装備つくってください()

 

とりあえず、下が実装例。これ、別記事でも使うのでPokeRNGと呼ぶことにする。

 

f:id:iid01:20190219211945p:plain

パワポケ乱数観測機実装

 

 

※追記 if文のところ、X/Mではなくて正確には2 ** -32 * math.floor(2 ** -32 * X)

なんだそうです・・・(要するに下位32ビットを捨てて、上位32ビット部分をとって2^-32してる、詳しくは参考動画のおまけ参照。結果上の写真だと詳しい説明は省くが小数第10位あたりで誤差が出る、つまり実用上は「ほとんど」問題はなく、99.99999999%くらいは信用していい)

直すには最初にimport mathってやってX/Mのところを書き換え。

 

解説としては、最初のところでは出力結果が分かりやすいように色を定義しておいてる感じ。

 

その次の #DS Liteでの起動時間 ってところが、DS初代またはDS Liteで、ゲームメニューのところでパワポケに合わせてAを押す時間。起動した時間に応じて、書き換えてください。h:m:s=時間:分:秒。ただしs=59にするときは注意。(後述)

m=9のときとかは、09って書かずに9って書いてね。前者は8進法扱いになって正確な値が出ないから・・・

 

#乱数生成回数 ってところが、何個の乱数の出力結果が見たいか、っていうこと。あんまり多くすると出力に時間がかかるうえに、乱数調整するのにも時間がかかる。

 

Y,X,A,C,Mってところは、Yはオート命名のスキップ判定(後述)

Xは実際のパワポケ起動時間(DS初代かLiteだとゲームメニューでAを押した時から約1秒後にパワポケが「起動」するので+1って書いてある。よって、s=59のときをやりたい人はmに+1してsには-1って書いたりして、うまくコードを書き換えてね。)とその時の初期乱数の値(=h*2^16+s*2^8+s)。パワポケでは乱数は64ビットのやつと32ビットのやつ、2種類ある。今回扱っているのは前者で、これは人力調整が十分可能。後者は正確な消費が難しいっぽいのでまだ。この辺については、σ軸さんの動画が素晴らしく分かりやすい:sm27061077

A,Cは、古典的な線形合同法に使う定数で、この値はパワポケ9~12までで共通であることが分かっている。σ軸さんによる解析で判明。いじっちゃダメ。別のゲームになっちゃう。ちなみに先頭に0xとつけてあるので16進法での表記。

Mは、線形合同法のmodで使う値。後ろの長々と書いてあるif文にX/Mとか出てるけど、0~2^64-1の値のXをM=2^64で割ることで0~1の一様乱数を「疑似的に」発生させて、この値が0.02以下であれば確率2%の事象を起こす処理をする、そうでなければ起こさない、みたいなことをゲーム内で行っているっていうこと。

 

ちょっとここで00:03:34のときの出力を見てみる。

あ、ちなみにこれ、Jupyter Notebookっていうやつで、上にあるRunっていうボタンを押すと動きます。コンパイルいらないです。

 

f:id:iid01:20190219215320p:plain

00:03:34のときの出力結果

 

 

0番目はぴったり0。0番目が使われることはパワポケ10のPカードとかを除いてあんまりない。

 

1番目以降は、0~0.2のとき赤、0.2~0.4のとき黄色、0.4~0.6のとき色なし(黒)、

0.6~0.8のときシアン(薄い水色っぽい)、0.8~1.0のとき青(濃い水色)で色付け。

11裏とか12裏で虹色作ったり、10裏で主砲粘ったり、単に乱数観測をするときに分かりやすくするため。

 

1番目は0.79、2番目は0.57、3番目は0.57。(小数点第3位以下切り捨て。)次にスキップってあるのは、パワポケではオート命名をしたときに乱数を1個消費するが、直前と同じ名前になってしまった場合、再度乱数を発生させて違うのが選ばれたらそれを採用っていう仕様になっているため。

 

この例では、0.79は高田、0.57は中野、0.41は後藤に割り当てられているので、パワポケ10,11で上の時間に起動して表サクセスでオート命名すると、高田→中野→後藤 になる。3番目に当たる乱数(2番目の中野→3番目の中野)は、オート命名をするときは仕様により「スキップ」される、つまり乱数がこの時だけ2個消費。

 

乱数のどの値がどの名前にあたるかはいずれ書く。

追記:書きました↓

iid01.hatenablog.com

 

14番目の下の「MPだああああああああああああああ」ってなっているのは、もともとこのプログラム、12裏か11裏でMP装備を出すために書いたので・・・

この例だと、13番目まで乱数を消費して12裏で装備を作ると必ずMP作品ができます。

※追記。ただし、11裏と12裏では裏サクセス起動時に乱数を消費してしまうのでぴったり乱数を合わせるのは単純な話ではないです。いずれ書きます。

 

12裏の合成と乱数消費および調整方法についてはどっかで書く予定。

11裏、12裏でMPを出す以外の用途でこのプログラムを使う場合は、

 

print("MPだああああああああああああああああああ")

 

って部分は先頭に#をつけてコメントアウト するか、単に消しておくといいです。

 

それではまた。

 

 

参考動画:【パワポケ9 TAS】乱数解析を駆使してブギウギ商店街で暴れまわる #1

https://www.nicovideo.jp/watch/sm27061077