Dungeon Crawl 素手の速度

ぬるぽ堂さんのDC モンクの攻撃速度について id:xppm:20040914#p1
ソースみて近似的に期待値だすことを考えてみました。もしかしたら100回くらいサンプリングして確率を測定した方が手っ取り早いかもしれませんが^^;
スピードの計算の前に防具のペナルティを表す整数 h が乱数で決定され、重量超過がない場合に確率 1/(1+h) で高速な攻撃が出る。高速攻撃のスピードには乱数を使わない。 h の確率分布をP(h) とおくと高速攻撃が出るトータルの確率は\sum_{h=0}^{h_max}P(h)/(1+h)
しかし h が大きい場合を無視する近似が使える。素手の場合は h を計算したあとに50% ずつで2倍or 3倍されるので、その時点で h=0 と h=1 になっている場合だけ考えれば良い近似になる。
h は盾からの寄与 hs と鎧からの寄与 ha の和になる。したがって両方が0あるいは一方が1でもう一方が0の場合だけ考える。 hs が 0 である確率を Ps0 などとおく。h=0 となる確率は Ps0*Pa0。倍になる前に h=1 となる確率は Ps0*Pa1 + Ps1*Pa0。したがって P(2), P(3)は 0.5*(Ps0*Pa1 + Ps1*Pa0) で近似できる。この近似では高速攻撃の出る確率は P(0) + P(2)/3 + P(3)/4
以下で Pa0 などを求める。R(a,b)= a/b ただし1を超える場合は1と定義する。鎧の EV ペナルティをEv、プレイヤの甲冑スキルレベルをSa とおくと

fight.cc:
if (random2(Sa) < Ev) h += random2(Ev); //random2(x) は 0から x-1 までの乱数
より
Pa0 = 1-R(Ev, Sa) + R(Ev, Sa)/Ev
Pa1 = R(Ev/Sa)/Ev

小型の盾の場合、プレイヤの盾スキルレベルをSsとおくと

if (Ss < random2(7)) h++;
より
Ps0 = R(Ss+1,7)
Ps1 = 1 - Ps0

大型盾、種族がトロルやオーガなどの場合

if (Ss < random2(13)) h++;
より
Ps0 = R(Ss+1,13)
Ps1 = 1 - Ps0

大型盾、それ以外の種族の場合

for (int i = 0; i < 3; i++)
    if (Ss < random2(13)) h += random2(3);
より
C0 = R(Ss+1, 13) + (1-R(Ss+1, 13))/3
C1 = (1-R(Ss+1, 13))/3
とおくと
Ps0 = C0*C0*C0
Ps1 = 3*C0*C0*C1

float とかを使うとおそくなるので100倍して整数で計算とかにする。掛け算は掛けてから100で割る。
あとで実際のコードをアップしときます。