バトルファクトリー 必勝(?)乱数調整
ポケモンHGSSにおけるバトルファクトリーの必勝(?)乱数調整の動画を撮影しました。
作った(or 使った)ツールは以下
- http://oupo.github.io/factory-npc/
- https://github.com/oupo/factory-search (UIなし)
- オーキドはかせのポケモンこうざで乱数消費補助ツール
必勝seedを探すのとNPCのシミュレータを作るのどっちが手間かかっただろう…
オープンレベル5周目、ボーナスポケモンなし、seedは0x2263499bです。
この乱数調整はさきさんによるバトルステージ乱数調整とバトルトレイン乱数調整に影響を受けてやってみました。
必勝seedの探索
必勝seedは2^32通りしらみつぶしです。
まず次の2匹が最初の6匹に出るseedだけに絞ります。
- ムクホーク 技: ブレイブバード, ギガインパクト, インファイト, とんぼがえり アイテム:こだわりハチマキ
- ムウマージ 技: シャドーボール, サイコキネシス, 10まんボルト, みちづれ アイテム: きあいのタスキ
大変な火力を持つ鉢巻ムクホークとタスキ道連れムウマージ。この2匹の力でなんとか必勝できるものを探そうということですね。ちなみに鉢巻ムクホークはさきさんのバトルトレイン乱数でも活躍しています。
この2匹を選び、あとの1匹を4匹の中からどれを取るか、全て試します。
必勝判定関数を用意しておき、7回の戦闘に全て勝てるか判定します。なお、二つの戦闘の間の交換は一切しないものとします。
この必勝判定関数は必勝かどうかを完全に判定するものではありません。すなわち判定関数が必勝でないといっても本当は必勝な可能性はあります。ですが、必勝判定関数が必勝だといえばそれは本当に必勝です。そういうふうに作ってあります。
ただし、みちづれのPP切れと相手がポケモンを交換する可能性を無視しているので厳密にそうとは言い切れません…そのためタイトルの必勝のあとに(?)をつけています
必勝判定関数は再帰によって実装されています。
- 手持ちのHPがすべて0なら「負け」と判定
- 相手のHPがすべて0なら「勝ち」と判定
- 場に出てる自分のポケモンのHPが0→交換。控えが2匹いる場合は両方試してどちらかで少なくとも一方で「勝ち」なら「勝ち」と判定
- 場に出てる相手のポケモンのHPが0→相手が次に出すポケモン最大2通りを両方試してどちらでも「勝ち」なら「勝ち」と判定
- 技を選択するか、交換をするか、両方試してどちらか少なくとも一方が「勝ち」なら勝ちと判定し、どちらもダメなら「負け」と判定
- 技を選択する場合
- 素早さが負けていたなら自分のHPを0にしたのち必勝判定
- 「みちづれ」を持っていて、相手が「どくどく」などの技を持っていない場合、自分と相手のHPを0にして必勝判定。「勝ち」になれば「勝ち」を返す。「負け」なら続けて他の選択肢を試す
- 一番相手にダメージを与えられる技を選ぶ。ただしダメージは最小乱数が出るものとして計算する。相手が「ゆうばく」などを持っていたら「負け」とする。
- 相手のHPが残っていて積み技などを持っていた場合「負け」とする。
- 攻撃した結果、相手のHPが残っている場合、自分のHPを0にする。その後必勝するか判定
- 交換する場合
- 相手が積み技などを持っている場合「負け」とする
- 交換先はすべて試す。すなわちどれか一つ「勝ち」が出れば「勝ち」。
- 「きあいのタスキ」を持っている場合を除いて、交換先は即倒れるものとする。
(こうして書いてみると何か穴があるような気がしてきたぞ…)
くわしくは次のcomplete_winnnable関数を見てください
2^32通りしらみつぶしをJavaScriptで書いて、しかもそれでうまくいったのだから、すごいですよね。
NPC消費によるズレを防ぐ
さきさんによるバトルステージ乱数調整ではポケモン選択画面でペラップを鳴かせることでNPC消費によるズレが起こらないようにされていました。しかしバトルファクトリーではそんなことできません。
そこでNPCのシミュレータを作ってNPCの消費が入らないような一定の長さ以上を持つ区間を探してそこを狙いました。
NPCのシミュレータを作るためにNPCの動きをわざわざエミュレータを使って解析しました。
またバトルファクトリーの外にもNPCがいるので、建物に入った瞬間に消費がいくつであったかをNPCの動きから特定します。
図で示したのがNPC消費の隙間です。婦人が上を向いた直後に隙間ができるのでそれを目印にします。