ダメージ拡大の期待値計算法

清松みゆき

 興味のあるかた向けに、計算方法を解説しておきます。計算式を多発しますので、ブラウザの横はなるべく広く取ってください。なお、乗算記号に「×」ではなく「*(たまに・)」、除算記号に「÷」ではなく「/」を使用しています。
 なお、このページは積極的意図をもって、壁紙を使ってません。だって……使ったら、異様に見にくかったんだもん。


ステップ1:基本−拡大なし、クリティカルなし

 基本となるのは拡大もせず、クリティカルも起こらない場合の計算法です。あるキーナンバーにおいて、レーティング表が

*,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12

 と並んでいたとします。言うまでもありませんが、添え字は2Dの出目に対応します。たとえば、キーナンバー10であるなら、

3=1,a4=1,a5=2,a6=3,a7=3,a8=4,a9=5,a10=6,a11=6,a12=7 です。

 このときの期待値は、各事象の起こる確率を乗算して合計し、

3*2/36 + a4*3/36 + a5*4/36 + a6*5/36 + a7*6/36 + a8*5/36 + a9*4/36 + a10*3/36 + a11*2/36 + a12*1/36

 となります。厳密には、a2*1/36 も足すわけですが、a2は常に0ですから。

 整理して

(a3*2 + a4*3 + a5*4 + a6*5 + a7*6 + a8*5 + a9*4 + a10*3 + a11*2 + a12) / 36

 ちょっと、数学に心得のあるかたなら、言われるまでもないってことですね。

 これを、(nc/ne)とします(nc=ノン・クリティカル、ne=ノン・エンハンス)。

 キーナンバー10の場合、この値は 3.33(厳密には10/3)となります。

 余談ですが、レーティング表は、このX(nc/ne)がキーナンバーに対して比例する(厳密に言えば、一次関数となる)ように作られています。
 キーナンバーをn、それに対応する期待値をX(nc/ne)(n)としたときに、次の式が成立します。

(nc/ne)(n) = (6n+60)/36 = 1/6・(n+10)

ステップ2:拡大なし、クリティカルあり

 1ステップ進みましょう。今度はクリティカルが起こる場合です。とりあえず、基本であるクリティカル値10のケースを検証します。他のクリティカル値を取る場合でも、ちょっと応用するだけですみます。
 ここで、テクニックとして、「こいつの期待値は、あらかじめわかっていて、そいつは (yc/ne)である」と、仮定します。そうしておいてから、「起こった結果に、起こる確率を乗算して合計する」という、ステップ1の考えをそのまま適用します。

 出目3〜9までは、変化ありません。そのまま、a3 〜 a9 を適用して、

3*2/36 + a4*3/36 + a5*4/36 + a6*5/36 + a7*6/36 + a8*5/36 + a9*4/36

 問題は出目10からです。クリティカル処理があるために、出目10、11、12が出た場合の結果は、a10、a11、a12の値そのものではなくなり、より以上ということになります。ゲームに戻って考えると、「a10、a11、a12を適用した後、さらにサイコロを振る」ことになります。
 いいです。b10,b11,b12としちゃいましょう。期待値は、

(a3*2 + a4*3 + a5*4 + a6*5 + a7*6 + a8*5 + a9*4 + b10*3 + b11*2 + b12) / 36

 b10は、a10よりどれだけ大きいでしょう? b10というのは、a10にクリティカルで増えた分を足したものです。さて、クリティカルでいくら増えるか?
 う〜ん、ちょっと待てよ、最初の1回も、クリティカル後の2回目以降もサイコロの振りかた自体は同じじゃありませんでしたっけ? 同じように2Dを振り、同じキーナンバーの欄を見て、10以上はやっぱり同じくクリティカル。

 そう、クリティカルで増える分、というのは、そのキーナンバーの欄を使ったときの期待値と同じなのです。

 ここで、期待値をX(yc/ne)だと勝手に仮定したことを思いだしてください。そうすると、b10=a10+X(yc/ne) とできます。
 同様、b11=a11+X(yc/ne)、b12=a12+X(yc/ne)。これを使えば、期待値はこう書き表されます。

{ a3*2 + a4*3 + a5*4 + a6*5 + a7*6 + a8*5 + a9*4 + (a10+X(yc/ne))*3 + (a11+X(yc/ne))*2 + (a12+X(yc/ne))} / 36

 整理して、

(a3*2 + a4*3 + a5*4 + a6*5 + a7*6 + a8*5 + a9*4 + a10*3 + a11*2 + a12) / 36 + X(yc/ne)*6 / 36

 この前半は、ステップ1で計算した、X(nc/ne)じゃあないですか。ゆえに、

(nc/ne) + X(yc/ne) * 6/36

 やりましたね、完成……って、嘘つけ(笑)。X(nc/ne)は、実際の数値から計算できていますが、X(yc/ne)のほうは、勝手に仮定しただけで、数値としての実体をまだ持っていません。
 えーっと、この式って何を表そうとしたんだっけ? そうそう、「拡大なし、クリティカルあり(クリティカル値10)」のときの期待値だったよな。
 そう、つまり、この式で表されるものこそ、X(yc/ne)なのです。とすれば、必然的にこう。

(yc/ne) = X(nc/ne) + X(yc/ne) * 6/36

 か〜んたんな一次方程式です。方程式というほどか? 小学校の□算のレベル。

□ = 3.33 + □ * 6/36

 これを解いて、

(yc/ne) = X(nc/ne) *36/30

 キーナンバー10ならば、X(nc/ne)は、3.33(厳密には10/3)ですから、

(yc/ne) = 3.33 * 1.2 = 4.00

 クリティカル値が10以外のときでも、これを少し変形させただけになります。クリティカル値が9ならば、a9*4/36 ではなく、(a9+X(yc/ne))*4/36 を使うので、

(yc/ne) = X(nc/ne) *36/26

 になりますし、クリティカル値が11ならば、

(yc/ne) = X(nc/ne) *36/33

 このへん、すでに「キーナンバー期待値対応表」や「マジック・アイテムの価格計算式」に使用されています。

 余談:これで、わかるように(拡大をしない場合)クリティカルが発生する処理では、発生しない場合に対し、期待値は定数倍となります。クリティカル値10の場合、必ず1.2倍です。ですから、クリティカル値10における、キーナンバーnに対する期待値をX(yc/ne)(n,c10)とすると、次の式が成立します。

(yc/ne)(n,c10) = 1.2・X(nc/ne)(n) = 1/5・(n+10)

 わかりやすく作ってあんのよ。クリティカル値10なら、打撃力5増しは+1ダメージなんだな。

ステップ3:拡大あり、クリティカルなし

 それじゃ、次は、(nc/ye)、つまり、拡大あり、クリティカルなしの計算です。
 2倍拡大なら、2回サイコロを振って高いほう、3倍拡大なら、3回サイコロを振って、その最大ってやつです。
 m倍拡大のときに、a2,a3,……,a12が起こる確率を p(m)2,p(m)3,……,p(m)12 とします。拡大なし(つまり1倍拡大とも言える)のときには p(1)2=1/36,p(1)3=2/36,……,p(1)7=6/36,……,p(1)12=1/36 なんですが、実際に拡大が入るとなると、どんなものか。

 p(m)k ってのは、どういうことか? 考えてみましょう。m回振って、出目kを採用するのはどんなとき?

 まず、このm回振ったサイコロの出目には、k+1以上は一つもないはずです。「すべてk以下」のはずです。
 次に、この出目の中には、最低一つkが存在します。ゆえに「すべてk−1以下」ということはありません。

 この二つを考え合わせれば、m回振ったサイコロの目が、「すべてk以下」である確率から、「すべてk-1以下である」確率を引けばよいということになります。
「(1回振った)サイコロの目がk以下」の確率を、qkとしますと、「m回振ったサイコロの目がすべてk以下」の確率は、qkmです。
 ゆえに、p(m)k は、こうなります。

(m)k = qkm - qk-1m


 qkの計算は悩みませんね。(1回振った)出目の確率を下から素直に足せば良い。

          k
k = Σp(1)i
         i=2

(1)kk
1/361/36
2/363/36
3/366/36
4/3610/36
5/3615/36
6/3621/36
5/3626/36
4/3630/36
103/3633/36
112/3635/36
121/3636/36

 これで、すべて既知の数値となりました。あとは、計算するだけです。

(nc/ye)
 ={a3*(3m - 1m) + a4*(6m - 3m) + a5*(10m - 6m) + a6*(15m - 10m) + a7*(21m - 15m) + a8*(26m - 21m) + a9*(30m - 26m) + a10*(33m - 30m) + a11*(35m - 33m) +a12*(36m - 35m)} / 36m

 見やすさのために、式では、36mを括りだしましたが、コンピュータなど使って実際に計算させるときは、1/36,3/36,……のqkをそのまま使ってもいいでしょう。

ステップ4:拡大あり、クリティカルあり

 いよいよ、最後の難関、(yc/ye)です。こいつは、今までのように一筋縄ではいきません。
 まず、間違えやすい例から。「ステップ2」と「ステップ3」を単純に組み合わせて、

(yc/ye)
 ={a3*(3m - 1m) + a4*(6m - 3m) + a5*(10m - 6m) + a6*(15m - 10m) + a7*(21m - 15m) + a8*(26m - 21m) + a9*(30m - 26m) + (a10+X(yc/ne))*(33m - 30m) + (a11+X(yc/ne))*(35m - 33m) +(a12+X(yc/ne))*(36m - 35m)} / 36m
 = X(nc/ye)+{1-(30/36)m}X(yc/ne)

「10、11、12が出た場合は、クリティカル処理で、これはクリティカルあり分の期待値を足せばいい」って考え。きれいに式もまとまって嬉しいな、と言いたいところなのですが……
 これは、大間違いなのです。

 なぜか? この式が表すのは「m回サイコロを振り、その最大出目を使用する。それが10、11、12であった場合にはクリティカル処理を行なう」というサイコロの振りかたをしたときの期待値です。
 これは、実際のレーティング表の使いかたに即していません。m回振るうちに、クリティカルが2回以上現われた場合のことを考慮していないのです。たとえば3倍拡大を考えてみましょう。

 1回目:出目3、結果を書き留めて終了。
 2回目:出目10、クリティカル! もう1回、またも10! もう1回、8。3つ分の合計を書き留めて終了。
 3回目:出目12、クリティカル! もう1回、出目6。2つ分の合計を書き留めて終了。
 結果:2回目を適用する。

 これが、正しい処理です。しかし、前述の式が表す振りかたはこうなってしまいます。

 1回目:出目3、結果を書き留めて終了。
 2回目:出目10、結果を書き留めて終了。
 3回目:出目12、結果を書き留めて終了。
 結果:出目12を適用することに決め、クリティカル処理に移行する……。

 クリティカルで合計が増える機会が2度あるはずが、1度になっています。ゆえに、間違いで、本来の期待値より少ない計算結果しか返してくれません。

 X(yc/ye)を計算するには、別のアプローチが必要なのです。

 ここで、レーティング表を使った結果は0または正整数であることに着目します。
 そして、結果が{0,1,2……}である場合に対応する確率を並べた、数列{r0,r1,r2,……}を設定します。
 さらに、この{r0,r1,r2,……}から、結果が0以下、1以下、2以下……である確率を並べた{s0,s1,s2,……}を作ります。

          k
k = Σri
         i=0

 このsk数列が手に入れば、簡単です。ステップ3での考えを踏襲して、m倍拡大で、結果がkちょうどとなる確率を

km − sk-1m

 とすることができるのですから。そうなれば、期待値X(yc/ye)は、

               
(yc/ye) = Σ(skm − sk-1m)・k
               k=1

 問題は、sk数列及び、その基準となるrk数列をどう求めるかと、無限をどう処理するか、です。

 無限に関しては、実は、簡単です。概算で我慢するなら、sk数列(rk数列)を無限まで求める必要はないのです。
 この数列は、きわめて早く収束します(sk数列は1に、rk数列は0に、むろん、skm−sk-1mも、あっというまに0)。
 どのくらい早いかって言うと、s/r200までも考えれば、期待値計算で乗算するk(=200)を考慮しても、とてもとても小数点以下第3位に影響しないぐらいです。
 乱暴に言えば、キーナンバー50においてすら、kが、13〜15増える度に、rkは、1/6になる、ということです。

 それより問題は、rk数列自身です(これさえわかれば、sk数列は足すだけ。k=200で区切るなら、せいぜい200回の足し算)。

 結論から言います。こいつを計算するのは、手計算では、まず無理です。単純にサイコロの出目を振り足していくのなら、まだマシなのですが、レーティング表に書かれた数値は不規則です。結果(拡大なしでの期待値)を合わせることを最低条件に、後は、ぱっと見に違和感がないように作ってあるだけです。
 ええ、作った本人が言うのだから間違いありません(笑)。
 でも、「0もしくは正整数のみを使用し、51行に渡って、10列きっかり、(縦横とも)順序が狂うことなく並べ、結果(拡大なしでの期待値)は、キーナンバーの一次関数でなければならない(このとき係数は1/6が望ましい)。ついでに、偏差も徐々に大きくしていくのがベター」という制限の上で、機械的規則性を持たせることが、はたして可能かどうかは、各自判断してくれな。『ドラゴンハーフRPG』も入れれば、61行だぜ。

 ここから先はどういうプログラムを組んだかになるので、詳しいことは、はしょります(大体、プログラムに使った言語自体、マイナーだ)。基本は、「レーティング表をデータとして持ち、出目に対応する確率を、レーティング表から得た結果を添え字にした配列にぶちこんでいく。出目、10〜12に相当する分は、その確率を乗じた上で再帰手続き」となります。
 このとき、再帰の深さは12で切りました(はい、kは200に到達していません)。(1/6)12・200に満たない数値が小数点以下2桁の概算において影響するとは思えませんからね。これでも余裕を見たほうでしょう。


<<戻る