この記事は Roguelike Advent Calendar 2020 19日目の記事です

こんにちは、Hourierです
今日は数ヶ月前に実験した結果をお送りします

皆さんは新しいセーブデータを作る時、どれくらい時間をかけますか?
その中でも特に、ダイスロール部分にどれくらい時間をかけますか?

ダイスロールの結果は以下のような感じです。
基本値の合計が86の時に理論上最悪値になります (87以上はそもそも永遠に停止しない)
以下の画面は複雑な計算に基づくもの値なので少数第1位未満切り捨てですが、ここでは見えている値をそのまま採用します
ダイスロール

さて、上のパラメータが実現する確率はいくつでしょうか?
答えは0.021^4 * 0.992^2 == 0.000000191381750784 ≒ 191ppb です
平均すると520万回に1回程度の確率で成功することになります
ところが実際にこのダイスロールを回すと、その100倍即ち5.2億回以上回してもぶっちゃけ出ないです
更に10倍の52億回でも出ない時は出ないです
これは単純な確率にして3.27*10^(-44)となり、「明日地球が滅びる確率とどっちが高いか」というレベルの低確率です
はて、そんな低確率がどうしてぽんぽこ発生するのだろうか?
これが第1の疑問として湧き上がりました

そこでコードを調査したところ、「HP」「身長」「隠密」等の値も全部ダイスロールで判定していることが判明しました
これ自体は毎回値が変わるので自明ですが、自明でないのはここからです

各種パラメータは「平均値と標準偏差を基に正規分布となるようにダイスを回す。出た値が規定範囲内に収まっていたらパスする」という動きをしていました
変愚蛮怒のダイスロールは、最終的なダイスロールに現れる結果を見る感じ、以下の要素から成ります (コードレベルで他に何をやっているのかも多少調べましたが、全部は調べきれませんでした)
  • 年齢
  • 身長
  • 体重
  • 社会的地位
  • 打撃修正
  • 射撃攻撃修正
  • AC (肉体のACなのか装備品の修正なのかは不明)
  • HP
  • レベル50時の最大HP (マスクデータ)
  • MP
  • レベル50時の最大MP (マスクデータ)
  • 所持金
  • 打撃命中
  • 射撃命中
  • 魔法防御
  • 隠密行動
  • 知覚
  • 探索
  • 解除
  • 魔法道具
  • 掘削
  • ライフレート (マスクデータ)
  • 各能力の最大値 (18/70 ~ 18/130) ← 多分これは一発で決まる
なんと最後を除いても22パラメータです
正規分布のテンプレを当てはめ、仮に全部「68.3%の確率 (偏差値で言えば40~60)でダイスロールをパスする」と仮定すると、「約1/4400」です
これらを加味すると「1/229億」!
いい感じの数字が出てきました!
ちなみに上記の数値は特別な条件 (狂戦士の隠密等)がない限りマイナスにはならないはずなので、実際の確率は70%台前半かそれ以上と思われます
そう考えるとそう外れた数値でもないでしょう

さて、こんな低確率のダイスロールをどうやってキビキビ動かすか?
これが第2の疑問点です
ようやくタイトル回収です、ここで「C言語」ではなく「C#」を使うとどうなるのか!

ということで(?)MultiThreadAutoRollerというツールを開発しました
単なるダイスロールシミュレータです
但し、「PCに搭載されたCPUスレッドを全部ぶん回してロールしまくる」というイカれたツールです
ここでは正規分布とか細かいことは考えず、「1/42億 のガチャを引くのに何秒かかるかの計測ツール」として作りました
これを使うと何秒くらいかかるでしょうか?

HourierのPCでは「最速1秒未満、最遅40秒程度」です!!
何分経っても出ないダイスロールもこれなら余裕ですね!
化け物級CPUをお持ちの方は最遅記録と共にお声がけ下さい!

ここまで爆速化できた理由は2つあります:
  • C言語ではマルチスレッド処理がほぼ不可能 (*1)だが、C#ならサクサク作れた
  • 画面描画を10fpsに落とす (*2)ことによって、ダイスロール方向にリソースを全力で割いた
これを叩き台にしつつ、今後Unity 2Dで作るとかそんな話になった時にガッツリ実装して、今の 度し難い 名状しがたき バールのようなもの コードをキレイにまとめ上げて行きたい所存です
それがいつになるかは全くの未定ですが、そうできたら嬉しいなという取り掛かりの報告と致します

明日は記者・題目ともに未定です……が、何か来ると思います
お楽しみに♪

*1 C言語の標準機能では今でも不可能だと思われます (調査不足かも)。そして現実問題、変愚のダイスロールはシングルスレッドで動作しています。OSごとに最適化されたマルチスレッド処理用ヘッダは多分ありますが、そうするとWindows用/OS X&Linux用/BSD用とプリプロがえげつないことになるので実装する気も保守する気もないです

*2 今の変愚蛮怒にも「Escを押すとその瞬間のパラメータ一覧を表示する」という機能があります。しかし事実上目押し不可能なフレームレートで基本値が目まぐるしく変わるので、10fpsでも60fpsでも事実上変わりません。ついでにいうとフレームレートを落とすためのコードが見当たりませんでした……