【Poke-Controller】レジェンズアルセウスのフィールド色違い探し自動化(紅蓮の湿地ver)
はじめに
色違いオヤブンをゲットしたい!
そんな思いから、Poke-Controllerを使ったレジェンズアルセウスのフィールド色違い探し自動化プログラムを作成しました。
プログラムは下記に格納しています。
2023/4/30追記:
v3.0に修正しました。夜盗と戦闘せずリセットするようになっています。
(戦闘すると、博士に図鑑の報告をして止まってしまうため)
また、テンプレートマッチング未使用版を作成しました。
※本記事とカメラ感度の設定が異なるのでご注意ください!(2023/8/15追記
何が出来るの?
紅蓮の湿地エリアで 、次のオヤブンがいるルートを自動移動します。
・リングマ 、パチリス 、ドクロッグ 、ドダイトス 、ヌメイル
運が良ければ、上記のオヤブン色違いを発見できます。
また、移動中に出現するオヤブン以外の色違いポケモンも発見できます。
色違いに会うまでの所要時間は、今のところ平均45分くらいです(光るお守りありの場合)
ただ、最長で1時間半くらい色違いが出ないこともありました
捕獲は手動です!逃げられないように注意してください!
注意事項
PokeCon3.6(Python3.6)でのみ動作確認しています
Poke-Controllerの環境設定が必要です。
(pyaudioというライブラリをインストールする必要があります)
事前準備
Poke-Controllerの環境設定(pyaudioのインストール)
すみません、やり方を忘れました・・・。
再現できず自信ないですが、下記の手順で出来ると思います。
人によって環境が違うため、記載のやり方ではできないかもしれません!
1.コマンドプロンプトの起動
「Windows」キーを押しながら「r」キーでファイル名を指定して実行
「cmd」と入力してコマンドプロンプトを起動します
2.コマンドプロンプト上でコマンド入力
コマンドプロンプト(黒背景の格好良い画面)が開きます
下記の順にコマンドを入力して、pyaudioをインストールします
(人によってはパスが違うかもしれません・・・)
カレントディレクトリをConda環境のあるところにします
cd %USERPROFILE%\Anaconda3\Scripts\
Conda環境を起動します
activate.bat
PokeCon3.6の環境を呼び出します
call conda activate PokeCon3_6
pyaudioをインストールします
call pip install pyaudio
これでpyaudioのインストールは終了です
やり方がうろ覚えのため、上手くいかなかったらごめんなさい・・・
プログラムの格納
1. ダウンロードしたファイル「ArceusFieldShinyv1_0.py」を格納する
「ArcuesFieldShinyv1_0.py」は、下記フォルダに格納してください
※2022/09/05追記:最新版は「ArceusFieldShinyv2_0_Guren.py」ですが、あまり変わらないのでどちらでも大丈夫です
パス:Poke-Controller-master\SerialController\Commands\PythonCommands
2. ダウンロードしたフォルダ「Arceus_Tree」を格納する
「Arceus_Tree」は、下記フォルダに格納してください
パス:Poke-Controller-master\SerialController\Template\
レジェンズアルセウスの設定
下記の状態であることを確認してください
(0)オプションで「カメラ感度」を「3」にする
(1)オプションで「話の速さ」を「速い」にする
(2)オプションで「BGM」と「鳴き声」を「0」にする
(3)「紅蓮の湿地」の「湿地ベース」へ移動する
(4)ライドポケモンは、ウォーグルにカーソルを合わせる
(5)低確率で夜盗に襲われるため、A連打でドクロッグを倒せるポケモンを手持ちに入れ、カーソルを合わせる
(6)レポートを書いておく(おまかせレポートはオフにする)
※プログラムの誤動作で主人公が倒れてアイテムロストするかもしれません、念のためレポート重要です
動作の流れ
紅蓮の湿地に移動した後、プログラムを実行してください
ウォーグルに乗って、下記のオヤブンがいるルートを自動で移動します
・リングマ
・パチリス
・グレッグル
・ドダイトス
・ヌメイル
色違いが見つからなかった場合は、キャンプに戻る→村に戻る→紅蓮の湿地に移動して、また先ほどの移動を繰り返します。
色違いが見つかった場合は、CAPTUREボタンを長押しして動画を撮影した後、HOMEボタンを押してプログラムを終了します。
プログラムが終了したら、撮影された動画を確認してください。
動画を見れば、色違いがどこに発生したのか分かります。
(動画に映っていない場所で色違いが発生することもあります・・・)
ゲームを始めるときは、まずレポートを書きましょう。
(逃げられたらリセット!)
その後、動画の情報をもとに色違いのポケモンを探してましょう。
見つからない場合は、一度キャンプに戻ってから同じ場所へ行ってみてください。
もう一度、色違い出現の演出を見ることができるため、確認しやすいです。
※キャンプで朝まで休んだり、時間帯が変わったりで色違いのポケモンが消えることがある気がします(詳細不明。キャンプに戻るだけなら消えなかったです)
※ポケモンの捕獲は手動で頑張ってください。ヒメグマやチュリネなど逃げやすいポケモンが多いので気を付けて!(油断すると逃げられます…)
参考動画
プログラムの動きを動画化しました。
1周目は色違いなし、2周目に色違いを検知して終了します。
あとがき
本プログラムは、こちゃてす様とろっこく様にアドバイスをいただき、完成させることができました!
改めて、本当にありがとうございました。
(元々のプログラムはPoke-Controllerのstopボタンを押しても止まらないという致命的な不具合があり、私にはどうしても修正できませんでした…)
また、自動化を推進してくださっている先人の方々、いつも本当にありがとうございます…!
おかげさまで自動化することができました
おまけ:プログラムの内容と改変箇所について
プログラムの中身をざっくり記載します。
他のプログラムに流用する際の参考となれば幸いです。
なお、あまり厳密な検知方法ではないため、誤検知が起こりやすいです。
レジェンズアルセウスは、BGMや鳴き声を設定でオフにできるため、この方法でもそれなりに検知することができました。
BGMなどをオフにできないゲームでは、他のやり方を検討した方が良さそうです。
プログラムの改変箇所
音声認識処理(audiolv関数)を実行すると、音声処理が開始されます。
音声認識する内容を変更したい場合には、下記の箇所を書き換えてください
while stream.is_active():
try:
print(self.counter, '周目(夜盗',self.yato,'回、逃走失敗',self.target,'回):経過時間',int(((self.ends - self.starts) / 3600) % 24),'時間',int(((self.ends - self.starts) / 60) % 60),'分',int((self.ends - self.starts) % 60),'秒')
self.fue = False
self.toGuren()
self.fue = True
self.returnCamp()
self.talkLaven()
self.toField()
self.counter += 1
上記「try:」の中身を、認識したい処理に書き換えます。(357~364行目)
例えば、「self.toGuren()」を「self.toGunjo()」に変更して、「toGunjo()」という関数内で「群青の海岸」を移動するプログラムを記述すれば、群青の海岸で色違い探しをすることが出来ます。
移動するプログラムを記述する際は、色違いを検知したい区間でノイズが発生しないよう注意してください!
例:色違い検知区間はウォーグルの移動中にBボタンを押さない(加速しない)
Bボタンの加速中は余計な音が発生するため、色違いの検知を上手くできない可能性が高いです。
本プログラムは、色違いオヤブンの検知を主目的として作成したため、オヤブンが出現する数秒間だけBボタンを押さずに移動しています。それ以外の箇所はBボタンを押していますが、これは移動の効率化が目的(=検知できなくても良い箇所)です。
なお、誤検知を防ぐために、「self.fue」という変数を使っています。
「self.fue = True」の場合、比較する周波数と一致していても、検知しないようになっています!
これは、「+」ボタンを押してライドポケモンを呼び出した際に流れる笛の音を、色違いの周波数と誤検知することがあったため追加した処理です。
誤検知する可能性がある移動処理中は「self.fue = True」として、実際に検知したい処理の間だけ「self.fue = False」とすることで、誤検知を防ぐ効果があります。
なお、比較する周波数は283行目、下記で定義しています。
FREQ_HIGH_BASE = 1399.80 #フィールド上の色違いSEで反応する周波数
私の環境では、この周波数でフィールド上の色違いを検知できました。
なお、戦闘時の色違いは別の周波数「1249.23」で検知できそうです。
音声認識の内容
このプログラムは、音声を使って色違いかどうかの判定をしています。
音声認識にも色々やり方はありますが、今回は下記のようにしました。
一定以上の音量を検知した場合、FFTで最大振幅の周波数を取得し、事前に設定した色違いSEの周波数と一致しているかを調べる
音声関連の処理は、「audiolv」関数で行います。
下記の処理で、音声取得を開始します。
stream = P.open(format=pyaudio.paInt16, channels=1, rate=RATE,
frames_per_buffer=CHUNK, input=True, output=False,
stream_callback=callback
)
stream.start_stream()
音声関連の設定は次の通りです(私の理解が正しければ)
format=pyaudio.paInt16:取得する音声の音量レベルの範囲を指定。
Int16なので、2^16=65,536段階(-32,767~+32,767)の値で取得。channels=1:モノラルは1、ステレオは2。今回はモノラルなので1。
rate=RATE(=8000):サンプリングレート。1秒間で8,000個の音を取得。
frames_per_buffer=CHUNK(=1024):callback関数で扱うフレーム単位を指定。リアルタイムで音声を取得していき、1,024個の音が集まったらcallback関数を呼んで、その1,024個の音の集まりに対して処理。この値は2のべき乗(2^n)を指定する必要があります。
input=True:音声入力をする(Falseだと音が入ってこない?)
output=False:音声出力をしない(リアルタイム再生するかどうか?)
stream_callback=callback:フレーム分の音声が集まったときに呼ぶ関数名を指定
実際に色違いかどうかの判定をしているのは、「callback」関数です。
大きく2段階で色違いかどうかの判定をしています。
1.音量が一定レベル以上かどうか
ndarray = np.frombuffer(in_data, dtype='int16')
abs_array = np.abs(ndarray)/32768
#print(abs_array.max())
#音量が一定レベル以上の場合
if abs_array.max() > 0.04:
295~299行目あたりで、音量が一定レベル以上か判定しています。
取得したフレーム内の音声の音量レベルを正規化した後、最大値が一定レベル(0.04)より大きいかどうか判定しています。
この値(0.04)を変えることで、精度を上げることができるかもしれません。
(print(abs_array.max())のコメントを外せば、音量レベルが確認できます)
2.事前に設定した周波数と一致するか
事前に設定した周波数と一致するかは、「detectDualToneInOctave」関数内で確認しています。
val = int(freq_in) - int(freq_high_base)
print('比較結果:',val)
if int(val) == 0:
return True
else:
return False
342~347行目あたりで、比較しています。
比較したい周波数と今回検知した周波数を、整数化して一致するか確認しています。
厳密にやるのであれば整数化せずに比較した方が良いかもしれません。
その他、精度を上げる方法
本プログラムでは振幅最大の周波数1つしか取得していません。
そのため、色違いが発生したフレームで別の振幅最大の周波数が発生すると、正しく検知できないという問題があります。
フレーム内で振幅の大きい周波数を複数取得するように変更することで、この問題を解消できるかもしれません。(誤検知を招く可能性もあります)
プログラム置き場に格納しているもう一つのプログラム「ArcuesTreeShinyv0_9.py」では、振幅の大きい周波数を10個取得して、比較したい周波数と一致するか確認しています。
場合によってはこちらのやり方の方が良いかもしれません。
よろしければ、参考にしてください。