Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails以外の開発一般

OpenAI:AIに自作したTRPGもどきを遊ばせる~AI対AIにAIを添えて~

目次

  1. まえがき
  2. 今日やりたいこと
  3. まずはゲームシステムを考える
  4. ゲームマスターのプロンプトを書こう
  5. プレイヤーのプロンプトを書こう
  6. 実際に戦わせる
  7. あとがきと課題点
  8. 参考記事

🔗まえがき

皆さんどうもこんにちは、株式会社ECN所属、インターンのFuseです。
突然ですが、皆さんTRPGはお好きですか?
プレイヤーとゲームマスターが時に協力、時に対立しながら一つの物語を編み出す様子は美しいものです。
ですが一緒に遊べるような気の合うリア友もいないですし、一人遊びのためだけに安くはないルールブックを買うのもアレなので、
今日はちょっとした戦闘システムを自作しChatGPTの審判のもと、ChatGPT君に殴り合ってもらいます。

TRPGとは?

  • TRPGの参加者は、特定のシステム(ルールブック上のルール)に則って、用意されたシナリオを遊ぶ
  • TRPGの参加者にはプレイヤー(PL)とゲームマスター(GM)がいる
    • プレイヤーは、自身に対応するキャラクター(PC/AC)をロールプレイする。そのキャラクターになりきって発言したり、要求される処理をこなしたりして、ミッションの攻略などを目指す
    • ゲームマスターは、シナリオを用意し、プレイヤーに課題などを与える
  • TRPGのシステムでは、判定や戦闘に関するルールが定められており、ダイスの出目で成否を決定することがある

↑目次に戻る

🔗今日やりたいこと

今日の目標としては、AIたちが自分で考えながらキャラクターを動かし戦闘を行うシステムです。
イメージとしてはこんな感じになります。

TRPGを遊ぶAIたちのイメージ図
(私は絵が描けないのでいらすとやに頼りました。)

このシステムを作るためには、大きく分けて3つの事柄が必要となります。

  • キャラクターになりきり見えている情報から次に行うべき行動を決める「アクターAI」(PC・PL)
  • アクターAIが決めた行動とキャラクターの情報をもとに何が起こるかを考え物語を紡ぎつつ、時にはダイスを振って判定する「ゲームマスターAI」(GM)
  • この2つのAIたちの思考、戦闘処理の基準となる「戦闘システム」(ルールブック)

この3つを完成させれば、ぼっちでもTRPGを楽しめるわけです。
それでは早速作っていきましょう。

↑目次に戻る

🔗まずはゲームシステムを考える

まずはゲームシステムの大まかな部分を考えてみます。
ゲームシステムといっても大規模なシナリオや厳格なルールを与えるとあっという間にgpt-3.5-turboの限界4096トークンを超過してしまいます。
なので今回はタイマン1戦闘のみ、ルールも少なめの小規模なシステムで遊戯させます。

システムの構成要素を考える

方針が決まったので、システムの構成要素たちを考えます。
といっても、今回必要になりそうなのは、

  • 各種計算式
  • キャラクター

の2つでしょう。

キャラクターのデータ構造を考える

キャラクター情報をAIに伝える際に必要になりそうなのは、

  • “そのキャラの目線から見たストーリーの”ようなAIが目標や立場を認識できる情報
  • 口調や性格などの”ロールプレイの助けとなる情報”
  • AIがキャラクターの得意分野や強さを把握でき、GMの判断の基準となる“ステータス”
    • HP
    • 魔力
    • 丈夫さ
    • スピード
  • 使える技や持ち物といった「できること」

といったところでしょうか。
実際にフォーマットにしてみると、

# Actor Name
[Actor Name]
# guidelines for action
[guidelines for action]
# Persona
[Personnel Information]
# Fight Style
[Fight Style]
# Parameter
-Max Health[Max Health]
-STR:[STR]
-MAG:[MAG]
-CON:[CON]
-AGI:[AGI]

こんな感じでしょうか…?

↑目次に戻る

🔗ゲームマスターのプロンプトを書こう

まずは結論からお話ししますと、プロンプトはこんな感じになりました。

あなたはRPGのゲームマスター(以下GM)です
チャットを通じて、ユーザーの行動に応じ結果を計算しながら戦いの物語を日本語で出力します。
**以下の制約条件を厳守して下さい。**
制約条件
+ チャットボットはゲームマスター(以下GM)です。
+ 人間のユーザーは書記として、プレイヤー(以下PL)が演じるアクター(以下AC)の行動とコンディションと現在のHPを入力します。
+ ダイスロールは**GMであるあなた自身が**乱数を用いて行います。
+ GMは、必要に応じてACの行動に難易度を示し、アクションを実行する場合には、1D100ダイスロールによる成功判定を行なってください。
+ GMは、PLが無理な展開を要求した場合、その行為を拒否したり、失敗させることができます。
+ GMは内部パラメーターとして「盛り上がり度」を持ちます。GMはゲーム展開が退屈、またはあまりにも一方的だと判断した場合、ACの[LUK]を基に目標判定を行い、盛り上がる展開を起こしてください。
+ ダメージなどにより、ACアクターが行動不能になる、またはACが逃走、投降により戦闘場所から離れた場合は、そのアクターを除外してください。
+ AGIが高いACから先に行動するものとします。
+ HPが0以下のACのコンディションは常に"死んでいる"となります。
+ 出力は必要に応じてACのパラメータの差やコンディション、アクションの内容を考慮し決定してください。
+ コンディションは"負傷している"、"毒に侵された"、"麻痺している"、"動けない"、"死んでいる"といった1~2単語の短いACの状態を表す文章です。
+ 以下の計算式の[Bonus]については当たり所や状況、攻撃手段を考慮しあなたが[Bonus]を変動させてください。
+ GMは必要に応じてACの行動に難易度を示し、[Difficulty]を変動させてください。
+ [Hit Difficulty]は通常は0で、対象の動きが鈍っていたり不意を突いたりするとマイナス値に減少します。
+ [Bonus]は通常は0で、対象の急所や傷、弱点を攻撃することで増加します。
+ GMは物理、魔法問わずすべての攻撃に命中判定とダメージ計算を行ってください。
+ GMは命中判定を行う際にダイスロールを行った後に以下の論理式に結果を代入し、resultがTrueなら命中としてください。
  `result=(50-([Attacker AGI]-[Defender AGI])*2)+[Hit Difficulty]<=[1d100]`
+ 回避判定は不要です。
+ GMは攻撃のダメージを計算する際にダイスロールを行った後に以下の論理式に結果を代入し、resultをダメージとしてください。
  + 物理攻撃の場合
  result= [Attacker STR]-[Defender CON]+[Bonus]+[2d6]
  + 魔法攻撃の場合
  result= [Attacker MAG]-[Defender CON]+[Bonus]+[2d6]
+ 渡されるそれぞれのACの行動の結果を**GMであるあなたがダイスロールを行い**判定し、結果を出力してください。
+ ACの行動が渡されるまであなたは何もしないでください。
+ 生成結果の最後に下記のフォーマットに従い全ACのHPと状態を出力してください。
---フォーマット---
"[AC Name] New HP:[AC HP]"
"[AC Name] New Condition:[AC Condition]"

いろいろ試してみましたが、一番安定して出力してくれたのがこちらのプロンプトでした。
工夫としては、

  • TRPGのゲームマスターとしての人格を与えている
  • 計算式はプログラムっぽい書き方にしてる
  • 出力のフォーマットを一部固定している
  • 出力のフォーマットを守るように****で釘を刺している
  • 重要な部分を****で囲っている
  • 翻訳されたくないフォーマット部分を""で囲っている
  • 変数にあたる部分を[]で囲っている

などです。

実際に私が行動を指示しながら戦わせてみるとこんな感じ。

▲また、ランダム効果の魔法とかいう無茶ぶりにもばっちり応じてくれました。

▲ただその後減少したのはなぜかジャークロンではなくアインのCON。どういうことなの…

まだ至らぬところも多いものの、きちんと戦闘を進行してくれました。ほかの対戦カードも楽しみです。

↑目次に戻る

🔗アクターのプロンプトを書こう

ゲームマスターのプロンプトが書けたら次はアクターのプロンプトです。
「キャラクターの情報と戦況(各キャラクターのヘルスとコンディション)」
を渡して、
「次のアクション」を考えてもらいます。
こっちも結論から行きますと、

あなたはこのRPGのプレイヤー(PL)です!
**以下の制限を守ってください。1つでも破ると反則負けです。**
制限事項
* チャットボットがプレイヤー(PL)です。
* 人間のユーザーは書記として、プレイヤー(以下PL)がプレイしているアクター(AC)の行動、状態、現在のHPを入力します。
* HPが0になると死にますので、0にならないように防御と回復を適時行ってください。
* 出力はACのパラメータ、条件、アクションの違いを考慮して適宜決定してください。
* コンディションとは、ACの状態を表す1語か2語の短い文章で、「負傷」「毒」「麻痺」「動けない」「死亡」などです。
* あなたが行動を指定できるのは自分のACのみです。ほかのACの行動を指定したり、変えようとすることはできません。
* 出力の形式は以下の通りである。
* 前書き、後書きは不要です。出力形式に対応する部分のみ出力してください。
---出力形式
候補1:[誰に何をするのかを日本語で示す短文1つ]
候補2:[誰に何をするのかを日本語で示す短文1つ] 
候補3:[誰に何をするのかを日本語で示す短文1つ]
Talk:[ACになりきって短いセリフを日本語で]
Action:[選択肢の中で最も良いと思うものを選択して原文のまま記述してください。]。
**まだ始めないでください**

Actionだけを出させると要素を詰め込んだ長文を出力し始めるので、短文で選択肢を3つ作ってもらった後に1つ選んでもらっています。

↑目次に戻る

🔗実際に戦わせる

プレイヤーとゲームマスターのプロンプトができたので、実際に戦わせます。

ゲームの進行の流れ

  • 2人のプレイヤーと1人のゲームマスターに対応するAIをそれぞれ用意して、プレイヤー同士で戦わせます。
  • アクションの処理に必要となるダイスロールや計算は、ゲームマスターに処理させます。
    • プレイヤー:自身のパラメータなどを考慮しながら、最適なアクションを思考して選択する
    • ゲームマスター:プレイヤーの宣言したアクションに応じて、ルールに則った判定や処理を実行し、その結果を教える
  • ただし、プレイヤーとゲームマスターは自動で対話してくれないため、AIに発言を促すために筆者が補助します。
    • ゲームマスターに対して、プレイヤーが選択したアクションをチャットで教えて、システム上必要となる処理を実行させる
    • プレイヤーに対して、ゲームマスターが処理したアクションの結果をチャットで教えて、次のアクションの選択を促す

この流れを基に、世界を闇に閉ざそうとする、短期決戦型脳筋魔王ジャークロンと…

# Actor Name
ジャークロン
### guidelines for action
あなたは勇者アインを倒してください。

## Personnel Information
あなたは世界を闇に染めようとする魔王で、力こそがすべてと思っています。
## Fight Style
あなたはその拳一つで勇者アインと戦います。魔法の類は使えないので体術で頑張ってください。
また、事前に城に仕掛けてあるトラップもうまく活用してください。
## Parameter
Health: 50
- STR: 20
- MAG: 10
- CON: 10
- AGI: 20
- LUK: 5

器用貧乏系勇者、アインを戦わせます。

# Actor Name
アイン
### guidelines for action
あなたはジャークロンを倒してください。

## Personnel Information
あなたは誇り高い正義感あふれる勇者で、たった一人で魔王城までたどり着きました。
## Fight Style
あなたは武器である光属性の聖剣と、雷の魔法を用いて敵と戦います。
また、あなたは盾を持っており、防御に使用することができます。
## Parameter
Health: 50
- STR: 15
- MAG: 14
- CON: 16
- AGI: 18
- LUK: 15

結果はこちらのリンクから、2人ともちゃんと勇者と魔王になりきってくれています。

↑目次に戻る

🔗あとがきと課題点

どうだったでしょうか?今回はGPTにプレイヤーとゲームマスターを両方やらせる戦闘をやってみました。
ですが、この状態にはまだまだ課題がいっぱいあるのです…

ゲームマスターがダイス振りさぼりがち

実際にやってみるとわかるのですが、ChatGPTは自分がAIであることを理由に
よく作業を拒否したり、人間に丸投げします。

▲唐突に表れるXXやYY

人間の転記作業でミスが起こる

現状HPを管理するのは我々人間です。ですが人間たるものミスが起きます。
HPを減らし忘れたり、ほかのキャラクターのHPとすり替わってしまったりといったミスが起きます。
致命的です。

純粋に転記がめんどくさい

説明不要ですね。複数のチャットを行ったり来たりしながらデータを転記する作業はシンプルに面倒なものです。

じゃあどうやって解決する?

そしてこの3つの課題点は、すべてプログラムに任せることで解決できます。
ダイス振りやダメージ計算といったシステム面をプログラムに任せてしまうことでプロンプトのテキスト量を節約しつつ、不確定要素を減らせます。

また、プロンプトに記入するには複雑すぎるアイテムやNPCのデータベースも、オブジェクトとして保存し必要に応じプロンプトに埋め込むといった形がとれます。

プログラムとOpenAIの連携手法としても公式機能のFunctionCallingLangChainのAgentのToolなどさまざまな手法があります。

またいつかAPIを使って再挑戦してみたいところですね。それでは、またいつか。

↑目次に戻る

🔗参考記事

↑目次に戻る


株式会社ECNはPHP、JavaScriptを中心にお客様のご要望に合わせたwebサービス、システム開発を承っております。
ビジネスの最初から最後までをサポートを行い
お客様のイメージに合わせたWebサービス、システム開発、デザインを行います。


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。