麻雀AI対戦サーバhttps://gimite.net:443/pukiwiki/index.php?Mjai%20%E9%BA%BB%E9%9B%80AI%E5%AF%BE%E6%88%A6%E3%82%B5%E3%83%BC%E3%83%90麻雀AI同士を対戦させることができるサーバです。†Rubyをインストール。RubyGems?をインストール。3人を相手に1局戦ができます。テストにご自由にお使いください。途中で切っても大丈夫です。サーバが落ちていたらGimiteに教えて下さい。†クライアント(プレーヤ)4人がTCPでサーバに接続します。その後、サーバ、クライアントが交互にJSONを1行ずつ送り合います。1ゲーム終わるとTCPの接続を切断します。†サンプルとしてこのゲーム(牌譜ビューア)での各プレーヤの通信内容がそれぞれ0、1、2、3となっています。"<-"がサーバからのメッセージ、"->"がクライアントからのメッセージです。ここでのid属性が、このゲーム中での自分のIDになります。3のものが順に入ります。親から順ではないので注意。->{"type":"none"}<-{"type":"tsumo","actor":0,"pai":"?"}->{"type":"none"}<-{"type":"dahai","actor":0,"pai":"6s","tsumogiri":false}->{"type":"none"}<-{"type":"tsumo","actor":1,"pai":"3m"}->{"type":"dahai","actor":1,"pai":"7s","tsumogiri":false}<-{"type":"dahai","actor":1,"pai":"7s","tsumogiri":false}->{"type":"none"}<-{"type":"tsumo","actor":2,"pai":"?"}->{"type":"none"}<-{"type":"dahai","actor":2,"pai":"S","tsumogiri":false}->{"type":"none"}<-{"type":"tsumo","actor":3,"pai":"?"}->{"type":"none"}<-{"type":"dahai","actor":3,"pai":"F","tsumogiri":false}->{"type":"none"}ポン:<-{"type":"dahai","actor":1,"pai":"5sr","tsumogiri":false}->{"type":"pon","actor":0,"target":1,"pai":"5sr","consumed":["5s","5s"]}<-{"type":"pon","actor":0,"target":1,"pai":"5sr","consumed":["5s","5s"]}->{"type":"dahai","actor":0,"pai":"9p","tsumogiri":false}<-{"type":"dahai","actor":0,"pai":"9p","tsumogiri":false}->{"type":"none"}チー:<-{"type":"dahai","actor":3,"pai":"4p","tsumogiri":true}->{"type":"chi","actor":0,"target":3,"pai":"4p","consumed":["5p","6p"]}<-{"type":"chi","actor":0,"target":3,"pai":"4p","consumed":["5p","6p"]}->{"type":"dahai","actor":0,"pai":"9m","tsumogiri":false}<-{"type":"dahai","actor":0,"pai":"9m","tsumogiri":false}->{"type":"none"}加槓:<-{"type":"tsumo","actor":0,"pai":"6m"}->{"type":"kakan","actor":0,"pai":"6m","consumed":["6m","6m","6m"]}<-{"type":"kakan","actor":0,"pai":"6m","consumed":["6m","6m","6m"]}->{"type":"none"}<-{"type":"tsumo","actor":0,"pai":"1p"}->{"type":"dahai","actor":0,"pai":"2p","tsumogiri":false}<-{"type":"dora","dora_marker":"3s"}->{"type":"none"}<-{"type":"dahai","actor":0,"pai":"2p","tsumogiri":false}->{"type":"none"}大明槓:<-{"type":"dahai","actor":1,"pai":"5m","tsumogiri":false}->{"type":"daiminkan","actor":3,"target":1,"pai":"5m","consumed":["5m","5m","5mr"]}<-{"type":"daiminkan","actor":3,"target":1,"pai":"5m","consumed":["5m","5m","5mr"]}->{"type":"none"}<-{"type":"tsumo","actor":3,"pai":"S"}->{"type":"dahai","actor":3,"pai":"S","tsumogiri":true}<-{"type":"dora","dora_marker":"8p"}->{"type":"none"}<-{"type":"dahai","actor":3,"pai":"S","tsumogiri":true}->{"type":"none"}暗槓:<-{"type":"tsumo","actor":1,"pai":"N"}->{"type":"ankan","actor":1,"consumed":["N","N","N","N"]}<-{"type":"ankan","actor":1,"consumed":["N","N","N","N"]}->{"type":"none"}<-{"type":"dora","dora_marker":"4s"}->{"type":"none"}<-{"type":"tsumo","actor":1,"pai":"3p"}->{"type":"dahai","actor":1,"pai":"6s","tsumogiri":false}<-{"type":"dahai","actor":1,"pai":"6s","tsumogiri":false}->{"type":"none"}リーチ:<-{"type":"tsumo","actor":1,"pai":"2m"}->{"type":"reach","actor":1}<-{"type":"reach","actor":1}->{"type":"dahai","actor":1,"pai":"7s","tsumogiri":false}<-{"type":"dahai","actor":1,"pai":"7s","tsumogiri":false}->{"type":"none"}<-{"type":"reach_accepted","actor":1,"deltas":[0,-1000,0,0],"scores":[28000,23000,24000,24000]}->{"type":"none"}<-{"type":"tsumo","actor":2,"pai":"?"}->{"type":"none"}ツモあがり:<-{"type":"tsumo","actor":2,"pai":"2m"}->{"type":"hora","actor":2,"target":2,"pai":"2m"}<-{"type":"hora","actor":2,"target":2,"pai":"2m","uradora_markers":["8p"],"hora_tehais":["1m","3m","5m","6m","7m","1p","2p","3p","4p","5pr","6p","W","W","2m"],"yakus":[["akadora",1],["reach",1],["menzenchin_tsumoho",1]],"fu":30,"fan":3,"hora_points":4000,"deltas":[-2100,-1100,6300,-1100],"scores":[25900,21900,29300,22900]}->{"type":"none"}<-{"type":"end_kyoku"}->{"type":"none"}ロンあがり:<-{"type":"dahai","actor":0,"pai":"7s","tsumogiri":true}->{"type":"hora","actor":1,"target":0,"pai":"7s"}<-{"type":"hora","actor":1,"target":0,"pai":"7s","uradora_markers":["3s"],"hora_tehais":["2m","3m","4m","4p","5pr","6p","6p","7p","8p","6s","8s","N","N"],"yakus":[["akadora",1],["reach",1]],"fu":40,"fan":2,"hora_points":2600,"deltas":[-4400,8400,0,0],"scores":[27500,22300,24300,25900]}->{"type":"none"}<-{"type":"end_kyoku"}->{"type":"none"}流局:<-{"type":"ryukyoku","reason":"fanpai","tehais":[["5m","5m","5mr","3s","3s","N","N"],["?","?","?","?","?","?","?","?","?","?","?","?","?"],["?","?","?","?","?","?","?","?","?","?","?","?","?"],["?","?","?","?"]],"tenpais":[true,false,false,false],"deltas":[3000,-1000,-1000,-1000],"scores":[28000,24000,24000,24000]}->{"type":"none"}<-{"type":"end_kyoku"}->{"type":"none"}不明な点は@gimiteを捕まえて聞いてください。1.9以上をインストール。ruby1.9.1-devmjaiをインストール。送ると、mjai-shanten(単純なAI)3人相手の1局戦が開始します。mjsonp://localhost:11600/defaultを繰り返し実行し、mjai-shantenとの東南戦を100戦行います。天鳳の喰い断あり赤ありルール互換になる...予定です。現状色々未実装なルールがあります。2012-04-30-215246.mjson2012-04-30-215246.htmlなどとすることで、ログをHTML形式の牌譜ビューアに変換できます。今のところたぶんChromeでしか動きません。†プロトコルはあまりいじらないつもりですが、問題を見つけたら大きく変わる可能性もあります。RubyでAIを書く場合はmjai内のクラスを使うと便利かもしれませんが、Rubyのクラス構成やインタフェースはガンガン変わります。天鳳の強い人2人の全牌譜が公開されています。convertで.mjsonに変換できます。Mjai::Archiveクラスで読めます。gem付属)シャンテン数が最小になる打牌の中からランダムで選ぶ。gem付属)ツモ切りするだけ。