天鳳牌譜 mjlog形式について
牌譜解析するにあたって、mjlog形式の仕様がよくわからないので調べた。 2010年ごろの記事は多いんだけど、リンクが切れてたりなんだかんだでアレなので書きます。
なにか気づき次第追記していきます。
目次
- 参考文献
- 牌譜の入手方法
- ファイル構造
参考文献
先人たち
公式のコード
http://tenhou.net/1/script/tenhou.js
http://tenhou.net/img/tehai.js
牌譜の入手方法
プレミアムだと簡単に自分の分は保存できるらしい。
牌譜IDを入手する
Flash版クライアントの[メニュー]->[牌譜の管理]->[バックアップ]に
http://tenhou.net/0/?log=2011020417gm-00a9-0000-b67fcaa3&tw=1
こんな感じのURLがある。このlog=の後の、正規表現でいうところの
[0-9]{10}gm-[0-9a-f]{4}-[0-9]{4}-[0-9a-f]{8}
な部分を牌譜IDと以降呼ぶ。 これは、
{日付時刻}gm-{対局形式}-{ロビー}-{乱数?}
という構造である。
また、tw=1の部分は自分がどのユーザかを示す(後述)。
大量の牌譜を入手したい場合は、鳳凰卓のみ公開されている。
http://tenhou.net/sc/raw/
また天鳳位の一人ひとりの牌譜も公開されている。
http://tenhou.net/ranking.html
mjlogファイルの入手
http://tenhou.net/0/log/?2011020417gm-00a9-0000-b67fcaa3 のように入手できる。
観戦用リンクは /0/?log={ID}&tw={Who} に対し、牌譜リンクは /0/log/?{ID} であるので注意すること
このリンクは
- http://e.mjv.jp/0/log/archived.cgi?{ID}
- http://e.mjv.jp/0/log/plainfiles.cgi?{ID}
- http://e1.mjv.jp/0/log/?{ID}
などにリダイレクトされるが、正直よくわからない
mjlogファイルがgzip圧縮されているという記述をたまに見かけるので留意すること。 おそらく古いファイルのみで、私はあまり古いファイルを解析しないので遭遇していない。
ファイル構造
mjlogファイルはXML形式で記述されている。mjloggmタグ以下は階層構造を作っていない。
<mjloggm ver="2.3"> <SHUFFLE seed="略" ref=""/> <GO type="169" lobby="0"/> <UN n0="%2D%72%6F%6E%2D" n1="%41%53%41%50%49%4E" n2="%E3%81%86%E3%81%8D%E3%81%A7%E3%82%93" n3="%E8%B6%85%E3%83%92%E3%83%A2%E3%83%AA%E3%83%AD" dan="16,19,16,18" rate="2135.55,2260.11,2018.07,2198.52" sx="M,M,M,M"/> <TAIKYOKU oya="0"/> <INIT seed="0,0,0,2,2,112" ten="250,250,250,250" oya="0" hai0="48,16,19,34,2,76,13,7,128,1,39,121,87" hai1="17,62,79,52,56,57,82,98,32,103,24,70,54" hai2="55,30,12,26,31,90,3,4,80,125,66,102,78" hai3="120,130,42,67,114,93,5,61,20,108,41,100,84"/> <T107/> <D39/> <U47/> <E70/> <V14/> <F125/> (中略) </mjloggm>
麻雀牌について
それぞれの牌には0~135のIDが割り当てられている。
0~3は1m,4~7は2mといった具合である。順序は萬子→筒子→索子→東南西北白發中である。Unicodeの配置順とは異なるため注意すること。
赤ありの場合、赤はmod4で0となる牌(16,52,88)に割り当てられている
hai = ["一", "二", "三", "四", "五", "六", "七", "八", "九", #萬子 "①", "②", "③", "④", "⑤", "⑥", "⑦", "⑧", "⑨", #筒子 "1", "2", "3", "4", "5", "6", "7", "8", "9", #索子 "東", "南", "西", "北", "白", "發", "中"] return hai[id >> 2]
mjloggm
<mjloggm ver="2.3">
rootタグ。verは2.3
SHUFFLE
牌山について
<SHUFFLE seed="mt19937ar-sha512-n288-base64,pu4S9w/yELLYjkzj略" ref="" />
refは不明
seed
http://tenhou.net/man/に記述がある。
Q) 乱数種から山を生成する方法を教えてもらえませんか?
ツモ/配牌/王牌などなどは次の方法で乱数種から再現可能です
■2009年7月22日以降
牌山生成手順 http://blog.tenhou.net/article/30503297.html
牌山生成方法の検証用データ http://blog.tenhou.net/article/174202532.html
牌山生成乱数種のハッシュ公開β http://tenhou.net/stat/rand/■2009年7月22日以前
unsigned long seed[n]; // INITのshuffleから生成
mt.init_by_array(seed,n);
for(i=0;i<136;++i) yama[i]=i;
for(i=0;i<136-1;++i) swap(yama[i],yama[i + (mt.genrand_int32()% (136-i))]); // サンマは108
※yama[135,134,133,132]が親の最初の配牌4枚、yama[0]が1つ目の嶺上牌
私はまだ検証していない
GO
対局形式について
<GO type="169" lobby="0"/>
type
対局形式を表す
http://tenhou.net/1/script/tenhou.js を読めば分かる。
BIT | HEX | FLAG=1 | FLAG=0 |
---|---|---|---|
1 | 0x001 | 対人戦 | 対コンピュータ戦 |
2 | 0x002 | 赤ナシ | 赤アリ |
3 | 0x004 | 喰ナシ | 喰アリ |
4 | 0x008 | 東南 | 東風 |
5 | 0x010 | 三麻 | 四麻 |
6 | 0x020 | 特上 | ※ |
7 | 0x040 | 速 | 5+10秒 |
8 | 0x080 | 上級 | ※ |
9 | 0x100 | 暗 | |
10 | 0x200 | 祝 | |
11 | 0x400 | 雀荘 | |
12 | 0x800 | 技能 |
※特上と上級のフラグが両方立っているときは鳳凰、両方立ってないときは一般
(w&0x0020)>>4 | (w&0x0080)>>7; // 0=一般 1=上級 2=特上 3=鳳凰
例の169は10101001より、鳳南喰赤とわかる。
lobby
対局ロビーを表す。段位戦は0
UN
対局者について。
対局開始前に有るが、再接続時なども呼ばれる。再接続時はその人の名前のみ
三麻は三人分しか入ってない(4人目は、名前は"“、段位やレートはデフォルト値、性別はコンピュータ)。
四麻
<UN n0="%2D%72%6F%6E%2D" n1="%41%53%41%50%49%4E" n2="%E3%81%86%E3%81%8D%E3%81%A7%E3%82%93" n3="%E8%B6%85%E3%83%92%E3%83%A2%E3%83%AA%E3%83%AD" dan="16,19,16,18" rate="2135.55,2260.11,2018.07,2198.52" sx="M,M,M,M"/>
三麻
<UN n0="%E3%83%84%E3%83%BC%E3%82%A2%E3%82%A6%E3%83%88" n1="%E3%81%82%E3%82%8B%E3%81%B5%E3%81%83%E3%81%BF%E3%81%83" n2="%40%EF%BC%8D%E8%89%B2" n3="" dan="17,19,16,0" rate="2210,2440,2126,1500" sx="M,F,F,C"/>
再接続
<UN n0="%2D%72%6F%6E%2D"/>
n0,n1,n2,n3
対局者の名前がパーセントエンコーディングされている。観戦機能で匿名表示した時に順にAさん、Bさん、Cさん、Dさんと表示される。起家はAさんとなる。
dan
段位 Aさんから順にカンマ区切りで整数値が入っている。整数値の意味は以下
var DAN=[ "新人","9級","8級","7級","6級","5級","4級","3級","2級","1級", "初段","二段","三段","四段","五段","六段","七段","八段","九段","十段", "天鳳","RESERVED..." ];
rate
レート Aさんから順にカンマ区切りで整数値が入っている。
sx
性別 Aさんから順にカンマ区切りで1文字入っている。M:男性、F:女性、C:コンピュータ
BYE
<BYE who="2" />
who
切断したユーザを表す
TAIKYOKU
対局開始
<TAIKYOKU oya="0"/>
oya
0 固定 起家がAさんであることを表している
INIT
局開始
<INIT seed="0,0,0,0,3,33" ten="350,350,350,0" oya="0" hai0="74,124,51,60,3,36,100,107,123,108,121,111,127" hai1="130,91,56,96,112,117,93,97,2,109,126,79,69" hai2="110,118,52,133,63,62,61,44,49,88,114,59,101" hai3=""/>
seed
この局について カンマ区切りで整数値が入っている。
i | seed[i] |
---|---|
0 | 東一局~北四局 0-3が東一-東四、4-7が南場、8-11が西場 |
1 | 本場 |
2 | リーチ棒の本数 |
3 | 一つ目のサイコロの目-1 |
4 | 二つ目のサイコロの目-1 |
5 | ドラ表示牌 |
ten
点数 Aさんから順にカンマ区切りで整数値が入っている。100倍すること。
oya
親の人を表す
hai0,hai1,hai2,hai3
配牌を表す 牌を表す整数値がカンマ区切りで入っている
[T-W][0-9]*
ツモを表す
TならばAさん、UならばBさん、VならばCさん、WならばDさんのツモ
その後の数が牌を表す
<V94/>
[D-G][0-9]*
打牌を表す
DならばAさん、EならばBさん、FならばCさん、GならばDさんの打牌
その後の数が牌を表す
<D39/>
REACH
立直を表す
<REACH who="1" step="1"/> <E115/> <REACH who="1" ten="250,240,250,250" step="2"/>
who
立直をした人を表す
step
1のとき立直宣言をする。その後打牌をし、ロンされなければstep=“2"が呼ばれる。
ten
リーチ棒を除いた後の点数を表す
N
鳴きを表す
<N who="3" m="42031" />
who
鳴いた人を表す
m
鳴きの形を表す 16bitの整数値
http://tenhou.net/img/tehai.js に詳しい
鳴き | FLAG |
---|---|
順子 | m&0x0004 |
刻子 | m&0x0008 |
加槓 | m&0x0010 |
北抜き | m&0x0020 |
大明槓・暗槓 | otherwise |
上記の表に従って上から順に判定し、鳴きの形を決定する
順子
BIT | HEX | 内容 |
---|---|---|
1-2 | 0x0003 | 食われた人 上家なので3 |
3 | 0x0004 | 順子フラグ 1 |
4-5 | 0x0018 | 最小の数牌のID mod 4 |
6-7 | 0x0060 | 真ん中の数の数牌のID mod 4 |
8-9 | 0x0180 | 最大の数牌のID mod 4 |
10 | 0x0200 | 空き |
11-16 | 0xfc00 | 下記 |
11-16bit目の値をtとする
1m,…,7m,1s,…,7s,1p,…,7pの21枚の中で floor(t/3)番目のものを最小の数牌とする。
floor(t/3)+t%3の数牌が鳴かれた牌
刻子・加槓
BIT | HEX | 内容 |
---|---|---|
1-2 | 0x0003 | 食われた人 下家1,対面2,上家3 |
3 | 0x0004 | 空き |
4 | 0x0008 | 刻子フラグ 刻子なら1 |
5 | 0x0010 | 加槓フラグ 加槓なら1 |
6-7 | 0x0060 | 未使用牌ID mod4 |
8-9 | 0x0180 | 空き |
10-16 | 0xfe00 | 下記 |
10-16bit目の値をtとする
1m,…,9m,1s,…,9s,1p,…,9p東南西北白發中の34枚の中で floor(t/3)番目のものを鳴いた牌とする。
未使用牌を除いて昇順に並べた時、t % 3番めの牌が鳴かれた牌
北抜き
BIT | HEX | 内容 |
---|---|---|
1-5 | 0x001f | 空き |
6 | 0x0020 | 北抜きフラグ |
7-8 | 0x00c0 | 空き |
9-16 | 0xff00 | 牌ID |
勘
大明槓・暗槓
BIT | HEX | 内容 |
---|---|---|
1-2 | 0x0003 | 食われた人 暗槓0,下家1,対面2,上家3 |
3-8 | 0x00fc | 空き |
9-16 | 0xff00 | 鳴いた牌ID |
DORA
槓ドラ 明槓・加槓はツモの後、暗槓の場合は鳴きの後
<DORA hai="8" />
hai
槓ドラ表示牌のID
AGARI
誰かが和了したことを示す。ダブロンなど、2つ発生することもある。
<AGARI ba="2,2" hai="17,22,26,68,70,74,77,81,84,91,94" m="44618" machi="91" ten="30,2000,0" yaku="12,1,52,1" doraHai="73" who="1" fromWho="1" sc="215,-7,285,46,328,-7,152,-12" />
ba
場に出ている点棒を表す カンマ区切りの整数で、ba[0]が百点棒(本場)、ba[1]がリーチ棒を表す。
hai
和了した時の手牌。和了牌も含まれている。 カンマ区切りの整数で牌IDを表す。
m
副露があるときのID カンマ区切りの整数でNのmに同じ
machi
和了牌
ten
点数に関する情報 カンマ区切りの整数で、ten[0]が符、ten[1]が和了点を表す。
ten[2]は和了ランクを表し、以下
ten[2] | 内容 |
---|---|
0 | なし |
1 | 満貫 |
2 | 跳満 |
3 | 倍満 |
4 | 三倍満 |
5 | 役満 |
yaku
役について
[役A,役Aの翻数,役B,役Bの翻数,役C,役Cの翻数]と言った具合である。
役満はyakuman属性に記述される。
var YAKU=[ //// 一飜 "門前清自摸和","立直","一発","槍槓","嶺上開花", "海底摸月","河底撈魚","平和","断幺九","一盃口", "自風 東","自風 南","自風 西","自風 北", "場風 東","場風 南","場風 西","場風 北", "役牌 白","役牌 發","役牌 中", //// 二飜 "両立直","七対子","混全帯幺九","一気通貫","三色同順", "三色同刻","三槓子","対々和","三暗刻","小三元","混老頭", //// 三飜 "二盃口","純全帯幺九","混一色", //// 六飜 "清一色", //// 満貫 "人和", //// 役満 "天和","地和","大三元","四暗刻","四暗刻単騎","字一色", "緑一色","清老頭","九蓮宝燈","純正九蓮宝燈","国士無双", "国士無双13面","大四喜","小四喜","四槓子", //// 懸賞役 "ドラ","裏ドラ","赤ドラ" ];
tenhou.jsより
yakuman
役満の種類 複合役満の場合、カンマ区切りの整数 役満のときのみ存在
doraHai
ドラ牌 複数ある場合はカンマ区切りの整数
doraHaiUra
裏ドラ牌 複数ある場合はカンマ区切りの整数 存在しないときは省略される
who
誰が和了したか
fromWho
誰が放銃したか ツモ和了の場合whoと一致する
sc
点数 カンマ区切りの符号付き整数
[Aさんの点数, Aさんの変動,Bさんの点数,Bさんの変動,……,Dさんの変動]
この点数は変動が反映される前の点数となっている
owari
終局を示す
点数 カンマ区切りの符号付き整数
[Aさんの点数, Aさんのスコア,Bさんの点数,Bさんのスコア,……,Dさんのスコア]
スコアにはウマが含まれている
RYUUKYOKU
流局を示す
<RYUUKYOKU ba="1,2" sc="200,15,270,15,343,-15,167,-15" hai0="8,9,15,19,20,24,25,26,29,33,41,47,50" hai1="27,30,52,53" />
ba
場に出ている点棒を表す カンマ区切りの整数で、ba[0]が百点棒(n本場)、ba[1]がリーチ棒を表す。
sc
点数 カンマ区切りの符号付き整数
[Aさんの点数, Aさんの変動,Bさんの点数,Bさんの変動,……,Dさんの変動]
この点数は変動が反映される前の点数となっている
hai0,hai1,hai2,hai3
流局によって手牌が公開される場合の牌。カンマ区切りの整数
副露したものは示されない。
聴牌したプレイヤーもしくは九種九牌のプレイヤーのみ表示
type
流局の種類 通常の流局以外の場合存在
type | 流局 |
---|---|
yao9 | 九種九牌 |
reach4 | 四家立直 |
ron3 | 三家和了 |
kan4 | 四槓散了 |
kaze4 | 四風連打 |
nm | 流し満貫 |
owari
終局を示す
点数 カンマ区切りの符号付き整数
[Aさんの点数, Aさんのスコア,Bさんの点数,Bさんのスコア,……,Dさんのスコア]
スコアにはウマが含まれている