見出し画像

【Arduino Leonardo】自動どうぐプリンター乱数調整(1連→5連×2)【ポケモン】


はじめに

どうぐプリンター乱数調整ができるようになったのでArduino LeonardoでポケモンSVのどうぐプリンター乱数調整(1連→5連×2)を自動化しました。
ライブラリはNintendoSwitchControll-masterを使用しています。導入方法等はこちらでは説明しませんのでリンク先や他サイトを参考にしてください。
ポケモンSVは処理落ちやエラー落ち等発生する場合があるため長時間放置するのは自己責任でお願いいたします。

道具プリンター乱数調整とは

簡単に説明するとプリントする日時(秒単位)で結果が決まっているので、欲しい道具が出る日時に変更してプリントすることです。
詳しくはこちら。

プリント設定もほとんどこちらから使わせていただいています。

プログラムについて

1連1回してレアボールチャンスを引いた後5連2回するのを非売品ボール分ループで回します。秒ズレしなければ5連中マスボは4個、他は5個出ます。

事前準備

ゲーム内設定で「話のはやさ」を「はやい」にしてください。

プリントするために必要なBPと落とし物を集めておいてください。落とし物はおまかせで消費していきます。

プリントする回数を1回に設定します。

プリント回数を1回にする

「プリントする!」の画面まで進めます。

この画面

上記画面から日付設定画面まで進み、1連レアボールチャンスの日時(初期設定 2057年1月10日 12時42分)にしてカーソルがOKの所にある状態でプログラムを実行してください。

この状態でプログラム実行

プログラム(コード)

以下コピペしてください。不要なボールは実行有無の「1」を「0」に変えると飛ばすようになります。秒設定は環境によると思うのでずれる場合は0.1秒単位で微調整してください。+0.1秒→+10、-0.1秒→-10です。

※2024/4/28 一連の動作を関数にまとめました。変数名、関数名を一部変更しました。一部ボタン連打に変更しました。59分設定で1分繰り上がり1時間増えた際に減らす処理を追加しました。チャンス中に回す日付が29日以上の場合、日付変更時にずれないように対応しました。1分経過するか微妙な範囲を少し広げました。

#include <auto_command_util.h>

int i,j,k;
int PrintSet[5];//差分保存用、年月日時分
int checkSec;//1分経過するか微妙な秒数判定用
int checkDay;//CTPrint29日以上の際の処理に使用

//年,月,日,時,分,秒*10 で入力
//1分経過した場合の処理の都合上、以下はNG
//待機3秒以内.3秒以上かつ+1分で日付が変わる.63秒以上
int OnePrint[6]={2057,1,10,12,42,210};//1連チャンス発生日時

//年,月,日,時,分,秒*10, 実行有無(有1無0) で入力
//1分経過した場合の処理の都合上、以下はNG
//3秒以内.13秒以上かつ+1分で日付が変わる.73秒以上
int CTPrint[12][7]={//チャンス中にプリントする日時
  //初期設定seedの秒-1(ずれる場合は各自0.1秒単位で微調整)
  {2041,2,13,9,36,100,1},//マスター
  {2042,10,14,5,56,320,1},//ムーン
  {2023,5,22,5,36,100,1},//ラブラブ
  {2034,9,1,2,33,380,1},//スピード
  {2057,11,21,4,28,360,1},//ルアー
  {2029,7,24,11,53,100,1},//ヘビー
  {2046,12,11,2,23,160,1},//フレンド
  {2045,3,17,10,5,370,1},//レベル
  {2009,6,5,20,17,100,1},//コンペ
  {2049,1,2,1,20,210,1},//サファリ
  {2043,10,23,16,32,440,1},//ドリーム
  {2037,2,2,15,37,140,1},//ウルトラ
};

void setup() {
  pushButton(Button::ZL, 500, 5);//switchに認識させる為に無駄打ちをしておく
}

void loop() {

//プリントする回数は1回に設定する//「プリントする!」待機状態でOnePrintの日付にしてカーソルをOKの位置でスタート

//マスタ-~ウルトラまでループ
  for(i=0;i<12;i++){
  
    //実行有の場合1連→5連*2プリント
    if(CTPrint[i][6]==1){
      
      //1連設定からチャンス中設定の差を計算
      for(j=0;j<5;j++){
        PrintSet[j]=OnePrint[j]-CTPrint[i][j];
      }
      checkDay=CTPrint[i][2]-28;//29日以上の場合0より大きくなる
      
      //◆チャンス発生1連~チャンス中に回す日付設定まで
      StartPrint(1,OnePrint[4],OnePrint[5],'R');
      //1連、1連の分設定、1連の秒設定、回す回数1→5に変更
      //1連→10連の場合はRをLに変更

      //◆5連1回目~5連2回目に回す日付設定まで
      StartPrint(5*1,CTPrint[i][4],CTPrint[i][5],'0');
      //5連1回目、5連の分設定、5連の秒設定、回す回数変更なしなので0
      //1連→10連の場合は削除(//で消す)
      
      //◆5連2回目~チャンス発生1連の日付設定まで
      StartPrint(5*2,CTPrint[i][4],CTPrint[i][5],'L');
      //5連2回目、5連の分設定、5連の秒設定、回す回数5→1に変更
      //1連→10連の場合はLをRに変更
    }
  }
}

//●ホーム画面から日時変更画面へ
void FromHomeToDay(){//5200ミリ秒
  // ホーム画面 > 設定
  pushButton(Button::HOME, 600);
  pushHatButton(Hat::DOWN, 30);
  pushHatButton(Hat::RIGHT, 30, 5);
  pushButton(Button::A, 480);
  // 設定 > 本体 > 日付と時刻
  pushHatButtonContinuous(Hat::DOWN, 1750);
  pushHatButton(Hat::RIGHT, 30);
  pushHatButton(Hat::DOWN, 30, 4);
  pushButton(Button::A, 280);
  // 日付と時刻 > 現在の日付と時刻
  pushHatButton(Hat::DOWN, 30, 2);
}

//●1.1連,5連1,5連2,10連、2.プリントする分設定、3.プリントする秒設定値、4.LR0
void StartPrint(int nowPrint,int PrintMin,int PrintSec,char LR){
  
  //日付決定~プリント~「プリントする!」待機状態まで
  pushButton(Button::A,100);//日付決定
  pushButton(Button::HOME,1200);//HOME画面へ
  pushButton(Button::A, 900);//ゲーム画面へ.ここまでで2500ミリ秒
  for(j=0;j<(PrintSec-25)/300;j++){
    delay(30000);//最長30秒待ち
  }
  delay((PrintSec-25)%300*100);//30秒未満待ち

  //プリントする~ハンドルを回すまで.入力漏れ対策XA連打
  for(j=0;j<60;j++){//12000
    SwitchController().pressButton(Button::X);
    SwitchController().pressButton(Button::A);
    delay(100);
    SwitchController().releaseButton(Button::X);
    SwitchController().releaseButton(Button::A);
    delay(100);
  }
  delay(10000);
  pushButton(Button::A,1000);//結果表示
  pushButton(Button::A,100,5);//結果送り
  delay(4000);
  if(nowPrint==1){//1連の場合チャンス表示待ちする
    delay(10000);
  }

  if(LR=='R'){//回数1→5や10→1へ変更
    pushButton(Button::R,400);
  }
  else if(LR=='L'){
    pushButton(Button::L,400);//回数5→1や1→10へ変更
  }
  pushButton(Button::B,100,20);//キャンセル 4000
  pushButton(Button::A,50,4);//プリンター選択
  delay(1400);
  pushButton(Button::A,1000);//メッセージ送り「プリントする!」待機状態

  //◆1分経過値の設定
  //この値(checkSec)が1分経過する秒設定ライン
  //60000-5200- 1連48200ミリ秒,5連1回目37700ミリ秒,5連2回目or10連38200ミリ秒
  if(nowPrint==1){
    checkSec=66;
  }else if(nowPrint==5){
    checkSec=171;
  }else{checkSec=166;
  }
  //1分経過値の前後1秒に待機処理をする
  if(PrintSec>checkSec-10 && PrintSec<checkSec+10){
    delay(1500);//一律1.5秒待機
    if(PrintSec<checkSec){
      delay(1000);//1分経過値~-1秒は更に1秒待機
    }
  }


  //●日付変更画面へ
  FromHomeToDay();
  pushButton(Button::A, 200);

  //●次のプリント設定に日付変更
  if(nowPrint==10){//1連に戻す際に正負逆転させる
    for(j=0;j<5;j++){
      PrintSet[j]=PrintSet[j]*-1;
    }
    if(checkDay>0){//CTPrintが29日以上の処理
      PrintSet[2]=PrintSet[2]-checkDay;
      pushHatButton(Hat::RIGHT,30,2);
      pushHatButton(Hat::DOWN, 30,checkDay);
      pushHatButton(Hat::LEFT,30,2);
    }
  }

  if(nowPrint==5){//5連1回目は日付変更なし
    pushHatButton(Hat::RIGHT,30,5);
  }else{//5連1回目以外は日付変更
    for(j=0;j<5;j++){//日付差分変更
      if(PrintSet[j]>0){//差が整数の場合
        for(k=0;k<PrintSet[j];k++){
          pushHatButton(Hat::DOWN,30);
        }
      }else{//差が0か負数の場合
        for(k=0;k>PrintSet[j];k--){
          pushHatButton(Hat::UP,30);
        }
      }
      pushHatButton(Hat::RIGHT,30);
    }
  }

  if(PrintSec>checkSec-10){//1分経過した分1分減らす
    pushHatButton(Hat::LEFT,0);
    pushHatButton(Hat::DOWN, 30);
    if(PrintMin==59){//59分設定の時1時間減らす
      pushHatButton(Hat::LEFT,0);
      pushHatButton(Hat::DOWN, 30);
      pushHatButton(Hat::RIGHT,0);
    }
    pushHatButton(Hat::RIGHT,0);
  }
}

その他(補足等)

お好みでOnePrint、CTPrintの日時設定変更できるので、1連道具2倍→5連×2も可能。プリントするものを増減したければCTPrint[12][7]での設定とfor(i=0;i<12;i++)を変更してください。

1連→10連、連続1連→10連

1連→10連は記載の通り、

      //◆チャンス発生1連~チャンス中に回す日付設定まで
      StartPrint(1,OnePrint[4],OnePrint[5],'L');
      //1連、1連の分設定、1連の秒設定、回す回数1→5に変更
      //1連→10連の場合はRをLに変更

      //◆5連1回目~5連2回目に回す日付設定まで
      //StartPrint(5*1,CTPrint[i][4],CTPrint[i][5],'0');
      //5連1回目、5連の分設定、5連の秒設定、回す回数変更なしなので0
      //1連→10連の場合は削除(//で消す)
      
      //◆5連2回目~チャンス発生1連の日付設定まで
      StartPrint(5*2,CTPrint[i][4],CTPrint[i][5],'R');
      //5連2回目、5連の分設定、5連の秒設定、回す回数5→1に変更
      //1連→10連の場合はLをRに変更

これでいけると思います。(試すの忘れました)

ちなみに5*1、5*2と書いているのは視覚的にわかりやすいからです。5*1→5、5*2→10なので書き換えてもOKです。

連続1連→10連は非対応。そもそも連続1連→10連のはチャンス引くのが安定しないと思うので自動は不向きかと。手動でやりましょう。


以下は後日消します。

設定不可日(2024/4/23追記)→対応しました(2024/4/28)

そういえば31日→30日→28日とかは考慮してなかったな、ということで。
・31日は不可
・30、29日で2月を跨ぐ場合は不可
です。
前者はわかりやすいので説明は省略。後者は具体例として1/1⇔5/30は不可。4/1⇔5/30は可です。
この辺はちゃんと判定処理入れれば行けると思いますが現状自分には影響がない(のとあまり時間を取れない)ので気が向いたら対応します…。

改善案メモ(2024/4/23追記)→対応しました(2024/4/28)

・たまに入力漏れが発生するので連打できる部分は連打に変える
連打可能な箇所の確認と1分経過判定の範囲変更が必要なので腰が重い。連打できない箇所で入力漏れが発生した場合は潔く引っこ抜くしかない。

・1分経過した際に1時間増える場合に減らす処理を追加
コメント見れば各自対応可能。最低でも自分でコンパイルしてからコード更新するべきなので保留中。

・1分経過判定が環境なのかラグなのかたまに失敗しているので範囲をもう少し広げる
同じ設定で回してるのに突然ギリギリ1分経過しなくて1分減らす処理をするのを見てしまったので。現状きちんと動いてる人はそのままでいいです。同じ現象が起きた人は判定範囲広げた分待機時間も長くすればいいのでわかる人はやってもいい。それか万一失敗した際に手動で直せるように日付決定Aボタンの前に delay(5000); とか入れましょう。

この記事が気に入ったらサポートをしてみませんか?