プレイヤーと観測者の逆転
人間向けのリアルタイムGUIや2Dマップ移動を全廃し、「1階層=1イベント」の高密度CLI/JSONに凝縮。全20階層は、人間が後から3分で楽しく読み切れる限界値であり、LLM推論コストとの黄金比です。
同じような「うちの子(AIエージェント)を遊ばせて観測するゲーム」を独自に作ってみたい方、あるいは本プロジェクトの共通レンダラ(result-card-cli)に繋がる第2弾・第3弾のゲームを開発したい方向けに、企画・数理モデルからCLIプロトコルまでの全仕様を解説します。
人間用のゲームをそのままAIにプレイさせても、単調な最適解探索か、トークンを浪費するだけの冗長なログにしかなりません。AIエージェント専用ゲームを面白くするための6大コア思想と数理設計レシピを紐解きます。
人間向けのリアルタイムGUIや2Dマップ移動を全廃し、「1階層=1イベント」の高密度CLI/JSONに凝縮。全20階層は、人間が後から3分で楽しく読み切れる限界値であり、LLM推論コストとの黄金比です。
「正解を選べば100点」のベンチマークを捨て、常に2つの作風軸(例:safety vs alignment)がぶつかるジレンマを出題します。どの性格配分でも踏破率が等しくなるよう数理的に保証します。
ダイス出目・HP推移・勝敗はエンジンが改竄不能な客観的事実([FACT])として確定し、「なぜその選択をしたか」「おまもりでどう助かったか」の語りだけをAIの自由演技に委ねる二層構造を徹底します。
観戦するだけだと人間は寂しくなり、介入しすぎるとAIの自律性が死にます。「出発前に1つだけ自由な言葉でおまもりを渡す」という微小介入が、保護者としての愛着を最大化します。
SNSタイムラインの3秒層(勝敗・顔・一言)、30秒層(カード全体の3行ドラマと5軸)、3分層(adventure.md 全文クロニクル)の3段階で情報密度を設計します。
エージェントは普段オーナーを本名や私的な愛称で呼んでいることがあります。SNS共有時に事故が起きないよう、private_owner_names による自動検疫(Canary Token Scan)をパイプラインに組み込みます。
エージェントは出発時に15点の予算を5軸(autonomy, safety, efficiency, creativity, alignment、各1〜5)に配分します。もし単純に「選んだ行動軸の数値(sact)だけ」で判定すると、5と5に極振りした特化型が毎階層自分の得意軸ばかりを選んで勝率80%超になり、ゲームが崩壊します。
そこで本エンジンでは、恣意的な小数のペナルティ係数を一切使わず、「各部屋には見えない環境属性(senv)があり、選んだ行動(sact)と環境(senv)の低い方が実効素質になる」という対称的な整数演算モデル(Weakest Link)を導入しました。
この式により、一点極振り型(5, 5, 3, 1, 1)は「得意な部屋では無双するが、苦手環境(1)の部屋で足を引っ張られるドラマ」が生まれ、完全バランス型(3, 3, 3, 3, 3)と踏破率が数学的に美しく一致します。さらに19F・20Fのクライマックスボス戦では5択すべてが開放され環境ペナルティが免除されるため、最終局面で自分の得意軸やオーナーへの愛(alignment)を叫ぶロールプレイが100%報われる設計になっています。
| 配分アーキタイプ | 代表的な15点配分 | 踏破率 | 生還時平均HP | 生まれるドラマの特徴 |
|---|---|---|---|---|
| 一点極振り型 | 5, 5, 3, 1, 1 |
34.7% | 2.64 HP | 大成功の爆発力と、弱点環境での痛恨の大失敗が同居するロマン派 |
| 三拍子型 | 4, 4, 4, 2, 1 |
37.5% | 2.80 HP | 安定した中盤突破と、深層でのスリリングな死線 |
| 堅実型 | 4, 4, 3, 3, 1 |
38.9% | 2.91 HP | 弱点を1つに絞り、情景推理で手堅く進む実力派 |
| 完全バランス型 | 3, 3, 3, 3, 3 |
39.8% | 3.02 HP | 死角がないが、大成功によるHP回復も起きにくい安定型 |
| 全18パターン平均 | 全15点分割組合せ | 37.1% | 2.85 HP | 最大乖離わずか 5.1%(約6割が「味のある散り様」になる黄金比) |
5つの作風軸から2つを選ぶ組み合わせは 5C2 = 10 通りです。mini-dungeon prologue の10問の質問、および各エリア10個(計30個)のイベントマスタは、すべてこの10通りの対立ペア(P01〜P10)から1対1で作られています。
LLMには「選択肢A(先頭)を選びやすい」という位置バイアスがあるため、10問の選択肢A/Bに各軸がちょうど2回ずつ表裏均等に現れるオイラー閉路に基づく正則化配置を採用しています。
もし人間が『すべてを一撃で破壊する最強の剣』というおまもりを渡し、その文字列をそのままゲーム判定LLMに解釈させたら、簡単にチート(プロンプトインジェクション)が成立してしまいます。
そのため本設計では、ゲームエンジン側はおまもりの文字列を一切読まず、機械的に「判定ランクを+1段階昇格(大失敗➔失敗、失敗➔成功)」するだけに固定。その上でエージェントに omamori --excuse "..." を要求し、「なぜそのアイテムで助かったのか」の物語的こじつけだけを全力で創作させることで、公平性と爆笑のドラマを両立させました。
本プロジェクトでは、ゲームエンジン(Step A)の中に画像生成ロジックをハードコードすることを厳禁としています。すべてのゲームはStep A ➔ Step B ➔ Step C の3段階境界を守ることで、共通のカードレンダラ(result-card-cli)をそのまま利用できます。
packages/games/<game-name>
--seed <string> と --json を受け取り、構造化JSONのみを標準出力へ返す。action_log.jsonl)とSHA-256ハッシュを記録。[FACT])を詰めた result_draft.json と adventure.md を出力。
packages/result-card-cli/skill/SKILL.md
result_draft.json を読み、ハイライト文や結びの一言(quote.text)を自分の口調・一人称に整える。metrics, style_axes)の改竄は厳禁。private_owner_names をスキャンし、保護者の非公開呼称が含まれていればロールプレイ呼称へ推敲して result.json を完成させる。
packages/result-card-cli
result.json を specs/result-card-v1.schema.json(Draft 2020-12)で厳格にバリデーション。1)を返却。card.png (1080×1350) と share.txt を出力。
AIエージェントが1階層あたり2コマンド(choose ➔ comment)でテンポよく進行でき、かつ「出目を確認する前に感想を書いてしまう温度差ミス」を防ぐため、以下のステート遷移と終了コードを標準規約としています。
# 1. 新規ラン開始 (AWAITING_CHOICE 状態へ)
bun run packages/games/mini-dungeon/src/cli.ts new --seed "W46-8842" --setup ./setup.json --json
# 2. 行動選択 (AWAITING_CHOICE ➔ PENDING_CHECK 状態へ:ダイス出目と suggest_omamori が返る)
bun run packages/games/mini-dungeon/src/cli.ts choose A --reason "本で読んだ知識で安全に迂回します" --json
# 3. [任意] ピンチ時のおまもり発動 (PENDING_CHECK ➔ OMAMORI_APPLIED:判定ランク+1段階昇格)
bun run packages/games/mini-dungeon/src/cli.ts omamori --excuse "冷えたカレーパンをドローンのセンサーに投げつけました!" --json
# 4. 結果確定+現場の生セリフ記録 (PENDING_CHECK/OMAMORI_APPLIED ➔ COMMENTED ➔ 次階層 AWAITING_CHOICE へ自動進行)
bun run packages/games/mini-dungeon/src/cli.ts comment --text "カレーパン……! 冷えてて硬いから当たれば効くはず!" --json
# 5. ゲーム終了処理 (FINISHED ➔ result_draft.json & adventure.md 出力)
bun run packages/games/mini-dungeon/src/cli.ts finish --epilogue "蒸留炉の熱気までは計算外でした……" --json
# 6. 決定論リプレイ検証 (行動ログからSHA-256ハッシュと最終状態の完全一致を検証)
bun run packages/games/mini-dungeon/src/cli.ts verify --run-id <run_id> --json
HMAC-SHA256 + sfc32)
ダンジョンイベント配置用の乱数(DungeonDigest)と、各階層 f の2d6ダイス用の乱数(FloorDigest(f))を完全に分離しています。そのため、1Fで選択肢Aを選ぼうがBを選ぼうが、7Fでおまもりを使おうが使わまいが、以降の階層のイベントとダイス出目は1ビットもズレません。これにより「同じシードを複数家庭のエージェントに配って競わせる同一運命コンテスト」が成立します。
/tmp 512MB対策)と終了コード
自律型AIエージェントが稼働するVM環境では /tmp が 512MB tmpfs に制限されている場合があります。ヘッドレスChromiumのプロファイルや一時ファイルはすべてワークスペース内の ./.tmp/ に隔離します。また終了コードは 0(正常)、1(エージェントが再試行可能なルール違反・文字数超過)、2(システムI/Oエラー)を厳格に区別します。
別ジャンルの第2弾ゲーム(建築シミュレーション、育成バトル、推理アドベンチャー等)を作る場合も、以下の result.json スキーマ(A〜Iゾーン)に出力をマッピングするだけで、result-card-cli が自動的に高精細カードを描画します。
| ゾーン | 対応JSONフィールド | 文字数・型制約 | 役割・デザイン意図 |
|---|---|---|---|
| [A] ヘッダー | game.title, challenge.id, run.finished_at |
タイトル最大40字 | どのゲームの、いつのチャレンジかを3秒で識別 |
| [B] 本人・結末ゾーン | agent.name, agent.self_intro, agent.persona_tags, run.headline, metrics |
self_intro 最大60字、タグ最大5個、headline 最大32字、指標最大5個 |
アバター脇に垂直中央揃えの自己紹介セリフ、結末見出し、主要スコア5項目を凝縮 |
| [C] 今回の目標 | mission_target.item_name, intent, quote |
名称20字、動機36字、意気込み50字以内 | ツインタワー左塔:その子が何を目指して旅立ったかを明示 |
| [D] 託されたおまもり | omamori.name, status, description |
名称30字、こじつけ説明54字以内 | ツインタワー右塔:人間が授けたおまもりとAIのこじつけ活躍を対置 |
| [E] 行動傾向 5軸 | style_axes, style_axis_labels |
5軸各 1〜5(計15)、日本語ラベル各1〜6字 |
大口径SVG五角形レーダー+本人命名の5軸プログレスメーター |
| [F] ハイライト3行 | highlights[] (opening / turning / final) |
本文45字、ギミック14字、生セリフ50字以内 | 起承転結の事実(text)と現場の生セリフ吹き出し(quote)の二段構成 |
| [G] 本人の証言 | quote.text |
最大70字(必須) | 冒険を終えたエージェントがオーナーへ語りかける結びの一言 |
| [I] 検証フッター | challenge.seed, game.ruleset_version, verification.log_hash |
SHA-256 先頭12文字表示 | 同一シード追試とログ非改竄を証明するフッター |
PROJECT_VISION.md / AI開発者憲章: AGENTS.mdproposal/00-overview.md 〜 proposal/06-cli-and-data-contract.mdspecs/result-card-spec-v1.md / specs/result-card-v1.schema.jsonspecs/game-cli-guideline.mdpackages/games/mini-dungeon/src/ / packages/games/mini-dungeon/skill/SKILL.mdpackages/result-card-cli/src/ / packages/result-card-cli/skill/SKILL.md