補足その2:ダメージ計算式の導出

5.更に細かい事柄について

  1. 丸め誤差
  2. 剣の強さとちからの合計が大きい場合
  3. 攻撃力は本当に離散値か?
  4. はぐれメタルの防御力

丸め誤差

前節までに求めた計算式を使うとほとんどのデータを説明できるのですが、実はごく稀に1ポイントだけずれるケースがあります。例えば、これまでに示した攻撃力最大のトルネコがモンスターに与えるダメージデータステータスを変えながらスライムとドラキーを攻撃した時のダメージデータの中で、以下の三種類はどうしても説明できないケースとして残ります。

表5-1:うまく合わないデータ
トルネコのステータス敵の種類防御力予想ダメージ実際のダメージ
レベル12、武器なし、ちから1(攻撃力21)スライム/ドラキー117-2117-22
レベル28、武器なし、ちから25(攻撃力190)スライム/ドラキー1155-198155-199
攻撃力255おばけキノコ8133-169133-170

また、以下に述べるように最小/最大ダメージ以外にも目を向けると、予想からの微妙なズレは更に見つかります。モンスターの攻撃力とダメージ分布その2で述べたように、同一パラメータで取りうるダメージ値は最大で32通りあり、それらはほぼ等間隔に並ぶのですが、

最小ダメージ=攻撃力×(15/16)^防御力×7/8の端数を切り捨てた値
最大ダメージ=攻撃力×(15/16)^防御力×143/128の端数を切り捨てた値

である事から考えると、32個の数値の分布の詳細は

攻撃力×(15/16)^防御力×(n/128)の端数を切り捨てた値(n=112〜143の整数)

となるものと推測されます。が、この式を使って導いた32個の値をひとつひとつ実際の分布と比較すると、やはり1ポイントだけずれる例が稀にある事がわかりました。例えば、攻撃力255のトルネコがゴーストとももんじゃを攻撃した場合、最小ダメージと最大ダメージの間にいくつか絶対に生じない値ができます。最小値の124と最大値の159は予想と合うのですが、「生じないダメージ」が上式では126、136、146、155となるはずなのに対し、実際には126、136、145、155が生じません。どうやら切り捨てを行う前の端数が1に近いとうまく行かない事があるようです。おそらく計算の精度があまり高くないのでしょう。より正確な計算式を求めるには、実際の結果を再現するような精度の低い計算方法を考えてやる必要があります。

図5-1
図5-1:攻撃力最大のトルネコがゴースト/ももんじゃを攻撃した時に与えるダメージを記録したもの

上式の計算を、なるべく簡単に、精度をあまり気にしない方法で実装する事を考えてみます。スーパーファミコンのCPUには実数演算の機能は無く、乗除算についてもビットシフトによる×2、÷2の機能があるだけです。よって、機械語レベルで簡単に実装する方法としては、

という手順がおそらく自然でしょう。整数演算のみでそれなりの精度を出すために「×n(=112〜143)」を先に済ませて「/128」を後回しにし、「×15/16」を計算するために、16で割って元の値から引くというやり方を使うわけです。このようにすると、プログラム上では小数点以下の数字を一切気にせず、整数だけを扱って済ませる事ができます。この計算方法を用いると、先に示した微妙なズレはすべて消失する事が確認できました。


剣の強さとちからの合計が大きい場合

実はこれまでの考察では無視していたのですが、トルネコでは力や武器の修正値をひたすら上げていくと、突然あるところで攻撃力が不可解に変化する現象が知られています。長時間ダンジョンに潜りっぱなしで階段の昇降を繰り返していると急に攻撃力が弱くなってしまって、「武器は鍛えすぎると逆に弱くなる」と認識している人もいるようです。こうした現象は、剣の強さとちからの合計が136以上になると起こります。それ以下では攻撃力は少しずつ上がっていくものなのに、136になった途端に急激に変化するのです。この急激な変化、そして136という数字は一体何に由来するのでしょうか。

実はこの現象は、前節で結論した攻撃力の算出式によって解釈することが可能です。

トルネコの攻撃力=基本攻撃力(レベルによって決まる整数値)+[基本攻撃力×(剣の強さ+ちから−8)÷16を四捨五入した値]

136という数字は一見中途半端な数に見えますが、次のように考えると理解できます。コンピュータで数字を扱う場合、二進数八桁である8ビットという単位が多く用いられます。8ビットでは0から255までの数を表現することができるのですが、場合によっては、128以上の数字を負の数と見なすことで、-128から+127までの数字を同時に扱えるようにすることがあるのです。つまり、剣の強さとちからの合計が136になると、上式の「剣の強さ+ちから−8」の部分が128になるため、プログラム内部ではこの数値が-128に見えてしまい、計算結果がおかしくなってしまうというわけです。

よって、剣の強さとちからの合計が136以上の場合、攻撃力の計算手順は以下のようなものになります。

  1. 「基本攻撃力×(剣の強さ+ちから−8−256)÷16を四捨五入した値」を計算する(ただし、値が-255以下になった場合は一律-255とする)
  2. 基本攻撃力を足す
  3. 計算結果が負の数になった場合は256を足す

図5-2
図5-2:レベル37の時の攻撃力の変化の様子。横軸は剣の強さとちからの合計、縦軸は攻撃力。

このようにして、レベル37の時の攻撃力の変化の様子を計算してみたのが図5-2です。武器や力が弱いうちは鍛えるほどに上がり、最大である255に到達した後は横這いだった攻撃力が、合計136に達した途端に半分以下に落ちてしまっているのがわかります。

ちなみに、136になると必ず弱くなるというわけではありません。レベルが低く、元々の攻撃力が弱ければ、逆に強くなることもあったりします。レベル1での変化を同様に計算したのが図5-3です。この場合だと、136を境にして急激に強くなります。レベルが1のままで剣の強さやちからだけが上がっていく事は普通あり得ないので、このような変化を実感する機会はあまりありませんが、パルプンテの巻物を使って武器を異常強化した場合などにこのような不自然な攻撃力を見ることができます。

図5-3
図5-3:レベル1の時の攻撃力の変化の様子。横軸は剣の強さとちからの合計、縦軸は攻撃力。

図5-4
図5-4:剣の強さとちからの合計が136以上だと、異常な攻撃力になる

次に、剣の強さとちからの合計を136に固定して、レベルを上げていった場合の攻撃力の変化を見てみましょう。図5-5が計算結果ですが、なんと最初のうちはレベルが上がるほどに弱くなっていきます。レベル11からようやく強くなり始めますが、攻撃力は素手の場合とほとんど変わらない値です。

図5-5
図5-5:剣の強さとちからの合計を136にして、レベルを上げた時の攻撃力の変化

ところで、これまでの図にも示したように、剣の強さとちからの合計が248になると再び攻撃力が急激に変化し、完全に0になるという現象が起こります。また、上述の計算式に「−256」という値が含まれているため、合計が257以上では「武器なし、ちから1」から上げていった場合と同じ上昇の仕方をすることになります。数字の上での最強ステータスは「剣の強さ255、ちから99」なのですが、実際は剣の強さとちからの合計が98の時と同じ攻撃力にしかならないわけです。こうした現象も含め、実際のデータについて、この節で求めた式ですべてうまく説明できることが確認できました。


攻撃力は本当に離散値か?

以上で今度こそ完璧なダメージ計算式が完成です。が、念のためもう少しだけ検証作業を行ってみましょう。 これまでの議論で最も危うい部分は、プレイヤーからは直接見えない「攻撃力」という内部パラメータを仮定した事だと思われます。これが単に計算の途中で出てくる数字というだけならば気にしなくても良いのですが、問題はそれを整数値しかとらない離散的なパラメータと仮定したことです。結局はその仮定により観測ダメージが計算と合うようになったとは言え、できればもっと直接的な、攻撃力が離散的な値か否かがはっきりわかるような証拠が欲しいものです。

そこで、剣の強さとちからの合計を249にしてスライム/ドラキーを攻撃し、各ダメージ値の出現確率がレベルによってどのように変化するかを見てみました。先に述べたように、剣の強さとちからの合計が248を超えると、数値が一周してものすごく弱い(「武器なし、ちから1」よりもっと弱い)状態に陥ります。この状態でレベルを上げていくと、攻撃力の算出時に端数を処理して整数化する前の値はほんの僅かずつしか変化しません。よって整数化した後の数値は、数レベル上がってようやく1ポイント上がる、というのを繰り返す事になります。

従って、もし攻撃力が本当に離散的であり整数値しかとらないものなのであれば、数レベル上がるごとにダメージ値の出現確率分布が突然変化するはずです。一方、攻撃力が離散的でないならば、ダメージ分布がじわじわと変化していくのが観測されるでしょう。実際のデータを表5-2に示します。

表5-2:剣の強さ199、ちから50でスライム/ドラキーを攻撃した時の観測ダメージ分布
レベル攻撃力? (整数化前)攻撃力? (整数化後)試行回数ダメージ0ダメージ1ダメージ2ダメージ3ダメージ4ダメージ5ダメージ6
10.31250攻撃不可
20.4375 攻撃不可
30.56251298222(74%)76(26%)
40.6875 259201(78%)58(22%)
50.8125 323248(77%)75(23%)
61.0000 400293(73%)107(27%)
71.1875 400298(75%)102(26%)
81.3750 400297(74%)103(26%)
91.56252269215(80%)54(20%)
101.8125 346270(78%)76(22%)
112.0625 273214(78%)59(22%)
122.3125 400311(78%)89(22%)
132.56253252201(80%)51(20%)
142.8750 379296(78%)83(22%)
153.1875 400316(79%)84(21%)
163.5000 400307(77%)93(23%)
173.8125410072(72%)28(28%)
184.0625 5040(80%)10(20%)
194.4375 400322(81%)78(20%)
204.6250510978(72%)31(28%)
214.8125 10088(88%)12(12%)
225.0000 400317(79%)83(21%)
235.1875 400321(80%)79(20%)
245.3750 400312(78%)88(22%)
255.5625640030(8%)300(75%)70(18%)
265.6250 40030(8%)268(67%)102(26%)
275.6875 40019(5%)295(74%)86(22%)
285.7500 40034(9%)279(70%)87(22%)
366.2500 40019(5%)285(71%)96(24%)

攻撃力=基本攻撃力(レベルによって決まる整数値)+[基本攻撃力×(剣の強さ+ちから−8)÷16を四捨五入した値]

参考に、攻撃力の式をもう一度示しました。表の一番左の欄がトルネコのレベル、二番目の欄が上式での四捨五入をしない場合の攻撃力、三番目の欄が上式による四捨五入で整数化された攻撃力、四番目の欄が試行回数、五番目以降の欄がダメージ値の出現頻度です。ダメージ分布が整数化後の攻撃力と対応して変化しているのがおわかりでしょうか。例えば、整数化する前の攻撃力は、レベル1からレベ5までは0.125ずつ、レベル5からレベル9までは0.1875ずつ上がっていきます。が、ダメージ分布はレベル3からレベル8まではほぼ同じで、その前後でだけ急に変化するのです。間違いなく攻撃力は離散的な量のようです。


はぐれメタルの防御力

前々節でモンスターの防御力を求めたのですが、実はこの時ひとつだけ無視したモンスターがいます。はぐれメタルです。他のモンスターに関しては、トルネコの攻撃力を255に固定してダメージを記録し、ダメージ=攻撃力×(15/16)^防御力という式から防御力を逆算したわけですが、はぐれメタルにはこの式が当てはまりません。攻撃力に関わらず最大で1ポイントのダメージしか与えられないので、同じ手法が使えないのです。

そこで、はぐれメタルの特殊能力に元々関係のない、低い攻撃力で攻撃した時のデータを利用することにします。この場合でも「ダメージが0か1になる」というのは同じですが、攻撃力を変化させると0になる確率、1になる確率は変化していきます。攻撃力が低ければダメージは必ず0になりますし、攻撃力が高ければダメージは必ず1になるわけですが、その境目がどこになるかははぐれメタルの防御力によって決まるはずです。攻撃力を変えながらはぐれメタルを攻撃して、どの時点でダメージが0から1に変化するかを調べてみました。

表5-3:はぐれメタルへ与えたダメージの分布
条件 攻撃力 観測結果 防御力49の場合の予想値
試行回数 ダメージ0 ダメージ1 ダメージ0 ダメージ1
レベル9、木の矢による攻撃 19 100 100 0 100% 0%
レベル9、剣の強さ0、ちから5 20 100 92 8 93.75% 6.25%
レベル12、剣の強さ0、ちから1 21 100 63 37 71.875% 28.125%
レベル10、木の矢による攻撃 22 100 52 48 53.125% 46.875%
レベル9、剣の強さ0、ちから7 23 100 36 64 34.375% 65.625%
レベル10、剣の強さ0、ちから5 24 100 16 84 18.75% 81.25%
レベル9、剣の強さ0、ちから8 25 100 3 97 6.25% 93.75%
レベル13、剣の強さ0、ちから2 26 100 0 100 0% 100%

いろいろ条件を変えてデータを収集しましたが、そのうち境界値付近のデータのみを示します。攻撃力が19〜26の場合の数値を示したのが表5-3です。攻撃力19以下でははぐれメタルにダメージを与えることはできません。20〜25ではダメージ0とダメージ1が混在し、26以上になるとダメージは必ず1になります。今まで得られた計算式を使って、この結果を再現するような防御力を見つけてやればいいわけです。幸いな事に、この方法で防御力を一意に決めることができました。結果は49です。防御力が48や50ならば、攻撃力19で必ずダメージ0、攻撃力26で必ず1とはなりません。また、攻撃力が20〜25の時の確率分布も、防御力49による予想値にかなり近い結果が得られました。


この節の結論

  1. ダメージの計算は以下の手順で行われる。
    1. 攻撃力に112〜143の整数値乱数をかける。
    2. 16で割って端数を切り捨てたものを元の数字から引く、という手順を防御力の分だけ繰り返す。
    3. 128で割って端数を切り捨てる。
  2. 剣の強さとちからの合計が136以上の場合、攻撃力は以下の手順で算出される。
    1. 「基本攻撃力×(剣の強さ+ちから−8−256)÷16を四捨五入した値」を計算する(ただし、値が-255以下になった場合は一律-255とする)
    2. 基本攻撃力を足す
    3. 計算結果が負の数になった場合は256を足す
  3. 攻撃力は整数値である。
  4. はぐれメタルの防御力は49である。

以上でようやくダメージ計算式の導出過程についての説明は終了です。最後まで読んで下さった方(いるのかなあ……)、お疲れ様でした。


前へ

トップ > ゲームの話 > トルネコの大冒険 > 補足その2:ダメージ計算式の導出 > 5.更に細かい事柄について