アルパカログ

プログラミングとマネジメントがメインです。時々エモいのも書きます。

ポケモン剣盾のバトルシミュレーターを書いた

ポケットモンスターソード&シールドを発売以来ずっと遊んでいて、対人戦(シングルバトル)でいろいろ試したいなーと思ったので、2月3月の可処分時間のほとんどを開発に突っ込んで作った。権利まわりが怖いのでデータやソースコードは公開していない。

f:id:otoyo0122:20200328184024g:plain:w420
シミュレーターの画面

開発に使ったのはPython 3.7で標準ライブラリのみ。行数は全部で5,000いかない程度。

以下、苦労したところなど。

ポケモンバトルについて

ポケモンバトルには自分と相手が場に1匹ずつポケモンを出し合って戦うシングルバトルと、2匹ずつ出し合って戦うダブルバトルがあるが、今回は自分が普段遊んでいるシングルバトルだけを考えることにした。

ポケモンバトルはパラメータが多い。ポケモンのステータスに関するものだけでも種族値個体値努力値と呼ばれる3種類があり、そこに性格や特性や道具の効果が乗ってくる。

ステータス以外だと、皆さんご存知のタイプ。タイプはポケモンが持つタイプ(2個まで)と、技のタイプがある。タイプ相性によって「効果は抜群だ!」となったり「効果はいまひとつのようだ...」となったりする。タイプは18あるので、相性はその掛け算の数だけある。加えて、技のタイプがポケモン自身のタイプと一致していると技の威力が1.5倍になる。

技には物理、特殊、変化の3つの区分があり、例えばやけど状態だと物理攻撃のダメージが半分になるといった仕様がある。やけどを先に挙げたが、いわゆるステータス異常には2種類あって、ポケモンを交代しても継続する状態異常と、ポケモンを交代すると解除される状態変化がある。状態異常には、やけど、まひ、こおり、どく、もうどく、ねむりがあり、状態変化には、のろい、やどりぎのタネ、こんらんなどがある。

混乱してきただろうか?まだまだある。

ポケモンはそれぞれ「特性」を持っており、例えば特性「ふゆう」を持つポケモンにはじめんタイプの技が当たらない。一見するとひこうタイプと同じように思えるが、特性「かたやぶり」を持つポケモンのじめんタイプの技は当たる。「かたやぶり」は特性を無効化する特性なのだ。しかし、全ての特性を無効化するわけではない。

このようにポケモンバトルは例外が多い。例外に対応するのは面倒くさい。しかしもっと面倒なのが、データの整理だ。

データの整理と設計がしんどい

ポケモンの技には様々な追加効果がある。効果としては先に挙げた状態異常、状態変化があり(さらにステータスランク変化も)、それ加え発生確率、発生タイミングをデータで上手く表現しなければならない。

結局、追加効果ごとにデータを定義し、対応するクラスを定義する形をとった。今見たら対応したものだけでも100種類以上あった。そこからは、どの技がどの追加効果を持つか、ひたすら手入力していく泥臭い作業だ。何度も心が折れそうになったが、バトルで負けるたびに負けた悔しさを開発のモチベーションにした。

もう一つ、面倒だったのが、道具と特性の表現だ。道具も特性も同じ効果を持つものはまずない。

例えば道具の「こだわりスカーフ」は、こだわりスカーフを持つポケモンが最初に出した技しか出せなくする代わりに、素早さが1.5倍になる。そして、同じく道具である「オボンのみ」は、持ち主のポケモンのHPが半分になるとHPを1/3回復する。

このくらい、道具であれば「道具である」以外に共通点がないのだ。

道具も特性も、技の追加効果と同じように1データ1クラスという形で一つ一つ対応した。具象化されていると考えるとインスタンスでも良かったが、まあ実装においてはさしたる違いはない。

作った理由みたいなもの

ポケモンバトルのシミュレーターを作ったのには実はもう少しちゃんとした理由があった。コマンドラインで動けば、機械学習を使ってAIを作れると考えたからだ。言語にPythonを選んだのも、ライブラリが豊富で機械学習と親和性があると考えたからだ。

「あった」というのは、AlphaGoみたいに強化学習でひたすら対戦させて強いAIを作れればと思っていたが、さらにここからAIを作る気力はもう残っていないからだ。機械学習は計算リソースがかかるし、ポケモンバトルは修羅の道だし、また気が向いたら挑戦するかもしれない。