※本記事は、ポケモン剣盾の預かり屋での孵化厳選を自動化するプログラムについて解説した記事です。ポケモン剣盾の操作をArduino Leonardoで自動化しております。「Arduinoって何?」って方は00回目の記事を、Arduinoの環境構築(ライブラリ含む)は01回目の記事をご覧ください。
このプログラムは、使用しているライブラリ(01回目の記事)に含まれるサンプルプログラムをベースとして、孵化効率を高めるために改良したプログラムです。大半はサンプルと同様となります。
2021/11/27追記: sleepNowが機能していなかったので修正したVer.2.01を公開しました。
本記事では、このプログラム(スケッチ)でできることや原理を解説したうえで、スケッチを配布しています。とにかくスケッチが欲しいという方は下へと読み飛ばしてください。
きっかけ、動機
ポケモン剣盾で自動化させたい動作として、真っ先に思い浮かぶものの1つは孵化厳選ではないでしょうか。バトル用の個体値厳選、色違い厳選どちらにおいても最もメジャーな厳選方法、そして時間のかかる作業。執筆者が自動化を行おうと思った最初の作業となります。
...そんなメジャーな自動化なので、本ブログの第3回くらいでこの記事を書いたつもりでいました。忘れていたので今更の投稿となります。
孵化厳選のプログラムは、使用しているライブラリ(01回目の記事)に含まれるサンプルプログラムの中にも入っています。ただし、サンプルのままでは孵化効率が低いので、それを高めることを目的としています。
これで何ができるの?
主な動作はサンプルプログラムと同様です。ただし、新しいタマゴを貰う→1個ずつ孵化、ではなく、貰い続ける→5個ずつまとめて孵化、とすることで時間短縮をしました。また、プログラムにてタマゴを入れるBOX数を指定するため、思いがけずBOXがあふれる事態を防ぐようにしました。
原理、おおまかな流れ
概要
主な動作はサンプルプログラムと同様に、ワイルドエリア内、ハシノマはらっぱの預かり屋からタマゴを受け取り、それを孵化させます。ただし、サンプルのままでは効率が低く、手動でやる場合の何倍もの時間がかかっていたので、より早く孵化させるための効率化を行いました。
サンプルプログラムの問題点
サンプルプログラム「auto_hatching」は、ライブラリを導入した後であればスケッチ例から開くことができます。
このプログラムでは、
タマゴを1個貰う→1個を孵化させる→貰う、孵化...→5個孵化させたらBOXへ入れる→ループ...
のように繰り返します。
このような動作について、以下の問題点が挙げられます。
・手動であればタマゴ5個をまとめて孵化させるのに対して、プログラムでは1個ずつ孵化させるため、5倍近い時間がかかる。
・動作が永遠にループするため、長時間放置するとBOXを埋め尽くすまで孵化を繰り返す。意図していないBOXまで孵化個体で埋め尽くされ、整理が大変になる。
問題点に対する、本プログラムでの改良点
以上の2つの問題点に対して、本プログラムでは以下のように改良しています。
・1個ずつ孵化させるため、5倍近い時間がかかる
>手動に近い効率とするため、1度に5個のタマゴを手持ちに加えて走り、5個ずつまとめて孵化させます。ただし、孵化させながらタマゴを受け取ろうとすると、生まれる演出により操作にずれが生じるため、タマゴを受け取る動作と孵化させる動作を別々にしました。
はじめにタマゴを指定した個数分受け取ります。
20秒ほど走り回る→タマゴを受け取る
という動作を繰り返します。手持ちにタマゴを入れないために、マイコンを挿す前に手持ちを別のポケモンで埋めます。走り回る時間20秒間で、親が異なり、種族の異なるポケモンの組み合わせ(自己産ポケモン×他人産メタモンなど、まあまあの仲の良さ)であればおおよそタマゴが発見されます。預ける組み合わせ、仲の良さが異なるポケモンである場合は、この時間設定を調整してください。
タマゴを指定個数まで受け取った後は、BOXに敷き詰められたタマゴを5個ずつ孵化させます。
という動作を繰り返します。初期設定では、ドラメシヤ等の孵化までに時間がかかるポケモンまで、すべてのポケモンが孵化する時間を孵化させる時間として設定しております。コイキングのような、孵化時間の短いポケモンである場合は、余計に走り続けることとなるので調整してください(執筆者は面倒なので調整していません)。
・長時間放置するとBOXを埋め尽くすまで孵化を繰り返す
寝てる間など、長時間放置する状況でも埋め尽くさないように、孵化させるBOX数(=孵化させる個体数30匹単位)を指定できるようにしました。これにより、指定数の孵化が終了した場合に自動で停止します。初期設定では5BOXとなっているので、1-31の範囲であれば好きに設定してください。
準備、必要なもの
本スケッチでは、マイコンを挿す前に以下の準備が必要となります。
・ハシノマはらっぱにて、自転車に乗った状態にする。
・ハシノマはらっぱの預かり屋にタマゴが見つかる組み合わせで預ける。本スケッチは自己産ポケモン×他人産メタモンを想定しているため、仲の良さがイマイチ(同じ親、異なる種族の組み合わせ)の場合は、タマゴが見つかるまでの時間を要調整。
・手持ちの先頭を「ほのおのからだ」「じょうききかん」などの孵化が早くなる特性をもつポケモンにする。また、2匹目以降をタマゴではないポケモンで埋める。
・タマゴを孵化させるBOXの数だけ、隣り合ったBOXを空にする。また、それらBOXの1つ前(左)のBOXに5匹分以上の空きを作り、手持ちの2-6匹目が入るようにする。最後に、空のBOXの先頭(一番左)を開いた状態からBOXを閉じる
・Xボタンを押して出るメニュー画面のうち、左上を「ポケモン」、左下を「タウンマップ」とする。(異なる場合はプログラム側を要調整)
作成したスケッチ
作成したスケッチはこちら。Ver.2.01
ついでに、タマゴ回収をせず、ボックス内のタマゴの孵化のみ行う場合はこちら
2021/11/27追記: sleepNowが機能していなかったので修正したVer.2.01を公開しました。
本スケッチを実際に使用した動画はこちら↓
* ボックス内タマゴを指定ボックス分孵化
* 始めに指定BOX分だけタマゴを回収してから、まとめて孵化
*
* 初期条件は以下の通り
* 1.ハシノマはらっぱで自転車に乗る
* 2.育て屋(はらっぱ)にあらかじめタマゴができる組み合わせを預ける
* 3.手持ちポケモンの先頭を「炎のからだ」などの特性持ちのポケモン、2-6番目を適当なポケモン(タマゴ以外)にする
* 4.タマゴを孵化させるためのボックス数を、本スケッチの GOAL に指定する。
* 伴って、GOALと等しい数の、連続するBOXを空にし、さらに1つ前のBOXに空きを5匹分以上空ける(手持ち2-6番目が入る予定)
* 5.空にしたBOXの一番上(左)を出した状態でBOXを閉じる
* 6.Xボタンを押したメニュー画面で「ポケモン」が左上、「タウンマップ」が左下にあるように並び替える
*
*/
#include <auto_command_util.h>
#include <avr/sleep.h>
int box_count = 0;
//消費するbox数を入力(×30個のタマゴを孵化)
#define GOAL 5
//卵1個にかかる時間、孵化させるポケモンにより要調整
// 130であれば、ドラメシヤを含むすべてのポケモンに対応
const int TIME_TO_HATCHING_SEC = 130;
// 空飛ぶタクシーでハシノマはらっぱに移動
void moveToInitialPlayerPosition(){
pushButton(Button::X, 1000);
pushHatButtonContinuous(Hat::DOWN_LEFT, 1000);
pushButton(Button::A, 2500);
pushButton(Button::A, 1500, 2);
delay(2000);
}
// 初期位置から育て屋さんに移動し卵を受け取る
void getEggFromBreeder(){
// 初期位置(ハシノマはらっぱ)から育て屋さんのところまで移動、自転車に乗ったまま
tiltJoystick(-30, 100, 0, 0, 300);
tiltJoystick(50, 100, 0, 0, 600);
// 育て屋さんから卵をもらう
pushButton(Button::A, 1000, 4);
pushButton(Button::B, 500, 10);
}
// 初期位置(ハシノマはらっぱ)からぐるぐる走り回る、走りながらAボタンを繰り返し押す
void runAroundWithA(int run_time_sec){
// 野生ポケモンとのエンカウントを避けるため初期位置から少し移動する
tiltJoystick(100, -50, 0, 0, 2000);
//スティックを固定
SwitchController().setStickTiltRatio(100, 0, -100, 0);
// 1秒間に2回のA連打、指定された秒数だけ
pushButton(Button::A, 400, 2 * run_time_sec);
//スティックを戻す
SwitchController().setStickTiltRatio(0, 0, 0, 0);
delay(100);
}
// 手持ちが満杯の状態から、卵受け取りをボックス*30回、孵化させずボックスへためていく
void recieveEggs(){
for(int egg_num=0; egg_num< 30*GOAL; egg_num++){
moveToInitialPlayerPosition();
getEggFromBreeder();
moveToInitialPlayerPosition();
runAroundWithA(20);
}
}
// メニューを開き、BOXを開く
void openBox(){
// ボックスを開く
pushButton(Button::X, 1000);
pushHatButtonContinuous(Hat::LEFT_UP, 1000);
pushButton(Button::A, 2000);
pushButton(Button::R, 2000);
//範囲選択モードに
pushButton(Button::Y, 300, 2);
}
// openBox後、孵化した手持ちのポケモンを預ける
// box_line : 何列目にポケモンを預けるか
void changeHatchedPoemonInBox(int box_line){
// box_lineが0以外であれば、孵化した手持ちを(line-1)列目に置き、line 列目にカーソル合わせ
if(box_line>0){
// 手持ちの孵化したポケモンを範囲選択
pushHatButton(Hat::LEFT, 300);
pushHatButton(Hat::DOWN, 300);
pushButton(Button::A, 500);
pushHatButtonContinuous(Hat::DOWN, 2000);
pushButton(Button::A, 500);
// ボックスに移動させる
pushHatButton(Hat::RIGHT, 300, box_line);
pushHatButton(Hat::UP, 300);
pushButton(Button::A, 500);
//隣のラインの卵にカーソル
pushHatButton(Hat::RIGHT, 300);
}
//box卵を範囲選択
pushButton(Button::A, 500);
pushHatButton(Hat::DOWN, 300, 4);
pushButton(Button::A, 500);
//手持ちに移動させる
pushHatButton(Hat::LEFT, 300, box_line+1);
pushHatButton(Hat::DOWN, 300);
pushButton(Button::A, 500);
// ボックスを閉じる
pushButton(Button::B, 1500, 4);
}
//手持ちをボックスに詰めて置き、次のボックスへ移る
void temochiOkizari(){
// 手持ちの孵化したポケモンを範囲選択
pushHatButton(Hat::LEFT, 300);
pushHatButton(Hat::DOWN, 300);
pushButton(Button::A, 500);
pushHatButtonContinuous(Hat::DOWN, 2000);
pushButton(Button::A, 500);
//ボックス一覧へ
pushHatButton(Hat::UP, 300, 3);
pushHatButton(Hat::RIGHT, 300);
pushButton(Button::A, 500);
// 端詰でおいていく
pushButton(Button::A, 500);
pushButton(Button::B, 500);
// ボックスを移動
pushButton(Button::R, 2000);
// ボックスを閉じる
pushButton(Button::B, 1500, 4);
}
// 孵化シーケンスを実行
void execHatchingSequence(){
for(int box_line=0; box_line<6; box_line++){
moveToInitialPlayerPosition();
openBox();
changeHatchedPoemonInBox(box_line);
runAroundWithA(TIME_TO_HATCHING_SEC + 100);
}
}
void sleepNow()
{
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_mode();
}
void setup(){
//画面起動
pushButton(Button::B, 500, 13);
//初めのタマゴを出すため走り回る
moveToInitialPlayerPosition();
runAroundWithA(20);
//ひたすら受け取り、孵化はさせない
recieveEggs();
//受け取り終えたら、初期手持ちを1つ前のボックスにおいていく
openBox();
pushButton(Button::L, 1000);
temochiOkizari();
//1度ボックスを閉じる
}
void loop(){
if (box_count >= GOAL) {
sleepNow();
}
else {
//30個孵化、ボックス移動
execHatchingSequence();
openBox();
temochiOkizari();
box_count++;
//boxcount増加
}
}
最後に
本スケッチを使用することで、ある程度効率よく孵化厳選が可能となります。理想個体の厳選、あるいは色違いの厳選にお役立てください。
なお、動画などを見るとわかりますが、所々非効率な箇所がありますので、効率が気になる方は調整してみてください。私の場合は5BOX程度であれば寝ている間に完了しているのであまり気にしていません。プログラムの不備、改善点などありましたらコメントやお問い合わせからお願いいたします。
Arduino Arduino Leonardo (ピンソケット・ピンヘッダ実装済) 【A000057】 | ||||
|
とても良いプログラムをありがとうございます。今はレジギガスを自動で粘っていますが、それが終わったらこのプログラムを使ってゾロアの色違い厳選をしてみようと思います。
返信削除5ボックス程度ゾロアを孵化させてみたら2体も色違いが生まれていました。他にも、このプログラムのおかげでカントー御三家やホウエン御三家等の色違いを手に入れることができました。本当にプログラムの配布ありがとうございます。そして、これからもプログラム作り頑張ってください。
削除void recieveEggs();のなかのrunAroundWithA(20);の括弧の中の数字を25くらいにすると、卵を安定して受け取れたので、報告をしておきます。
返信削除