Watson Assistantを使ってゲームを作る

#はじめに
今年もAdvent Calendarの季節がやってきましたね！今年も参加させていただきます♪
今回も夫が作り妻が記事にするスタイルです。

#どんなゲームなの?
チャットを通じてWatsonと戦う格闘ゲームです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/141025/22376006-ad11-75b5-bc4c-c77cf4f8a476.png)

#Watson Assistantとゲームの相性
Watson Assistantには
・ SpEL(Spring Expression Language)でちょっとしたプログラミングができるので、ゲームに必要な計算をWatson Assistant単独で実行可能
・ ダイアログツリーは条件分岐とジャンプができるので、ゲームの進行を理解しやすい。

といった特徴があり、今回のようなチャットゲームを制作することに適しています。

つまり、今回のゲームでいうと、HPの計算やチャットの結果によってどんな応答をさせるかということを、外部のサービスを使わずに、Watson Assistant単体でシンプルに実装できるということです。

#ゲームの作り方
以下でこのゲームの作成方法をつまんで解説していきます。詳しくは [Github](https://github.com/ymunemasa/WatsonAssistantGame) にこのゲームのJSONファイルを置いておくのでインポートしてみてください。

##Watson Assistantサービスの立ち上げ
IBM Cloudのアカウントを取得しログインします。
カタログから「AI」カテゴリを選択し、Watson Assistantをクリックします。
左上の「カタログ」をクリックし、左部のメニューの「AI」から「Watson Assistant」を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/141025/673e90da-8b49-c419-ef0c-6d3aa6238211.png)

##Skillの作成
立ち上がったサービス上の「ツールの起動」をクリックします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/141025/9eeeb721-b898-a2f7-9b89-caf20dbddb1f.png)

立ち上がったツールの上部にある「Skills」をクリックし、続いて「Create new」をクリックします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/141025/f0667611-9fcd-d90b-5a79-9852afac2c63.png)

スキルというのはチャットに関する要素の一式です。
会話のトリガーにするキーワードや会話のフローなどを設定します。

スキルの名称と用いる言語を設定し「Create」を押してスキルを作成します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/141025/349bee39-da2f-29f5-47fa-28cfc8db7935.png)

また、「Import skill」から既成のスキルを導入することも可能です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/141025/e2b76e7d-905d-c1a2-427e-5a7b899dd96c.png)

##Intentの設定
まずは、Intentを設定します。
Intentとは利用者の意図をWatsonに伝えるためのキーワードを設定する部分です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/141025/eca9f306-da4f-2289-ecc9-793b81506a3e.png)

「Add intent」をクリックし、Intent名を設定します。
その後このIntentを起こすためのトリガーとなるキーワードを複数設定します。
今回のゲームでは「ゲームを遊ぶ」意図をWatsonに伝えたいため下図のように設定しました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/141025/c3c2013b-d13a-304d-fe53-f3f45d183f6a.png)

##Entityの設定
次にEntityです。
Entityは、とあるテーマに対して類する単語をまとめるものです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/141025/6245b863-c11f-65eb-37e3-92251682cd7d.png)

「Add entity」をクリックします。
Entity名をクリックし、そのEntityに合う単語(Entity values)を設定します(下図の"guard", "jump", "kick", "punch")。そして、それぞれをvalueとして導くチャット上で使われる単語を設定して「Add value」をクリックします。

今回のゲームでは下図のように、格闘ゲームで用いられる技を導き出す単語をEntityとして設定しています。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/141025/6d57a6bc-6788-a25c-32b8-13718d16ec77.png)

##Dialogの設定
ここまでに作成したIntentやEntityを利用したチャットのフローを作成します。
Createを押してフローの作成を開始します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/141025/3a4b37bd-9d22-73d1-10f8-e3e264354fa6.png)

会話は基本的に上のノードから順に展開されます。
**「If Assistant recognized」** - Watson AssistantがどんなIntent/Entity/変数などをトリガーにそのノードを実行するかを設定します。
**「Then respond with」** - 入力された内容に対してWatsonがどのように返答するかを設定します。複数設定してランダムな内容で返答することも可能です。数式を組み込むこともできます。
**「And Finally」** - このノードを実行した後にどのノードを実行するのかを設定します。

デフォルトでは2つのノードが設定されています。
サービスにアクセスした時に1番最初に展開されるノード(「ようこそ」ノード)と、条件に合う会話の展開がなかった際に展開されるノード(「その他」ノード)です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/141025/dde88ce6-6137-e62f-c8a0-9f0a71543313.png)

「ようこそ」ノードはWatson Assistantサービスが呼び出された際にどのように応答するかを設定したものです。
「If assistant recognizes(もしも・・・が認識されたら)」の欄にIntentやEntityを設定することで、それをきっかけに適切なノードを呼び出して会話を展開することができます。
「ようこそ」ノードではこの部分が「welcome」になっています。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/141025/e770af16-343d-5498-0b29-5f2bd2b26d99.png)

「その他」ノードでは、Watsonが会話を受けた後にどのノードに会話を展開させればいいかが不透明だった際に展開する会話を設定します。
このノードの「If assistant recognizes」の部分は「anything_else(その他)」になっています。会話の内容が他のどのノードにも当てはまらずWatsonがどのノードを展開すれば良いか不透明になった際はこのノードに飛ぶことになります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/141025/92e8284c-6e93-7753-b44f-7060f8ce8e19.png)

それでは今回のチャットの特色であるゲーム部分を展開するためのフローを紹介します。
ノードの上にある「Add node」を押すことでノードを追加することができます。ノードをクリックした状態で「Add child node」をクリックすると、そのノードを親とする子ノードを追加することができます。

このゲームではゲーム部分を「ゲーム開始」というノードで展開し、そのノードの中でさらに細かな子ノードを展開しています。

「ゲーム開始」ノードの中は下図のようになっています。
「ゲーム開始」ノードを通ることでプレイヤーとWatsonにはそれぞれHP(ヒットポイント/残機)が20ポイントずつ与えられるようになっています（後述）。
その後それぞれのHPを確認し、その値が0以下になっていた場合、ゲームを終了するための会話が展開されるようになっています。
HPが0よりも大きい時には「バトル継続」ノードに飛び、バトルが展開されます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/141025/c8308ff1-012d-b9ef-5a6b-fdc95b11afbc.png)

「バトル継続」ノードの中は下図のようになっており、格闘ゲームの中で受けた技によって会話が展開されるようになっています。ここでも「anything_else」ノードが設定されており、どの技で攻防が行われたかが不透明だった際は確認を行うようになっています。
また、それぞれの攻防の後は必ず「enemy down」ノードに飛びHPの残りを確認して会話を続けるべきか終了させるべきかが判断されるようになっています。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/141025/08126642-c31a-af8f-cb69-acecabfab42e.png)

それではそれぞれのノードを細かく見ていきましょう。

### ゲーム開始 - HP初期値の設定
ノード内の「Then respond with」の横にある縦に3つ並んだ点をクリックすることでcontext editorを開くことができ、変数の設定ができます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/141025/d89ba073-391f-5bf5-3926-47abd0284efc.png)

このゲームでは「ゲーム開始」ノード内でプレイヤーと対戦相手のHPを以下のように設定しています。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/141025/54ff5849-98fa-6b42-123f-55534a92ebfa.png)

### HPの計算 - 応答文に計算式を記述
`<? 式 ?>` を応答文に挿入することでWatsonに計算をさせ、その時々に当てはまる値で応酬させることが可能になります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/141025/cfadd834-c7d0-5e87-68ee-9b79bc969e8c.png)

### ランダム回答
それぞれの応答文が出現する確率は均等です。もしも1つの応答文が出てくる確率を上げたい場合、その応答文を「Then respond with」欄に複数コピーして貼っておく必要があるのではないかとやってみた感じだと考えています。

### 技名
本ゲームではEntity（目的語）をトリガーに技を認識するように設定しています。
(夫いわく、Watson Assistantの無料版では作成できるIntentの数に制限があるのでEntityで設定したとのこと)

今回利用しているEntityは「キック」「パンチ」「ガード」「ジャンプ」です。Watsonがそれに当てはまる物をプレイヤーが言ったと認識すれば技名が正確でなくても通用します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/141025/c65b7bad-6379-f042-a2aa-0a299380b12b.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/141025/759a4fd8-a2c2-e510-403f-af77d8800221.png)

#おわりに
いかがでしたでしょうか。
今回はチャット機能のみについて言及して記載しました。
これをSpeech to Textと連携させる/UIを加えるなどすれば、さらに面白さに磨きがかかるのではないかと思います。

ぜひ挑戦してみてください。
#参考
[【2018/11月時点】いまさら聞けない!? 簡単にチャットボットをつくれる「Watson Assistant」の基礎知識](https://qiita.com/ishida330/items/666ced65a04243ce286c)