Markdown+AIでノベルゲーム制作

Markdown AIというサイトの力を借りて、「Markdown Adventure」というゲームを作ってみました！遊んでみてください！

[ゲームページ](https://mdown.ai/content/64eca81b-329b-4811-a107-4eea93eb870b) / [コード](https://github.com/very-ame/markdown-game)

*編集1: ゲームページへのリンクと、コードを公開しました！
**編集2: 2025/02/05 時点で正しくJavaScriptが動作しないことを確認しました。Markdown AIの側で仕様変更があったのかもしれません。

![md_game.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3920746/f454524c-06bb-a16d-d357-53742b8c1a2c.png)


# 要約
マークダウンが好きです。洗練された見た目の、メモ帳のすごい版だよ！って感じの文章が簡単に書けちゃう。でも作れるのは文章だけ？**ゲーム作って公開したくない？** マークダウンでそんなことできるの？できます！

**Markdown AI**って言うツールがあるらしいです。

- マークダウンで作った記事をウェブサイトとして一般公開できる！

- 自分でサーバーを用意しなくていい！

- AIとおしゃべりできる機能もついてくるよ！

**AIを使ったウェブアプリ**を**誰でも作れて、遊んでもらえる**ってことだよね？すごくね？

ゲームとかウェブアプリなんて当然つくったことないし、どう公開したらいいかとかも分かんないし、アプリの中でAIを使ってみようなんて夢のまた夢だけど、全部簡単にできちゃうのかも :kissing:

# ゲームの概要

## コンセプト

「マークダウンの美麗なテキストレンダリング」と「AIによるストーリー生成」をかけ合わせて、新感覚のノベルゲームをつくることをコンセプトにしてみました。

## ゲームシステム

AIが生成したストーリーの上で、プレイヤーはいくつかの選択をしていきます。その選択に応じてストーリーがさらに生成され、物語が展開していきます。いくつかの選択の先にエンディングを迎えます。

# 実装
## マークダウンの表示
Markdown AIでは、マークダウン記法によってタイトル、太字、箇条書きなどのベーシックなマークダウン表記を記述することができます。通常の文字表示にはプレーンテキスト、ストーリー上のTips的なものの表示には引用を利用しました。

![img1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3920746/69988f3e-1aa3-e6b2-ea7a-deab7f1fba3f.png)
- 初めに冒険を始めるかどうか選ぶシーンです。プレイヤーの文字入力に応じた反応が返ってきます。

## HTMLによる動的な表示
Markdown AIでは、HTMLを利用して高度な表示をサポートしています。文字を点滅させたり、クリックできるボタンを作ったり。Markdown特有の手軽さは失われますが、拡張性があります。

単にHTMLが使えるだけでなく、HTMLとJavaScriptによる動的な表示と、Markdownのレンダリングを組み合わせることもできます。役に立った使い方を二つ紹介します。

### 1. マークダウンのテキスト部分にHTMLタグで文字を挿入
```html
# <p id="title">&nbsp;</p>

<script>
document.addEventListener('DOMContentLoaded', async () => {
  let titleElement = document.getElementById('title');
  titleElement.innerText = "New Title";
});
</script>
```
- 通常のHTMLでは、マークダウン記法である`#`による見出し化はできませんが、Markdown AIでは利用可能です。同様に箇条書きや引用にもHTMLの要素を適用可能です。`<script>`内で指定すれば、動的に表示内容を変えることができます。
- この例では、ページがロードされた際に見出しが"New Title"になります。


### 2. マークダウン要素をまるまるdiv要素として扱う
````html
<div id="mdown-block" style="opacity: 1;">

## 見出し
---------------------
```
コードブロック表記
```

</div>

<script>
async function fadeOut(element, duration) {
    return new Promise(resolve => {
        element.style.transition = `opacity ${duration}ms ease`;
        element.style.opacity = '0';
        element.addEventListener('transitionend', () => resolve(), { once: true });
    });
}

document.addEventListener('DOMContentLoaded', async () => {
  let markdownBlockElement = document.getElementById('mdown-block');
  await fadeOut(markdownBlockElementm, 1000);
  titleElement.style.display = "none";
});
</script>
````
- 1の方法だと、見出しのプレースホルダーそのものや、水平線のようなものを動的に表示/非表示することができません。また、コードブロックのような複数行にわたるマークダウン記法のテキストを書き換えることもできません。そこで、それらの要素そのものをまとめて`<div>`タグなどで囲うことで、マークダウンのデザインを保ったままHTMLとJavaScriptによる表示の操作が可能になります。
- **`<div>`要素の中身で、必ず最初と最後に一行あける**ことが必要です。他の方法もあるのかもしれません。おそらく内部的にMarkdown記法をHTMLに変換する際の仕様なのでしょう。初めはこれが分からず少し悩みました。
- この例では、1秒かけて見出し・水平線・コードブロックが透明になっていって非表示になります。

## ストーリー生成
モデルにはあらかじめプロンプトを与えておくことができます（すばらしい機能です）。ストーリー生成のためには次のようなプロンプトを用意しておきました。
```
次のルールに沿って、ストーリーを作成してください。作成したストーリーを、物語風に語ってください。

ルール
- 主人公は一人で、他に登場人物がもう二人います。
- 物語は、3つのパートに分かれています。一つ目は話題定期、二つ目は物語の展開、三つ目は結末です。
- それぞれのパートはおよそ400字くらいの地の文と、主人公以外のキャラクターのセリフで展開されます。主人公は話しませんが、地の文では語ります。一人称視点の物語です。
- それぞれのパートに、こちらが選択する部分を作ってください。例えば選択肢を示してください。私の選択に応じて、話が展開するようにしてください。
```
- 実際には、モデルからの返答をパースしやすいようにフォーマットなどを指定したり、プロンプトの工夫を行いました。出力されるストーリーのクオリティを上げようと突き詰めると沼です。詳細なプロンプトは[コードページ](https://github.com/very-ame/markdown-game)に記述してあります。

# 最後に
Markdown AIの用途はいろいろと考えられます。文章と図が主体のwebページに、コンテキストを備えたAIに質問できる機能を簡単に追加することができます。ページそのものに結合できる手軽さと、モデルに事前知識を与えられる部分が、「ChatGPTでよくね？」への答えになっているように感じました。

私はこのサイトをすごく気に入りました。AIとの会話機能があるサイトを作ろうという時点で、単なる記事公開やメモと異なり、動的なウェブページを作成することが必要です。でも、動的なページはMarkdownだけでは実装できません。かといって、すべてHTMLで書けと言うのは習得コストが大きく、素人が制作しても見た目が悪くなります。Markdown AIを使えば、Markdownの手軽さとスタイリッシュさを流用しながらサイトを作れるのが絶妙です。

今回はマークダウンのレンダリングの美しさに注目してノベルゲームを作ってみましたが、もっと実用的なコンセプトで他のページも作ってみたいです！

ぜひプレイしてみてください。**毎回ストーリーが変わる**んです。もう一回プレイしてみませんか？

[ゲームページ](https://mdown.ai/content/64eca81b-329b-4811-a107-4eea93eb870b) / [コード](https://github.com/very-ame/markdown-game)