LINE株式会社は、2023年10月1日にLINEヤフー株式会社になりました。LINEヤフー株式会社の新しいブログはこちらです。 LINEヤフー Tech Blog

Blog


詰将棋LINE Botを作りました

DataLabs所属の@sugyanです。この記事はLINE Advent Calendar 2017の11日目の記事です。

個人的な話ですが、この秋から新たな趣味として将棋を始めました。この趣味に自分の技能を活かして何かしてみたいと思い「詰将棋の問題を自動生成して出題してくれるLINE Bot」を作りましたので、紹介します。

詰将棋とは

簡単に紹介しますと、詰将棋とは将棋のルールを用いた一種のパズルで、以下のようなルールになっています。

  1. 攻め方(先手)が玉方(後手)の玉を詰ますのが目的。
  2. 攻め方は必ず王手をかける(玉方は必ず王手をはずす)。
  3. 玉方は盤上と攻め方の持駒以外すべての駒(ただし玉は除く)を合駒として使用できる。
  4. 玉方は最善を尽くし、最も長く手数がかかるように逃げる。
  5. 玉方は無駄な合駒をしない。
  6. その他は指し将棋のルール通り。二歩、打ち歩詰め、行き所のない駒、連続王手の千日手はいけない。

日本将棋連盟 詰将棋ページより)

例えば、以下のような形で出題されます。

この問題の正解は▲2二歩成 △1三玉 ▲2三飛までの3手詰めとなっていて(「▲」が攻め方の動きを、「△」が玉方の動きを表しています)、それ以外の攻め方で詰ませようとしても玉は3段目、4段目へと逃げられてしまいます。

詰将棋の問題生成エンジンについて

詰将棋の問題を作成する方法にもいろいろあるようなのですが、今回は自分でプログラムを書いてゼロから作ってみました。考え方や方法などについては個人の技術ブログに書き残してありますので、興味のある方は読んでみてください。

特に高度なアルゴリズムの知識などなくても、とりあえず3手詰くらいの問題なら生成できるようになりました。ただし1問生成するのにも数秒〜十数秒かかってしまうのが難点ですが……。ここはこれから改善していきたいと思っています。

問題生成エンジンを使ってBotに組み込む

問題が生成できるようになったので、多くの人に見てもらえるようSNSなどに自動投稿できるアプリケーションを考えてみました。最初に公開したのは、Twitter Botです。

これは、9時から21時の間、毎時0分に、生成した問題を画像付きでツイートするだけのBotです。解答は見たい人だけが見られるように、専用の解答ページを用意してそのURLをツイートに含めるようにしています。

これはこれで悪くないのですが、例えば定期的にタイムラインに流すだけではなく、もう少しパーソナライズして利用できるようにしようとすると、以下のようなインタラクションを個人への返信やダイレクトメッセージを使ってやりとりできる機能が必要になってきます。

  • 任意のタイミングで出題をリクエストする。
  • 問題の解答を教えてくれるようリクエストする。
  • 出題された問題の評価・フィードバックを送る。

Twitterのテキストのやりとりだけでこれを実現するのは、なかなか大変そうです。

LINE Botでの応用

そこでLINE Botです。

早速ですが、拙作の「詰将棋BOT」を紹介させていただきます。

友だち追加

友だち追加して、トーク画面で出題リクエストを送ると、次々と生成された問題が出題されます。また、それぞれの問題に対する解答と詰め上がり図を確認することもできます。

リッチメニュー

現在、この詰将棋BOTは「1手詰の問題」か「3手詰の問題」を選んで出題できるようになっています。テキストメッセージで「1手詰」と送れば1手詰の問題を、「3手詰」と送れば3手詰の問題を出題してくれるのですが、いちいちそれを入力して送るのも面倒ですよね。

そんなときに使えるのが「リッチメニュー」です。トーク画面を開いた瞬間に下から「ヒャッ」とメニューが出てきます。これでユーザはわざわざ文字入力せずに問題の種類を選択するだけで、出題のリクエストを送ることができます。

ちょっとデザインが手抜きすぎてアレですが……

リッチメニューについて詳しくは、以下のリンクを参照してください。

テンプレートメッセージ

詰将棋BOTからの出題・解答時に使っているのが、テンプレートメッセージ(Template message)です。生成した問題の画像をただ送信するだけでも良いのですが、後述するポストバックアクション(Postback action)を有効に利用できるのでこれを選択しました。

現在、テンプレートメッセージは、「ボタン(Buttons)」、「確認(Confirm)」、「カルーセル(Carousel)」、および「画像カルーセル(Image carousel)」の4種類が提供されています。詳しくは、以下のリンクを参照してください。

詰将棋BOTでは、

  • 問題図の画像を1つだけ表示したい。
  • 正解をリクエストするアクションを指定したい。

という理由から、ボタンテンプレートを使用しています。

ポストバックアクション

正解を教えて欲しい、というユーザからのリクエストを送信する際に、上記のテンプレートメッセージに付与したポストバックアクションを利用すると便利です。

これはテンプレートメッセージの送信時に指定できるアクションオブジェクトの1つで、他にも「メッセージ(Message)」、「URI」、「日付選択(Datetime picker)」といったアクションを利用できます。詳しくは、以下のリンクを参照してください。

ポストバックアクションは、指定した文字列データを(ユーザからは見えない)裏側を通してイベントを発行してくれます。ユーザからはボタンを押しただけで何も送っていないように見えても、Bot側はイベントを受け取ってレスポンスとなるメッセージを返すといった処理を行うことができます。

詰将棋BOTでは、問題図のテンプレートメッセージについている「正解を見る」というボタンをタップすると、その問題のIDが裏側で送信され、IDを受け取ったサーバからその問題の正解が送信される、という方法を取っています。

また、同様の方法で、解答時に問題に対して「いいね」のようなフィードバックを送れるようにもしています。この機能にもポストバックアクションを利用しています。

Go on Google App Engine

特に強いこだわりがあったわけではないですが、今回のLINE BotはGoogle App Engine Go Standard Environmentを使って動かしています。

詰将棋BOTを動かすために工夫した点、利用しているサービスについて簡単に触れておきたいと思います。

Go SDK for the LINE Messaging API

LINE Botを動かすためのLINE Messaging APIは、さまざまな言語で利用できるよう各種のSDKが提供されています。その1つにGo版があり、私もそのSDKの開発に関わっています。

多くの開発者の皆様からプルリクエストをいただいて反映しており、Google App Engineの環境でも利用できるようになっています。

DataStoreとCronジョブで問題をストック

Messaging APIでの応答は、一定時間内に返さないと応答トークン(Reply token)の期限が切れて無効になってしまいます。詰将棋の問題もリクエストされて即座に生成して返せれば良いのですが、現状の生成エンジンでは数秒〜数十秒かかってしまうので、タイムアウトで失敗してしまうケースが出てきます。運良く期限ギリギリで生成して返すことができたとしても、やはり何秒間も返答を待たされるのはストレスです。

そこで、出題リクエストに対しては常にある程度の問題数をストックしておいて、そこから利用する方式にしました。Cronジョブで定期的に問題を生成してDataStoreに保存し、出題リクエストを受け取った際にはストックされた未出題のものから選択して返す、という動作です。こうすることで、次々と生成された問題を即座に返すことができるようになります。

もちろん、定期的に生成されるペースより出題リクエストされるペースの方が早くなるとストックが尽きてしまうのですが、そのときには過去に出題した古い問題からランダムに選択して対応するようにしています。このときに、上述した「いいね」を貰った数が多い問題が優先的に選択されやすくなるようにしています。

過去の問題を使い回すことになるので常に新しい問題を提供し続けることはできないかもしれませんが、それは過去に他のユーザに対して出題されたものかもしれませんし、それほど「同じ問題ばかり出てくる」ということはないと思います。

CloudStorage

問題図の画像はCloudStorageにアップロードして使用しています。ここまで触れていませんでしたが、盤面図の画像も素材を組み合わせて生成するプログラムを書いて作っています。

Goは標準のライブラリだけでこういった画像操作ができて便利ですね。

今後の展望

5手詰や7手詰などもう少し長手数の問題も安定して供給できるよう、生成エンジンを強化していきたいと思っています。

友だち追加して使っていただいて、UIや機能への要望などのご意見をいただけると嬉しいです。よろしくお願いします。

まとめ

このように、ある程度のコンテンツを作ることができるようになると、ちょっとした工夫でインタラクティブに操作しやすいBotをLINEプラットフォーム上で提供できる、という例を紹介しました。

明日は立花翔さんによる「イメージマップメッセージを使って終電に乗り遅れないボットを作りました」です。お楽しみに!