🙌

ヒトカゲを遺伝的アルゴリズムで救いたい

2024/01/01に公開

初代ポケモンの話ですが、最初の3匹は強さに偏りがあるというはなしですが、どんなかんじでしょうか。
ポケモンの対戦を模倣して勝率を計算します。

ためしに最初の検証としてニビジムのタケシの1匹目のイシツブテとの対戦を考えます。
フシギダネ、ヒトカゲ、ゼニガメがそれぞれイシツブテと1対1で戦闘するしたらどうなるかです。
https://github.com/horitaku1124/pokemon_fight_simuration/blob/main/src/main/kotlin/com/github/horitaku1124/gen1/studies/Study101.kt
お互い使用する技はランダムに1つ選んだとして、それを1000回繰り返した勝率をもとめます。

フシギダネ ヒトカゲ ゼニガメ
Lv.7 51 0 0
Lv.8 63 1 77
Lv.9 78 14 93
Lv.10 84 30 95
Lv.11 88 41 96
Lv.12 92 61 99
Lv.13 99 73 99
Lv.14 99 86 99

フシギダネ/ヒトカゲ/ゼニガメの勝率

フシギダネはLv.7でやどりぎのたねを覚えるので低レベルでも善戦します。
ゼニガメはLv.8であわをおぼえるので、善戦するようになります。
ただしヒトカゲは効果抜群となる技を覚えないため全体的に低い勝率となっています。

遺伝的アルゴリズムを使ってヒトカゲの勝率を高めることを考えます。
毎ターンの使う技を遺伝的アルゴリズムで決定します。

class Gene(size: Int) {
  val gene: Array<Int> = Array(size) { 0 }
}

これを遺伝子クラスとして、内部配列に各ターンの使用する技を保存します。
これ20個ランダムに生成しそれぞれ1000回対戦した勝率を求めます。

fun intersect(parent1: Gene, parent2: Gene): Gene {
  val mixed = Gene(parent1.gene.size)
  for (i in 0 until mixed.gene.size) {
    if (i % 2 == 0) {
      mixed.gene[i] = parent1.gene[i]
    } else {
      mixed.gene[i] = parent2.gene[i]
    }
  }
  return mixed
}

対戦結果の勝率で並び替えて1位と2位を上記メソッドで混ぜます。
このGeneを20個複製して、ランダムに1つ書き換えます。

fun nextGenerations(gene: Gene, num: Int): List<Gene> {
  val newGenes = arrayListOf<Gene>()
  for(i in 0 until num) {
    val newGene = Gene(gene.gene.size)
    for (j in 0 until gene.gene.size) {
      newGene.gene[j] = gene.gene[j]
    }
    newGene.gene[rand.nextInt(gene.gene.size)] = rand.nextInt(256)
    newGenes.add(newGene)
  }

  return newGenes
}

とりあえず200世代続けてみます。

世代ごとの勝率

結果を見ると15世代くらいで最高の数値になっています。
とりあえず最大まで最適化してみます。

ヒトカゲ強化後の勝率

このグラフを見れば遺伝的アルゴリズムで勝率を上げることはできたようです。
ただし一つの技を連続で出していたという結果かもしれないですが、遺伝的アルゴリズムでその答えが導けるというのは有用だと思います。

Discussion