完全なワールドステートを待ち時間ゼロで
16 プレイヤーの資源と人口。最大 1024 ユニットの HP・マナ、オーダー、攻撃中の相手、スキルのクールダウン、バフ、インベントリ。地面のアイテム、樹木、生産キュー、昼夜。ランタイムが共有メモリにプッシュし、1 回の読み取りは約 0.4 ms。
War3AI はゲームを Agent のための API に変えます。50 ms ごとにマップ全体の完全な状態をプッシュし、セマンティックコマンドは約 1 フレームで反映、すべてにレシートと理由コードが返ります。ドキュメントを Claude、GPT、Gemini、Qwen などの Agent に渡せば、Bot を書き、対戦に出し、結果を読み取り、自ら改善していきます。
Windows 10/11 · Warcraft III 1.27a · start.bat をダブルクリック、あとは自動でインストール
ヒューマン。ヒーローの HP が 40% を切ったら本拠地に撤退。夜になったら、兵が 3 体以上いれば最寄りのクリープキャンプを攻撃。
llms.txt と api.json を読み、night_raider.py を生成しました。使っているのは検証済みの API 8 個だけです。
from openwar3 import Bot
class NightRaider(Bot):
def on_tick(self, g): # 毎秒約 5 回
halls = g.my_buildings({"htow", "hkee", "hcas"})
army, camps = g.my_army(), g.creeps()
if not halls:
return
home = halls[0]
with g.batch(): # このティックのコマンドをまとめて送信
for h in g.my_heroes():
if h.hp < h.hp_max * 0.4: # ヒーローの生存
g.move(h, home.x, home.y)
if g.is_night() and len(army) >= 3 and camps:
camp = min(camps, key=lambda c: g.path_distance(home, c) or 1e9)
g.attack_move(army, camp.x, camp.y) # 夜にクリーピング
def on_event(self, g, ev):
if ev.kind == "production.done" and ev.owner == g.me():
print("完了", ev.done_code, f"{ev.value:.1f}s") コードを書ける、または JSON を出力できるあらゆるモデルと Agent に対応
数値は 1.27 のテストインスタンスでの実機測定(2026-09-23 / 24)によるものです。測定方法は プラットフォーム · パフォーマンス を参照してください。
プログラミングができなくても大丈夫。あなたはどう戦ってほしいかを伝えるだけ。コードを書き、対戦に出し、結果を見て、満足いくまで直すのは Agent の仕事です。
「ヒューマンで、まずアークメイジを出す。兵舎 2 つでフットマンとライフルマンを出す。12 体たまったら相手の拡張を攻める。ヒーローの HP が 30% を切ったら撤退。」
llms.txt、api.json、マニュアルを渡します。API はゲーム内の呼び方(4 文字コード、スキル名)を使っているので、モデルは読めばすぐに理解できます。
tools/play.py がゲームの起動、注入、ゲーム開始、Bot の起動まで行います。ゲーム速度、種族、難易度、フェアモードはすべて引数で指定できます。
すべてのコマンドにレシートと理由コードがあり、イベントストリームにはすべてのダメージ、キル、生産が記録されます。Agent はそれをもとに問題を特定し、コードを直し、もう 1 戦します。
観測は待ち時間ゼロ、コマンドにはレシート、結果にはイベント。モデルに必要なのは、まさにこうした構造化され、検証でき、自己修正につながるフィードバックです。
16 プレイヤーの資源と人口。最大 1024 ユニットの HP・マナ、オーダー、攻撃中の相手、スキルのクールダウン、バフ、インベントリ。地面のアイテム、樹木、生産キュー、昼夜。ランタイムが共有メモリにプッシュし、1 回の読み取りは約 0.4 ms。
移動、攻撃、採集、建設、訓練、スペル使用、スキル習得、蘇生、アイテム使用、購入……受理されたかどうか、されなかったならなぜか、同じフレームでわかります。
ユニットの出現 / 死亡、オーダー変更、ヒーローのレベルアップ、アイテムの出現。エンジンレベルの 1 回ごとのダメージ(発生源、攻撃タイプ、アーマー適用前のダメージ)と生産完了。相手のものも含みます。
with g.batch() 内のコマンドは 1 バッチにまとめて送信されます。実測で 8 件の移動が 68 ms から 6.5 ms に短縮。
stats / time_to_kill はゲーム付属の相性表とリアルタイムのテクノロジーを使用。path_distance / walk_path はエンジンの地形グリッド上で A* を実行します。
視界内のユニット、アイテム、生産、イベントだけが見えます。last_seen が霧の中の敵を記憶します。アリーナのルールもこれと同じです。
api.json はコードから生成され、各 API に実測ステータス、レイテンシ区分、内部メカニズムを記載しているので、モデルが推測する必要はありません。llms.txt / llms-full.txt で Agent はサイト全体のドキュメントを一度に読めます。
ランタイムはオリジナルのゲームに注入され、ゲームスレッド上でワールド全体を収集し、コマンドを実行し、結果を返します。あなたの AI は、バージョン付きの W3P プロトコルを通じてランタイムと対話します。Python SDK でも、共有メモリを読み書きできる任意の言語でも構いません。
ファサードはたった 2 つのクラス。Bot がティックを担当し、Game が観測と操作を担当します。ユニットは 4 文字コード、スキルはオーダー名で、ゲーム内の呼び方と同じです。
None、0 ではない queue='after' from openwar3 import Bot
class FocusFire(Bot):
"""最も近い敵ではなく「最も早く倒せる」敵に集中攻撃し、瀕死の兵は本拠地へ下げる。"""
def on_tick(self, g):
army, halls = g.my_army(), g.my_buildings()
foes = [e for e in g.enemies(fighters_only=True) if e.visible_to(g.me())]
if not army or not foes or not halls:
return
home = halls[0]
# 相性表、アーマー、攻撃/防御アップグレード、目標のリアルタイム HP を考慮
target = min(foes, key=lambda e: g.time_to_kill(army, e) or 1e9)
with g.batch(): # 数十件のコマンドでもゲームスレッドを待つのは 1 回
for u in army:
if u.hp < u.hp_max * 0.35:
g.move(u, home.x, home.y) # 瀕死のユニットを後退
elif (t := g.current_target(u)) is None or t.handle != target.handle:
g.attack(u, target) # まだ攻撃していないユニットにだけ命令 brains/examples/micro_bot.py(集中攻撃、瀕死ユニットの後退、ヒーローの生存、夜のクリーピング)を参照してください。 あなたは Warcraft III 1.27 用の AI(Python)を書きます。api.json に載っている Game メソッドだけを使い、
存在しないメソッドをでっち上げないでください。openwar3.Bot を継承し、on_start(g) と on_tick(g) を実装します。
ルール:
- on_tick は毎秒約 5 回呼ばれるので、高速に処理すること(中で sleep しない)。
- 読めない値は None で、0 ではない。使う前に判定すること。
- コマンドはレシートを返す:`if r:` ならエンジンが受理した。受理されなかったときは r.reason に理由が書かれている。
- 特定の敵を攻撃するには g.attack(兵, 敵) を使う。見えない目標は拒否される(1001)。
- ヒーローが死んだら g.revive(祭壇) で蘇生する。もう 1 体訓練することはできない。
- 1 ティックで多くのコマンドを出すときは with g.batch(): で包む。
希望する戦術:
ヒューマン。序盤はピーザント 5 体で金を採掘、1 体で伐採。まずアークメイジを出す。兵舎 2 つでフットマンとライフルマンを出す。
12 体たまったらヒーローと一緒に相手の拡張を攻める。ヒーローの HP が 30% を切ったら本拠地に撤退。 >>> r = g.train(barracks, "hfoo")
>>> bool(r), r.reason
(False, 'rejected(人口不够)')
>>> r = g.attack(footmen, grunt_in_fog)
>>> r.verdict, r.reason
(1001, 'rejected(目标看不见(在迷雾/黑区里))')
>>> r = g.move(footmen, 1200, -800)
>>> bool(r), r.exec_us # このコマンドがゲームスレッドで使った時間(µs)
(True, 6)
>>> g.can_do(altar, "Hamg") # 命令前にエンジンに問い合わせる:185 = 祭壇がヒーローを蘇生中
185 // レフェリーが毎ティック Bot に送る観測(その Bot の視界内のものだけ)
{"t": "obs", "tick": 57, "gameMs": 11400, "me": 1,
"res": {"gold": 320, "lumber": 150, "food": [18, 30]},
"units": [
{"id": 101, "type": "hfoo", "owner": 1,
"x": -4500, "y": 2200, "hp": 380, "hpMax": 420}],
"visibleEnemies": [
{"id": 733, "type": "ogru", "owner": 2,
"x": -3900, "y": 2500, "hp": 700}],
"deadlineMs": 180}
// Bot が返すアクション(どの言語、どのモデルでも生成可能)
{"t": "act", "tick": 57, "actions": [
{"do": "attack", "unit": 101, "target": 733},
{"do": "train", "unit": 5, "code": "hfoo"},
{"do": "cast", "unit": 7, "spell": "thunderbolt", "target": 733}]} 5 つは今日から使え、1 つは開発中です。これらは排他的ではありません。同じゲームの中で、Agent が書いた Bot が実行し、ローカルモデルがアドバイザーを務め、別のモデルがユニットのセリフを担当し、さらにあなたが Claude Code からいつでもひと言指示を挟む、といった組み合わせも可能です。
Claude Code、Cursor、Codex、ChatGPT……がドキュメントを読んで bot.py を書き、対戦に出してレシートとイベントを見て、また直します。最も手早く始められる方法で、プログラミングの知識は不要です。
数ゲーム秒ごとに局面の要約をモデルに渡し、厳密な JSON を受け取ります。診断、ワーカー配分、優先して出すもの、この 1 分間の構え。ルール層がホワイトリスト + クランプを通してから実行します。
任意のユニットが任意の役柄で頭上に吹き出しを出し、ローカル LLM のストリーミング出力とつながります。農民の井戸端会議、ヒーローの掛け合い、戦況の実況。
Claude Code、Claude Desktop、または MCP に対応した任意のクライアントにサーバーを 1 つ登録するだけで、LLM が局面を見る、コマンドを出す、画面上でプレイヤーに話しかける、カードを出してプレイヤーに尋ねる、スクリーンショットで画面を見る、といったことを直接行えます。先にコードを書く必要はありません。
WebSocket / JSON ゲートウェイが公開 API をそのまま外に出します。JS、C#、Go、ブラウザのページ、別のマシン上のプログラムから、局面を見る、コマンドを出す、イベントを購読する、ゲームにボタンを置く、といったことができます。選手ロールは自分だけを指揮し、自分の視界だけを見ます。
アリーナ:レフェリーが視界で観測をフィルタリングし、ユニットの所有権をチェックし、ゲーム時間に合わせてティックを刻み、2 つの外部 AI が同じゲームで勝敗を決めます。どの言語、どのモデルでも直接対戦できます。
画面に自分だけの UI を描けば、描いたボタンはクリックでき、ホットキーにも反応します。マップ作者が使える関数をすべて外部から呼び出し、RPG マップでは一緒に戦ってくれる AI の仲間を連れて行けます。新しい遊び方を丸ごと MOD として書けば、AI スキームと同じようにワンクリックで切り替え、気軽に共有できます。
テキストボックス、パネル、プログレスバー、画像、地形に沿った円、矢印付きのルート。ユニットに追従し、CJK フォント、角丸、半透明も自由自在。描くのは自分の画面だけなので、マルチプレイでも安全です。
マップ作者が使える関数を名前で直接呼び出せます。ユニット生成、エフェクト、パネル、ダイアログ、サウンド、カメラ、霧……Farsight コンソール、コマンドライン、HTTP、Python のどれからでも使え、チャットコマンド、ボタンメニュー、矢印キーにもつなげられます。
あなたについて来て、狩りを手伝い、HP が減ったら回復し、話し相手にもなります。セリフはローカル LLM につなげられます。同盟、自軍、マップのユニットを引き継ぐ、会話のみ、の 4 つのモード。カスタムユニットの名前はマップから直接読み取ります。
1 つの AI に 1 つのフォルダー。ワンクリックで切り替えられ、対戦中のゲームも別の AI に引き継げます。zip をエクスポートすればそれが共有。他人のスキームは信頼を確認してから実行し、スキームごとの戦績は自動で集計されます。
描いたボタンや選択カードはクリックでき、ホバーで自動的にハイライトします。ホットキーの登録、地面のクリックによる位置指定、マウスが指している場所の取得も可能。プレイヤーが誰を選択したか、どのスキルを使ったか、チャットで何を打ったかも、すべてイベントストリームに入ります。ボタンはマウスカーソルの下に描かれ、そのクリックはゲームには届きません。
プレイするのはあなた、お題を出すのは MOD。序盤の配置、時間に応じた敵の出現、レベルアップ時の 3 択、ホットキーでのウェーブ呼び出し、地面をクリックしての塔の設置、勝敗判定。openwar3.Mod を継承していくつかの関数を書くだけです。ヒーローローグライクとエンドレスディフェンスの 2 つのサンプルを同梱。
プロセス間通信そのものは遅くありません。遅いのは「リクエストごとにメッセージポンプを 1 回待つ」ことと「マシン全体で 1 つのロック」です。ファストレーンでは各クライアントが専用のレーンを持ち、ロックなしで、ゲームスレッドのイベントディスパッチ内でまとめて実行されます。
ゲームの起動、AI の思考の確認から、振り返りや配信の実況まで、すぐに使えるツールがそろっています。
P0 〜 P3、P5、ゲームプレイ拡張、ゲートウェイと MCP は 1.27 で動作を確認済み。次は複数バージョン対応とアリーナです。
ローカル、LAN、自分で立てたゲーム。ディスク上の Game.dll は変更せず、Blizzard のファイルも一切配布しません(ゲームデータはあなた自身のゲームから抽出します)。Battle.net やアンチチートを備えたサーバーでは使用できません。