急にポケモンの話をします。最近、熱心にポケモンの対戦動画を見ていて、自分でも昨年11月に発売されたポケモン ウルトラサンムーンで対戦用ポケモンの厳選環境を作ってしまった。
ポケモンは対戦においてはタイプがとても大事なのだけど、タイプ同士の強弱関係を覚えるのが意外と大変。タイプは18種類ありすべての組み合わせに相性が設定されている(公式のタイプ相性表)。タイプ相性には方向があり、対象性はあったりなかったりするので、基本的には全組み合わせ覚えるしかない。また、2つのタイプをもつポケモンもいるので、複数のタイプ相性関係をかけ合わせて考える必要もある。
たぶん全部覚える必要はなくて、頻出の組み合わせを覚えば、なんとかなると思うのだけど、慣れるまでは大変。タイプ相性表を印刷なりして都度確認しつつ覚えていくのが良さそうだったけど、ちょうど良さそうな課題だったので自分でタイプチェッカーを作って見ることにした。
できたもの
こういう感じのWebアプリケーションを作った。
選択したタイプでぼうぎょするか、こうげきするかを選んでおき、上部のボタンを押してタイプを選択する。そうすると下の方に、タイプ相性の計算結果が一覧になって表示される。
スクリーンショットの例では、ゴーストとフェアリーの2つのタイプを持ったポケモン(=ミミッキュ) に対して、どんなタイプのわざが効果があるのかがあるのかがわかるようになっている。ミミッキュはこうかはばつぐんになる技のタイプが少なくて優秀ですね、という感じ。
https://douzemille.net/poketype/ にデプロイしてあるのでどうぞご利用ください。
実装
ポケモンタイプ相性チェッカーのコアドメインはタイプ相性関係である。そこで、まず、その部分を抽象化したnpmモジュールを実装した。
ここは一番大事なので、Flowで型アノテーションをほどこしてある。全組み合わせのテストはできそうにもないので、代表的な部分だけテストも書いてある。実装で一番大変だったというかだるかったのはこのへん。
このモジュールを使うと特定のタイプを持ったポケモンに対して、特定のタイプの技のこうげきを行ったときの効果を得ることができる。だいたい以下のようなイメージ。
import poketype from 'pokemon-type' const { ほのお, くさ } = poketype.Types const フシギダネ = poketype.createPokemon(くさ) const ひのこ = ほのお const effectiveness = poketype.calcEffectiveness(ひのこ, フシギダネ) console.log(effectiveness.message) // 'こうかは ばつぐんだ!'
まだ、npm publish してないけどそのうちしたい。インターフェースに日本語使っているのだけはやめたほうが良いかもと思っている。すでに、flow gen-flow-files
すると日本語の型定義の部分が8進数のunicode表記に変換された結果、use strict
されたJSの処理系で評価できなくなるという問題に遭遇している。
そして、このpokemon-types
モジュールを利用して、今回のWebアプリケーションを実装した。
このWebアプリケーションはフロントエンドだけで完結していて、ペラ1のHTMLとJavaScriptで構成されている。見よう見まねで現代的な感じのするReactアプリとして実装した。状態の管理にはRedux、コードのbundleを作るのには、webpackを使っている。
コアの部分はちゃんと実装できているという前提でこちらのコードはわりと殴り書きしている。実装がすべてindex.jsに書かれていたりしてひどいがまぁ動く。デザインセンスはないものの18種類の色のボタンを並べるとカラフルで華やかにはなった。
感想
できたものは、まぁ普通に便利という感じになった。UIの操作感のこなれなさはあるものの、とっさにぱぱっとタイプ相性を調べられる。
ただ、対戦相手のポケモンが登場したときに、そもそもそのポケモンのタイプを覚えていないことが多く、結局ググって調べることも多い。また、ポケモンにはタイプ以外にもいろんなパラメータがあるので、タイプ相性だけ知っていてもどうしようもなく総合的な情報がどうしても必要になる。そこまでくるとデータベースサイトを運用するみたいな世界になってくるが、そういうサイトはすでに存在するので自分でやるメリットはそんなになさそう。
まぁタイプ相性表を実装するのは世の中に何人もいなくて良いはずなので、公開しておくと誰かにとっては便利になるかもしれない。
自分のプロダクトでフロントエンドのJavaScriptを書くのはひさびさだったので、技術的な感想も羅列しておく
- VSCode でFlowのコードは書けるけど、VSCode自体はTypeScript推しなので時々TypeScriptっぽい型の解釈をしはじめたりする。設定で
javascript.validate.enable
をfalseにしておくと良い - eslint --fix + prettier で完全なる心の安心が得られる
- 日本語の識別子使うとテンションは上がるけど、動かないツールに遭遇する心配は増える(そして実際遭遇した)
- webpackは普通に良くできていてコレでいいじゃんという感じ。gulpよりも実際のユースケースに合わせてもうちょっとモデリングされている
- SASSでMap型の値をループするのは便利。ポケモンのタイプの数だけCSS書かずに済んだ
- eslintとbabelとflowとwebpackの設定をすべてやらないと開発が開始できないのは大変。一つのプロジェクトで設定を作ったらその後は使いまわせるので楽。ポケモンの厳選と同じやな!
- create-react-app には途中で気づいた
追記 (2017-01-09)
motemenさんによる先行研究があった
タイプ相性表を入力しているひとがここにもいた。その部分だけでも拝借すれば良かった...!