見出し画像

歌姫座学の歴史を変えるオーディションシュミレータ【計算機配布】

どうも初めまして。なぶらです。4周年Pカップお疲れさまでした。
ちまちまやってた計算機が完成したので公開します。
この計算機は編成と打つ札の順番、判定を指定するとバフ、パッシブ、対面の判定と殴り先変遷、アピールの順番を含め、オーディションの内容を大量にシュミレートし、勝率や3ターン締め、4ターン締めできる確率を計算します。また、すべてのオーディション内容をログとして保存するので、どんなパッシブが鳴いているときにどんな札回しをすれば負けるのかを調べることもできます。

まずは下のリンクから動作デモをご覧ください。

https://youtu.be/EvtObFf_KjU

Googleドライブが使用できれば誰でも使用可能で、PCでもiPadでも何ならスマホでも動きます。GoogleColaboratoryという機能を使ってPythonのプログラムを回しています。

エラーの報告やどうしたら直るのかの質問、実装してほしい機能の希望なんかは僕のTwitterの方に寄せてくださると嬉しいです。

使用方法

①下のzipファイルを解凍してGoogledriveのマイドライブにアップロードする。


ダウンロードしたzipファイルをそのままドライブに突っ込まないよう注意。解凍してからドライブに移動してください。


ファイルのアップロード

audition_simulator_v.1.0の中に次ものがすべて入っていればOKです。

  • audition_simulator.ipynb…本体。基本ここをいじります。

  • database.xlsx…サポ札やオーディションの情報が格納されています。

  • deck_database.pickle…複数の編成を記憶させておく時に使います。開くことはないです。

  • rival_critical.pickle…対面の判定を解析した結果が格納されています。開くことはないです。

  • outputフォルダ…シュミレートしたオーディションのログが入るフォルダです。

ファイルの中身

ここで、Google colabを使ったことがない場合は、左上の+新規→その他→アプリを追加からColaboratoryをインストールしてください。

Colabインストール画面

audition_simulator.ipynbファイル(以下シュミレータ)を開いた時に下のような画面になっていれば準備完了です。

シュミレータの画面


②Pアイドル取得札登録、パッシブ登録、関数宣言のセルを実行する

セルというのはプログラムのコードが書いてある灰色の大きな箱みたいなもので、これらを順番に実行していくことでデータが読み込まれていきます。上から順番に「#自札の登録」から始まるセル、「#パッシブの登録」から始まるセル、「def choose_weapon(weapon_cnd,aim,P_ATK,week,critical,support_list,skill_history,buff_list):」から始まる3つのセルを左側の再生ボタンっぽいところクリックして実行します。これは新しくシュミレータを開くたびにやってください。場所わかんなかったらランタイムタブ→すべてのセルを実行でも大丈夫です。

あらかじめ走らせておく部分

③各種設定を指定してシュミレータを走らせる

いよいよ実行部分のセルを動かしていきます。左上の方の⁝≡みたいなマークから目次を開き、実行部分に飛ぶと下のようないろいろ指定する部分に飛べます。

いろいろ指定する部分

まずは編成部分(support_list、taken_Pweapon、taken_passive、EX_dict)に触らず、最初から入れてある編成で走らせてみましょう。status={}の中身には各ステータス、audition_name = の後に""で囲んだオデ名(正式名称じゃないとエラー吐くのでデータベースのExcelファイルからコピペするといいと思います。)、week=の後に経過ターン(S3初週なら16、歌姫突入S4残4週なら28)、Memory_lv=の後に思い出レベル、link_memory={}の中に各属性の思い出リンク追撃倍率、memory_add = {}の中に各属性の追加アピール部分の倍率(Lv3からつくやつ)(思い出でのバフ付与は対応してないです。思い出でのバフが大事になってくる編成なんかができたら実装するかもです。)を指定します。

ここからよく変える部分です。critical_list=[]の中に各ターンの判定を指定します。思い出の指定は別の場所で指定するので思い出のターンはpにでもしておいてください。(思い出はパフェ倍率で計算するので何入力しても結果変わらないんですけどね)例えばppgmを試したいときは、critical_list=[p,p,g,g,g]って感じにしておいてください。4ターン目までしか考えてなくても必ずもし4killできなかったときの5ターン目の判定も指定してください。

次にtrend=[]の中に流行を指定します。VoDaViの場合はtrend = ["Vo","Da","Vi"]として指定します。各属性名は「""」で囲み、3つの間は「,」で区切ってください。

aim_list =[]の中身で殴り先を指定します。殴り先は指定順にスピアするモードとターンごとに指定するモードを用意しています。

スピアを指定する場合は、優先順に3つの属性を指定してください。たとえばaim_list = ["Da","Vi","Vo"]と書くとDaの審査審が落ちるまでスピアし、落ちたらViにスピアするようになります。

ターン別に指定する場合は1ターン目から順番に殴り先を指定してください。指定先の審査員が落ちている場合、VoDaViの優先順で残っている審査員にアピールします。ここの指定はできないので審査員が落ちる順番とかある程度考えて入れないと確率ずれるかもです。4ターン目までしか考えてなくても必ず5ターン目の殴り先まで指定してください。

最後にweapon_list = []の中身で各ターンに打つ札を指定します。順番にsupportlist = []の中身のサポ札とtaken_Pweapon=[]の中身の自札からコピーして指定してください。また、思い出アピールはここで指定します。思い出打ちたいターンに"memory"と入力してあげるとそのターンに思い出アピールをしてくれます。また、"*"と指定すると、手札3枚のうちから指定された殴り先に対する攻撃力が最も高い札を選んで切ってくれます。(これめちゃめちゃ便利ですごいと思うのでいっぱいほめてください)札の名前は「”」で囲い、4ターン目までしか考えてなくても必ず5ターン目の札まで指定してください。
例えば、weapon_list = ["櫻木真乃花風smiley4凸","*","memory","*","*"]とすると、初ターンに花風完凸、3ターン目に思い出を打ち、それ以外は手札3枚から一番火力の高い札を選んで打ってくれます。(思い出は3ターン目以降に1度だけ打てます。手札周りに関しては、全札から3枚初手をランダムに生成し、打った札は手札から消えてまだ選ばれていない札から1枚補充されます。もし指定なんかで手札にない札を打った場合は手札はそのままで次ターンに移行し、それ以降その打った札は補充されません。要約するとちゃんとsシュミレーションできるようにうまいことなってます。)

あとはitr_num=の後に何回シュミレートするかを指定してこのセルを実行するとシュミレーションが始まります。いろいろ認証が来ますが(ドライブにアクセスしていいかとか)全部許可してください。デフォルトでは1000回回すことにしていて大体30秒ぐらいで終わります。編成によりますが誤差1%ぐらいかと思います。セルの下にシュミレーションの結果が出力されていると思います。各ターンで締まった確率と負けた確率(6ターン以降にもつれ込んだ時を含む)、18負けの確率(厳密には2位のTAは取れたけど負けた確率)を出力します。うおおおぉぉぉ花風最強!!

出力結果

④シュミレーション結果を確認する

グーグルドライブに戻ってoutputフォルダを開くと数字の名前のフォルダができていると思います。この数字は実行した時間を表していて、4月19日の12時30分00秒にシュミレーションを開始していた場合、0419_1230_00というフォルダにログが入っています。この日時のフォルダを開くとdefeated(負けパターン)、5turn_finish(5ターン締めパターン)、4turn_finish(4ターン締めパターン)…のフォルダが入っています。中身は見ればわかると思います。1回1回のオーディションのログがテキストファイルとして保存されています。手札とパッシブ、手札と打つ札が記録されている部分、各ターンに自分と対面がどこにどれだけのアピールを飛ばし、各審査員の残り体力がどうなっているかを記録した部分、各ユニットの与えたアピールと獲得した星を表形式で出力した部分から成っています。このファイルとにらめっこしてどの盤面で何を切ったら負けパターンか、3締めパターンかなど研究していってください。

ログの出力(上の方)
ログの出力(下の方)


自札、パッシブスキルの登録方法

では下の編成を登録していきながら自分で編成を作成する手順を紹介します。ハ♡トフェルトゥギフトの髪型と私服めちゃめちゃ可愛いですよね。持ってる中で見栄えが良くてデータベースにデフォルトで情報がない札を入れ込んだ感じなので編成にケチはつけないでください。札は自札無凸札と海完凸、空切り完凸とメンキュアの4枚、パッシブは自札金バフと海金、空切り金をとるとしましょう(説明のため以下略)

とりあえず編成指定を下のように打ち込みます。deck_nameに編成の自分で決めた名前、suport_listにサポ札を「アイドル名+カード名+〇凸」という書式で列挙、taken_passiveに取得するパッシブ、taken_Pweaponに取得する札を「Pアイドル名+札名+〇凸」という書式で列挙します。これらのワードはすべて「"」で囲んでください。画像のように文字が赤くなっていればOKです。EX_dict = {}の中には各サポ札のEXによるステ上昇量を書いてください。画像は全部DaVi虹貼ったときの例です。load_flgは後述します。Falseのままにしておいて下さい。

このまま実行すると、下のように札が登録されていませんというエラー文が表示されると思います。まずはこれら2つの取得札を登録していきましょう。

取得札が登録されていない

①取得札の登録

目次からカードのデータベースの項目を開きます。このセルを見てみると、いろいろな札が登録されているのがわかると思います。まずは一番上の自札のテンプレの内容をコピーして、適当に列を追加してペーストしましょう。

シャッターと海の間に行を追加してテンプレートをコピーした画面

ここに<>で囲まれた部分に対応する情報を書き込んでいきましょう。あとコメントアウトについてですが行の先頭に#を付けるとその行の内容をプログラムとして認識しないため、メモを残すことができます。札の名前が一目でわかるようにつけておくといいです。全体札やバフ付与、リンクなんかは実装していますが、渾身や背水、○○が高いほど威力上昇、注目度や興味あたりは実装していません。要望次第で実装するかもしれないです。できんことはないので…

登録例

特筆すべき点としては、

  • 数字、アルファベットは全部半角

  • <自分がわかる札名>は半角アルファベットと数字のみ対応で自分で名づける部分なので気を付ける。

  • 「”」忘れない(文字の色が他と一緒になってるか確認)

  • ALLバフや2色バフでも属性ごとにバフ追加の行を書く

  • インデント(行の最初のスペース)が違うと違う挙動をするので気を付ける

  • バフの名前("name":~~)はログにかかれる部分なので簡潔に

あたりです。
サポの完凸札(空切り)も同様に先頭からテンプレートをコピーして作っておきましょう。札の情報の並ぶ順番はあんま関係ないです。

取得札の登録例

最後にこのセルの最後の方にある部分に作ったこれら2枚の札情報を登録しておしまいです。画像では一番下に追加しています。
自札は"<編成指定のtaken_Pweaponで指定した札名>":Pweapon_templete("<アイドル名>",<自分で決めたアルファベットの札名>),
サポ取得札は、idol_name+"<札の名前>":Pweapon_templete(idol_name,<自分で決めたアルファベットの札名>),
という行を追加して下さい。最後の「,」忘れ一つでエラー吐くので他の行からコピペして作るといいと思います。

この状態で実行部分のセルを走らせると「~~は登録されていません」という文字が消えているはずです。これで札の登録は完了です。

②サポ札のデータベースへの登録

走らせたときに下のようなエラーを吐くときは、そのサポート札の名前が間違っているか、データベースに登録されていないかです。データベースのExcelファイルを開き、情報を追加しましょう。

データベースに情報が登録されていないエラー


大体見たらわかると思います。

  • ステータスはEXを張る前のもの

  • 空白は0が入っているものとして認識しますが一応0って入れておくと怖くない

  • Da_rateとかの行各属性のアピール倍率

  • Da_buffとかはバフの値

  • Da_buff_coTはそのバフが継続するターン数

これ以外の右の方は使わないので空白でOKです。ストレイなんかの同属性で複数バフがある場合はカンマで区切って並べることで実装できます。たとえばVo_buffに「5,5,5」、Vo_buff_coTに「3,5,8」とすれば3ターン5パーバフと5ターン5パーバフと8ターン5パーバフを付与します。

チョコ党の追加

③パッシブの登録

実行したときに下のようにパッシブが登録されていませんと表示された場合、taken_passiveで指定したパッシブ札が登録されていないので書き込む必要があります。

パッシブの登録は上から2番目のセルの下の画像のような場所です。ここにパッシブの情報を書き込んでいきます。

パッシブの登録場所

書き方は、同じように
"<taken_passiveで指定したパッシブの名前>":Passive_template("<ログに表示する短い名前>",<鳴く回数>,<鳴く確率>,<条件(後述)>,<付与する倍率リスト>,<追加情報(後述)>),
という行を追加していきます。例を見ると何となくわかると思います。
倍率リストについてですが、DaVi30%ずつのバフなら[["Da",30],["Vi",30]]、Vo50%バフなら[["Vo",50]]です。角括弧は1属性バフでも2ついるので注意してください。各条件について列挙していきます。

無条件バフ:no_requirement
「自分が参加している場合」、「(編成にイルミネ揃っていて)イルミネ全員がそろっている場合」などのときに使います。追加情報には何も書かなくてもいいです。例として花風の75%バフ乗っけときます。
"花風smiley金1":Passive_template("花風金1",3,30,no_requirement,[["Da",75]]),

3色バフ条件:three_color_requirement
全色のバフがついているときに鳴くバフに使います。追加情報には何も書かなくてもいいです。例の花風白です。
"花風smiley白":Passive_template("花風白1",3,30,three_color_requirement,[["Vo",50],["Da",50],["Vi",50]]),

1色バフ条件:buff_requirement
「Daバフが付与されている場合」なんかに使います。一応注目度UPが付与されている場合なんかにも使えます。追加情報に何のバフが付与されているかを書きます。例としてシャッターの金を上げておきます。
"シャッターチャンス金":Passive_template("シャッター金",3,30,buff_requirement,[["Vo",75]],"Vo"),
注目度UPが付与されているときなんかは、バフの追加のときに"Vo"とかの属性を指定していた部分に"注目度"なんかを指定して、ここの追加情報の部分にも"注目度"とすれば条件を拾うことができます。

ターン以前/以降条件: before_turn_requirement/after_turn_requirementnターン以降/以前というタイプのパッシブに使います。nを追加条件に書いてください。海の金バフは下のように書けます。
"水面を仰いで海の底金":Passive_template("海金",3,10,after_turn_requirement,[["Da",60],["Vi",30]],3),

履歴条件:history_requirement
スキル履歴に~~があるときなんかのバフに使えます。追加条件には履歴に必要なアイドルをすべて列挙して各括弧で閉じたものを書きます。一人でも各括弧で囲ってください。きゅんコメの金バフを例として挙げておきます。
"きゅんコメ金":Passive_template("きゅんコメ",3,40,history_requirement,[["Vi",75]],["櫻木真乃","風野灯織"])

これらすべてに当てはまらない場合はpossibility_requirementを使用します。追加情報に各ターンにそのパッシブが鳴く確率を指定することで疑似的にどんなバフでも再現ができるというものです。この計算機は体力が減ったりする部分を実装していないため、被弾バフやメンタル~%以上みたいなバフが指定できません。そこでこれを使用します。たとえばLATEの100%バフは
"LATE金2":Passive_template("LATE金2",2,20,possibility_requirement,[["Vi",100]],[0,0,10/32,58/512,0,0]),
としています。これは3ターン以降メンタル70%以上という条件を、そのターンまでに3回以上しない確率と解釈しています。(ただ回避や注目度UPが実装されておらず被弾率なんかが実際とはずれちゃうのはあります。)

これでハ♡トフェルトゥギフトと空切りは下のように実装できます。

実行するとちゃんと回りました

結構勝てるんだな…まあDa極でDa1位だし

便利機能

①複数の編成を切り替える

殴り先の指定で、スピアかターン毎指定を切り替えるときにコメントアウト機能を使いましたが同様に複数の編成よ用意しておき、使わない情報をコメントアウトすることで一から情報を書き換えずに済みます。

「#入力場所」から「itr_num =」の範囲をまるまるコピーして増やし、新しい編成情報を書き込んだうえで、使わないものを"""で囲みます。使わない編成の情報が全部赤くなってたらその部分は無視されます。

②札に優先順位をつける 

打つ札を自動で選んではほしいけど、火力の高い順に札を切るよりバフ札打つ方が強いから、切る札に優先順位を付けたいって時の対処法を紹介します。
切る札を選択する部分は、「関数宣言」の一番上のdef choose_weapon()の
部分です。

実はデフォルトでも優先順位がついていて、#手札から選ぶときの下の部位分で、花風2枚について記述があると思います。これは、

if "櫻木真乃花風smiley4凸" in weapon_cnd and turn_num < 2:
→花風完凸が手札にあり、かつ2ターン以内であれば
  return "櫻木真乃花風smiley4凸"
→花風完凸を打つ
elif  "櫻木真乃花風smiley0凸" in weapon_cnd and turn_num < 2:
→上の条件を満たさず、かつ無凸は手札にあって2ターン目以内なら
  return "櫻木真乃花風smiley0凸"
→花風無凸を打つ
else:~~~~~~
→どちらにも当てはまらなければ手札3枚から最も火力の高い札を選ぶ

というプログラムになっているのです。(この部分がないと、花風無凸よりも白札の方が単体火力は高く優先されてしまう。ほかの編成であれば「花風が手札にあり」という条件を満たさないので関係なく、else内の手札3枚から最も火力の高い札を選ぶという処理に入るので問題ない)
なので、たとえば海があれば最優先で切り、海がなくて自札Aがあれば自札Aを切る。それ以外は火力高い順にしたいなら下のように書き換えればいいわけです。(ちなみに4凸取得札の海は「(アイドル名)水面を仰いで海の底4凸」、サポ札の海は「風野灯織水面を仰いで海の底4凸」なので注意)


エラーを吐いたときの対処法

①NameError:~~is not defined

~~にあたる部分を""で囲み忘れています。原則指定場所は数字を除き全部""が必要です。(p,g,nの判定指定は例外的にそのままでOK)

②IndexError:list index out of range

打つ札や判定の指定を5ターン目までしていないことで起こることが多いです。100%4締めできる編成だとしても5ターン目まで指定しましょう。

③KeyError: "[~~] not in index"

~~がデータベースや自札、パッシブの登録部分に存在しないか、名前を間違えています。まずは名前間違いを疑います。たとえば画像の例では、「水面仰いで海の底」の「を」が抜けています。記号や数字の全角、半角なんかでも別物になってエラーを吐くので気を付けて下さい。

その他エラーが出たよという情報があれば解決方法とともに追記します。

謝辞

おおまかな草案ややデータベースの作成、基本的な使用を解説してくれた橘君、1000回分ものラベル付きのプレイ動画を提供していただいたMeteorさん、その判定解析を手伝ってくださったサーバーのみなさん、細かな仕様の確認や、デバック作業を手伝ってくれたshavaくんに感謝申し上げます。

新シナリオでこのシュミレータが全くの無価値にならないことを祈ります。

PS:2/28STEPが実装されました。ゴミツールと化しました。憐れんでください。

PS 10/8 Pカップファン数STEPで稼いだ分はカウントせずうおおおおおぉおぉぉぉぉぉぉおこれはゴミツールではありません神ツールです。WINGの難易度に対応させてないけどdatabase.xlsxのオーディション情報を書き換えれば対応できます。うおおっぉぉぉぉぉぉぉ。


この記事が気に入ったらサポートをしてみませんか?