0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Jev API で DOOM をプレイさせる — criteria と自動探索の実験

0
Last updated at Posted at 2026-09-22

はじめに

※生成AIで作成された記事です。

参考: TypeSafe AI は Jev のローンチ時に、DOOM をプレイする公式デモを公開しています。
本記事はその発想を自分で組み直し、「criteria(自然言語の行動指針)」「判断の可視化」
「自動探索ループ」を追加したものです。Jev API 自体は公式デモと同じものを使っています。

TypeSafe AI の Jev に古典 FPS「DOOM」をプレイさせる実験をしています。クラウド API 経由で 1 判断 250ms、家庭用 PC(GTX 970、RAM 16GB)でリアルタイムに動作します。

本記事では、30 秒の短い録画を例に、Jev がどう状態を受け取り、どう行動を選んでいるかを紹介します。
image.png

動作環境

項目 内容
OS Ubuntu 24.04 LTS
CPU Intel Core i5
GPU NVIDIA GeForce GTX 970 (4GB VRAM)
RAM 16GB
Python 3.10.21 (conda env vizdoom)
ViZDoom 1.3.1
WAD freedoom2.wad (MAP01, skill 3)

構成

[ViZDoom] --(状態)--> [Python] --(テキスト)--> [Jev API]
                          ↑                        |
                          |                    (行動選択)
                          |                        ↓
                       [QUAD SYSTEM ログ]      [ボタン入力]
  • ViZDoom 1.3.1 で DOOM を起動(freedoom2.wad, MAP01, skill 3)
  • Jev API(TypeSafe AI)に状態をテキストで送信
  • Jev が返した行動(move_forward, attack など)を ViZDoom のボタンに変換
  • 1 判断あたり 8 tic(frame_skip=8)進む

Jev に渡している状態テキストの例

You are playing DOOM. Your goal is to progress through the level and survive.
Balance offense and movement. Do not attack blindly when no enemy is visible.
Current state: var0=100, var1=0, var2=50, var3=0, red_mean=38.3,
enemy_visible=no enemy_count=0, front_blocked=no, took_damage=no,
damage_side=none, stuck_timeout=no,
open_left=far, open_center=far, open_right=far, item_visible=no
[Memory: visited=1cells, keys=none, max_dist=0, dead_ends=0]

各フィールドの意味は以下のとおりです。

フィールド 意味
var0 HP
var1, var2, var3 ViZDoom のゲーム変数(武器、弾薬など)
red_mean 画面中央の赤成分平均(敵検出の補助)
enemy_visible labels_buffer による敵検出
enemy_side 敵が画面の左右どちらにいるか
front_blocked 前方が壁かどうか
took_damage 直前の判断以降に被弾したか
damage_side 被弾方向(left / right / back / front)
stuck_timeout 同じ場所に 80tic 以上留まっているか
open_left/center/right 深度バッファから算出した 3 方向の開け具合(far / mid / near)
item_visible 取得可能アイテムの検出
Memory 訪問セル数、鍵、最大距離、行き止まり数

行動指針(criteria)も自然言語

Jev には「行動指針」も渡しています。たとえば move_forward には以下を指定:

Only advance when open_center=far or open_center=mid.
Do NOT advance if open_center=near;
instead turn toward the side that is far.

これで「前が塞がっていたら進まない」を表現できます。プロンプトエンジニアリングだけで行動を制御できるのが、この構成の面白いところです。

他の行動にも、それぞれ自然言語で条件を書いています。

"attack": "Fire whenever enemy_visible=yes. Do not wait for centering.",
"move_backward": "Retreat only when health < 30 AND enemy_visible=yes.",
"use": "Select 'use' whenever front_blocked=yes. Try 'use' before turning away.",

プレイ中の動画で見えるJevの判断ログ

image.png

画面下の QUAD SYSTEM オーバーレイに、Jev の判断理由がリアルタイム表示されます。

  • 判断ごとに Reason: が更新される
  • 敵の検出(enemy_visible, enemy_side)
  • 被弾方向(damage_side)
  • スタック検出(stuck_timeout)

オーバーレイは Python + Tkinter で別プロセスとして起動し、/tmp/jev_status.txt 経由でゲーム本体と通信しています。

現状の課題

項目 値
30 秒での撃破数 4 体
最終 HP 36 / 100
MAP01 の敵総数 18 体
全滅達成 未達(探索時間が足りない)
stuck_timeout=yes 発生率 約 33%
画面外の敵からの被弾率 65%

主な問題

  1. 探索時間の不足
    MAP01 の EXIT 到達には最低 2〜3 分必要。現在のエピソードタイムアウトでは短すぎる

ViZDoom では1回のプレイを「エピソード」と呼び、制限時間(tic 単位)を設定できます。
1 tic = 1/35 秒(DOOM の標準)。frame_skip=8 なので、1判断あたり 8 tic 進みます。

  1. スタック頻発
    同じ場所に 80tic 以上留まるケースが 3 回に 1 回

  2. 画面外被弾
    被弾の 65% は、Jev が敵を視認していない状態で発生

今後の予定

  • criteria の自動探索
    Gemini が提案 → Claude Code が実装 → 5 時間走行で評価
  • 判断ログのデータセット化
    (状態テキスト, Jev の選択) のペアを蓄積
  • 長時間無人運転
    5 時間で約 7〜8 criteria を評価

まとめ

  • クラウド LLM(Jev)で古典 FPS をリアルタイム操作
  • 状態も行動指針も自然言語で記述
  • 判断理由を可視化することで、研究・デバッグが容易
  • 家庭用 PC で動作、特別な GPU は不要

※TypeSafe AI の公式デモで既に「Jev が DOOM をプレイする」は示されています。
本記事の独自性は、criteria による行動制御、判断の可視化、自動探索ループの3点です。

参考


環境: Ubuntu 24.04 / GTX 970 / Python 3.10.21 / ViZDoom 1.3.1

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?