ダメージ計算式の組み立て

国内で広まっているダメージ計算機の多くが同様の誤差が発生する問題を抱えていると前回指摘しましたが、ではどのように計算機を作れば誤差が発生しなくなるかの解決方法を今回紹介します。
今回の記事はSmogon University様の解析結果を引用しています。
英語が読める方は私の稚拙な解説よりも上記のページを読むべきです。


ダメージ計算順序は以下の通りです。

ダメージ = ( ( ( ( ( ( 攻撃側のレベル * 2 ) / 5 + 2 ) * 威力 * 攻撃力 ) / 防御力 ) / 50 + 2 ) * マルチ対象※ * 天候※ * 急所 * 乱数幅(16分率) * タイプ一致※ * タイプ相性 * 火傷 * ダメージ補正※ )
威力 = ( いりょく(技) * 威力補正 )
攻撃力 = ( こうげき * 攻撃力補正 )
防御力 = ( ぼうぎょ * 防御力補正 )
※のついたステップは五捨六入、それ以外のステップは切り捨て
また威力、攻撃力、防御力、ダメージに関わる補正は全て五捨六入

まず注意したいのが古いダメージ計算機は第四世代の計算式を引きずっているところです。
例えばトレーナー天国様のダメージ計算機は火傷による攻撃力低下を、上の計算式の場所で行っておらず、「攻撃力」を直接2で割り切り捨てています。
故にそれを参考にしているダメージ計算機も同様の処理を行っているため、「やけど」状態でのダメージ計算が正しく行えていません。


そして最も気をつけなければならないのが補正です。
ポケモンは技の効果、特性、持ち物などで様々な補正が掛かります。
この補正処理を誤ると、一つ一つは小さな誤差で表面上に現れなくとも、その数が多くなるにつれ誤差の原因となってしまいます。
また、そもそも補正を掛ける場所を誤ってしまえば初めから正確でない結果が出てしまいます。


補正計算は次の通りです。

補正'' = ( 補正 * 補正' + 0x800 ) >> 12

注意すべきは補正はいきなり補正対象に掛け合わせるわけではなく、同じ対象に掛ける補正は補正同士を掛け、最後に補正対象に掛けます。
また補正同士を掛ける度に処理が入ります。上の計算式では0x1000の半分に当たる0x800を足し右に12ビットシフトさせます。
同じ対象に掛ける補正の順序は概ね下記の通りです。

壁系→特性→持ち物→技の効果→場の効果

また補正対象に補正を掛ける場合は全て五捨六入です。
切り上げ、切り捨て、四捨五入などの処理はこのステップ中では一切存在しません。


以上のルールを守った場合の計算は、前回の検証を例にすると下記の通りとなります。

検証1

威力 攻撃力 防御 一致 相性
102 177 62 1.5 1
補正 補正
[防御1.5倍(0x1800)] 火傷


( ( ( ( ( ( 50 * 2 ) / 5 + 2 ) * 威力 * 攻撃力 ) / 防御力 ) / 50 + 2 ) * 1 * 1 * 1 * 乱数幅 * 1.5 * 1 * 0.5(火傷) )
防御力補正 = 0x1800
ダメージ補正 = 1
威力 = 102
攻撃力 = 177 (火傷はここで計算しない!)
防御力 = ceil ( 62 * ( 0x1800 / 0x1000 ) - 0.5 ) = 93

結果 54〜65

検証2

威力 攻撃力 防御 一致 相性
130 100 125 1.5 1
補正 補正 補正 補正
[威力1.199951171875倍(0x1333)] [威力1.300048828125倍(0x14CD)] [威力1.25倍(0x1400)] [威力1.5倍(0x1800)]


( ( ( ( ( ( 50 * 2 ) / 5 + 2 ) * 威力 * 攻撃力 ) / 防御力 ) / 50 + 2 ) * 1 * 1 * 1 * 乱数幅 * 1.5 * 1 * 1 )
威力補正の順序は0x14CD, 0x1400, 0x1333, 0x1800
威力補正 = 0x14CD
威力補正 = ( 0x14CD * 0x1400 + 0x800 ) >> 12 = 0x1A00
威力補正 = ( 0x1A00 * 0x1333 + 0x800 ) >> 12 = 0x1F33
威力補正 = ( 0x1F33 * 0x1800 + 0x800 ) >> 12 = 0x2ECD (/0x1000 = 2.925048828125)
ダメージ補正 = 1
威力 = ceil ( 130 * ( 0x2ECD / 0x1000 ) - 0.5 ) = 380
攻撃力 = 100
防御力 = 125

結果 171〜202