酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

Swiftでポケモンサンムーンのダメージを計算する

ダメ計の闇……

ポケットモンスター サンムーン(以下、サンムーン)でのダメージ計算をしてみました。

今、試合結果をメモるアプリを開発しているんですけれどダメージ計算について調べて見たところ、アプリではサポートする気はないけれど面白そうなのでSwiftでダメージを計算してみました。

基本計算式

基本の計算式は、下記の記事を元にしています。

ダメージの基本計算式は以下のものです。
((攻撃側レベル×2÷5+2)×技の威力×攻撃側能力値÷防御側能力値÷50+2)×(急所補正)×(乱数補正)×(タイプ相性補正)
※ただし左から計算し小数点は発生する都度常に切り捨て

電卓を利用したダメージ計算法 - Paradigm Shift

疑似コードで書くと以下のようになります。

  1. レベル定数値 = floor((攻撃者レベル * 2) / 5 + 2)
  2. 基本ダメージ量 = floor(floor(レベル定数値 * 技の威力 * 攻撃者の攻撃力 / 防御者の防御力) / 50 + 2)
  3. 乱数適用後ダメージ量 = floor(基本ダメージ量 * 乱数倍率)
  4. ダメージ量 = pokeRound(floor(乱数適用後ダメージ量 * タイプ一致) * タイプ相性)

計算後には五捨六入します。本記事ではpokeRound関数を利用します。

func pokeRound(_ num: Double) -> Int {
    if (modf(num).1 > 0.5) {
        return Int(ceil(num))
    } else {
        return Int(floor(num))
    }
}

実際にダメージ計算してみました。

ガブリアスの「じしん」をメガバシャーモに使った場合

攻撃側:ガブリアス(Lv.50 じめん・ドラゴン) 攻撃実数値182
防御側:メガバシャーモ(Lv.50 ほのお・かくとう) 防御実数値101
使用する技:じしん(じめん) 威力100 命中100

ガブリアスはじしん・ドラゴン複合タイプなので、じめんタイプのじしんを使った場合 タイプ一致補正がかかり威力が1.5倍になります。メガバシャーモはほのお・かくとう複合タイプで、じめん技は効果が抜群となり威力がさらに2.0倍になります。

タイプ一致補正:1.5倍
タイプ相性補正:2.0倍

//攻撃者: ガブリアス
//実数値: A 182
let 攻撃者レベル: Double = 50.0
let 攻撃者の攻撃力: Double = 182

//技: じしん(物理 威力100)
let 技の威力: Double = 100
let タイプ一致: Double = 1.5

//防御者: メガバシャーモ
//実数値: B 101
let 防御者の防御力: Double = 101

//タイプ相性
let タイプ相性: Double = 2.0

//計算
let レベル定数値 = floor((攻撃者レベル * 2) / 5 + 2)
let B = floor(レベル定数値 * 技の威力 * 攻撃者の攻撃力 / 防御者の防御力)
let 基本ダメージ = floor(B / 50 + 2)

print("レベル定数値: \(レベル定数値)")
print("基本ダメージ: \(基本ダメージ)")

let 乱数倍率: [Double] = [
    0.85, 0.86, 0.87, 0.88, 0.89,
    0.9, 0.91, 0.92, 0.93, 0.94,
    0.95, 0.96, 0.97, 0.98, 0.99, 1.0
]

var damageValues = [Int](repeating: 0, count: 16)

for i in 0..<16 {
    let damage = floor(基本ダメージ * 乱数倍率[i])
    damageValues[i] = pokeRound(floor(damage * タイプ一致) * タイプ相性)
}

let 最小ダメージ量 = damageValues.first
let 最大ダメージ量 = damageValues.last

print("ダメージ量: \(最小ダメージ量!)\(最大ダメージ量!)")

上記のサンプルコードを実行すると、以下の計算結果を求めることができます。

レベル定数値: 22.0
基本ダメージ: 81.0
ダメージ量: 204〜242

特殊な技効果(フォトンゲイザーなど)、特性(テクニシャンなど)やアイテム使用(とつげきチョッキ)を含めた計算のタイミングは異なるようです。攻撃者の攻撃力に対しての倍率や技の威力に対しての倍率などそれぞれ個別に適用させて行く必要がありそうです。

命の珠を持ったガブリアスの「じしん」を特性ファーコートのトリミアンに使った場合

基本的な計算方法をベースにしてやや複雑な事例の場合のダメージ計算をしてみましょう。命の珠を持ったガブリアスの「じしん」を特性ファーコートのトリミアンに使った場合です。

攻撃側:ガブリアス(Lv.50 じめん・ドラゴン) 攻撃実数値182
防御側:トリミアン(Lv.50 ほのお・かくとう) 防御実数値80
使用する技:じしん(じめん) 威力100 命中100

ガブリアスはじしん・ドラゴン複合タイプなので、じめんタイプのじしんを使った場合 タイプ一致補正がかかり威力が1.5倍になります。トリミアンはノーマルタイプで、じめん技の威力は等倍です。

タイプ一致補正:1.5倍
タイプ相性補正:1.0倍

ガブリアスは「いのちのたま」 を持っておりダメージが1.3倍になります。トリミアンの特性「ファーコート」は防御力が2倍になります。

//攻撃者: ガブリアス
//実数値: A 182
//アイテム:いのちのたま(ダメージ*1.3)
let 攻撃者レベル: Double = 50.0
let 攻撃者の攻撃力: Double = 182

//技: じしん(物理 威力100)
let 技の威力: Double = 100
let タイプ一致: Double = 1.5

//防御者: トリミアン
//実数値: B 80
let 防御者の防御力: Double = 80 * 2.0 //ファーコートのように防御値を変更する場合はここを弄る

//タイプ相性
let タイプ相性: Double = 1.0

//計算
let レベル定数値 = floor((攻撃者レベル * 2) / 5 + 2)
let B = floor(レベル定数値 * 技の威力 * 攻撃者の攻撃力 / 防御者の防御力)
let 基本ダメージ = floor(B / 50 + 2)

print("レベル定数値: \(レベル定数値)")
print("基本ダメージ: \(基本ダメージ)")

//命の珠とかダメージ計算後の計算
var multiple = 1.0
multiple = multiple * 1.3 //命の珠(他に複合するダメージ係数があればここにのせる)

let 乱数倍率: [Double] = [
    0.85, 0.86, 0.87, 0.88, 0.89,
    0.9, 0.91, 0.92, 0.93, 0.94,
    0.95, 0.96, 0.97, 0.98, 0.99, 1.0
]

var damageValues = [Int](repeating: 0, count: 16)
for i in 0..<16 {
    let damage = floor(基本ダメージ * 乱数倍率[i])
    damageValues[i] = pokeRound(floor(damage * タイプ一致) * タイプ相性 * multiple)
}

let 最小ダメージ量 = damageValues.first!
let 最大ダメージ量 = damageValues.last!

print("ダメージ量: \(最小ダメージ量)\(最大ダメージ量)")

上記のサンプルコードを実行すると、以下の計算結果を求めることができます。

レベル定数値: 22.0
基本ダメージ: 52.0 ダメージ量: 86〜101

まとめ

基本的なダメージ計算ですら1〜2の誤差が出てしまってどうしようかと悩んでいたところ、ダメ計Zを開発しているスターホシさんから計算過程を出すモードがあることを教えていただきました。

計算式がどこまで合っているのかを調べる(デバッグする)ためにダメ計Zを使うのはアリです。

関連記事

この他にもポケモンについて書いています。まとめておりますのでこちらのページをご参照ください。よろしくお願いします。