延ばし延ばしにしていた和了点の計算について。
麻雀の和了点を求める手順は以下の流れになる。
- 状況役*1の一覧を作る
- 懸賞役*2の一覧を作る
- 和了形の一覧を求める
- 個々の和了形について以下を行う
- 面子構成を調べ、符を計算する
- 手役の一覧を求める
- 符、状況役、手役、懸賞役から和了点を計算する
- 得られた和了点の最大値を解とする
和了形を求めるプログラム - koba::blog でも触れたように和了形は複数に解釈できる場合があり、日本麻雀のルールではその最高点を選択しなければならない*3。
和了点を計算するだけでは不十分で、ゲームを進める上では各プレーヤーの点数の移動の情報も必要だし、ゲームの表示上は和了役の表示も必要だろう。
電脳麻将 では、Majiang.Util.hule()
で和了点計算をしている。
Majiang.Util.hule = function(shoupai, rongpai, param)
shoupai
は 麻雀の手牌のJavascript表現 - koba::blog で説明した Majiang.Shoupai
のインスタンス。ロン和了の場合は和了牌をツモった形にして呼出す。
ドラ表示牌
上記の和了形の場合、
{ _bingpai: { m: [0,2,3,0,0,0,0,0,0,0], p: [0,0,0,0,0,0,0,1,1,1], s: [0,0,0,0,0,0,0,0,0,0], z: [0,0,0,0,0,0,0,0], }, _fulou: ['p456-', 'p1-23'], _zimo: 'p8' }
となる。
rongpai
は和了牌。麻雀の手牌の文字列表現 - koba::blog の単独の牌の形式と大体同じだが、誰から和了したかの情報を付加する。上記を対面からの和了とすると、'p8='
となる。
param
は牌姿からは判断できない和了点計算に必要な情報。
{ zhuangfeng: 0, // 場風 (0: 東, 1: 南, 2: 西, 3: 北) menfeng: 1, // 和了者の自風 hupai: { lizhi: 0, // 1: 立直, 2: ダブル立直 yifa: false, // 一発のとき true qianggang: false, // 槍槓のとき true lingshang: false, // 嶺上開花のとき true haidi: 0, // 1: 海底摸月, 2: 河底撈魚 tianhu: 0 // 1: 天和, 2: 地和 }, baopai: [ 'p1' ], // ドラ表示牌 fubaopai: [], // 裏ドラ表示牌 jicun: { changbang: 0, // 積み棒の数 lizhibang: 0 // 供託立直棒の数 } };
返り値の形式は以下の通り。
{ hupai: [ // 役の名称と翻数のリスト { name: '一気通貫', fanshu: 1 }, { name: 'ドラ', fanshu: 1 } ], fu: 30, // 符 fanshu: 2, // (全体の)翻数 damanguan: 0, // (役満の場合)複合しているか defen: 2000, // (供託を含めない)和了点 fenpei: [ 0, 2000, 0, -2000 ] // (供託を含めた)点数の移動 }
和了できない場合は hupai
が null になる*4。fenpei
はその局の東家からの順。立直棒の供託を含めると収支が ±0 にならないことに注意。
次回は状況役、懸賞役一覧作成についての予定。