3世代のダメージ計算処理順を調査した。(2025/6/8 おいうち成功時などの2倍処理を追記)
前置き
3世代のダメージ計算ツールを作成する都合上調べる必要が出てきたので調査結果を記載する。
リーク+解析情報が含まれるため注意。
s32(符号あり32bit)で記載されているので、各項で計算後に(0方向に)小数点以下切り捨て。
※もしJavascriptで実装するのであればMath.Trunc()になるが、マイナスの値は出てこないのでMath.Floor()でもよい
各項では条件分岐が入っていると読み替えてほしい。(但し8項~15項, 20項は必ず処理が行われる)
1~20項はpoketool.c、21項~27項はserver.c, 27項~28項はcalctool.cを参照した。
以後実数値はそれぞれH, A, B, C, D, S、技威力はpow、レベルはlevel, 乱数生成結果をworkと表記する。
また、param[1], param[2], procのような表記を後述するが、この記事オリジナルの変数表記であることに注意。
1. ちからもち OR ヨガパワー(A*2)
2. バッジ補正
2-1. ストーンバッジ(A*110/100)
2-2. バランスバッジ(B*110/100)
2-3. マインドバッジ(C*110/100)
2-4. マインドバッジ(D*110/100)
3. 持ち物補正
3-1. 1.n倍系アイテム{A*(100+n)/100かC*(100+n)/100}
3-2. こだわりハチマキ(A*150/100)
3-3. こころのしずく(C*150/100, D*150/100)
3-4. しんかいのキバ(C*2)
3-5. しんかいのウロコ(D*2)
3-6. でんきだま(C*2)
3-7. メタルパウダー(B*2)
3-8. ふといホネ(A*2)
4. 特性 (実数値補正系)
4-1. あついしぼう(C/2)
4-2. はりきり(A*150/100)
4-3. プラス(C*150/100)
4-4. マイナス(C*150/100)
4-5. こんじょう(A*150/100)
4-6. ふしぎなうろこ(B*150/100)
5. 遊び
5-1. どろあそび(pow/2)
5-2. みずあそび(pow/2)
6. 特性 (威力補正系)
6-1. しんりょく(pow*150/100)
6-2. もうか(pow*150/100)
6-3. げきりゅう(pow*150/100)
6-4. むしのしらせ(pow*150/100)
7. 爆発技(B/2)
じばく、だいばくはつのこと。
8. 攻撃側ランク補正(A*倍率かC*倍率)
ランク補正は倍率の数値が10をベースにしているだけで、当然ながらランク+1で1.5倍になったりするところに変化はない。
| ランク | -6 | -5 | -4 | -3 | -2 | -1 | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 倍率 | 10/40 | 10/35 | 10/30 | 10/25 | 10/20 | 10/15 | 15/10 | 20/10 | 25/10 | 30/10 | 35/10 | 40/10 |
9. 攻撃側ランク補正後の実質実数値×技威力(A*powまたはC*pow)
この計算結果をparam[1]とする。
10. (level*2/5)+2
この計算結果をparam[2]とする。Lv50だと22になるよくあるやつ。
(level*2/5)で一度切り捨てされることに注意。
11. param[1]*param[2]
この計算結果をprocとする。
ここまでで下記計算が行われたことになる:
攻撃側ランク補正込みの実数値×特性補正込みの技威力×レベル考慮計算(level*2/5+2)
12. 防御側ランク補正(B*倍率かD*倍率)
項8と特に変わりなし。
13. proc/Bまたはproc/D
14. proc/50
15. やけど(proc/2)
16. ひかりのかべ OR リフレクター(proc/2)
18. 天候
18-1. あめがふりつづいている(proc*15/10またはproc/2) -> 水2倍と炎半減
18-2. すなあらし/あられ/ゆき状態のソーラービーム(proc/2)
18-3. ひざしがつよい(proc*15/10またはproc/2)-> 炎2倍と水半減
余談だが、没の「おおあめ」状態ではみずタイプがproc*2、ほのおタイプがproc/4、ソラビがproc/4だったようだ。恐ろしい。
19. もらいび(proc*15/10)
20. proc+2
21. 急所(proc*2)
後述する疑似乱数(pp_rand)で発生させている。
急所テーブル16,8,4,3,2を読み込んでいる。
きあいだめが無ければpp_rand()%16で0~15の16通り、この乱数発生結果が0のときに2倍になる。
つまり1/16の確率で急所が発生する。
22. 特定条件下2倍(proc*2)
22-1. おいうち->交代際
22-2. なみのり->ダイビング状態
22-3. ふみつけ->ちいさくなる状態
22-4. きつけ->まひ状態
22-5. からげんき(状態異常時)
22-6. リベンジ(被ダメージ時)
22-7. ウェザーボール(天候変化後)
23. 充電(proc*2)
24. 手助け(proc*15/10)
25. タイプ一致(proc*15/10)
26. タイプ相性(proc*20/10かproc*5/10かproc*0/10)
抜群(2倍)、半減(0.5倍)、無効(0倍)。
27. 乱数生成(85~100)
この計算結果をworkとする。厳密には下記。
u16 work = 100-(pp_rand()%16);
疑似乱数を発生させ16の剰余を求めて、100から引くことで85~100の範囲を再現している。
2世代までは217/255~255/255の39段階(≒2.56%)で発生するため、3世代は仕様が異なる。
また、39段階を16段階に圧縮されていたと仮定した場合は85~100の16段階の発生確率は不均等となるが、
実際のpp_rand()ではそのようになっていない。
pp_rand()の定義はcalctool.cに記載がある。
下記抜粋:
u16 pp_rand(void)
{
r_next = r_next *1103515245L + 24691 // 12345*2+1
return (u16)(r_next / 65536L);
}
ポケモン内部で使われている一般的なLCG。
0~65535の範囲で疑似乱数を返したのち、16の剰余を求めている。
pp_rand()%16を繰り返すコードでも作成して試してみると、0~15のそれぞれの数値が発生する確率は6.25%に近似していく。
このことから3世代における発生確率ダメージはそれぞれ1/16(≒6.25%)と均等である。
28. 乱数処理(proc*work/100)
つまるところ、27項~28項で(切り捨ての処理があるため厳密には違うものの)、
ダメージに対して0.85~1.00の乱数が掛け算されたことになる。
最後に
本記事では計算処理順を述べた。
他の世代では、乱数->タイプ一致->タイプ相性のようになることもあるが、
3世代ではタイプ一致->タイプ相性->乱数となる点に注意されたい。