あけましておめでとうございます。ますたーです。
今回はポケモンSVの「コレクレーのコイン」を自動で回収する記事です(お年玉かな?)。パルデア十景を巡ることで、景観も楽しめます(初日の出かな?)。
ポケモンSV自動化の記事、第3弾となります。
なお、Arduino Leonardo自動化の導入・機材構成については導入記事を参考にしてください。
導入記事:【Arduino自動化01】Arduino開発環境の導入
(または 【2022年12月最新版】ZIP版IDEでのArduino開発環境の構築)
※本ブログに初めてお越しの方は「本ブログについて」もぜひ、ご覧ください。
概要
パルデア十景をめぐり、各地にいるコレクレー(とほフォルム)に話しかけて「コレクレーのコイン」を自動で集めてくれます。パルデア十景を5分52秒で1周し、コレクレーのコインを平均12.86枚を拾い集めることができました*1。単位時間に換算すると、1時間あたりの回収実績が131枚となります*2。約8時間で999枚カンストできる計算になりますね*3。
★★Nintendo Switch2(Ver22.1; 「ゲームカード」の追加対応)で動作確認しました(2026年5月24日 追記)★★
パルデア十景(10箇所のフォトスポット)の看板にいるコレクレーに話しかけてコインを集める
1周あたり5分52秒(日付変更・リセット込)で、拾えたコインは平均12.86枚だった
※警告:本プログラムは動作中に移動とセーブを行うため、決して目を離さず、利用は「自己責任」でお願いします。特に、貴重な道具やボール・アイテムを利用したり、ポケモンを逃したりする可能性があります*4
もくじです。いつも通り検証を含みます。
(個人的には2-4節と3章がおもしろいと思います←)
1.コレクレーは「コレクレーのコイン」999枚を使ってサーフゴーに進化する
サーフゴーというポケモンをご存知でしょうか。コレクレーから進化する、金ピカボディが印象的なポケモンです。見た目の通り、「おうごんのからだ」というとくせいを持っています*5。はがね・ゴーストという恵まれたタイプ*6に加え、合計種族値が550、とくこうの種族値も133と高く、2022年12月現在の対戦環境において猛威を振るっている、紛れもない強ポケです。
この、サーフゴーの入手方法ですが、バッグに「コレクレーのコイン」を999枚持った状態でレベルアップさせることで進化させることができます。

「コレクレーのコイン」999枚を所持した状態でレベルを上げるとサーフゴーに進化するぞ
(ちなみに進化させるとコレクレーのコインは使い切ってしまう。また集め直そう!)
2.コレクレーのコインは、パルデア地方各地にいるコレクレーからドロップする
さて、サーフゴーへの進化のためには「コレクレーのコイン」999枚が必要ですが、進化させると「コレクレーのコイン」999枚は1枚残らず使い切ってしまいます。
肝心の「コレクレーのコイン」の集め方ですが、パルデア各地にいるコレクレーに話しかけることでドロップ入手できます。このとき、話しかけるコレクレーのフォルムによって「入手できる枚数」に違いがあるため、それぞれについて紹介します。
2-1.看板の影などにいる「とほフォルム」のコレクレーから1~10枚ドロップ
パルデア地方の各地にある看板の裏や上、影などには「とほフォルム」のコレクレーがいることがあります。話しかけると「!」マークが出てすぐさま逃げてしまいますが、その際にランダムにコレクレーのコインを落としていきます。
ドロップする「コレクレーのコイン」の枚数はまちまちですが、ほとんどの場合1枚・3枚・5枚・10枚のいずれかになります。低確率ながら、「30枚」「50枚」「100枚」のコインがドロップすることもあります*7。新年の運試しにピッタリですね。
とほフォルムのコレクレーが近くにいる場合、鳴き声がするので簡単に気づけると思います。

パルデア各地の看板や屋根の上などにコレクレー(とほフォルム)がいる。
話しかけるとすぐに逃げ出すが、コレクレーのコインを1~10枚ほどドロップする。
運が良ければ「30枚」「50枚」「100枚」のコインがもらえることもある。当たればラッキー!
(筆者は6時間かけて195匹のコレクレーと出会って「30枚」は2回、「50枚」は1回だけだった)
2-2.物見塔などにいる「はこフォルム」のコレクレーから30~80枚ドロップ
パルデア地方には、各地に物見塔や遺跡などがあり、そこに「宝箱」のような見た目のポケモンがいることがあります。その宝箱にAで話しかけることで戦闘になり、はこフォルムのコレクレーと戦うことができます。はこフォルムのコレクレーを倒すと、30枚~80枚ほどの「コレクレーのコイン」をドロップ入手することができます。
ちなみに、はこフォルムのコレクレーは捕獲することもできますので、育成用の個体厳選がてら、各地の物見塔を捕まえて回るのも良いかもしれませんね。

パルデア各地にある物見塔などに、コレクレー(はこフォルム)がいる。
倒すか捕まえれば30~80枚ほどのコレクレーのコインがドロップするぞ
2-3.とほフォルムのコレクレーは日付変更+セーブリセットで、確率で復活(リポップ)する
ところで、看板の上や影に隠れている「とほフォルム」のコレクレーは、みなさまもご存知の通り、いつの間にか復活していることがあります。
復活(リポップ)の条件ですが、日付変更をすることで、時々復活することが確認できたため、(おそらく)Switchの日付で24時の経過後に抽選判定が行われると考えられます。なお、日付変更後は、そらとぶタクシーで別マップに移動するなどで、マップの更新をしないと、復活しているかどうかの確認ができませんので注意しましょう。
ちなみに、「はこフォルム」のコレクレーの復活条件は、筆者検証では分かりませんでした。日付変更の度に5%の確率でリポップしているなどの報告もありますが、筆者未検証情報になります。

セーブ&ゲーム終了、日付変更して再起動すると、時々コレクレーが復活する
ただし、そらとぶタクシーなどで一度、画面を再読込しないと出現しないから注意が必要だ!
2-4.日付変更時、コレクレー(とほフォルム)はパルデア中で44.7%の確率で同時に復活している
肝心のリポップ確率について、5時間かけて検証(「セーブ&リセット&日付変更」と「パルデア十景を巡って看板を調べる作業」を47回=延べ376箇所の看板の確認を行いました)を行いました。具体的には、これらの試行でパルデア十景*8の看板をすべて見て回ることで、コレクレーがどのように復活するのかを確認・検証しました。結果、非常に興味深いことがわかりました。
【コレクレーの復活確率(筆者調べ。日付変更の度に8箇所の看板を確認。全47試行)】
- 44.7%の割合で、コレクレーが8箇所すべてで復活した
- 8.5%の割合で、コレクレーが8箇所のうち一部のみで復活した
- 46.8%の割合で、どこのコレクレーも8箇所すべてで復活しなかった
検証の結果、とほフォルムのコレクレーの復活(リポップ)の確率は53.2%でした。
さらに、日付変更の度に8箇所を巡ったことで、その復活が「一部だけ」なのか「全体」なのかに分かれることも発見し、「とほフォルムのコレクレーが、全体で同時に復活する確率が44.7%」という内訳を発見しました。わかりやすく円グラフにしたものを下図に掲載します。

コレクレー(とほフォルム)のコインのドロップ数と、リポップ(復活)の確率を調べた。
ドロップはほとんど1~5枚の範囲内で、10枚以上はラッキーだ。2日に1回のペースで復活するらしい。
ここで、コレクレーがすべての場所で一斉に復活するのではなく、仮に各スポットで5割のリポップ率で設定されていると仮定すると、8箇所が同時に復活する確率・8箇所が同時に復活しない確率というのは非常に小さく、偶然発生するとは考えにくいと言えます(統計学で「符号検定」と言われる考え方です)。
※参考式 P = (1/2)^8 ×2 = 0.0078125 < 0.01
このように、各スポットごとに50%のリポップ率が設定されているとは(統計学的には危険率1%で)考えにくい検証結果が得られており、このことからも、少なくとも「パルデア十景」の看板8箇所では「同時に復活している」と考えるのが妥当だといえます。
3.コレクレーのコイン集めにはパルデア十景巡りが最適解
さて、「コレクレーのコイン」について、上記の検証結果をまとめます。
- 看板の裏や上にいる「とほフォルム」のコレクレーから回収することができる
- とほフォルムのコレクレーは、日付変更&セーブリセットで、確率で復活する
- 復活していても、そらとぶタクシーなどで画面を更新しないと出現が確認できない
- 約4割の確率で、パルデア各地で復活している
これらを踏まえると、「日付変更」と「そらとぶタクシー」での移動はセットにしつつ、1度のセーブリセット試行の中で、複数拠点を巡ってコレクレーの有無を確認することが最適な動きであると結論付けられます。
そらとぶタクシーを利用する所以で、コレクレーの出現場所へのアクセスが容易な箇所を検討する必要がありますが、これは、「パルデア十景」が最適です。理由は明白で、そらとぶタクシーの行き先が、看板の眼の前に設定されているためです。
これらを踏まえ、パルデア十景の10箇所の看板を調べるための最適な動きを地図にしてみましたので下図に示します。

「コレクレーのコイン」集めに最適な、パルデア十景 コイン周回ツアーMAPを作ってみた。
1週あたりわずか6分足らずで、平均(期待値)で12.86枚ものコインを入手できるぞ
そらとぶタクシーでのカーソル移動ができるだけ最短になるようにパルデア十景の各スポットをつなぎ合わせることで、最小の時間で最大効率での「コレクレーのコイン」の回収を実現できるように設計しています。この経路での周回を行うことで、1周を6分弱に抑えつつ12.86枚ものコイン回収を期待することができるようになりました。
1時間あたり131枚*9ものコインを集めることができます。すなわち、わずか8時間足らずで999枚のコインを集めることができるという時間効率と言えます。

パルデア十景の看板を巡り、セーブして日付変更&リセットを繰り返せばOKだ。
1周あたり5分50秒で、平均12.86枚のコインを入手できるぞ
4.コレクレーのコイン集めの自動化
さて、ここからはArduino Leonardoでのコレクレーのコイン集めの自動化について紹介します。
前述の通り、パルデア十景をひたすら周回して日付変更を行うことが「最適」な戦略であると結論付けましたので、今回紹介するプログラムも、それに倣ったアルゴリズムを採用します。すなわち、パルデア十景を順番にそらとぶタクシーで移動する、という方法です。
ひそやかビーチ→オリーブ大農園→列柱洞→ありがた岩→オージャの大滝→ナッペの手→パルデア最高峰→みだれつきの滝→100万ボルトの夜景→…(以下ループ)で時計回りにぐるぐると10箇所を巡り、セーブして日付変更を繰り返します。
4-1.自動化準備:ひそやかビーチに空を飛んで、東を向いてセーブしよう
今回の自動化では、パルデア十景を巡るのですが、デフォルトでは「ひそやかビーチ」を始点に選びました。好戦的な野生ポケモンが少なく不意に突進されることが少ないと感じたからです。
Yボタンの「そらとぶタクシー」でひそやかビーチに降り立ったら、デフォルトでカメラは東向き・主人公は西向き(こっちを向いている状態)になっていると思います。上方向にちょいっと入力を行って、主人公も東を向けた状態(背を向けた状態)にしてください。セーブも推奨です。

そらとぶタクシーで「ひそやかビーチ」に降り立ったら、主人公の向きを東(上)に向けてセーブだ
ちなみに、プログラム上はパルデア十景のどこからでも始めることができるように設計しています。
具体的には、ソースコードの「STARTPOINT」を0~9の任意の数字に書き換えることで、パルデア十景の中から好きな地点を開始位置に変更することができます(もっとも、恩恵はほぼないと思うので、6のままでよいかと思いますが)。
const int STARTPOINT = 6;
4-2.自動化準備:Switch本体は「自動で日付を設定しない」状態にしておこう
本プログラムでは、日付変更を行うため、「インターネットで時間をあわせる」機能はOFFにしておきます。

Switchの本体設定から「インターネットで時間をあわせる」はOFFにしておこう
4-3.ソースコード
予めパルデア十景には訪問しておいて、そらとぶタクシーの行き先に加えておいてください。「ひそやかビーチ」に空を飛んだら、必ず主人公の向きを看板の方向に向けてからセーブ(←大事)してください。
その状態でArduino Leonardoを差し込むだけで、あとは自動でパルデア十景を巡って看板のコレクレーからコインを回収し、ひそやかビーチまで戻ってきます。その後セーブして日付変更&リセットを繰り返します。
※1試行5分以上でセーブを挟むという特性上、くれぐれも目を離さずにご利用ください。意図しない挙動(野生ポケモンに突進される、そらとぶタクシーのカーソルが吸われるなど)が発生した場合、動作がズレて貴重なアイテムなどを消費してセーブしてしまう可能性などがあります。不審な挙動が発生した際は、Arduinoを抜いてください(筆者は8時間放置で、野生ポケモンに突進されてもセーブ位置から再開してちゃんとループ再開しましたが、保証はできません)。ご利用に際して発生した不具合等には責任は取れません。
★(2026年5月24日 追記ここから)★
★「Switch2」で動作確認(ソースコード修正)しました(2026/5/24追記)
Nintendo Switch2で動作確認を行いましたので、そのバージョンのソースコードです。
特に、「日付変更」の部分において、Switchバージョン22で追加された「ゲームカード」機能による、「Switch設定」までの移動数の変更にも対応しました。
また、ビシャビシャの斜塔→列柱洞のマップ移動のカーソル移動時間が、従来よりも短くなったため、カーソルが外れてしまう事象が発生しておりましたので、これを修正しております。
#include <SwitchControlLibrary.h>
#define HOLDTIME (95)
#define SWITCH_VER (22)
#define A_TIME (75)
#define B_TIME (3)
int PushKey(char* keyname, int holdtime, int delaytime);
void TiltLeftStick(int direction_deg, double power, int holdtime, int delaytime);
void Hit_Button_repeatedly(char *keyname, unsigned long int while_sec);
void Save_for_SV(void);
void GameStart_for_SV(void);
void GameQuit_for_SV(void);
void NextDay_in_HomeMenu(void);
void JumpTo(double deg, double sec, int expand_level = 0);
void Dash_for_Gimmighoul(double deg, double sec, bool need_reset_cam = false);
void setup() {
for(int i=0;i<7;i++)PushKey("UP", HOLDTIME, 300);
PushKey("B", HOLDTIME, 300);
delay(1000);
}
struct{
int dash_deg;
double dash_sec;
bool dash_ZL;
int jump_deg;
double jump_sec;
int jump_zoom;
}command_list[] = {
{ 90, 0.50, true,
105, 3.40, 1},
{315, 0.72, false,
118, 0.95, 1},
{290, 0.71, true,
101, 2.48, 1},
{340, 0.88 , false,
101, 3.23, 1},
{ 34, 0.80, false,
189, 2.80, 1},
{ 25, 0.68, false,
191, 4.74, 1},
{ 0, 0.80, false,
292, 5.86, 1},
{287, 0.79, true,
238, 2.80, 1},
{ 58, 1.24, false,
0, 5.45, 1},
{350, 1.00, false,
351, 3.80, 1},
};
void loop() {
const int STARTPOINT = 6;
for(int i=0; i< 10 ; i++){
int j = (i+STARTPOINT)%10;
Dash_for_Gimmighoul(command_list[j].dash_deg, command_list[j].dash_sec, command_list[j].dash_ZL);
JumpTo( command_list[j].jump_deg, command_list[j].jump_sec, command_list[j].jump_zoom);
}
TiltLeftStick(0, 0.5, 150, 550);
Save_for_SV();
GameQuit_for_SV();
NextDay_in_HomeMenu();
GameStart_for_SV();
}
void Dash_for_Gimmighoul(double deg, double sec, bool need_reset_cam = false){
if(need_reset_cam){
PushKey("L", HOLDTIME, 800);
}
TiltLeftStick(deg, 1.0, (int)((double)sec*1000UL), 300);
Hit_Button_repeatedly("A", 3);
delay(500);
return;
}
void JumpTo(double deg, double sec, int expand_level = 0){
PushKey("Y", HOLDTIME, 2500);
switch(expand_level){
case -1:
PushKey("ZL", HOLDTIME, 1700);
break;
case 1:
PushKey("ZR", HOLDTIME, 1700);
break;
case 0:
default:
break;
}
TiltLeftStick(deg, 1.0, (int)((double)sec*1000UL), 300);
while(expand_level >= 0){
PushKey("ZL", HOLDTIME, 1700);
expand_level--;
}
Hit_Button_repeatedly("A", 6);
delay(5000);
return;
}
void Save_for_SV(void){
PushKey("X", HOLDTIME, 1200);
PushKey("R", HOLDTIME, 1000);
PushKey("A", HOLDTIME, 3200);
PushKey("B", HOLDTIME, 1200);
PushKey("B", HOLDTIME, 1500);
return;
}
void NextDay_in_HomeMenu(void){
PushKey("down", HOLDTIME, 105);
PushKey("right", HOLDTIME, 105);
PushKey("right", HOLDTIME, 105);
PushKey("right", HOLDTIME, 105);
PushKey("right", HOLDTIME, 105);
PushKey("right", HOLDTIME, 105);
#if (SWITCH_VER >= 22)
PushKey("right", HOLDTIME, 105);
PushKey("right", HOLDTIME, 105);
PushKey("right", HOLDTIME, 105);
#elif (SWITCH_VER >= 20)
PushKey("right", HOLDTIME, 105);
PushKey("right", HOLDTIME, 105);
#endif
PushKey("A", HOLDTIME, 1500);
PushKey("down", 1500, 105);
PushKey("right", HOLDTIME, 105);
#if (SWITCH_VER >= 22)
for(int i=0; i<7; i++){
PushKey("down", (int)HOLDTIME/2, (int)105);
}
#elif (SWITCH_VER >= 15)
PushKey("down", 750, 105);
#elif (SWITCH_VER >= 13)
PushKey("down", 780, 105);
#else
for(int i=0; i<4; i++){
PushKey("down", (int)HOLDTIME/2, (int)105);
}
#endif
PushKey("A", HOLDTIME, 500);
PushKey("down", HOLDTIME, 105);
PushKey("down", HOLDTIME, 105);
PushKey("A", HOLDTIME, 500);
PushKey("right", HOLDTIME, 105);
PushKey("right", HOLDTIME, 105);
PushKey("up", HOLDTIME, 105);
PushKey("A", HOLDTIME, 105);
PushKey("A", HOLDTIME, 105);
PushKey("A", HOLDTIME, 105);
PushKey("A", HOLDTIME, 105);
PushKey("Home", HOLDTIME, 2000);
return;
}
void GameStart_for_SV(void){
PushKey("A", HOLDTIME, 1500);
PushKey("A", HOLDTIME, 24000);
PushKey("A", HOLDTIME, 23500);
return;
}
void GameQuit_for_SV(void){
PushKey("Home", HOLDTIME, 1200);
PushKey("X", HOLDTIME, 500);
PushKey("A", HOLDTIME, 4000);
return;
}
void Hit_Button_repeatedly(char *keyname, unsigned long int while_sec){
unsigned long int current_time=0;
unsigned long int start_time=0;
unsigned long int temp_time=0;
if( while_sec > 2147483){
Hit_Button_repeatedly(keyname, while_sec - 2147483);
while_sec = 2147483;
}
for( start_time=millis(), current_time=start_time ; current_time - start_time < (unsigned long)while_sec*1000UL ; current_time=millis() ){
if( current_time - start_time < (unsigned long)while_sec*1000UL )PushKey(keyname, HOLDTIME, 300);
}
return;
}
int PushKey(char* keyname, int holdtime, int delaytime){
if(strlen(keyname)==1){
switch(keyname[0]){
case 'A': case 'a':
SwitchControlLibrary().PressButtonA(); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonA(); delay(delaytime);
break;
case 'B': case 'b':
SwitchControlLibrary().PressButtonB(); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonB(); delay(delaytime);
break;
case 'X': case 'x':
SwitchControlLibrary().PressButtonX(); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonX(); delay(delaytime);
break;
case 'Y': case 'y':
SwitchControlLibrary().PressButtonY(); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonY(); delay(delaytime);
break;
case 'L': case 'l':
SwitchControlLibrary().PressButtonL(); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonL(); delay(delaytime);
break;
case 'R': case 'r':
SwitchControlLibrary().PressButtonR(); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonR(); delay(delaytime);
break;
case 'H': case 'h':
SwitchControlLibrary().PressButtonHome(); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonHome(); delay(delaytime);
break;
case '+': case 'p': case 'P':
SwitchControlLibrary().PressButtonPlus(); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonPlus(); delay(delaytime);
break;
case '-': case 'm': case 'M':
SwitchControlLibrary().PressButtonMinus(); delay(holdtime);
if(holdtime>0)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);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonZR(); delay(delaytime);
}
if(keyname[1]=='L'||keyname[1]=='l'){
SwitchControlLibrary().PressButtonZL(); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonZL(); delay(delaytime);
}
break;
case 'r': case 'R':
SwitchControlLibrary().MoveHat(2); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().MoveHat(8); delay(delaytime);
break;
case 'l': case 'L':
SwitchControlLibrary().MoveHat(6); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().MoveHat(8); delay(delaytime);
break;
case 'u': case 'U':
SwitchControlLibrary().MoveHat(0); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().MoveHat(8); delay(delaytime);
break;
case 'd': case 'D':
SwitchControlLibrary().MoveHat(4); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().MoveHat(8); delay(delaytime);
break;
case 'H': case 'h':
SwitchControlLibrary().PressButtonHome(); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonHome(); delay(delaytime);
default:
break;
}
}else{
return -1;
}
return strlen(keyname);
}
void TiltLeftStick(int direction_deg, double power, int holdtime, int delaytime){
double rad = (double)direction_deg*PI/180.0;
int x, y;
x = (double)128*sin(rad)*power;
y = (double)-128*cos(rad)*power;
x += 128; y += 128;
if(x >= 255) x=255; if(x <= 0) x=0;
if(y >= 255) y=255; if(y <= 0) y=0;
SwitchControlLibrary().MoveLeftStick(x,y);
if(holdtime> 0){
delay(holdtime);
SwitchControlLibrary().MoveLeftStick(128,128);
}
if(delaytime>0) delay(delaytime);
return;
}
★(2026年5月24日 追記ここまで)★
★以下、2025年5月2日時点のソースコードです。念のため残しておきます。
こちらは古いソースコードです。原則、上記のソースコードを使ってください。
NintendoSwitch Ver.20.0アップデート対応済です(2025年5月2日追記)。
#include <SwitchControlLibrary.h>
#define HOLDTIME (95)
#define SWITCH_VER (20)
#define A_TIME (75)
#define B_TIME (3)
int PushKey(char* keyname, int holdtime, int delaytime);
void TiltLeftStick(int direction_deg, double power, int holdtime, int delaytime);
void Hit_Button_repeatedly(char *keyname, unsigned long int while_sec);
void Save_for_SV(void);
void GameStart_for_SV(void);
void GameQuit_for_SV(void);
void NextDay_in_HomeMenu(void);
void JumpTo(double deg, double sec, int expand_level = 0);
void Dash_for_Gimmighoul(double deg, double sec, bool need_reset_cam = false);
void setup() {
for(int i=0;i<7;i++)PushKey("UP", HOLDTIME, 300);
PushKey("B", HOLDTIME, 300);
delay(1000);
}
struct{
int dash_deg;
double dash_sec;
bool dash_ZL;
int jump_deg;
double jump_sec;
int jump_zoom;
}command_list[] = {
{ 90, 0.50, true,
105, 3.40, 1},
{315, 0.72, false,
118, 0.95, 1},
{290, 0.71, true,
101, 2.48, 1},
{340, 0.88 , false,
101, 3.28, 1},
{ 34, 0.80, false,
189, 2.91, 1},
{ 25, 0.68, false,
191, 4.74, 1},
{ 0, 0.80, false,
292, 5.86, 1},
{287, 0.79, true,
238, 2.80, 1},
{ 58, 1.24, false,
0, 5.62, 1},
{350, 1.10, false,
351, 3.80, 1},
};
void loop() {
const int STARTPOINT = 6;
for(int i=0; i< 10 ; i++){
int j = (i+STARTPOINT)%10;
Dash_for_Gimmighoul(command_list[j].dash_deg, command_list[j].dash_sec, command_list[j].dash_ZL);
JumpTo( command_list[j].jump_deg, command_list[j].jump_sec, command_list[j].jump_zoom);
}
TiltLeftStick(0, 0.5, 150, 550);
Save_for_SV();
GameQuit_for_SV();
NextDay_in_HomeMenu();
GameStart_for_SV();
}
void Dash_for_Gimmighoul(double deg, double sec, bool need_reset_cam = false){
if(need_reset_cam){
PushKey("L", HOLDTIME, 800);
}
TiltLeftStick(deg, 1.0, (int)((double)sec*1000UL), 300);
Hit_Button_repeatedly("A", 3);
delay(500);
return;
}
void JumpTo(double deg, double sec, int expand_level = 0){
PushKey("Y", HOLDTIME, 2500);
switch(expand_level){
case -1:
PushKey("ZL", HOLDTIME, 1700);
break;
case 1:
PushKey("ZR", HOLDTIME, 1700);
break;
case 0:
default:
break;
}
TiltLeftStick(deg, 1.0, (int)((double)sec*1000UL), 300);
while(expand_level >= 0){
PushKey("ZL", HOLDTIME, 1700);
expand_level--;
}
Hit_Button_repeatedly("A", 6);
delay(5000);
return;
}
void Save_for_SV(void){
PushKey("X", HOLDTIME, 1200);
PushKey("R", HOLDTIME, 1000);
PushKey("A", HOLDTIME, 3200);
PushKey("B", HOLDTIME, 1200);
PushKey("B", HOLDTIME, 1500);
return;
}
void NextDay_in_HomeMenu(void){
PushKey("down", HOLDTIME, 105);
PushKey("right", HOLDTIME, 105);
PushKey("right", HOLDTIME, 105);
PushKey("right", HOLDTIME, 105);
PushKey("right", HOLDTIME, 105);
PushKey("right", HOLDTIME, 105);
#if (SWITCH_VER >= 20)
PushKey("right", HOLDTIME, 105);
PushKey("right", HOLDTIME, 105);
#endif
PushKey("A", HOLDTIME, 1500);
PushKey("down", 1500, 105);
PushKey("right", HOLDTIME, 105);
#if (SWITCH_VER >= 15)
PushKey("down", 750, 105);
#elif (SWITCH_VER >= 13)
PushKey("down", 780, 105);
#else
for(int i=0; i<4; i++){
PushKey("down", (int)HOLDTIME/2, (int)105);
}
#endif
PushKey("A", HOLDTIME, 500);
PushKey("down", HOLDTIME, 105);
PushKey("down", HOLDTIME, 105);
PushKey("A", HOLDTIME, 500);
PushKey("right", HOLDTIME, 105);
PushKey("right", HOLDTIME, 105);
PushKey("up", HOLDTIME, 105);
PushKey("A", HOLDTIME, 105);
PushKey("A", HOLDTIME, 105);
PushKey("A", HOLDTIME, 105);
PushKey("A", HOLDTIME, 105);
PushKey("Home", HOLDTIME, 2000);
return;
}
void GameStart_for_SV(void){
PushKey("A", HOLDTIME, 1500);
PushKey("A", HOLDTIME, 24000);
PushKey("A", HOLDTIME, 23500);
return;
}
void GameQuit_for_SV(void){
PushKey("Home", HOLDTIME, 1200);
PushKey("X", HOLDTIME, 500);
PushKey("A", HOLDTIME, 4000);
return;
}
void Hit_Button_repeatedly(char *keyname, unsigned long int while_sec){
unsigned long int current_time=0;
unsigned long int start_time=0;
unsigned long int temp_time=0;
if( while_sec > 2147483){
Hit_Button_repeatedly(keyname, while_sec - 2147483);
while_sec = 2147483;
}
for( start_time=millis(), current_time=start_time ; current_time - start_time < (unsigned long)while_sec*1000UL ; current_time=millis() ){
if( current_time - start_time < (unsigned long)while_sec*1000UL )PushKey(keyname, HOLDTIME, 300);
}
return;
}
int PushKey(char* keyname, int holdtime, int delaytime){
if(strlen(keyname)==1){
switch(keyname[0]){
case 'A': case 'a':
SwitchControlLibrary().PressButtonA(); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonA(); delay(delaytime);
break;
case 'B': case 'b':
SwitchControlLibrary().PressButtonB(); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonB(); delay(delaytime);
break;
case 'X': case 'x':
SwitchControlLibrary().PressButtonX(); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonX(); delay(delaytime);
break;
case 'Y': case 'y':
SwitchControlLibrary().PressButtonY(); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonY(); delay(delaytime);
break;
case 'L': case 'l':
SwitchControlLibrary().PressButtonL(); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonL(); delay(delaytime);
break;
case 'R': case 'r':
SwitchControlLibrary().PressButtonR(); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonR(); delay(delaytime);
break;
case 'H': case 'h':
SwitchControlLibrary().PressButtonHome(); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonHome(); delay(delaytime);
break;
case '+': case 'p': case 'P':
SwitchControlLibrary().PressButtonPlus(); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonPlus(); delay(delaytime);
break;
case '-': case 'm': case 'M':
SwitchControlLibrary().PressButtonMinus(); delay(holdtime);
if(holdtime>0)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);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonZR(); delay(delaytime);
}
if(keyname[1]=='L'||keyname[1]=='l'){
SwitchControlLibrary().PressButtonZL(); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonZL(); delay(delaytime);
}
break;
case 'r': case 'R':
SwitchControlLibrary().MoveHat(2); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().MoveHat(8); delay(delaytime);
break;
case 'l': case 'L':
SwitchControlLibrary().MoveHat(6); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().MoveHat(8); delay(delaytime);
break;
case 'u': case 'U':
SwitchControlLibrary().MoveHat(0); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().MoveHat(8); delay(delaytime);
break;
case 'd': case 'D':
SwitchControlLibrary().MoveHat(4); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().MoveHat(8); delay(delaytime);
break;
case 'H': case 'h':
SwitchControlLibrary().PressButtonHome(); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonHome(); delay(delaytime);
default:
break;
}
}else{
return -1;
}
return strlen(keyname);
}
void TiltLeftStick(int direction_deg, double power, int holdtime, int delaytime){
double rad = (double)direction_deg*PI/180.0;
int x, y;
x = (double)128*sin(rad)*power;
y = (double)-128*cos(rad)*power;
x += 128; y += 128;
if(x >= 255) x=255; if(x <= 0) x=0;
if(y >= 255) y=255; if(y <= 0) y=0;
SwitchControlLibrary().MoveLeftStick(x,y);
if(holdtime> 0){
delay(holdtime);
SwitchControlLibrary().MoveLeftStick(128,128);
}
if(delaytime>0) delay(delaytime);
return;
}
4-4.動作の様子(YouTube)
2024年1月6日(←1年経っちゃった…)、DLCを導入したことで起動時間が多少長くなったことを受けて、void GameStart_for_SV(void)の中身の数字を調整しました。
それを受けて、同ソースコードで動作が確認できたので、その様子をYouTubeにアップしております。
あとがき
2023年、初の更新となる今回は「コレクレーのコイン」を回収する自動化を取り扱いました。
コイン集めはさながら「お年玉」、そしてパルデア十景から眺める日の出はまさに「初日の出」。全身が金色の”サーフゴーは「縁起が良い」ですし、まさに新年を飾るのにふさわしいトピックだったと思います。

2023年、あけましておめでとうございます。
コレクレー・サーフゴーと一緒にパルデア最高峰からの初日の出を眺めました。
今回のプログラムでは、そらとぶタクシーのデバッグ作業だけ、非常に骨が折れました。
そらとぶタクシーのカーソル移動が、雨や雪などで多少伸び縮みしたり、近くのテラスタルレイドバトルにフォーカスされたりなど、かなり難航を極めました。
結論として、今回のプログラムでは「地図の縮尺を最小(最大まで拡大)にしてからカーソル移動」をすることで、それらのズレの影響を最小限にしつつ、万が一カーソルが合わなかった際にも、カーソル移動後にマップ縮尺を拡大することで、目的地を選択しやすくする工夫を行いました。
これにより、非推奨ながら、8時間の放置*10も実現できました。

マップの拡大率を最大(詳細)にしておけば、マップを縮小することでカーソルのズレを吸収できる
ちなみに、肝心のコイン集めの自動化という観点においても、マップ移動に苦労したこともあり、「時間効率」の点では良好で、わずか8時間ほどでカンストまで持っていけました。満足しています。
また、アルゴリズムという意味でも、プログラムの全体構成はほぼ一発でかけたため、気持ちよく新年を迎えることができました。

8時間ほどで、コレクレーのコインが999枚でカンストしました!はやい!!
特に、この検証という意味で、デバッグ作業を兼ねて5時間にも渡る録画記録を見ながらExcelで集計し、時間効率についてもしっかりと検証を重ねました。結果、単純平均で1周あたり12.86枚という高効率を叩き出すことができていて、納得の仕上がりでした。
興味深かったのは、「列柱洞」と「みだれづきの滝」には48試行すべてでコレクレーが一度も出現しなかったことです。もし、このプログラムを改修する場合には、まっさきにこれら2つの行き先をカットすることで、より効率よくコイン集めをすることができるようになると考えます。
パルデア十景(10箇所のフォトスポット)のうち8箇所の看板にはコレクレーが出現する。
(集計の結果、「列柱洞」と「みだれづきの滝」にはコレクレーが出現しないことがわかった)
以上のように、コレクレーのコインを集めるという話題から、色々と論じることもできて、このブログ記事としてもしっかり厚くまとめられたことは、嬉しく思います。
これからも、本ブログでは、自分の気が向いた内容についてより詳しく、より楽しくまとめられるように工夫を凝らして行きたいと思いますし、マイペースながらもしっかりと続けていきたいと考えますので、引き続き応援のほどよろしくお願いいたします。
*
改めまして、2023年、新年あけましておめでとうございます。本年もどうぞご贔屓のほどよろしくお願いします!
「お役に立った」という方は、ぜひとも本ブログをお気に入り登録していただきつつ、拡散していただけるとすごく嬉しいです(ダイレクト広告)。
ではまたーc⌒っ.ω.)っ
--
筆者の利用マイコン(Arduino Leonardo)の購入リンク:
--
本ブログについて:本ブログについて
導入記事:【Arduino自動化01】Arduino開発環境の導入
(または 【2022年12月最新版】ZIP版IDEでのArduino開発環境の構築)
ポケモンSVの記事:スカーレットバイオレットArduino自動化 カテゴリーの記事一覧
ポケモン剣盾の記事:ポケモン剣盾Arduino自動化 カテゴリーの記事一覧
ポケモンBDSPの記事:ダイパリメイクArduino自動化 カテゴリーの記事一覧
レジェンズアルセウスの記事:レジェンズアルセウスArduino自動化 カテゴリーの記事一覧
YouTubeチャンネル:ますたーの忘備録 - YouTube