あの伝説の国士無双13面待ち
これが出る確率を求めてみました。

解説動画はこちら


国士無双13面待ちが出る確率は?


今回は麻雀ネタです。

麻雀における最高峰の役「役満」の一つに
「国士無双」という役満があります

13種類の么九牌(一九字牌)を
各1枚以上集める特殊な形の役満です。


13面待ち
萬子・索子・筒子の1・9、東・南・西・北・白・發・中の
計13種類をすべて揃えた状態でアガリ待ちの状態のことです。

13



この13面待ちがどれくらいの確率でやってくるのか
プログラムで求めていきたいと思います。



1.接待麻雀モード

自分一人がずっと国士無双13面待ちを狙い
他はただパイを捨て続けるとした場合の確率です。



簡易に求めるコード
import random

# ヤオ九牌(1, 9, 字牌)のインデックス定義
YAOCHU_INDICES = [0, 8, 9, 17, 18, 26, 27, 28, 29, 30, 31, 32, 33]

def is_kokushi_13men_machi(tehai):
    """
    国士無双13面待ちの判定
    13種類のヤオ九牌がすべて1枚ずつ揃っているか
    """
    for idx in YAOCHU_INDICES:
        if tehai[idx] < 1:
            return False
    return True

def simulate_one_game_kokushi():
    # 山の作成(136枚)
    yama = []
    for i in range(34):
        yama.extend([i] * 4)
    random.shuffle(yama)

    # 全員の手牌(4人分)
    players_tehai = [[0] * 34 for _ in range(4)]
    
    # 配牌(各13枚)
    for p in range(4):
        for _ in range(13):
            pai = yama.pop()
            players_tehai[p][pai] += 1

    turn = 0
    while len(yama) > 14:
        turn += 1
        for p in range(4):
            # --- 1. ツモ ---
            tsumo_pai = yama.pop()
            players_tehai[p][tsumo_pai] += 1

            # --- 2. 判定(プレイヤー0のみ国士無双を判定) ---
            if p == 0 and is_kokushi_13men_machi(players_tehai[p]):
                return True, turn, p

            # --- 3. 捨て牌選択 ---
            if p == 0:
                # プレイヤー0: 国士無双を狙う戦略
                discard_candidates = []
                
                # 優先順位1: 中張牌を捨てる
                for i in range(34):
                    if i not in YAOCHU_INDICES and players_tehai[p][i] > 0:
                        discard_candidates.extend([i] * players_tehai[p][i])
                
                # 優先順位2: 被っているヤオ九牌を捨てる
                if not discard_candidates:
                    for i in YAOCHU_INDICES:
                        if players_tehai[p][i] >= 2:
                            discard_candidates.append(i)

                # 優先順位3: どれでも(13面待ち完成中など)
                if not discard_candidates:
                    discard_candidates = [i for i, count in enumerate(players_tehai[p]) if count > 0]
                
                discard_pai = random.choice(discard_candidates)
            else:
                # 他のプレイヤー: ツモ切り(今引いた牌をそのまま捨てる)
                discard_pai = tsumo_pai

            players_tehai[p][discard_pai] -= 1
            
            # 山がなくなったら終了(流局)
            if len(yama) <= 14:
                break
                
    return False, turn, None

def run_kokushi_experiment(episodes_per_step=10000):
    print(f"国士無双13面待ちシミュレーション ({episodes_per_step}局)\n")
    print("成立回数 | 成立確率 | 平均巡目")
    print("-----------------------------------------")

    success_count = 0
    total_turns = 0
        
    for _ in range(episodes_per_step):
        is_clear, turns, winner = simulate_one_game_kokushi()
        if is_clear:
            success_count += 1
            total_turns += turns
    
    prob = (success_count / episodes_per_step) * 100
    avg_turn = total_turns / success_count if success_count > 0 else 0
    print(f"{success_count:4}回  | {prob:6.2f}% | {avg_turn:5.2f}巡")

run_kokushi_experiment(100000)
国士無双13面待ちシミュレーション (100000局)

成立回数 | 成立確率 | 平均巡目
-----------------------------------------
 120回  |   0.12% | 16.44巡



接待麻雀モードになっていますが
10万局中120回
確率0.12%でした。



2.他家が確率でアガるモード

先ほどのプレイヤーがずっと国士無双を狙う状態で
他家が10巡目以降、確率でアガられてしまう状態の
確率を求めています。


3.13面待ちからアガる確率

他家が確率でアガるモードに加えて
13面待ちから、上がれたかどうかの
確率も求めました。

こちらはぜひ動画で確率をご覧ください。



まとめ

国士無双13面待ちは、それなりにアガるプレイヤーがいても
10000局に1回位は見れると推測されるので
年間300試合、試合平均11局だと、3-4年に1回は
13面待ちの実況が見れるかもしれません。

13面待ちでアガリの確率はさらに低いので(一生に一度出せるかどうか)
もう10年は見れないかもしれないですね。


今回は麻雀ネタでしたが
次回も多分麻雀ネタです。
それでは。