【YouTube動画公開】YouTubeチャンネル設営&紹介動画を初投稿【ポケモン剣盾Arduino自動化】

ますたーです。こんにちは。

 

本日5/6にYouTubeチャンネルを作成しましたので、その報告記事となります。

記念すべき第1弾の投稿動画は、本ブログで取り扱っているArduino Leonardoを活用した自動化デモ紹介です。人生でYouTube初投稿です。是非とも御覧ください!

※本ブログに初めてお越しの方は「本ブログについて」もぜひ、ご覧ください。

 

【投稿したYouTube動画はコチラ】

www.youtube.com

【Arduino自動化】ポケモン剣盾の面倒な作業をマイコンで自動化しよう(紹介動画) - YouTube

 

動画中では、下記3記事の内容をデモとして紹介しております。

 

・A連打(無限穴掘り兄弟)

 【Arduino自動化01】Arduino開発環境の導入


ポケモンキャンプでカレー自動調理

 【Arduino自動化09】ポケモンキャンプでカレー自動調理【カレーのあかし】


・雪中渓谷のワットショップの目玉商品
 【Arduino自動化02】雪中渓谷のワットショップの目玉商品を全自動回収【カンムリ雪原】

 

この動画投稿を機に、より多くの人がArduinoでの自動化に魅力を 感じていただければ幸いです。

ではではc⌒っ.ω.)っ

 

【Arduino自動化18】ローカルレイド自動配布【デリバードレイドでマックスこうせき】

ますたーです。こんにちは。

前回の更新から1ヶ月が経ち、5月になりました。業務繁忙で、文字通り「忙殺」される毎日でした。

 

さて、今回は、前々回の記事(第17回)のコメント欄でリクエストをいただいた、「レイドを自動でローカル配布するプログラム」を紹介します。

Arduino自動化記事も今回で第18回。これからもよろしくお願いいたします。

 

なお、Arduino Leonardo自動化の導入・機材構成については導入記事を参考にしてください。

導入記事:【Arduino自動化01】Arduino開発環境の導入

※本ブログに初めてお越しの方は「本ブログについて」もぜひ、ご覧ください。

 

概要

ローカル通信(YY通信)でのレイドバトル配布を自動で繰り返し行います。待機時間の変更・バトル時のA連打時間も変更可能です。

f:id:tangential_star:20210503200445g:plain

レイド募集→みんなで挑戦→30秒待機→レイド開始→リセット…を自動で繰り返す
(上記画像は「レイド開始まで30秒」「開始後リセットまで9秒待機」で設定)

 

もくじです。

今回は、レイド配布について一般論など余談を交えて記載しています。

基本的にローカル通信でのレイド配布に焦点を当て、中でもデリバードレイドに焦点を当てて執筆しています。例のごとく長めに丁寧に書きました。もし「説明なぞいらぬ!プログラムだけ寄越せ!」という方は、どうぞ⇒読み飛ばす

 

レイド周回とは

いつものごとくまずは余談から入ります。今回の目的まで読み飛ばしOKです。

用語の説明になりますが、「レイド周回」とは、友人や仲間で集まって、レイド募集側・参加側に分かれて参加側が高効率に報酬を稼ぐという行為を言います。

より具体的には、レイド募集側のプレイヤーは目的のレイドを出現させてセーブし、YY通信でメンバー募集し参加したら挑戦してまもなく切断を繰り返します。参加側のプレイヤーは、募集されているレイドに参加して最後までクリアし、レイドポケモンの捕獲や報酬の受け取りを繰り返します。

ヌケニンハピナスタブンネデリバードなど、レイド報酬が高効率なマックスレイドバトルを周回したり、乱数調整(Arduino自動化05)で出現させた任意の色違いレイドを周回して色違いポケモンを何匹も捕獲したりなど、目的のレイドを1度作りさえすれば、他のロムで何度も挑戦して量産できるのがポイントです。

f:id:tangential_star:20201123161659g:plain
f:id:tangential_star:20210501190713g:plain
レイド周回すれば、色違いのポケモンや希少なアイテムを量産できる

レイド周回の募集側を「レイド配布」と呼ぶ

上記のように、友人や仲間で一緒に遊べる人はともかく、現実には時間や場所の制約でなかなか難しかったり、そもそもそんな仲間がいない人もいます。

その場合、2台以上のSwitchを持っているユーザーならば、上記の募集側・参加側を自作自演することで高効率のレイドに挑戦し続けることができます。特に同一レイドには3人まで参加側を募ることができるため、1度に3台(つまり、主催者とは他の3人)までは高報酬の恩恵を得ることができます。この募集側、つまりは高報酬のレイドを配布している主催者(通信ホスト)あるいはこの行為を「レイド配布」と俗に呼びます。

必ずしもローカル通信に限定されることはなく、有志の方々がオンラインで上記のような高報酬レイドバトルや、色違いレイドのおすそ分けとして募集を呼びかける場合もあり、これも「レイド配布」と呼ばれています(狭義には、オンラインでのレイド募集に限定してレイド配布と呼びます)。ちなみに、レイド配布の手順は下記の通りです。

【レイド配布のやり方(募集側)】

  1. 目的の巣穴を出してセーブ
  2. オンラインで募集する場合は、YY通信からインターネット接続
  3. 巣穴で『みんなで挑戦』から募集を募る
  4. 挑戦が始まり、レイドバトルが始まったらHome画面に戻りリセット
  5. 以降、手順3~4を繰り返し

この「レイド配布」のよくある身近な例としては、チャンネル登録者数を増やして収益化をしたいYouTube投稿者が、募集側としてレイド配布を行う代わりにチャンネル登録と高評価を促しつつ、その様子をYouTube他で生配信するという使い方でしょうか。YouTubeニコニコ動画ほか、配信動画共有サイトで「レイド配布」と検索するとたくさん出てきます。

なお、レイド配布自体は特に問題は無いと考えますが、その使われ方・是非についてはここでは言及しません。各人が良識の範囲内で遊んでいただければ幸いです。

 

ローカルでレイド配布をしたい(今回の目的)

さて、ローカル通信でのレイド配布に話を戻します。

私を含め、Switchを2台持っているユーザーからすれば、片方でレイド配布を、もう片方で周回してひたすら攻略…としていきたいのですが、いかんせん、2台のSwitchを同時に操作するのはめんどくさいのです。言わずもがな、3台・4台のSwitch所有者であればなおのことでしょう。ほかにも、募集側・参加側の両方を操作すると、別の作業をする時間・余裕が意外と無く、ガッツリと周回作業に時間を取られることになります(つまり、勉強や仕事の合間に周回する、みたいなことができません)。

f:id:tangential_star:20210504140008g:plain

Switch2台(募集側・参加側)の両方を操作をしなければならず、とても大変

 

そこで、今回の自動化記事では、募集側(レイド配布側)の作業を完全自動にするプログラムを紹介します。

基本的にローカル環境であれば、誰かが「準備完了」を押さなくて予定時間内にレイドが開始できないといったトラブルも未然に防げる上、レイド中に回線切断、あるいはそれに付随したバグや障害が万が一発生しても自己責任のもと実行できます。

なお、オンライン(YY通信インターネット接続)でのレイド配布については私の環境では動作確認・検証ができないため、そういった意味でもまずはローカル通信でのレイド配布を実装していきます。

 

デリバードレイドの報酬は「マックスこうせき」含め最高効率!?

続いて今回の主な目的たる「デリバードレイド」の紹介です。

嘘か真か、一説にはデリバード」のマックスレイドバトルの報酬は、数あるレイド報酬の中で最高効率とも言われています。特筆すべきは、「マックスこうせき」「ドリームボール」の存在でしょう。有志の検証によれば、マックスこうせきが2個確定ドリームボールが1~3%金の王冠が1~5%でドロップするようです。

さらに、デリバードレイドは★3-4レイドなら1ターン攻略が可能。筆者の実測値でもわずか1周あたり1分35秒と、高速周回が可能です。なお、周回を目的とする場合、★5レイドでは最短でも2ターンかかるため、時間効率を考えると★4レイドを周回するのが効率的です。

f:id:tangential_star:20210501190713g:plain
f:id:tangential_star:20210504144905p:plain
デリバードレイドは「マックスこうせき」が【2個】確定で手に入る
1周あたり1分35秒。単純計算でダイマックスアドベンチャーと同等以上の効率になる
f:id:tangential_star:20210504230301g:plain
f:id:tangential_star:20210504230350p:plain
デリバードレイドでは「ドリームボール」が低確率(★4レイドで2%)で手に入る
マックスこうせき・けいけんアメ・ふしぎなアメなどを含めると実に好報酬

まずはデリバードレイドの1ターン攻略要員を育てよう

前述の通り、星3-4レイドであれば、デリバードのレイドバトルは1ターンでの攻略が可能です。募集側・周回側で手持ち1匹ずつ、少なくとも2匹を周回用に固定してNPCポケモンに依存しない、安定した周回を目指しましょう。

そのためには、下記条件を満たすポケモン・わざを準備する必要があります。

  • デリバードよりも先行して攻撃できるポケモン2匹(レベル100が望ましい)
  • NPCの特性など(コータスの『ひでり』等)で威力が半減しない『わざ』
  • 初撃要員のほうが、追撃要員よりも素早い(あるいは確実に先制が取れる)
  • 初動の1撃で確実にバリアを展開させるまで持っていける高火力
  • 追撃でバリア展開状態から確1で持っていける高火力

これらの条件に合うポケモンは複数検証報告されていますが、ここでは、参考までに筆者の使用ポケモンを紹介します。検証するのが面倒な方はご参考ください。

なお、より多くのプレイヤーに向けてレイド配布をするために、ホスト側がレイド開始直後にリセット(通信切断)することがありますが、その場合には、あらかじめ上記のわざ以外は忘れさせておきましょう。ランダム選択されたときに確実にそのわざが使用できないと、参加側の周回効率が大きく落ちるためです。

初撃オススメ:Cぶっぱレジエレキ「エレキボール」

レジエレキはS種族値200というトンデモ性能で、デオキシススピードフォルムすら抜き去る圧倒的な素早さの持ち主。そのユニークな特性「トランジスタ」により、でんきタイプのわざであれば実数値1.5倍の火力を出せるため、初撃に使うにはもってこいです。

でんきタイプなので、デリバードには抜群を取れる上、ひでり・あめふらし等の天候による威力増減も無く非常に安定した初動要員として重宝します。わざは命中安定&高火力な「エレキボール」一択でしょう。

なお、バリアを張る既定値までHPを削るだけで良いので、十分なレベル差・素早さがあれば、初撃に関しては過剰な火力は不要です。妥協して、例えばテッカニンなどでも十分に削ることができます。

f:id:tangential_star:20210504164042g:plain
f:id:tangential_star:20210504164006j:plain
初撃オススメはCぶっぱレジエレキによる圧倒的素早さからのエレキボール

追撃オススメ:ASぶっぱ夢ルガルガン@こだわりハチマキ「ストーンエッジ

続いて、追撃要員の紹介です。こちらは、こうげき努力値に極振りし、こだわりハチマキを持たせたルガルガンストーンエッジがオススメです。夢特性であれば「ノーガード」になるため命中不安なエッジを確定で当てることができます。また、いわタイプなので、デリバード(こおり・ひこう)の4倍弱点を突くことができることもポイントです。無論、天候による威力増減の影響も受けません。

なお、追撃要員は、デリバード「ふしぎなバリア」込みで確1に持っていくだけの圧倒的火力が必要です。きちんと確1で持っていけることを検証しておきましょう。

ちなみに、ふしぎなバリアは攻撃ダメージを1/10に軽減するため、抜群を突くか、過剰な火力を叩き込まないと確1で持っていけません。無論、NPCが攻撃してくれること前提であればやや火力不足でも1ターン周回は可能ですが、安定効率を高めるには必須でしょう(コスモパワーをやたら使いたがるソルロックとかいますからね)。

f:id:tangential_star:20210504164026g:plain
f:id:tangential_star:20210504164011p:plain
追撃オススメはASぶっぱルガルガン夢特性:ノーガード)のストーンエッジ

これらのポケモンを準備したら、配信側・参加側の2プレイヤーがそれぞれ1匹ずつを持つように手持ちの先頭にあらかじめ加えておきましょう

どちらのプレイヤーがどちらのポケモンを使っても構いませんが、少なくともホスト側のプレイヤーの覚えているわざは1つにしておきましょう。

 

事前準備1.カンムリ神殿の巣穴でレア柱を建てる

デリバードは、冠の雪原の様々な場所のレア柱(紫の太い光柱)で稀に出現しますが、アクセスのしやすさを考えると一番のオススメは「カンムリ神殿」の巣穴です。巣穴の周りには野生ポケモンもおらず、そらとぶタクシーから徒歩3秒の好立地です。

そらとぶタクシーでカンムリ神殿に降り立ったら、左手に進み、「ねがいのかたまり」を投げ入れてレアな柱(紫色の光柱)を建てましょう。

後は、デリバードの★4レイドがでるまで日付変更を繰り返してください。妥協する場合はデリバードの★3レイドでもOKです。

f:id:tangential_star:20210504173750g:plain
f:id:tangential_star:20210504173019g:plain
カンムリ神殿の巣穴のレア柱で「デリバード★4」レイドを出現させよう

目当てのレイドを出現させたら、巣穴の目の前でセーブしてください。目安として、Aをクリックしたら巣穴に話しかけられる状態です。

f:id:tangential_star:20210504194801p:plain

Aを押したら巣穴のレイド募集画面に入れる状態でレポートを書いておこう

 

事前準備2.プログラムの書き換え

おまたせしました。遂にプログラムの書き換えです。

ソースコード全文は後述しますが、必要に応じて2つの値(WAIT_TIMEとBATTLE_TIME)を修正してください。

なお、基本的に今回のプログラムはローカル配布を想定していますので、レイドパスコードの設定は実装しておりません。

書き換える値はWAIT_TIMEとBATTLE_TIMEの2箇所

#define WAIT_TIME (30)   // 「みんなで挑戦!」を押してから何秒待ち続けるか?
#define BATTLE_TIME (9)  // 挑戦後、何秒間レイドバトルを継続するか?(その間はA連打をします)

これらの値は、それぞれホスト側(募集側=レイド配布側)の待機時間を表します。具体的には、WAIT_TIMEは「みんなで挑戦」を押してから他のプレイヤーを何秒間待ち続けるかを、BATTLE_TIMEは「挑戦する」を押してから実際のレイド画面にかけて、何秒間A連打を続けるかの設定をそれぞれ表します。

BATTLE_TIMEの時間中は、A連打を続けるプログラムにしていますが、これによってレイドバトルを中断することなく、たたかう→1番目のわざを選んで進めてくれる、というわけです。そのポケモンを倒すまでの時間を計測して値を入れておくと、一人でローカル通信を行う分には重宝します。

一応、初期値としてはWAIT_TIMEを(30)、BATTLE_TIMEは(9)に設定しています。もし、レイド配布の際にレイドポケモンの姿をひと目見てからリセットしたい場合は(16)程度にしておくと良いと思います。また、レイド開始直後にリセットせずに、戦闘も行わせたい場合にはBATTLE_TIMEを十分に長い秒数で指定すると良いと思います、

星4デリバードレイドでのBATTLE_TIMEのオススメ設定は(55)

まずは結論から。前述のオススメポケモン2体で星4デリバードレイドを周回する場合には、BATTLE_TIMEを(55)に設定するのがオススメです。

以下説明ですので、本項は読み飛ばし可です。→読み飛ばす

レイドバトル開始直後にすぐさまリセットし、次のレイドを開いて募集するオンラインでのレイド配布とは異なり、ローカル通信でのレイド配布では通信切断のタイミングをバトル終了後~報酬画面前に調整するのが一般的です。これは、レイドを開催するまでのスパンを短くして、より多くの不特定多数のプレイヤーにレイド配布を行うという目的の「オンラインでのレイド配布」とは異なり、ローカル通信環境では高々3人までが固定周回を行うことに由来します。

オンラインのレイド配布に参加した際、あるいは、通信レイド中に回線切断が起こった場合に、1分ほど入力を受け付けない時間(通信待機中…となったり、何のダイアログも出ないままバトルの進行が止まったりなど)が発生することがあります。これは、ポケモン剣盾でバトル進行の同期を取るために、通信のタイムアウト設定がなされているからです。つまり、レイドバトル中は、ホスト(募集側)がゲームをリセットすると、当該レイドに参加中のプレイヤーが最大1分間そのホストの応答を待つ挙動をするのです。この仕様はローカルレイドでも同様なので、レイド開始直後にゲームリセットを行うとそのまま1分間待たされることになります。一方で、レイド終了の撃破演出の後はこの同期(通信待機)がなくなるため、任意のタイミングでリセットが可能です。

そのため、ローカル通信でレイド周回をする際には、募集側もレイドポケモンを倒すまで一緒に操作して、ポケモンを撃破した演出が出てから(=捕獲画面になってから)リセット→次のレイドを立ち上げる、という流れで進めることが一般的です。そこで、今回のプログラムもこれに倣い、あらかじめプログラムにはA連打を仕込んでおき、レイドバトルもA連打で自動化する、という構成に仕上げてあります。

ここで、星4デリバードの撃破にかかる時間は上記2匹を利用した場合、おおよそ45秒です。さらにNPCが「ひでり(コータス)」「ぎょぐん(ヨワシ)」「いかく(ハリーセン)」「プレッシャー(マニューラ)」などの戦闘開始時に発動する特性を使ったり、「てだすけ(イーブイ)」「このゆびとまれ(ピッピ)」「ふいうち(マラカッチ)」などの先制技を使ったりすると、45秒に加えてこれらの時間分待機時間が増えることになります。おおよそ特性演出は5秒程度ですので、45秒+5秒+5秒程度の時間があれば良いことになります。

f:id:tangential_star:20210504204955g:plain

「いかく」「ひでり」を持つポケモンNPCから同時に選出されることが稀にある。
この際、バトルにかかった時間(開始~撃破演出まで)は55秒だった

手動検証中、ハリーセンコータスの2匹が出現したことがありました。この時のバトル終了までの時間(挑戦開始~撃破演出まで)の実測値は55秒でしたので、前述の数字(仮説)は概ね正しいと言えるでしょう。ゆえに、BATTLE_TIMEは(55)程度で設定しておけば良いことになります。

なお、それぞれのモーションが長めになる、ヨワシの「ぎょぐん」+イーブイの「てだすけ」に加え、「ストーンエッジ」が急所に当たると、55秒を若干超えるようなので、心配な方は(60)秒くらいにしておくと良いかもしれません。逆に長すぎると周回効率が下がるばかりか、レイド終了後そのまま巣穴に「ねがいのかたまり」を投げ入れてセーブしてしまうため、注意しましょう。

 

ソースコード

前述の通り、ソースコード冒頭のWAIT_TIMEとBATTLE_TIMEの値を各自で必要に応じて修正してください。上記にはケーススタディとしてデリバードでのレイドを中心に、設定数値の紹介などをしております。合わせてご参考ください。

WAIT_TIMEは他のプレイヤー参加を待つ時間、BATTLE_TIMEは、レイドバトルの進行(戦闘)にかかる時間(いずれも単位は「秒」)です。

/* 
 *  固定レイドYY通信(ローカル)配布
 *  目的のレイドが出現した巣穴の目の前でセーブしておくこと。
 *  あとは、Arduinoを挿すだけで自動でレイド募集→挑戦→リセットを繰り返します。
 *  
 *  (c) 2021 ますたーの忘備録
 *  https://tangential-star.hatenablog.jp/
*/

#include <SwitchControlLibrary.h>

#define HOLDTIME (95) // 1回のキー入力の長押し時間[ms]

#define WAIT_TIME (30)   // 「みんなで挑戦!」を押してから何秒待ち続けるか?
#define BATTLE_TIME (9)  // 挑戦後、何秒間レイドバトルを継続するか?(その間はA連打をします)
// レイドを開始するまでなら(9)秒でOKです。
// 登場ポケモンの姿を見たい場合(色違い確認など)は(16)秒くらいで設定ください。
// なお、このBATTLE_TIME中は、ずっとA連打をしてくれます。
// レイドバトル中も自動操作させたい場合は(16)以上の数字を入力してもOKです。
//   ※使うわざを先頭にしておく必要があります
// ただし、レイド終了の如何に関わらずひたすらA連打をし続けるため、この設定が適切で無い場合、
// 巣穴に新たな願いのかたまりを投げ入れてしまうので注意してください。
// デリバードレイドの場合の目安は(55)です(ひでり+いかくエフェクト込みでデリバード1ターン撃破までの秒数)。
// 56秒であれば、NPCの上記特性の発動無しでも、ポケモン捕獲エフェクトで中にリセットされるため大丈夫だと思います
// 心配な方は(60)くらいにしておくと良いかと思います。各人で調整ください。

void PushRL(int delay_time_ms);
int PushKey(char* keyname, int holdtime, int delaytime);
void NextDayInCheatMode(void);

void setup() {
  // コントローラーとして認識されるためにRLを7回ほどカチャカチャする
  for(int i=0;i<7;i++)PushRL(300);
  delay(1000);
}


void loop() {
  unsigned long int current_time=0;
  unsigned long int start_time=0;
  unsigned long int temp_time=0;

  // 巣穴の前で乱数したい個体を出してセーブした状態。
  
  PushKey("A", HOLDTIME, 1500); // 募集画面に入る

  PushKey("A", HOLDTIME, 2500); // みんなで 挑戦!(→通信待機中 しばらくお待ち下さい)
  PushKey("UP", HOLDTIME, 300); //
  PushKey("A", HOLDTIME, 500); // 準備完了!
  PushKey("A", HOLDTIME, 500); // バトルを 開始する
  PushKey("A", HOLDTIME, 500); // 参加人数が足りません! ▼ (→サポートの トレーナーが 参加しますが よろしいですか?)
  delay(1000UL*WAIT_TIME); // WAIT_TIME秒待機する
  PushKey("A", HOLDTIME, 300); // →はい

  // 挑戦画面~レイドバトル(誰かが「準備完了」を押しそこねていた場合のケアも兼ねてA連打)
  for( start_time=millis(), current_time=start_time ; current_time - start_time < (unsigned long)BATTLE_TIME*1000UL ; current_time=millis() ){
    if( current_time - start_time < (unsigned long)(BATTLE_TIME-3)*1000UL )PushKey("A", HOLDTIME, 300); // ひたすらA連打
  }

  // リセットして次の挑戦
  PushKey("Home", HOLDTIME, 1000); // ゲーム終了のためのHomeボタン
  PushKey("X", HOLDTIME, 500);     // 終了Xを押す→終了しますか?画面
  PushKey("A", HOLDTIME, 3000);    // はい→終了しています・・・
  PushKey("A", HOLDTIME, 1000);    // ゲームタイトルクリック→ユーザを選んでください画面(複数ユーザいる場合)
  PushKey("A", HOLDTIME, 18500);   // A押してから起動までおおよそ16秒(最短目安。環境に合わせて設定すること)
  PushKey("A", HOLDTIME, 10000);   // タイトル画面からフィールド遷移までおおよそ10秒(環境に合わせて設定すること)

}

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){
  // ホームボタン・方向キーはRight, Left, Up, Down, Homeなど2文字以上で入力。
  // その他ボタン入力は1文字(A,B,X,Y,R,L,+,-)ZR・ZLにも対応
  // 同時押しは非対応
  
  if(strlen(keyname)==1){
    switch(keyname[0]){
      case 'A': case 'a': // A
        SwitchControlLibrary().PressButtonA(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonA(); delay(delaytime);
      break;
      case 'B': case 'b': // B
        SwitchControlLibrary().PressButtonB(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonB(); delay(delaytime);
      break;
      case 'X': case 'x': // X
        SwitchControlLibrary().PressButtonX(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonX(); delay(delaytime);
      break;
      case 'Y': case 'y': // Y
        SwitchControlLibrary().PressButtonY(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonY(); delay(delaytime);
      break;
      case 'L': case 'l': // L
        SwitchControlLibrary().PressButtonL(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonL(); delay(delaytime);
      break;
      case 'R': case 'r': // R
        SwitchControlLibrary().PressButtonR(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonR(); delay(delaytime);
      break;
      case 'H': case 'h': // Home
        SwitchControlLibrary().PressButtonHome(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonHome(); delay(delaytime);
      break;
      case '+': case 'p': case 'P': // Plus
        SwitchControlLibrary().PressButtonPlus(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonPlus(); delay(delaytime);
      break;
      case '-': case 'm': case 'M': // Minus
        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': // ZR/ZL
        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': // right
        SwitchControlLibrary().MoveHat(2); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().MoveHat(8); delay(delaytime);
      break;
      case 'l': case 'L': // left
        SwitchControlLibrary().MoveHat(6); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().MoveHat(8); delay(delaytime);
      break;
      case 'u': case 'U': // up
        SwitchControlLibrary().MoveHat(0); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().MoveHat(8); delay(delaytime);
      break;
      case 'd': case 'D': // down
        SwitchControlLibrary().MoveHat(4); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().MoveHat(8); delay(delaytime);
      break;
      case 'H': case 'h': // Home
        SwitchControlLibrary().PressButtonHome(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonHome(); delay(delaytime);
      default:
      break;  
    }
  }else{
    return -1;
  }
  return strlen(keyname);
}
void NextDayInCheatMode(){
  // ★日付変更
  // Homeボタンを押して設定の画面へ移動
  PushKey("Home", HOLDTIME, 1000);

  // Home画面で「設定」を選ぶ
  PushKey("down", HOLDTIME, 105);
  PushKey("right", HOLDTIME, 105);
  PushKey("right", HOLDTIME, 105);
  PushKey("right", HOLDTIME, 105);
  PushKey("right", HOLDTIME, 105);
  PushKey("right", HOLDTIME, 105);
  PushKey("A", HOLDTIME, 1500);

  // 設定画面で「日付と時刻」を開く
  PushKey("down", 1500, 105); // 1.5秒「↓」長押し
  PushKey("right", HOLDTIME, 105); 

  for(int i=0; i<4; i++){
    PushKey("down", HOLDTIME, 55);
  }
  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);
  PushKey("A", HOLDTIME, 1000);
  return;
}

 

このプログラムでレイド周回の作業負荷が半減!

今回のプログラムを使うことで、従来、募集側と参加側を1人2役でやっていたレイド周回作業の手間が文字通り半減しました

それだけでなく、コントローラーを持ち替える手間が減り、操作手順をそれぞれで考える必要がなくなり、体感負荷は半分以下になりました

f:id:tangential_star:20210504232424p:plain
f:id:tangential_star:20210504232540p:plain
常に2台を操作しなければならなかった周回作業が、1台のSwitch操作で完結
まさに劇的なビフォーアフターと言える

実際、プログラムを稼働させつつ、もう片方のSwitchをPCのキーボード前に置いてレイド周回を行いながら、なんと1時間以上にもわたり、無理なくこの記事の執筆作業を続けることができました。

f:id:tangential_star:20210504223406g:plain

レイド周回の募集側を完全自動化したことで、作業しながらでもレイド周回が可能に!
※殆どの時間、キーボードから手を離さなずに済んでいることがわかる(41倍速再生)

上記のGIF画像をご覧いただければ一目瞭然ですが、レイド周回から文字通り手が離せなかった従来とは違い、ほとんどの時間をキーボード作業ほかに充てることができています如実に、単純作業を代替させるにはArduinoは適任であると感じられる結果だったと考えます。

 

あとがき

気づけば5月になっていました。前回更新が3月28日でしたから、まるまる1ヶ月以上、更新できずでした。実際、3月~4月は年度末・年度初めによるものか業務繁忙で、あっという間に過ぎてしまいました。

ブログの更新はおろか、ゲームで遊ぶ時間もほぼ無く、かなり大変な2ヶ月でしたが、そんな中、本ブログに定期的に足を運んでいただいている方や、温かいコメントを残していただける方もいらして、やはり私のモチベーションにも繋がりますし、心の支えにもなっています。

また、このコロナ禍で在宅勤務が増え、仕事とプライベートの境が非常に曖昧になりつつある昨今ですが、このように趣味のポケモンが心の安寧・支えになっていることに改めて気付かされます。

今回のブログ更新のきっかけの一つは、やはり、前々回の記事(第17回)のコメント欄でリクエストをいただいたことにほかなりません。自分の中でも「いつか作りたい」「いつか更新したい」と思っていた内容ではあったものの、やはり明確に「ブログ記事が役に立っている」ことがわかると実装・執筆の意欲も段違いに上がりました。そういう意味でも、コメントをいただけると嬉しく思います。

 

もし、皆様にとって、本ブログがご参考・お役立ていただけているようであれば筆者としては嬉しく思いますし、その旨をコメントでご報告いただけるとさらに嬉しく思います

引き続き、本ブログをどうぞよろしくお願いいたします。

 

ではではc⌒っ.ω.)っ

 

前記事:【Arduino自動化05ex】乱数調整レイドでのArduino Leonardoの使い方

導入記事:【Arduino自動化01】Arduino開発環境の導入

Arduino自動化記事一覧は こちら

 

【Arduino自動化05ex】乱数調整レイドでのArduino Leonardoの使い方

ますたーです。こんにちは。

3月は繁忙でなかなか更新ができませんでした。

 

さて、今回はArduino自動化記事05で紹介・実施した乱数調整色レイドの手順についての補足記事です。具体的には、Arduinoをどのタイミングで使うのか、に焦点を当てて執筆しました。一応、本記事だけでも読めるように書きますが、先に当該記事を一読しておくとスムーズです。

なお、Arduino Leonardoでの自動化環境の導入については、導入記事を参考にしてください。

※本ブログに初めてお越しの方は「本ブログについて」もぜひ、ご覧ください。

【!】本記事では乱数調整の内容を扱います。

 

概要

今回の記事では、レイド乱数調整の中で「Arduino Leonardoをどのタイミングで使うのか」を紹介します。 

詳細実際の作業手順は適宜 前回の記事(Arduno自動化05) で補ってください(途中途中にリンクも貼りますのでご安心ください)。

本記事のメインターゲットは「乱数調整は知っているけどArduinoを使うというのがいまいちピンとこない人」「前回記事を読んだけど、Arduinoコンパイル?抜き差し?をどのタイミングでやればいいのかわからない人」になります。

では目次です。補足記事なので、例のごとく分量多めです。順番に読んで頂くと抜け漏れが無いかと思いますが、各人、必要になる部分について、目次から飛んで読んでいただいても大丈夫です。

とりあえずお急ぎの方は【ここから本題】まで読み飛ばすと良いと思います。

 

自動化で準備するハードウェア5つ(おさらい)

まずは、使用機材についておさらいです。必要なものは以下の通りです。

ひとまず、これらが揃っていることを確認ください。

実際に筆者が使っている機材については「番外編03:機材紹介記事」をご参考ください)セットアップ手順は「Arduino自動化01:導入記事」で紹介しています)。

乱数調整の自動化に必要なものは、「Nintendo Switch」と「Arduino Leonardo」、これらをつなぐ「USBケーブル」と「ドック」、そして「PC」の5点です。

筆者が使っている機材のイメージ。要するに上記5つで準備完了だ。

 

乱数調整に使うツール

続いて、使うツールの話です。

具体的には、乱数調整は「初期シード特定」「目標消費作業」の2ステップありますが、インストールするアプリケーションがいくつかあります。特に初期シード特定作業は有名なツールが2つあります。ここでは補足記事として両方紹介します。

初期シード特定は「1-Star Seed Search」「SW Seed Calculator」どちらもOK

様々なブログ記事や動画などで紹介されている乱数調整(初期シードの特定)を行うツールとしては、さびたコイル氏による「1-Star Seed Search」と、ぼんじり氏による「SW Seed Calculator」の2つが特に有名だと思います。

どちらも、初期シードの推定ができるツールとして優れており、筆者は両方とも使っています。どちらのツールも大変素晴らしいと思います。

「SW Seed Calculator」は初期シード特定に特化

一応、前回の記事(Arduino自動化05)では、1-Star Seed Searchを使っていますが、これは乱数調整の記事を扱う上で、「初期シード特定」と「目的の消費数の特定」の作業が同じツールで完結するため、説明しやすかったことが理由です。

一方で、ぼんじり氏が提供する「SW Seed Calculator」は、その次のステップ(目的の消費数の特定作業)には別のツール(夜網氏が提供する「8densearch」など)を使う必要があるため、乱数調整の流れを理解していない人には少し説明がしにくいです。

ただし、「初期シード特定」に限定するなら「SW Seed Calculator」はすごく使いやすくしかも高速で、エラーも少ないため個人的には大変おすすめです。特に、6日目検索ができるため初期シード特定の精度も高く、セットアップの煩雑さや別ツール連携の手間をいとわないのであれば、ぜひとも使っていきたいと感じます。

本記事や様々な記事で「乱数調整の全体の流れ」がわかってから使うと驚くほど使いやすいと思いますし、もし、前回の記事(Arduino自動化05)で初期シード特定につまづいているなら、試してみても良いかもしれません。

f:id:tangential_star:20210314181645p:plain
f:id:tangential_star:20210314181653p:plain
「1-Star Seed Search」「SW Seed Calculator」はどちらも初期シード特定ができる。
大きな違いはポケモンを捕まえる回数だ

乱数調整に使うツールの組み合わせ

乱数調整は大きく「初期シード特定」「目的の消費数の特定」の2つに分かれます。前回の記事では紹介した「1-Star Seed Search」では、これら2つを1つのツールで完結できるので、初期導入としては比較的簡単です。

一応、下記の2パターンがおすすめです。お好きな方で実施ください。前回の記事(Arduino自動化05)では下記1を採用しています。

  1. さびたコイル氏の「1-Star Seed Search」のみ(流れを理解するまではおすすめ)
  2. ぼんじり氏の「SW Seed Calculator」+夜網氏の「8densearch(慣れたらおすすめ)
f:id:tangential_star:20210314203914p:plain
f:id:tangential_star:20210314203921p:plain
「1-Star Seed Search」では目標個体検索まで1つのツールで完結する。
「SW Seed Calculator」利用時などは「8denSerach」など別ツールで目標個体検索を行う

 

「1-StarSeedSearch」を使う場合は、前回の記事(Arduino自動化05) を参考にセットアップしてください。「SW Seed Calculator」を使う場合は、ぼんじり氏のWebサイトから「SW Seed Calculator」をダウンロードしてください。

原則として、これらは最新版が良いかと思いますが、お好みで決めてください。その後、そのページの手順(ダウンロードリンクの下の方に設定方法載っています)に沿ってセットアップしてください(リンク先に載っているので、本稿ではセットアップ方法は割愛します)。

この記事では補完記事としての側面から、初期シード特定にはSW Seed Calculatorを利用します

 

【ここから本題】乱数調整でArduino自動化できる2つの手順

ここからが本題です。

前回の記事でも紹介した通り、乱数調整の手順は大きく4つです。

この中でArduinoによる一部自動化ができるのは下記2と3、2つの手順です。

  1. 準備(目当ての巣穴を見つけてねがいのかたまり投げ入れる)
  2. 乱数調整(日付回してポケモン捕まえて初期シードを特定する作業
  3. 乱数消費(目標の日付に向かって何度も日付を変更する作業
  4. 捕獲(お気に入りのボールで捕まえる)

ここからはまず、この「初期シードを特定する作業」について 紹介をします。

 

1.準備(目当ての巣穴を決めて「ねがいのかたまり」を投げ入れる)

まずは、レイド乱数調整に挑戦する巣穴を決めましょう。

具体的には、ポケモン徹底攻略の「レイドバトルのポケモン一覧」などから、欲しいポケモンのいる巣穴を探します。もし、乱数調整ツールに前述の「SW Seed Calculator」をお使いの場合は、右上の「巣穴マップを開く」から巣穴を逆引きできますので、必要に応じてご活用ください。

f:id:tangential_star:20210320190437p:plain
f:id:tangential_star:20210320184124p:plain
巣穴の場所は「ポケモン徹底攻略(左)」や「SW Seed Calculator(右)」などで調べよう

余談ですが、DLC冠の雪原の巣穴で出てくるポケモン夢特性が固定されるので、それが気になる人はガラル本土で探しましょう。

さて、今回は、色違いが金色で美しい、チルタリスを狙って行きます。チルタリスは様々な巣穴で出現しますが、今回は「ボールレイクの湖畔 D」の巣穴を目指します。 

f:id:tangential_star:20210320212626g:plain

まずは、目標の巣穴に向かおう

巣穴について、狙うポケモンによっては(例えばキョダイマックス個体など)、いわゆる「レア柱」でないと出現しないことがあります。つまり、目標となる巣穴の場所はもちろん、「通常」「レア」のいずれの柱を建てる必要があるのかも確認しておきましょう(レアの柱とは、通常の赤色の光の柱ではなく、紫色のオーラが出ている太い光柱のことです)。

f:id:tangential_star:20210320211737g:plain
f:id:tangential_star:20210320211758g:plain
巣穴前でセーブしておき、「ねがいのかたまり」を投げ入れたらすぐにHomeボタン。
赤色がうっすらと見えていたら即リセットすることで、投げ直し(レア柱厳選)ができる

なお、自分で「ねがいのかたまり」を投げ入れて建てた柱でないと、乱数調整はできません。もし、すでに目標の巣穴に光の柱が建っていても、そのまま次のステップに進まず、日付変更やレイド挑戦などで予め消しておき、必ず自分で建てましょう。

無事に目標の巣穴に光の柱を建て終わったら、念の為、セーブしておいてください。


2.Arduinoにプログラム(3日後・4日目用)を書き込もう

さあ、ついに手順の中にArduinoが登場しました。なお、本記事は導入記事でセットアップが完了している想定で書いています。悪しからずご了承ください。

ここから、乱数調整が始まりますが、今からの手順は「初期シードの推定」作業になります。このステップでは、条件を満たすポケモンが現れるまでひたすら3日後(4日目)のポケモンを捕まえてはリセット、捕まえてはリセット、…と幾度となく繰り返し作業が発生します。ここを、Arduinoで自動化する準備となります。

まずは、PCで、Arduino IDEを開いてください。そこに、Arduino自動化05記事のソースコード1つ目をコピペして、検証&マイコンボードに書き込みを行ってください。

f:id:tangential_star:20210320222301p:plain
f:id:tangential_star:20210320220743p:plain
PCとArduinoをつないでおき、IDEソースコードをコピペしてボードに書き込もう

ちなみに、「新しい名前で保存する」ダイアログが出てきたら、半角英数字でファイル名をつけてください。日本語はNGです。

無事にArduinoにプログラムが書き込まれたら、ArduinoをPCから抜いてください。

 

3.最初の目標ポケモンを把握する

まずは乱数調整のファーストステップです。ツールを使って、初期シード特定に必要なポケモン(3日後=4日目に出会わなければならないポケモン)を調べます。

「SW Seed Calculator」をお使いの方も、「1-Star Seed Search」をお使いの方も手順は共通です。巣穴情報を入力しておけば、最初に出会わなければならないポケモンはプルダウンメニューの中に出てきます。

※以降、本記事では「SW Seed Calculator」で画面説明をします。

f:id:tangential_star:20210320230213p:plain
f:id:tangential_star:20210320230225p:plain
まずは3日後(4日目)に遭遇する必要のあるポケモンを把握しよう
なお、「SW Seed Calculator」「1-Star Seed Search」いずれもやることは同じだ

今回の例(ボールレイクの湖畔D・レア/バッジ=8個/ROM=ソード)だと、まずは「★3 アオガラス」「★3 ゴルバット」のいずれかを見つける必要があることがわかります。これをまずは把握しましょう。

 

4.ArduinoをSwitchに挿し込もう 

さて、ゲーム画面に戻ります。ゲーム画面では、巣穴に「ねがいのかたまり」を投げ入れたタイミングで終了していると思います(つまり、Aを押したらレイド募集画面に入れる状態)。この状態のまま、SwitchとArduinoを接続してください。充電しながら行う場合は、先にSwitchをドックに差し込んでから、ドックのUSBポートにArduinoを挿し込んでください。

正しく接続されると、勝手に「ゲーム終了→ゲーム起動→レイド調整~日付変更を3回繰り返す→日付を戻して挑戦画面で待機」という一連の流れが行われます。自動操作が止まるまで、放置しましょう(2分半くらい)。

※このプログラムは3日間日付を進めても月をまたがない想定で使っています。注意してください

f:id:tangential_star:20210320224404p:plain
f:id:tangential_star:20210320225156g:plain
ArduinoをSwitchに接続すると自動で操作される。他コントローラー接続は解除しておくこと

なお、SwitchとArduinoを接続する際には、Switchに接続されている有線・無線コントローラーすべて(本体から取り外した状態のJoy-conや、プロコントローラーなどを含みます)の接続を解除または切断した状態にしてください。

 

5.自動操作が止まったら、目標のポケモンを捕獲しよう

ゲーム画面の動きが止まったら、画面に映っているポケモンが目標のポケモンだったかどうかを確認します。具体的には、ステップ3で確認したポケモンであればOKです。

今回の例(ボールレイクの湖畔D・レア/バッジ=8個/ROM=ソード)だと、まずは「★3 アオガラス」「★3 ゴルバット」のいずれかを見つけなければなりませんから、例えば「★4 アオガラス」「★5 クロバット」などで画面が止まっている場合はNGとなります(★の数も要注意!)。

目標のポケモンではなかった場合は、目標のポケモンが出るまでArduinoをSwitchから一度抜き、挿し直しましょう。

目標のポケモンが出現していた場合には、そのポケモンを捕獲します。

f:id:tangential_star:20210320232957p:plain

目標のポケモンが出るまでひたすらArduinoを挿し直そう
f:id:tangential_star:20210320231942p:plain
f:id:tangential_star:20201123010702g:plain
画面が目標のポケモンではなかった場合、Arduinoを挿し直す
f:id:tangential_star:20210320231438p:plain
f:id:tangential_star:20210320235704g:plain
画面が目標のポケモン(★も要チェック!)だった場合、レイドに挑戦して捕獲する

 

6.捕まえたポケモンの能力をツールに入力

捕まえたポケモンの特性・性格・能力値(個体値)をツールに入力します。

個体値の計算には、原則としてLv100まで引き上げるだけの「けいけんアメ」や「ふしぎなアメ」、そして性格補正で個体値判別が出来なかった場合に備えての「まじめミント」またはドーピングアイテムがあると非常に便利です。 

f:id:tangential_star:20210321002240g:plain
f:id:tangential_star:20210321001907p:plain
捕まえたポケモンの能力値をツールに入力しよう。アメとまじめミントがあると便利だ

6-1.利用できない個体値の場合

能力値を入力後、1-Star Seed Searchでは「NG!」、SW Seed Calculatorの画面で「利用できない個体値です」 という言葉がでてきた場合、残念ながら手順をやり直す必要があります。単純にやり直すのではなく、1日日付をずらす必要があります。

f:id:tangential_star:20210321005840p:plain
f:id:tangential_star:20210321004552g:plain
個体値がNGだった場合、再起動して日付を手動で1日進めよう。セーブも忘れずに

 具体的な手順としては

  1. 一度、ゲームを終了する(再起動する)
  2. 巣穴レイドバトル「みんなで挑戦」を選択する
  3. Homeボタン→設定→日付を1日すすめる
  4. 巣穴からワットを回収する
  5. セーブする

になります。 セーブまで完了したらまた4~6の手順をやり直します。

6-2.利用できる個体値の場合

能力値を入力後、1-Star Seed Searchで「OK!  Next ->」、SW Seed Calculatorの画面で「利用可能な個体値です」 という言葉がでてきた場合は、おめでとうございます。第1関門突破です。セーブしてはいけません。注意しましょう。

f:id:tangential_star:20210321012622g:plain
f:id:tangential_star:20210321012647p:plain
「利用可能な個体値です」となれば次ステップに進める

利用可能な個体値だった場合、次の目標ポケモンの指示も合わせてツール上に出てくるので、そちらを確認してください。具体的には、3V, 4V, 5Vなど、次に捕まえるべきポケモンのV数の指定が出てくるので、その数字にあった巣穴のポケモンを捕まえます。

f:id:tangential_star:20210321014105p:plain

次の目標ポケモンの条件が表記されるので、プルダウンからポケモン名を確認しよう

なお、詳細な原理については割愛しますが、「SW Seed Calculator」を利用の場合、「4V -> 4連」のように、Vの数と連数が両方表示されることがあります。

この時、もし、複数のV数・連数のペアが表示されている場合は、可能な限り「連数」が多い方のV数ポケモンを捕まえてください。例えば「4V->6連 3V->5連」と表示された場合は、「4V」の方を選択してください。「4V/5V -> 4連」のように、連数が変わらない場合は、どちらでも大丈夫です。

次の目標となるポケモンを把握したら、セーブせずに次のステップに進んでください。

 

7.次の目標ポケモンを捕まえて個体値入力

「4日目(2体目)」のポケモンを捕まえる場合、基本的に4~6と同じ手順です。

要するに、「次のターゲットとなるポケモンが出るまでArduinoを挿し直す」だけでOKです。ターゲットとなるポケモンが出たら、レイドバトルをして捕獲してください。

f:id:tangential_star:20210321030638g:plain
f:id:tangential_star:20210321031025p:plain
基本的に前の手順と同一。指定のV数を持つポケモンを捕まえればOKだ。

これで、最初の日を起算日として、3日後のポケモン2匹の個体値がツールに入力された状態となっています。ここまでくれば次の作業も同じ流れ。この調子です。

なお、やはりレポートはしません。要注意です。

 

8.Arduinoのプログラム(4日後・5日目用)に書き換えよう

さて、ここでArduinoに話が戻ります。次のステップでは「5日目(4日後)」のポケモンを捕まえる必要がありますので、事前にArduinoのプログラムを書き換える必要があります。

具体的には、再びArduino IDEで先程のソースコードを開いて、TIME_WARP_DAYSの(3)を(4)に書き換えてArduinoに書き込めばOKです。

#define TIME_WARP_DAYS (4) // 何日すすめるか(=ここは基本的に「3」こ

この1箇所の書き換えが完了したら、PCとArduinoをつなぎ、左上の「検証」「マイコンボードに書き込み」作業を行ってください。

ちなみに、次に捕まえるポケモンについてはツールの指示通り、基本的には不問ですが、可能な限りVの少ないレイドのほうが望ましいです。特にVの少なさはそっくりそのまま計算速度・精度に比例しますので、もし、マシンスペックが低いPCを使っている場合などは特に気をつけましょう。

f:id:tangential_star:20210321094229p:plain
f:id:tangential_star:20210321022029p:plain
次は「4日後(5日目)」のポケモンを捕まえる必要があるのでプログラムを書き換える

 

9.次の目標ポケモンを捕まえて個体値入力

続いて、「5日目」のポケモンを捕まえる場合も、基本的に4~6と同じ手順です。ただし、ターゲットは不問となりますので、★の少ないレイドなどを厳選しましょう。要するに、「極力Vの少ないレイドが出るまでArduinoを挿し直す」だけでOKです。

f:id:tangential_star:20210321104404g:plain
f:id:tangential_star:20210321104129p:plain
同様の手順で4日後(5日目)のポケモンを捕まえて能力値を入力しよう

口酸っぱく言いますが、ポケモンを捕まえた後はくれぐれもセーブしないように注意してください。

 

10.Arduinoのプログラム(5日後・6日目用)に書き換えよう

ここまで読まれた方にはお分かりかと思いますが、次のステップでは「6日目(5日後)」のポケモンを捕まえる必要がありますので、再びArduinoのプログラムを書き換えます。TIME_WARP_DAYSを(5)に書き換えてArduinoに書き込めばOKです。

#define TIME_WARP_DAYS (5) // 何日すすめるか(=ここは基本的に「3」こ

 

 

11.最後の目標ポケモンを捕まえて個体値入力

「6日目」のポケモンを捕まえる手順も、基本的に4~6と同様です。★の少ないレイドが出るまでArduinoを抜き差しして、目当てのレイドだったら捕獲して個体値チェックです。

ここで妥協して星5レイドなどで済ませると、SEEDの誤検出のリスクも高くなるため、極力★3レイドなど、V数が少ないレイドを選ぶようにしましょう。ここまでくれば、「SW Seed Calculator」の4項目(ポケモン4匹分の個体値・性格ほか)が埋まっている状態となります。

なお、目安として、この時点でも右下の「誤Seed検出率」が「高」の場合は、素直に最初からやり直したほうが良いです(V数の少ないレイドが不十分だったり理由は色々ですが…)。

f:id:tangential_star:20210321110809g:plain
f:id:tangential_star:20210321114808p:plain
同様の手順で5日後(6日目)のポケモンの能力を入力。誤Seed検出率が「低」ならベストだ

ここでも、捕まえてからセーブしてはいけません。くれぐれも気をつけましょう。

 

12.Seed推定をしよう

ここまでお疲れ様でした。あとは「SW Seed Calculator」右下の「計算」ボタンを押すだけです。

高速なCPU・グラフィックボード(GPU)を備えているゲーミングパソコンなどであれば、「Seedを1個見つけたら終了」の条件下では1分ほどでSeed特定ができます。

再計算回数と目安となる推定計算時間はツール中に記載の通りですので、例えば、再計算5回・CPUのみでの計算をするとこれが4時間半程度かかることがわかります。とにかく、計算が終わるまでは気長に待ちましょう。

f:id:tangential_star:20210321111610g:plain

SW Seed Calculatorの画面。「計算」を押すと、個体値から巣穴初期Seedが推定される

※誤Seed検出率が高いと「Seedを1つ見つけたら計算終了」条件だと不適
※ゲーミングPC(RAM:64GB, CPU: core i9-10900X, GPU: RTX2080Ti)での等倍速録画

なお、誤Seed検出率によっては、左下の「Seedを1つ見つけたら計算終了」のチェックボックスを外しておくことが必要になります。ただし、計算時間が非常に増えるのでPCスペックと相談してください。

参考までに、筆者環境(かなりしっかりしたゲーミングPC)でチェックを入れて計算すると10秒で計算完了していましたが、チェックを外して「10回」再計算の上限設定だと7分20秒もかかりました。計算時間で見ると44倍です。

まともに考えて、GPUを積んでいないPCだと時間がかかりすぎてしょうがないので、「誤Seed検出率が低であること」を前提とした上で、再計算「0~2」とかが落とし所ではないかと思います。

さて、推定されたSeedが無事に算出できれば、初期シード推定は完了です。お疲れ様でした。なお、この推定シードが複数ある場合には、初期シードを絞り込む作業が必要です。本稿では割愛しますが、前回記事の手順2-2-1を参考にしてください。

本稿では、初期シードは0xCBC17754E4E6EA62と特定できたので、次項もその数字で紹介します。

 

13.目標消費数を特定する

初期シードが特定できたので続いて、色違いのポケモンが出る目標消費数を計算します。目標消費数の計算ツールとしては、夜鯛氏による「8denSearch」、さびたコイル氏による「1-Seed Star Search」が主要です。これらの間で機能的な差はありません。本稿では導入手順については割愛しますが、本当にお好きな方を使ってください。

初期シード特定に使ったツールがSW Seed Calculatorの場合は8denSearchを、1-Star Seed Searchを使っている場合はそのまま1-Star Seed Searchを使うことをとりあえずはおすすめします。

本稿では、初期シード特定にSW Seed Calculatorを使ったので8denSearchを利用します。とは言っても、1-Star Seed Searchでも同じことができるので、ご安心ください。

手順としては、目標消費数を特定するためのツールに、初期シード値、バージョン・巣穴情報ほか、必要事項を入力し、計算を押すだけです。画面は、下記画像を参考にしてください。

f:id:tangential_star:20210328001418p:plain
f:id:tangential_star:20210328001425p:plain
「1-Star Seed Search」も「8denSearch」も目標個体の検索ができる

目標の個体の左には、1日目(巣穴に投げ入れた日)から起算して、何日目に色違いが出現するかの消費数が記載されています。これが、十分に小さい数字であれば、その数字を手元に控えて次のステップに進みましょう。今回は、色違いの菱形・星型を特に気しないので、最も消費数が小さい「1108」を目指します。この数字は「1108日後」を表します。「1108日目」ではありません。次のステップで重要なので注意しましょう。

 

14.Arduinoのプログラムを書き込もう

次は高速消費のプログラムをArduinoに書き込みます。具体的には、前回記事のソースコード2からArduino IDEにコピペして書き込みます。

ただし、コピペして使うだけでなく、SHOHISUの数字を書き換える必要があります。先程ツールで確認した数字から-3の数字を入力してください。例えば、今回の例だと、1108なので、1105と入力します。ただし、-3だと、消費数と現在日付の関係でずれることがあるので、実際には-10程度で残りを手動でしたほうが良いと思います。

また、ソースコードの作りの甘さもあるので-10くらいでやるのが良い気もします。

このプログラムは31日まである月で使う前提なので、もしこれがクリアしていない場合は、予め2,4,6,9,11月「以外」に日付を変更しておいてください。

#define SHOHISU (1108-3) // ここを「目的消費数-3」にする。

なお、このSHOHISUの上限は「32767」となります。もし、32768以上の消費が必要な場合、2回に分けるなどの工夫が必要です。これはArduino本体の仕様です。

また、プログラムですが、私が横着して作ったプログラムだったので、消費数の内部計算が甘く、実際の消費予定数より少なく消費される仕様になっていたので、55行目を下記のように書き換えると、より消費数が正しく消費できると思います

maxlooptime =31* (SHOHISU/30) + SHOHISU%30;

本件は、私がExcelで計算して検証した数式なので、誤っている可能性もありますが、筆者は実機でこれでうまくいきました(検証回数:1回)。

これらを自己責任で書き換えていただき、ArduinoIDEでプログラムを書き込みましょう。

f:id:tangential_star:20210320222301p:plain
f:id:tangential_star:20210328004343p:plain
PCとArduinoをつないでおき、IDEにソースコードをコピペしてボードに書き込もう

 

15.ランクマバグ状態にして、Arduinoを挿し込む

さて、目当てのポケモンに向けて消費(日付を進める作業)に移る必要がありますが、まずは、一度巣穴の場所を離れて、ポケモンセンターに移動してください

その状態で、いわゆる「ランクマバグ状態」に移行してください。詳細な手順は、前の記事の手順3-1を参考にしてください。

ランクマバグ状態にしたら、Homeボタンから設定画面に入り、「日付と時刻」から日付の変更画面に入り、日付を更新せずに「OK」を押してください。

この状態でArduinoをSwitchに挿せば自動的に日付更新が始まっていきます。

f:id:tangential_star:20210320224404p:plain
f:id:tangential_star:20201123121934g:plain
事前に「OK」を押しておき、Arduinoを指すだけで日付更新(乱数消費)が始まる

 

16.巣穴に戻り、セーブして準備完了

自動作業が終わったら、前回記事の捕獲パートです。お疲れ様でした。ポケモンセンターから目的の巣穴の目の前まで戻り、セーブしましょう

f:id:tangential_star:20210328032359g:plain

乱数消費が終わったら巣穴まで戻り、セーブしよう

あとは、自身が目的の消費数-3の日付になっていることを確認し、「みんなで挑戦」から3回、日付を変更すればOKです。その際に、目的のポケモンが出たら挑戦してそのまま捕獲、違うポケモンだったらリセットして、目当てのポケモンのシルエットが出るまで3回日付を変更して挑戦を繰り返すだけです。

なお、このとき、目標のポケモンではなかった場合(色違いのはずなのに光らなかった場合)は、一度そのまま捕まえて、それがどの個体のポケモンなのか、該当する性格・個体値のポケモンが目標の個体の付近にいるかをツールで確認してください。

もし、目標のポケモンよりも手前(上側)のポケモンが出現している場合には、日付を回す回数をそのズレ分だけ実施すればOKです。なお、目標ポケモンよりも下側だったり、そもそも付近にそのポケモンが見当たらなかった場合は、手順1からやり直しとなります。前者の場合は消費が大きすぎる、後者の場合はそもそも初期シードの特定に失敗しています。めげずに確認してみましょう。

f:id:tangential_star:20210328031105p:plain
f:id:tangential_star:20210328031921g:plain
3回日付を回して、目当てのポケモンが出たら挑戦しよう

 

17.捕獲しておしまい!

目当てのポケモンに、任意のボールを投げて捕獲できれば完了です。お疲れ様でした。

f:id:tangential_star:20210328033259g:plain

色違いが捕まえられたら完了だ。お疲れ様でした

 

あとがき 

本稿では、前回記事では必要最小限に留めていた「Arduino Leonardoを乱数調整のどのタイミングで使うのか?どのタイミングでプログラムを書き込むのか?」に焦点を当てた補足記事を書きました。

基本的には最小限のプログラム書き換えで済むことや、Switchとの接続タイミングが何となくお分かりいただけたかと思います。

もし、前回の記事で「Arduinoと乱数調整が結びつかない!」となっていた人にとって、この記事が参考となれば幸いです。

 

ではではc⌒っ.ω.)っ 

 

前回記事(本補足記事の対象):

【Arduino自動化05】乱数調整レイドで色違いパッチルドン探し【冠の雪原】

次の記事:

【Arduino自動化18】ローカルレイド自動配布【デリバードレイドでマックスこうせき】

導入記事:

【Arduino自動化01】Arduino開発環境の導入

 

【Arduino自動化17】ふしぎなおくりもの受け取り【あいことば自動入力】

ますたーです。こんにちは。

今回の記事では「ふしぎなおくりもの」での『あいことば』(シリアルコード)による受け取りを自動化します。

 

Arduino自動化記事はこれで第17回。これからもよろしくお願いします。

 

なお、Arduino Leonardo自動化の導入・機材構成については導入記事を参考にしてください。

導入記事:【Arduino自動化01】Arduino開発環境の導入

※本ブログに初めてお越しの方は「本ブログについて」もぜひ、ご覧ください。

 

概要

「ふしぎなおくりもの」の「シリアルコードで受け取る」を自動で行います。

f:id:tangential_star:20210226230616g:plain
f:id:tangential_star:20210226225427p:plain
シリアルコード(あいことば)の入力から受け取りまでを全部自動で行ってくれる

f:id:tangential_star:20210226234312g:plain

幻のポケモンゲットチャレンジ」など、10個以上の『あいことば』もまとめて入力できる
(注)「幻のポケモンゲットチャレンジ」はすでに終了しています

 

では、もくじです。

今回も余談が多めなので、ソースコードだけ欲しい方は⇒読み飛ばす

 

2021年2月27日は「赤・緑」発売から25周年の「ポケモンデー」

いきなり余談をはさみますが、ポケモンの最初の作品「赤・緑」が発売されたのは、今からちょうど25年前の、1996年2月27日でした。つまり、本日2021年2月27日は「ポケモン赤・緑発売25周年」となります。おめでとうございます!!

実は、昨年2020年には、株式会社ポケモンにより、2月27日を「ポケモンデー」として、記念日として制定(日本記念日協会が認定)されています。つまりは、今年の2月27日は発売25周年「ポケモンデー」となるわけですね。

f:id:tangential_star:20210226232259j:plain
f:id:tangential_star:20210226232303j:plain
「Pokémon Day」のロゴとポケモン一般社団法人 日本記念日協会のHPより引用)

 

「うたうを覚えたピカチュウ」を受け取ろう

明日2021年2月28日(日)には、ポケモン25周年を記念したバーチャルコンサートが開催されます。これを記念して、2021年2月27日現在、ポケモン剣盾では、「うたう」を覚えた特別なピカチュウがプレゼントされています(期日:3月25日(木)23時59分まで)。

f:id:tangential_star:20210226233517j:plain
f:id:tangential_star:20210226233513j:plain
Post Malone氏によるポケモン25周年記念コンサートの開催案内と、配信されるピカチュウ
ポケモン公式サイトの記事(2021.2.19掲載)より画像引用)
f:id:tangential_star:20210227000103p:plain
f:id:tangential_star:20210227000107p:plain
「うたう」を覚えていて、夢特性ひらいしん」のピカチュウ

プレゼント方法は、剣盾「ふしぎなおくりもの」の「あいことば」を使った配信です。

ちなみに、今回のピカチュウを受け取るための「あいことば」は「P25MUS1C」です。まさに「ポケモン25周年コンサート」を表すあいことばですね。

 

準備(プログラムの使い方など)

ここからが本題です。

「あいことば」をプログラムに書き込もう

今回のArduino自動化では、「あいことば」の入力から受け取りまでを自動で行います。入力する『あいことば』を予め準備しておきましょう。

プログラム上では、serial_code[][32]に書き込みます。

具体的には、今回のあいことばが「P25MUS1C」なので、これを半角のダブルクオートで囲み、最後に半角のカンマをつけて記入してください(例⇒ "P25MUS1C", )。「"P25M US1C",」のように、区切りの半角スペースを挟んでもしっかり動きます。

char serial_code[][32] = {
   "P25MUS1C", // ポケモン25周年記念ピカチュウのコマンド
    "" // ←この行は残してください(ループの判定に使うため)
};

余談ですが、剣盾のキーボードでは「Z(ゼット)」「I(アイ)」「O(オー)」はそれぞれ数字の「2」「1」「0」と間違えやすいため使われません。

このプログラムでは上記表記ミスにも対応できるように作ったつもりです。例えば、誤って「P25 MUSIC」などと記入しても動くはずなので、各人が読みやすい方法で記入してください。

f:id:tangential_star:20210227011924g:plain

プログラムに書き込むことで、「P25MUS1C」の入力が自動で行える

ちなみに、キャンペーンによっては、1つのキャンペーン中に複数(10程度)の『あいことば』が発行される場合があります(例えば、いずれもすでに期間は終了していますが「幻のポケモンゲットチャレンジ」「サトピカゲットキャンペーン」など)。このプログラムでは複数の「あいことば」の入力にも対応可能ですので、『あいことば』を複数serial_code[][32]の中に記入することで全部続けて入力できます。

 

// 例:「サトピカゲットキャンペーン」の『あいことば』
char
serial_code[][32] = { "P1KACHUGET", "P1KAADVANCE", "V0LTTACKLEP1KA", "P1KABESTW1SH", "KAL0SP1KA", "ULTRAP1KA", "K1NP1KA1855", "1CH00SEY0U", "" // ←この行は残してください(ループの判定に使うため) };

1つのシリアルならいざ知らず、複数のシリアルコード(あいことば)を入力する場合には、特にサブロムを持っている人などは重宝すると思います。

YY通信でオンライン接続し、カーソルを「ふしぎなおくりもの」に合わせる

次に、ゲーム本編での準備ですが、まず、YY通信で「インターネットに接続」をしてください。フィールド画面でYボタン⇒+ボタンで接続できるはずです。そして、Xボタンでメニューを開いた時に「ふしぎなおくりもの」にカーソルが合うようにしたら、Bを押してフィールド画面にもどってください。以上、わずか2ステップで準備完了です。

あとは、フィールド画面でArduinoを挿すだけ。簡単ですね。

f:id:tangential_star:20210227011003p:plain
f:id:tangential_star:20210227011009p:plain
準備は「インターネット接続」「カーソルを『ふしぎなおくりもの』に合わせる」だけ

 

ソースコード

プログラムにはポケモン25周年コンサート記念の「うたうピカチュウ」のシリアルコード(P25MUS1C)が入力されています。必要に応じて書き換えて使用ください。

なお、予めインターネットに接続した状態で、メニュー開いた際に「ふしぎなおくりもの」にカーソルが合う状態で、Arduinoを挿すだけで動きます。

 

/* 
 *  自動でふしぎなおくりもののシリアルコードを入力して受け取ってくれるやつ。
 *  
 *  Xボタンでメニューを開いた時に「ふしぎなおくりもの」にカーソルが合うこと。
 *  YY通信がオンラインになっている状態(予めインターネット接続するため)でArduino差し込むだけ!
 *  (c) 2021 ますたーの忘備録
 *  https://tangential-star.hatenablog.jp/
*/

#include <SwitchControlLibrary.h>

#define HOLDTIME (95) // 1回のキー入力の長押し時間

// ★ここに受け取りたい文字列を入力(半角・ダブルクオートで囲み、最後は半角カンマ,で改行)
char serial_code[][32] = {
   "P25MUS1C", // ポケモン25周年記念ピカチュウのコマンド
    "" // ←この行は残してください(ループの判定に使うため)
};


void PushRL(int delay_time_ms);
int PushKey(char* keyname, int holdtime, int delaytime);
void NextDayInCheatMode(void);

void input_serial(char*);

void setup() {
  // コントローラーとして認識されるためにRLを7回ほどカチャカチャする
  for(int i=0;i<7;i++)PushRL(300);
  delay(1000);
}

void loop() {
  int i=0;
  PushKey("X", HOLDTIME, 500);  // メニューを開いて
  PushKey("A", HOLDTIME, 1500); // ふしぎなおくりものを選択
  PushKey("A", HOLDTIME, 500);  // ふしぎなおくりものを受け取る

  // シリアルコード列が終わるまで受け取り続ける
  for(i=0; strcmp(serial_code[i],"") != 0 ;i++){
    
    PushKey("down", HOLDTIME, 120);
    PushKey("down", HOLDTIME, 120);
    PushKey("A", HOLDTIME, 1100);  // 警告画面が出る
    PushKey("A", HOLDTIME, 1500);  // Aを押さないと進まない

    // キーボード起動
    input_serial(serial_code[i]);  // シリアルを入力

    PushKey("+", HOLDTIME, 7000);  // +で確定⇒ギフトを探しています…

    PushKey("A", HOLDTIME, 5000);  // Aで受け取り⇒本当は21秒待機

    // 失敗した場合のケア(もう一度入力しますか?)
    PushKey("Down", HOLDTIME, 16000);

    PushKey("A", HOLDTIME, 1000);    // ▼
    
  }

  PushKey("B", HOLDTIME, 500);  
  PushKey("B", HOLDTIME, 500);  
  PushKey("B", HOLDTIME, 500);  
  PushKey("B", HOLDTIME, 500);  
  PushKey("B", HOLDTIME, 500);  
  for(;;) delay(100); // プログラム終了

}

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){
  // ホームボタン・方向キーはRight, Left, Up, Down, Homeなど2文字以上で入力。
  // その他ボタン入力は1文字(A,B,X,Y,R,L,+,-)ZR・ZLにも対応
  // 同時押しは非対応
  
  if(strlen(keyname)==1){
    switch(keyname[0]){
      case 'A': case 'a': // A
        SwitchControlLibrary().PressButtonA(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonA(); delay(delaytime);
      break;
      case 'B': case 'b': // B
        SwitchControlLibrary().PressButtonB(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonB(); delay(delaytime);
      break;
      case 'X': case 'x': // X
        SwitchControlLibrary().PressButtonX(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonX(); delay(delaytime);
      break;
      case 'Y': case 'y': // Y
        SwitchControlLibrary().PressButtonY(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonY(); delay(delaytime);
      break;
      case 'L': case 'l': // L
        SwitchControlLibrary().PressButtonL(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonL(); delay(delaytime);
      break;
      case 'R': case 'r': // R
        SwitchControlLibrary().PressButtonR(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonR(); delay(delaytime);
      break;
      case 'H': case 'h': // Home
        SwitchControlLibrary().PressButtonHome(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonHome(); delay(delaytime);
      break;
      case '+': case 'p': case 'P': // Plus
        SwitchControlLibrary().PressButtonPlus(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonPlus(); delay(delaytime);
      break;
      case '-': case 'm': case 'M': // Minus
        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': // ZR/ZL
        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': // right
        SwitchControlLibrary().MoveHat(2); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().MoveHat(8); delay(delaytime);
      break;
      case 'l': case 'L': // left
        SwitchControlLibrary().MoveHat(6); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().MoveHat(8); delay(delaytime);
      break;
      case 'u': case 'U': // up
        SwitchControlLibrary().MoveHat(0); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().MoveHat(8); delay(delaytime);
      break;
      case 'd': case 'D': // down
        SwitchControlLibrary().MoveHat(4); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().MoveHat(8); delay(delaytime);
      break;
      case 'H': case 'h': // Home
        SwitchControlLibrary().PressButtonHome(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonHome(); delay(delaytime);
      default:
      break;  
    }
  }else{
    return -1;
  }
  return strlen(keyname);
}
void NextDayInCheatMode(){
  // ★日付変更
  // Homeボタンを押して設定の画面へ移動
  PushKey("Home", HOLDTIME, 1000);

  // Home画面で「設定」を選ぶ
  PushKey("down", HOLDTIME, 105);
  PushKey("right", HOLDTIME, 105);
  PushKey("right", HOLDTIME, 105);
  PushKey("right", HOLDTIME, 105);
  PushKey("right", HOLDTIME, 105);
  PushKey("right", HOLDTIME, 105);
  PushKey("A", HOLDTIME, 1500);

  // 設定画面で「日付と時刻」を開く
  PushKey("down", 1500, 105); // 1.5秒「↓」長押し
  PushKey("right", HOLDTIME, 105); 

  for(int i=0; i<4; i++){
    PushKey("down", HOLDTIME, 55);
  }
  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);
  PushKey("A", HOLDTIME, 1000);
  return;
}

void input_serial(char *str){
  char keyboard[4][15]={
    "1234567890@",
    "QWERTYUIOP=",
    "ASDFGHJKL&;",
    "ZXCVBNM*#!?"
  };
  int cur_x=0, cur_y=0; // 現在カーソル位置
  int x,y; // 目標キーボード位置
  int i=0;
  char *p;

  // ★すべて大文字に変換
  toupper(str);

  // ★剣盾のキーボードはZ,I,Oは不使用(それぞれ2,1,0に置き換え)
  for(i=0; str[i]!='\0' ;i++ ){
    switch(str[i]){
      case 'Z':
        str[i]= '2';
        break;
      case 'I':
        str[i]= '1';
        break;
      case 'O':
        str[i]= '0';
        break;
      default:
        break;
    }
  } 

  // ★入力する文字列strを1文字ずつ処理
  for(i=0; str[i] != '\0' ; i++ ){

    // 空白文字は読み飛ばし(例:"P25M US1"みたいなやつ)
    if(str[i] == ' ' ) continue;

    // キーボードから該当文字を検索(x,yを決定)
    for(x=0; x < 4 ; x++){
       p = strchr(keyboard[x], str[i]);
       if( p == NULL){ continue;
       }else{
         for(y=0; keyboard[x][y] != *p ; y++);
         break;
       }
    }
    delay(100);
    // y(左右位置)
    if(cur_y != y){
      for( ; cur_y < y ; cur_y++) PushKey("Right", HOLDTIME, 150);
      for( ; cur_y > y ; cur_y--) PushKey("Left", HOLDTIME, 150);
    }
    // x(上下位置)
    if(cur_x != x){
      for( ; cur_x < x ; cur_x++) PushKey("DOWN", HOLDTIME, 150);
      for( ; cur_x > x ; cur_x--) PushKey("UP", HOLDTIME, 150);
    }
    // 入力
    PushKey("A", HOLDTIME, 150);
  }
  

  return;
}

f:id:tangential_star:20210227012752g:plain

動作確認(再掲)。自動でふしぎなおくりものを開き、受け取ってくれる


あとがき

今回は、ポケモン25周年ということで、記念して配布されている「うたうを覚えた特別なピカチュウ」をArduinoで受け取りました。

Arduino自動化の記事と言いつつ、まずはポケモンのファンとして、心の底から25周年をお祝いします

自身が初めて出会ったポケモン作品が「金・銀」で、そこから遡る形で「赤・緑」も遊び、今に至るまでにポケモン本編作品についてはほぼすべてを遊んできました。どの作品にも思い入れがありますが、これだけシリーズを通してのめり込めたゲームは「ポケモン」だけです。自分の人生はポケモンとともにあった、と言っても過言で無い気もします。

そして、その遊び方も、「図鑑集め」「コンテスト制覇」「リボン集め」「育成・対戦」「ポケモンとの触れ合い」「色違い厳選」など、ずっと飽きることなく、たくさん広がりました。そして、ポケモン剣盾では、新たな遊び方として「Arduino自動化」が加わったような形です。

私にとってポケモンは、かけがえの無いゲームで、遊びごたえもキャラクタ性も、シナリオも全部が全部、大好きなのです。この25周年という節目の日に、こうやってブログで気持ちをしたためることができるのも、本当に光栄ですし、これからのポケモンの作品も楽しみで仕方がありません。

そういう意味では、ちょうど今日未明に新作「ブリリアントダイヤモンド」「シャイニングパール」のティザームービーも公開されましたが、今から発売日(2021年冬)が待ち遠しくてしょうがないです。25年分のワクワク、しっかりと温めておきたいです。

なにはともあれ、改めてポケモン25周年、おめでとうございます。

 

さて、話がだいぶ逸れました。

皆様のポケモンライフが、あるいはArduino自動化ライフが、このブログにより一助となれば幸いです。ではではc⌒っ.ω.)っ

 

前記事:【Arduino自動化16】自動ミラクル交換(ID集めほか)

導入記事:【Arduino自動化01】Arduino開発環境の導入

 

【Arduino自動化16】自動ミラクル交換(ID集めほか)

ますたーです。こんにちは。

今回は、自動でボックスのポケモンをマジカル交換(旧:ミラクル交換)に出し続けます。

※本記事ではポケモンを「交換に出します」。利用に際してはくれぐれも自己責任でお願いします

 Arduino自動化記事はこれで第16回。これからもよろしくお願いします。

 

なお、Arduino Leonardo自動化の導入・機材構成については導入記事を参考にしてください。

導入記事:【Arduino自動化01】Arduino開発環境の導入

※本ブログに初めてお越しの方は「本ブログについて」もぜひ、ご覧ください。

 

概要

本記事では、YY通信のマジカル交換(旧:ミラクル交換)を自動で繰り返し行います。「孵化余り」の有効活用や、ロトミIDくじ用のID集めなどにお役立てください。

※2021年2月19日AM9時追記:本稿中の「ミラクル交換」はすべて「マジカル交換」の誤りです。過去作品に引っ張られました。以降、適宜読み替えてください

f:id:tangential_star:20210213121954g:plain
f:id:tangential_star:20210213121616p:plain
マジカル交換(ミラクル交換)を自動で行う。待機時間など含め1回あたり約2分20秒ほど

では、目次です。

ソースコードのみ欲しいという方はどうぞコチラから⇒読み飛ばす

 

ラクル交換でID集め(ロトミIDくじを効率的に)

ラクル交換の大きな特徴は、何よりも交換先が全国不特定多数のポケモントレーナーであることです。ポケモン剣盾での「おやID」は6桁なので、32ボックス960匹をランダムに交換し続けたとしても、これらの間で重複が起こる可能性はほぼ0です

※無作為の960匹について、これらでIDが重複する確率は単純計算で 1-(1-1/106)960=0.09595%

おやIDをたくさん集めることで、ロトミIDくじの当選確率もアップします。例えば、50種類のおやIDを入手しておくと「はずれ」が出る確率が1%を下回ったり、100種類のおやIDがあれば50%以上の確率で「ポイントアップ」が手に入るようになったりと、非常にお得です。【Arduino自動化14】ロトミIDくじ無限抽選では、このあたりの、IDの数と当選確率の話も纏めているので、合わせてご参考いただければと思います。

f:id:tangential_star:20210204135040g:plain
f:id:tangential_star:20210203180947p:plain
たくさんのIDがあれば、ロトミIDくじ当選確率もアップ!

要するに、ミラクル交換で他人産IDのポケモンを50匹程度を集めておけば、ロトミIDくじが、まさにソシャゲの「ログインボーナス」のようになるのでおすすめです。

ほとんど毎日「ポイントアップ」が貰えて、時々「ポイントマックス」が貰えるとなれば、毎日のポケモンのモチベーションが大きく上がりますよね。

 

他人の孵化余りも手に入る

ラクル交換のもう一つの魅力、それは、孵化余りを流すプレイヤーも多いということ。私も含め、孵化余りは積極的にGTSポケモンHOMEでの交換、ミラクル交換に出していますが、ID集めはもちろん、これは何よりも他人の孵化余りを手に入れられるから。

現在、環境で流行っているポケモンの孵化余りが手に入ったり、有用なタマゴわざを持ったポケモンうたかたのアリア持ちラプラス、じばく持ちゴンベなど)などが手に入りやすく、対戦ガチ勢にも嬉しい仕様ですね。

f:id:tangential_star:20210218224023p:plain
f:id:tangential_star:20210218224028p:plain
有用なタマゴわざを覚えていたり、希少価値の高いオシャボに入っていたりも多い

つまりは、個体値ポケモン夢特性ポケモンタマゴわざを持っているポケモンおしゃれボールに入ったポケモンなどを手に入れることもできます。特に海外産ポケモンも手に入りやすく、これらを活用するとタマゴ孵化による色違い厳選もはかどります

ちなみに、全自動タマゴ孵化については本ブログでも取り扱っています。合わせてご参考いただければ幸いです⇒【Arduino自動化12】全自動タマゴ受け取り&孵化

 

準備(プログラムの書き換え)

ラクル交換をたくさん行うにあたっては、大量のポケモン準備する必要があります。また、効率的に通信交換をするためにも、図鑑は完成させておくと良いでしょう。

さて、本稿で扱う自動化プログラムについても、必要に応じて4箇所書き換える必要があります。

通信交換するポケモンの数

1箇所目は、何匹のポケモンを交換に出すかです。MAX_TRADE_POKEMONにて指定してください。必ずしも30の倍数である必要はありませんが、左詰めにあずけておいてください。

#define MAX_TRADE_POKEMON (30*3-5)
// ★何匹通信交換するか?【重要】

ラクル交換の待ち時間

2箇所目は、ミラクル交換の待機時間です。具体的には、YY通信で「ミラクル交換」を選んでフィールドに戻ってから「交換完了!」の文字が出るまでの待機時間です。

概ね30秒あればマッチングすることが多いですが、時々マッチングに時間がかかり、50秒ほどかかることもあります。皆様の環境に合わせて数字を記入してください。

数字は、WAIT_TIME_FOR_MATCHINGに単位「秒」で記入してください。

#define WAIT_TIME_FOR_MATCHING (45) 
// ★通信交換を何秒待つか?(単位:秒)

なお、この時間指定が短すぎると、その次のループでうまく交換ができませんので注意しましょう。45秒で設定した筆者実証時には、85回の交換中3回、45秒以内での通信交換に失敗しています。もし、時間に余裕のある人は、60秒などの充分に大きな数字を設定しておくと良いかもしれません。

図鑑の状況と通信進化ポケモン

3箇所目・4箇所目は、ポケモン図鑑の完成状況(新たに登録される可能性があるかどうか)と、受け取ったポケモンが進化する可能性を考慮するかどうかです。これらは数字ではなく、trueまたはfalseを記入します。

ポケモン図鑑が完成している場合はPOKEDEX_COMPLETEDにtrueを指定してください。また、通信交換で進化するポケモンを無視する場合はIGNORE_EVOLVEをtrueにしてください。デフォルトでは、ポケモン図鑑は完成済(true)・通信進化ポケモンは無視しない(false)になっています。

 

#define POKEDEX_COMPLETED (true) 
// ★ポケモン図鑑は完成済か?【重要】

 

#define IGNORE_EVOLVE (false)
// ★通信進化ポケモンは来ない前提とするか?【重要】

 

ポケモン図鑑に登録されていないポケモンを交換で受け取った場合、その図鑑説明の画面が出てきます。こちらは、たかだか5秒程度のロスなので、図鑑完成していない人も、あまり気にならないかもしれません。

一方で、バケッチャパンプジンに進化)などの通信進化するポケモンを受け取った場合、そのポケモンの進化画面が発生してしまいます。この進化ポケモン、数は20数匹と多めで、意外と受け取る機会が多いです。

通信進化は長くて20秒は時間を取られるので、よほど受け取らない自信が無い限りは、IGNORE_EVOLVEをfalseにしておきましょう。

特に、稀有な機会ではありますが、メタルコート持ちストライクの場合、進化時に「バレットパンチ」を覚えようとするため、そういうところもケアする必要があります。

f:id:tangential_star:20210218233952g:plain

バケッチャなど、通信交換で進化するポケモンを受け取る機会は意外と多い。注意しよう

 

実際に自動化ミラクル交換を試してみた

早速、85匹のパッチルドンを用意して、ミラクル交換のArduino自動化を実装&試してみました。

 

f:id:tangential_star:20210218234741g:plain
f:id:tangential_star:20210218234922g:plain
85匹のパッチルドンでミラクル交換!所要時間3時間20分の大半は待ち時間だ

設定は1試行あたり45秒の待機時間ポケモン図鑑は完成済、進化ポケモンは無視しない想定で、かかった時間は約3時間20分でした。1回の交換にかかる時間を平均すると約2分20秒となります。

なお、特筆すべき点として、待機時間を45秒に設定で、85回の通信交換中、3回はこの時間内に通信交換が成立せず、それぞれの翌試行分の交換が失敗しています。ゆえに、通信交換に成功したのは82匹です(いずれの試行も、通信交換に失敗した次の試行でループが復帰していました)。一応、これを避けるためには、待機時間を冗長に設定する他はありません。体感としては、60秒ほどあれば通信交換がほぼ成立すると考えます。

ちなみに、82匹の交換が成立したわけですが、そのうち1回のみ、通信交換するポケモンバケッチャ)を受け取っています。約80回に1回(確率にすれば約1.25%)ですし、もし「全体的に時間効率を高めたい」という人は、IGNORE_EVOLVEを(true)にしても良いかもしれません。

f:id:tangential_star:20210218234725g:plain

ラクル交換後のボックス。オシャボ入が7匹、準伝説3匹など上々の結果

 

ソースコード

さて、実際に使ったソースコードです。

使い方は簡単。ボックスを左詰めにした後、ポケモン剣盾をインターネット接続し、Arduinoを挿し込むだけ。

ただし、前述の通り、4箇所は各人のステータスに応じて書き換えてください。

/* 
 *  マジカル交換自動化
 *  
 *  ボックスは交換を始める先頭&左詰めにしておくこと。
 *  野生ポケモンが近くに発生しない環境で使うこと!
 *  (重くならない、ワイルドエリア「外」+オブジェクトが少ない場所を推奨)⇒シュートシティのタワー前とか?
 *  あとはYY通信がオンラインになっている状態でArduino差し込むだけ!
 *  (c) 2021 ますたーの忘備録
 *  https://tangential-star.hatenablog.jp/
*/

#include <SwitchControlLibrary.h>

#define HOLDTIME (95) // 1回のキー入力の長押し時間


// 実測値メモ 45秒指定で、85匹交換=合計3時間14分45秒[1試行平均137秒]
// [うち、交換失敗3回・改造と思しき個体3匹]

#define MAX_TRADE_POKEMON (30*3-5)
// ★何匹通信交換するか?【重要】
// ボックスの中で交換するポケモンの数を入れましょう。
// ※無論、ボックスの中身は左詰めでお願いします。

#define WAIT_TIME_FOR_MATCHING (45) 
// ★通信交換を何秒待つか?(単位:秒)
// 実際の待ち時間が上記指定時間をを超えた場合など、短すぎるとずれる可能性あり。
// 2順目でズレを吸収し、3順目から正式に進行するはずだが、この事象が発生したタイミング
// 如何によってはボックスの遷移が正しく行われない可能性あり。
// ※時間に余裕がある場合は、確実に交換できるよう「充分に長い時間(75など)」にしておくと安心。
// 特に深夜帯25:30を回ると45では心許なくなる。

#define POKEDEX_COMPLETED (true) 
// ★ポケモン図鑑は完成済か?【重要】
// 完成済の人は「true」にしてください
// 新規ポケモン受取時に図鑑登録ダイアログ出現を考慮するかどうかです。
// ※未完成の挙動は筆者未検証です!(そのへんの動画見て時間合わせしてるので動かないかも)

#define IGNORE_EVOLVE (false)
// ★通信進化ポケモンは来ない前提とするか?【重要】
// 進化後のポケモン例:フーディン・カイリキー・ゲンガー・ヤドキング・ニョロトノ・ハガネール・ハッサム・
// キングドラ・ポリゴン2・ミロカロス・ポリゴンZ・ドサイドン・エレキブル・ブーバーン・ヨノワール・
// ギガイアス・ローブシン・フレフワン・ペロリーム・オーロット・パンプジン・シュバルゴ・アギルダー
// ※コイツら↑を受け取らない前提なら「true」にしてください(非推奨)
// ※参考までに、筆者は本デバッグ中にバケッチャを受け取りました(パンプジンに進化しました)。わずか33試行目でした。


void PushRL(int delay_time_ms);
int PushKey(char* keyname, int holdtime, int delaytime);
void NextDayInCheatMode(void);

void YYconnection_start(int which_pokemon);
void YYconnection_receive(void);

void setup() {
  // コントローラーとして認識されるためにRLを7回ほどカチャカチャする
  for(int i=0;i<7;i++)PushRL(300);
  delay(1000);
}


void loop() {
  int num_pokemon; // 規定回数入れ替えたら
  for(num_pokemon=1; num_pokemon <= MAX_TRADE_POKEMON ; num_pokemon++){
    YYconnection_start(num_pokemon);
    delay( (unsigned long int)WAIT_TIME_FOR_MATCHING*1000UL );
    YYconnection_receive();
  }
  for(;;) delay(100); // プログラム終了
}

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){
  // ホームボタン・方向キーはRight, Left, Up, Down, Homeなど2文字以上で入力。
  // その他ボタン入力は1文字(A,B,X,Y,R,L,+,-)ZR・ZLにも対応
  // 同時押しは非対応
  
  if(strlen(keyname)==1){
    switch(keyname[0]){
      case 'A': case 'a': // A
        SwitchControlLibrary().PressButtonA(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonA(); delay(delaytime);
      break;
      case 'B': case 'b': // B
        SwitchControlLibrary().PressButtonB(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonB(); delay(delaytime);
      break;
      case 'X': case 'x': // X
        SwitchControlLibrary().PressButtonX(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonX(); delay(delaytime);
      break;
      case 'Y': case 'y': // Y
        SwitchControlLibrary().PressButtonY(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonY(); delay(delaytime);
      break;
      case 'L': case 'l': // L
        SwitchControlLibrary().PressButtonL(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonL(); delay(delaytime);
      break;
      case 'R': case 'r': // R
        SwitchControlLibrary().PressButtonR(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonR(); delay(delaytime);
      break;
      case 'H': case 'h': // Home
        SwitchControlLibrary().PressButtonHome(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonHome(); delay(delaytime);
      break;
      case '+': case 'p': case 'P': // Plus
        SwitchControlLibrary().PressButtonPlus(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonPlus(); delay(delaytime);
      break;
      case '-': case 'm': case 'M': // Minus
        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': // ZR/ZL
        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': // right
        SwitchControlLibrary().MoveHat(2); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().MoveHat(8); delay(delaytime);
      break;
      case 'l': case 'L': // left
        SwitchControlLibrary().MoveHat(6); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().MoveHat(8); delay(delaytime);
      break;
      case 'u': case 'U': // up
        SwitchControlLibrary().MoveHat(0); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().MoveHat(8); delay(delaytime);
      break;
      case 'd': case 'D': // down
        SwitchControlLibrary().MoveHat(4); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().MoveHat(8); delay(delaytime);
      break;
      case 'H': case 'h': // Home
        SwitchControlLibrary().PressButtonHome(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonHome(); delay(delaytime);
      default:
      break;  
    }
  }else{
    return -1;
  }
  return strlen(keyname);
}
void NextDayInCheatMode(){
  // ★日付変更
  // Homeボタンを押して設定の画面へ移動
  PushKey("Home", HOLDTIME, 1000);

  // Home画面で「設定」を選ぶ
  PushKey("down", HOLDTIME, 105);
  PushKey("right", HOLDTIME, 105);
  PushKey("right", HOLDTIME, 105);
  PushKey("right", HOLDTIME, 105);
  PushKey("right", HOLDTIME, 105);
  PushKey("right", HOLDTIME, 105);
  PushKey("A", HOLDTIME, 1500);

  // 設定画面で「日付と時刻」を開く
  PushKey("down", 1500, 105); // 1.5秒「↓」長押し
  PushKey("right", HOLDTIME, 105); 

  for(int i=0; i<4; i++){
    PushKey("down", HOLDTIME, 55);
  }
  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);
  PushKey("A", HOLDTIME, 1000);
  return;
}

void YYconnection_start(int which_pokemon){
  // (注)which_pokemonはボックスの何匹目を交換に出すか?
  // 1 <= which_pokemon <= 30 (0<29ではないので注意)

  static int shift_box = 0; // ボックスで「R(次のボックスに変える)」を押すタイミング見計らい
  
  PushKey("Y", HOLDTIME, 1300);
  PushKey("Down", HOLDTIME, 700);
  PushKey("A", HOLDTIME, 2700);

  int col=0, row=0;
  col = (which_pokemon -1) % 6; 
  row = ((which_pokemon -1)%30) / 6;

  // 31匹目以降は必要に応じてRキーで次のボックスを参照する
  if((which_pokemon -1) / 30 == 1+shift_box){
    PushKey("R", HOLDTIME, 1600);
    shift_box++;
  }

  for(int i = 0 ; i < col ; i++ ){
    PushKey("Right", HOLDTIME, 170);
  }
  for(int i = 0 ; i < row ; i++ ){
    PushKey("Down", HOLDTIME, 170);
  }
  PushKey("A", HOLDTIME, 700);  // ○○を どうしますか?
  PushKey("A", HOLDTIME, 6000); // ⇒えらぶ ~ レポートを書いて マジカル交換を 始めても よろしいですか?
  PushKey("A", HOLDTIME, 900);  // ⇒はじめる ~ 通信できる 人を 探します! ▼
  PushKey("B", HOLDTIME, 900);  // 通信する 項目を 選ぶと 探すのを キャンセルできます ▼
  PushKey("B", HOLDTIME, 3000); // レポートをかいています。
  
  return;  
}
void YYconnection_receive(void){
  delay(100);
  PushKey("Y", HOLDTIME, 1300);
  PushKey("B", HOLDTIME, 1000); // ループ破綻防止用(想定待ち時間を超えて受け取り損ねた場合のケア)
  PushKey("B", HOLDTIME, 1000); // 予備

  // 通信交換(27秒待つ)
  delay(27*1000UL);

  // 通信進化ポケモン受取時のループ破綻防止   
  if(!IGNORE_EVOLVE){
    delay(6*1000UL); // 暗転画面で6秒
    delay(7*1000UL); // 鳴き声含め5秒
    PushKey("A", HOLDTIME, 13000); // ……おや!? ○○の 様子が……! ▼ 
    PushKey("A", HOLDTIME, 3500);  // おめでとう! ○○は ○○に 進化した!▼

    // 進化時にわざを覚えるポケモン(ハッサム=バレットパンチなど)対応
    PushKey("B", HOLDTIME, 1100);    // ○○は 新しく ○○を 覚えたい…… ▼
    PushKey("Down", HOLDTIME, 1100); // ○○の かわりに 他の 技を 忘れさせますか?
    PushKey("A", HOLDTIME, 1400);    // ⇒忘れさせない
    PushKey("B", HOLDTIME, 3000);    // ○○は ○○を 覚えずに 終わった! ▼
    
    delay(4*1000UL); // 暗転終了後、明転して次画面に
  }
  PushKey("B", HOLDTIME, 300); // 予備
  PushKey("B", HOLDTIME, 300); // 予備
  PushKey("B", HOLDTIME, 300); // 予備
  delay(2*1000UL); // 予備
  if(POKEDEX_COMPLETED) return; // ポケモン図鑑完成済なら以降のダイアログ出現なし

  PushKey("B", HOLDTIME, 1000); // ○○の データが 新しく ポケモン図鑑に 登録されます!▼
  PushKey("B", HOLDTIME, 2000);
  if(!IGNORE_EVOLVE){ // 進化ポケモンも未登録の場合
    PushKey("B", HOLDTIME, 3000);
    PushKey("B", HOLDTIME, 1000); // ○○の データが 新しく ポケモン図鑑に 登録されます!▼
    PushKey("B", HOLDTIME, 2000);
  }
  PushKey("B", HOLDTIME, 300); // 予備

  return;
}

 

あとがき 

今回は16回目のArduino自動化記事として、ミラクル交換の自動化を紹介しました。

自分で実装してみて、思った以上にデバッグが大変だと思いました。長時間放置することが前提のプログラムゆえに、挙動を見守るのが大変で、コーディングをする時間よりも、本当に動くのか?を見守る時間のほうが10倍くらい長かった気がします。

私の本職は、プログラマでもデバッガーでもSEでも無いですが、本当にデバッグという作業は心がポキっと行くんだろうな、と漠然と感じました。

 

さて、話が逸れましたね。

今回のミラクル交換の実装により、今まで作ったプログラムが更に相互に利用しやすくなったな、と感じます。

具体的には、下記のようなサイクルでポケモンを遊び続けられるなぁと。

  1. 【Arduino自動化12】全自動タマゴ受け取り&孵化で色違い厳選など
  2. タマゴ孵化を経て、余ったポケモンたちを他人産ポケモンと交換(本稿)
  3. 集まったIDを使って【Arduino自動化14】ロトミIDくじ無限抽選
  4. 抽選後、不要なポケモン【Arduino自動化13】全自動ポケモン逃がしでリリース
  5. オシャボや海外産ポケモンを活用し、タマゴ孵化厳選へ(1に戻る)

ほかにも、育成用アイテムは例えば【Arduino自動化11】5番道路で全自動羽集めなどで端数の努力値振りも対応できますし、「とくせいパッチ」などは【Arduino自動化06】完全放置「マックスこうせき」集め【ダイマックスアドベンチャー】で手に入れられるんですよね。

そういう意味で、Arduinoの自動化は、ポケモンの遊び方を深めることも、作業の代替もできるんだな、と改めて感じました。

 

皆様においても、このブログの記事ほかがお役立ていただければ幸いです。

 

ではではc⌒っ.ω.)っ

 

前記事:【Arduino自動化15】ラテラルタウン掘り出し物自動購入

次記事:【Arduino自動化17】ふしぎなおくりもの受け取り【あいことば自動入力】

導入記事:【Arduino自動化01】Arduino開発環境の導入 

 

【Arduino自動化15】ラテラルタウン掘り出し物自動購入

ますたーです。こんにちは。

今回は、いわゆるランクマバグ状態で「掘り出し物」を買い続ける自動化記事です。

第15回目のArduino自動化記事。引き続きよろしくお願いします。

 

なお、Arduino Leonardo自動化の導入・機材構成については導入記事を参考にしてください。

導入記事:【Arduino自動化01】Arduino開発環境の導入

※本ブログに初めてお越しの方は「本ブログについて」もぜひ、ご覧ください。

 

概要

本記事では、ランクマバグ状態による自動「ほりだしもの」購入を実装します。
※便宜上「ランクマバグ」と表記しますが、当ブログではランクマッチを使用しません。通信切断・初手降参の推奨もしません。

 

NintendoSwitch Ver.11.0アップデート対応済です。

f:id:tangential_star:20210211120145g:plain
f:id:tangential_star:20210211120226p:plain
ほりだしもの市で自動購入。「ぼうごパット」はここでしか手に入らない超レアアイテム

 

では、目次です。

相変わらず余談多めですので、ソースコードだけ欲しいという方は⇒読み飛ばす

 

ほりだしもの市でしか手に入らない「ぼうごパット」

余談を挟む余地もなく、最初に結論から話します。なぜ掘り出し物市を自動化するのか、その理由は、ここでしか買えないアイテム「ぼうごパット」があるからです。

また、ここでの入手が現実的なアイテムも複数あるのも魅力ですね。

f:id:tangential_star:20210211125124p:plain
f:id:tangential_star:20210211125118p:plain
「ぼうごパット」の他、野生のワンリキーがたまに(5%)持っている「きあいのハチマキ」なども買える

ここからはすこしだけ、余談をはさみます。

「『ぼうごパット』についてはいい、他のアイテムは何が手に入るんだ」という方は⇒読み飛ばす

どうぐ「ぼうごパット」の希少性

ガラル地方では本編(DLC含まず)において入手が困難なアイテムがいくつかあります。その中の筆頭として挙がるのはおそらく、「かえんだま」と「どくどくだま」※1、「マスターボール※2」「各種ガンテツボール※3」などでしょうか。なぜかは言わずもがな、これらは原則として「運」でしか手に入らないからです。

※1「かえんだま」「どくどくだま」はDLC・配布を除くと、トーナメントでの勝利報酬でしか入手できません
※2「マスターボール」はシナリオ内で1個+IDくじの特等で入手できます
※3「各種ガンテツボール」はシナリオ内で各1個+トーナメントでの勝利報酬で入手できます

さて、前述の通り「ぼうごパット」は、ラテラルタウンの「ほりだしもの市」でしか入手できない貴重なアイテムです。

しかも、上記「かえんだま」「どくどくだま」「ガンテツボール」などとは違い、剣盾発売から1年以上経った2021年2月11日現在において1度たりとも配布されたりレイド報酬になったりしたことがない「正真正銘」ここでしか手に入らないアイテムです。また、DLCで拾えたり作れたりするようになった「かえんだま」等とも違い、DLCを含めても入手方法がここだけです。如何に「ぼうごパット」がレアかがお分かりいただけたかと思います。

f:id:tangential_star:20210211144958p:plain
f:id:tangential_star:20210211144818g:plain
鎧の孤島では、ウッウロボで「たいようのいし」4つを合成すると「かえんだま」になる

どうぐ「ぼうごパット」の効果

そんな幻の超激レアアイテム「ぼうごパット」は、多少ピンポイントながら効果も優秀。その驚きの効果は「直接攻撃に対して発動するわざ・とくせい・どうぐの効果を受けない」というもの。

メジャーどころでは「せいでんき」「ほうし」「さめはだ」「てつのトゲ」など、直接攻撃した際に発動する特性をほぼシャットアウトできます。また、追加効果が非常に厄介な守備技「ブロッキング(防御2段階ダウン)」「トーチカ(どく状態付与)」「ニードルガード(最大HPの1/8ダメージ)」などの追加効果を無効化できます。

さらに、どうぐゴツゴツメット」の効果も無効にできるので、例えばナットレイには2重の意味で強く出られますし、ゴツメサンダー@夢(せいでんき)にも強く出られるかもしれませんね。

f:id:tangential_star:20210211145003p:plain
f:id:tangential_star:20210211143034g:plain
わざ「ブロッキング」の厄介な防御2段階ダウン効果を「ぼうごパット」で無効化できる
f:id:tangential_star:20210211144850g:plain
f:id:tangential_star:20210211143000g:plain
「ぼうごパット」があれば、相手の特性「てつのトゲ」「さめはだ」などを無効化できる

ただ、ここまで持ち上げておいてなんですが、皆様もよくご存知の通り対戦ではほとんど使われません。つまりは読まれにくい、ということだと思うので誰か使ってみてください。

 

ほりだしもの市で入手できる道具

さて、大きく話が逸れたので、一旦ラテラルタウンの話題に戻します。

ほりだしもの市では、1日に1回、露天商のお兄さんから3,000円でその日のほりだしものを購入することができます。また、前日に購入していなかった場合は、前日のほりだしものも5,000円で購入することができます。

目玉商品は前述の「ぼうごパット」ですが、有用なアイテムや他の入手方法が困難or現実的ではないアイテムも売られることがあるため、そちらも狙い目です。

いちおう、筆者的に狙い目のものには、黄色で網掛けしています。入手方法について特にコメントしていないものは、道中で拾えたり貰えたりするものです。

ラテラルタウンほりだしもの市で買えるもの一覧
店頭に並ぶ頻度 なまえ 用途 入手方法または筆者コメント
非常に多い われたポット ヤバチャ(がんさくフォルム)の進化用 実はガラル地方のどこにも落ちていない。DLC2弾「巨人の寝床」でドロップ報告あり。
多い するどいツメ 急所率が1段階上がる。夜にはニューラの進化にも 進化に使うが、ニューラは持っていない。ちなみにピントレンズと同じ効果。
多い プロテクター サイドンの通信進化用 第4世代では1個しか手に入らない貴重アイテムだったのに…
多い れいかいのぬの サマヨールの通信進化用 DPではギラティナ捕獲後、最奥の部屋にあるアイテムだった。でもギラティナは関係ない
ときどき せんせいのツメ 20%で先制攻撃できる ニューラが5%で持っている。ここで手に入れよう。
ときどき メタルコート はがねタイプのわざの威力が1.2倍に。イワーク等の通信進化にも。 穴掘り兄弟が掘り当ててくれるので結構余りがち。進化アイテムなのに効果がある。
まれ かけたポット ヤバチャ(しんさくフォルム)の進化用 ポケセンで売ると19,000円に化ける。まさに文字通りの掘り出し物。
まれ きあいのハチマキ ひんし相当の被ダメージ時、10%の確率でHP1で耐える ワンリキーが5%で持っている。ここで手に入れよう。
まれ きせきのタネ くさタイプのわざの威力が1.2倍になる 特にコメントが思いつかない。
まれ くろいヘドロ どくタイプは毎ターン1/16回復。それ以外は1/8ダメージ ドヒドイデのイメージが強いが、野生で持っているのはグレッグル系列とダストダス
まれ しめつけバンド わざ「しめつける」の毎ターンダメージが1/8⇒1/6になる かつては幻の超激レアアイテムだったDLC第2段冠の雪原で開放。
まれ しんぴのしずく みずタイプのわざの威力が1.2倍になる 実はラプラスが100%持っている。2番道路でランダムに会えるぞ。
まれ どくバリ どくタイプのわざの威力が1.2倍になる ハリーセンロゼリア系列・スコルピ系列が5%で持っている。
まれ ねらいのまと 相性無効タイプの被ダメージが等倍で当たるようになる DLC第1段ウッウロボ以外では入手不可。こいつも幻の超激レアアイテムだった
まれ のろいのおふだ ゴーストタイプのわざの威力が1.2倍になる ヨマワル系列が5%で持っている。ここで手に入れよう。
まれ ぼうごパット 直接攻撃に対して発動するわざ・とくせい・どうぐの効果を受けない 幻の超激レアアイテム。文字通りここでしか手に入らない!ちなみに「パッド」ではない
まれ まがったスプーン エスパータイプのわざの威力が1.2倍になる ケーシィが5%で持っている。ここで手に入れよう。
まれ メトロノーム 同じわざを繰り返し使うと威力アップ(+20%ずつ/最大+100%) かつては幻の超激レアアイテムだったDLC第2段冠の雪原で開放。
まれ もくたん ほのおタイプのわざの威力が1.2倍になる 金銀では9,800円で買えた=売価4,900円だったが、今作では500円にしかならない。
まれ りゅうのキバ ドラゴンタイプのわざの威力が1.2倍になる DLC第1段ウッウロボ以外では入手不可。こいつも幻の超激レアアイテムだった
ごくまれ ぎんのこな むしタイプのわざの威力が1.2倍になる コメント特になし。4番道路で拾えるそうです。
ごくまれ するどいくちばし ひこうタイプのわざの威力が1.2倍になる コメント特になし。これも4番道路で拾えるそうです。
ごくまれ くろいメガネ あくタイプのわざの威力が1.2倍になる RSEでカナシダトンネルを抜けたところで拾ったときのイベントが思い出です。
ごくまれ くろおび かくとうタイプのわざの威力が1.2倍になる 金銀ではいかりのみずうみで水曜にミズオから貰えたが、いあいぎり必須なので不便。
ごくまれ じしゃく でんきタイプのわざの威力が1.2倍になる 金銀では日曜日のニチオから貰えた。個人的に初めて出会った曜日兄弟でした。
ごくまれ シルクのスカーフ ノーマルタイプのわざの威力が1.2倍になる RSEではマッスグマにもたせていました。まさか今作であくタイプになるとは…
ごくまれ せいれいプレート フェアリータイプのわざの威力が1.2倍になる 唯一残ったプレート。アルセウスはノーマルかフェアリーの二者択一を迫られることに。
ごくまれ とけないこおり こおりタイプのわざの威力が1.2倍になる バイバニラが50%の確率で持っている。バニプッチは5%だ。

※注:上記の「幻の超激レアアイテム」とは、このラテラルタウンでしか入手できないことを指します 

 

プログラムの使い方(ランクマバグの入り方)

前述の項目などを通して、ラテラルタウンの「ほりだしもの市」が如何に重要かがわかったと思います。特に、DLCを買っていない人には唯一の入手経路となるアイテムが5つもあるわけですから、無視するわけにもいきませんね。

さて、おまたせしました。肝心のプログラムの使い方です。

本稿でも、前回の【Arduino自動化14】ロトミIDくじ無限抽選と同じく、いわゆるランクマバグ状態でプログラムを動かします。やり方については、何も難しいことはなく、ランクマッチで1戦するだけなのですが、ランクマッチ以外の方法だと下記もあります。画像は過去記事の使いまわしです。あしからず。

  1. YY通信で「通信対戦」を行う(ローカル通信)
  2. もう一台のSwitch・剣盾を使ってその通信対戦に応じる
  3. 戦闘が始まったらHomeボタン長押し→「機内モード」をONに変更する
  4. エラーが発生するのでそれを閉じて、「にげる」選択
  5. フィールド画面に戻ってくる(ランクマバグ状態に移行完了)
f:id:tangential_star:20201122213022g:plain
f:id:tangential_star:20201122213037g:plain
YY通信でローカル対戦を募る。バトルが始まったらHomeボタン長押しで機内モード
f:id:tangential_star:20201122213148g:plain
f:id:tangential_star:20201122213205g:plain
エラーが出たら「にげる」で対戦終了。この状態で時刻変更すると一瞬画面が暗転する

 

ソースコード

使い方は、ラテラルタウンの露天商のお兄さんの前で、ランクマバグ状態でArduinoを挿し込むだけの簡単仕様です。1試行あたり25秒(実測値)でした。1回で3,000円取られるので、ちゃんと金額は準備しておきましょう。

なお、新規アイテム(初めて入手したアイテム)があっても、そのままループは破綻しませんので、そのまま放置でOKのはずです。

NintendoSwitch Ver.11.0アップデート対応済です。

/* 
 *  ラテラルタウン掘り出し物市 自動購入
 *  
 *  【ランクマバグ】状態で使うこと!
 *  掘り出し物市の前でArduino差し込むだけ!
 *  (c) 2021 ますたーの忘備録
 *  https://tangential-star.hatenablog.jp/
*/

#include <SwitchControlLibrary.h>

#define HOLDTIME (95) // 1回のキー入力の長押し時間

void PushRL(int delay_time_ms);
int PushKey(char* keyname, int holdtime, int delaytime);
void NextDayInCheatMode(void);

void setup() {
  // コントローラーとして認識されるためにRLを7回ほどカチャカチャする
  for(int i=0;i<7;i++)PushRL(300);
  delay(1000);
}


void loop() {

  // ★日付を回すやつ
  NextDayInCheatMode();

  PushKey("A", HOLDTIME, 700);  // いらっしゃい… ほりだしもの みていくかい? 
  PushKey("A", HOLDTIME, 1500); // ⇒本日の ほりだし (※シークタイムあり)
  PushKey("A", HOLDTIME, 700);  // 本日の ほりだしものは ○○ だな…… ▼
  PushKey("A", HOLDTIME, 700);  // ○○円だが 買っていくかい? ⇒はい
  PushKey("B", HOLDTIME, 2100); // まいど どうも ▼ (※SEチャリーン音あり)
  PushKey("B", HOLDTIME, 3000); // ○○は ○○を 手に入れた! ▼
  PushKey("B", HOLDTIME, 700);  // ○○は ○○を ○○ポケットに しまった ▼
  PushKey("B", HOLDTIME, 700);  // ほかに 用は あるかい? ▼
  PushKey("B", HOLDTIME, 700);  // 気が 変わったら また 来な…… ▼
  PushKey("B", HOLDTIME, 700);  // 
  
  PushKey("B", HOLDTIME, 300); // 予備
  PushKey("B", HOLDTIME, 300);

  //// 以下、新規購入のダイアログ出現時に効率よく回せるようになるので、「きあいのハチマキ」「ぼうごパッド」など新規アイテムが多い人はつけよう(↓3行の//を消そう)
  // PushKey("B", HOLDTIME, 500);
  // PushKey("B", HOLDTIME, 500);
  // PushKey("B", HOLDTIME, 500);

}

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){
  // ホームボタン・方向キーはRight, Left, Up, Down, Homeなど2文字以上で入力。
  // その他ボタン入力は1文字(A,B,X,Y,R,L,+,-)ZR・ZLにも対応
  // 同時押しは非対応
  
  if(strlen(keyname)==1){
    switch(keyname[0]){
      case 'A': case 'a': // A
        SwitchControlLibrary().PressButtonA(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonA(); delay(delaytime);
      break;
      case 'B': case 'b': // B
        SwitchControlLibrary().PressButtonB(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonB(); delay(delaytime);
      break;
      case 'X': case 'x': // X
        SwitchControlLibrary().PressButtonX(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonX(); delay(delaytime);
      break;
      case 'Y': case 'y': // Y
        SwitchControlLibrary().PressButtonY(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonY(); delay(delaytime);
      break;
      case 'L': case 'l': // L
        SwitchControlLibrary().PressButtonL(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonL(); delay(delaytime);
      break;
      case 'R': case 'r': // R
        SwitchControlLibrary().PressButtonR(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonR(); delay(delaytime);
      break;
      case 'H': case 'h': // Home
        SwitchControlLibrary().PressButtonHome(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonHome(); delay(delaytime);
      break;
      case '+': case 'p': case 'P': // Plus
        SwitchControlLibrary().PressButtonPlus(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonPlus(); delay(delaytime);
      break;
      case '-': case 'm': case 'M': // Minus
        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': // ZR/ZL
        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': // right
        SwitchControlLibrary().MoveHat(2); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().MoveHat(8); delay(delaytime);
      break;
      case 'l': case 'L': // left
        SwitchControlLibrary().MoveHat(6); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().MoveHat(8); delay(delaytime);
      break;
      case 'u': case 'U': // up
        SwitchControlLibrary().MoveHat(0); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().MoveHat(8); delay(delaytime);
      break;
      case 'd': case 'D': // down
        SwitchControlLibrary().MoveHat(4); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().MoveHat(8); delay(delaytime);
      break;
      case 'H': case 'h': // Home
        SwitchControlLibrary().PressButtonHome(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonHome(); delay(delaytime);
      default:
      break;  
    }
  }else{
    return -1;
  }
  return strlen(keyname);
}
void NextDayInCheatMode(){
  // ★日付変更
  // Homeボタンを押して設定の画面へ移動
  PushKey("Home", HOLDTIME, 1000);

  // Home画面で「設定」を選ぶ
  PushKey("down", HOLDTIME, 105);
  PushKey("right", HOLDTIME, 105);
  PushKey("right", HOLDTIME, 105);
  PushKey("right", HOLDTIME, 105);
  PushKey("right", HOLDTIME, 105);
  PushKey("right", HOLDTIME, 105);
  PushKey("A", HOLDTIME, 1500);

  // 設定画面で「日付と時刻」を開く
  PushKey("down", 1500, 105); // 1.5秒「↓」長押し
  PushKey("right", HOLDTIME, 105); 

  for(int i=0; i<4; i++){
    PushKey("down", HOLDTIME, 55);
  }
  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);
  PushKey("A", HOLDTIME, 1000);
  return;
}

一応、ループが破綻せずに2周目でズレを吸収する様子を↓下記GIF画像にて。

f:id:tangential_star:20210211170119g:plain
f:id:tangential_star:20210211125124p:plain
新規アイテム入手時のダイアログで動作がズレても、次の試行で吸収する設計

 

 

あとがき

今回で、Arduino自動化記事も15本目となります。

皆様に支えられ、本ブログも開設から3ヶ月が経過し、月間PV数も平均で2,537PV/月にまで成長しました(2021/2/8 0:00計算)。引き続きよろしくお願いいたします。

 

さて、DLCも第2弾まで出ているのに「なんで今更ラテラルタウンの記事?」と思った方も、ここまで読んでいただいて、「ここでしか入手できないアイテムなんてあったのか!」と驚いた方も多いのでは無いでしょうか。また、「『ぼうごパット』というアイテムなんて存在すら知らなかった!」という方もいらっしゃると思います。

 

f:id:tangential_star:20210211174915p:plain

落書き:パッチルドン@ぼうごパット

上述しましたが、超激レアアイテムの「ぼうごパット」は、メタとしては強力な一方、汎用性には乏しくかなりピンポイントな運用になると思います。が、それ故にきっと意表を突けるアイテム枠として採用できるポテンシャルは充分にあると思います。

本ブログ記事が、皆様にとって「ぼうごパット」を今一度認識する機会となったり、Arduino自動化の一助となったりすれば幸いです。

 

ではではc⌒っ.ω.)っ

 

前記事:【Arduino自動化14】ロトミIDくじ無限抽選

次の記事:【Arduino自動化16】自動ミラクル交換(ID集めほか)

導入記事:【Arduino自動化01】Arduino開発環境の導入 

 

【Arduino自動化14】ロトミIDくじ無限抽選

ますたーです。こんにちは。

今回は、いわゆるランクマバグ状態で「ロトミIDくじ」を引き続ける自動化記事です。

Arduino自動化記事もこれで第14回。これからもよろしくお願いします。

 

なお、Arduino Leonardo自動化の導入・機材構成については導入記事を参考にしてください。

導入記事:【Arduino自動化01】Arduino開発環境の導入

※本ブログに初めてお越しの方は「本ブログについて」もぜひ、ご覧ください。

 

概要

本記事では、ランクマバグ状態を利用した、ロトミIDくじ無限抽選を実装します。
※便宜上「ランクマバグ」と表記しますが、当ブログではランクマッチを使用しません。通信切断・初手降参の推奨もしません。

【!】ロトミIDくじは、その特性上、大量の「レポート」を伴います。必然的にmicroSDや本体メモリへの書き込みが増えますので、セーブデータ破損のリスクや動作不良のリスクなど、充分に危険性を理解した上でご参考ください。

 

NintendoSwitch Ver.11.0アップデート対応済です。

f:id:tangential_star:20210130135029g:plain
f:id:tangential_star:20210201212827p:plain
無限にIDくじを引き続けることができる。目指せ、特賞「マスターボール

では、目次です。確率計算とかもしました!(理系っぽい!)

ロトミIDくじの当選確率を知りたいという方はコチラ⇒読み飛ばす

ソースコードだけほしい方はコチラ⇒読み飛ばす

 

ポケモンセンターでロトミIDくじが引ける

まずは前提、というか余談です。

ポケモン剣盾では、ポケモンセンター各店舗のパソコンライクな機械「ロトミ」で1日1回「IDくじ」を引くことができます。

「IDくじ」をご存じない方にも説明をすると、手持ち・ボックスにいる全ポケモンの親IDと、ランダムで発生した5桁の乱数とを比較し、一致する桁数に応じて賞品が貰える、という毎作品お馴染みのおまけ要素です。

古くは第二世代(金銀)時代に始まり、ID完全一致の特等景品「マスターボール」は当時からの憧れの的でした(当時は、1日1回ではなく1週間に1回だったので引ける回数は大きく増えましたね)。完全に余談ですが、この「IDくじ」、何故か第五世代(BW)だけなかったんですよね。毎日のゲームモチベが減ったものです。

f:id:tangential_star:20210202103550g:plain
f:id:tangential_star:20210202085422p:plain
ポケモンRSEではミナモデパートでIDくじを引くことができた

前作までは、わざわざコガネシティ(ラジオとう)やミナモシティ(ミナモデパート)、コトブキシティ(テレビコトブキ)などの街に移動する、いわゆる「IDくじのための移動」が必要でした。

今作は、なんと、どこの街のポケモンセンターでもIDくじが引けますDLCでも、鎧の孤島なら拠点にロトミを連れてくることができるため、大変手軽にくじを回すことができるようになりました。また、今作のIDくじについても例外なく、特等(=ID下5桁一致)の賞品は「マスターボール」になります。

 

ロトミIDくじで特等「マスターボール」を狙う

ロトミIDくじは、ランダムに生成された5桁の数字を、手持ち・ボックスの全ポケモン(ポケジョブ除く)の親IDそれぞれの下5桁とを比較し、一致した桁数に応じて賞品がもらえます。

さて、肝心の特等「マスターボール」ですが、前述の通り親IDの下5桁が完全一致する必要があります。親IDが1つの場合(例えば一切他人と交換していない場合)の「マスターボール」当選確率を計算すると、「10の5乗分の1」になります。すなわち、わずか0.001%です

※一説によれば、今作は先頭5桁の一致も含むという噂?があるようです。それに則れば単純計算で当選確率は2倍になりますが、本ブログでは7回「特等」を当選していますが「上5桁一致」での当選はありませんでした。そのため、下5桁のみ当選する前提にて確率計算・表記しています

※ところが、後述の通り、実測値で計算した確率が「理論値の2倍」になります

f:id:tangential_star:20210203092440p:plain
f:id:tangential_star:20210203092444p:plain
f:id:tangential_star:20210203092449p:plain
「特等」当選時のメンバーの一例。いずれも下5ケタ一致だ(205575, 101082, 590328
f:id:tangential_star:20210203003331g:plain
f:id:tangential_star:20210203003339g:plain
f:id:tangential_star:20210203003348g:plain
筆者は7回「特等」を引いたが、いずれも「下5ケタ すべてが おんなじロ」と評される

 

ロトミIDくじの当選確率

上述の通り、「マスターボール」の当選確率はただでさえ低いですので、ミラクル交換やポケモンHOME(スマホ版)の交換機能などを活用し、できるだけ親IDを集めておくと良いでしょう。

ボックスいっぱいにすると30匹×32ボックス=960匹預けることができますので、これらのIDに一切の重複が無いと仮定すれば、マスターボールの当選確率が約1%まで跳ね上がります

一応、理論値としては、手持ち6匹+960匹すべて違うポケモンで0.9614%が上限です。

300匹で特等の確率は0.3%程度になるので、マスターボール狙いなら、少なくとも10ボックス程度は他人の親IDのポケモンで埋めておきたいです。どうしても難しい場合でも、ハズレの確率が1%を下回る50種類までは少なくとも集めておきたいです。

なお、IDの一致桁数に応じた賞品の当選確率は下記の通りです(筆者試算)。

 

所持ID数と各賞品の当選確率(小数点第3位を四捨五入)
ID数 【特等】5桁
マスターボール
【1等】4桁
ふしぎなあめ
【2等】3桁
ポイントマックス
【3等】2桁
ポイントアップ
【4等】1桁
モーモーミルク
はずれ
1 0.00% 0.01% 0.09% 0.90% 9.00% 90.00%
10 0.01% 0.08% 0.81% 7.75% 52.41% 38.94%
25 0.02% 0.20% 2.00% 18.00% 70.31% 9.46%
50 0.05% 0.40% 3.95% 31.96% 62.74% 0.90%
100 0.10% 0.80% 7.71% 50.90% 40.48% 0.01%
300 0.30% 2.36% 21.01% 69.69% 6.64% 0.00%
500 0.50% 3.90% 31.85% 62.66% 1.09% 0.00%
700 0.70% 5.41% 40.65% 53.07% 0.18% 0.00%
960 0.96% 7.32% 49.59% 42.11% 0.02% 0.00%
966 0.96% 7.37% 49.77% 41.89% 0.02% 0.00%

 

所持ID数と各賞品の当選確率のグラフ

狙う賞品によって最適なID数は違うが、はずれが出にくくなる50種は少なくとも欲しい

f:id:tangential_star:20210208165840p:plain

特等(マスターボール)・1等(ふしぎなあめ)は、ID数に応じて当たりやすくなる

言わずもがな、ポイントマックスはもちろんマスターボールやふしぎなあめの当選確率は、持っているID数が多ければ多いほど上がります。ユニークなのはポイントアップとモーモーミルクの当選確率で、途中で極大値を取ります。

具体的には、ポイントアップは283匹の時に69.764%、モーモーミルクは28匹の時に70.504%でそれぞれ極大値を取ります。現実的に960匹違うIDでボックスを埋めるのはツライと思いますので、このあたりを参考に、狙う道具を検討しつつ、事前に用意するポケモンの数を検討すべしですね。

 

マスターボール」の当選確率は2倍?

9時間46分放置でマスターボールを7個入手しました

筆者は過去作でGTS交換したものなども含めて12ボックス分(360匹)、ポケモンHOMEで連れてきて、自動化プログラムを使用しました。結果、プログラムを9時間46分稼働させ続け、推定試行回数888抽選で「マスターボール」7つを入手できました。

※プログラムソースコード後述します

f:id:tangential_star:20210204135040g:plain
f:id:tangential_star:20210130135029g:plain
他人産ポケモンで12ボックスを埋めて、いざ自動化!
f:id:tangential_star:20210204130023p:plain
f:id:tangential_star:20210204130028p:plain
9時間46分稼働させ、「マスターボール」7個を入手(左:実施前/右:実施後)

マスターボールの当選確率を計算(考察)

さて、確率計算です。完全に余談ですので、読み飛ばしOKです→読み飛ばす

888試行に対して7回の「特等」当選ですが、これは確率に表すと0.7883%になります。一方、12ボックス分(360匹)での、1試行あたりの入手確率は計算上、0.3593%になります。すなわち、実績値が理論値のおおよそ2倍になるという、かなり稀有な事象が起こっています。

もし、噂通り「上5桁も当選する仕様」なら理論値は上記2倍の0.7187%になるので理論値とかなり近しくなりますが、これはかなり不思議です。というのも、筆者が特等を引いた7回とも「下5桁」で当選しているからです

※7回続けて「下5桁」で当選するのは統計学的に有意水準1%で有意な偏り(符号検定よりp<0.01)と言えます。要するに偶然の範疇を超えています

なので、もしかしたら、ロトミは内部的に2回「下5桁完全一致」の抽選を行っているのかもしれませんし、上5桁で当選した時に、下5桁で言い直しているのかもしれません。

いずれにしても、実績値から考えるに当選確率は、単純な「下5桁完全一致」で計算した理論値の2倍と考えるのが妥当なので、ロトミIDくじの各賞品の当選確率は下表になるかもしれません。どちらを信じるかは読者の判断に委ねます。

 

所持ID数と各賞品の当選確率(特等の当選確率が2倍で仮定した時の試算)
ID数 【特等】5桁
マスターボール
【1等】4桁
ふしぎなあめ
【2等】3桁
ポイントマックス
【3等】2桁
ポイントアップ
【4等】1桁
モーモーミルク
はずれ
1 0.00% 0.01% 0.09% 0.90% 9.00% 90.00%
10 0.02% 0.06% 0.82% 7.75% 52.41% 38.94%
25 0.05% 0.15% 2.03% 18.00% 70.31% 9.46%
50 0.10% 0.30% 4.00% 31.96% 62.74% 0.90%
100 0.20% 0.60% 7.81% 50.90% 40.48% 0.01%
300 0.60% 1.77% 21.30% 69.69% 6.64% 0.00%
500 1.00% 2.93% 32.33% 62.66% 1.09% 0.00%
700 1.39% 4.06% 41.31% 53.07% 0.18% 0.00%
960 1.90% 5.49% 50.48% 42.11% 0.02% 0.00%
966 1.91% 5.52% 50.66% 41.89% 0.02% 0.00%

 

プログラムの使い方(ランクマバグの入り方)

おまたせしました。

肝心のプログラムの使い方ですが、ロトミの前でソースコードを書き込んだArduinoを挿し込むだけの簡単仕様です。ただし、いわゆる「ランクマバグ」状態で使う必要がありますので、ランクマッチで1戦してください。

なお、ランクマッチを使用しない方法での「ランクマバグ状態」移行は下記手順でできます。画像は過去記事の使いまわしです。あしからず。

  1. YY通信で「通信対戦」を行う(ローカル通信)
  2. もう一台のSwitch・剣盾を使ってその通信対戦に応じる
  3. 戦闘が始まったらHomeボタン長押し→「機内モード」をONに変更する
  4. エラーが発生するのでそれを閉じて、「にげる」選択
  5. フィールド画面に戻ってくる(ランクマバグ状態に移行完了)
f:id:tangential_star:20201122213022g:plain
f:id:tangential_star:20201122213037g:plain
YY通信でローカル対戦を募る。バトルが始まったらHomeボタン長押しで機内モード
f:id:tangential_star:20201122213148g:plain
f:id:tangential_star:20201122213205g:plain
エラーが出たら「にげる」で対戦終了。この状態で時刻変更すると一瞬画面が暗転する

 

ソースコード

今回も例のごとく、「ランクマバグ」状態で使います。使い方は、最寄りのポケモンセンターのロトミの前でArduinoを挿し込むだけの簡単仕様です。

30試行あたり19分47秒(実測値)だったので、ざっくり1時間放置で90回抽選できます。

NintendoSwitch Ver.11.0アップデート対応済です。

/* 
 *  ロトミIDくじ自動抽選c⌒っ.ω.)っ
 *  
 *  【ランクマバグ】状態で使うこと!
 *  ロトミの前でArduino差し込むだけ!
 *  (c) 2021 ますたーの忘備録
 *  https://tangential-star.hatenablog.jp/
*/

#include <SwitchControlLibrary.h>

#define HOLDTIME (95) // 1回のキー入力の長押し時間



void PushRL(int delay_time_ms);
int PushKey(char* keyname, int holdtime, int delaytime);
void NextDayInCheatMode(void);

void setup() {
  // コントローラーとして認識されるためにRLを7回ほどカチャカチャする
  for(int i=0;i<7;i++)PushRL(300);
  delay(1000);
 
}


void loop() {

  // ★日付を回すやつ
  NextDayInCheatMode();

  PushKey("A", HOLDTIME, 700); // こんにちロ~! なにを しますロミ? ▼
  PushKey("A", HOLDTIME, 700); // 
  PushKey("down", HOLDTIME, 350); // IDくじ
  PushKey("A", HOLDTIME, 700); // ただいま IDくじセンターの 抽選コーナーに つないだロミ!▼
  PushKey("A", HOLDTIME, 700); // 引いた くじの ナンバーと ○○さんの ポケモンのIDが▼
  PushKey("A", HOLDTIME, 700); // みごと あってると ステキな 賞品を もらえちゃうんだロ!▼
  PushKey("A", HOLDTIME, 700); // 運試しに レポートを 書いて 引いてみるのは どうロミ?
  PushKey("A", HOLDTIME, 2000); // はい⇒レポートを書き込んでいます⇒しっかり書き残した▼
  PushKey("B", HOLDTIME, 800); // かしこまりロ~! 抽選 スタート ロミ!▼
  PushKey("B", HOLDTIME, 1200); // …… …… ……▼
  PushKey("B", HOLDTIME, 700); // ハイ! でたロミ! くじの ナンバーは *****!▼
  PushKey("B", HOLDTIME, 700); // ○○さんの ポケモンのIDと どれだけ あってるか▼
  PushKey("B", HOLDTIME, 700); // 調べて 見るロ!▼
  PushKey("B", HOLDTIME, 3000); // おめでロ~~~!!!!▼
  PushKey("B", HOLDTIME, 700); // ボックスに 預けている ○○ちゃんの IDが みごと▼
  PushKey("B", HOLDTIME, 700); // くじの ナンバーと ぴったしロミ!▼
  PushKey("B", HOLDTIME, 700); // ロミ! ○ケタが おんなじロ!▼
  PushKey("B", HOLDTIME, 700); // そんな スペシャルな 奇跡には 2等の 賞品▼
  PushKey("B", HOLDTIME, 700); // ポイントマックスを プレゼントだロ!!▼
  
  PushKey("B", HOLDTIME, 3000); // ○○は ポイントマックスを 手に入れた!▼
  PushKey("B", HOLDTIME, 700); // ○○は ポイントマックスを どうぐポケットに しまった▼
  PushKey("B", HOLDTIME, 900); // それじゃあ またの 挑戦を お待ちしてるロ~~!▼
  PushKey("B", HOLDTIME, 700); // ▼
  
  PushKey("B", HOLDTIME, 300); // 予備
  PushKey("B", HOLDTIME, 300);
  PushKey("B", HOLDTIME, 300);
  

}

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){
  // ホームボタン・方向キーはRight, Left, Up, Down, Homeなど2文字以上で入力。
  // その他ボタン入力は1文字(A,B,X,Y,R,L,+,-)ZR・ZLにも対応
  // 同時押しは非対応
  
  if(strlen(keyname)==1){
    switch(keyname[0]){
      case 'A': case 'a': // A
        SwitchControlLibrary().PressButtonA(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonA(); delay(delaytime);
      break;
      case 'B': case 'b': // B
        SwitchControlLibrary().PressButtonB(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonB(); delay(delaytime);
      break;
      case 'X': case 'x': // X
        SwitchControlLibrary().PressButtonX(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonX(); delay(delaytime);
      break;
      case 'Y': case 'y': // Y
        SwitchControlLibrary().PressButtonY(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonY(); delay(delaytime);
      break;
      case 'L': case 'l': // L
        SwitchControlLibrary().PressButtonL(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonL(); delay(delaytime);
      break;
      case 'R': case 'r': // R
        SwitchControlLibrary().PressButtonR(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonR(); delay(delaytime);
      break;
      case 'H': case 'h': // Home
        SwitchControlLibrary().PressButtonHome(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonHome(); delay(delaytime);
      break;
      case '+': case 'p': case 'P': // Plus
        SwitchControlLibrary().PressButtonPlus(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonPlus(); delay(delaytime);
      break;
      case '-': case 'm': case 'M': // Minus
        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': // ZR/ZL
        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': // right
        SwitchControlLibrary().MoveHat(2); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().MoveHat(8); delay(delaytime);
      break;
      case 'l': case 'L': // left
        SwitchControlLibrary().MoveHat(6); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().MoveHat(8); delay(delaytime);
      break;
      case 'u': case 'U': // up
        SwitchControlLibrary().MoveHat(0); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().MoveHat(8); delay(delaytime);
      break;
      case 'd': case 'D': // down
        SwitchControlLibrary().MoveHat(4); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().MoveHat(8); delay(delaytime);
      break;
      case 'H': case 'h': // Home
        SwitchControlLibrary().PressButtonHome(); delay(holdtime);
        if(holdtime>0)SwitchControlLibrary().ReleaseButtonHome(); delay(delaytime);
      default:
      break;  
    }
  }else{
    return -1;
  }
  return strlen(keyname);
}
void NextDayInCheatMode(){
  // ★日付変更
  // Homeボタンを押して設定の画面へ移動
  PushKey("Home", HOLDTIME, 1000);

  // Home画面で「設定」を選ぶ
  PushKey("down", HOLDTIME, 105);
  PushKey("right", HOLDTIME, 105);
  PushKey("right", HOLDTIME, 105);
  PushKey("right", HOLDTIME, 105);
  PushKey("right", HOLDTIME, 105);
  PushKey("right", HOLDTIME, 105);
  PushKey("A", HOLDTIME, 1500);

  // 設定画面で「日付と時刻」を開く
  PushKey("down", 1500, 105); // 1.5秒「↓」長押し
  PushKey("right", HOLDTIME, 105); 

  for(int i=0; i<4; i++){
    PushKey("down", HOLDTIME, 55);
  }
  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);
  PushKey("A", HOLDTIME, 1000);
  return;
}

 

あとがき

今回は、「ロトミIDくじ」の自動化について紹介しました。

ロトミってRotom Information Serviceの意味だったんですね。この記事を書くまで知りませんでした。

 

さて、本稿でも結構考察しましたが、様々なWebサイトを調べてもマスターボールの当選について「5桁一致」とは書いてあるものの「下5桁」のみならず「上5桁」も含むのかが分からず、自分で検証してしまいました。

結論、ロトミは「下5桁」でしか当選を教えてくれないが、確率は単純計算時の2倍で設定されている、という仮説ができましたね。そういう意味では、ある意味「自動化記事」でありながら「疑問だし記事」にもなってしまいました(笑)。

誰か、数学に強い人か、ロトミに詳しいポケモン博士にぜひともコメントしていただきたいものです(もしかしたらそもそも私の試算が間違っている、なんて本末転倒かもしれませんし)。

 

話が逸れましたが、これで「マスターボール」の自動入手もできるようになりました。マスターボールは「孵化厳選」では絶対に引き継げない、とても希少なボールですし、ボールエフェクトもカッコイイんですよね。そういう意味でも、すごく需要があるボールなのに…。もう少し手軽に入手できれば良いのにな、と思います。そういった意味でも、需要のある自動化だったのではないでしょうか。

 

本ブログが皆様の自動化ライフをより豊かなものにできれば幸いです。

ではではc⌒っ.ω.)っ

 

前記事:【Arduino自動化13】全自動ポケモン逃がし

導入記事:【Arduino自動化01】Arduino開発環境の導入 

次の記事:【Arduino自動化15】ラテラルタウン掘り出し物自動購入

 

2021/2/19追記:IDを効率よく集められる「ミラクル交換」の自動化記事を執筆しました。

参考:【Arduino自動化16】自動ミラクル交換(ID集めほか)

【Arduino自動化 番外編3】筆者の使用機材一覧【紹介記事】

こんにちは。ますたーです。

今回は、番外編その3として、Arduinoでの自動化で私が「実際」に使っている機器類を紹介します。 

 

なお、機器全般・ソフトウェアの構成・セットアップは【Arduino自動化01】Arduino開発環境の導入をご覧ください。

※本ブログに初めてお越しの方は「本ブログについて」もぜひ、ご覧ください。

 

概要

今回の記事では、実際に筆者が使っている機材を紹介します。参考になるよう、私が実際に購入した際の、購入日・購入金額・Amazonのリンクも載せます。

金額は私が購入した当時のものなので、あくまでも参考金額として参照ください(最新の金額はAmazonのリンク先で記載のものでご確認をお願いします)
※有線コントローラーのみAmazonではなく実店舗で購入しています。同型番のものを紹介します。

 

目次です。

私の使っている機材の一覧は最後に表で纏めています。

「説明はいらん」というかたは読み飛ばしてください⇒読み飛ばす

 

自動化の基本機材構成

まず、導入記事の一部繰り返しになりますが、Nintendo Switchの操作を自動化するにあたり、基本的な機材構成としては下記のものを準備する必要があります。

さらに、給電しながら自動化をする場合には、追加で

  • Switchドック(Switchの場合)または USBスタンド(Switch Liteの場合)
  • 充電アダプタ

が必要です。筆者としては、長時間放置できるからこそ自動化の意義があると考えるので、上記の下2つも合わせて使うことをおすすめします。

f:id:tangential_star:20201107181011p:plain
f:id:tangential_star:20201107181445p:plain
機材構成イメージ(左:おすすめ/右:最低限の構成)

 

必須ではないが、あると便利な機材

導入記事では紹介しておりませんでしたが、Nintendo Switchの操作を自動化するにあたって、前述の機材構成に加えて、あると便利だったものは下記の通りです。

なお、これらはいずれも筆者が実際に使っているものです

ただ、これらはあれば重宝しますが、「必須ではない」ので、無理に揃える必要はありません。まずは上記基本構成で自動化ができるようになってから必要に応じて購入すればOKです。

  • Arduino Leonardoのケース(カバー)
  • Switchドック用USBハブスタンド
  • USBスイッチ付きコネクタ
  • 有線コントローラー

以上に述べたこれらの機材について、次項からは1つずつ紹介します。 

 

 

実際に使用している機材の紹介

【前提】Arduino Leonardo(マイコン

まずは、ポケモン自動化の要となるマイコンArduino Leonardo」の紹介です。

自動化方法の調査記事でも紹介している通り、Arduinoには「Arduino UNO」系列と「Arduino Leonardo」系列の2種類があります。

見た目は似ていますが、これらの間でポケモン自動化の方法は大きく異なるので、UNOとLeonardoを間違えないように購入しましょう。

本ブログでは、導入記事でも紹介している通り、後者(Leonardo)を利用しています。

このArduino Leonardoには様々な互換機や類似品が売っています。もし、しっかりとした理解が無い状態で選ぶのであれば、筆者としては互換機ではなく純正の「Leonardo」を購入することを強くおすすめします。

ちなみに購入して1年経ちますが、全く壊れる気配がありません。

(筆者購入日:2020/1/28;購入時の金額:3,190円)

 

【前提】通信対応USBケーブル(USB-Aオス・USB-microBオス)

これは、すでにお持ちの方も多いと思います。

具体的には、少し前のAndroidスマホのPC通信ケーブルがまさにUSB-A・USB-microBですので、これが使えるかもしれません。

なお、SwitchまたはSwitch Liteと直接つなぐ(給電しない)場合は、USB-microB・USB-Cの通信対応USBケーブルを購入するか、別途USB-Aメス・USB-Cオスの変換口を購入してください。

念の為、USB-microB側をArduino Leonardoに挿し込み、USB-A側をSwitchのドックまたはUSBスタンドに挿し込みます。このケーブルはPCからArduinoにプログラムを書き込む際にも使うので、Arduino側(USB-microB側)は基本的に挿しっぱなしの運用になると思います。ケーブルが長すぎると邪魔になるので、自身のちょうどよい長さのものを買い揃えましょう。

ちなみに、よくあるミスのひとつとして「充電専用ケーブル」は使えないので、「通信対応」などと書かれているものを購入しましょう

(筆者購入日:2020/2/5;購入時の金額:598円)

 

【あると便利】Arduino用ケース(エンクロージャー)

Arduinoはその性質上、基盤がむき出しになることが多いです。そのため、不意に素手でベタベタ触っているときに誤って汚損・破損することもあります。しかし、Arduino Leonardoにはその専用のケースがありません

そこで、Arduino Leonardoに「UNO用」エンクロージャーをあてがうと、なんとなく良い感じに仕上がります(紹介していてアレですが、この使い方は公式に推奨されるものではありません!)。

本来は、Arduinoの基盤に空いた穴と付属のネジの位置が合致するためエンクロージャー内部で基盤が固定されるのですが、UNOとLeonardoでは基盤の配置や穴の位置が若干異なるため、これができません。

なので、私は、側面のアクリルを使わずに基盤を直接挟んでネジ固定する荒業で使っています。買って約1年経ちますが、壊れる気配が無いので安心しています。

(筆者購入日:2020/2/5;購入時の金額:340円)

f:id:tangential_star:20210128100318j:plain
f:id:tangential_star:20210128100139j:plain

筆者の使用しているマイコンArduino Leonardo」の外観
「UNO用」エンクロージャーでLeonardoを挟む荒業だが約1年間、問題なく使えている

 

【Liteの場合は必須】USBハブスタンド

Switch Liteを利用している方のうち、充電しながら自動化する場合には必須です(もちろん、すでに代替ドックなどのUSBポートと給電が同時にできるものを持っている方はそちらでもOKですし、そもそも給電しないのであれば不要です)。

純正ドックが使えるSwitch(Liteではない)では原則不要です。ただし、長時間使うことが前提になるので、「ドックに挿すと本体に熱がこもるのでは?」「ディスプレイが画面焼けするのでは?」などが気になる人は使ってみても良いかもしれません(テーブルモードになります)。私は、Switch Liteで自動化をするために買っています。ポータブルUSBハブスタンドの良いところは、なんと言ってもSwitch・Switch Liteいずれも安定してテーブルモードで利用できること。

筆者はこれの2ポート版も持っていますが、やっぱり横に広くなる4ポート版のほうが卓上で安定するのでなんとなく安心しています。

f:id:tangential_star:20210128004650j:plain
f:id:tangential_star:20210128004639j:plain
Nintendoライセンス商品の、ホリの「ポータブルUSBハブスタンド(4ポート)」。
Arduinoと充電アダプタを同時に挿せるので、給電しながら自動化ができる

なお、重要な欠点として、純正でありながら「Switch保護ケース」をつけたSwitchやSwitch Liteとは充電部分が干渉してしまい、使えないという点があります。

もし、普段は携帯モードで遊ぶ機会が多く、テーブルモードで遊ばないという人は注意が必要です。

(筆者購入日:2020/11/6;購入時の金額:3,550円)

 

【あると便利】Switchドック用USBハブスタンド

前述の通り、Switch(Liteではない)を利用する場合、純正のドックをUSBポートとして利用できます。

しかし、ドックの置き方にもよりますが、USBポートはドックの側面に付いているため、Switch本体を挿すとその裏側になり、Arduinoや有線コントローラーを挿しにくいという欠点があります。

また、別途冷却用ファンを使っている人などは、そもそもUSBポートが不足している、ということもあるかもしれません。

そこで、側面のUSBポートを1つ使い、Switchドックの「正面」にUSBポートを4つ拡張できるドック用のUSBハブスタンドを使うと便利です。特に、Arduinoを抜き差しして3日後の巣穴厳選をひたすら繰り返す【Arduino自動化05】乱数調整レイドの自動化では、横にあるよりも正面にある方が便利でした。

(筆者購入日:2020/11/14;購入時の金額:2,600円)

f:id:tangential_star:20201123010702g:plain

USBポートが正面にあるため抜き差しが楽々できるように

 

【あると便利】USBスイッチ付きコネクタ

スイッチひとつでON・OFFが切り替えられるコネクタです。

Arduino自動化で一番「買ってよかった」と感じている「個人的MVP機材」です。前述のドック用USBハブスタンドで、正面にUSBポートができたので、Arduinoの抜き差しも幾分手軽にできるようになったのですが、いかんせん、その抜き差しがめんどくさくなったのです(省力志向)。

ArduinoでSwitch操作を自動化する場合、他のコントローラーを予め抜いておく(無線コントローラーの場合は切断しておく)必要があります。

すなわち、「何かしらの自動化をするたびにコントローラーを抜いてArduinoを挿す」「自動化が終わったらArduinoを抜いてコントローラーを挿す」作業が必要になります。この抜き差しが大変に面倒くさいのです。

そこで、筆者はこれをなんと4個も買い(アホです)、上述のSwitchドック用USBハブスタンドにすべて挿し込み、ON・OFF切り替え対応機能をドックにつけました。

f:id:tangential_star:20210128150338j:plain
f:id:tangential_star:20210128150349j:plain
Switchドック用USBハブスタンドに、スイッチ付きUSBコネクタを4本挿し

結論、Arduinoもコントローラーも両方ともSwitchに挿しっぱなしで、スイッチでON・OFFが切り替えられるので、「今はコントローラーで操作したい!」というタイミングだけ有線コントローラー側をONにする、みたいなことができるように。

ちょっと操作が終わったらON・OFFを逆にするだけ、という極限の省力化に成功しました。しかも、Arduinoを普段ずっと挿しっぱなしにしても誤動作しなくなったので、Arduinoの収納場所を考えなくて済むようになりました(ただのズボラ)。

(筆者購入日:2020/12/5;購入時の金額:485円)

f:id:tangential_star:20210128161917j:plain

有線コントローラーとArduinoの2本刺しが可能。抜き差しせずに入力を切り替えられる

 

【余談】Switch本体のJoy-conカバーと有線コントローラー

最後に余談がてら、筆者の使っているNintendoSwitch周辺機器の紹介です。

もちろん、Switch本体の種類(Switch・Switch Lite)は自動化部分(ソフトウェア部分)とは本来、直接の関係はありません。前述の通り、私はSwitchとSwitch Liteの2台持ちですが、どちらも同じプログラムで動作しています。

f:id:tangential_star:20210127233334j:plain
f:id:tangential_star:20210127233348j:plain
筆者が愛用するSwitch本体。
ピカブイカラーのJoy-conと、Amazonで買ったシリコンカバーがお気に入りだ

筆者はピカブイセットでNintendo Switchを購入したので、Joy-conがピカブイカラーにちなんだ茶色と黄色になっています。

そこで、普段からさらにテンションを上げるために、別途購入したシリコンカバーをつけています。デザインがとてつもなくかわいいので気に入っています。

ただ、スティック部のシリコンカバーがずれやすかったり、単純に切り抜いただけのシリコンなのでボタンが埋もれて押しにくくなったりと、実用には多少ネックとなる部分もあります。

普段から別途コントローラーを使ったり、Arduinoで操作を自動化したりする場合にはこのデメリットは気にならないので、普段Switch用ドックに挿しっぱなし、という人は買ってみても良いかも?(私は欲しい物は多少値が張っても買っちゃうタイプなのでいらない人はやめましょう)

(筆者購入日:2020/12/16;購入時の金額:1,399円)

 

また、有線コントローラーも、もちろん、ピカブイの物にそろえて購入しています。淡い色合いにピカチュウイーブイが単色で入っているシンプルなデザインですが、とにかくかわいいです。スティックやボタンが茶色いのもアクセントになっていてすごく好みです。

やっぱり、普段遣いのものこそ、自分の好きなものを使ってテンションを上げていきたいですもんね。

 (筆者購入日:2020/7/13;購入時の金額:2,728円)

 

 

まとめ(購入リンク集)

本稿では、実際に私が使っている機材について紹介しました。

一覧で表示したものも準備しました。下記表を御覧ください。

 

筆者の使用機材一覧

必須 商品名 画像 Amazonリンク

備考(筆者コメント)

必須 Arduino Leonardo

https://amzn.to/3pvglNJ

筆者の使用マイコン。これがないと始まらない。

必須 通信対応USBケーブル(A-microB)

https://amzn.to/3aaSJrk

探せば家に5本くらいありそう。
  Arduino用ケース

https://amzn.to/36l50IC

本当はUNO用だが、Leonardoでも騙し騙し使っている。
  USBハブスタンド

https://amzn.to/2MfLFBD

Switch Liteでは必要。
  Switchドック用USBハブスタンド

https://amzn.to/39oyxTy

純正ドックのUSBポートをより使いやすくできる。おすすめ。
  USBスイッチ付きコネクタ

https://amzn.to/2NFc0tf

USBポートにON・OFFスイッチが付く。マジでおすすめ。
  Joy-conカバー

https://amzn.to/3ckmbO3

自動化には全く不要。だが、かわいい。

  有線コントローラー

https://amzn.to/2YnN6R6

あると便利だが、これでなくても良い。かわいい。

 

あとがき

思えば、今まで記事で使用機材を紹介する機会がなかったので、自動化記事も13件と増えてきましたので、良い機会かと思ってまとめてみました。

実は、私がArduino Leonardoを購入したのが2020年1月28日です。今日が2021年1月28日ですので、Arduino Leonardoを購入してから今日でちょうど1年なんですよね

1年前の今頃は、こうやってブログを作ろうと決意するなんて考えてもなかったですし、こんなにコロナが流行るなんて夢にも思ってなかったですから、世の中ってわからないなぁ、と感じます。

 

話が逸れましたが、少なくともArduino Leonardoが1年間壊れずに動いてくれたことに感謝しつつ、これからも使い倒していきます(笑)

 

皆様も、上記機材の一覧が役に立てば何よりですし、自分に合う機材構成で自動化ライフを楽しんでいただければ幸いです。

ではではc⌒っ.ω.)っ

 

導入記事:【Arduino自動化01】Arduino開発環境の導入

番外編1: 【Arduino自動化 番外編】マイコン導入にあたって気をつけるべきと思ったこと【ポケモン自動化 方法調査】

番外編2: 【Arduino自動化 番外編2】NintendoSwitchControllライブラリの導入と、自動化できる作業の一覧【ポケモン剣盾自動化】