暇つぶしがてらポ〇モン的対戦RPGゲームを開発したので、その中身の作り方の概要を記事にしたいと思います。Qiitaに投稿するの初めてで書くの慣れてないので読みにくかったらすいません。また、Unity触って1年の初心者が独学で作っただけなのであくまで方法の一つ程度として考えてください。
全部で何記事になるか分かりませんが、
1.ゲーム進行の管理
2.外部データのインポートとEditor拡張
3.簡単なAIの設計
くらいまで書けたらと思っています。
1.↓
2.↓
・評価値
敵AIが手を選ぶ際には基準となる評価値が必要です。今回はがりゅうさんの記事を参考にさせて頂きました。
私が作った評価値の計算式は、
評価値=
Σ(AIのポケモンのHP割合)×(有効ランク補正)×(状態異常補正)×(その他の補正)
÷
Σ(プレイヤーのポケモンのHP割合)×(有効ランク補正)×(状態異常補正)×(その他の補正)
としました。
ランク補正については、例えば物理アタッカーで攻撃ランクが下がってたら有効だし、鈍足アタッカーのSが下がってるのは有効じゃないなどを考慮して計算しました。
状態異常補正についても同様で耐久ポケモンが猛毒になっていたら評価を下げ、高速アタッカーがマヒになっていたら評価を下げるなどです。
その他の補正の部分に関しては、例えば変化技を拘りトリックやアンコールなどでロックされているポケモンは評価値を下げたり、身代わりを残せていれば評価値を上げたりなどです。
これを残ポケモン毎に和を取ったものを自分と相手で比を取った値を評価基準として、この値がなるべく高くなるような状況を目指させました。
・実装の方法とそれらの課題
最初の実装では、プレイヤー側は常に最高打点を出してくるものだと仮定して、それに対応してAIに4ターン後までの全手(4^4=256通り)を試させて、そのルートの中で目の前の相手に勝つ(またはHP割合が相手より多くなる)ようなルートを検索させてみました。
しかし、明らかにほぼ勝てない状況なのにAIがめちゃくちゃ強気に居座る選択をすることが多くありました。
どうやら、256回も試行している中で、例えばAI側の全部の技が急所に当たって楽に突破できたり、プレイヤー側が混乱でずっと動かなくて勝ったりと確率は低いが通れば強いといういわゆる「運ゲー」に勝利できたルートが見つかったらしく、AIはそのルートを辿ろうとしていたようです。(しかし勿論現実は1回きりの試行なのでそんなに上手くはいかない)
次の実装では勝てるルートを見つけた場合に、そのルートが本当に安全なルートなのか(1回きりの試行である現実でそのルートを取っても大丈夫なのか)を検証するため、シミュレーション上で1度勝てたルートを後でもう何回か追加検証としてシミュレーションすることにしました。
例えば発生確率が1%未満のような低確率で勝てる場合は、追加検証を50回した時にせいぜい1,2回くらいしか勝てないと予想されます。そのような低い確率でしか勝てないルートを間引こうという考えです。
この追加検証で一定以上の確率で勝てるという結果が得られた場合、それらのルートの中で最も評価値の高い(最も良さそうな)選択肢を選ばせるようにしました。
しかし、今度は1回目のルート探索で勝てるルートが多く見つかった際に追加検証の計算回数が多すぎてAIの思考時間がとても長くなってしまい、画面がフリーズという問題が発生しました。
そこで、重い計算処理を非同期にして画面をフリーズさせない方法を調べていて、カヤックさんの記事を参考にしました。
これによって何度も処理される計算を一定時間ごとに割り振ることで画面のフリーズの確率は下がりました。しかし、計算の回数自体が減っている訳ではなく相変わらず特定の状況では(特に耐久型モンスターで頻発)AIの思考時間が非常に長くなってしまいました。
そこで計算量を減らすために、ルート探索を全手256パターン探させるのではなく、ある程度の所で打ち切らせることを考えました。
ルート探索途中で、ある技を使って負けた場合、それ以降の探索ではその技を使うのは無駄と判断してその技を使うルートは探索しない事にしました。これによって無駄な計算(地面タイプに電気技を使うルートなど)を省いてより計算時間を短縮することに成功しました。
これによってある程度の精度でそこそこ短い計算時間のAIが出来ました。
しかし、何度か対戦してみると明らかにAI側が勝つ確率の方が高そうな状況なのに勝負を仕掛けてこない場合がありました。例えば、AI側が先制で眠り粉(命中75%)→蝶の舞を積めばSを逆転して全抜きが狙えそうなのに眠り粉を選択してこないなどです。
どうやら、最初のルート探索中に眠り粉を何度も使う内に外してしまう場合が1回はあったようで、その外しによって結果的に打ち負けてしまったのでそれ以降は眠り粉を使うルートを探索することを諦めてしまったようでした。
計算量を減らすために探索するルートを削った結果として勝てるはずだったルートを見つけられなかったようです。
そのため、初回の256パターンのルート探索ではAI側の技の命中率を100%である、と上振れを仮定して考えさせて、最検証の際に命中を考慮して計算させることで本当に安定して勝てるのかを検証させることにしました。
これによって連続混乱や急所といったような確率のかなり低いルートを省きつつ、命中率がある程度ある場合は強気に勝負を挑んでくるというAIが出来ました。
しかし、これはあくまで相手が常に攻撃技を選び続けるという仮定の下であり、AI側が相手の手を読んで手を変えるという事は実現できていないため、これからの課題点であるといえます。
以上がAI設計初めての人間の試行錯誤の結果でした。何かの参考にしてもらえれば。