麻雀の手牌のJavascript表現

麻雀に関するプログラムを作ろうと思ったら、まずやるべきことは手牌の表現になるだろう。電脳麻将では以下の形式で表現している。

{
    _bingpai: {
        m: [0,0,0,0,0,0,0,0,0,0],
        p: [0,0,0,0,0,0,0,0,0,0],
        s: [0,0,0,0,0,0,0,0,0,0],
        z: [0,0,0,0,0,0,0,0],
    },
    _fulou: [],
    _zimo:  null
}

_bingpai は副露牌以外の打牌可能な手牌*1の数を表しており、添字0は赤牌を表す。

_fulou は副露した面子を表す。横三筒二筒四筒の場合は 'p23-4'五萬横赤五萬五萬 の場合は 'm550='となる。'-' が上家からの鳴き、'+' が下家からの鳴き、'=' が対面からの鳴きを表していると言うわけ。暗槓は 'p9999'、加槓は 's222+2' のような形式とする。

_zimo にはツモしてきた牌、あるいは直前の副露面子を設定し、打牌後は null に戻す。つまり _zimo が null 以外の場合は打牌可能な状態であることを示している。

この表現方法だと
赤五萬五萬五萬中中發横發發裏白白裏横八萬七萬九萬

{
    _bingpai: {
        m: [1,0,0,0,0,3,0,0,0,0],
        p: [0,0,0,0,0,0,0,0,0,0],
        s: [0,0,0,0,0,0,0,0,0,0],
        z: [0,0,0,0,0,0,0,2],
    },
    _fulou: [ 'm78-9', 'z5555', 'z666=' ],
    _zimo:  'z7'
}

と表せる*2

これに自摸(zimo())、打牌(dapai())、副露(fulou())、暗槓、加槓(gang())の操作をするメソッドを追加したのがクラスMajiang.Shoupai

ソースコードはこちら。

*1:中国語では兵牌(bingpai)というらしい

*2:副露の順番に注意