Mjaiボットを対戦させるサーバー mjai-test-server を作成し、これを使って既存のMjaiボットを対戦させ、その強さを評価しました。
麻雀は運の要素が大きい競技です。 完全に同じプログラム同士を戦わせても、1000戦の対局では平均順位で2.45〜2.55程度のバラつきは出てしまいます。 そこで 電脳麻将 ではAIの評価に デュプリケート対局 と呼ばれる対局方法を導入しています。 デュプリケート対局とは「牌山を固定」した同じ条件で対局を行うことで「相対評価」で強弱を決定するという方法です。 まずベースとなる同じ4人のプレーヤーで一定数(1000戦程度)の対局を行います。 次にその中の1名を評価対象のプレーヤーと交代し、同じ条件で対局を行います。 これを評価対象者数分繰り返すことで、それぞれのプレーヤーを相対的に評価できるという訳です。
mjai-test-serverを使えば、以下でこれを実現できます。
$ mjai-test-server -i shan.json.gz -o manue.json mjai-diannao mjai-manue
牌山 shan.json.gz を使って mjai-diannao 3体と mjai-manue 1体でデュプリケート対局を行い、その結果の牌譜をmanue.json に保存します。
今回評価したボットは以下の6体です。
| ボット | 言語 | GitHub | アルゴリズム |
|---|---|---|---|
| mjai-diannao | JavaScript | kobalab/mjai-bot | ルールベース |
| mjai-shanten | Ruby | gimite/mjai | ルールベース |
| mjai-manue | Ruby | gimite/mjai-manue | 期待値ベース |
| mjai-akochan | C++ | critter-mj/akochan | 期待値ベース |
| mjai-akagi | Rust + Python | shinkuan/Akagi-MjaiBot-Mortal | 機械学習(mortal_298k) |
| mjai-mortal | Rust + Python | Equim-chan/Mortal | 機械学習(mortal-582500) |
今回評価するMjaiボットのインストール方法を簡単に説明します*1。
電脳麻将のMjaiボットです。 nodeとnpmをインストール*2した上で、以下でインストールします。
$ npm i -g @kobalab/mjai-bot
本家Mjaiに同梱されているMjaiボットです。 rubyとgemをインストール*3した上で、以下でインストールします。
$ gem install mjai
Mjaiの作者によるMjaiボットです。 gem でインストールします。
$ gem install mjai-manue
天鳳七段相当とされるAIです。 ボットはC++でビルドする必要があります*4。
GitHubからcloneします。
$ git clone https://github.com/critter-mj/akochan.git
$ cd akochan/
ビルドに boost が必要なのでインストールします*5。
$ sudo dnf install boost-system boost-devel
ボットのログ出力にバグらしきもの*6があるので修正 し、ビルドします。
$ cd ai_src
$ make -f Makefile_Linux
$ cd ..
$ make -f Makefile_Linux
ボットは LD_LIBRARY_PATH=. ./system.exe mjai_client で起動しますが、mjai-akochan として起動したいので、以下のshellでラップしています*7。
#!/usr/bin/bash
[[ "$1" =~ ^mjsonp://[^:]+:([0-9]+)/[^/]+$ ]] && port="${BASH_REMATCH[1]}"
cd $HOME/Git/akochan/
LD_LIBRARY_PATH=. exec ./system.exe mjai_client $port
Mortalとは何か?については 電脳麻将でMortalと対戦する を参照してください。 Mortalのセットアップはやや複雑ですので、まずはビルド済みのライブラリを配布している Akagi-MjaiBot-Mortal を使うのが簡単です。 uv(Pythonパッケージ・プロジェクト管理ツール)をインストール*8した上で以下を行います。
GitHubからcloneします。
$ git clone https://github.com/shinkuan/Akagi-MjaiBot-Mortal.git
$ cd Akagi-MjaiBot-Mortal/
uv sync で環境構築します。
$ uv sync
Mortal系のボットを動作させるには、その頭脳にあたる「モデル」が必要です。 同梱されている mortal.pth はあくまで評価用であまり強くありません。 今回は mortal_298k を使うことにします。 mortal_298k.pth をダウンロードして、カレントディレクトリの mortal.pth を上書きします*9。
ボットは uv run python bot.py で起動しますが標準入出力でしか通信できないので mortal-wrapper の助けを借りて mjai-test-server と接続します。 これを mjai-akagi として起動したいので、以下のshellでラップしています*10。
#!/usr/bin/bash
[ $1 ] && url=$1 || url=mjsonp://127.0.0.1:11600/default
exec mortal-wrapper -v --akagi $url $HOME/Git/Akagi-MjaiBot-Mortal
最後に本家Mortalをセットアップします。 ビルドにはRustが必要ですので rustup が使えるようにしておいてください*11。
GitHubからcloneします。
$ git clone https://github.com/Equim-chan/Mortal.git
$ cd Mortal/
libriichi をビルドします。
$ source ~/.cargo/env
$ cargo build -p libriichi --lib --release
$ cp target/release/libriichi.so mortal/
uv で環境構築し、必要なパッケージをインストールします。
$ uv venv
$ uv pip install tqdm toml tensorboard
$ uv pip install torch
MortalのGitHubリポジトリは巨大な開発環境ですが、ボット起動環境は mortal/ ディレクトリにあります。 今回モデルは mortal-582500 を使います。 mortal_582500.pth をダウンロードして、mortal/ ディレクトリに配置します。 どのモデルを使用するかは config.toml で以下のように指定します。
[control]
state_file = 'mortal_582500.pth'
uv で起動しますが、これも mjai-mortal として起動したいので以下のshellでラップします*12。
#!/usr/bin/bash
[ $1 ] && url=$1 || url=mjsonp://127.0.0.1:11600/default
exec mortal-wrapper -v $url $HOME/Git/Mortal
まず mjai-diannao 4体でデュプリケート対局1000戦を行い、この成績を基準値とします。 その後、1席を評価対象のボットと置き換えて同じく1000戦ずつ対局を進めます。
8日間にわたって対局を行い、以下の結果を得ました。