ishida

2014.12.25

ポケモンでOOPしていく(その3)(Advent Calendar 25日目)

挨拶

メリークリスマス! Adevent Calendarの最終日です。ポケモントレーナーの石田です。

僕はクリスチャンではありませんが、アドベントカレンダーのラストを飾ることになってしまいました。そんな僕ですが、クリスマス・イヴのイヴはeveningで、アダムとイヴのイヴとは関係ありませんので恋人の日的な扱いではなくて家族と静かに過ごすべきだし、25日はキリストが生まれた日ではないし、サンタクロースが赤い服を著ているのはコカ・コーラのせいではなくて赤い服を着ているサンタクロースはコカ・コーラ以前から記録にあるよねみたいなことは知っているので、ちゃんとクリスマスに歩みよって厳かに締め括りたいなと思います。ORASではメガタブンネのパーティをまだ作れていませんが、今日の夜はしっかりデリバードを厳選したいなと思います。ダブル想定で、|タスキ|おくびょう|CS中心の調整振り|ねこだま|ここかぜ|みちづれ|まもる、みたいな構成にして、ランダム対戦で、クリスマスの夜にデリバードから悪夢をお届け出来るところまでイケたら良いなと。

ロードマップ

前回はオブジェクト指向とクラス設計について説明しました。今回は実際に、それらを用いてS振りについて考えていきたいと思います。

実行環境について

ソースはGitHubにあります。リポジトリ内にVagrantで実行可能なように諸々入っています。./vm ディレクトリにVagrantFileと、./playbookにAnsibleのplaybookがあり、Vagrantで立ち上げてAnsibleを実行すれば環境が作れるようになっています。このplaybookはansible-galaxyのgeerlingguy.phpとgeerlingguy.php-xdebugに依存しています。適宜インストールして実行してください。Ansibleの実行時引数にはdevelop=trueが必要です。環境が整ったら、自身のhostsに 192.168.33.12 を pokemon.local を追加すれば実行出来ると思います。また、このプログラムはThe Pokémon RESTful APIを利用しています。

Macならば、必要そうなコマンドは以下です。内容を理解した上で自己責任でお試しください。

S振りって?

役割論理で考えればS振りはありえませんが、今回は一般的な育成論を題材としてオンバーンを例に上げてS振りについて説明します。さて、オンバーンの種族値を見てみましょう。

H 85
A 70
B 80
C 97
D 80
S 123

「ちょっと良い位の耐久を持った高速アタッカー」という印象を受けたんじゃないかと思います。さて、こいつをどう使ったら良いだろうか?ということで、誰もがイメージするであろうところの「このSとドラゴンであることを生かして、先発で出して最速でりゅうせいぐんを撃てるドラゴンキラーとして運用しよう」ということにします。先にも書きましたが、ここで「りゅうせいぐんwwww最速wwwww」と脊髄反射でCSぶっぱして許されるのは中学生までです。節度の有る紳士的なポケモントレーナーとしては「誰を抜いて、誰を落とし、何を耐えるか?」について無駄の無い振り方を考えるべきです。この「誰を抜いて?」を考えるのがS振りです。ここではSから調整を始めていますが「ドラゴン最速でりゅうせいぐんを撃ちたいオンバーンなので、Sから考え始める」のであって、常にSから考えれば良いというものではありません。「耐久を生かして耐えてから返り撃ちにしたい」のであれば「耐久と火力から調整を始めて、余りでSも調整する」という流れもあり得ます。

S振りについて考える

実際に、Sから考え始めるにあたって誰を抜くのか?ということになりますが種族値だけで言えばオンバーンは既にドラゴン最速です(メガ進化を除く)。しかし、それは種族値の話で、実数値には性格補正や努力値、アイテムが絡んできます。とりあえず、オンバーンの無振りの実数値を見てみましょう。http://pokemon.local/sample/Sample1を表示してみてください。これは以下のプログラムで表示してます。今回は簡略化のためにアイテムについては考慮外とします。アイテムを考慮する場合も、そんなに難しくはないはずなので、どうしたら良いのか考えてみてください。

actionの内容

コメント「おくびょう」と書いてある部分ですが、これは性格をセットしています。性格のクラスはどうなっているか?というとclasses/temperament/Temperament.php に有ります。これは、Enumという列挙型を模したクラスです。性格ごとの補正掛率が定義されています。中身について、くどくど説明しようかと思ったのですが、何も難しくないので実際に実装を見てもらった方が良いかなと思います。また、$this->repositoryについては、コメントで書いてある以上のことをしておらず、本題とはあまり関係ないので説明しません。各自で見ておいてください。

Viewの内容

HTML部分は省略してますが、こんな雰囲気です。

さて本題はviewに現れるgetHpValueとgetAttackValueの辺りです。これは実数値を取り出すメソッドになっており、Pokemonクラスに定義されています。以下がその内容です。

それぞれHPとその他のパラメータは、それぞれParameterとParameterを継承したHPクラスのオブジェクトです。calcParameterは、それぞれ以下のように定義されています。第一回で説明した式をそのままコードにしたものですね。実際の式と見比べてみると良いでしょう。

Parameter

HP

さて、実際にどのように計算しているのかが掴めたのではないかと思います。では、実際に無振りの実数値であるところの、157ってどれくらいなの?というのを見てみましょう。http://pokemon.local/sample/TargetListにアクセスしてみてください。この一覧はclasses/speed/TargetLoader.phpの中にあります。内容は高速アタッカーで有名どころの実数値をかき集めたマスタです。さて、オンバーンは性格補正有りの無振りで、S補正有り最速90族まで抜けることを確認出来たのではないかと思います。ターゲットはオンバーンを除けば最速であるところのラティオスの最速なので、最速110族抜きの調整をすれば目的は達成です。ORAS環境におけるメガラティオスになってもSは上がらないので考慮しなくても良いです。例外として、メガジュカインはオンバーンより速いのですが、こいつについてはメガ進化してくれなければ、りゅうせいぐんは刺さらないし、考慮すると複雑になり過ぎるため、ここでは見なかったことにしましょう。http://pokemon.local/CalcSpeedを見てください。「実数値178の最速110族を抜くには156振れば良い」という計算結果が出ています。では、どうしているのかを見ていいきましょう。

responses/templates/CalcSpeedView.phpを見てみると、以下のような記述があります。

では、呼び出しているcalcTargetSpeedはというと、Pokemonクラスの中の以下のメソッドですね。

では、そのcalcBasePointは、というと以下のようになっています。$targetを抜くために、どれだけの基礎ポイントが必要かを計算しています。メンバ変数を計算に利用しているため、$backUpとか現れて妙なコードになってしまっていますが、そこは御愛嬌ということで。データを保持するクラスと計算するクラスを分ければ問題は解決するのですが、それだと「データとロジックをセットにしてクラスにする」という基本から外れてしまうので、ここではこのままにしておきます。機会があれば「リファクタリングする」というネタも取り扱いたいですね。

さて、ここまででオンバーンのSに振るべき努力値の算出が出来ました。しかし、このままでは火力が足りません。相手より速く動けても相手を一撃で落とせなければ返り討ちにされてしまうかも知れません。次回は、どれだけCに振れば良いのか?を算出するためのプログラムを作っていきたいと思います。

まとめ

前回までのクラス構造の考え方に続いて、今回は実際にプログラムを起こしてみました。classesの中身をソリッドに保ったままViewをレンダリングさせるために即席で作った風のMVCな構造が出来ており若干戸惑ったかも知れません。しかし、中身を見てみればそんなに難しくはないと思います。CalcSpeedでは、おくびょうなオンバーン固定になっていますが、性格やIDをパラメータで受け取ってコントロールすれば他のポケモンで他の性格でも計算出来ることは想像に難くないと思います。またアイテムについては算出済みの実数値に掛率がかかるだけなのでマスタの定義さえしてしまえば、これの追加も難しくないでしょう。良かったら、forkして遊んで見てください。ただ、記事の内容と合わなくなるのでPull Requestは送られてもマージできませんので悪しからず。元のリポジトリへのマージは出来ないのは申し訳ないのですが、そのまま自身のリポジトリを進めて機能追加をしたり、デザインを当て込んだりは勿論、それを「一般公開したい」というのもOKです。このソースはMITライセンスです。さて、次回は耐久調整の予定ですが、その前に耐久調整に使える努力値の量を決めるためにCを先に振らないとダメですね。次で終われるのかな……

アライドアーキテクツではポケモントレーナーと連載記事をシレっと1年近く放置しておいて、いきなり再開してもへっちゃらな心の強さを持ったエンジニアを募集しております