見出し画像

雀魂牌譜解析001

雀魂の牌譜を解析したい。

構造を調べてみると大変に面倒くさいことが分かった。このシリーズは解析のためのメモ書きを行っていく。


前提

処理本体は「code.js」にまとまっている。code.jsは「version.json」を取得して、code.jsを決定している。

code.js内では牌譜は「paipu」という変数名・名称が使われている模様。code.jsは改行やインデントが除去されているものの、難読化はされておらず変数名が直接残っている。

LayaBoxという中国のフレームワークを使っているっぽいが、不案内。

请先引用小游戏适配库laya.wxmini.js, 详细教程:
https://ldc.layabox.com/doc/?nav=zh-ts-5-0-0
ミニゲーム適応ライブラリーlaya.wxmini.jsの詳細なチュートリアルを参照してください:https://ldc.layabox.com/doc/?nav=zh-ts-5-0-0

エラーメッセージは主に中国語だが、都度Google翻訳で翻訳すれば処理の理解に役立つ。

雀魂は中国語・日本語・英語に対応しており、役名などは「language.txt」を取得して中身が「jp」か「en」かそれ以外か(こちらは詳細は不明)によって切り替えている。


API

wss://mjjpgs.mahjongsoul.com:4501/

様々な処理は、上記URIへアクセスして行っている。

このリソースへのアクセスを監視することで色々分かってきた。
ひとまず今は牌譜の取得にのみ焦点を当てて解析する。


牌譜の取得要求

 app.NetAgent.sendReq2Lobby("Lobby", "fetchGameRecord", {
           game_uuid: t
       },

牌譜のUUID(牌譜URLの?以降)を指定し、このコードで牌譜を取得している。

実際に送出されていたリクエストは以下。

画像1

感のいい方なら分かるかと思うが、バイナリデータ形式(´・ω・`)。
文字列は普通にutf-8で問題ないが、数値等は色々解析が必要で面倒くさい。


取得した牌譜データ(バイナリ)の解析-UUID

画像2

まず例のごとく牌譜のUUIDを返してるっぽい。


取得した牌譜データ(バイナリ)の解析-プレイヤー名

続けてユーザーの名前が4人分帰ってくる。多分称号も入ってるはず。

画像3

各プレイヤー名は「00」~「03」+「1a」+バイト長というデータの後、utf-8で記録されている。

画像4

確かに、以下の条件で強調してみると4名分の名前がその単位で記録されていることが分かる。他にも記録されているデータが有る模様だが、牌譜を抽出する目的では必要なさそうなので無視する。

0[0-3][ ]?1a


取得した牌譜データ(バイナリ)の解析-新しい局

バイナリデータではあるが、「lq.GameDetailRecords」から牌譜の情報が始まり、「lq.RecordNewRound」が各局それぞれの牌譜の開始を示していることが分かった。

これは解析しやすい。

画像7

実際「code.js」に「RecordNewRound」で検索すると、該当するコードを特定できた。


取得した牌譜データ(バイナリ)の解析-配牌

画像5

4人分の配牌がそのまま記録されていた。

画像6

対面が起家で、

・対面:一一二⑥⑥⑧12346南發發、接頭辞「:.」(0x3a02)
・上家:二四四③⑤⑨289南西北白、接頭辞「B.」(0x4202)
・自家:三四赤五六七七九④⑦⑧19南、接頭辞「J.」(0x4a02)
・下家:三七②③④⑨48西西北白白、接頭辞「R.」(0x5202)

と対応していることが分かった。

取得した牌譜データ(バイナリ)の解析-配山コード

画像8

画像9

配山コード(ハッシュ値)は直接utf-8の文字列として記録されている。そして即座に配山も記録されていた。


取得した牌譜データ(バイナリ)の解析-配山と王牌

画像10

画像11

画像12

王牌は配山の最後の14牌。

表ドラが8pで裏ドラが2s。2s8pという順番なので注意。それ以外は普通に配山の前から順番どおりに該当する。


取得した牌譜データ(バイナリ)の解析-摸打

画像13

親が第一打「南」、上家ツモ「西」→打「北」。

画像14

・打牌:lq.RecordDiscardTile…打つ牌
・ツモ:lq.RecordDealTitle…ツモる牌

実際に打つ牌とツモる牌が記録されているが、それ以外のデータも散見される。詳細は不明。


取得した牌譜データ(バイナリ)の解析-立直

詳細は不明だが、立直のパターンが分かった。

画像15

対面が7pをツモって、8pで立直をかけた。

画像16

7pを「lq.RecordDealTitle」(ツモ)し、8pを「lq.RecordDiscardTile」(打牌)している。

また、初めてのパターンとして「lq.RecordDealTitle」の後に「8p 8p 5p 5p」というデータが記録されており、打てば聴牌となるパターンが記録されているように見える。

同様に「lq.RecordDiscardTile」の後ろに「6z 4s」と和了牌も記録されている模様。

立直したフラグも記録されていると思われるが、データからでは特定できない。ただ、これはソースを解析したほうが早そうなので次回に回す。


取得した牌譜データ(バイナリ)の解析-チー

画像17

上家2mをチーして9mを打ったパターン。

画像18

・lq.RecordChiPengGang

が、チーを表している模様。「3m4m」で「2m」をチーしていることが記録されている。その他2m-5mなどのデータもあるが、それは詳細不明。

チー後の打牌は「lq.RecordDiscardTile」で、9m。和了牌「6p」が記録されている。9pも記録されており、役があるかどうかというより、「和了系」となる牌を示すようだ。


取得した牌譜データ(バイナリ)の解析-和了

やっちまった(´・ω・`)。

画像19

生牌の發であることは分かっているが、序盤の立直で哭きがないのでこれ以外に選択肢はない。

…牌譜解析の材料となってラッキーと思おう。

例のごとく和了りは「lq.RecordHule」と記録されている。和了りの形である

・⑤⑥⑦12344567發發發

が記録されている。


なお、翻数や符、和了点などは記録されていないように見える。その場で計算しているのかも。


最後に

画像20

とりあえず雀魂の牌譜は認証周りがクリアできれば、解析するソフト・アプリを作れそうだ。

今回の解析である程度仕組みが理解できた。まだ色々と解析しきれていない点はあるけど、それは後日Javascriptの中身を詳細に解析して行きたいと思う。


ということで、今回の内容はこれで終わりです!

画像21

よかったら、YouTubeのチャンネル登録や、Twitterのフォローをお願いします✊

↓ ↓ ↓ YouTubeチャンネル登録お願いします(っ'-') =͟͟͞͞👍 ブォン ↓ ↓ ↓


↓ ↓ ↓ Twitterのフォローもお願いします📲_(:3」∠)_ ↓ ↓ ↓



記事を読んでいただき、ありがとうございます。何かの参考になりましたら、ツイッター等でシェアして頂けると嬉しいです!😉 サポートいただけるとモチベアップに繋がります!