数値計算でポケモンのパーティを作る
※2021/07/07 追記 ブログの移行にミスって画像が消えてます。リクエストあれば書き直します。
ポケモン(シングルバトルを想定)のパーティを数値計算で自動生成してしまおうというお話
PTの強さを数値化できるモデルを用意し、その値が最大になるようなポケモンの組み合わせを探す。
計算は単純なダメージレースだけで、特性や補助技は一切考慮していないので実用性はないが、これから発展させていくとしてまずは現段階での結果報告。
Pokemonクラス
最終的に「全てのポケモンの組み合わせについてPTの強さを計算」という形になるので、ポケモン1匹を表すオブジェクトを用意する。
つまりこのようなクラスを作成して、そのインスタンスで特定のステータスを持つポケモン一匹を表す。
さて、問題になるのがこの中身。700匹以上いるポケモンのタイプ・種族値などの情報をどこから取得するかということ。さすがに手動はアレなのだが
いいものがあった。一応説明すると画像はPokemon Showdown (http://pokemonshowdown.com/)というポケモンバトルシミュレーターのソースコード(GitHubで公開されている)。
Pokemon Showdownは非公式とは思えないほどゲームシステムの再現性が極めて高く、本家の新バージョンが出たときなどの更新も速い。ということでこれのポケモンデータベースを拝借すれば信頼できるポケモン情報が手に入る。
pokedex.jsをダウンロードすれば後はテキストファイルとして煮るなり焼くなり好きに処理できるはず。個人的な趣味だが今回は内容を自前のデータベースに保存し直した。
このデータベースから情報を取得し、前述のポケモンオブジェクトを作成していく。
性格・努力値振り推定
ポケモンクラスの各メンバーは基本的にデータベースから取得すればいいのだが、性格・努力値はいわゆる"育て方"によって異なるパラメータであり、データベースに載っているようなあらかじめ決まりきった設定値ではない。そのため、自分で設定してやる必要がある。
今回は以下のような基準で決定した。
性格
上昇箇所:種族値の最大箇所
下降箇所:種族値のA・Cを比べてどちらか低い方
ただし、
・S100以上の場合無条件でS特化(性格もS上昇のものにする)
・B、DよりはHPを優先させる(例えばABはHAに、CDはHCに変更する)
標準ダメージ比
ポケモン同士の1:1の相性(どちらがどれくらい有利か)を定量的に評価する方法。これを発展させてPTの強さ計算へと結びつける。今回は標準ダメージ比という指標を設定した。
まず標準ダメージの説明
標準ダメージの定義:自分の攻撃タイプのうち相手に対してより有効な方を用いて、威力90の技で攻撃したときのダメージ割合
例えばドリュウズ対ファイヤーだとすると、
ドリュウズのファイヤーに対する標準ダメージD1は、ドリュウズが威力90の鋼タイプの技でファイヤーを攻撃したときのダメージ割合
ファイヤーのドリュウズに対する標準ダメージD2は、ファイヤーが威力90の炎タイプの技でドリュウズを攻撃したときのダメージ割合
これの比をとったものを相性値とする。つまり
ドリュウズのファイヤーに対する標準ダメージ比:D1/D2
ファイヤーのドリュウズに対する標準ダメージ比:D2/D1
であり、おそらく後者の方が大きな値となる。
定義から分かるように、標準ダメージ比は正の値をとり、1より大きければそのポケモンに対して有利で、1より小さければそのポケモンに対して不利である。
素早さの考慮
上の定義だけだと6つの能力値のうち素早さだけが全く考慮されない計算となってしまうので、補正をかけ、先手をとって攻撃することの優位性を組み込む。
A,BのうちAの素早さの方が高かったとする。A、Bがそれぞれ相手の攻撃によってNa, Nb回で倒れるとして、
Na >= NbならばAの標準ダメージ比にNb / (Nb - 1) を、Bの標準ダメージ比にその逆数をかける。
どういうことかというと、先攻で(そのターンの相手の返しの攻撃を食らわずに)相手を倒したときには攻撃回数が実質的に1回増えているという考え。
ちなみに、一発で倒した場合にはこの補正項は無限大になってしまうので、最終的な標準ダメージ比の値の方で適当に上限を設けている。
相性ベクトルの生成
PTの強さ計算の下準備。高度な線形代数を使うわけではないが、情報を二次元的に格納するためにベクトルを使う。
1つのポケモンについて以下のような相性ベクトルを用意する。これはあらゆるポケモンに対する標準ダメージ比の値を各成分にもつベクトルである。
(例)ハッサムの相性ベクトル
実際には、このベクトルの次元は考慮するポケモンの総数になるので、数百を超えるのが普通である。
PTの強さ
一番重要な部分なのでどう計算するか試行錯誤を繰り返したが、計算時間の制約もあり今のところは以下のような単純な方法に落ち着いている。おそらく最適ではない。
ある組み合わせのPTについて、各ポケモンの相性ベクトルを用意する。
各成分の最大値を集めたベクトルを作る。
ノルムを求めてPTの強さとする。
というわけで、PT(ポケモン1~ポケモン6)の組み合わせを総当りして、最大値ベクトルのノルムが一番大きい組み合わせを一番強いPTとして出力すれば目的が達成される。
感覚的には、どのポケモンにも対抗できる手段をもつPTの探索。ただし、ポケモン一種類についての対策度合いを最大値でのみ判断するため、対策の"厚み"とでもいう部分の評価に欠けており、実戦に応用しようとするとPTの一匹が過労死するようなことがあるかもしれない。
計算結果
何はともあれ結果です。
まず、考慮したポケモン集団はデジポケ(http://degipoke.pro.tok2.com/)の「XY環境KP集計」から取得した上位100匹(からミュウツーを除いたもの)
ガルーラ |
ポリゴン2 |
||||||||
サンダー |
|||||||||
エーフィ |
|||||||||
エルレイド |
|||||||||
ラッキー |
サンダース |
||||||||
ヌオー |
|||||||||
組み合わせるポケモンは全てこの中から選び出し、PTの強さはこの集団に対して計算するということ。
結果(生成されたPT)の評価方法について
1つの指標として、ポケモン徹底攻略(http://yakkun.com/)のタイプバランスチェッカーでの評価結果を載せる。
もちろんタイプ相性だけでPTの強さを計算しているわけではないのだが、それでも相性計算に支配的な要素ではあるため。あとポケモンのアイコンをちょうどいい感じに並べてくれる。
さて、組み合わせを総当りして~と書いたが、計算時間の都合上6匹の組み合わせ全て(= 100C6 = 1,192,052,400通り)は厳しかったので、最初にPTの一部のポケモンを指定し、残りのポケモン枠に対して組み合わせ計算を行った。
前3匹を固定(その選び方自体はランダム)して、最適な後ろ3匹の組み合わせを探索した結果を羅列。
ポケモン力が低くて気の利いたコメントが書けないのでただ羅列するだけ。
というわけで、どの場合でも結局のところ似たようなポケモンが出現していることがわかる。
強いポケモンを3匹組み合わせればそれだけで見た目上のバランスはとれるということか。
最後に、前2匹を固定して後ろの4匹を出力した結果。
タイトルを「タイプバランスチェッカーで高得点をとれるPTの自動生成手法の開発」に変えた方がいいかもしれない