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

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

今回の記事は、Arduino乱数調整の一部手順と高速消費を自動化する方法についてです。乱数調整の流れにそって説明します。今回の目標は、色違いのパッチルドン(乱数レイド産)を捕まえることです。

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

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

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

 

概要

本記事では、レイド乱数調整で必要な2つの作業をArduinoで自動化します。
・1つ目:「初期シード」を推定するための2Vポケモン探し(3日進める作業)
・2つ目:「ランクマバグ」状態での乱数消費(日付を進める作業)
※便宜上「ランクマバグ」と表記しますが、当ブログではランクマッチを使用しません。通信切断・初手降参の推奨もしません。

2020/12/5追記:NintendoSwitch Ver.11.0アップデート対応済です。
2021/9/20追記:NintendoSwitch Ver.13.0アップデート対応済です。
2022/10/23追記:NintendoSwitch Ver.15.0アップデート対応済です。

 

2021/3/28追記:補足記事を執筆しました。Arduinoを使う具体的なタイミングについてもう少し詳しく知りたい、という方向けの記事です。合わせてご参考ください。

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

f:id:tangential_star:20201122220708g:plain
f:id:tangential_star:20201122220734g:plain
「シード特定用の3日後レイド厳選」と「高速乱数消費」をArduinoで自動化
(左:リセットして3日日付を進める 右:ランクマバグ状態で日付変更)

 

なお、本記事では乱数調整ツールは、さびたコイル氏の「1-StarSeedSearch」を使います。記事のメインは、Arduino Leonardoによる一部手順の自動化になりますが、乱数調整の忘備録も兼ねた構成で書きますので、Arduinoを持っていない人も乱数を始めたばかりorこれから始めるよっていう人にも読めるよう書いているつもりです。
(丸2日間かけてできるだけ丁寧に書きました。是非とも参考にしてください)

「いや、ソースコードと使い方だけ寄越せ」って方はどうぞ→ソースコードと使い方

 

目次です(もりだくさん!)。

 

作ったきっかけ

前回の記事では、色違いパッチルドンを、自動カセキ受け取りで厳選する方法 について紹介しました。今回は、どうしても色パッチルドンの「ボール厳選」がしたくて、DLCでレイドバトルが解禁されたパッチルドンの色乱数に挑戦しました。結論、紆余曲折ありましたが成功しました。

f:id:tangential_star:20201123113607g:plain
f:id:tangential_star:20201123113647g:plain
待ちに待った色パッチルドンのお出まし!かわいいいいい!!!

剣盾レイドの乱数調整では、手動だとめちゃくちゃ大変な部分が2つあります。中でもArduinoの価値が活きたのは、「何百日~何千日も日付を進める手順(乱数消費)」だと思います。こちらは流石に手作業では骨が折れる…というか、ミスの温床なのでArduinoで自動化しようというわけです。また、最初の厳選作業(3日日付を進めてツール指定の★3レイドが出るまでひたすらやり直す作業)も地味に大変で、運が悪いと何度も挑戦することになります。ゆえに、こちらも自動化しました。

 

大前提

本記事では「乱数調整」の手順に沿った構成で書き下します。乱数調整の紹介をメインとする記事ではありませんので原理やツールの使い方、導入手順などの紹介は最小限に留めます。ソースコードと使い方だけ必要な方は適宜読み飛ばしてください。

 ⇒ 「ソースコードと使い方」まで読み飛ばす

ただし、Arduinoの自動化は、あくまでも乱数調整の手順を簡略化するだけですので、全く予備知識がない状態で自動化を試みるのはリスクがあります。一度でも良いので、手動で乱数調整を試みてから、Arduinoプログラムを使って自動化してみることを筆者としてはおすすめいたします。

なお、乱数調整は改造・セーブデータの改竄とは違い、正規仕様の範囲内で出現するポケモンの性別や個体値、色違いの別を操作するものです。本稿で乱数調整の是非は問いませんが、本件ご理解の上、閲覧・活用くださいませ。

 

色パッチルドン探しの手順

パッチルドンの色違いを捕まえるまでは大きく4ステップあります。かなり長丁場ですが、オシャボ入り色違いパッチルドンのために頑張りましょう!

  1. 準備
    (パッチルドンが出る巣穴にねがいのかたまりを投げ入れる)
  2. 乱数調整
    (乱数ツールで、色違いが出るまでの日数を計算)
  3. 乱数消費
    (計算日数-3日だけ日にちをひたすら進める)
  4. 捕獲
    (手動で3日進めてパッチルドンを捕まえる)

なお、手順上に「@自動化可能」と書いているものは、Arduino Leonardoでの自動化プログラムを提供しています。適宜ご活用ください。ソースコード後述します

1.準備パート

【色パッチルドン探しの手順】
1.準備
(イマココ) → 2.乱数調整 → 3.乱数消費 → 4.捕獲
(1-1. 乱数調整ツールを準備 1-2.目的の巣穴で柱を建てる)
1-1.乱数調整ツール(PC)を準備

まずは、乱数調整ツールをPCにダウンロードします。本稿では、さびたコイル氏がGPL3.0ライセンスで提供する「1-StarSeedSearch」を使います。自身のPC環境に合ったものをダウンロード・解凍してください。筆者はWindows10(64bit)です。

起動したら、自身のバージョン・目的の巣穴に合わせて選択します。目的の巣穴の情報は、yakkun氏が運営するポケモン攻略サイトポケモン徹底攻略」で検索して拾ってください。パッチルドンの場合は「雪中渓谷 G」「レア」でOKです。

f:id:tangential_star:20201122010711p:plain
f:id:tangential_star:20201122010727p:plain
1-StarSeedSearchをダウンロード&ZIP解凍し、OneStar.exeを起動
f:id:tangential_star:20201122010741p:plain
f:id:tangential_star:20201122010903p:plain
起動したら、パッチルドンの巣穴の場所(雪中渓谷G・レア)をプルダウン入力
1-2.目的の巣穴で柱を建てる

ツールへの入力を済ませたら、該当の巣穴に「ねがいのかたまり」を投げ入れて光の柱を立てます。パッチルドンの巣穴の場合は、入り口から登っていくよりも、カンムリ神殿から道なりに下ったほうがスムーズに到着できます。

「ねがいのかたまり」を投げ入れたら、念の為セーブをしておきます

なお、パッチルドンは紫の柱からしか出現しませんので、注意しましょう。

f:id:tangential_star:20201122014031p:plain
f:id:tangential_star:20201122014103p:plain
パッチルドンは雪中渓谷にいる。お気に入りのボールを準備しておこう。
f:id:tangential_star:20201122013234g:plain
f:id:tangential_star:20201122010634p:plain
パッチルドンの巣穴へはカンムリ神殿から下っていくとスムーズに着く

2.乱数調整パート

【色パッチルドン探しの手順】
1.準備 → 2.乱数調整(イマココ) → 3.乱数消費 → 4.捕獲
(2-1. 現在シードの特定 2-2.消費数の特定)
2-1.現在シードの特定

ここからは乱数調整の要となる、「初期シード値」の推定を行います。推定と言っても我々ではなくツールが計算してくれますのでご安心を。ただし、かなり運の要素が絡むため、この部分だけで下手すると1日が終わります。

2-1-1.3日後のオムスター探し @自動化可能

まずは、3回日付を進めた上で、自然発生Vを除いて2Vのポケモン(難しければ3Vのポケモン)を捕まえます。具体的なターゲットはツールに表示されます。

パッチルドンの巣穴では、3回日付を進めて「★3 オムスター」のレイドが出るまで粘ります。出なかったらセーブせずにリセットしてもう一度繰り返しこの手順を行ってください。自動化プログラム(ソースコードは後述)は、このリセットを含めて対応しています。

※妥協する場合は3V個体が出るレイド「★3 パッチルドン」「★3 プテラ」でも可能です。ただし、ここで妥協すると、今後の作業でかなりのマシンスペックが必要となるのでPCスペックに余裕が無い場合はお控えください。また、成功率が下がるという報告もあります(筆者は未検証)。

f:id:tangential_star:20201122021129p:plain
f:id:tangential_star:20201122021040g:plain
「みんなで挑戦!」から日付変更を3度繰り返し、★3オムスターが出ればOK
2-1-2.オムスター捕獲と個体値チェック

おそらくここが一番の鬼門(究極の運ゲ)。沼にハマると時にはまともに色違い厳選したほうが楽なのでは?と思うほどの苦行です(決して乱数は「楽」ではない)

手順2-1-1で見つけたオムスターを捕まえます。その性格・個性・個体値(わからなければLv100にしたステータスから計算)をツール入力、「個体値チェック」ボタンを押してください。あまり出ませんが「OK」が出たら、セーブせずにリセットして手順2-1-3 に進んでください。第1関門にして最大の鬼門をクリアです(ちなみに2Vレイドで「OK」が出る確率は1/3です。運が良ければすぐにクリアできます)。

「NG」が出てもセーブせずにリセットし、その後、改めて「みんなで挑戦」で日付を1日進めてからセーブします。そして、手順2-1-1に戻ってください

f:id:tangential_star:20201122030252g:plain
f:id:tangential_star:20201122031447p:plain
オムスターを捕まえて性格や能力値をチェック。Lv100にするとわかりやすい
f:id:tangential_star:20201122145808p:plain
f:id:tangential_star:20201122145819p:plain
能力を入れて「個体値チェック」。OKが出る確率は3割程度なので根気強くやろう
2-1-3.指示に従い、3日後の個体を探す @自動化可能

第1関門突破、おめでとうございます。喜び勇んでセーブしないよう、くれぐれも注意してくださいね(リセットして同じ柱から続きをやります)。

続いて、同じく3日後の個体を探します。ツールの「OK! Next ->」の後に「3V」「4V」「3V or 4V」など、次のターゲットの指示が記載されているので、それに従います。自動化プログラム(ソースコードは後述)をそのまま使えます。

例えば、今回の巣穴であればターゲットはそれぞれ

  • 「Next -> 3V」なら、★3 パッチルドン、★3 プテラ
  • 「Next -> 4V」なら、★3 パッチラゴン、★3 パッチルドン、★4 パッチラゴン
  • 「Next -> 3V or 4V」なら、上記いずれも可能(3Vの方をおすすめ)

…となります。手順2-1-1と同様に、ターゲットを見つけて捕まえます。捕まえたら、個体値をツールに入力して、セーブせずにリセットして次へ進んでください。

なお、Vの数が指定と異なる場合、計算ミスでなければ初期シード推定が不可能になる場合があります。セーブせずにリセットし、その後、改めて「みんなで挑戦」で日付を1日進めてからセーブしてから手順2-1-1に戻るか、続けるか選んでください。

f:id:tangential_star:20201122152955p:plain

指示に従って次のターゲットを決める。複数選べる場合はVが少ないほうがおすすめ
f:id:tangential_star:20201122160131g:plain
f:id:tangential_star:20201122161045p:plain
ターゲットを捕まえて個体値を確認。Lv100にするとわかりやすい

f:id:tangential_star:20201122161205p:plain

個体値を入力したら次へ。この時点でVの数が指定通りかを確認しておく
2-1-4.極力Vの少ない4日後の個体を探す @自動化可能

今までの手順と同様に、今度は「4日後」ポケモンを捕まえます。指定は特に無いので、好きなポケモンを選んでください。なお、Vの数が少ないほうがマシンスペックを食わずに済むので、もし心許ないPCを利用している方は極力Vが少ないものを選びましょう。また、精度の問題から、複数の初期シード候補が見つかることを防ぐためにも、Vの数は少ないほうがおすすめです。

※Vの数は、自然発生「ではない」Vの数です。ゆえに、2Vのポケモンを捕まえて3V以上でないことを確認するのが最も確実ですが、ミスを防ぐためにあえて5Vのポケモンを選び、6Vじゃ無いことを確認するのも有効です

捕まえたら手順2-1-3同様、個体値をツールに入力してください。そして、入力が終わったら、セーブせずにリセットしてください。自動化プログラム(ソースコードは後述)は、対応箇所を「3」から「4」に書き換えることで利用できます。

f:id:tangential_star:20201122162203p:plain

最後のステップでは「4日後」のポケモンを捕まえる。肝心なので間違えないように注意!

2-2.消費数の特定

ここまでお疲れさまでした。これで、3つの項目すべてが埋まったことだと思います。あとは、意気揚々と「検索開始」を押すだけです。計算時間がかなりかかります。マシンスペックにもよりますが、 「1つ見つけたら終了」にチェックを入れた状態なら、NVIDIAGPUグラボを積んだPCであれば10秒もかからずに検索可能です。普通に計算すると10分くらいかかるそうです。

なお、ここもマシンスペックとの相談ですが、運に自信がない人は右下の「1つ見つけたら終了」のチェックボックスは外しておいてください。推定された初期シードが複数候補が見つかっていた場合に、それに気づけず、その後の作業がすべて無駄になってしまう恐れがあるからです。

f:id:tangential_star:20201122175957p:plain

「検索開始」を押す前に確認しておく。グラボ設定は該当者のみでOK
2-2-1.推定初期シードの検証(シード特定作業を兼ねる)

「計算開始」を押してからしばらくすると、推定リスト(推定された初期Seedに基づいた消費数と個体値・色違いの有無)がテキストファイルで出てきます。この際、複数の初期シード(ツール上ではDen Seed)が候補になった場合、その旨を表すダイアログも出てきますので、見逃さないように注意しましょう。

このseeds.txtの行をまるまるコピーし、「1-StarSeedSearch」の「リスト出力」タブのDen Seedに入れてリスト出力すると、レイドの内容と推定されたSeed条件で、それぞれ出てくる能力の羅列が出てきます。なお、複数候補がでてきた場合、これらはツールに渡した情報(3日後・4日後のポケモン個体値や性格など)はすべて共通して満たしています。

ゆえに、複数の初期シード候補が出てきた場合は、6日目(5日後)以降でVの数が少ないレイドで比較検証することで、正しい初期シードを絞り込むことができます

f:id:tangential_star:20201122180338p:plain
f:id:tangential_star:20201122180347p:plain
推定された初期シードが複数見つかった場合、「seeds.txt」ができているので確認

f:id:tangential_star:20201122182950p:plain

候補ごとの結果と実際の結果で比較すれば正しいシードが特定できる
f:id:tangential_star:20201122190453g:plain
f:id:tangential_star:20201122190602p:plain
日付を(5回以上)回してオムスターが出ればラッキー。捕まえてリストと比較しよう
2-2-2.色違いが何日先に出現するかを調べる

次に、「色違いのみ」にチェックを入れて、「リスト出力」を押してください。もし、結果が何も出てこなければ適宜「最大消費数」を増やして出力してください。消費数とは、要するに次の手順で進める必要のある日数のことです。

なお、手順2-2-1で必ず「初期シードが正しいこと」を確認した上で以降の手順を進めてください。この特定が曖昧のままだと、これからの作業はすべて水の泡になります。 

f:id:tangential_star:20201122192117p:plain
f:id:tangential_star:20201122192425p:plain
「色違いのみ」にチェックを入れると、何日後に色違いレイドが出現するかが分かる

一応、今回の私の例で言うと、Seed=0x 3DC5C8246ECEC24C で、19046日後に星エフェクトの色違いレイドになることがわかります。

 

3.乱数消費パート

【色パッチルドン探しの手順】
1.準備 → 2.乱数調整 → 3.乱数消費(イマココ) → 4.捕獲
(3-1. ランクマバグ状態に移行 3-2. 乱数消費する)
3-1.ランクマバグ状態に移行

ここからは手順2-2-2で確認した「目標個体までの日数」を目指して、日付をひたすらすすめていきます。なお、目標までの消費数(日付を回す回数)が100日程度であれば、手動で変更することをおすすめします。

まず、効率よく日付を進めるために、ランクマッチやYY通信のカジュアルバトルで機内モードに変更した際に日付変更ペナルティが解除されるバグ(通称:ランクマバグ)を活用します。まずは、巣穴の前からポケモンセンターに移動してください。 

そして、ランクマバグ状態に下記手順で移行します。なお、この方法が使えない人は、素直にランクマッチで1戦してください(Nintendo Onlineへの加入が必要です)。

  1. ポケモンセンターの中に入る
  2. YY通信で「通信対戦」を行う(ローカル通信)
  3. もう一台のSwitch・剣盾を使ってその通信対戦に応じる
  4. 戦闘が始まったらHomeボタン長押し→「機内モード」をONに変更する
  5. エラーが発生するのでそれを閉じて、「にげる」選択
  6. ポケモンセンターに戻ってくる(移行完了)

この状態で、一度Home画面に戻り、日付を1日進めて、ゲーム画面に戻ってください。一瞬だけ画面全体がチラッと暗転していれば、正常にランクマバグ状態に移行できています。

f:id:tangential_star:20201122212921p:plain
f:id:tangential_star:20201122212902p:plain
ランクマバグ状態に入る前に、まずはブラッシータウンのポケセンに入ろう
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
エラーが出たら「にげる」で対戦終了。この状態で時刻変更すると一瞬画面が暗転する
3-2.乱数消費する @自動化可能

手順3-1でランクマバグ状態になると、日付変更のペナルティが発生しなくなります。さらに「設定で日付を変更してゲーム画面に戻った瞬間」ではなく「日付を変更した瞬間」にゲーム中でも日付変更が反映されるようになります。つまり、設定画面の中で日付を変更し、「OK」を押すたびにゲーム中の日付も同じ回数だけ進んでいることになります。したがって、Home画面などを介する必要がなくなるため、日付変更が1日あたり約2秒という驚きの速さで実現可能になります(ソースコードは後述)。

この状態で、手順2-2-2で確認した「目標個体までの日数」までひたすら進めていくのですが、実際に進めるのは「目標の日数-3日間」となることに注意してください。原理は割愛しますが、例えば目標の日数が「19046日後」なら、この手順で消費するのは19046-3=「19043日」となります。

f:id:tangential_star:20201123121934g:plain

ゲーム画面に戻る必要はない。ひたすら日付を進めていこう

目安までに、自動化プログラム(ソースコードは後述)で日付を1ヶ月進めるのに実測値で42秒かかりました。ざっくりアバウトで5000日分を2時間くらいで消費できます。もしかしたら、消費上限数はこの値を参考に決めても良いかもしれません。

 

消費する日数と、実際にかかる時間(Arduino Leonardo用プログラム利用時)

消費する日数 自動化プログラムで
かかる時間(推定)
備考
1日 約1.4秒  
30日 42秒(実測値) ※31日分日付変更
100日 約140秒(2分20秒)  
200日 約280秒(4分40秒) この辺から手動だとツライ
300日 約420秒(7分)  
365日 約511秒(8分31秒)  
720日 約1022秒(約17分) 経験上、手動の限界
1000日 約1400秒(23分20秒)  
2000日 約2800秒(46分40秒)  
2500日 約3500秒(58分20秒) 約1時間
5000日 約7000秒(116分40秒) 約2時間
10000日 約14000秒(3時間54分) 約4時間
15000日 約21000秒(350分) 約6時間
20000日 約28000秒(700分) 約8時間

 

4.捕獲パート

【色パッチルドン探しの手順】
1.準備 → 2.乱数調整 → 3.乱数消費 → 4.捕獲(イマココ)
(4-1. 残りの消費数確認 4-2. 3日後のパッチルドン探し 4-3. 捕獲!)
4-1.残りの消費数を確かめる

目的消費数の概ね10日くらい前まで消費が終わったら、まずは巣穴の前に戻り、セーブします(無論、最初から自信があれば目的消費数の3日前でも問題ありません)。

そして、巣穴に出ているポケモンを捕まえます。捕まえたら、個体値を計算してください。レイドの情報をもとに乱数調整ツールでリストを出力し、その個体値と性格の組み合わせがどこにいるかを確認してください。これが、「目的の消費数-3」に重なれば準備完了です。なお、現在位置を調べるためにポケモンを捕まえたら、必ずセーブせずにリセットしてください

現在位置が、「目的消費数-3」に届いていない場合は、巣穴の「みんなで挑戦」から日付を1日ずつ進めてください。ちょうど「目的消費数-3」の位置にいる場合はセーブして次の手順に進んでください。

f:id:tangential_star:20201123145601p:plain
f:id:tangential_star:20201123145639p:plain
巣穴に戻って出ているポケモンを捕まえる。レイド★の数確認も忘れずに
f:id:tangential_star:20201123145747g:plain
f:id:tangential_star:20201123145742p:plain
捕まえたら個体値チェックだ。性格・能力値・特性・性別なども忘れずチェック

f:id:tangential_star:20201123151702p:plain

リスト出力し、現在の個体がどのくらい離れているかを確認しよう

f:id:tangential_star:20201123153210p:plain

現在位置が「目的の消費数-3」になるまでズレを計算して進めていこう
4-2.3日後のパッチルドンを探そう!

ここまで長らくお疲れさまでした。あとは、パッチルドンを探すだけです。

感の良い方・ここまで読んでくれた方はお気づきかと思いますが、巣穴のレイドバトルは2日後まで出現するポケモンが決定しており、3日後以降はランダムになっています。ゆえに、現在位置が「目的消費数-3」のタイミングでセーブしたわけです。

では、3回日付を進めて「★3 パッチルドン」「★4 パッチルドン」「★5 パッチルドン」のレイドが出るまで粘りましょう。出なかったらセーブせずにリセットしてもう一度この手順を行ってください。出たら、セーブして次の手順に進みます。

この流れは、手順2-1-1と完全に同様ですね。一応、2-1-1で使った自動化プログラム(ソースコードは後述)でも同じことができるのですが、最後くらいは自力でやったほうが、喜びがひとしおだと思います。

f:id:tangential_star:20201123155836g:plain
f:id:tangential_star:20201125115703p:plain
3日進めてパッチルドンが来たら終了だ。忘れずにセーブしておこう

ちなみに、パッチルドンが出たらセーブするのが本来の流れなのですが、代わりに「キャンプ」を開くのも有効です。万が一、日付を多く進めてしまった場合の保険になります(キャンプであればセーブしないためリセットでやり直しができます)。ここでは詳細は割愛しますが、興味のある方は「キャンプバックアップ」で調べてみてください。Switchと剣盾を2組持っている場合には、ひたすらサブロム側で色違い手に入れ続けることもできます。

 

4-3.パッチルドンの捕獲

本当にここまでお疲れさまでした。あとは、お好きなボールを使ってパッチルドンを捕まえるだけです。

パッチルドンはキョダイマックス個体が無いので、「一人で挑戦」の場合にはどのボールを投げても捕獲率は100%になるはずですが、本当に捕まるか心配な人や「みんなで挑戦」で色違いレイドを配布する場合には、挑戦前に必ずセーブをしておきましょう。

f:id:tangential_star:20201123113607g:plain
f:id:tangential_star:20201123161659g:plain
待ちに待った色パッチルドン。好きなボールを投げよう!

f:id:tangential_star:20201123134007p:plain

色パッチルドンは全体的にグレーの色合い。レイドで大きくなってもかわいい

 

ソースコードと使い方

読み飛ばしてここまで来た方に向けて一応説明をしておくと、今回は2つのソースコードを作成しています。それぞれ使い方も合わせて載せますのでご参考ください。

1つ目→「3日後の巣穴厳選」 2つ目→「高速乱数消費

ソースコード1:「3日後の巣穴厳選」

このプログラムは、「リセット」⇒「ゲーム起動」⇒「巣穴から『みんなで挑戦』を押して日付進める」をTIME_WARP_DAYS回繰り返す ⇒「TIME_WARP_DAYS日分日付を戻す」という一連の流れを自動化してくれます。基本的に厳選1回目・2回目は「3」、3回目は「4」になるかと思います。適宜数字を調整して活用ください。

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

なお、現在の日時から起算してTIME_WARP_DAYS日進めて月をまたぐ場合には日付がズレてしまいます(例えば、2月27日や12月30日などから3日進めたら月をまたぐためNG)。現在の日時を調整するか、この値を+1するなどで対応してください。

使い方のイメージとしては、

  1. プログラムをArduinoに書き込む
  2. 「ねがいのかたまり」を入れて柱を建てる
  3. セーブする
  4. Arduinoを差し込む
  5. 動作が止まるまで放置
  6. 目的のレイドか確認。違った場合はArduinoを挿し直す(4に戻る)

となります。挿し直すだけで、リセット含めて3日後のレイドの内容確認まで放置ができるので、繰り返しの際には重宝します。

f:id:tangential_star:20201123132507g:plain
f:id:tangential_star:20201123010702g:plain
自動で日付が進み、募集画面で待機してくれる。目的のレイドでなかったら挿し直そう

もし、このリセットが冗長だと感じる場合には、PROTO_AUTO_GAME_QUITをfalseにしてください。その場合は「みんなで挑戦」の手前でArduinoを挿してください。

ではプログラムのソースコードです。

2020/12/5追記:NintendoSwitch Ver.11.0アップデート対応済(変更点はこちら

2021/9/20追記:NintendoSwitch Ver.13.0アップデート対応済(詳細はこちら

2022/10/23追記:NintendoSwitch Ver.15.0アップデート対応済
※Switch Liteをご利用の方は「#define SWITCH_VER (15)」を「#define SWITCH_VER (12)」に書き換えてご利用ください。

/* ★NintendoSwitchのファームウェアVer11に対応版(2020/12/1)★
 * ★NintendoSwitchのファームウェアVer13に対応版(2021/9/20)★
 * ★NintendoSwitchのファームウェアVer15に対応版(2022/10/23)★
 * 
 * 日付はTIME_WARP_DAYS日進めても、月がまたがないようにしておくこと。
 * あとは自動で日付巻き戻しもしてくれるので繰り返し利用もできます。
*/

#include <SwitchControlLibrary.h>

#define HOLDTIME (95)
#define INTERVAL (105)
#define TIME_WARP_DAYS (3) // 何日すすめるか(=ここは基本的に「3」。最後のステップで使うなら「4」)
#define FIRST_DAY_WATT_EARNING (false) // 1日手動で進めた場合など、Watt回収をしていない場合は「true」にしてください。
#define PROTO_AUTO_GAME_QUIT (true) // trueなら挿し直すだけで再起動も行ってくれるようになる

#define SWITCH_VER (15)
// 2021/9/20、SwitchのVer13アップデートに伴う追記
// Switchのバージョンを整数で入力(例:12.2.1⇒12, 13.0.0⇒13, 15.0.0→15)

int current_days;

void PushHome(int delay_time_ms);
void PushA(int delay_time_ms);
void PushB(int delay_time_ms);
void PushX(int delay_time_ms);
void PushR(int delay_time_ms);
void PushL(int delay_time_ms);
void PushRL(int delay_time_ms);
void move_for(char* Direction); // ex: "right" "left" "up" "down"
void move_for(char* Direction, int delay_time_ms);
void move_for(char* Direction, int hold_time_ms, int delay_time_ms);

void setup() {
  PushRL(300);
  PushRL(300);
  PushRL(300);
  PushRL(300);
  PushRL(300);


  delay(1000);
  
  if(PROTO_AUTO_GAME_QUIT){
    PushHome(1000); // ゲーム終了のためにホームを押し。
    PushX(500); // 終了Xを押す→終了しますか?画面
    PushA(3000); // はい→終了しています・・・
    PushA(1000); // ゲームタイトルクリック→ユーザを選んでください画面(複数ユーザいる場合)
    PushA(18500); // A押してから起動までおおよそ16秒(最短目安。環境に合わせて設定すること)
    PushA(10000); // タイトル画面からフィールド遷移までおおよそ10秒(環境に合わせて設定すること)
    // if(!FIRST_DAY_WATT_EARNING)PushA(1500); // 募集画面に明示的に入る <- chinese対応
  }
  current_days = 0;

  if(FIRST_DAY_WATT_EARNING){
    // ★フィールド画面に戻ってくる(watt回収)
    // There's energy pouring out from the den! [Enter]
    PushA(500);  // 1回目は「A」
    // You gained 2,000W! [Quit]
    PushB(500);  // 2回目は「B」
  }
}

void loop() {

  // [Enter]
  PushA(1500);  // 3回目は「A」(募集画面に入る)

  if(current_days >= TIME_WARP_DAYS ){
    // TIME_WARP_DAYS日進めたあとの処理として、日付を戻す。
    PushA(4000); // 通信待機中・・・
    PushHome(1000);
    // Home画面で「設定」を選ぶ
    move_for("down");move_for("right");move_for("right");move_for("right");move_for("right");move_for("right");
    PushA(1500);
 
    // 設定画面で「日付と時刻」を開く
    move_for("down", 1500, (int)INTERVAL/4);move_for("right");

#if (SWITCH_VER >= 15)
  // Switchのver15アプデでBluetoothオーディオの設定が変わった?ので、微修正。
  // ※本体のバッテリー残量(%)にずれるようになったので。
  move_for("down", (int)750, (int)INTERVAL); 
#elif (SWITCH_VER >= 13)
  // Switchのアプデで「ドックの更新」項目が追加されたので
  // 日付変更をする場合には「↓」キー長押しが必要に。
  move_for("down", (int)780, (int)INTERVAL/2); 
#else
  // ver12まで(13アプデ前)は、1ページに収まるのでそのままでOK
  for(int i=0; i<4; i++){
    move_for("down", (int)HOLDTIME/2, (int)INTERVAL/2);
  }
#endif

    PushA(500);
  
    // 時間設定(現在の日付と時刻を選ぶ)
    move_for("down");
    move_for("down");
    PushA(500);
  
    // 時刻設定(日付の部分のみ回していく
    // 時間の変更
    move_for("right");
    move_for("right");
    for(int i=0;i<TIME_WARP_DAYS;i++) move_for("down"); // 日付巻き戻し
    PushA(INTERVAL);
    PushA(INTERVAL);
    PushA(INTERVAL);
    PushA(INTERVAL);
    PushHome(2000);
    PushA(1000);
    // ↑ここまでで設定画面おわり。
  
    // 募集終了処理
    PushB(500);  // 「募集終了」を選択
    PushA(1000); // 「はい」
    PushA(4500); // 「はい」

    // フィールドに戻ったら募集待機画面状態で待機
    PushA(4000); // 通信待機中・・・
    for(;;)delay(1000);  
  }


  // 開始 みんなで挑戦の直前から(1日目もWatt回収がある前提)。
  PushA(4000); // 通信待機中・・・
  
  // Homeボタンを押して設定の画面へ移動
  PushHome(1000);

  // Home画面で「設定」を選ぶ
  move_for("down");
  move_for("right");
  move_for("right");
  move_for("right");
  move_for("right");
  move_for("right");
  PushA(1500);

  // 設定画面で「日付と時刻」を開く

  move_for("down", 1500, (int)INTERVAL/4); // 「↓」長押し
  move_for("right");

#if (SWITCH_VER >= 15)
  // Switchのver15アプデでBluetoothオーディオの設定が変わった?ので、微修正。
  // ※本体のバッテリー残量(%)にずれるようになったので。
  move_for("down", (int)750, (int)INTERVAL); 
#elif (SWITCH_VER >= 13)
    // Switchのアプデで「ドックの更新」項目が追加されたので
    // 日付変更をする場合には「↓」キー長押しが必要に。
    move_for("down", (int)780, (int)INTERVAL/2); 
#else
    // ver12まで(13アプデ前)は、1ページに収まるのでそのままでOK
    for(int i=0; i<4; i++){
      move_for("down", (int)HOLDTIME/2, (int)INTERVAL/2);
    }
#endif
  PushA(500);

  // 時間設定(現在の日付と時刻を選ぶ)
  move_for("down");
  move_for("down");
  PushA(500);

  // 時刻設定(日付の部分のみ回していく
  // 時間の変更
  move_for("right");
  move_for("right");
  move_for("up");
  PushA(INTERVAL);
  PushA(INTERVAL);
  PushA(INTERVAL);
  PushA(INTERVAL);
  PushHome(2000);
  PushA(1000);
  // ↑ここまでで設定画面おわり。

  // 募集終了処理
  PushB(750);  // 「募集終了」を選択 // 500->750 chinese対応
  PushA(1000); // 「はい」
  PushA(4500); // 「はい」

  // ★フィールド画面に戻ってくる(watt回収)
  // There's energy pouring out from the den! [Enter]
  PushA(500);  // 1回目は「A」
  // You gained 2,000W! [Quit]
  PushB(1500);  // 2回目は「B」

  current_days++;

}

void PushHome(int delay_time_ms){
  SwitchControlLibrary().PressButtonHome();
  delay(210);
  SwitchControlLibrary().ReleaseButtonHome();
  delay(delay_time_ms);
  return;
}

void PushA(int delay_time_ms){
  SwitchControlLibrary().PressButtonA();
  delay(HOLDTIME);
  SwitchControlLibrary().ReleaseButtonA();
  delay(delay_time_ms);
  return;
}
void PushB(int delay_time_ms){
  SwitchControlLibrary().PressButtonB();
  delay(HOLDTIME);
  SwitchControlLibrary().ReleaseButtonB();
  delay(delay_time_ms);
  return;
}
void PushX(int delay_time_ms){
  SwitchControlLibrary().PressButtonX();
  delay(HOLDTIME);
  SwitchControlLibrary().ReleaseButtonX();
  delay(delay_time_ms);
  return;
}
void PushR(int delay_time_ms){
  SwitchControlLibrary().PressButtonR();
  delay(HOLDTIME);
  SwitchControlLibrary().ReleaseButtonR();
  delay(delay_time_ms);
  return;
}
void PushL(int delay_time_ms){
  SwitchControlLibrary().PressButtonL();
  delay(HOLDTIME);
  SwitchControlLibrary().ReleaseButtonL();
  delay(delay_time_ms);
  return;
}
void PushRL(int delay_time_ms){
  SwitchControlLibrary().PressButtonR();
  SwitchControlLibrary().PressButtonL();
  delay(HOLDTIME);
  SwitchControlLibrary().ReleaseButtonR();
  SwitchControlLibrary().ReleaseButtonL();
  delay(delay_time_ms);
  return;
}

void move_for(char* Direction){
  // ex: "right" "left" "up" "down"
  
  switch(Direction[0]){
    case 'r':
    case 'R':
    SwitchControlLibrary().MoveHat(2); // right
    delay(HOLDTIME);
    SwitchControlLibrary().MoveHat(8); // center
    delay(INTERVAL);
    break;

    case 'l':
    case 'L':
    SwitchControlLibrary().MoveHat(6); // left
    delay(HOLDTIME);
    SwitchControlLibrary().MoveHat(8); // center
    delay(INTERVAL);
    break;

    case 'u':
    case 'U':
    SwitchControlLibrary().MoveHat(0); // up
    delay(HOLDTIME);
    SwitchControlLibrary().MoveHat(8); // center
    delay(INTERVAL);
    break;

    case 'd':  
    case 'D':
    SwitchControlLibrary().MoveHat(4); // down
    delay(HOLDTIME);
    SwitchControlLibrary().MoveHat(8); // center
    delay(INTERVAL);
    break;

    default:
    break;  
  }
  
}

void move_for(char* Direction, int delay_time){
  // ex: "right" "left" "up" "down"
  
  switch(Direction[0]){
    case 'r':
    case 'R':
    SwitchControlLibrary().MoveHat(2); // right
    delay(HOLDTIME);
    SwitchControlLibrary().MoveHat(8); // center
    delay(delay_time);
    break;

    case 'l':
    case 'L':
    SwitchControlLibrary().MoveHat(6); // left
    delay(HOLDTIME);
    SwitchControlLibrary().MoveHat(8); // center
    delay(delay_time);
    break;

    case 'u':
    case 'U':
    SwitchControlLibrary().MoveHat(0); // up
    delay(HOLDTIME);
    SwitchControlLibrary().MoveHat(8); // center
    delay(delay_time);
    break;

    case 'd':  
    case 'D':
    SwitchControlLibrary().MoveHat(4); // down
    delay(HOLDTIME);
    SwitchControlLibrary().MoveHat(8); // center
    delay(delay_time);
    break;

    default:
    break;  
  }
  
}

void move_for(char* Direction, int hold_time_ms, int delay_time_ms){
  // ex: "right" "left" "up" "down"
  
  switch(Direction[0]){
    case 'r':
    case 'R':
    SwitchControlLibrary().MoveHat(2); // right
    delay(hold_time_ms);
    SwitchControlLibrary().MoveHat(8); // center
    delay(delay_time_ms);
    break;

    case 'l':
    case 'L':
    SwitchControlLibrary().MoveHat(6); // left
    delay(hold_time_ms);
    SwitchControlLibrary().MoveHat(8); // center
    delay(delay_time_ms);
    break;

    case 'u':
    case 'U':
    SwitchControlLibrary().MoveHat(0); // up
    delay(hold_time_ms);
    SwitchControlLibrary().MoveHat(8); // center
    delay(delay_time_ms);
    break;

    case 'd':  
    case 'D':
    SwitchControlLibrary().MoveHat(4); // down
    delay(hold_time_ms);
    SwitchControlLibrary().MoveHat(8); // center
    delay(delay_time_ms);
    break;

    default:
    break;  
  }

}

 

ソースコード2:「高速乱数消費」

このプログラムは、ランクマバグ状態で日付を自動で進めるプログラムです。あらかじめSHOHISUを「(目的消費数-3)」に書き換えてから使ってください。

プログラムを横着したので、31日まである月(1月・3月・5月・7月・8月・10月・12月)で使ってください。また、消費数を31で割って月繰り上がり(31日→1日)のズレ吸収を行っている単純なプログラムなので、もしかしたら消費数がズレているかもしれません。なので、実際は、「目的消費数-10」くらいで設定しておき、あとは手動で検証しながら進めることをおすすめします。

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

2021/1/26追記:
このSHOHISUの上限は「32767」となります。もし、32768以上の乱数消費が必要な場合、2回に分けて自動化をするなどで工夫してください。

 

使い方としては、

  1. プログラムを書き換え、Arduinoに書き込んでおく
  2. ポケモンセンターに入る
  3. ランクマバグ状態にする
  4. Homeボタンを押し、設定→本体→日付と時刻→現在の日付と時刻から、何も変更せずに「OK」を押しておく【重要】
  5. Arduinoを差し込んで放置

になります。注意としては、上記4にも書いている通り、一度日付変更画面に入り、OKを押しておいてください(カーソルの位置が変わるからです)。もし、この4の手順すら面倒だと感じる方はFIRST_TIMEを(true)にしてください。

f:id:tangential_star:20201123142146p:plain
f:id:tangential_star:20201123121934g:plain
時刻設定で「OK」を押しておくと、カーソルが「OK」から始まるので高速に消費ができる

特に難しいところも無いと思います。

プログラムのソースコードです。

2020/12/5追記:こちらはNintendoSwitch Ver.11.0アップデートの影響はありません
2021/9/20追記:こちらはNintendoSwitch Ver.13.0アップデートの影響はありません

/* 消費日数の計算はかなり甘めに作っているので、注意してください。
●ランクマバグ後につかうこと。
●31日ある月にしておくこと。
^^^^^^^^^^^^^^^^^^^^^^^
*/

#include <SwitchControlLibrary.h>

#define HOLDTIME (40)
#define INTERVAL (105)
#define FIRST_TIME (false)

#define SHOHISU (19046-3) // ここを「目的消費数-3」にする。
// ※実際には-10くらいにして、残りを手動でやったほうが良いかもです。

int maxlooptime;
int currentlooptime;

void PushHome(int delay_time_ms);
void PushA(int delay_time_ms);
void PushB(int delay_time_ms);
void PushR(int delay_time_ms);
void PushL(int delay_time_ms);
void move_for(char* Direction); // ex: "right" "left" "up" "down"
void move_for(char* Direction, int delay_time_ms);
void move_for(char* Direction, int hold_time_ms, int delay_time_ms);
void Debug(void);

void setup() {
  if(FIRST_TIME){
    PushR(100);
    PushL(100);
    PushR(100);
    PushL(100);
    PushR(100);
    PushL(100);
    delay(10000);
  }else{
    PushR(100);
    PushL(100);
    PushR(100);
    PushL(100);
    PushR(100);
    PushL(100);
    PushR(100);
    PushL(100);
    delay(3000);
  }

  
  // 現在のループ回数を数える変数
  currentlooptime = 0;

  // 31日ごとに消費できる数は30なので31試行ごとに1試行分のモレが発生。それを計算。
  maxlooptime = (int)( (double)SHOHISU + (double)SHOHISU/31.0 ); 


  // first time
  if(FIRST_TIME){
    PushA(3000);
    
    PushA(250);
    PushA(250);
    move_for("up");
    PushA(250);
    PushA(250);
    PushA(250);
    PushA(250);
    currentlooptime++;
  }
  delay(1000);

}

void loop() {

  if(currentlooptime >= maxlooptime ){
    PushHome(1000);
    for(;;)delay(1000);  
  }

  PushA(INTERVAL);
  delay(20);
  move_for("left");
  move_for("left");
  move_for("left");
  move_for("up");
  PushA(INTERVAL);
  PushA(INTERVAL);
  PushA(INTERVAL);
  PushA(INTERVAL);
  currentlooptime++;
  delay(20);
}

void PushHome(int delay_time_ms){
  SwitchControlLibrary().PressButtonHome();
  delay(210);
  SwitchControlLibrary().ReleaseButtonHome();
  delay(delay_time_ms);
  return;
}

void PushA(int delay_time_ms){
  SwitchControlLibrary().PressButtonA();
  delay(HOLDTIME);
  SwitchControlLibrary().ReleaseButtonA();
  delay(delay_time_ms);
  return;
}
void PushB(int delay_time_ms){
  SwitchControlLibrary().PressButtonB();
  delay(HOLDTIME);
  SwitchControlLibrary().ReleaseButtonB();
  delay(delay_time_ms);
  return;
}
void PushR(int delay_time_ms){
  SwitchControlLibrary().PressButtonR();
  delay(HOLDTIME);
  SwitchControlLibrary().ReleaseButtonR();
  delay(delay_time_ms);
  return;
}
void PushL(int delay_time_ms){
  SwitchControlLibrary().PressButtonL();
  delay(HOLDTIME);
  SwitchControlLibrary().ReleaseButtonL();
  delay(delay_time_ms);
  return;
}void move_for(char* Direction){
  // ex: "right" "left" "up" "down"
  
  switch(Direction[0]){
    case 'r':
    case 'R':
    SwitchControlLibrary().MoveHat(2); // right
    delay(HOLDTIME);
    SwitchControlLibrary().MoveHat(8); // center
    delay(INTERVAL);
    break;

    case 'l':
    case 'L':
    SwitchControlLibrary().MoveHat(6); // left
    delay(HOLDTIME);
    SwitchControlLibrary().MoveHat(8); // center
    delay(INTERVAL);
    break;

    case 'u':
    case 'U':
    SwitchControlLibrary().MoveHat(0); // up
    delay(HOLDTIME);
    SwitchControlLibrary().MoveHat(8); // center
    delay(INTERVAL);
    break;

    case 'd':  
    case 'D':
    SwitchControlLibrary().MoveHat(4); // down
    delay(HOLDTIME);
    SwitchControlLibrary().MoveHat(8); // center
    delay(INTERVAL);
    break;

    default:
    break;  
  }
  
}

void move_for(char* Direction, int delay_time){
  // ex: "right" "left" "up" "down"
  
  switch(Direction[0]){
    case 'r':
    case 'R':
    SwitchControlLibrary().MoveHat(2); // right
    delay(HOLDTIME);
    SwitchControlLibrary().MoveHat(8); // center
    delay(delay_time);
    break;

    case 'l':
    case 'L':
    SwitchControlLibrary().MoveHat(6); // left
    delay(HOLDTIME);
    SwitchControlLibrary().MoveHat(8); // center
    delay(delay_time);
    break;

    case 'u':
    case 'U':
    SwitchControlLibrary().MoveHat(0); // up
    delay(HOLDTIME);
    SwitchControlLibrary().MoveHat(8); // center
    delay(delay_time);
    break;

    case 'd':  
    case 'D':
    SwitchControlLibrary().MoveHat(4); // down
    delay(HOLDTIME);
    SwitchControlLibrary().MoveHat(8); // center
    delay(delay_time);
    break;

    default:
    break;  
  }
  
}

void move_for(char* Direction, int hold_time_ms, int delay_time_ms){
  // ex: "right" "left" "up" "down"
  
  switch(Direction[0]){
    case 'r':
    case 'R':
    SwitchControlLibrary().MoveHat(2); // right
    delay(hold_time_ms);
    SwitchControlLibrary().MoveHat(8); // center
    delay(delay_time_ms);
    break;

    case 'l':
    case 'L':
    SwitchControlLibrary().MoveHat(6); // left
    delay(hold_time_ms);
    SwitchControlLibrary().MoveHat(8); // center
    delay(delay_time_ms);
    break;

    case 'u':
    case 'U':
    SwitchControlLibrary().MoveHat(0); // up
    delay(hold_time_ms);
    SwitchControlLibrary().MoveHat(8); // center
    delay(delay_time_ms);
    break;

    case 'd':  
    case 'D':
    SwitchControlLibrary().MoveHat(4); // down
    delay(hold_time_ms);
    SwitchControlLibrary().MoveHat(8); // center
    delay(delay_time_ms);
    break;

    default:
    break;  
  }

}

void Debug(){
  // Homeボタンを2回押すだけの関数
  PushHome(1000);
  PushHome(1000);
  return;  
  
}

 

あとがき

今回は、乱数調整をベースにArduinoを活用して、色パッチルドンを見つける記事を書きました。前回の記事では、パッチルドンをウカッツから自動で受け取って色違いを厳選する方法を紹介しましたが、やっぱりレイド産はボール厳選ができることが何よりも強みですね。

ただし、モンスターボール以外で捕まえると自ずとレイド産とバレてしまうという点は注意が必要です。レイド産のパッチルドンは必ず夢特性になるので「ゆきかき」で意表を突くことが難しくなり、「ちくでん」ではないことを自ら告白することになります。

とはいえ、タマゴ未発見のオシャボ入りというだけでその価値は天井知らずですから、そんなのは些細な問題に過ぎないかもしれませんね。私も今回、サファリボールで捕まえましたし。

 

ところで、乱数を今まで知らなかった人にとっては、かなり「大変」だと思ったのではないでしょうか。また、乱数を知っている人も、文章にするとかなり長くなると感じたのではないでしょうか。どちらが楽かという議論ではなく、乱数調整は厳選と同じく手間暇がかかる作業です。その点、Arduinoであれば、乱数・厳選を問わず簡略化や効率化ができるという点あるいは可能性にも気づいていただけたのではないかと思います。

これを読んでArduinoのユーザーが増えたり、コミュニティが活性になったりを期待しています。また、プログラミングや組み込み系への興味、はたまたゲームへの興味などが増えるとより嬉しいですね。

 

パッチルドンかわいい(余談)

さて。突然ですが、こちらを御覧ください。

f:id:tangential_star:20201123163741g:plain
f:id:tangential_star:20201123163828p:plain
パッチルドンは歩くのが苦手なのだ
f:id:tangential_star:20201123164331g:plain
f:id:tangential_star:20201123165307g:plain
キャンプではよちよち歩いてくる。戦闘では可憐に登場するぞ

執筆中ずっと思ってたんですけど、パッチルドンって本当にかわいらしいですよね。 

いや、コイツめちゃくちゃかわいくないですか?? 

何がって、たぶんチャームポイントは鼻水だと思うんですよ。上のgif画像でも分かると思いますが、念の為0.5倍速と0.16倍速を準備しましたので、下記にて御覧ください(あと、捕まえたボール「サファリボール」のエフェクトもご確認ください)。

f:id:tangential_star:20201123171250g:plain
f:id:tangential_star:20201123171313g:plain
はなみずに着目!かわいいぞ!!(左:0.5倍速/右:0.16倍速)

 いやぁ。良いんじゃないでしょうか…。

 

てなわけで今回はこのへんで。

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

 

 

補足記事(Arduinoの使い方・使うタイミングについての詳しい解説はこちら):

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

  

前記事:

【Arduino自動化04】パッチルドン自動受け取り(中国語・英語対応)

次記事:

【Arduino自動化06】完全放置「マックスこうせき」集め【ダイマックスアドベンチャー】

導入記事:

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