ポケモンの実数値や努力値をプログラミングで計算してみよう

adventar.org

Pokémon RNG Advent Calendar 2017 6日目です!
乱数の話ではありませんが、ポケモンの実数値, 努力値をプログラミングで計算する話をします。

この記事は、

  • プログラムに興味あるポケモン好きな人
  • ダメージ計算などで実数値の調整をしてるけど実際にどうやって計算しているのかわからない人

になんとなく理解してもらえたらなと思います。

はじめに

ポケモンには3値(種族値個体値努力値)がありますが、これらの解説はしません。
この3値を使って実数値を算出していきます。

数値計算

ポケモン徹底攻略 にわかりやすく実数値の計算方法が書いています。

HP
能力値=(種族値×2+個体値努力値÷4)×レベル÷100+レベル+10

HP以外の能力
能力値={(種族値×2+個体値努力値÷4)×レベル÷100+5}×性格補正

特に難しくないですね、単なる四則演算です。
これを Swift というプログラミング言語で書くとこのようになります。

HP

let hp種族値 = 100
let hp個体値 = 31
let hp努力値 = 0
let level = 50

let temp1 = Float((hp種族値 * 2) + hp個体値 + (hp努力値 / 4))
let temp2 = temp1 * (Float(level) / 100)
let hp = Int(temp2) + level + 10

ちょっと複雑になってしまいました、Int と Float という概念が入ってくるとややこしいですね。
整数と小数点で扱いが違うので、プログラム上はそれらを意識しなければなりません。

レベル÷100 のところでが、 50÷100 の場合整数だと切り捨てられて0になってしまいますが、小数点だと0.5になります。
なので Float という小数点を扱える型に変換してから計算しています。

HP以外の能力

let 攻撃種族値 = 100
let 攻撃個体値 = 31
let 攻撃努力値 = 0
let 性格補正: Float = 1.0
let level = 50

let temp1 = Float((攻撃種族値 * 2) + 攻撃個体値 + (攻撃努力値 / 4))
let temp2 = temp1 * (Float(level) / 100)
let temp3 = Int(temp2) + 5
let 攻撃 = Int(Float(temp3) * 性格補正)

HP と似ていますがちょっとだけ違いますね、大きな違いとして、性格補正の計算が入ってきました。
やはり整数<->小数点の型変換があって難しく見えますが、やっていることは HP と同じ四則演算です。

努力値を算出してみよう

さて、種族値個体値努力値を使って 実数値 を割り出すことができました。
今度は種族値個体値・実数値の3つを使って 努力値 を算出してみましょう。

HP

種族値が100, 個体値が31, 実数値が 200 の場合、努力値は幾つになるかを求めてみます。

let hp種族値 = 100
let hp個体値 = 31
let hp実数値 = 200
let level = 50

for hp努力値 in 0...252 {
    let temp1 = Float((hp種族値 * 2) + hp個体値 + (hp努力値 / 4))
    let temp2 = temp1 * (Float(level) / 100)
    let tempHp実数値 = Int(temp2) + level + 10
    if hp実数値 == tempHp実数値 {
        print(hp努力値)
        break
    }
}

for というものが入ってきました。これは繰り返しを表すもので、 0 ~ 252 を1つずつ増やして実行し続けます、ループなどとも呼ばれます。
for の中をみてみると、先ほど HP の実数値を求めた式と同じものが書かれています。

努力値を求めるというのは実は単純で、努力値が0の場合の実数値を求め、努力値が1の場合の実数値を求め... というのを繰り返します。
そしてその実数値が 200 になった時、求めていた努力値を計算できたことになります。

今回でいうと努力値196 というのが算出されます。

HP以外の努力値個体値も今まで解説したのと同じ方法で取得できます。気になる人は考えてみましょう。

わざわざこんな計算したくないよね

個体値ずかんZ for ポケモン ウルトラサンムーン

個体値ずかんZ for ポケモン ウルトラサンムーン

  • Kensuke Hoshikawa
  • ユーティリティ
  • 無料

はい、便利なアプリがあるので使いましょう。

もっと深く知りたい人は

github.com

上記で解説したプログラムをもっと抽象的にしたライブラリがあります。
こんな感じでステータスをセットするとだけで計算ができるようになっていますので、興味がある人は覗いてみてください。

let name = "ミュウ"
let baseStats = BaseStats(hp: 100, attack: 100, defense: 100, specialAttack: 100, specialDefense: 100, speed: 100)
let effortValues = EffortValues(hp: 0, attack: 0, defense: 0, specialAttack: 0, specialDefense: 0, speed: 0)
let individualValues = IndividualValues(hp: 31, attack: 31, defense: 31, specialAttack: 31, specialDefense: 31, speed: 31)
let nature: Nature = .calm

let pokemon = Pokemon(name: name, baseStats: baseStats, effortValues: effortValues, individualValues: individualValues, nature: nature)
print("hp: ", pokemon.hp) // hp:  120
print("attack: ", pokemon.attack) // attack:  108