なるほどえたきちのブログじゃねーの

チラ裏雑記帳

ポケモン過去作の解析とか乱数調整とかそこら辺。不定期更新。

【ポケモンXY】ID調整

事の発端はこちら。
 ↓
sina-poke.hatenablog.com


XYのID調整に成功したので適当に調整手順等を纏めます。
(元々纏める気なかったけど)




疑似乱数周りの仕組み



IDの決定自体はORASと同様にTinyMTが用いられており、初期seedも同様に起動時刻によって決まっている。
但し、OP内でキャラクターオブジェクトのまばたきによる不定消費が発生している為、ORASと同様の手順ではseedの特定が難しい。
ここで使用されているまばたき処理は以下の通り。
(滅茶苦茶単純である)

u32 _counter;

void init()
{
	_counter= 0x021E - ((rand() * 0xB4) >> 0x20) << 0x01);
}

void next()
{
	_counter--;
	if (_counter == 0)
	{
		init();
	}
}

また、名前入力画面に遷移した際の1消費以外にその他消費は行われていない模様。
OP内ではキャラクターの数が変動する箇所があり、これによって時間あたりのおおよその消費速度が変化する。
キャラクター数の変動の仕方は以下の通り。


1人 (博士)
 ↓
2人 (博士,メェークル?)
 ↓
1人 (博士)
 ↓
3人 (博士,男主人公,女主人公)
 ↓
文字入力画面 (まばたき判定停止)
 ↓
3人 (博士,男主人公,女主人公)
 ↓
4人 (博士,男主人公,女主人公,選んだ方の主人公)


また、OPの最後に現れる主人公は名前確定時にまばたきカウンタのリセットを行っているよう。
名前確定→まばたきカウンタリセットまでの空白時間は主人公の性別によって異なっている。


ID調整方法の考察



TinyMTの初期seedはORASと同様に決定されている為、TinyMTを元に生成された値を観測することができれば32bitの総当たりによって初期seedの特定が可能となる。
但し、ID決定までの消費数が不定である都合上ORASと同じ手法は使えない。(使えたとしてもミリ秒ゲー以上の難易度になるが)
ID決定以外の乱数消費には「キャラクターのまばたき処理」があり、これは「まばたきのインターバル」という形で乱数値を使用する。
その為、今回はキャラクターのまばたきの長さを利用して32bitの総当たりを行い、現在seedを求める。
キャラクターが1人である状態なら、「現在seed」と「1人のキャラクターが持つまばたきカウンタの値」の2つを得ることで乱数値の制御が可能となる。
シーンの切り替わりによって新たに登場するキャラクターのまばたき処理についても、前述した2つの値が分かっていれば「シーン切り替わりの契機となる操作タイミング」を管理するだけで制御可能。
その為、今回の乱数調整では「キャラクターが1人である状態からまばたきのインターバルを複数記録して現在seedを特定した後、3DSの操作タイミングを管理することによって後に現れるキャラクターのまばたき処理を全て制御する」といった形でOP中の乱数消費を再現する。

キャラクターのまばたきのインターバルは最長542F(約9秒)、最短でも184F(約3秒)である為、時間あたりの消費速度はかなり遅めである。
また、まばたき以外の不定消費が存在していない為、消費速度を踏まえると操作精度が余程低くない限りは消費数がズレる可能性は低い。

調整にあたっての理論的な説明っぽいのは以上の通り。
これらの作業を簡潔に行う為のツールを作成したので使い方を適当に紹介する。
DL:https://bzl.hatenablog.com/entry/2090/11/11/000000#6genTidSearch


基準seedの特定



o3DSではラグの影響で消費の進む速度に若干の遅れが生じるようです。
このツールはラグの考慮を一切行っていない為、極力n3DSを使用して乱数調整を行うことを推奨します。

OP開始後、この画面まで進めておく。

6genTidSearchを起動し、[XY]→[基準seed検索]タブを開く。
初回は『全範囲探索』を選択し、その後OP内のプラターヌのまばたきに合わせて『瞬き』ボタンを押してまばたきの空白時間を記録する。
(数分間見つめ合ってるとちょっとロマンチックな雰囲気になってくる)
まばたきの空白時間を10個程記録したら検索を開始する。
2回目以降の検索を行う際は『基準seedから探索』を選択し、前回特定した初期seedを入力する。

seedが見つかった後、セルをダブルクリック又は『seedを選択』を押しておく。


目的のIDの検索



ID検索タブを開き、許容する消費数と目標IDを入力して検索を開始する。
ここで目標のIDが見つからなかった場合はリセットし、再度seedを特定する。
(複数候補の検索したかったら3DSRNGTool使ってね)


まばたきズレの補正



目標IDが出現するseedであった場合は消費数管理タブを開く。
『瞬き調整』内の開始ボタンを押すとプラターヌの瞬きに合わせて音が鳴るようになる。
但し、目視でまばたきを観測している都合上、実際のまばたきタイミングとはズレが生じている。
ここではその誤差の補正を行っていく。
基本的にはプラターヌのまばたきより遅く音が鳴っている為、『早める』を押してズレを縮めていく形となる。
プラターヌのまばたきと鳴る音のタイミングが一致したらこの手順は終了。


まばたき消費制御



ツール内で主人公の性別を選択する。
その後、以下のシーンでAボタンを押すのと同時に『ステップ(F9)』を押して消費の制御を行っていく。
また、名前確定時を待機フレームの始点としている為、CCTimerを使用している場合はF9キーを使用することを推奨する。


>> 主人公の性別選択

>> 名前入力画面

>> 名前決定

>> 名前確定



操作終了後はこの画面で待機を行う。

消費範囲を指定後、『計算』を押してリスト出力を行う。
ハイライト部分は「現段階でAボタンを押すと引くことのできるID」となっている。

出力されたフレーム数に合わせて待機を行い、出現したIDを確認する。
目標のIDが無事に引けていれば成功。


あとがき



XYの方は特に纏める予定はなかったのですが、任せられてしまったのでこちらも書くことにしました。
以前纏めたORASと比較すると手順は若干ややこしいものの、狙ったIDを引きやすいのでNN目的でID調整を行う方はこちらの方が都合良いかもしれませんね。
これを応用するとフィールド上でTinyMTのseedが特定できるようですが使い道がよく分からない...