892

ぷよぷよを統計する~statsを作成してみた~ その2

by
mokkun393939
mokkun393939
みなさん、こんにちは。
前回記事に予想よりも多くの反響があり、びっくりしています。
今回はぷよstatsの作成で「ぷよ動画から取得しているデータ」についての解説記事となります。

1. はじめに
はじめに少し自己紹介を。
昨年から趣味でpythonを始め、学習の目標としてぷよ動画を解析しています。
年末ごろに画像解析を覚え、それからぷよstatsに取り組んでいます。当初は私的に楽しむだけでしたが、考え出すと非常に面白いことに気付いて記事投稿に至ります。
何が言いたいかというと、ぷよstatsは今後もっと洗練される可能性がある、ということです!そしてプログラミング初心者の取り組みなので、エラーや不完全な部分について大目に見てもらえると嬉しいです…泣


2. データ取得方法
さて、本題ですが、私がデータ取得する際は、pythonのopencvを用いて自動で動画読み込み・画像処理を行っています。
この部分については下記リンク先の記事を参考にさせていただきました。

(ぷよぷよのプレイ動画を解析して棋譜を生成する)
https://nojima.hatenablog.com/entry/2018/12/03/224157

なお、本記事ではプログラミング自体には踏み込まないのでプログラミングの知識は不要です。


3. ゲームの流れを取得する
まずはゲーム中の流れを「いつ」「1P or 2Pが」「何連鎖したか」で表現します。
具体例として、「2021/1/29 ぴぽにあさん vs いさなさん」 の10-15からの1戦について紹介します(ぴぽにあさんのアーカイブのリンク)。
このゲームの流れは次の通りです。


~ゲームの流れ~
・2Pが1連鎖(イバラ)をうち、1Pが受ける
・1Pが2連鎖ダブル
・→2Pが5連鎖で対応
・→1Pが5連鎖で対応
・→2Pが7連鎖の本線(先打ち)
・→1Pが8連鎖の本線(後打ち
)


これを動画解析から表にすると次のようになります。
(連戦の最初を0Frameとしているため「Frame」はかなり大きな値になります。)



続いて、ゲームの流れをより詳細にデータから読み取るために、各連鎖に性質を追加します。



追加した列の意味は次の通りです。


①「Honsen(本線)」:本線なら1、そうでないなら0。画像解析上は「フィールド1段目のぷよが消えたかどうか」で判定しています。
②「Kaishu(回収率)」:本線の場合に算出。連鎖開始時と終了後のフィールドのぷよ量を比較し、本線回収率を算出しています。
※現在の私の技術ではぷよ量の取得が安定せず、表中4行目の回収率が実際より低く算出されています。(実際は34/39 = 87.2%のところ、31/37と誤取得)
③「Ojama」: おじゃまを降らせた側のプレイヤー。「受けた側」ではないので注意。0行目の2Pイバラ・5行目の1P本線でおじゃまを降らせたことがわかります。
④「Ojama_detail」: おじゃまが発生した場合の個数。
※ぷよ量取得が安定しないため、この数値も誤差・エラー多めです。現在は連鎖終了時から一定時間後で差分をとっているので、おじゃま31個以上(おじゃま落下のエフェクト2回以上)については本来の値からずれます。
⑤ラリー情報: 詳しくは次項で紹介しますが、ラリーを構成する要素として「ラリーの最初の連鎖かどうか」「その連鎖が対応されたか」の情報を付与しています。表中の「Start」「Continue」列に相当します。


このように、各連鎖に対して性質を与えることで、連鎖を追うだけで試合の流れを構築できるようにしています。


4. データの加工(ラリーで考える)
ここまでのデータを集計することでstatsができますが、対応や先打ち・後打ちを考えやすくするため、集計前に一度「ラリー」の表を作成しています。

そもそも、ぷよぷよにおける「対応」「対応の勝ち負け」とは何でしょうか?
答えは一つではありませんが、私がstatsを作成するうえでは「どちらかが連鎖を始めてからおじゃまが降るまで、もしくは本線を打たせるまでの連鎖のやり取り」と定義しています。やり取りの間の相殺が続いている状態を「ラリー」と呼んでいます。

さて、先ほどのゲームの流れをラリーで考えてみます。


~ラリーの流れ~
1ラリー目:2Pが1連鎖(イバラ)(→1Pにおじゃま)
2ラリー目:1Pが2連鎖ダブル
      →2Pが5連鎖で対応
      →1Pが5連鎖で対応
      →2Pが7連鎖の本線(先打ち)
      →1Pが8連鎖の本線(後打ち
)(→2Pにおじゃま)


「対応」を考えると、1ラリー目は対応なしです。2ラリー目は2Pが先打ちしたので、1Pの勝ちと言えます。
「先打ち」「後打ち」を考えると、2ラリー目で2Pが先打ち、1Pが後打ちしています。
このようにラリーで考えることで、1ラリー毎に「対応の勝ち負け」「先打ち」「後打ち」を定義できます

さて、先ほどのゲームの流れの表を参照してラリーの表を作成すると、次のようになります。



①「Player」:ラリー(=最初の連鎖)を仕掛けたプレイヤー
②「Rally」:ラリーの回数
③「Win」:ラリーの勝者(=相手におじゃまを降らせたプレイヤー)
④「First_Rensa」:最初の連鎖の連鎖数
⑤「Max_Rensa」:ラリー中の最大連鎖数
⑥「Ojama_detail」:降らせたおじゃまの個数
⑦「Honsen」:ラリー中の本線の有無(あり:1、なし:0)
⑧「Honsen_Player」:本線がある場合、先打ちしたプレイヤー
⑨「Honsen_Chain」:先打ち時点のラリー数

⑩「Second」:セカンドの有無(あり:1、なし:0)。「先打ちしたプレイヤーが2回目の本線を打ち、かつ連鎖数が4以上」を判定基準としています。


1行目からは「2Pが1連鎖でおじゃまぷよ9個を降らせた」ことがわかり、2行目からは「1Pが仕掛けた2連鎖から連鎖5回分・最大連鎖数8連鎖のラリーが発生し、2Pが本線を先打ちし、1Pが後打ちで勝利した。セカンドはなかった」ことがわかります。

このようにラリーとしてデータをまとめなおすことで、「対応」や「先打ち」「後打ち」を機械的に判断して集計しやすくしています。集計については次の記事で紹介します。


5. データ取得時の課題
データ取得には課題が多いので、簡単にまとめておきます。(備忘録なので読み飛ばし推奨です)

①画像取得によるエラー
ぷよ対戦の画像解析は「連鎖アニメ」「フィールドの揺れ」等の影響を大きく受けます。できるだけ影響が少なくなるようにコードを書いていますが、まだ精度はあまり良くありません。

②時間のずれによるエラー
現在は連鎖開始or終了時を起点とし、一定時間経過したときのぷよ量を算出する手法が多く、この時間のラグが設定値から外れると正確なデータが取れません。「おじゃまを受けるときに迷って置く」「極端なクイック」など、時間のイレギュラーが意外に多いです。

③解析時間
30本先取の動画の解析に15~20分かかります。複数の値の取得のために動画を何度も読み込むのが原因です。

④リアルタイム解析
現在は既存の動画しか解析できないので、リアルタイム解析はできません。正直私の技術力では全くフォローしきれない部分なのですが、遠い将来できるようになると面白いと思います。

このうち①~③についてはもう少しやりようがあると感じているので、今後の検討課題です。


6. まとめ
今回はstats作成のための取得データについて解説しました。
ご意見やご質問があれば、コメント欄かtwitterでいつでも受け付けますのでよろしくお願いします。

次の記事では取得したデータの集計・解析について紹介する予定です。
それでは、またどこかで。
更新日時:2021/02/23 17:54
(作成日時:2021/02/23 17:53)
コメント( 4 )
4件のコメントを全て表示する
mokkun393939
mokkun393939
2月23日 19時39分

もるつさん
はじめまして!コメントありがとうございます。
似たようなことをしている方がいてとても嬉しいです!
譜面生成できると自分や他者の手順を確認できて、上達に良さそうですね。
画像解析の精度など課題も多いですが、今後ももっといろんなことが見れるようになるといいなーと思ってます!

もるつ
Bo_no36
Bo_no36
2月24日 21時32分

はじめまして!
詳細な記事をありがとうございます。
大変面白く読ませて頂きました!
僕もぷよぷよの分析に興味あるので、こちらの記事を参考に実践してみます!

mokkun393939
mokkun393939
2月25日 0時29分

Bo_no36 さん
ありがとうございます!
いろんな人に考えてもらうことで、自分にはないアイデアや発想が産まれることも期待しています!是非実践お願いします!

Bo_no36
コメントするにはログインが必要です
シェア