博多電光

技術ブログ

TSGのSlackbot紹介「一人麻雀BOT」

※この記事は TSG Advent Calendar 2017 3日目の記事です。

前日の記事でお送りした通り、TSGのSlackには部員が実装した多くのSlackbotが棲息している。この記事ではそんなSlackbotたちの中でも特に手間をかけて作られた、一人麻雀BOTを紹介する。

一人麻雀BOTとは

名前の通り、麻雀を一人でプレイできるBOTである。

#sandboxチャンネルで「配牌」と言うとゲームが始まる。

f:id:hakatashi:20171203182349p:plain

プレイヤーは「打◯◯」もしくは「ツモ切り」と発声することでゲームを進行させる。和了るか流局するとゲーム終了である。

f:id:hakatashi:20171203182633p:plain

得点は引き継がれ、チーム内全体で共有される。なのでなかなかスリルがある。

一人麻雀のルール

筆者が調べた限り、一人で行う麻雀に関する統一的なルールは存在しない。なので以下のルールは主に筆者が調整したものだが、プレイしている部員からのゲームバランスの評価は高い。

  • 最初の持ち点として25000点を与えられる。
  • ゲームの最初に13牌の手牌を並べ、17回の摸打で和了を目指す。
  • 配牌するたびに場代1500点を支払う必要がある。
  • 和了った場合通常の麻雀と同じように得点計算が行われ、その点数を獲得する。
  • 17回の摸打で和了れなかった場合、流局となる。このときノーテンだと不聴罰符として3000点を取られる。
  • リーチすると一巡ごとに河として牌を三つ公開する。この中に当たり牌が含まれていた場合ロンとなる。リーチ前のロンはできない。
  • リーチ状態で流局した場合、供託点1000点が支払われる (供託点は返ってこない)。
  • 持ち点が0点を下回るか50000点を上回った場合、勝敗が記録され点数がリセットされる。
  • ポン・チー・カンは存在しない。暗槓も (今のところ) できない。
  • 場局は常に東一局、プレイヤーが親となる。(なので東の刻子は常にダブ東である)
  • 誤ツモ・誤ロン・不聴立直は満貫払いの錯和である。

通常の麻雀で必要とされる、相手の河から手牌を読むという一番不毛な考えさせられる手順を必要としないので、気軽にプレイできると評判である。

ちなみに現在までの最大得点は倍満24000点で、2回出ている。

f:id:hakatashi:20171203181959p:plain

f:id:hakatashi:20171203181955p:plain

技術的な話

ソースコードはこちら。

github.com

Node.jsで実装されている。得点とか役の計算とかは自前で実装なんてやってられないので、riichi-coreというライブラリを使用させて頂いている。このライブラリは四人麻雀のゲーム進行全体を実装したものなのだが、無理くりいじって得点計算の部分だけ流用した。

Slackとの繋ぎ込み、ゲームの進行、得点管理、ドラ・天和・海底摸月・ダブルリーチ・一発などの判定はこのライブラリでは賄えないので自前で実装してある。

手牌画像生成

画像生成はmahjong.hakatashi.comに投げている。これは本来別の目的のために実装したものだが、一人麻雀BOTのために大幅に改造したので、ついでに解説する。

ソースコードはこちら。

github.com

mahjong.hakatashi.comは、任意の手牌画像を生成できる Web API である。Unicodeの麻雀文字を使用して以下のようなURLにアクセスすると、いい感じの画像が降ってくる。

例: https://mahjong.hakatashi.com/images/🀊🀊🀋︀🀋🀌🀌🀜🀝︀🀓🀔︀🀕🀘🀘🀞?王牌=🀫🀫🀅🀫🀫🀫🀫🀫🀫🀫🀫🀫🀫🀫

f:id:hakatashi:20171203184216p:plain

赤ドラは赤くしたい牌の直後に U+FE00 を挿入すると表現できる。

画像生成はかなりお手軽実装で、「snap.svgSVG生成 → electronでPNGに変換」という手順を取っている。Web技術だけで完結するので非常に楽ちんだが、バックでいちいちブラウザを起動しているのでとてつもなく重い*1。余裕があればimagemagickとかに置き換えて高速化したいところ。

今後

  • Hubotへの移植
  • 暗槓の実装
  • 三麻モードの実装

他のSlackチームへの移植もご自由にどうぞ (今のところかなりめんどくさそうだが)。プルリクも待ってます。

明日は@_gacinがなにか書きます。

*1:なのでむやみにアクセスされると死ぬ