14
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ポケモンホームAPIを使って今採用すべきポケモンを可視化する

Last updated at Posted at 2020-11-24

ポケモンの環境とは

ポケモン対戦で使われる環境という言葉は,ポケットモンスター ソード・シールドのランクバトルにおいてどんなポケモン・戦略・構築が使われているかを指す言葉です.環境を知ることで,それに対するメタを考察することで現環境で勝ちやすい構築を作っていくのがポケモン対戦の醍醐味と言えます.

環境の中心

ガチ勢向けポケモン対戦情報共有サイトのポケモンソルジャーさんが運営するキャラランクメーカーではS ~ Eランクまでの評価を個人的に設定することができ,有名な実況者や解説動画投稿者が主観的に評価を下したキャラランクが参考にされています.

ポケモンソルジャーさん自身も定期的にキャラランクを公開しています.
https://youtu.be/TMXQ497foRg

スクリーンショット 2020-11-24 172842.png

このキャラランクのSランクについて,ポケモンソルジャーさんでは「環境の中心」と動画内で定義しています.
一方でその環境の中心の評価については主観的であり,またこれを見ても初心者としてはどんなポケモンを採用すればよいかわかりにくいと思います.

目標

目標はずばり,対戦環境を考えた上で今採用すべき汎用性の高いポケモンを可視化することです.

ポケモンホーム

ポケモンホームはスマホとSwitchで利用可能なポケモンの管理アプリです.ソフト内に保管しておけるポケモンの数に限りがあるため,こちらに不要なポケモンを一時的に保管するなどして使うことができます.

このポケモンホームにはそれ以外には交換機能やランクバトルでのポケモンの環境情報・プレイヤーのランキング機能なども備わっていて,ガチ勢の間ではこまめに環境調査に利用されています.

API

コチラの記事で紹介されている通り,ポケモンホームはUser-Agentを偽装することでアプリ内で利用されているAPIを直接叩いてjsonデータを取得することができます.今回使用するのは以下のAPIです.詳細についてはリンク先からご確認ください.

# シーズン・タームの情報の取得
https://api.battle.pokemon-home.com/cbd/competition/rankmatch/list
# 該当シーズン・タームの対戦データの取得
https://resource.pokemon-home.com/battledata/ranking/$id/$rst/$ts2/pokemon
# 該当シーズン・タームにおけるポケモンのデータ
https://resource.pokemon-home.com/battledata/ranking/$id/$rst/$ts2/pdetail-$j

評価手法

環境を視覚的にもわかりやすく,かつ分析がしやすい形に加工するために,今回はグラフを用いた評価を検討します.
グラフについては過去に書いた記事があるので,コチラを参照してください.

この記事では,使用率ランキング上位のポケモンとの同時採用率の高さを使ってグラフを作成することにしました.
採用するべきポケモンは,単体の性能ではなく他のポケモンに与える影響やパーティへの組み込みやすさを重視すべきだと考えたためです.
ポケモンホームの使用率ランキング上位30匹までの同時採用率が高いポケモンTOP10までを考慮し,その関係性を無向グラフで可視化することにします.ポケモン対戦環境をグラフとして考えて,そのグラフの媒介中心性が高いポケモンこそが環境のメディア,採用する必要のあるパーティのピースと考えます.

媒介中心性

媒介中心は,もともとはノードのクラスタリングを行う際にネットワークの切断面を決めるために用いられる指標です.

切断点はネットワークにおける関所のようなもので、異なる集団同士をつなぐ存在だったり、ボトルネックになるような重要な存在であると捉えることができます.

今回考えたい採用すべきポケモンとは,環境上位の周囲のポケモンに対して要となるようなパーティのピースになるポケモンなので媒介中心性を評価することで得ることができるはずです.

ノードとエッジ

無向グラフではノードとエッジを定義する必要があります.

今回はノードをポケモン,エッジを同時採用率上位の有無としてグラフを作成します.

例えば,エースバーンと同時採用率が高い10匹を考えるとすると,エースバーンのノードから10本のエッジをそれぞれのポケモンのノードに伸ばすことになります.

図1.png

これを上位30匹のポケモンに対して繰り返し,媒介中心性が高いノードに君臨するポケモンが環境上位のポケモンと相互に関係が強く影響を与えるまさしく採用すべきポケモンであると考えました.

中心性には複数の候補があり,以下のような特徴があります.

  • 次数中心性: そのノードから伸びるエッジの数で評価.つまり,友達の多い人気者が高く評価される.
  • 媒介中心性: 直接的なつながりだけではなく,すべてのノードへの平均経路長が評価される.幅広いつながりを持ち,複数の人気者とつながっていることを評価する.

データ収集

必要なデータは以下の通りです.

  • ポケモン図鑑(図鑑番号と名前の対応づけ)
  • シーズン・タームのID情報(rst・ts1・ts2)
  • 当該シーズン・タームの対戦環境情報(使用率上位のポケモンリスト)
  • 当該シーズン・タームのポケモンに関する情報(同時採用率上位のポケモンリスト)

ポケモン図鑑

8世代に対応したポケモン図鑑を探したところ,jsonファイルで配布してくださっている方がいたのでコチラをお借りしました.まだ鎧の孤島以降に追加されたウーラオス・ブリザポス等のポケモンの情報が更新されていないため,最新の環境で試すと図鑑にないポケモンのせいで少し結果にノイズが入ります.

> git clone https://github.com/dayu282/pokemon-data.json
import json

pokedex = {}
for i in range(8):
  # すべての世代のポケモンを追加
  j = i + 1
  with open("pokemon-data.json/en/gen" + str(j) + "-en.json", "r", encoding = "utf-8") as f:
    pokemons = json.loads(f.read())
    for pokemon in pokemons:
      pokedex[pokemon["no"]] = pokemon["name"]

シーズン・タームのID情報

# シーズンの情報を丸ごと全取得してjson形式で保存
> curl https://api.battle.pokemon-home.com/cbd/competition/rankmatch/list \
  -H 'accept: application/json, text/javascript, */*; q=0.01' \
  -H 'countrycode: 304' \
  -H 'authorization: Bearer' \
  -H 'langcode: 1' \
  -H 'user-agent: Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Mobile Safari/537.36' \
  -H 'content-type: application/json' \
  -d '{"soft":"Sw"}' \
  -o season.json
with open("season.json", "r", encoding = "utf-8") as f:
  data = json.load(f)["list"]

# タームごとに必要な情報だけを配列にまとめる
terms = []
for season in data:
  for id in data[season]:
    terms.append({"id" : id, "season" : data[season][id]["season"], "rule" : data[season][id]["rule"], "rst" : data[season][id]["rst"], "ts1" : data[season][id]["ts1"], "ts2" : data[season][id]["ts2"]})

当該シーズン・タームの対戦環境情報・ポケモンに関する情報

Jupyterを使ってコマンドに変数を埋め込むことでループを使って取得していく.ポケモン情報については5分割されているので,pdetail-{1から5}すべてを取得して連結する

for term in terms:
  if term["rule"] == 0:
    # 対戦環境の取得
    id = term["id"]
    rst = term["rst"]
    ts1 = term["ts1"]
    ts2 = term["ts2"]
    pokemons_file = str(id) + "-pokemons.json"
    !curl -XGET https://resource.pokemon-home.com/battledata/ranking/$id/$rst/$ts2/pokemon -H 'user-agent: Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Mobile Safari/537.36'  -H 'accept: application/json' -o $pokemons_file
    for i in range(5):
      # 当該タームのポケモン情報を取得
      j = i + 1
      pokeinfo_file = str(id) + "-pokeinfo-" + str(j) + ".json"
      !curl -XGET https://resource.pokemon-home.com/battledata/ranking/$id/$rst/$ts2/pdetail-$j -H 'user-agent: Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Mobile Safari/537.36'  -H 'accept: application/json' -o $pokeinfo_file
id = 10011 # シーズン1のシングルバトル

# 上位のポケモンリスト
with open(str(id) + "-pokemons.json", "r", encoding = "utf-8") as f: 
  top_pokemons = json.load(f)[:30]

# ポケモンの情報
pokemons_info = {}
for i in range(5):
  j = i + 1
  with open(str(id) + "-pokeinfo-" + str(j) + ".json") as f:
    data = json.load(f)
    for index in data.keys():
      pokemons_info[index] = data[index]

グラフの描画と媒介中心性ランキングの作成

必要なデータが集まったので,グラフを描画していきます.

nodes = [] # ノードリスト
edges = [] # エッジリスト

# トップ30匹を考慮
for pokemon in top_pokemons:
  # 当該ポケモンをノードに追加
  nodes.append(pokedex[pokemon["id"]])
  # 一緒に採用されるポケモンを追加
  with_poke_list = pokemons_info[str(pokemon["id"])][str(pokemon["form"])]["temoti"]["pokemon"]
  for with_poke in with_poke_list:
    nodes.append(pokedex[with_poke["id"]])
    if (pokedex[with_poke["id"]], pokedex[pokemon["id"]]) not in edges: # 順番による重複をなくす
      edges.append((pokedex[pokemon["id"]], pokedex[with_poke["id"]]))

nodes = list(set(nodes)) # 一度集合に変換して重複なしにする
import networkx as nx
import matplotlib.pyplot as plt
from matplotlib import font_manager

G = nx.Graph()

G.add_nodes_from(nodes)
G.add_edges_from(edges)

# 中心性を計算
bc_dict = nx.betweenness_centrality(G)
bc_list = np.array([bc_dict[n] for n in G.nodes])

# 中心性をノードのサイズで表して可視化
pos = nx.spring_layout(G, k = 7.5, iterations = 300)
fig = plt.figure(figsize=(15, 15))
nx.draw_networkx(
    G,
    pos=pos,
    node_color="c",
    node_size=bc_list*500/np.mean(bc_list),
    edge_color="lightblue"
)
plt.axis("off")
plt.savefig(str(id) + '-graph.png')
plt.show()
# 媒介中心性順に並び替える
bc_dict_sorted = sorted(bc_dict.items(), key=lambda x:x[1], reverse = True)

# グラフの出力
x, height = list(zip(*bc_dict_sorted))
plt.figure(figsize=(15, 15))
plt.xlabel("betweenness centarity")
plt.ylabel("Name")
plt.barh(x, height)
plt.savefig(str(id) + '-degs.png')
plt.show()

結果

シーズン1から順番に示していきます.鎧の孤島解禁以降はノイズが乗っています.

シーズン1

剣盾環境開幕.媒介中心性ランキングを見るとロトム・ミミッキュ・ドラパルトが同率一位であり,上位のポケモンとのシナジーの良さが評価されている.特に,ロトムに関しては「パーティの潤滑油」と評価がされているポケモンであるため,媒介中心性を用いると使用率ランキングよりも上位に食い込むのは自然に感じられる.

10011-graph.png
10011-degs.png

シーズン2

環境の変化が始まる.ヌルアント・ブリムオンドサイドン・ヌオードヒドなどが環境入りし,上位のポケモンとのシナジーが高いアイアント・ドヒドイデ・ドサイドンの媒介中心性が非常に高まる.

10021-graph.png
10021-degs.png

シーズン3

キョダイマックスカビゴンとキョダイマックスラプラスが解禁.ラプラスは採用率は高いものの,環境上位ポケモンとのシナジーが悪いのか媒介中心性は低い.ラプラスは並びで採用されるというよりは単体性能の高さを活用した弱点保険型が多かったため,この結果が得られたと考えられる.前シーズンまで媒介中心性が高かったドヒドイデとドサイドンは評価が下がり,アイアントだけが安定して採用され,環境の中心性ランキングがミミッキュ・ドラパルトを差し置いて1位になる.

10031-graph.png
10031-degs.png

シーズン4

新たにキョダイマックスポケモンが何匹か解禁される.リザードンが媒介中心性ランキング一位にランクイン.コータスリザードンの並びが環境に見られる.キョダイマックスの選択肢が追加されたことにより,話題性の向上と構築に組み込みやすくなったことがわかる.
また,リザードンの流行に伴ってカビゴンの使用率が徐々に伸びる.特性厚い脂肪を持った残飯カビゴンが採用されるようになったこともありパーティの最後のピースとして採用率が伸びる.

10041-graph.png
10041-degs.png

シーズン5

リザードンの流行が少し落ち着く.話題性がなくなってきた影響がありつつも,まだまだ環境の中心にいつづける.前シーズンの名残でカビゴンの採用数が増える.シーズン4上位構築にカビゴンを採用したものが多かったため影響を与えたものと考えられる.

10051-graph.png
10051-degs.png

シーズン6

ナットレイが媒介中心性ランキングの上位に食い込み始める.採用率・媒介中心性ともにトップレベルのドラパルト・ミミッキュ・ドリュウズなどの物理アタッカーの対策として採用され,オッカのみやきあいのたすきを持たせた行動保障型ステルスロック撒きが流行ったことが原因と考えられる.その影響かはわからないが,リザードンが再度媒介中心性トップに.

10061-graph.png

10061-degs.png

シーズン7

鎧の孤島解禁.エースバーン・ゴリランダーの夢特性の解禁とキョダイマックスの解禁により,一気に環境の中心へ.リザードンは引き続き媒介中心性トップ.環境上位ポケモンとのシナジーの高さを見せる.

10071-graph.png
10071-degs.png

シーズン8

ポケモンホームが解禁.驚いたことに,ハピナスが媒介中心性トップに.天の恵みハピナスが話題になってはいたがこの評価手法だとトップになるとは思いませんでした.落ち着いて媒介中心性の高いポケモンを観察すると,ハッサムやカバルドン,ポリゴン2,ドヒドイデなどのサイクルの中で活躍するポケモンが多くランクインしていることがわかる.つまり,シーズン8はサイクル構築が多く,高耐久を生かした戦術が流行っていたことがわかる.そのピースとしてハピナスが非常に重要な役割を担っていたということだ.

10081-graph.png
10081-degs.png

シーズン9

ハピナスが一気に環境から姿を消す.それにともなってポリゴン2・カバルドン以外の耐久ポケモンの媒介中心性が急下降.ウーラオスが参入してきたことによる,サイクル破壊が影響しているかもしれない.対面性能が高めのポケモンが上位にランクインしている.トゲキッスが2位にランクインすることから,対面構築のシーズンであったことがわかる.
※Charizard-1は図鑑の関係でおかしくなっているウーラオス

10091-graph.png
10091-degs.png

シーズン10

上位ポケモン禁止ルールになり,環境が激変.媒介中心性ランキング一位は圧倒的なホルード.ミミッキュやドラパルトなどの主要なゴーストタイプがいなくなったため,効果力ノーマル技の一貫性が非常に高くなったことからどんな構築でも活躍していたことがわかる.重要なポケモンに対してほとんどに等倍以上で攻撃ができるため,まさしくシーズン10で採用すべきポケモンである.

10101-graph.png
10101-degs.png

シーズン11

ハピナスが再度媒介中心性ランキング1位に.ゲンガーとアシレーヌのランキングが上昇し,ホルードが下がる.ホルードが前シーズンで猛威を振るったことに対するメタが見える.ハピナスは増えた特殊アタッカーに対する回答になる.

10111-graph.png
10111-degs.png

シーズン12

冠の雪原解禁.ランドロス・テッカグヤ・カプ・レヒレ・サンダー・ウツロイドなどの準伝説が環境のほとんどを占める.媒介中心性トップはバンギラスになった.おそらく環境上位のポケモンとの相性が抜群であり,どのポケモンとも距離が近いことが評価されている.カバルドンに対して挑発を打つこともでき,高耐久で安定した起点作成が可能であること,攻撃面での性能も高く型が豊富であることがアドバンテージに思える.

10121-graph.png
10121-degs.png

最後に

今回は媒介中心性に注目をしてランキングを作成しているので環境上位のポケモンの中で特にパーティに組み込みやすい,入れるべきポケモンを評価する形になっています.それにしてもミミッキュの安定感がとんでもないですね.「困ったらミミッキュを入れておけ」といわれているくらいですからね.常に採用すべきポケモンの一匹だと思います.

次回以降はその他の中心性を用いた可視化を行うことで,環境そのものを可視化できるように取り組んでいきます.

追記: 似たようなことやってる方がいました
https://qiita.com/b_aka/items/9020e3237ff1a3e676e4

追記: 中心性の定義が非常に曖昧のまま次数中心性を採用していましたが,媒介中心性を評価するように変更しました

14
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?