MJSim AIインターフェース仕様 バージョン1
■目次
- 概要
- AI作成手順
- 麻雀のルール
- インターフェース関数
- 呼び出しタイミング
- 補足仕様
- Q&A
- 注意事項
■概要
MJSim用のAIを作るための仕様を公開する。
■AI作成手順
AIはDLLとして作成する。
①Windowsアプリケーション開発ソフトで、DLLのプロジェクトを作る。
②MJSim.hをインクルードする。
#include "../MJSim/MJSim.h"
③AIInterfaceVersionとAIAction関数を実装する。
C言語から呼び出せる形式で作成してください。
(コンパイラのマニュアル等で確認してください)
東風戦で、食いタン無し、後付け有り。
詳細は東風荘ホームページで確認してください。
AIインターフェースv1では、ルールが変化することはない。
■インターフェース関数
[戻り値]
現在は1を返してください。
- void AIAction(int Msg, int Index, MJTAKU *Taku)
[引数]
Msg 呼び出された理由。MJMSG_???(ヘッダファイル参照)が渡される。
Index 自分がどこに座っているか。0:起家~。
これは、MJTAKU構造体の、どのPlayer構造体が自分の手なのかを知るのに必要。
席順なので、試合中は変化しない。試合毎に変化する。
Taku MJTAKU構造体へのポインタ。
卓上の情報が入っている。
■呼び出しタイミング
以下のタイミングで、AIAction関数が呼び出される。
①東風戦開始 MJMSG_GAMESTART
②局開始 MJMSG_KYOKUSTART
③自分が牌をツモったとき(リンシャン含む) MJMSG_TSUMO
④誰かが、ツモったり鳴いた後に牌を捨てたとき、またはカンしたとき MJMSG_REACTION
局中は③~④が繰り返し送られてくる。
鳴きが入らない時は一順でツモ1回、リアクション4回が送られる。
⑤局終了 MJMSG_KYOKUEND,
試合中は②~⑤を繰り返す。
⑥東風戦終了 MJMSG_GAMEEND,
MJSim動作中は①~⑥を繰り返す。
■補足仕様
DLLのファイル名は15文字までにしてください。
■Q&A
Q:AIから牌を捨てる、上がる、鳴くなどの指示は、どうやるのか。
A:Taku->Player[Index].Action構造体で指定する。
Q:指示のコード例は?
A:以下のようにする。
●メッセージがツモ(MJMSG_TSUMO)のとき
・ツモ切りする
Taku->Player[Index].Action.Type = MJACTION_SUTEHAI;
Taku->Player[Index].Action.Sutehai = 0;
・1マンを捨てる
Taku->Player[Index].Action.Type = MJACTION_SUTEHAI;
Taku->Player[Index].Action.Sutehai = 1;
・ツモ上がりする
Taku->Player[Index].Action.Type = MJACTION_TSUMOAGARI;
・1マンを捨ててリーチ
Taku->Player[Index].Action.Type = MJACTION_RICHI;
Taku->Player[Index].Action.Sutehai = 1;
・2マンを暗カンする
Taku->Player[Index].Action.Type = MJACTION_ANKAN;
Taku->Player[Index].Action.Hosoku = 2; ←Hosokuにセットする
・2マンを加カンする
Taku->Player[Index].Action.Type = MJACTION_KAKAN;
Taku->Player[Index].Action.Hosoku = 2; ←Hosokuにセットする
●メッセージがリアクション(MJMSG_REACTION)のとき
・何もしない
Taku->Player[Index].Action.Type = MJACTION_NULL;
・最後に捨てられた牌をロンする
Taku->Player[Index].Action.Type = MJACTION_RON;
・最後に捨てられた牌を、3から始まるメンツ(3,4,5)でチーして、1マンを捨てる
Taku->Player[Index].Action.Type = MJACTION_KAKAN;
Taku->Player[Index].Action.Sutehai = 1;
Taku->Player[Index].Action.Hosoku = 3;
・最後に捨てられた牌をポンして1マンを捨てる
Taku->Player[Index].Action.Type = MJACTION_PON;
Taku->Player[Index].Action.Sutehai = 1;
Q:Taku->Player[Index].Action以外の部分を書き換えてもかまわないか。
A:OK。関数からの戻り時に元のとおりである必要は無い。
当然書き換えた内容が反映されることは無い。
Q:MJSim.exeの関数を呼び出すことはできない?
A:できない。MJTAKU構造体の情報を使ってアクションを決めてください。
Q:自風を取得したい。
A:自風を表す変数は無いので、席と局数から計算してください。
・サンプル
int GetZikaze(int Index/*席*/, int Kyoku/*局数*/){return (Index + 4 - (Kyoku % 4)) % 4;}
Q:リアクション時に、他家の最後のアクションを取得したい。
A:Taku->Player[Taku->Trun].Action.Typeから取得する。
「Taku->Trun」のインデクスのプレイヤーが最後に何らかのアクションをしたプレイヤー。
Q:リアクション時に、他家の最後の捨て牌を取得したい。
A:ツモ切りで無い場合は、Taku->Player[Taku->Trun].Action.Sutehai。
0がはいっている時はツモ切りで、この場合は河から取得する。
河は、牌を捨てていないところが0になっているので、0の直前の牌が最後の牌。
・サンプル
int LastSutehai = GetLastSutehai(Taku->Turn);
//河の最後の捨て牌を取得
//河に1つも牌が無い場合は0を返す
int GetLastSutehai(int Index)
{
int len = GetKawaLen(Index);
if(len == 0){return 0;}
return abs(Taku->Player[Index].Kawa[len - 1]);
}
//河の牌の数を取得
int GetKawaLen(int Index)
{
int i;
for(i = 0; Taku->Player[Index].Kawa[i] != 0; i++);
return i;
}
Q:チャンカンのやり方は?
A:誰かがカンしたとき、リアクションメッセージが来る。このとき、
①Taku->Player[Taku->Trun].Action.Typeから最後のアクションを取得して、
MJACTION_KAKAN(加カン)だったら、
②Taku->Player[Taku->Trun].Action.Hosokuにカンした牌が入っているので、
それが上がり牌ならロンできる。
Q:AIが間違ったアクションを指定したときどうなるのか。
A:指示は訂正される。場合によってはチョンボになったり、不利になる。
・誤ツモ上がり、誤ロン →チョンボになる
・持っていない牌を捨てる →ツモ切りに訂正
・誤暗カン →ツモ切りに訂正
・リーチ後にツモ切り、ロン、暗カン以外 →ツモ切りに訂正
・誤ポン、誤チー、誤明カン →何もしないに訂正
・暗カン、明カン時のリアクション →何もしないに訂正
・加カンのときのロン以外 →何もしないに訂正
・ポン、チー時の捨て牌でツモ切りを指定 →一番左の牌が切られる
■注意事項
- MJSim.iniの[AI]セクションに同じDLLを登録しないでください。
以下のような不具合が出る。
・たとえばAI0、AI1に同じDLLを指定すると、2人分のメッセージがきてしまう。
1順の間にツモ2回、リアクション8回。
・グローバル変数を共有してしまう。
・集計ツールで読み込んだとき、結果がおかしくなる(同じ名前になるため)。
[対処方法]
DLLをコピーして名前を変える。
元の名前がMEGUMI.dllなら、MEGUMI_1.dllなど。
- DLLとiniファイルは、作業フォルダ(カレントディレクトリ)にないといけない。
デバッガを使うときなど、 設定で作業フォルダがプロジェクトのあるフォルダになっていると、
そこにDLLは無いため(DLLはdebug等にある)、読み込めずにエラーとなるので注意。
今後新しいインターフェースが定義されたときに、以前のインターフェースのAIも
(ソースの修正や再コンパイル無しで)同時に使用できるようにするためのもの。
例えば、渡される構造体(MJTAKU)に新しい変数が追加されたなどの場合、
バージョン2が定義される。バージョン1と2のAIで対戦可能にする。
ただし、プログラム上矛盾が出てしまうとか、
どちらかが不利になってしまう場合などは対戦できなくする。
最終更新:2010年07月19日 05:18