プログラム

2014年05月23日

PAIFUN ファイルの形式 (1)

PAIFUN ファイルの形式 (0) ではわかっていなかった新しい情報がいくつかある。

  • 打牌の6バイト後にはツモ切りなら1が格納されている
  • ポン牌の6バイト後に0は上家から、1は対面から、2は下家からを表す
  • 誰から鳴いたかを示すのは取牌部と最終形との両方に付され、最終形なら面子全体に付される
  • 最終形で加槓になっていても誰から鳴いたかは残ったまま
  • 河の8バイト後には放銃なら2が、流局なら4が格納されている
  • カンで増えた手牌は副露数に対応する位置に置かれる (最も右の副露が槓子ならアガリ牌の手前、最も左の副露が槓子なら13枚目の直後)
  • 最終形で横にする牌の 0x10 バイト後に1が格納されている


wo_da_majiang at 23:45Comments(0)Trackbacks(0)

2014年05月17日

PAIFUN ファイルの形式 (0)

概要

牌譜編集ソフトPAIFUN のデータを他の形式に変更することを試みる。

序論

PAIFUN というソフトウェアが、作者の Web サイト JANPARK で配布されている。 現在のバージョンが公開されたのは1997年で、Web サイトが更新されたのは2010年が最後である。 当該ソフトは麻雀界で広く利用されている [要出典] が、突然の公開終了や今後の OS アップデートへの対応などのリスクがある。 本研究では PAIFUN のデータ形式を推測し、他の形式の牌譜 [天鳳][東風荘] へ変換できるようにすることを試みる。

More...

wo_da_majiang at 09:18Comments(0)Trackbacks(0)

2013年09月01日

最高到達段位の確率分布

うたたねこ氏によるシミュレーションの純粋数値計算による追試。 といえば聞こえがよいが、まあ、ただの二番煎じのようなもの。 鳳凰卓で打てなくなる場合の処理 (0試合で七段に復帰) は、シミュレーションの条件と合わせてある。 ただし、実力八段の順位分布は確率が等差数列となる [0.264705882, 0.254901961, 0.245098039, 0.235294118] とした。 数値計算では、まず (現在の段位およびpt, 最高到達段位) でインデクスされた存在確率ベクトルを作り、推移行列を乗じることを繰り返す。 ただし、インデクスは1次元にしない方が書き易く、推移行列は疎であることを利用しているので、実装は普通の行列乗算とは大きく異なる。

結果を表にする。 量が多すぎるような気もするが、気にしない。 有効数字は8桁から10桁だと思うが、確率の106倍を四捨五入してある。 丸め誤差によって合計が最大2ずれうる。

最高到達段位の確率分布: 鳳南七段 (画像)
南七
100921216787127200
200768101227615428130
30063900434480016123730
400531679435792322093190
500442398506822500157632
6003681135621726834313674
7003063036049428666320848
800254871637495104746287514
900212075661696122494371520
1000176465679047139874458628
20002807766422729384613737114
3000446755573541669022905203
400071145259751441231987293
500011336669759182440983382
60001829680065281649894472
7000324017870053758720562
8000019435173753567463651
9000015726676587076123741
10000012725878721284701830
200000153178168321661261725
30000018447553952401412620
4000002226888513074143513
500000276270163685514406
60000035705934241065298
70000005192314745796189
80000004724905204307080
90000004299575620747969
100000003912525998908858
最高到達段位の確率分布: 鳳東七段 (画像)
東七
1009909669034000
200929977699913200
30085602414344752900
400785858212077206500
500721246274077467430
6006619523299258112100
70060754738030912120240
80055762242583716497450
90051180346701921106720
1000469751504288258561050
2000199311725729743875730
30008456679342512091510921
40003588179744816505516141
50001522477571520692421362
6000645974424524663626572
7000274170977628430231793
8000116367510932002537003
900049364137735390542204
1000020960901038603647414
20000036143962862299309
3000002144367704591509114
4000001272218525332022619
500000754788991632533424
600000447809247753041629
700000265679379283547134
800000157629437004049939
90000093519451034550144
100000055489439265047749
最高到達段位の確率分布: 鳳南八段 (画像)
南八
10084478015487234700
20057821940209119647430
300393067534877710989571
400267257592966135486427714
5001817326077202000541041875
60012358059746125985418885221
7008403657300931349028996469
8005714554092236093640177820
90038860505233402632520121263
100026425468435439140642161785
20005591907026154101844168914
3000127389262068028862216794
400002855756947037730824665
500001103550385745263132477
60000426443905051646040226
70000164838003957040147913
8000063732798961583655539
9000024628269665395563103
1000009524351368578570607
200000054531803050142419
300000012207779112208682
40000002732727443269825
5000000612673145326243
6000000137621560378303
700000031573630426340
80000007529328470665
90000002488433511565
100000000450695549305
最高到達段位の確率分布: 鳳東八段 (画像)
東八
10097475225248000
20081846118122331600
300649719345218506210
40051068846985319438210
500400773555847432361450
600314457611497735345120
70024673864461310740312461
80019360966128414269624092
90015192366603617803040066
1000119214662189212581600313
20001055447283747892237400287
300093429663762817273502755
4000831830907067801087891259
500071127467427281427501770
60001694057529321753812281
70000427237477552067302792
80000262987335552368453302
90000161887142262657733813
10000099656921512935614323
200000784728625176509411
300000131856766696014472
400000021458576590719508
500000014454283094024518
60000009736287313529503
70000006558289995634462
80000004417691642939395
90000002975692594044304
100000002004493076949187


wo_da_majiang at 01:02Comments(0)Trackbacks(0)

2012年12月29日

昇降段率数値計算機 (1)

前の記事で「まだ公開していないが」と書いた「昇段するまでに何ゲームを消化するかの期待値」について書くことにする。 これを年内に書くモチベーションを得ることができたのは、@enkaism さんがツールを公開されたことによるので感謝したい。 なお、12/29版のツールは私の記事とは独立であったようだ。

確率変数 X を「昇段する場合は、それまでにプレイする試合数。降段する場合は0」とおく。 すると、その期待値 E[X] を昇段する確率 W で割れば、昇段する条件でのプレイする試合数の期待値が求められる。 もちろん E[X] は現在の段位ポイント x の関数である。 境界条件は「0未満やM以上では0」となる。

W(x) と同じように考えることによって、E[X](x) の新しい漸化式が E[X](x) = W(x) + Σ[1 ≦ r ≦ 4]prE[X](x+Vr) とわかる。 第1項は、現在のポイントから昇段する場合は最初のゲームが算入されるということを表している。

連立方程式を行列の形で表すとき、係数行列は W(x) を求めるためのものと全く同じで、定数部分だけを上の式に従って変えればよい。 つまり、前の記事のコードでいう GaussEliminationb にあたる部分に、W(x) を入力すればよいのである。



wo_da_majiang at 15:38Comments(0)Trackbacks(0)

2012年12月21日

昇降段率数値計算機 (0)

天鳳の段位戦はレーティング以上に段位ポイントが重視され、シミュレーションなどによる遊びや研究の対象となってきた。 順位分布から段位変動をシミュレートするツールとしてkansenzako氏によるものなめとん氏によるものが、具体的なテーマを定めた研究にはみ〜にん氏によるものがある。 個人的にはレーティングには興味があるが、段位は「レーティングの差を正しく解釈できるほど賢くないプレイヤーにも、パッと見て「格の違い」をわかりやすく提示するツール」と軽く見ていた。

私の主観に変更はないが、段位の変動はシミュレートによらなくても簡単な計算で明らかにすることができると気付いた。 段位ポイントが離散値を取ることを利用し、昇段や降段の確率や、それまでにプレイするゲーム数の期待値を求めることついて記しておくことにする。

まず前提となる条件をまとめておく。 プレイする卓のランク・ゲームの種類は任意に1種とって固定する。 ランクは簡単のため、特上 (四段以上) と鳳凰 (七段以上) とに限る。 ゲームの種類は、東南と東風との区別のみを問題とする。 ただしこれは「東南に決めたならそのどのルールを打ってもよい」という意味ではなく「東南のルールを任意にとって固定したことにするが、どれに固定したかは計算上は不問となる」という意味である。 プレイしている間、実力の変化や流れ的な現象は起こらないとする。 つまり、各ゲームの結果は確率変数として独立同分布 (i.i.d.) である。

1位から4位を獲得する確率をそれぞれ p1, p2, p3, p4 とする。 もちろんこれらは [0..1] の値をとり、p3 = 1 - (p1+p2+p4) である。 現在の段位で1位から4位を獲得した場合の段位ポイント変動を V1, V2, V3, V4 とする。

段位ポイントが 0 未満で降段、現在の段位によって決まる定数 M 以上で昇段する。 有限ゲーム後、降段するより先に昇段する確率を W とし、昇段するより先に降段する確率を L とする。 これらはともに現在の段位ポイント x の関数である。

一般的な設定では獲得段位ポイントの絶対値の期待値は正である。 すなわち Σ[1 ≦ r ≦ 4]pr|Vr| > 0 となる。 この仮定がみたされないのは、特上卓や鳳凰卓では「必ず3位を取る」場合のみである。 この仮定がみたされるとき、確率1で有限ゲーム後に昇段または降段する。 すなわち W(x) + L(x) = 1 である。 したがって、以下 W(x) のみを考えれば十分である。

ポイントが 0未満や M以上であるときは、昇段と降段のどちらが先であるか確定している。 つまり x < 0 ⇒ W(x) = 0 および MxW(x) = 1 が成り立つ。

x が上記の範囲外であるとする。 このとき昇段や降段の確率は、最初にプレイするゲームの結果によって変化する。 具体的には、ゲームの結果が r位であれば昇段の確率は W(x+Vr) に変化する。 r位になる確率は pr であったから、結局 W(x) = Σ[1 ≦ r ≦ 4]prW(x+Vr) となる。

このままでは厄介な関数方程式であるが、よい性質が2つある。 まずxは離散的である (具体的には5の倍数のみをとる) から、上の方程式は有限個である。 次に関係式は線型なものだけからなる。 したがって、問題は連立一次方程式に帰着される。 変数は十段であっても 4000/5 = 800個 しかないため、特に工夫をしなくてもガウス消去法で解くことができる。

以下は上記の式を行列で表し、標準的なアルゴリズムで解くコードである。 プログラミング言語は書き易くて高速に動作するD言語を用いた。

More...

wo_da_majiang at 22:36Comments(0)Trackbacks(0)

2011年05月24日

整数除算の仕様比較

プログラムを組んでいて嵌まったので、メモしておく。

整数除算の仕様
言語Python
4 / 311
4 % 311
(-4) / 3-2-1
(-4) % 32-1
4 / (-3)-2-1
4 % (-3)-21
(-4) / (-3)11
(-4) % (-3)-1-1

具体的には Java で組んでいて Python と同じように書いて嵌まったのだが、使ったことのある他の言語 (Visual Basic, C++) も Java と同じ仕様だった。 数学的には Python の仕様が最も正しいだろう。



wo_da_majiang at 23:14Comments(0)Trackbacks(0)

2010年02月25日

平和天和におけるドラ指標牌枚数の確率分布

放置しすぎていたので、最近書いたプログラムでも。 以下に示すのは「平和天和におけるドラ指標牌枚数の確率分布」を求めるための基礎データを出力するプログラムである。 プログラムは4つの部分からなる。

RANK, IDENTICAL = 9, 4 # tile condition
PAIR, SET, SETS = 2, 3, 4 # winning condition
USEPAIR = 1 # if zero, no pair
ONESEQ = RANK-SET+2 # Frequently used constant

まずは設定を行う。 Python では複数の変数へ同時に代入を行うことができる。 上3行は順に数牌の定義、和牌型の定義、雀頭を含む組合せを出力するかどうかの設定で、第4行は順子の種類数を表す定数である。 順子にはプログラム上、ランクの小さいものから順に 0, 1, ... が割り振られるが、順子を使わない場合を -1 で表す。

SP = set([tuple(sorted(filter(lambda seq: seq != -1, [idx // ONESEQ**seti % ONESEQ - 1 for seti in range(SETS)]))) for idx in range(ONESEQ**SETS)])
# all -> filter -> sort -> set
SP = [[sum(map(lambda seq: seq <= rank < seq+SET, P)) for rank in range(RANK)] for P in SP]
# sequence index -> tile count
SP = filter(lambda P: max(P) <= IDENTICAL, [[P[i]+PAIR*(i==pair) for i in range(RANK)] for P in SP for pair in range(-1, RANK*USEPAIR)])
# with or without pair

この3行で順子および雀頭からなるパターンをすべて生成している。

各 idx に対して [idx // ONESEQ**seti % ONESEQ - 1 for seti in range(SETS)] は第 idx 番目の順子使用パターンを与えるが、これを idx in range (ONESEQ**SETS) に対して並べるだけでは「順子を使わないという意味の -1 を順子番号として含んでいる」「順子を使う順番を区別している」という問題がある。 そこで「順子を使わないという意味の -1 を除去する」「順子の番号をソートする」「集合とすることによって重複を除く」という操作を行っているのだが、リストを集合に変換する際に tuple を使い、その要素をタプルに変換している。 これはリストが hashable ではないため集合の要素として使えない (一方、タプルは変更不可能なため hashable で、集合の要素として使える) という仕様に基づいている。

次に順子番号のタプルを、各牌を使用する枚数のリスト (牌式) へ変換している。

最後に対子を加えた組み合わせを生成するのだが、ここでも対子インデクス -1 を「対子なし」として処理している。

def uradora(P):
    return [sum([IDENTICAL-P[rank-1] for rank in range(RANK) if P[rank] == identical]) for identical in range(IDENTICAL+1)]
def prob(P):
    return reduce(lambda a, b: a*[1, 4, 6, 4, 1][b], P, 1)
F = [[tuple(uradora(P)), prob(P)] for P in SP]
# uradora pattern probability

uradora 関数は牌式 P を受け取って「裏ドラが n 枚乗るための指標牌は m 枚ある」というリスト (裏ドラ分布) を返す。 prob 関数は同様に、牌式 P を受け取って「牌式 P をみたす牌の組合せ数」を返す。

これらのリストは、必要とするデータのほぼすべてを含む。

for e in sorted([[RANK*IDENTICAL-sum(k)] + list(k) + [sum([P[1] for P in F if P[0] == k])] for k in set([P[0] for P in F])]):
    print '	'.join(map(str, e))

最後に整形出力してプログラムは終了である。 それぞれの裏ドラ分布に対して、使用している牌の枚数、裏ドラ分布、それをみたす牌の組合せ数の和をリストとして生成し、これをソートする。 それらを1行ずつ、タブ文字でつないでテキストとして出力している。

行がはみだしても気にしない。



wo_da_majiang at 11:36Comments(0)Trackbacks(0)

2009年03月08日

中麻平和何切る (1)

前稿では、平和の点数を評価するべき手の総数について上界を求めた。 実際にプログラムを組む際には、この上界を減らす工夫が重要である。

麻雀において、ある意味で「同じ形」と考えることのできる手牌には3つのパターンがある:

反転
全ての牌のランクを、10から引いたものに変更する。ex. 12344m345567p234s → 66789m345567p678s
変色
スートごとに、牌式を交換する。ex. 12344m345567p234s → 12344m234p345567s
平行移動
すべての牌のランクに、定数を加える。ex. 12344m345567p234s → 23455m456678p345s

これらによってパターンを削減することを考えよう。 ただし、操作「変色」においては定色役*1について、「平行移動」においては偏数役*2について、それぞれ「同じ」ではなくなることがある。*3 変色で緑一色の有無が変わるような手は、ほとんど清一色だから、8点を作るという観点からは問題として重要ではない。 また、推不倒が狙える手はそれをわかっていれば済むので、推不倒を無視しても大きな影響はない。 平行移動については、8点を作るという観点から、8点以下の役、すなわち断幺の有無については注意する必要がある。 また、非和了形において両搭を平行移動すると辺搭が現れたり、その逆が起こるので、やはり平行移動については特に注意しなければならない。

*1 定色役: 限られたスートの数牌で成立する役。推不倒・緑一色 の2種を指す。

*2 偏数役: 数牌のランクによる全体役。 断幺・大于五・小于五・全大・全中・全小 の6種を指す。

*3 反転は偏数役に影響を及ぼすが、断幺および全中は結果として変化がなく、他4役は大小が反転するだけなので、注意するに及ばない。

More...

wo_da_majiang at 11:07Comments(1)Trackbacks(0)

2009年03月03日

中麻平和何切る (0)

中国麻将の「何切る」は、日本麻雀のような「この手は攻めるべきか降りるべきか」より、純粋に「この手を和了に結びつけるためにはどちらを切るべきか」が難しく、また重要であることが多い。 理由の1つには8点縛りがある。 なんとしてでも8点を作らなければならず、そのためにはまだ関連牌すらないところに面子を見出したり、鳴きを駆使したりするのだ。

中国麻将を始めた人が最初に出会う中麻独自の役は、三色三歩高だろう。 「数牌の雀頭で順子4組なら、待ちがどんなのでも平和だよ」- そう言われてまず「ぴんふさんぷーこー、はちはじゅうろく」を目指すのではないか。

三色三歩高の特殊性は、もう1つの順子によって成立する役が自在に変化することだ。 たとえば 123m234p34sXX という聴牌は、5s で三色三歩高が成立するが、2s では点数がたりない片和了りだ。 しかし、ここに第4の順子を加えると状況は一変する。 それがもし 234m であれば三色三同順、345p であればまた別の三色三歩高が成立するのだ。

このような、両面待ち (以上) で、和了牌によって別々の軸手役*1が成立して和了となるような聴牌を「両和了り」ということがある。 三色三歩高を狙う際には、この「両和了り」聴牌を目指して打牌することになる。

これに関してきんとん氏はすでに非常に多くの成果を出され、その一部を公開されているが、私はプログラムによる力技で全解を求めてみようと思う。

*1 軸手役: 和了が8点縛りを満たす中心となる手役の意。6点以上の手役を指す。

More...

wo_da_majiang at 01:27Comments(3)Trackbacks(0)

2009年02月10日

正規表現

Python CGI で大会集計をやるので、開発のついでに要素を切り分けてここに書いておこうと思う。第1回は正規表現。

Python を含めた多くのプログラミング言語で強力な文字列検索/置換機能を提供しているのが、正規表現。天鳳のログにマッチするもの。

四麻
\d{2}:(\d{2} \| ){2}四(般|上|特|鳳)(東|南)(喰|−)(−|赤) \|( [^ ]+\((\+|-)?\d+\)){4}
三麻
\d{2}:(\d{2} \| ){2}三(般|上|特|鳳)(東|南)(喰|−)(−|赤) \|( [^ ]+\((\+|-)?\d+\)){3}

正規表現は、初めて見たときは暗号にしか見えないが、初めて理解したときは感動するものである。



wo_da_majiang at 00:20Comments(0)Trackbacks(0)

2008年08月16日

Real Mahjong Rating & Ranking System

研究やプログラムに没頭しているときほど、逆に記事を書く暇もないとは皮肉なことである。 今回は後者、ちょうど佳境に入ったところだ。

プログラムの内容であるが、麻雀研究と直接は関係がない。 麻雀店用の成績管理システムで、いくつかの評価基準をもとにしたレーティング (詳しくは 麻雀評価論 (2) を参照のこと) などを出せるようにする予定である。

ネット麻雀のように「正しい試合結果が即時に入力される」のではないのが、少し難しかったところだ。 入力ミスなどを修正できる必要があるため、入力と同時にレーティング値の更新などをしてはいけないのだ。 そこでゲームデータを「未確定」と「確定」の2つに分け、ある程度「未確定」データが集まったら手動 (といっても、もちろんワンクリックである) で「確定」の操作をすることによってレーティング変化を追い、ランキングや個人戦績を更新することにした。

現時点で、未確定ゲームデータに関する入力 / 修正などの操作を実装が完了した。 また、成績出力用の XSL がほぼ完成しているので、残っているのはメインの「確定」「出力」となる。

# 発注元以外でも、使ってみたいという麻雀店があればメールで連絡いただきたい。 発注元である程度動くようになった時点で返答いたす。



wo_da_majiang at 22:56Comments(0)Trackbacks(0)

2008年04月06日

天鳳におけるデータ麻雀 (2)

前の記事で触れた日記にコメントをつけたところ、お返事をいただいた。 有志の方が作成されているそうだが、テスト版につき、一般公開はしていないとのこと。

今後、勝手に要望一覧を書く予定。



wo_da_majiang at 00:31Comments(0)Trackbacks(0)

2008年04月05日

天鳳におけるデータ麻雀 (1)

マイミクシィのマイミクシィのマイミクシィのある方が書いた日記で「天鳳の牌譜解析プログラム ver0.1.17」というスクリーンショットを見つけた。 東風荘においては、とつげき東北氏による「できすぎくん」が広く使われているが、それに近い機能をもっているようだ。

しかし検索してもダウンロードできるところが見つからない。どういうわけなのだろうか。 有料版天鳳の付属スクリプトが短期間のうちにここまで進化したとは考えにくいことから、有志の方が出力ファイルを読んでデータを吐くプログラムを作ったのだと思うのだが。

これを見て、特上に行って打ちたいという気持ちが少し出てきた。

まずはツールについての情報を知りたい。何か知っている方はコメントしていただければ幸いである。



wo_da_majiang at 14:31Comments(0)Trackbacks(0)
About

我打麻将

我打麻将の研究ノート

  • 各種ルールによって行われる麻雀の研究記録ブログです。
  • 研究課題や未知のルールは常に探しております。
  • 研究課題、未知と思われるルールを考え付いた・どこかで見た方は、e-mail またはコメントにてご連絡ください。

Sponsor

  • 当ブログの牌画は「雀のお宿」百貫雀氏によるものをフォーマット変更の上、利用しています。2次(実質3次)利用などは、氏の「雀のお宿」にて示されているガイドラインに従ってください。
Recent Comments
QR Code
QRコード
  • ライブドアブログ