<span style="font-size: 110%;">
こんにちは。[**ニアト**](https://twitter.com/21i10r29)です。
一年半前に[BDSPにおける乱数調整メモ](https://hackmd.io/@niart/B1S6AaniF) という記事を書いていましたが、性懲りもなくこのゲームの話をします。
## はじめに
BDSPにおける乱数調整用ツールである**PlayerBlink**[^playerblink]は乱数調整に必要なSeed特定やタイマーなどの機能を提供しています。
[^playerblink]:https://github.com/papajefe/Project_Xs/releases
一方で、いざこのツールを使ってみようとすると、
- ボタンが多すぎて何処を押したら何が出来るか分かりにくい
- 特定に失敗するとツールが止まって再起動が必要
- Seedの特定/再特定に時間がかかり過ぎる etc..
といった部分が目につきます。他にも幾つか気になる点はありますが、一言で言えばUXが著しく悪いのです。
今回はこれらの問題を解決する新ツール"[**XsReader**](https://github.com/niart120/Project_eXcelSior)"を紹介し、その使い方を解説します。
## 用語の定義
用語を次のように定義します;
- 基準Seed(Base Seed)
乱数列上での相対的な位置を決めるための基準となるSeed。
- Advance
基準Seedから幾つ乱数が進んだかを表す数。消費数。
- Target Advance (Target Adv.)
目標とする個体が生成される際のAdvance。目標消費数。
- タイムライン
得られた乱数列から乱数契機をエミュレートして次の乱数消費タイミングを予測することで得られる時系列。
Advance/Target Advanceに関しては消費数/目標消費数(あるいは[F]/目標[F])などの呼び方もありますが、本記事ではXsReaderや他ツールでの名称に合わせる形で呼ぶことにします。
## XsReaderの概要
Readmeに記載している内容を引用する形でツールの概要を紹介します。
> XsReaderはポケットモンスター ブリリアントダイヤモンド・シャイニングパール(以下BDSP)における乱数調整ツールです.
>
> このツールを用いてフィールド上での主人公の瞬きを観測することで,
>
> - 基準seedの特定
> - 基準seedからのadvance(どれだけ乱数が消費されたか)の特定
> - タイムラインの生成
> - 固定シンボルを考慮したタイムラインの生成
>
> を行うことが出来ます.
>
> このツールはPythonやJavaのように外部ランタイムを必要としません. 必要な実行環境は殆どのWindowsではデフォルトでインストールされています.
>
> また, OBSなどのプレビュー画面越しに観測を行うためキャプチャーボードを占有することもありません.
こんな感じの見た目をしています。

PlayerBlinkと比べるとだいぶシンプル…なハズ。
基本的には中央の`seed特定` `Adv.再特定`タブと`同期`内のタイムライン表示を使います。
:::info
ツールの画像は開発版で撮影したものです。最新版とは多少差異がある場合があります。
:::
XsReaderを用いて乱数調整を行う場合の想定フローは以下の通りです。
1. BaseSeed(基準Seed)を特定する
2. Pokefinderを用いてTargetAdv. (目標消費数)を調べてXsReaderにセットする
3. ポケモン図鑑などを用いて乱数消費する
4. Advanceの再特定をして目標消費数にどれだけ近づいたか調べる
5. 目標消費数のカウントダウンが十分小さくなるまで3,4 を繰り返す
6. カウントダウンが0になったタイミングでエンカウントする
7. 目標個体ゲット!
基準seedを求めて、そこから目標個体を探して目標消費を調べて、そこに到達するまで消費して、最後に個体生成のタイミングを合わせるだけです。
やってることはSM/USUMやソード・シールドのOW乱数に近いですね。
## XsReaderを用いた固定シンボル乱数手法の説明
XsReaderを用いたBDSPにおける固定シンボル乱数の手法について説明していきます。
### 準備:環境構築
必要な機材・ソフトウェアを以下に示します。
#### 機材
- **Windows PC**
- **Nintendo Switch**
- **ポケットモンスター ブリリアントダイアモンド・シャイニングパールのソフト**
- **キャプチャーボード** (推奨:FullHD/60FPS対応)
Switchの画面をPCに取り込める環境が必要となります。
所謂格安キャプチャーボードでも動作するとは思いますが、もし心配なようであれば、FullHD・60FPS出力に対応している製品を購入することを推奨します。
Switch Liteの場合でもWebカメラなどを活用して画面を取り込む環境が作れるのであれば乱数調整は可能ですが、映像品質や遅延の観点からおススメしません。
また、対応OSについてはWindowsのみをサポートしています。恐らくMac/Linux向けにもビルド/実行できるとは思うのですが、検証できる環境がないためサポート対象外です。
#### ソフトウェア
- [**PokeFinder**](https://github.com/Admiral-Fish/PokeFinder/releases)/[**BDSPSearch**](https://github.com/niart120/Project_extrema/releases) などの個体検索ツール
- [**OBS**](https://obsproject.com/download)などのキャプチャ用ソフト
個体検索ツールに関しては、基本的には固定シンボル・孵化乱数の両方に対応しているPokeFinderの利用を推奨します。固定シンボルのサイズ乱数を行う場合はBDSPSearchを利用してください。
キャプチャーボードを持っている方であればOBSなどは既に導入されていると思います。導入していない場合はインストールしてください。
:::info
以降の説明ではPokeFinder/OBSを用いて説明します。他のソフトをお使いの方は各自の環境に読み替えてください。
:::
### 準備:ツールのDL
以下のURLから最新版の`XsReader.zip`をダウンロードします。
https://github.com/niart120/Project_eXcelSior/releases
zipファイルをダウンロードしたらファイルを展開(解凍)します。
:::info
zipファイルをダブルクリックして開いても動作しません。必ず展開したフォルダから実行してください。
:::
### 実践:基準Seedの特定
#### Switch側の準備
基準Seedを特定するには、主人公の瞬き以外に乱数を消費する要因が無い状態が必要です。
フタバタウン自宅2Fや、シンジ湖・リッシ湖・エイチ湖の洞窟前、テンガン山(槍の柱出口)、地下通路内に生成した秘密基地などの、"静か"な場所[^place]に移動しましょう。
[^place]:基本的にはNPCの居ない屋内、ダンジョン内などが"静か"な場所として利用可能です。
移動したら、便利ボタンから"すごいつりざお"などを呼び出し、メッセージウィンドウが表示されている状態を作ります。

こうすることで _fidget_[^fidget]が抑制され、瞬き以外の乱数消費がすべてストップします。
[^fidget]: フィールド上で何も操作をせずに放置していると, _fidget_と呼ばれる、周囲を見回したり、伸びをしたりといった動作が入ることがあります。これらの動作は乱数消費の契機となるため、Seedの特定やAdvanceの特定に影響を及ぼします。
以降、基準Seed特定が完了するまでSwitch側を操作する必要はありません。場合によっては長時間放置することになるため、自動スリープは切っておきましょう。
:::warning
Switch側でやりがちなミスとして
- 固定シンボル前で基準Seedを特定しようとしている
- ウィンドウなどが開かれておらず主人公の動きがロックされていない
- 画面がスリープして観測が中断された
などが挙げられます。
:::
#### 画像の撮影
つづいてPC側で主人公の目の画像を撮影しましょう。
ツールを開くと、メインのウインドウと一緒に小さなウィンドウが出てきます。

今後、このウィンドウのことを**キャプチャウィンドウ**と呼称します。
キャプチャウィンドウをキャプボの画面上まで移動させて、主人公の目の位置に合わせます。

位置があっていることを確認して、ツールの`画像撮影`ボタンをクリックしてください。

すると、`eyeimage`フォルダに撮影した画像(`yyyymmddhhmmss.png`)が保存されます。必要に応じてリネームしてください。
また、目の画像が大きすぎる場合は正常に瞬きを検知できないことがあります。その場合は保存した画像を別途トリミングする必要があります。
以下は観測上望ましい画像とそうでない例です。
|||
| :--------: | :--------: |
| ◎(目だけが切り抜かれている) | ×(目以外の領域が大きい) |
:::warning
以降の操作ではOBSなどの画面の大きさを変更しないようにしてください。正しく瞬きを観測できなくなる恐れがあります。
:::
#### 瞬きの観測
いよいよ基準Seedの特定を行います。
先ほど撮影に用いたキャプチャウィンドウは少し広げておきます。
`Seed特定`タブ内の`瞬き画像`リストから先ほど撮影した画像を選択します。その後`Start`ボタンをクリックすると瞬き観測が開始されます。

観測中は`start`ボタン横のインジケーターが`InProgress`へと変化し、左側のテーブルに観測した瞬き間隔とその種類が追加されていきます。(左図)
エントロピーの値が128以上になるとSeedの復元処理が走り、特定出来るとBaseSeedの値が更新されます。また、インジケーターも`success!!`へと変化します(右図)
| | |
| :--------: | :--------: |
| 特定中 | 特定終了後 |
:::warning
ツール側でやりがちなミスとして
- 他の画面を全画面にした所為でOBS側のウィンドウが隠れてしまう
- キャプチャウィンドウの位置がズレている
- 間違った画像を選択している
:::
などが挙げられます。
特定終了後は、プレイヤーの瞬きと同期する形でAdvance(現在の消費数)のカウントや次の消費イベントまでのカウントダウンタイマーが走り始めます。
映像上の主人公の瞬きとツールが同期していることを確認してください。
基準Seed特定後はホーム画面に戻る、あるいはSwitchをスリープさせても構いません。
ホーム画面にいる間や、スリープ中はあらゆる乱数消費が止まります。落ち着いて次のステップに移りましょう。
:::danger
**注意:**
ゲームソフトを完全に終了させてしまうとSeedがリセットされます。
基準Seedの特定からやり直してください。
:::
:::info
**何回やってもインジケーターが`Failed`となって失敗してしまう方向けのTips:**
多くの場合、瞬きの誤検知が原因です。以下の事象が発生していませんか?
a. 瞬きの種類(`BlinkType`)が"***"のようになっている行が存在する
b. 0から2程度の極端に短い瞬き間隔(`Interval`)が5,6個連続している
c. 画面上だと瞬きしていないにも関わらず、勝手にツール側が更新される
d. 画面上だと瞬きしているのが目視で確認できたのに、ツール側が更新されていない
これらの問題は画像の再撮影やトリミング、あるいはキャプチャウィンドウの拡大によって解決されることが殆どです。
上記を全て試しても解決しない場合は、`設定`タブから`瞬き閾値`の値を調整することで解決することがあります。
a.~c.に該当する場合は閾値を増やし、d.に該当する場合は閾値を減らしたうえでSeedの特定を実施し、上記の事象が解消されることを確認してください。

:::
### 実践:目標個体の検索
特定した基準Seedを用いてPokeFinderから個体検索を行います。
PokeFinderを起動し、`Gen8`タブから該当する乱数調整種別を選択して検索ウインドウ画面を開きます。
例えばディアルガ・パルキアやハマナスパークなどの固定シンボル乱数を行うのであれば`Static`を、孵化乱数を行うのであれば`Egg`を選択してください。

その後、`Seed0` `Seed1`に求めた基準Seedを入力し、検索項目を埋めて`Generate`をクリックすると個体の候補が一覧で表示されます。

いくつか個体が出てくると思うので、候補の中から目的の個体を選んでください。その個体の`Advances`をXsReaderの`Target Adv.`に入力します。この値が今回のTarget Advanceとなります。
:::info
PokeFinder内の`Use Delay`を利用することで、個体生成前の消費を考慮した検索が可能です。
PokemonRNGGuides内の [**Stationary.md**](https://github.com/zaksabeast/PokemonRNGGuides/blob/main/guides/Brilliant%20Diamond%20and%20Shining%20Pearl/Stationary.md) に記載されている各ポケモンのDelayを入力したうえで検索することを推奨します。
:::
:::info
PokeFinderのより詳しい使い方については、じゃんきー氏の[はじめての BDSP固定乱数(パルキア/ディアルガ)](https://note.com/junky_poke_/n/na9b0634ef552)でも説明されているのでそちらもご参照ください。
:::
## 乱数の消費
目的の個体Target Advanceまでのカウントダウンが利用可能となりました。とはいえ、たいていの場合、カウントダウンの値は数千から数百万となることが多いため、手動で乱数消費を行うことでTarget Advanceまで近づける必要があります。
BDSPにおける乱数消費の手法に関しては幾つかありますが、ポケモン図鑑を開いて図鑑をスクロールするのが一番手軽です。
全国図鑑入手後のシンオウ図鑑を利用する場合の消費数を以下に掲載します[^pokedex]。
- 全国図鑑からシンオウ図鑑への切り替え:167 [Adv]
- 十字キー右を1回押すことによるスクロール:150 [Adv]
図鑑操作中も主人公やポケモンによる消費($1.00$ [Adv/s] ~ $1.15$ [Adv/s])が行われることを考慮すると、例えば"図鑑を開く->シンオウ図鑑に切り替える->十字キー右を10回押してスクロールする->図鑑を閉じる"までの一連の操作で約1700 [Adv]程度になると概算できます。
[^pokedex]:ポケモン図鑑のスクロールによる消費はモデル読み込みを契機として発生します。図鑑が埋まっていない場合だと掲載した消費数よりも少なくなることがあります。
他にも、連れ歩き可能な屋外フィールドで放置するなどでも高速消費が可能です。具体的な消費速度については各自でご確認ください。
良い感じに乱数を消費できたところで、Advanceの再特定を行い、Target Adv.までどれほど近づいたかを確認しましょう。
## 実践:Advanceの再特定
図鑑などで乱数消費をしてみたものの、具体的にどれくらい消費したのか正確な値は分かりません。現在のAdvanceを再特定するために、もう一度瞬きの観測を行いましょう。
XsReaderの`Adv.再特定タブ`を開くと、幾つかの入力項目が表示されます。

それぞれ簡単に説明しておきます。
- `検索範囲`
Advanceの検索範囲です。あまり広い範囲(100万~)を指定すると観測に支障が出る場合があります。
- `最低観測回数`
検索を行うのに必要な**瞬き間隔**の観測回数を指定します。瞬きの回数ではありません。
- `InNoisy`
固定シンボルの居るフロアでAdvanceの再特定をする場合はチェックを付けてください。
他の項目については`Seed特定`と同様です。
Advanceの再特定を行う場合は、基準Seedの特定時とは異なり固定シンボルのいる部屋での再特定が可能です。実際に試してみましょう。
検索範囲を調整し、最低観測回数を少し増やして、`InNoisy`にチェックを入れるのを忘れないようにして`start`ボタンをクリックします。
すると…

画像だと分かりにくいですがAdvanceの再特定に成功しました。どうやら今回はTarget Advanceを大幅に過ぎてしまったようですね。
この場合は再度Pokefinderで個体を検索しなおす必要があります。特定したBaseSeedは使いまわせるので、Seed特定からやり直し、ということはありません。
## 実践:エンカウント
Target Advanceが近づいたらいよいよエンカウントです。
消費と再特定を繰り返して、"*Target Adv.まで*"のカウントが100-200ぐらいになったら、メッセージウィンドウを閉じてシンボルに話しかけ、鳴き声のウィンドウを表示させます。

:::danger
博士の言葉のメッセージウィンドウを閉じる際に、**必ずアナログパッド(あるいは十字キー)を倒しながら閉じる**ようにしてください。
そのままメッセージウィンドウを閉じてしまうと _fidget_ による消費によって以降のタイムラインがズレる可能性があります。
:::
:::info
上図のように主人公が横を向いた状態で話しかけることで、鳴き声のウィンドウを開きつつ瞬きを観測することが出来ます。
横を向いた状態の目をキャプチャして再度`Adv.再特定`を行うことで、より安定して狙った個体を出現させることが出来ます。
:::
その後、"*Target Adv.まで*"のカウントが0になると同時にメッセージ送りをしてエンカウントします。成功していれば目的の個体が出現します。

成功しなかった場合でも、一度捕獲してPokefinder上で検索してどのくらいのズレが生じていたのかを検証することを推奨します。
±10以上ズレる場合はその分Pokefinder側の`delay`を調整してください。
:::info
**ちゃんとカウントを合わせた筈なのに失敗した!という方へ;**
これはタイムラインの予測が不完全なことに由来しています。
タイムライン生成中の主人公の消費タイミングと固定シンボルの瞬きがタイミングが非常に近い場合、以降のタイムラインがズレることがあります。
また、ユクシー・アグノムなどの幾つかのシンボルでは、鳴き声のウィンドウを表示した際に消費が挟まり、以降のタイムラインが不整合を起こす場合があります。
残念ながら現時点では根本的な対処方法はありません。
:::
## おわりに
本記事では拙作の**XsReader**の紹介と使い方解説をしました。
もしツールの使い方などで分からないことがあれば、Discordのポケモン乱数鯖までお問い合わせください。`#ダイパリメイク`チャンネルにてお伺いいたします。
発売から一年以上たった今、BDSPを遊んでいてかつ乱数調整をしたいという方がどれだけいらっしゃるかは分かりませんが、このツールがそういった方々の一助になることを願います。
[^pokeblink]:フィールド上に存在する固定シンボルは、ゲーム開始時に登場するゴンベと同様に瞬きを行います。
</span>