ますたーです。こんにちは。
今回は、「ダイマックスアドベンチャー」を自動周回し、完全放置で「マックスこうせき」を集めるArduino Leonardo自動化の記事です。
さらに、ソースコードの簡単な解説も紹介しますので、これを読むとArduino Leonardoを使った自動化ツール(ちょっとしたマクロ対応コントローラーの代わり)を自力で作れるようになるかもしれません。Arduinoを使った剣盾自動化プログラミングに興味のある方の一助になればと思います。
なお、Arduino Leonardo自動化の導入・機材構成については導入記事を参考にしてください。
導入記事:【Arduino自動化01】Arduino開発環境の導入
※本ブログに初めてお越しの方は「本ブログについて」もぜひ、ご覧ください。
2021年5月4日追記:Switch・剣盾を2台お持ちの方であれば、デリバードのレイドバトルを周回することで「マックスこうせき」をより効率的に回収できます。もしよければ、そちらもご参考ください。
⇒【Arduino自動化18】ローカルレイド自動配布
2021年9月20日追記:通常のレイドバトル「ひとりで挑戦」を完全放置で自動周回するプログラムも作りました。ぜひとも、合わせてご参考ください。
⇒【Arduino自動化19】ねがいのかたまりで自動レイドバトル周回【完全放置で「けいけんアメ」「ヨロイこうせき」】
2021年10月10日追記:Switch・剣盾を2台お持ちの方に向けて、「完全自動」でデリバードのレイドバトルを周回できるプログラムを開発しました!Arduinoも2台必要ですが、その分パワフルな自動化です。
⇒【Arduino自動化20】Switch2台で「完全」自動!レイドバトル自動周回【デリバード・色違いレイドなど】
概要
本記事では、「ダイマックスアドベンチャー(エンドレスモード)」の自動周回を実装します。
今回の目次です。今回はプログラムの書き方も交えますが、説明はいい、早く寄越せという方はどうぞ。 ⇒ 読み飛ばす
作ったきっかけ
実は、今回の記事で紹介するプログラムの流れ自体は、私が考案したものではありません。Twitterのタイムラインを眺めていたところ、あずき(@Azukiss_poke)氏によるマクロ対応コントローラーを使った自動周回方法のツイート(下記)が流れてきて、これをArduinoで実装するか、と思い至った次第です。要するに「Arduino Leonardoがあればマクロコンの代わりになる」というわけですね(暴論)。
この記事のスタンス
本記事で扱う内容は、「決められたコマンド入力」が分かっているものをArduino Leonardoで動く自動化プログラムを作った、というものです。今までのものと異なり、決められたコマンドがあったので、それをプログラムに書き起こしやすいようにソースコード化しました。
ゆえに、もし本記事を読んでいる皆様のほうで「入力したいキーの順番があらかじめ決まっている」のであれば、それを基にプログラムを自分で書ける雛形としてご利用いただけるかもしれません(他のサイトで紹介されているマクロコントローラーの自動化コマンドなど)。
今回は、あずき氏が下記ブログで紹介している「ダイマックスアドベンチャーエンドレスモードの自動周回方法」をArduino Leonardoで使えるプログラムに書き起こしていきます。出来上がったプログラムは後述します。 ⇒ソースコード
azukiss.hatenablog.com
自動周回のコマンド入力列(引用)
1 |
2 |
3 |
4 |
5 |
6 |
間 |
7 |
8 |
↓ |
A |
A |
A |
A |
A |
4s |
↓ |
A |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
間 |
16 |
↓ |
A |
A |
↓ |
A |
A |
B |
3s |
B(1.5s) |
※指定が無い部分のキー入力間隔は約2秒
上表はこのブログから引用したコマンド入力列ですが、要するに、この16コマンドをひたすら繰り返すことで、ダイマックスアドベンチャー(エンドレスモード)を延々と攻略してくれるということです。
なので、早速、これらのコマンド入力部分のみをプログラムにしてみます。
こちらは説明用に抜粋したプログラムの一部です。完成版プログラムは こちら からどうぞ。
#define HOLDTIME (95)
void loop() {
PushKey("down", HOLDTIME, 2000);
PushKey("A", HOLDTIME, 2000);
PushKey("A", HOLDTIME, 2000);
PushKey("A", HOLDTIME, 2000);
PushKey("A", HOLDTIME, 2000);
PushKey("A", HOLDTIME, 4000);
PushKey("down", HOLDTIME, 2000);
PushKey("A", HOLDTIME, 2000);
PushKey("down", HOLDTIME, 2000);
PushKey("A", HOLDTIME, 2000);
PushKey("A", HOLDTIME, 2000);
PushKey("down", HOLDTIME, 2000);
PushKey("A", HOLDTIME, 2000);
PushKey("A", HOLDTIME, 2000);
PushKey("B", HOLDTIME, 3000);
PushKey("B", 1500 , 2000);
}
このように、「void loop(){」と、これに対応する閉じカッコ「}」の間に、延々と繰り返す入力内容を挟むだけでArduinoのソースコードは完成します。
なお、今回のプログラムではキー入力を「PushKey();」という関数で実装します。細かいプログラムの仕様の話などをしてもしょうがないので割愛しますが、よくわからない人は「どのキーが何秒間押されて、その後何秒間やすむのか」をひたすら並べるとプログラムになる、とだけご理解いただければOKです。
今回は、ひたすら「押す」⇒「待つ」を16コマンド分繰り返すだけなので、プログラムの書き換える部分も16行で済みます。簡単ですね。
なお、書き換える部分ですが、1コマンドごとに「PushKey」を並べるだけです。
PushKey("A", HOLDTIME, 2000);
上記「PushKey("A", HOLDTIME, 2000);」の中で、「"A"」と書いている部分=どのキーを押すか、その次=何秒間押し続けるか、最後=キーを離した後に何秒間待つかをそれぞれ表しています。なお、「HOLDTIME」は95に設定しているので「95ミリ秒(=0.095秒)長押し」、すなわち普通にAボタンをポチッと押した後に2秒間待つ、というコマンドになっています。
この要領でプログラムを完成させていきます。全文は後述します。⇒ソースコード
プログラムの使い方(準備)
基本的にあずき氏のブログ記事に載っている通りですが、軽くこちらでも掲載します。
まず、Switchの本体を「機内モード」にします。そして、どうぐの「ボール」欄の一番上には「いらないボールを大量に準備」してください。あとは、ダイマックスアドベンチャー(エンドレスモード)を取り仕切るおっさんの目の前に立ったらArduinoを差し込むだけです。
なお、挑戦の前後には強制的にレポートが書かれてしまうので、貴重なボールが消費されてしまうなどのリスクがあることを理解した上で、使用しましょう。
今回のプログラムはかなりシンプルです。また、読者の皆様が流用して1から使いやすいように、今までの記事よりもきれいめに作っています。
今回のソースコードを全文コピペして、loop()の中身のコマンドを好みのものに変更することで、皆様好みのマクロコントローラーとしても使うことができると思います。興味があればチャレンジしてみてください。
2020/12/13追記:スティック入力にも対応したプログラムを作りました。合わせてご参考いただけます⇒【Arduino自動化07】トーナメント自動周回【マクロコン代替】
#include <SwitchControlLibrary.h>
#define HOLDTIME (95)
void PushRL(int delay_time_ms);
int PushKey(char* keyname, int holdtime, int delaytime);
void setup() {
for(int i=0;i<7;i++)PushRL(300);
delay(1000);
}
void loop() {
PushKey("down", HOLDTIME, 2000);
PushKey("A", HOLDTIME, 2000);
PushKey("A", HOLDTIME, 2000);
PushKey("A", HOLDTIME, 2000);
PushKey("A", HOLDTIME, 2000);
PushKey("A", HOLDTIME, 4000);
PushKey("down", HOLDTIME, 2000);
PushKey("A", HOLDTIME, 2000);
PushKey("down", HOLDTIME, 2000);
PushKey("A", HOLDTIME, 2000);
PushKey("A", HOLDTIME, 2000);
PushKey("down", HOLDTIME, 2000);
PushKey("A", HOLDTIME, 2000);
PushKey("A", HOLDTIME, 2000);
PushKey("B", HOLDTIME, 3000);
PushKey("B", 1500 , 2000);
}
void PushRL(int delay_time_ms){
SwitchControlLibrary().PressButtonR();
SwitchControlLibrary().PressButtonL();
delay(HOLDTIME);
SwitchControlLibrary().ReleaseButtonR();
SwitchControlLibrary().ReleaseButtonL();
delay(delay_time_ms);
return;
}
int PushKey(char* keyname, int holdtime, int delaytime){
if(strlen(keyname)==1){
switch(keyname[0]){
case 'A': case 'a':
SwitchControlLibrary().PressButtonA(); delay(holdtime);
SwitchControlLibrary().ReleaseButtonA(); delay(delaytime);
break;
case 'B': case 'b':
SwitchControlLibrary().PressButtonB(); delay(holdtime);
SwitchControlLibrary().ReleaseButtonB(); delay(delaytime);
break;
case 'X': case 'x':
SwitchControlLibrary().PressButtonX(); delay(holdtime);
SwitchControlLibrary().ReleaseButtonX(); delay(delaytime);
break;
case 'Y': case 'y':
SwitchControlLibrary().PressButtonY(); delay(holdtime);
SwitchControlLibrary().ReleaseButtonY(); delay(delaytime);
break;
case 'L': case 'l':
SwitchControlLibrary().PressButtonL(); delay(holdtime);
SwitchControlLibrary().ReleaseButtonL(); delay(delaytime);
break;
case 'R': case 'r':
SwitchControlLibrary().PressButtonR(); delay(holdtime);
SwitchControlLibrary().ReleaseButtonR(); delay(delaytime);
break;
case 'H': case 'h':
SwitchControlLibrary().PressButtonHome(); delay(holdtime);
SwitchControlLibrary().ReleaseButtonHome(); delay(delaytime);
break;
case '+': case 'p': case 'P':
SwitchControlLibrary().PressButtonPlus(); delay(holdtime);
SwitchControlLibrary().ReleaseButtonPlus(); delay(delaytime);
break;
case '-': case 'm': case 'M':
SwitchControlLibrary().PressButtonMinus(); delay(holdtime);
SwitchControlLibrary().ReleaseButtonMinus(); delay(delaytime);
break;
default:
break;
}
}else if(strlen(keyname)>=2){
switch(keyname[0]){
case 'z': case 'Z':
if(keyname[1]=='R'||keyname[1]=='r'){
SwitchControlLibrary().PressButtonZR(); delay(holdtime);
SwitchControlLibrary().ReleaseButtonZR(); delay(delaytime);
}
if(keyname[1]=='L'||keyname[1]=='l'){
SwitchControlLibrary().PressButtonZL(); delay(holdtime);
SwitchControlLibrary().ReleaseButtonZL(); delay(delaytime);
}
break;
case 'r': case 'R':
SwitchControlLibrary().MoveHat(2); delay(holdtime);
SwitchControlLibrary().MoveHat(8); delay(delaytime);
break;
case 'l': case 'L':
SwitchControlLibrary().MoveHat(6); delay(holdtime);
SwitchControlLibrary().MoveHat(8); delay(delaytime);
break;
case 'u': case 'U':
SwitchControlLibrary().MoveHat(0); delay(holdtime);
SwitchControlLibrary().MoveHat(8); delay(delaytime);
break;
case 'd': case 'D':
SwitchControlLibrary().MoveHat(4); delay(holdtime);
SwitchControlLibrary().MoveHat(8); delay(delaytime);
break;
case 'H': case 'h':
SwitchControlLibrary().PressButtonHome(); delay(holdtime);
SwitchControlLibrary().ReleaseButtonHome(); delay(delaytime);
default:
break;
}
}else{
return -1;
}
strlen(keyname);
}
あとがき
今回は、マクロコントローラーで自動化されていたものをArduino Leonardoで置き換えたらどのように実装されるかにフォーカスして紹介しました。
自明かとは思いますが、Arduinoによるポケモン剣盾自動化プログラムはとどのつまりマクロ対応コントローラーによるコマンド入力自動化と実質なんら変わりありません。むしろ、キー入力配列の上限にかなり余裕があり、柔軟な入力制御にも対応できる分だけArduinoはマクロ対応コントローラーよりも高機能とも言えるかもしれませんね。
要するに、マクロ対応コントローラーにせよArduinoにせよ、人が入力しているコマンドをプログラムに置き換える手段ですので、自分の工夫次第でいかようにでも動かすことができるのがプログラミングの醍醐味だと思います。
今までプログラミングをしてこなかった方も、もしこの記事を読んで「自動化にチャレンジしてみたい」と少しでも思えたのであれば幸いです。また、今までマクロ対応コントローラーを利用してきた方のうち、「マクロの中にHomeボタンが割り当てられない」という経験をされた方には、ぜひともArduinoでの自動化にもチャレンジしてみて欲しいと思います。
皆様のポケモン自動化ライフがより豊かになることを祈っています。
ではではc⌒っ.ω.)っ
2020/12/13追記:スティック入力にも対応したプログラムを作りました。
是非合わせて御覧ください⇒ 【Arduino自動化07】トーナメント自動周回【マクロコン代替】
前記事:
【Arduino自動化05】乱数調整レイドで色違いパッチルドン探し【冠の雪原】
導入記事:
【Arduino自動化01】Arduino開発環境の導入