Dreamdancer

モバマスイベント走行記、攻略情報(?)、あるいはモバマスについて思うことなど

モバマス最適フロント計算機を作りたいという話 Episode.2

前回の続きです。今回は、実際どういうふうに最適フロント計算機をプログラムとして書いていくか、について考えたいと思います。

計算機の条件(補足)

前回の記事から時間が経ち、計算機の条件として特技周りの条件がやや不十分だと分かってきました。そこで、以下のように条件を改訂・追加したいと思います。

  • バックメンバーについては、上位4人が[シンデレラドリーム]新田美波、5人目以下は全員[全力熱血]日野茜であるとする。茜は無尽蔵に所持しているとする*1
  • 特技の効果がランダムなカードについては、全ての特技発揮ケースに応じた発揮値を算定し、これの平均をフロントの発揮値とする*2
  • 特技発揮の効果・範囲がランダムな特技については、全てのケースが等確率で発生するとする

データの入力と出力

まず、最適フロント計算機のデータ入出力は以下のようになります。

  1. Sレアカードのリストを渡す(今回はクール・18コスト以上に限定)
  2. 最適フロントのメンバーと、稼げる声援ptを返す

データの出力はまぁ普通に行うとして、データをどのようにインポートするかが問題になります。今回考える計算機においては、1つのカードについて以下の情報が保有されている必要があります。*3

  • カードの名前*4
  • コスト
  • 攻発揮値
  • 特技の効果範囲・効果量
  • 相場

これらを一元的に管理するために、今回はカード1枚1枚をあるクラス(以下、idolCardクラスと呼びます)のインスタンスとして扱うことにして、カードの名前やコストなどの情報はidolCardクラスのメンバ変数に格納することにします。そこで、入力するデータは以下のようなテキストファイルと、計算機はこのテキストファイルを入力として実行することにします。

100
kaede_01 24000 21 4 35 35 1000
ranko_01 23000 21 3 34 29 1000
...

このファイルの1行目には、カードの枚数を整数で入れておきます。次の行からは、カード1枚の情報を1行ずつ記述していきます。最初の文字列はカード名、次の数字は攻発揮値、さらにその次に数字はコストです。次は特技の効果範囲なのですが、特技の効果範囲に応じた特技効果量は既に分かっているので、ここには効果範囲のバクメンの人数を置きます。2~3人ランダムの場合は5とします。次が特技の効果量ですが、特技の効果量は(18コスト以上の範囲では)ランダムで最大2通りが存在するので、2つの数値を置いておくことにします。ランダムでなければ同じ数字を置きます。最後の数字が相場スタドリ数です。

このように設計されているテキストファイルを読み込んで、idolCardのインスタンスに情報を格納し、それぞれのインスタンスをベクタに格納することにします。

データの処理(1)

ここまででデータを外部から読み込むことが終わりました。次にデータの処理方法です。

1. 適当なidolCardを5枚選ぶ(要検討)

まず、発揮値・声援ptを計算したいフロントを、idolCardの中から5枚カードを選んで構成します。が、ここで問題になるのがカードの選び方です。

読み込んだファイルの中にはn枚カードがあるとして、単純にn枚の中から5枚選ぶのを全てやると、計算量が{}_n C _5 = O(n^5)となり、結構遅くなります。かといって今回やりたいのは5個のデータをn個のデータから選んで、そのデータを元にした計算結果をソートするということですから、単純にマージソートなどの各種ソートのアルゴリズムをそのまま適用することもできません。そこで、今回はカードの選び方について上手い具合のアルゴリズムを考える必要があるかと思います。

ただ、今回やりたいのは高々100枚程度のカードについての計算なので、計算の遅さには目をつぶってそのままやるということも考えられなくはないです。どのようなデータの選び方が良いのか(あるいは、単に組み合わせで5枚選んでくるしかないのか)については、もう少し考えたいと思います。とりあえず、データの選び方については棚上げして、次のことを考えることにします。

2. 発揮値を計算する

カードを5枚選べたら、1枚ごとの攻発揮値や特技をもとに発揮値を計算します。これは次回以降詳しく考えますが、まぁ発揮値の計算式が分かればそれをプログラムにするだけなので、そこまで大変でもないでしょう。

3. 声援ptを計算する

最後に、各カードの相場スタドリを予算の5000本から引いて、余ったスタドリを全てエナドリに変換した結果と掛け合わせて声援ptを計算します。これもそんなに難しくない作業ですかね。

4. フロントを声援ptごとにソートする

声援ptの計算が終わったら、フロントのカード名と声援pt(と消費エナドリ本数ぐらいあった方が親切かもしれません)を新しいクラス(仮にfrontPointとします)のメンバ変数に格納します。各フロントの声援ptの計算が終わったら、声援ptをキーとして降順にfrontPointクラスのインスタンスをソートし、一番声援ptが多いものを出力します。以上で計算は終わりです。

計算手順のまとめと今後の課題

以上の計算手順をまとめると、だいたい以下のようになります。

  1. データを受け取ってidolCardクラスのインスタンスに格納する
  2. idolCardのインスタンスから適当に5個選ぶ
  3. 発揮値を計算する
  4. 飲めるエナドリと発揮値を元に、声援ptを計算する
  5. フロントと声援ptをfrontPointクラスのインスタンスに格納する
  6. 各フロントの発揮値の計算が終わったら、発揮値をもとにfrontPointのインスタンスをソートする
  7. 最も声援ptが高いものを出力する

この手順の中において、目下の課題は以下の2点です。

  • idolCardからデータを5個選ぶより適切な方法を考える
  • フロントの発揮値の計算式を調べる

この企画の過程と結果は今年の夏コミで発表しようと思っていたのですが、思いの外いろいろと忙しくなってきた上、締切も想定よりかなり早かったため、実際間に合うかどうか怪しくなってきました。夏コミに間に合わなかったらブログで細々と続けることにします。

プログラミングや計算の方法についてツッコミがあれば是非コメントをください。

*1:バクメン4人特技に対応するため

*2:たとえば、あるフロントのカードAの効果量が極大~絶大ランダム、カードBの効果範囲がフロント+バクメン2人~3人の場合は、「カードA極大×カードBバクメン2人」「カードA極大×カードBバクメン3人」「カードA絶大×カードBバクメン2人」「カードA絶大×カードBバクメン3人」の発揮値を取って、これの合計の4分の1を代表の発揮値とする

*3:今回はクール属性のカードのみを考えることにするので、属性の情報は保有しないことにします

*4:これは必ずしも日本語でオリジナルのカード名を記憶しなくてもいいかなと思います。例えば、高垣楓のSレアについては、攻発揮値が高い順に「kaede_01」「kaede_02」……というふうにしておいて、後で読み替えるというようにしてもさほど問題はないと思われます。実のところは日本語文字列の入出力にあまり自信がないだけなんですけど