Copilot Studio ほぼ全ての処理をAIに任せたボードゲームを構築してみた|AI駆動アーキテクチャのようなもの

「AI駆動」という考え方がおもしろかったので、AIに処理を完全に任せてボードゲームを作って遊んでみた。

スポンサーリンク

AI駆動

AI駆動型のシステムとは、AIにシステムの制御を任せることで、柔軟で効率的なアプリ開発を実現する新しいアーキテクチャ

代表的なのがMVAアーキテクチャで、MVCのコントローラの部分をAIに任せてしまうことで、開発が楽になる上、ユーザーから想定外の入力があっても柔軟に対応できるのが利点

今回は若干AI駆動とは異なるかもだけど、AIを制御の中心に添えて、何でもできるボードゲームマスターを作ってみた。

構築

全体イメージは以下の通り。黄色いノードがAIに処理を任せている箇所なので、ほぼすべてのゲーム処理をAIに任せてみた。

今回プロンプトを練る時間があまりなかったので、LLMにはo1を使用。

GPT4oだとうまく動作しなかったけど、プロンプトをもっときちんと考えれば4oでも動くかも。
※特に判定処理がいまいちでループすることも有効な手を無効と判断することも多かった

手順1:ゲーム名の取得

まずはユーザーからゲーム名を取得する。
「ゲームしようぜ」をトリガーに、ユーザーにゲーム名を質問。応答全体を変数に入れる。
そのユーザーの質問の中からボードゲームの名前をプロンプトアクションで抽出。知らないボードゲーム名の場合や、ボードゲーム名が含まれない場合はこの時点で終了。
プロンプトはこんな感じ。
※ここは難しいタスクではないので4o-miniで。

手順2:先手の確認

続いて先手を確認する。
選択式の質問で手番を聞いて、
※1対1のボードゲームのみ想定
変数「手番(turn)」を設定。

手順3:駒の定義、ボードゲームの初期状態生成、初期盤面描画

続いてボードゲームの初期状態の作成から、初期盤面の描画まで実施する。
まずは「ゲーム名」と「手番」から、駒の色やその所有者を、定義する。

あたなはボードゲーム「 game_name 」のゲームマスターです。
プレイヤー「 user 」「 AI 」が game_name を開始します。
それぞれのプレイヤーの駒の種類(色など)を定義してください。
先手は「 turn 」です。
# example 1
## input
### ゲーム : オセロ
### プレイヤー : User, AI
### 先手 : User
## output
[{"player":"User", "piece":"黒"}, {"player":"AI", "piece":"白"}]

# example 2
## input
### ゲーム : チェス
### プレイヤー : User, AI
### 先手 : AI
## output
[{"player":"User", "piece":"白"}, {"player":"AI", "piece":"黒"}]
続いて、「ゲーム名」「駒の所有者」「手番」から、ボードゲームの初期状態をJSONで生成。

以下の条件で、ボードゲーム「 game_name 」の盤面の状況を、指定のJSONスキーマで出力して。
# 条件
## 1. プレイヤーは「 user 」または「 AI 」とし、先手は「 first_player 」とする
## 2. 各プレイヤーの駒の種類は「 piece_owner 」の通りとする
## 3. 「オセロ」などボードのサイズが決まっていないボードゲームの場合、5分ほどで終わるボードのサイズにすること

# JSON
"board": {
    "height": int,             // ボードのサイズ、[横, 縦](例:チェスは[8, 8])
    "width": int,
    "grid": [                       // ボードの状態を表現するグリッド
        {
            "position": "string",   // ボード上の位置(例:チェスの「e2」、オセロの「d4」など)
            "piece": {              // 駒の情報(駒がある場合のみ)
                "owner": "string",  // 駒の所有者( user  or  AI )
                "type": "string"    // 駒の種類(例:「黒石」、「白石」など)
            }
        }
    ]
}
最後に生成した初期状態を変数に保存し、その変数の値をもとに盤面を描画(HTMLで生成)させる。

描画した盤面は「メッセージの送信」でそのままユーザーに送信する。

手順4:ユーザーまたはAIが手を打つ(駒を進める)

いよいよ駒を動かしていく。
手番がユーザーのときは、単純にどんな手を打つか質問するだけ。
手番がAIのときは、「ゲーム名」「現在の盤面」「駒の所有情報」をもとに、次の一手を生成させる。

手順5:打った手をチェックする

ユーザーまたはAIが手を打ったら、その手が有効か無効か、また勝敗が決まったか決まっていないかを確認する。
「ボードゲーム名」「打った一手」「現在の盤面」「駒の所有者」をもとに、有効 or 無効(無効の場合は理由)、勝敗決定 or 未決定を生成。
※この判定が難しいらしく、4oでは全くうまくいかなかった。。。
あなたはボードゲーム「 game_name 」の審判です。
以下のJSONであらわされる盤面において、プレイヤー「 turn 」が一手を打ちました。
この一手が「有効か無効か」を判定してください。
また、この一手により「勝敗が決定したか」も併せて判定してください。
# プレイヤーがプレイ中のボードゲーム
 game_name 
# 各プレイヤーが使う駒の種類
 piece_owner 
# 現在の盤面
 board 
# 現在の盤面に対する、プレイヤー「 turn 」の手
 move 

# output
isValidMove : その一手が有効(true)か、無効(false)か
isDecisiveMove : その一手で勝敗が決したか(true)、否か(false)
reason : 有効でない場合の理由を日本語で表記
無効の場合はGo toで「現時点の盤面の描画」まで戻し、再度手を考えさせる。

手順6:勝敗の確認

先ほどの判定で、勝敗が決定しているかも確認しているので、それに合わせて分岐する。
勝敗が決まった場合は、勝者をユーザーに送信して終了。

手順7:盤面を進める

勝敗が決していないときは一手の情報をもとに盤面を進め、手番を入れ替え、盤面の描画まで戻る。
勝敗が決まっていない場合は、「ゲーム名」「現在の盤面」「駒の所有者」「手を打ったプレイヤー(ユーザーorAI)」「一手の情報」をもとに、手の通りに駒を動かした後の盤面情報を生成させる。
※ここも4oだとうまく動かないことが多かった。。

生成した盤面を変数に入れ、手番を入れ替え、Gotoで盤面の描画まで戻る。

以上で構築は完了。

動作確認

オセロ

まずはオセロ。こんな感じで盤面を作ってくれて、
駒を置くと、盤面が進む。
AIも手をきちんと考えてくれるので、普通に遊べる。
ちなみに角を普通にとらせてくれるので、レベルはそんなに高くないかも。

チェス

チェスも(若干見にくいけど)きちんと盤面を作ってくれる。
駒も普通に動かせて、(駒の上下は入れ替わっちゃったけど盤面は間違ってない)
AIも駒を動かしてくる。
取られるところに駒を動かすと、
普通にとってくる。

ということで、こちらも遊べそう。

チェッカー

AIのすごいところは、構築者がルールを知らないゲームも遊べること。チェッカーを要求すると、盤面を作ってくれる。
すごい!と思ってたら、残念ながら駒を動かすと盤面が崩れてしまう。。

ということで、限界はあるみたいだけど、ほぼプログラムなしで色々なゲームを作れるのはすごい。

コメント

タイトルとURLをコピーしました