いつ、どこで、誰が、何をした？のことばを使って長い文章を作成する試み



# はじめに
皆さんは、「いつ、どこで、誰が、何をした？」という遊びをご存じでしょうか。
これは、参加者がそれぞれ、「いつ」「どこで」「誰が」「何をした」の４種類の言葉を紙に書き、ランダムに組み合わせてできた文章を楽しむ遊びです。

最近、この遊びをiOS上で遊ぶことができる「いつどこ語り」というアプリをリリースしました。
このアプリはもともと小学生の娘たちと遊ぶためだけに作ったもので、追加した言葉で短文を作る機能しかありませんでした。
しかし、あるとき「長文も作れたら結構面白くなるのでは？」と思い機能追加したところ、かなり面白いもの（主観）ができたのでストアにリリースしてみることにしました。

本記事では、長文作成機能を組み込むにあたって苦労したこと・面白かったことを紹介しようかと思います。

# できあがったもの
技術的な話に入る前に、まずは、完成したものをお見せします。

**長文作成例：**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136183/56e8ea81-5bb1-22e8-19d9-017ab72a21c5.png)


# 設計

## 文章の骨組みは人間が作成する

最初は、単に
```
「いつ」「どこで」「誰が」「何をした」
一方「誰」が「どこで」「何をした」
しかし「誰」は「どこで」「何をした」
それから「誰」が「どこで」「何をした」
...
```

のように、ループを回しつつ、短文と短文を「一方」とか「しかし」とか「それから」とか、それっぽい接続詞でつないでいくだけの完全ランダム方式で、面白い文が作れるかと期待したのですが、これはいまいちでした。
（単調すぎてすぐに飽きてしまうし、意味不明すぎて面白みがない）

そこで、要所要所はランダムな言葉を入れるけれど、文章の基本的な骨組みは人間が作る方針に切り替えました。

## 文章のテンプレート
上述の「文章の骨組み」を定義するために、アプリ内で使用する「お話テンプレート言語」を設計することにしました。
詳細な仕様は省きますが、お話テンプレート言語がもつ機能を疑似言語風に解説していきます。

### 言葉の埋め込み機能

**テンプレート**
```
あ…ありのまま 今　起こった事を話すぜ！
「おれは　奴の前で [何をした] と
思ったら　いつのまにか [何をした] いた」
な…　何を言っているのか　わからねーと思うが　
おれも　何をされたのか　わからなかった… 
頭がどうにかなりそうだった…　 [何をした] だとか [何をした] だとか
そんなチャチなもんじゃあ　断じてねえ
もっと恐ろしいものの片鱗を　味わったぜ…
```

**作成例**
![simple.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136183/0f6a8ce0-4e6a-8f31-4e4f-7b7f15c5c86a.png)

のように、テンプレートの中に[いつ][どこ][誰][何をした]のプレイスホルダーを見つけたら、ランダムに言葉を埋め込む機能です。
まあ、まずはこれがないと始まらないということで。

### ID付与機能
ただ、テンプレートを作っているうちに、ランダムで埋め込んだ言葉を後からもう一度使いたくなるケースがあることがわかりました。
例えば、登場人物AとBを会話させたい場面。
ここで、AとBが毎回別人になってしまうと意味が分からなくなってしまうため、

**テンプレート**
```
[誰 id="a"]: おい、[誰 id="b"]。昨日は電話に出なかったけど何してたのさ。
[誰 id="b"]: えーっとね。[何した id="1"]してたら寝ちゃってたんだよね。
[誰 id="a"]: そうか。[何した id="1"]してたんなら仕方ないか...
```

**作成例**
![denwa.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136183/b1f165e5-71ff-0a66-3f18-4d930e366e8d.png)


のように、idを振った言葉は共通なものが入るようにしました。

### ランダム分岐・ループ
話の骨組みにも変化をつけたいので、ランダムによるループや分岐要素を追加しました。
- [分岐]に囲まれた子要素はランダムで一つ選択される
- [ループ]に囲まれた子要素は指定回数繰り返す

**テンプレート**
```
[ループ minOccur="3" maxOccur="6"]
  [分岐]
    [何をした]っていいじゃないか。
    [何をした]ときだってあるさ
    たまには[何をした]いときもあるさ
  [分岐end]
  [分岐]
    人間
    おれ
    凡夫
    [誰]
  [分岐end]
  だもの。
[ループend]
```

**作成例**
![loop_bunki.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136183/9d0fd23b-2b67-886a-9397-cd9cce4e8aa4.png)

のようなイメージです。

### 動詞の活用機能
テンプレートの機能の中では、これが一番苦戦しました。
これは、言葉の埋め込み機能の補助的な機能で、「何をした？」の言葉を埋め込むときに適切に活用させて埋め込む機能です。

例えば、ユーザが入力した「何をした」の言葉が「演歌を歌った」だったとして、それを

```
僕の趣味は毎週[何をした]ことです。
```

のようなテンプレートに埋め込んでしまうと

```
僕の趣味は毎週「演歌を歌った」ことです。
```

のような不自然な文章になってしまいます。

そこで、「何をした」を埋め込むときに活用形を指定して

```
僕の趣味は毎週[何をした 活用形="連帯系"]ことです。
```

とした場合、

```
僕の趣味は毎週「演歌を歌う」ことです。
```

のように、言葉を活用させて埋め込めるようにしました。

**短文作成用に登録した言葉を活用して長文に埋め込む機能：**
![活用埋め込みの図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136183/f903109e-6833-3ce1-afe4-1d3463018ee0.png)

これを実現するためには、ユーザが言葉を入れたときに、その言葉の語幹（その言葉の活用しても変化しない部分）と、活用の種類（ワ行５段活用とか）も判定しなければいけないという問題がありました。

この問題への対応としては、言葉を入力したときに以下のような補足の質問に回答してもらって動詞の活用の種類を判定することにしました。

**言葉を入力した後、以下のような問いかけをする：**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136183/5626cdac-2300-6121-75d3-e25d536ba4c1.png)

すべての言葉を完璧には判定できませんが、このアプリで使うぶんには充分実用的なものができたと思っています。

活用形の判定は実装していてかなり楽しい部分だったのですが、詳細は長くなるため本記事では省略します。
別記事で詳しく書いていますので、興味がある方はこちらをどうぞ。

https://rhikos-prgm.hatenablog.com/entry/2022/06/17/035058

# 今後の開発予定
本業があるのでこのアプリにあまりリソースは割けないのですが、娘が自分でもお話（テンプレート）を作ってみたいと言っていたので、テンプレートをGUIベースで作成・登録・公開できるような機能が追加出来たら楽しいかも？、と考えています
（娘駆動開発）

# さいごに
いつどこ語りはAppStoreで配信中です。
興味のある方は遊んでみてください。

https://apps.apple.com/jp/app/id1626244132