下層不知道上層的存在
介面層裡沒有任何一行「該不該打」的邏輯;各個大腦之間互不 import,只依賴 SDK。這是對戰平台得以成立的前提:平台只需要「介面層 + 裁判」,任何人的大腦都能接上來。
整張地圖,每 50 ms 一份
資訊由執行環境在遊戲執行緒上一次擷取完成、推送到共用記憶體,用戶端直接讀取,不必再到遊戲執行緒排隊。一次擷取的中位數為 0.5 ~ 0.9 ms(100 ~ 120 個單位),各階段耗時一律寫在世界區塊標頭中。
玩家 ×16
黃金、木材、人口與上限、累計採集量、種族
單位 ×1024
類型、所屬玩家、座標、血量魔力、目前指令與目標、實際在攻擊誰、等級經驗技能點、每位玩家對它的可見性
單位細節 ×256
12 個技能(等級、剩餘冷卻)、8 個 buff、6 格物品欄;英雄優先
生產表 ×128
訓練/研究/建造/升級:佇列、總時長、已進行時間、是否卡住
地上物品 ×256
類型、位置、耐久度;被撿走或用掉時發出事件
樹木 ×4096
可破壞物的位置和血量,每 2 秒刷新
地圖
128 一格的可通行/可建造網格、可遊玩區域、出生點;開局幾秒內算完
時間
引擎遊戲時鐘、遊戲內時間(晝夜)、遊戲速度、是否在對局中
走哪條路,由執行環境決定
採集、撤退、施法……同樣是「讓單位做事」,在引擎裡走的路徑各不相同。這些經驗全都收進執行環境:你只說做什麼,它用驗證過的做法執行,並在同一幀讀回下令前後的指令作為回執。
- 一次送出一批,在同一幀執行
- 每條都有回執:狀態碼 + 引擎原因碼 + 執行耗時
- Shift 排程、路徑點、連續建造
- 查詢:科技計數、可行性、可見性、金礦剩餘量、電腦對手的進攻目標
慢的從來不是跨行程
共用記憶體讀寫是奈秒級的,讀一份快照約 0.05 ms。舊通道之所以慢,是因為每個請求都要搶整台機器共用的一把鎖,再等遊戲下一次取訊息(一幀一次,16 ~ 33 ms)。參考大腦 93% 的牆上時間都花在等待上。
- 搶整台機器共用的互斥鎖
- 向遊戲執行緒投遞一則訊息
- 等遊戲下一次取訊息(一幀一次)
- 等待完成事件,釋放鎖
6 個行程同時使用時,吞吐量卡在約 88 次/秒。
- 每個用戶端獨佔一條車道:一個寫入者、一個讀取者,不加鎖
- 執行點位於遊戲執行緒的事件分發中(每秒數百次),沒有提交時的開銷只有幾次整數比較
- 一次送出 16 條,在同一次分發中全部執行;每次清空有 4 ms 的時間預算
- 每條都帶截止時間:暫停恢復後,過期的命令不會再執行
每條命令的回執都帶有執行耗時,車道標頭記錄著最慢的一條以及最近一次清空花了多久 —— 慢在哪裡一目了然。
| 等級 | 通道 | 延遲 | 使用者 | 狀態 |
|---|---|---|---|---|
| 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)
工程筆記:開局 3 分鐘內,每條命令慢了 1000 倍
為每條命令加上執行耗時之後,我們發現開局頭幾分鐘,同一批裡從第二條命令起每條都要 4 ~ 10 ms,到了遊戲時間約 180 秒時突然降到幾微秒。用執行環境內建的遊戲執行緒取樣器抓了 1700 個樣本,93% 落在執行環境自己的日誌函式裡 —— 每寫一行都要同步開啟、關閉一次日誌檔,而開局時每條引擎指令都要記一行。偵錯日誌預設關閉、日誌改為非同步寫入磁碟後,開局第 14 秒的命令也只需要 4 ~ 8 µs。
我們相信量出來的數字,不相信猜測。
每條車道都有角色
歸屬校驗和視野過濾在執行環境中進行 —— 引擎的執行層本身不校驗單位歸屬,只能在這裡補上。兩個 AI 對戰,就是在同一局裡開兩條 player 車道。
| 角色 | 能看到 | 能做 |
|---|---|---|
| player | 本方全部 + 視野內的敵方和中立單位(公平模式) | 只能指揮本方單位 選手、你的 Bot |
| observer | 全圖 | 不能下令;可以查詢、控制鏡頭、讀取 HUD 導播、解說、覆盤 |
不猜測,不當機
1.24 ~ 1.28 是同一套引擎結構,適合「一個執行環境 + 多份 profile」。1.29 之後及重製版是另一套引擎,不承諾自動相容。
- 識別 讀取 Game.dll 的版本資源和檔案雜湊值,選擇 profile
- 符號表 做法引用符號名稱,不引用數字;每個符號都帶有呼叫慣例和參數形式
- 特徵碼備援 在未知版本上依函式開頭的位元組特徵掃描,找到唯一符合的結果才使用
- 啟動自我檢查 每個符號都以無副作用的方式驗證,沒通過的能力標記為不可用
- 能力清單 SDK 讀到某項能力不可用時,呼叫會拋出清楚的錯誤,而不是悄悄回傳 0
一個 Bot 的 bug,不該拖垮整局遊戲
這也是每個 AI 都在獨立行程中執行的原因:行程內的一個空指標就會讓整局當掉;獨立行程當掉了,只是那一方停下來。
| 機制 | 做法 | 狀態 |
|---|---|---|
| 不拖垮遊戲 | 所有遊戲呼叫都有例外保護;每次清空有 4 ms 時間預算(高精度計時) | 已有 |
| 用戶端互不影響 | 每個用戶端一條車道、各自有配額;一個卡死不會擋住別人 | 已有 |
| 過期不執行 | 每條命令都帶截止時間,過期只標記不執行,暫停恢復後不會重送 | 已有 |
| 可觀測性 | 每條命令的執行耗時;每次擷取的各階段耗時寫在世界區塊標頭中 | 已有 |
| 斷線重連 | SDK 會隨著換局、換行程自動重新連線 | 部分 |
| 能力斷路 | 某項能力連續故障 N 次 → 標記為不可用並發出事件,其他能力照常運作 | 計畫中 |
在遊戲裡,打造你自己的東西
語意命令讓 AI 像玩家一樣操作;擴展層讓你改變玩家看到和經歷的東西 —— 畫出自己能點的介面,呼叫地圖作者能用的全部函式。兩條路依「在多人局安不安全」分開。
- 文字框、面板、進度條、圖片、貼合地形的圈、帶箭頭的路線
- 可跟隨單位、世界座標、螢幕位置;中文字型、圓角、半透明、任意顏色
- 由執行環境自行繪製,不建立遊戲物件、不改變遊戲狀態
- Python 一行一個元素,也可以走 HTTP,或直接寫入共用記憶體
- 按鈕、選項卡片能點,滑鼠停上去會醒目顯示;畫在滑鼠游標下面,點它的那一下遊戲收不到
- 建立單位、修改屬性、特效、面板、對話框、聲音、鏡頭、迷霧、天氣……
- 遠見控制台、命令列、HTTP、Python,同一套腳本寫法
- 常用效果一句一個:浮動文字、連線、範圍圈、頭像對白、全螢幕濾鏡
- 多人局裡只放行唯讀函式,避免不同步
| 畫板 | JASS 畫面函式 | |
|---|---|---|
| 誰來畫 | 執行環境自繪 | 遊戲本身 |
| 多人局 | 安全:只畫在本機畫面上 | 只能用於單人局 |
| 樣式 | 隨你定:字型、圓角、半透明、圖片 | 遊戲原生風格 |
| 跟著東西走 | 單位 / 世界座標 / 螢幕位置 | 視具體函式而定 |
| 單次開銷 | 每幀 0.2 ~ 0.35 ms | 每次呼叫約 13 ms |
玩家做了什麼,直接進入事件流
執行環境直接回報玩家的操作:點了哪個畫出來的按鈕、按了哪個熱鍵、點了地面哪裡、選取了誰、放了什麼技能、在聊天框打了什麼字。遊戲本身的觸發事件(進入區域、對話框按鈕、方向鍵)還可以用空觸發器接上:只註冊事件、不寫條件和動作,再計算它執行了幾次。