デュプリケート麻雀の実装

電脳麻将 の思考アルゴリズムを改善したときはプログラム同士を自動対戦させて効果を検証している。現在のアルゴリズムの場合、1000戦の試行に5時間くらいかかる*1のだが、麻雀には運の要素があるため同一のプログラム同士を対戦させても1000戦では平均順位に 2.45~2.55 ほどの幅が出てしまう。効果の高い改善であれば平均順位が 2.40 程度になりこの範囲を超えるのだが、このところ試している押し引きの改善では平均順位がこの幅の中に入ってしまい、効果があるのかないのか判然としない。

ならば1000戦分の牌山をあらかじめ作成しておき、同一の状況で対戦させればよいのではないか。リアル麻雀にはこのような試みがあり、「デュプリケート麻雀」と呼ぶらしい。

リアル麻雀でこれをやるのは相当大変そうだが、コンピューター麻雀なら簡単なはず。ということで実装してみた。

一番簡単なのは牌山だけを固定する方法だが、鳴きが1つ入るとツモ順が変わり、以降は全く違った展開になってしまう。また連荘があると準備済みの牌山がずれ、本来親番でもらうはずだった配牌を子でもらうようなことになる。すると自風も違うので以降がやはり違う展開となってしまう。結果として牌山を固定した意味があるのは最初の鳴きまでという努力に見合わないことになる。

なので、

  1. 牌山だけでなくツモも固定する。 鳴きがあってもツモは変化しない。カンした場合は次にツモるはずだった牌をリンシャン牌としてツモる。
  2. 局ごとに牌山を固定する。 東一局で連荘があってもなくても東二局の配牌に変化はない。

という工夫を入れてみた。*2

画面なしのプログラム同士の自動対戦は Majiang.Dev.Game で実装しており、局の開始時に牌山をパラメータで渡すことができるようになっている。牌山を表現するクラス Majiiang.Shan と同一のインタフェースでデュプリケート麻雀の牌山を実現するクラス Majiang.Dev.Shan を実装し、そのインスタンスを渡すことでデュプリケート対局を実現した。

試してみたが、アルゴリズムを修正した部分のみが結果に影響をあたえるので効果の検証が容易になった。今後はこれでアルゴリズム改善の効果検証を行うことにする。

追記

上の牌譜はデュプリケート麻雀の実例。東一局北家のツモは s2z6p3m5 の順。2つ目の牌譜では北家がポン・チーするがツモ牌は変わらない。また途中の連荘数は異なるが南三局の配牌は2戦とも同一となっている。

*1:最初期のアルゴリズムなら10分程度で1000戦できたのだが……

*2:リアルのデュプリケート麻雀でも考慮されている模様。ツモはあらかじめ各競技者専用に積まれるようだし、連荘はないルールになっているみたい