はかせのラボ

私の頭の中を書いていく雑記ブログです

ポケモン剣盾 ランクマッチで4桁順位になれたのでその構築の紹介

あいさつ

どうも、はかせです。
やっとこさポケモンのシングルランクマッチで4桁順位になれました。
f:id:hakase0274:20191229160847j:plain

マスターボール級に何人いるのか正確な数はわかりませんが、
少なくとも11万人以上いるのは確認しています。
(沼にハマり10連敗ぐらいして11万位第まで落ちましたw)

前振りが長くなりましたが、
今回は自分の備忘録も兼ねて構築や考えたことを書いていきます。

パーティ紹介

使ったパーティはこんな感じです。
f:id:hakase0274:20191229160859j:plain

前回同様細かい説明はしません。
ではそれぞれの説明です。

サダイジャ

個体値:6V
持ち物:さらさらいわ
性格:わんぱく
特性:すなはき
努力値:h228b148s132
わざ:へびにらみ、がんせきふうじ、じしん、ステルスロック

基本先発で麻痺とステロと砂まく要員です。

h228は実数値176でオボンのみでの回復効率が最高になる値です。
元々はオボンのみ運用だったのでこうしてますが、
今となってはオボンのみじゃないのでh252の方がいいかなと思ってます。

s132は実数値108で最速ドラパルトを麻痺込みで抜ける速度となっています。

物理方面はかなり硬くて
a特化ギャラドスたきのぼり確2
最速ごりむちゅうヒヒダルマつららおとし乱1(75.0)

このように弱点突かれても物理攻撃ならば高確率で生き残ることができます。

最悪一発で持ってかれてもすなは展開できるので、
最低限の仕事はできます。

ドリュウズ

個体値:6V
持ち物:きあいのタスキ
性格:ようき
特性:すなかき
努力値:as252h4
わざ:いわなだれ、つのドリル、じしん、アイアンヘッド

すな下のエースです。

最速タスキ型なのでミラー対決にも強く、
アーマーガアなどの苦手なキャラ以外には
上から倒しきれます。

サダイジャですなをまいてもいいし、
ダイマックスして自力ですなをまいてもいいしで
単純に強いです。

サダイジャとドリュウズがいると
ほぼほぼアーマーガアやミトムが出てくるので、
相手によっては選出誘導にもなってくれるという
対戦・選出ともに役立ってくれました。

リザードン

個体値:6V
持ち物:じゃくてんほけん
性格:おくびょう
特性:サンパワー
努力値:cs252b4
わざ:ぼうふう、だいもんじ、ソーラービーム、りゅうのはどう

サダイジャドリュウズで引きずり出した、
アーマーガアやミトムを狩る役です。

基本ダイマックスして相手に圧力をかけていきます。
リザードンが暴れて残った敵を、
サダイジャドリュウズで掃除するというのが基本でした。

ダイマックス前提なのでミトムをはじめとする
水タイプもこいつの役割対象となります。

メガシンカがあった時ほどの強さはありませんが、
弱すぎず強すぎず、
明確に役割を持てるちょうどいい強さのキャラになっていると思います。

hではなくbに4振ってるのは体力を奇数にしたかったからです。

サザンドラ

個体値:6V
持ち物:こだわりスカーフ
性格:おくびょう
特性:ふゆう
努力値:cs252d4
わざ:ラスターカノン、だいもんじ、あくのはどう、りゅうせいぐん

ドラパルトやアイアントの高速アタッカーを
スカーフを持たせることで上から叩く役です。

フェアリータイプ以外には強気に出られるうえ、
フェアリータイプはドリュウズで見ることができるので
大分動かしやすかったです。

オーロンゲやエルフーンいたずらごころ持ちの先制変化わざを無効にし、
返しのだいもんじやラスターカノンで狩ることもできます。
(読まれてムーンフォースとか打たれたら泣きますがw)

サザンドラ対策が全くされてない甘めのパーティに対しては
先発サザンドラで3タテできるので単純に強いです。

hではなくdに4振ってるのは体力を奇数にしたかったからです。

ローブシン

個体値:6V
持ち物:かえんだま
性格:いじっぱり
特性:こんじょう
努力値:h196a252b60
わざ:れいとうパンチ、かみなりパンチ、マッハパンチ、ドレインパンチ

アーマーガア+バンギラス、ドラパルト、サザンドラヒヒダルマみたいな
アーマーガア+リザードンに強いポケモンの選出をしてきそうな場合に
このポケモンをさしてました。

他にもカビゴンメタとしても使ってました。
(リザードンドリュウズカビゴンで止まりやすいため)

細かい値の調整とかは下記の育成論にあるので
そちらをご覧ください。
yakkun.com

ヨクバリス

個体値:5V、s逆V
持ち物:オボンのみ
性格:ゆうかん
特性:ほおぶくろ
努力値:h244a12b252
わざ:タネばくだん、ジャイロボール、ワイルドボルト、はらだいこ

前回の記事でも登場した最強キャラですw
前回は物理受け+削り役という役周りでしたが、
今回ははらだいこしてダイマックスして大暴れする形です。

ワイルドボルトでアーマーガア、ギャラドスを、
タネばくだんでミトム、ヌオー、ガマゲロゲ、バンドリを、
ジャイロボールでミミッキュヒヒダルマをそれぞれ対面から倒しきることが可能です。

相変わらず現環境に多い物理キャラを対面からなら
ほぼ全て倒しきることができます。

特殊キャラがかなり増えてきて
前ほど大暴れはできなくなりましたが、
今でもその強さは健在です。

運用

基本はダイマックスエース+サダイジャ+ドリュウズです。

初手ダイマックスで大暴れしてもらい、
残った相手をサダイジャドリュウズで掃除するという流れです。

ダイマックスエースは
リザードンだったり
サザンドラだったり
ヨクバリスだったりします。

ドリュウズが一貫しそうな相手には
サダイジャドリュウズでそのまましばきます。

構築に至った経緯

マスボに入った当初は相手の攻撃を受けて
その返しで倒すという形をとっていました。

ただアイアントやら弱保ジェット型やらと
受けて返しで倒すというのが難しい環境になってきました。

なのですなかきドリュウズで上からしばこうという
考えにいたりました。

使い始めた当初はドリュウズ=かたやぶりの印象しかなかったらしく、
面白いくらいすなかきドリュウズが刺さりました。

後半はアーマーガアがめちゃめちゃ流行り始めて
ドリュウズだけで戦うのが無理になってきました。

なのでドリュウズ以外のキャラで暴れたのちに、
すなかきドリュウズを決めようと考え、
現在の構築になりました。

あとがき

今回は順位4桁記念ということで
構築や考えを書きました。

シーズン1はあと数日ありますが、
年末年始はネットのない田舎に帰るので
おそらく私のシーズン1はこれで終了です。
(もしかしたらあと数戦はするかもしれませんが)

シーズン1はほぼ使うキャラが固定されていたので、
次のシーズンでは色々なキャラや仕組みを使ってみたいなーと思っています。

それでは今回はこの辺でノシ

C# コンソールアプリでBluetooth通信を行う

あいさつ

お久しぶりです。はかせです。
この記事は、C# その2 Advent Calendar 2019 の22日目の記事となります。

今回はコンソールアプリでBluetooth通信をやってみます。
やることとしては特定のBluetooth端末と通信し、
その端末からセンサーの値なりなんなりを取得できるようにします。

前準備

開発はVS2017の最新版を使っています。
C#にはBluetooth周りのAPIがあるっちゃあるんですが、
どれもこれもUWP専用らしいです。

UWPでやっても良いんですが、
どうせなら慣れているコンソールアプリの方が扱いやすいです。
ということでNuGetからUWP専用APIを通常アプリでも使えるようにする
「UwpDesktop」というものを入れています。

下記の画像の所をクリックして
検索窓にUwpDesktopと打ち込めば出てきます。
f:id:hakase0274:20191222003721p:plain

Bluetooth通信のやり方

まずざっくりと流れです。
・周囲のBluetooth端末をスキャン
・スキャンした端末が通信したい端末かチェックし値の購読を始める
・あとは煮るなり焼くなりお好きにどうぞ

それぞれ説明していきます。

周囲のBluetooth端末をスキャン

Bluetoothってのは「アドバタイズパケット」っていう
「俺は…ここにいるッ!!」ということを伝えるためのデータを発信します。

そしてそのデータをスキャンすることでBluetooth端末を認識し
接続することができます。

ではコードを

private BluetoothLEAdvertisementWatcher advWatcher;

advWatcher = new BluetoothLEAdvertisementWatcher();
advWatcher.SignalStrengthFilter.SamplingInterval = TimeSpan.FromMilliseconds(1000);
advWatcher.ScanningMode = BluetoothLEScanningMode.Passive;
advWatcher.Received += WatcherReceived;

advWatcher.Start();

やってることは
BluetoothLEAdvertisementWatcherに用意されているプロパティの値を
うまい感じに設定した後、
Start関数を呼んで実際にスキャンします。

スキャンした端末が通信したい端末かチェックし値の購読を始める

さてスキャンが出来たところで
次にそれが通信したい端末か調べます。

さっきのWatcherReceivedにスキャンされた端末の情報が流れてきます。
その情報をもとに判定します。

private GattDeviceService gattService;
private GattCharacteristic vroomService;

private async void WatcherReceived(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs args)
{
   CheckArgs(args);
}

private async void CheckArgs(BluetoothLEAdvertisementReceivedEventArgs args)
{
    bool find = false;

    var bleServiceUUIDs = args.Advertisement.ServiceUuids;
    foreach (var uuidone in bleServiceUUIDs)
    {
        //serviceGuid 端末のGuid
        if (uuidone == serviceGuid)
        {
            // 発見
            find = true;
            break;
        }
     }

     if (find)
     {
         try
         {
            // スキャンStop
            advWatcher.Stop();
            //接続
            BluetoothLEDevice device = await BluetoothLEDevice.FromBluetoothAddressAsync(args.BluetoothAddress);
            //サービスUUIDを使って目的のサービスを取得
            gattService = device .GetGattService(serviceGuid);
            //キャラクタリスティックUUIDを使って目的のキャラクタリスティックを取得
            var characteristics = gattService.GetCharacteristics(new Guid("キャラクタリスティックのGuid"));
            //戻ってくるのが配列なので空じゃないか確認
            if (characteristics.Count > 0)
            {
                vroomService = characteristics.First();
                if (vroomService == null)
                {
                     throw new Exception("そんなサービスはねぇ!");
                }
                //読み取り可能ならばキャラクタリスティックにアクセスしコールバックを設定する
                if (vroomService.CharacteristicProperties.HasFlag(GattCharacteristicProperties.Read))
                {
                     vroomService.ValueChanged += CharacteristicChangedVroomController;
                     Console.WriteLine("Connect");
                     await vroomService.ReadClientCharacteristicConfigurationDescriptorAsync();
                }

            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Exception...{ex.Message})");
        }
    }
}

さてやってることは単純で
・スキャンした端末がもつサービスのUUIDと使いたいサービスのUUIDを比較する
・同じならスキャンを停止しその端末と接続
・接続した端末のサービスの中から目的のデータの読取を試みる

こんな感じです。

なんでUUIDなんかを調べるのかと言うと
それはBluetooth通信に使われている
GATTというものが絡んできます。
こいつはBluetoothで標準的に使われているデータフォーマットです。

中身は
「サービス」「キャラクタリスティック」
二つからできていて、
それぞれがUUIDで設定されています。

Windowsユーザーに分かりやすく説明すると、
サービス=フォルダ
キャラクタリスティック=ファイル

って感じです。

GATTに則っているBluetooth端末は必ずこの形でデータを発信するので、
UUIDでサービスを調べることで目的の端末かわかるわけですね。
ちなみに使いたいサービスのUUIDはどうやって知るのという話ですが、
販売元が公開している場合もありますし、
自分で全パケットを調べて判断するしかない場合もあります。
(私が使おうとしてたものは公開されていなかったので全パケット調べましたw
疲れた・・・)

そんなこんなで目的の端末と接続が出来たら
これ以上スキャンかける必要がないので
スキャンを止めます。

その後サービスのUUIDとキャラクタリスティックのUUIDを用いて
目的のデータにアクセスします。

アクセスに成功したらコールバックを設定し
値の購読を開始します。
CharacteristicChangedVroomControllerってのは自作関数で
流れてきたバイト列を好きに煮るやつです。

バイト列を使いやすいよう加工したり、
データをUDPで送信したりしてます。
ここはそれぞれのプロジェクト状況に応じて
好きな関数作って登録してください。

あとがき

今回はコンソールアプリでBluetooth通信を行ってみました。

今回の実装は難しくはなかったですけど、
とにかく目的のサービスUUIDを探すのが大変でしたね・・・
まぁ公式に公開されていないものを使おうとしているわけですから、
大変なのは当たり前なんですけど。
(むしろそういうの好んでやっているまである)

Bluetooth通信はかなり身近なものではありますが、
あまり自作のアプリとかに組み込んでみたとかの事例を聞きません。

Bluetooth通信使えばお手軽にIoTができるので
やってみてはいかがでしょうか?

実際にモノが動いたり
モノの動きがソフトに反映されたりするのって
存外楽しいですよ。

それでは今回はこの辺でノシ

参考

qiita.com