牌の危険度計算アルゴリズム(4)

電脳麻将 の現在の押し引きアルゴリズムは親に対する考慮がない。牌の危険度計算アルゴリズム(1) - koba::blog までの 絶対危険度 は危険度を現物、字牌、スジ、無スジのように離散的に扱っており、危険度の値は序列を表しているに過ぎなかったのだが、牌の危険度計算アルゴリズム(2) - koba::blog牌の危険度計算アルゴリズム(3) - koba::blog相対危険度 を導入し、危険度が連続値になったことにより「親の危険度は1.5倍」のような比較が可能になった。今回は親のリーチに対する危険度を変動させながら実際にAI同士を対戦させ、適切な値があるのか検証する。

親リーチの危険度

親リーチを子のリーチより危険とする根拠は親の打点が1.5倍という麻雀のルールによるものなので、親のリーチに対する危険度を 1.30~1.50 倍(これを 係数A とする)で変動させ、実際の押し引きに効果があるか検証した。

結果 係数A: 1.30 係数A: 1.35 係数A: 1.40 係数A: 1.45 係数A: 1.50
割合 局収支 割合 局収支 割合 局収支 割合 局収支 割合 局収支
和了 10.3% +6833 10.3% +6841 10.3% +6841 10.3% +6851 10.2% +6845
放銃 10.3% -6391 10.2% -6351 10.1% -6385 10.1% -6382 10.0% -6372
被ツモ 31.7% -2748 31.7% -2746 31.8% -2744 31.7% -2742 31.8% -2741
横移動 29.0% -67 29.0% -67 29.0% -68 29.0% -68 28.9% -67
流局 18.7% -806 18.8% -814 18.8% -820 18.9% -824 19.1% -830
平均 -997 -987 -987 -986 -989

1.35〜1.50 で大きな差はなかったが局収支が最もよかった 1.45 を採用することとした。

二軒リーチの危険度

危険度を計算する対象が2名以上の場合、牌ごとに最大値を取るようにしていたのだが、ダブロンありのルールでは総和の方が正しいかもしれないと思い、総和をとるように変更してみた。

結果 割合 局収支
和了 9.9% +6847
放銃 9.6% -6385
被ツモ 31.9% -2744
横移動 29.4% -66
流局 19.2% -842
平均 -997

局収支が悪化。このアイデアは失敗のようなので不採用とした。

プログラム修正

クラス Majiang.SuanPai の牌の相対危険度を求めるメソッド suan_weixian_all() を以下に修正する。

suan_weixian_all(bingpai) {

    let weixian_all;                            // 相対危険度を格納するハッシュ
    for (let l = 0; l < 4; l++) {
        /* …… */

        /* 全ての牌の絶対危険度(weixian)とその総和(sum)を求める */
        /* …… */

        /* 全ての牌の相対危険度を計算する */
        for (let p of Object.keys(weixian)) {
            weixian[p] = weixian[p] / sum * 100 * (l == 0 ? 1.45 : 1);
                                    // 相対危険度を求める
                                    // リーチ者が親の場合は危険度を 1.45 倍する
            /* …… */
            weixian_all[p] = Math.max(weixian_all[p], weixian[p]);
                                    // リーチ者が2人以上の場合は最大値を選択する
        }
    }
    if (weixian_all) return (p)=>weixian_all[p.substr(0,2).replace(/0/,'5')];
                                    // 相対危険度を返す関数を返す
}

評価

今までの改善結果は以下の通り。*1

結果 改善前 改善(1)改善(2)改善(3)改善(4)
割合 局収支 割合 局収支 割合 局収支 割合 局収支 割合 局収支
和了 10.4% +6848 10.7% +6861 10.7% +6854 10.4% +6799 10.3% +6851
放銃 11.3% -6554 11.2% -6612 11.2% -6609 10.4% -6415 10.1% -6382
被ツモ 31.5% -2735 31.4% -2749 31.4% -2750 31.7% -2747 31.7% -2742
横移動 28.5% -69 28.6% -69 28.6% -70 29.0% -69 29.0% -68
流局 18.3% -762 18.0% -750 18.1% -749 18.5% -781 18.9% -824
平均 -1047 -1027 -1024 -993 -986

改善前 改善(2)改善(3)改善(4) 改善前 改善(2)改善(3)改善(4)
対戦数 1,000 1,000 1,000 1,000 総局数 10,480 10,488 10,505 10,502
1位率 .237 .237 .233 .232 和了率 .213 .215 .213 .213
2位率 .244 .250 .256 .264 放銃率 .133 .132 .128 .127
3位率 .248 .244 .247 .244 立直率 .231 .233 .233 .233
4位率 .271 .269 .264 .260 副露率 .342 .342 .342 .342
平均順位 2.55 2.55 2.54 2.53 平均打点 5,622 5,625 5,607 5,642

改善前と比べ、対リーチ和了率は 10.4% → 10.3% と若干下がったが、対リーチ放銃率は 11.3% → 10.1% と大幅に改善した。これにより対リーチ局収支も -1047 → -986 と向上した。

順位に関してはトップ率が下がったものの2位率が大幅に上昇しラス率が下がったことで、平均順位 2.55 → 2.53 と若干上昇した。和了率などの統計では、放銃率のみが 13.3% → 12.7% と大きく改善された。

このアルゴリズムを次回リリースの ver.1.6.0 に採用する。

*1:改善(1)と(2)で順位成績はほぼ同じなので、改善(1)は割愛した