麻雀の和了点を計算するプログラム

延ばし延ばしにしていた和了点の計算について。

麻雀の和了点を求める手順は以下の流れになる。

  1. 状況役*1の一覧を作る
  2. 懸賞役*2の一覧を作る
  3. 和了形の一覧を求める
  4. 個々の和了形について以下を行う
    1. 面子構成を調べ、符を計算する
    2. 手役の一覧を求める
    3. 符、状況役、手役、懸賞役から和了点を計算する
  5. 得られた和了点の最大値を解とする

和了形を求めるプログラム - 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 になる*4fenpei はその局の東家からの順。立直棒の供託を含めると収支が ±0 にならないことに注意。

次回は状況役、懸賞役一覧作成についての予定。

*1:立直や海底摸月など手牌からは判断できない役

*2:ドラなど和了してはじめてつく役

*3:高点法というらしい

*4:和了可否判定にも使えるということ