tomohxxの日記

麻雀プログラミング

麻雀AI開発(1)

はじめに

今回から何回かに渡って自作麻雀AIについて書きます。最初に開発に至るまでの経緯を述べます。これまでにシャンテン数計算アルゴリズムと有効牌・不要牌計算アルゴリズムを開発してきました。そして最近、悲願であった一人麻雀における和了確率を計算するアルゴリズムを開発しました。
qiita.com
これらのアルゴリズムによって一人麻雀で最適な戦略を求めることが可能になりました。一人麻雀を攻略したのだから四人麻雀でそこそこ良いAIを開発するのは容易なのでは、と思ったので麻雀AIの開発に着手しました。

麻雀AIの構成

私の開発した麻雀AIは打牌選択(押し/降り)、鳴き判断、リーチ判断、押し引き判断によって構成されます。以下、具体的なアルゴリズムをまとめます。

打牌選択(押し)

一人麻雀を仮定し、以下の評価関数の期待値を最大にする牌を選択する*1


\displaystyle
V(l) = 2 + (翻数) + (鳴いてもあがれる場合1, そうでないならば0)
\tag {1}

打牌選択(降り)

天鳳牌譜を使ったマルチラベルロジスティック回帰により、テンパイしているプレイヤに対して各牌の放銃率を推定し最も安全な牌を選択する。特徴量は各牌が河に存在するかを0か1で表す長さ34のベクトル。テンパイしてるプレイヤが複数存在する場合、いずれかのプレイヤに対して放銃する確率を推定する。

鳴き判断

一人麻雀を仮定し、役が確定しかつ和了確率が増加する場合は鳴く、そうでないならば鳴かない。

リーチ判断

天鳳牌譜を使ったランダムフォレストによりリーチをかけるかどうかを判断する。特徴量は、待ち牌の残り枚数、残りツモ回数、リーチをかけない場合の得点の最大値、リーチをかける場合の得点の最大値、何局目か、持ち点、親かどうかの7個。

押し引き判断

リーチ・ドラポンがなければ押し。リーチかドラポンがある場合、(翻数の期待値)>=1.8 かつ (シャンテン数)<=2 かつ (打牌選択(押し)で選択された牌の放銃率)<=0.12 ならば押し、そうでないならば降り。

麻雀AIの評価

麻雀AIをmjaiという環境で評価しました。
github.com
対戦相手はmjai-manue 3体です。
github.com
作者いわく「あまり強くない」そうですが、人間が相手をするというならばともかくプログラムで相手をするのはけっこう大変です。人間の判断基準をプログラムに落とし込まなければならないからです。以下のリンクに東風戦の牌譜を掲載しています。プレイヤ名はTestです。

成績をまとめました。

試合形式 東風
試合数 60
局数 347
和了 0.2046
ツモ率 0.3380
放銃率 0.0634
副露率 0.2133
流局率 0.2622
流局時テンパイ率 0.2418
リーチ率 0.1758
平均順位 2.467
平均打点 6883
1位率 0.1500
2位率 0.4333
3位率 0.2167
4位率 0.2000

考察と感想

和了率、放銃率が低いのが気になります。もう少し押してもよいのかなという印象を受けます。まあ、このような結果になったのはリーチ一発への放銃を避けるためリスクをとらないような設定にしたからなのですが。牌譜を見る限りではそこまで不自然な打ち方はしていないようです(安パイを残すような打ち方はまだできないです)。

あと、降りについてですが適当に作ったモデルのわりにはうまく機能している印象を受けました。まだまだ改善の余地があるのでより高精度なモデルを作ることができそうです。

正直なところ、平均順位はもう少し良くなることを期待していました。というのはリーチ判断を天鳳の牌譜から学習したためです。しかし、mjai-manueはリーチに対してほぼ降りを選択するので人間相手のリーチ戦術ではmjai-manue相手にうまくいかないといえます。よって、mjai-manue相手の最適な戦略を対戦結果を通じて設計するような仕組みが必要です。なお手動で戦略をプログラミングすることもできますが、その場合その戦略が最適であることの証明が困難になるという問題が生じます。ゲームの最適な戦略を設計することは一般的に強化学習によって行われます。麻雀の場合、打牌、リーチ、鳴きといった行動が得点あるいは順位等に直接的に結びつかないので強化学習における報酬を定義することが困難になります。報酬をどのように定義してどのように改善するかの方針を決定することが肝であるといえます。

おわりに

麻雀AIの開発についての記事を書きました。数日間、押し引きのチューニングをやっていたのですが、思うような動作ができずに心が折れそうになりました。このまま続けてもコードが汚くなったり開発が泥沼化しそうだと思ったので、中途半端な結果ではありますがここで報告することにしました。今後は強化学習についての理解を深めるべく調査・勉強に励もうと思います。たぶん、それなりに良い結果が出るので、その際はまたブログの記事で報告する予定です。

*1:この評価関数は、速度と打点、鳴ける可能性をいい感じで重みづけして評価値を決定します。評価関数については[麻雀]一人麻雀攻略! 和了確率の計算アルゴリズム - Qiitaの(13式)を参照してください。