ますたーです。こんにちは。
今回の記事は、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の使い方
なお、本記事では乱数調整ツールは、さびたコイル氏の「1-StarSeedSearch」を使います。記事のメインは、Arduino Leonardoによる一部手順の自動化になりますが、乱数調整の忘備録も兼ねた構成で書きますので、Arduinoを持っていない人も乱数を始めたばかりorこれから始めるよっていう人にも読めるよう書いているつもりです。
(丸2日間かけてできるだけ丁寧に書きました。是非とも参考にしてください)
「いや、ソースコードと使い方だけ寄越せ」って方はどうぞ→ソースコードと使い方
目次です(もりだくさん!)。
作ったきっかけ
前回の記事では、色違いパッチルドンを、自動カセキ受け取りで厳選する方法 について紹介しました。今回は、どうしても色パッチルドンの「ボール厳選」がしたくて、DLCでレイドバトルが解禁されたパッチルドンの色乱数に挑戦しました。結論、紆余曲折ありましたが成功しました。
剣盾レイドの乱数調整では、手動だとめちゃくちゃ大変な部分が2つあります。中でもArduinoの価値が活きたのは、「何百日~何千日も日付を進める手順(乱数消費)」だと思います。こちらは流石に手作業では骨が折れる…というか、ミスの温床なのでArduinoで自動化しようというわけです。また、最初の厳選作業(3日日付を進めてツール指定の★3レイドが出るまでひたすらやり直す作業)も地味に大変で、運が悪いと何度も挑戦することになります。ゆえに、こちらも自動化しました。
大前提
本記事では「乱数調整」の手順に沿った構成で書き下します。乱数調整の紹介をメインとする記事ではありませんので原理やツールの使い方、導入手順などの紹介は最小限に留めます。ソースコードと使い方だけ必要な方は適宜読み飛ばしてください。
⇒ 「ソースコードと使い方」まで読み飛ばす
ただし、Arduinoの自動化は、あくまでも乱数調整の手順を簡略化するだけですので、全く予備知識がない状態で自動化を試みるのはリスクがあります。一度でも良いので、手動で乱数調整を試みてから、Arduinoプログラムを使って自動化してみることを筆者としてはおすすめいたします。
なお、乱数調整は改造・セーブデータの改竄とは違い、正規仕様の範囲内で出現するポケモンの性別や個体値、色違いの別を操作するものです。本稿で乱数調整の是非は問いませんが、本件ご理解の上、閲覧・活用くださいませ。
色パッチルドン探しの手順
パッチルドンの色違いを捕まえるまでは大きく4ステップあります。かなり長丁場ですが、オシャボ入り色違いパッチルドンのために頑張りましょう!
- 準備
(パッチルドンが出る巣穴にねがいのかたまりを投げ入れる)
- 乱数調整
(乱数ツールで、色違いが出るまでの日数を計算)
- 乱数消費
(計算日数-3日だけ日にちをひたすら進める)
- 捕獲
(手動で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です。
1-2.目的の巣穴で柱を建てる
ツールへの入力を済ませたら、該当の巣穴に「ねがいのかたまり」を投げ入れて光の柱を立てます。パッチルドンの巣穴の場合は、入り口から登っていくよりも、カンムリ神殿から道なりに下ったほうがスムーズに到着できます。
「ねがいのかたまり」を投げ入れたら、念の為セーブをしておきます。
なお、パッチルドンは紫の柱からしか出現しませんので、注意しましょう。
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スペックに余裕が無い場合はお控えください。また、成功率が下がるという報告もあります(筆者は未検証)。
おそらくここが一番の鬼門(究極の運ゲ)。沼にハマると時にはまともに色違い厳選したほうが楽なのでは?と思うほどの苦行です(決して乱数は「楽」ではない)。
手順2-1-1で見つけたオムスターを捕まえます。その性格・個性・個体値(わからなければLv100にしたステータスから計算)をツール入力、「個体値チェック」ボタンを押してください。あまり出ませんが「OK」が出たら、セーブせずにリセットして手順2-1-3 に進んでください。第1関門にして最大の鬼門をクリアです(ちなみに2Vレイドで「OK」が出る確率は1/3です。運が良ければすぐにクリアできます)。
「NG」が出てもセーブせずにリセットし、その後、改めて「みんなで挑戦」で日付を1日進めてからセーブします。そして、手順2-1-1に戻ってください。
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に戻るか、続けるか選んでください。
2-1-4.極力Vの少ない4日後の個体を探す @自動化可能
今までの手順と同様に、今度は「4日後」のポケモンを捕まえます。指定は特に無いので、好きなポケモンを選んでください。なお、Vの数が少ないほうがマシンスペックを食わずに済むので、もし心許ないPCを利用している方は極力Vが少ないものを選びましょう。また、精度の問題から、複数の初期シード候補が見つかることを防ぐためにも、Vの数は少ないほうがおすすめ※です。
※Vの数は、自然発生「ではない」Vの数です。ゆえに、2Vのポケモンを捕まえて3V以上でないことを確認するのが最も確実ですが、ミスを防ぐためにあえて5Vのポケモンを選び、6Vじゃ無いことを確認するのも有効です
捕まえたら手順2-1-3同様、個体値をツールに入力してください。そして、入力が終わったら、セーブせずにリセットしてください。自動化プログラム(ソースコードは後述)は、対応箇所を「3」から「4」に書き換えることで利用できます。
2-2.消費数の特定
ここまでお疲れさまでした。これで、3つの項目すべてが埋まったことだと思います。あとは、意気揚々と「検索開始」を押すだけです。計算時間がかなりかかります。マシンスペックにもよりますが、 「1つ見つけたら終了」にチェックを入れた状態なら、NVIDIA製GPUグラボを積んだPCであれば10秒もかからずに検索可能です。普通に計算すると10分くらいかかるそうです。
なお、ここもマシンスペックとの相談ですが、運に自信がない人は右下の「1つ見つけたら終了」のチェックボックスは外しておいてください。推定された初期シードが複数候補が見つかっていた場合に、それに気づけず、その後の作業がすべて無駄になってしまう恐れがあるからです。
2-2-1.推定初期シードの検証(シード特定作業を兼ねる)
「計算開始」を押してからしばらくすると、推定リスト(推定された初期Seedに基づいた消費数と個体値・色違いの有無)がテキストファイルで出てきます。この際、複数の初期シード(ツール上ではDen Seed)が候補になった場合、その旨を表すダイアログも出てきますので、見逃さないように注意しましょう。
このseeds.txtの行をまるまるコピーし、「1-StarSeedSearch」の「リスト出力」タブのDen Seedに入れてリスト出力すると、レイドの内容と推定されたSeed条件で、それぞれ出てくる能力の羅列が出てきます。なお、複数候補がでてきた場合、これらはツールに渡した情報(3日後・4日後のポケモンの個体値や性格など)はすべて共通して満たしています。
ゆえに、複数の初期シード候補が出てきた場合は、6日目(5日後)以降でVの数が少ないレイドで比較検証することで、正しい初期シードを絞り込むことができます。
2-2-2.色違いが何日先に出現するかを調べる
次に、「色違いのみ」にチェックを入れて、「リスト出力」を押してください。もし、結果が何も出てこなければ適宜「最大消費数」を増やして出力してください。消費数とは、要するに次の手順で進める必要のある日数のことです。
なお、手順2-2-1で必ず「初期シードが正しいこと」を確認した上で以降の手順を進めてください。この特定が曖昧のままだと、これからの作業はすべて水の泡になります。
一応、今回の私の例で言うと、Seed=0x 3DC5C8246ECEC24C で、19046日後に星エフェクトの色違いレイドになることがわかります。
3.乱数消費パート
【色パッチルドン探しの手順】
1.準備 → 2.乱数調整 → 3.乱数消費(イマココ) → 4.捕獲(3-1. ランクマバグ状態に移行 3-2. 乱数消費する)
3-1.ランクマバグ状態に移行
ここからは手順2-2-2で確認した「目標個体までの日数」を目指して、日付をひたすらすすめていきます。なお、目標までの消費数(日付を回す回数)が100日程度であれば、手動で変更することをおすすめします。
まず、効率よく日付を進めるために、ランクマッチやYY通信のカジュアルバトルで機内モードに変更した際に日付変更ペナルティが解除されるバグ(通称:ランクマバグ)を活用します。まずは、巣穴の前からポケモンセンターに移動してください。
そして、ランクマバグ状態に下記手順で移行します。なお、この方法が使えない人は、素直にランクマッチで1戦してください(Nintendo Onlineへの加入が必要です)。
- ポケモンセンターの中に入る
- YY通信で「通信対戦」を行う(ローカル通信)
- もう一台のSwitch・剣盾を使ってその通信対戦に応じる
- 戦闘が始まったらHomeボタン長押し→「機内モード」をONに変更する
- エラーが発生するのでそれを閉じて、「にげる」選択
- ポケモンセンターに戻ってくる(移行完了)
この状態で、一度Home画面に戻り、日付を1日進めて、ゲーム画面に戻ってください。一瞬だけ画面全体がチラッと暗転していれば、正常にランクマバグ状態に移行できています。
3-2.乱数消費する @自動化可能
手順3-1でランクマバグ状態になると、日付変更のペナルティが発生しなくなります。さらに「設定で日付を変更してゲーム画面に戻った瞬間」ではなく「日付を変更した瞬間」にゲーム中でも日付変更が反映されるようになります。つまり、設定画面の中で日付を変更し、「OK」を押すたびにゲーム中の日付も同じ回数だけ進んでいることになります。したがって、Home画面などを介する必要がなくなるため、日付変更が1日あたり約2秒という驚きの速さで実現可能になります(ソースコードは後述)。
この状態で、手順2-2-2で確認した「目標個体までの日数」までひたすら進めていくのですが、実際に進めるのは「目標の日数-3日間」となることに注意してください。原理は割愛しますが、例えば目標の日数が「19046日後」なら、この手順で消費するのは19046-3=「19043日」となります。
目安までに、自動化プログラム(ソースコードは後述)で日付を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」の位置にいる場合はセーブして次の手順に進んでください。
4-2.3日後のパッチルドンを探そう!
ここまで長らくお疲れさまでした。あとは、パッチルドンを探すだけです。
感の良い方・ここまで読んでくれた方はお気づきかと思いますが、巣穴のレイドバトルは2日後まで出現するポケモンが決定しており、3日後以降はランダムになっています。ゆえに、現在位置が「目的消費数-3」のタイミングでセーブしたわけです。
では、3回日付を進めて「★3 パッチルドン」「★4 パッチルドン」「★5 パッチルドン」のレイドが出るまで粘りましょう。出なかったらセーブせずにリセットしてもう一度この手順を行ってください。出たら、セーブして次の手順に進みます。
この流れは、手順2-1-1と完全に同様ですね。一応、2-1-1で使った自動化プログラム(ソースコードは後述)でも同じことができるのですが、最後くらいは自力でやったほうが、喜びがひとしおだと思います。
ちなみに、パッチルドンが出たらセーブするのが本来の流れなのですが、代わりに「キャンプ」を開くのも有効です。万が一、日付を多く進めてしまった場合の保険になります(キャンプであればセーブしないためリセットでやり直しができます)。ここでは詳細は割愛しますが、興味のある方は「キャンプバックアップ」で調べてみてください。Switchと剣盾を2組持っている場合には、ひたすらサブロム側で色違い手に入れ続けることもできます。
4-3.パッチルドンの捕獲
本当にここまでお疲れさまでした。あとは、お好きなボールを使ってパッチルドンを捕まえるだけです。
パッチルドンはキョダイマックス個体が無いので、「一人で挑戦」の場合にはどのボールを投げても捕獲率は100%になるはずですが、本当に捕まるか心配な人や「みんなで挑戦」で色違いレイドを配布する場合には、挑戦前に必ずセーブをしておきましょう。
読み飛ばしてここまで来た方に向けて一応説明をしておくと、今回は2つのソースコードを作成しています。それぞれ使い方も合わせて載せますのでご参考ください。
1つ目→「3日後の巣穴厳選」 2つ目→「高速乱数消費」
このプログラムは、「リセット」⇒「ゲーム起動」⇒「巣穴から『みんなで挑戦』を押して日付進める」をTIME_WARP_DAYS回繰り返す ⇒「TIME_WARP_DAYS日分日付を戻す」という一連の流れを自動化してくれます。基本的に厳選1回目・2回目は「3」、3回目は「4」になるかと思います。適宜数字を調整して活用ください。
#define TIME_WARP_DAYS (3)
なお、現在の日時から起算してTIME_WARP_DAYS日進めて月をまたぐ場合には日付がズレてしまいます(例えば、2月27日や12月30日などから3日進めたら月をまたぐためNG)。現在の日時を調整するか、この値を+1するなどで対応してください。
使い方のイメージとしては、
- プログラムをArduinoに書き込む
- 「ねがいのかたまり」を入れて柱を建てる
- セーブする
- Arduinoを差し込む
- 動作が止まるまで放置
- 目的のレイドか確認。違った場合はArduinoを挿し直す(4に戻る)
となります。挿し直すだけで、リセット含めて3日後のレイドの内容確認まで放置ができるので、繰り返しの際には重宝します。
もし、このリセットが冗長だと感じる場合には、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)」に書き換えてご利用ください。
#include <SwitchControlLibrary.h>
#define HOLDTIME (95)
#define INTERVAL (105)
#define TIME_WARP_DAYS (3)
#define FIRST_DAY_WATT_EARNING (false)
#define PROTO_AUTO_GAME_QUIT (true)
#define SWITCH_VER (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);
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);
PushA(3000);
PushA(1000);
PushA(18500);
PushA(10000);
}
current_days = 0;
if(FIRST_DAY_WATT_EARNING){
PushA(500);
PushB(500);
}
}
void loop() {
PushA(1500);
if(current_days >= TIME_WARP_DAYS ){
PushA(4000);
PushHome(1000);
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)
move_for("down", (int)750, (int)INTERVAL);
#elif (SWITCH_VER >= 13)
move_for("down", (int)780, (int)INTERVAL/2);
#else
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);
}
PushA(4000);
PushHome(1000);
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)
move_for("down", (int)750, (int)INTERVAL);
#elif (SWITCH_VER >= 13)
move_for("down", (int)780, (int)INTERVAL/2);
#else
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);
PushA(1000);
PushA(4500);
PushA(500);
PushB(1500);
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){
switch(Direction[0]){
case 'r':
case 'R':
SwitchControlLibrary().MoveHat(2);
delay(HOLDTIME);
SwitchControlLibrary().MoveHat(8);
delay(INTERVAL);
break;
case 'l':
case 'L':
SwitchControlLibrary().MoveHat(6);
delay(HOLDTIME);
SwitchControlLibrary().MoveHat(8);
delay(INTERVAL);
break;
case 'u':
case 'U':
SwitchControlLibrary().MoveHat(0);
delay(HOLDTIME);
SwitchControlLibrary().MoveHat(8);
delay(INTERVAL);
break;
case 'd':
case 'D':
SwitchControlLibrary().MoveHat(4);
delay(HOLDTIME);
SwitchControlLibrary().MoveHat(8);
delay(INTERVAL);
break;
default:
break;
}
}
void move_for(char* Direction, int delay_time){
switch(Direction[0]){
case 'r':
case 'R':
SwitchControlLibrary().MoveHat(2);
delay(HOLDTIME);
SwitchControlLibrary().MoveHat(8);
delay(delay_time);
break;
case 'l':
case 'L':
SwitchControlLibrary().MoveHat(6);
delay(HOLDTIME);
SwitchControlLibrary().MoveHat(8);
delay(delay_time);
break;
case 'u':
case 'U':
SwitchControlLibrary().MoveHat(0);
delay(HOLDTIME);
SwitchControlLibrary().MoveHat(8);
delay(delay_time);
break;
case 'd':
case 'D':
SwitchControlLibrary().MoveHat(4);
delay(HOLDTIME);
SwitchControlLibrary().MoveHat(8);
delay(delay_time);
break;
default:
break;
}
}
void move_for(char* Direction, int hold_time_ms, int delay_time_ms){
switch(Direction[0]){
case 'r':
case 'R':
SwitchControlLibrary().MoveHat(2);
delay(hold_time_ms);
SwitchControlLibrary().MoveHat(8);
delay(delay_time_ms);
break;
case 'l':
case 'L':
SwitchControlLibrary().MoveHat(6);
delay(hold_time_ms);
SwitchControlLibrary().MoveHat(8);
delay(delay_time_ms);
break;
case 'u':
case 'U':
SwitchControlLibrary().MoveHat(0);
delay(hold_time_ms);
SwitchControlLibrary().MoveHat(8);
delay(delay_time_ms);
break;
case 'd':
case 'D':
SwitchControlLibrary().MoveHat(4);
delay(hold_time_ms);
SwitchControlLibrary().MoveHat(8);
delay(delay_time_ms);
break;
default:
break;
}
}
このプログラムは、ランクマバグ状態で日付を自動で進めるプログラムです。あらかじめSHOHISUを「(目的消費数-3)」に書き換えてから使ってください。
プログラムを横着したので、31日まである月(1月・3月・5月・7月・8月・10月・12月)で使ってください。また、消費数を31で割って月繰り上がり(31日→1日)のズレ吸収を行っている単純なプログラムなので、もしかしたら消費数がズレているかもしれません。なので、実際は、「目的消費数-10」くらいで設定しておき、あとは手動で検証しながら進めることをおすすめします。
#define SHOHISU (19046-3)
2021/1/26追記:
このSHOHISUの上限は「32767」となります。もし、32768以上の乱数消費が必要な場合、2回に分けて自動化をするなどで工夫してください。
使い方としては、
- プログラムを書き換え、Arduinoに書き込んでおく
- ポケモンセンターに入る
- ランクマバグ状態にする
- Homeボタンを押し、設定→本体→日付と時刻→現在の日付と時刻から、何も変更せずに「OK」を押しておく【重要】
- Arduinoを差し込んで放置
になります。注意としては、上記4にも書いている通り、一度日付変更画面に入り、OKを押しておいてください(カーソルの位置が変わるからです)。もし、この4の手順すら面倒だと感じる方はFIRST_TIMEを(true)にしてください。
特に難しいところも無いと思います。
プログラムのソースコードです。
2020/12/5追記:こちらはNintendoSwitch Ver.11.0アップデートの影響はありません
2021/9/20追記:こちらはNintendoSwitch Ver.13.0アップデートの影響はありません
#include <SwitchControlLibrary.h>
#define HOLDTIME (40)
#define INTERVAL (105)
#define FIRST_TIME (false)
#define SHOHISU (19046-3)
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);
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;
maxlooptime = (int)( (double)SHOHISU + (double)SHOHISU/31.0 );
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){
switch(Direction[0]){
case 'r':
case 'R':
SwitchControlLibrary().MoveHat(2);
delay(HOLDTIME);
SwitchControlLibrary().MoveHat(8);
delay(INTERVAL);
break;
case 'l':
case 'L':
SwitchControlLibrary().MoveHat(6);
delay(HOLDTIME);
SwitchControlLibrary().MoveHat(8);
delay(INTERVAL);
break;
case 'u':
case 'U':
SwitchControlLibrary().MoveHat(0);
delay(HOLDTIME);
SwitchControlLibrary().MoveHat(8);
delay(INTERVAL);
break;
case 'd':
case 'D':
SwitchControlLibrary().MoveHat(4);
delay(HOLDTIME);
SwitchControlLibrary().MoveHat(8);
delay(INTERVAL);
break;
default:
break;
}
}
void move_for(char* Direction, int delay_time){
switch(Direction[0]){
case 'r':
case 'R':
SwitchControlLibrary().MoveHat(2);
delay(HOLDTIME);
SwitchControlLibrary().MoveHat(8);
delay(delay_time);
break;
case 'l':
case 'L':
SwitchControlLibrary().MoveHat(6);
delay(HOLDTIME);
SwitchControlLibrary().MoveHat(8);
delay(delay_time);
break;
case 'u':
case 'U':
SwitchControlLibrary().MoveHat(0);
delay(HOLDTIME);
SwitchControlLibrary().MoveHat(8);
delay(delay_time);
break;
case 'd':
case 'D':
SwitchControlLibrary().MoveHat(4);
delay(HOLDTIME);
SwitchControlLibrary().MoveHat(8);
delay(delay_time);
break;
default:
break;
}
}
void move_for(char* Direction, int hold_time_ms, int delay_time_ms){
switch(Direction[0]){
case 'r':
case 'R':
SwitchControlLibrary().MoveHat(2);
delay(hold_time_ms);
SwitchControlLibrary().MoveHat(8);
delay(delay_time_ms);
break;
case 'l':
case 'L':
SwitchControlLibrary().MoveHat(6);
delay(hold_time_ms);
SwitchControlLibrary().MoveHat(8);
delay(delay_time_ms);
break;
case 'u':
case 'U':
SwitchControlLibrary().MoveHat(0);
delay(hold_time_ms);
SwitchControlLibrary().MoveHat(8);
delay(delay_time_ms);
break;
case 'd':
case 'D':
SwitchControlLibrary().MoveHat(4);
delay(hold_time_ms);
SwitchControlLibrary().MoveHat(8);
delay(delay_time_ms);
break;
default:
break;
}
}
void Debug(){
PushHome(1000);
PushHome(1000);
return;
}
あとがき
今回は、乱数調整をベースにArduinoを活用して、色パッチルドンを見つける記事を書きました。前回の記事では、パッチルドンをウカッツから自動で受け取って色違いを厳選する方法を紹介しましたが、やっぱりレイド産はボール厳選ができることが何よりも強みですね。
ただし、モンスターボール以外で捕まえると自ずとレイド産とバレてしまうという点は注意が必要です。レイド産のパッチルドンは必ず夢特性になるので「ゆきかき」で意表を突くことが難しくなり、「ちくでん」ではないことを自ら告白することになります。
とはいえ、タマゴ未発見のオシャボ入りというだけでその価値は天井知らずですから、そんなのは些細な問題に過ぎないかもしれませんね。私も今回、サファリボールで捕まえましたし。
ところで、乱数を今まで知らなかった人にとっては、かなり「大変」だと思ったのではないでしょうか。また、乱数を知っている人も、文章にするとかなり長くなると感じたのではないでしょうか。どちらが楽かという議論ではなく、乱数調整は厳選と同じく手間暇がかかる作業です。その点、Arduinoであれば、乱数・厳選を問わず簡略化や効率化ができるという点あるいは可能性にも気づいていただけたのではないかと思います。
これを読んでArduinoのユーザーが増えたり、コミュニティが活性になったりを期待しています。また、プログラミングや組み込み系への興味、はたまたゲームへの興味などが増えるとより嬉しいですね。
パッチルドンかわいい(余談)
さて。突然ですが、こちらを御覧ください。
執筆中ずっと思ってたんですけど、パッチルドンって本当にかわいらしいですよね。
いや、コイツめちゃくちゃかわいくないですか??
何がって、たぶんチャームポイントは鼻水だと思うんですよ。上のgif画像でも分かると思いますが、念の為0.5倍速と0.16倍速を準備しましたので、下記にて御覧ください(あと、捕まえたボール「サファリボール」のエフェクトもご確認ください)。
いやぁ。良いんじゃないでしょうか…。
てなわけで今回はこのへんで。
ではではc⌒っ.ω.)っ
補足記事(Arduinoの使い方・使うタイミングについての詳しい解説はこちら):
【Arduino自動化05ex】乱数調整レイドでのArduino Leonardoの使い方
前記事:
【Arduino自動化04】パッチルドン自動受け取り(中国語・英語対応)
次記事:
【Arduino自動化06】完全放置「マックスこうせき」集め【ダイマックスアドベンチャー】
導入記事:
【Arduino自動化01】Arduino開発環境の導入