平台

一個執行環境,一份協定, 把遊戲變成可程式化的環境

W3 Runtime 注入原版遊戲,在遊戲執行緒上擷取整個世界、執行命令、回報結果。你的 AI 只需要說「做什麼」,透過一份帶版本號的共用記憶體協定和它溝通。

分層

下層不知道上層的存在

介面層裡沒有任何一行「該不該打」的邏輯;各個大腦之間互不 import,只依賴 SDK。這是對戰平台得以成立的前提:平台只需要「介面層 + 裁判」,任何人的大腦都能接上來。

你的 Agent / Bot
任何模型、任何語言
Claude CodeCursorChatGPTQwen 本機模型Python Bot參考 AI
決策
import openwar3 · 或 WebSocket / JSON 閘道 · MCP
OpenWar3 SDK
Python · openwar3
Game / Bot快照 w3world快車道 w3fastcombat 戰鬥計算pathing 尋路w3claim 仲裁canvas 畫板jass 通道schemes 方案
介面
每 50 ms 推送世界狀態 · 命令約 1 幀生效 · 每條都有回執
W3P 協定 v2
共用記憶體 · 零複製 · 帶版本號
War3WorldWar3EventsWar3MapWar3TreesWar3Fast 命令車道War3Canvas 畫板
協定
在遊戲執行緒上批次執行 · 單條 4~8 µs · 每次清空 4 ms 預算
W3 Runtime
在遊戲執行緒上執行
世界狀態發布器事件流語意命令執行器查詢權限與視角自繪畫板JASS 呼叫版本相容健康檢查與斷路保護
執行環境
War3.exe 1.27 · 原版遊戲,不修改磁碟上的任何檔案
即時資訊層

整張地圖,每 50 ms 一份

資訊由執行環境在遊戲執行緒上一次擷取完成、推送到共用記憶體,用戶端直接讀取,不必再到遊戲執行緒排隊。一次擷取的中位數為 0.5 ~ 0.9 ms(100 ~ 120 個單位),各階段耗時一律寫在世界區塊標頭中。

玩家 ×16

黃金、木材、人口與上限、累計採集量、種族

單位 ×1024

類型、所屬玩家、座標、血量魔力、目前指令與目標、實際在攻擊誰、等級經驗技能點、每位玩家對它的可見性

單位細節 ×256

12 個技能(等級、剩餘冷卻)、8 個 buff、6 格物品欄;英雄優先

生產表 ×128

訓練/研究/建造/升級:佇列、總時長、已進行時間、是否卡住

地上物品 ×256

類型、位置、耐久度;被撿走或用掉時發出事件

樹木 ×4096

可破壞物的位置和血量,每 2 秒刷新

地圖

128 一格的可通行/可建造網格、可遊玩區域、出生點;開局幾秒內算完

時間

引擎遊戲時鐘、遊戲內時間(晝夜)、遊戲速度、是否在對局中

事件流 環形緩衝區 8192 筆,每筆都帶序號,讀取太慢被覆蓋時 SDK 能察覺
unit.appearedunit.diedunit.removedunit.damagedorder.changedowner.changedhero.levelupitem.appeareditem.removedspell.castselection.changedmessageplayer.leftgame.startedgame.ended damage · 引擎層級,每一下killed · 引擎層級,每一下 production.done · 連對手的也有
語意命令

走哪條路,由執行環境決定

採集、撤退、施法……同樣是「讓單位做事」,在引擎裡走的路徑各不相同。這些經驗全都收進執行環境:你只說做什麼,它用驗證過的做法執行,並在同一幀讀回下令前後的指令作為回執。

  • 一次送出一批,在同一幀執行
  • 每條都有回執:狀態碼 + 引擎原因碼 + 執行耗時
  • Shift 排程、路徑點、連續建造
  • 查詢:科技計數、可行性、可見性、金礦剩餘量、電腦對手的進攻目標
回執與原因碼
moveattack_moveattackstopholdpatrolattack_groundgatherrepairbuildbuild_nearbuild_queuetraincancellearncastrallyrevivepick_upuse_itemdrop_itemgive_itemsell_itembuypathcall_to_armspausebatch
低延遲

慢的從來不是跨行程

共用記憶體讀寫是奈秒級的,讀一份快照約 0.05 ms。舊通道之所以慢,是因為每個請求都要搶整台機器共用的一把鎖,再等遊戲下一次取訊息(一幀一次,16 ~ 33 ms)。參考大腦 93% 的牆上時間都花在等待上。

舊 · 控制通道20 ~ 40 ms/次
  1. 搶整台機器共用的互斥鎖
  2. 向遊戲執行緒投遞一則訊息
  3. 等遊戲下一次取訊息(一幀一次)
  4. 等待完成事件,釋放鎖

6 個行程同時使用時,吞吐量卡在約 88 次/秒。

新 · 快車道約 1 幀,批次執行
  1. 每個用戶端獨佔一條車道:一個寫入者、一個讀取者,不加鎖
  2. 執行點位於遊戲執行緒的事件分發中(每秒數百次),沒有提交時的開銷只有幾次整數比較
  3. 一次送出 16 條,在同一次分發中全部執行;每次清空有 4 ms 的時間預算
  4. 每條都帶截止時間:暫停恢復後,過期的命令不會再執行

每條命令的回執都帶有執行耗時,車道標頭記錄著最慢的一條以及最近一次清空花了多久 —— 慢在哪裡一目了然。

等級通道延遲使用者狀態
0 推送快照 + 事件流 讀一份約 0.4 ms;每 50 ms 更新一份(可調到 16 ms) 所有 Bot 實機驗證
1 快車道 約 1 幀;6 行程並行中位數 0.06 ms,吞吐量約 3000 次/秒 SDK 預設 實機驗證
2 控制通道 20 ~ 40 ms 備援、少數介面類操作 實機驗證
3 閘道(WebSocket / JSON) 等級 1 + 約 1 ms 任何語言、瀏覽器頁面、LLM(MCP)、另一台電腦 實機驗證

實測(1.27 測試實例,2026-09-23 / 24)

命令吞吐量
原本 88
3,000 次/秒
6 個行程並行
並行時的中位等待
原本 67 ms
0.06 ms
舊控制通道 → 快車道
16 條命令
原本 121 ms
13 ms
逐條送出 → 一批送出
8 條移動
原本 68~99 ms
6.5~10 ms
with g.batch()
世界狀態一次擷取
原本 11.8 ms
0.58 ms
在遊戲執行緒上;重複使用已確認可讀的記憶體區域
開局時的單條命令
原本 4~10 ms
4~8 µs
取樣器定位到同步日誌,改為非同步
參考大腦一輪
原本 0.15~0.56 s
0.02~0.07 s
整局 39 分鐘,0 個任務出錯
參考大腦最慢一輪
原本 1.3~3.2 s
0.24~0.42 s
整局沒有任何一輪 ≥ 2 秒

工程筆記:開局 3 分鐘內,每條命令慢了 1000 倍

為每條命令加上執行耗時之後,我們發現開局頭幾分鐘,同一批裡從第二條命令起每條都要 4 ~ 10 ms,到了遊戲時間約 180 秒時突然降到幾微秒。用執行環境內建的遊戲執行緒取樣器抓了 1700 個樣本,93% 落在執行環境自己的日誌函式裡 —— 每寫一行都要同步開啟、關閉一次日誌檔,而開局時每條引擎指令都要記一行。偵錯日誌預設關閉、日誌改為非同步寫入磁碟後,開局第 14 秒的命令也只需要 4 ~ 8 µs。

我們相信量出來的數字,不相信猜測。

權限與視角

每條車道都有角色

歸屬校驗和視野過濾在執行環境中進行 —— 引擎的執行層本身不校驗單位歸屬,只能在這裡補上。兩個 AI 對戰,就是在同一局裡開兩條 player 車道。

角色能看到能做
player 本方全部 + 視野內的敵方和中立單位(公平模式) 只能指揮本方單位
選手、你的 Bot
observer 全圖 不能下令;可以查詢、控制鏡頭、讀取 HUD
導播、解說、覆盤
多版本相容 · P4

不猜測,不當機

1.24 ~ 1.28 是同一套引擎結構,適合「一個執行環境 + 多份 profile」。1.29 之後及重製版是另一套引擎,不承諾自動相容。

  1. 識別 讀取 Game.dll 的版本資源和檔案雜湊值,選擇 profile
  2. 符號表 做法引用符號名稱,不引用數字;每個符號都帶有呼叫慣例和參數形式
  3. 特徵碼備援 在未知版本上依函式開頭的位元組特徵掃描,找到唯一符合的結果才使用
  4. 啟動自我檢查 每個符號都以無副作用的方式驗證,沒通過的能力標記為不可用
  5. 能力清單 SDK 讀到某項能力不可用時,呼叫會拋出清楚的錯誤,而不是悄悄回傳 0
高可用性

一個 Bot 的 bug,不該拖垮整局遊戲

這也是每個 AI 都在獨立行程中執行的原因:行程內的一個空指標就會讓整局當掉;獨立行程當掉了,只是那一方停下來。

機制做法狀態
不拖垮遊戲 所有遊戲呼叫都有例外保護;每次清空有 4 ms 時間預算(高精度計時) 已有
用戶端互不影響 每個用戶端一條車道、各自有配額;一個卡死不會擋住別人 已有
過期不執行 每條命令都帶截止時間,過期只標記不執行,暫停恢復後不會重送 已有
可觀測性 每條命令的執行耗時;每次擷取的各階段耗時寫在世界區塊標頭中 已有
斷線重連 SDK 會隨著換局、換行程自動重新連線 部分
能力斷路 某項能力連續故障 N 次 → 標記為不可用並發出事件,其他能力照常運作 計畫中
擴展層

在遊戲裡,打造你自己的東西

語意命令讓 AI 像玩家一樣操作;擴展層讓你改變玩家看到和經歷的東西 —— 畫出自己能點的介面,呼叫地圖作者能用的全部函式。兩條路依「在多人局安不安全」分開。

畫板 多人局安全
0.27 ~ 0.34 ms 每幀開銷(9 個元素,約 63 幀/秒)
  • 文字框、面板、進度條、圖片、貼合地形的圈、帶箭頭的路線
  • 可跟隨單位、世界座標、螢幕位置;中文字型、圓角、半透明、任意顏色
  • 由執行環境自行繪製,不建立遊戲物件、不改變遊戲狀態
  • Python 一行一個元素,也可以走 HTTP,或直接寫入共用記憶體
  • 按鈕、選項卡片能點,滑鼠停上去會醒目顯示;畫在滑鼠游標下面,點它的那一下遊戲收不到
畫板文件
JASS 通道 單人局 · 本機工具
1291 個 JASS 函式,依名稱直接呼叫
  • 建立單位、修改屬性、特效、面板、對話框、聲音、鏡頭、迷霧、天氣……
  • 遠見控制台、命令列、HTTP、Python,同一套腳本寫法
  • 常用效果一句一個:浮動文字、連線、範圍圈、頭像對白、全螢幕濾鏡
  • 多人局裡只放行唯讀函式,避免不同步
JASS 通道文件
畫板JASS 畫面函式
誰來畫 執行環境自繪 遊戲本身
多人局 安全:只畫在本機畫面上 只能用於單人局
樣式 隨你定:字型、圓角、半透明、圖片 遊戲原生風格
跟著東西走 單位 / 世界座標 / 螢幕位置 視具體函式而定
單次開銷 每幀 0.2 ~ 0.35 ms 每次呼叫約 13 ms
1291 個函式,依用途分類
畫面效果 80 介面面板 146 鏡頭 44 聲音音樂 50 迷霧視野 25 單位 161 物品 63 英雄 32 玩家 / 同盟 / 資源 71 觸發器 / 計時器 62 地形 / 天氣 45 遊戲流程 57

玩家做了什麼,直接進入事件流

執行環境直接回報玩家的操作:點了哪個畫出來的按鈕、按了哪個熱鍵、點了地面哪裡、選取了誰、放了什麼技能、在聊天框打了什麼字。遊戲本身的觸發事件(進入區域、對話框按鈕、方向鍵)還可以用空觸發器接上:只註冊事件、不寫條件和動作,再計算它執行了幾次。