[
 {
  "name": "status",
  "category": "meta",
  "status": "verified",
  "mechanism": "世界區塊 + 快車道 + 仲裁表",
  "latency": "本機計算",
  "signature": "status() -> 'dict'",
  "doc": "連線狀態：pid、世界發布（週期、採集耗時）、快車道計數。"
 },
 {
  "name": "snapshot",
  "category": "observe",
  "status": "verified",
  "mechanism": "W3P 世界區塊 Local\\War3World_<pid>（執行環境每 50 ms 推送，seqlock）",
  "latency": "推送快照",
  "signature": "snapshot(max_age: 'float' = 0.05)",
  "doc": "整張地圖的完整狀態（WorldState）：.units .players .items .clock .me，max_age 秒內重複呼叫會回傳同一份。\n⚠ 進了金礦的工人不在表裡；預設全圖可見（鎖步模型在本機什麼都有），Game(fair=True) 才依視野過濾。"
 },
 {
  "name": "last_seen",
  "category": "observe",
  "status": "verified",
  "mechanism": "推送快照的 visibleTo（每次更新快照時記下看得見的敵方/野怪單位）",
  "latency": "推送快照",
  "signature": "last_seen(owner: 'str | int' = 'enemy', max_age: 'float | None' = None) -> 'list'",
  "doc": "最後一次看見的敵方（或 'creep' 野怪、或某個玩家編號）單位：[(單位當時的樣子, 當時的遊戲時鐘, 過了幾秒)]，新的在前。\n看見它死了就從表裡刪掉。公平模式和一般模式都依「我方此刻看得見」來記錄 —— 這就是玩家腦中的那張地圖：\n偵察到的兵力、上次看見對方英雄在哪裡、對面分礦什麼時候開的。max_age：只要這麼多遊戲秒以內的。"
 },
 {
  "name": "map",
  "category": "observe",
  "status": "verified",
  "mechanism": "W3P 地圖區塊 Local\\War3Map_<pid>（開局後由執行環境分批計算，IsTerrainPathable 行走/建造）",
  "latency": "推送快照",
  "signature": "map()",
  "doc": "這一局的地形表 MapInfo：.walkable(x,y) .buildable(x,y) .at(x,y) .bounds（可玩區）.starts（出生點）.cells（bit0 不能走、bit1 不能蓋）。\n開局後要幾秒才算好，還沒算好時回傳 None。樹不在裡面（用 trees()）。"
 },
 {
  "name": "me",
  "category": "observe",
  "status": "verified",
  "mechanism": "世界區塊標頭",
  "latency": "推送快照",
  "signature": "me() -> 'int | None'",
  "doc": "我是幾號玩家（0~11）。"
 },
 {
  "name": "resources",
  "category": "observe",
  "status": "verified",
  "mechanism": "世界區塊 players[16]",
  "latency": "推送快照",
  "signature": "resources(player: 'int | None' = None) -> 'dict | None'",
  "doc": "{'gold','lumber','food_used','food_cap','gold_gathered','lumber_gathered'}；player 預設為我方，任何玩家都讀得到。\n讀不到時回傳 None，別當成 0。"
 },
 {
  "name": "players",
  "category": "observe",
  "status": "verified",
  "mechanism": "世界區塊 players[16]",
  "latency": "推送快照",
  "signature": "players() -> 'list'",
  "doc": "全部 16 個玩家欄位：Player(id, gold, lumber, food_used, food_cap, gold_gathered, lumber_gathered, race, known)。"
 },
 {
  "name": "units",
  "category": "observe",
  "status": "verified",
  "mechanism": "世界區塊 units[]",
  "latency": "推送快照",
  "signature": "units(owner: 'str | int' = 'all', types=None, alive: 'bool' = True) -> 'list'",
  "doc": "依擁有者/類型篩選單位。owner：'me' / 'enemy' / 'creep' / 'all' / 玩家編號。types：四字碼集合。"
 },
 {
  "name": "unit",
  "category": "observe",
  "status": "verified",
  "mechanism": "世界區塊 by_handle",
  "latency": "推送快照",
  "signature": "unit(handle) -> 'object | None'",
  "doc": "依控制代碼對 (lo, hi) 找單位（訂單目標、任務目標、事件給的都是控制代碼對）。"
 },
 {
  "name": "is_building",
  "category": "observe",
  "status": "verified",
  "mechanism": "快照 + units.json（spd==0 = 建築）",
  "latency": "推送快照",
  "signature": "is_building(u) -> 'bool'",
  "doc": "是不是建築（含塔）。依單位表的移動速度為 0 判斷；不死族大廳的占地是 0，別用占地判斷。"
 },
 {
  "name": "my_workers",
  "category": "observe",
  "status": "verified",
  "mechanism": "推送快照",
  "latency": "推送快照",
  "signature": "my_workers() -> 'list'",
  "doc": "我方工人（農民/苦工/侍僧/小精靈）。"
 },
 {
  "name": "idle_workers",
  "category": "observe",
  "status": "verified",
  "mechanism": "推送快照（訂單欄位 + 任務欄位）",
  "latency": "推送快照",
  "signature": "idle_workers() -> 'list'",
  "doc": "沒工作的工人：沒有訂單、也沒有任務（這一拍剛被你派了工作的不算）。\n⚠ 對有任務的工人重新下採集令會打斷採集週期（收入歸零）。"
 },
 {
  "name": "my_heroes",
  "category": "observe",
  "status": "verified",
  "mechanism": "推送快照",
  "latency": "推送快照",
  "signature": "my_heroes() -> 'list'",
  "doc": "我方活著的英雄（陣亡的在祭壇復活表裡，見 revive）。"
 },
 {
  "name": "my_army",
  "category": "observe",
  "status": "verified",
  "mechanism": "推送快照 + units.json",
  "latency": "推送快照",
  "signature": "my_army() -> 'list'",
  "doc": "我方作戰單位：不是工人、不是建築。"
 },
 {
  "name": "my_buildings",
  "category": "observe",
  "status": "verified",
  "mechanism": "推送快照",
  "latency": "推送快照",
  "signature": "my_buildings(types=None) -> 'list'",
  "doc": "我方建築（含塔、建造中的地基）；types 可以只要某幾種，例如 {'hbar'}。"
 },
 {
  "name": "is_constructing",
  "category": "observe",
  "status": "verified",
  "mechanism": "推送快照（訂單 = 建築四字碼，或施工令/修理令）",
  "latency": "推送快照",
  "signature": "is_constructing(worker) -> 'bool'",
  "doc": "這個工人是不是正在蓋房子（或正走去蓋 / 正在幫忙修；含這一拍剛派的）。挑建造工人時要跳過它，否則上一座地基會停工。"
 },
 {
  "name": "under_construction",
  "category": "observe",
  "status": "verified",
  "mechanism": "推送快照（地基的血量從很低一路漲到滿）",
  "latency": "推送快照",
  "signature": "under_construction(building) -> 'bool'",
  "doc": "這座建築還沒蓋完（血沒滿）。⚠ 被打殘的建築也不是滿血 —— 開局判斷夠用，開打之後要結合時間來看。"
 },
 {
  "name": "gold_mines",
  "category": "observe",
  "status": "verified",
  "mechanism": "推送快照（ngol/egol/ugol）",
  "latency": "推送快照",
  "signature": "gold_mines() -> 'list'",
  "doc": "地圖上的金礦。⚠ 夜精靈的纏繞金礦和中立金礦在同一座標各有一個單位，採集要派到自己的那一個。"
 },
 {
  "name": "enemies",
  "category": "observe",
  "status": "verified",
  "mechanism": "推送快照",
  "latency": "推送快照",
  "signature": "enemies(fighters_only: 'bool' = False) -> 'list'",
  "doc": "敵方玩家的單位（不含野怪）。fighters_only：去掉工人和建築。"
 },
 {
  "name": "creeps",
  "category": "observe",
  "status": "verified",
  "mechanism": "推送快照（owner 12 = 中立敵對）",
  "latency": "推送快照",
  "signature": "creeps() -> 'list'",
  "doc": "野怪（中立敵對）。⚠ 夜裡視野變短，遠處營地進入迷霧後，對它的目標命令會被拒（原因碼 1001）。"
 },
 {
  "name": "nearest",
  "category": "meta",
  "status": "verified",
  "mechanism": "純計算",
  "latency": "本機計算",
  "signature": "nearest(candidates, to)",
  "doc": "離 to（單位或 (x,y)）最近的一個；沒有候選時回傳 None。"
 },
 {
  "name": "life_mana",
  "category": "observe",
  "status": "verified",
  "mechanism": "世界區塊單位 hp/hpMax/mana/manaMax",
  "latency": "推送快照",
  "signature": "life_mana(u) -> 'dict | None'",
  "doc": "{'hp','hp_max','mana','mana_max'}（浮點數，引擎原始值）。u 用快照裡拿到的單位即可（會換成最新的一份）。"
 },
 {
  "name": "hero_info",
  "category": "observe",
  "status": "verified",
  "mechanism": "世界區塊單位 level/xp/skillPoints",
  "latency": "推送快照",
  "signature": "hero_info(hero) -> 'dict | None'",
  "doc": "{'level','xp','skill_points'}。"
 },
 {
  "name": "abilities",
  "category": "observe",
  "status": "verified",
  "mechanism": "世界區塊細節：技能（代碼/等級/旗標/剩餘冷卻）",
  "latency": "推送快照",
  "signature": "abilities(u) -> 'list'",
  "doc": "[{code, level, cooldown, flags}]；buff 在 buffs(u)。只有「有細節」的單位才有（英雄 > 玩家單位 > 野怪，最多 256 個）。"
 },
 {
  "name": "buffs",
  "category": "observe",
  "status": "verified",
  "mechanism": "世界區塊細節：B 開頭的技能物件",
  "latency": "推送快照",
  "signature": "buffs(u) -> 'list'",
  "doc": "單位身上的 buff 代碼（例如 'BHds' 神聖護盾、'Bslo' 減速）。代碼對應什麼效果見 data/game/buffs.json。"
 },
 {
  "name": "cooldown",
  "category": "observe",
  "status": "verified",
  "mechanism": "世界區塊細節：技能剩餘冷卻（技能計時器）",
  "latency": "推送快照",
  "signature": "cooldown(u, ability: 'str') -> 'float | None'",
  "doc": "這個技能還要冷卻幾秒（遊戲秒）；0 = 可以施放；沒有這個技能（或這個單位沒有細節）時回傳 None。"
 },
 {
  "name": "inventory",
  "category": "observe",
  "status": "verified",
  "mechanism": "世界區塊細節：物品欄 6 格",
  "latency": "推送快照",
  "signature": "inventory(hero) -> 'list | None'",
  "doc": "6 格物品的四字碼（空格為 None）；沒有物品欄時回傳 None。"
 },
 {
  "name": "current_order",
  "category": "observe",
  "status": "verified",
  "mechanism": "世界區塊單位 order / 訂單目標 / 訂單目標點",
  "latency": "推送快照",
  "signature": "current_order(u) -> 'dict | None'",
  "doc": "{'order','target','x','y'}：單位手上的這條訂單（order 是 0x000D00xx 或建築四字碼，0 = 閒置）。\ntarget 是控制代碼對，用 g.unit(target) 換成單位。"
 },
 {
  "name": "current_target",
  "category": "observe",
  "status": "verified",
  "mechanism": "世界區塊單位任務目標",
  "latency": "推送快照",
  "signature": "current_target(u)",
  "doc": "單位**實際在打/在追**的那個單位（沒有則回傳 None）。\n⚠ 攻擊令下完後訂單欄位很快就變空，攻擊掛在任務上 —— 判斷「在打誰」用這個，別用 current_order。"
 },
 {
  "name": "clock",
  "category": "observe",
  "status": "verified",
  "mechanism": "世界區塊標頭 clockMs（引擎遊戲時鐘）",
  "latency": "推送快照",
  "signature": "clock() -> 'float | None'",
  "doc": "引擎遊戲時鐘（遊戲秒，載入中為 0）。倍速下它比實際時間走得快。"
 },
 {
  "name": "production",
  "category": "observe",
  "status": "verified",
  "mechanism": "世界區塊生產表（Aque/ABnP/AUnP 技能物件 + 執行環境追蹤的已進行時間；實測誤差 < 0.2 遊戲秒）",
  "latency": "推送快照",
  "signature": "production(building)",
  "doc": "這座建築正在做什麼：Production(kind, queue, duration, elapsed, blocked, progress, remaining…)，沒在做則回傳 None。\n  kind 'queue'（訓練/研究/英雄，queue 最多 7 格，[0] 是正在做的）/ 'construction'（建造中）/ 'upgrade'（升級大廳/塔）；\n  blocked = 有排隊但沒開始（多半是人口不夠 —— 該蓋農場了）；progress 0..1。\n對手的建築也能看（公平模式下只有看得見的建築才有）。"
 },
 {
  "name": "queue",
  "category": "observe",
  "status": "verified",
  "mechanism": "世界區塊生產表",
  "latency": "推送快照",
  "signature": "queue(building) -> 'list'",
  "doc": "訓練/研究佇列裡的四字碼（[0] 正在做）；閒置或不是生產建築 = []。"
 },
 {
  "name": "all_production",
  "category": "observe",
  "status": "verified",
  "mechanism": "世界區塊生產表",
  "latency": "推送快照",
  "signature": "all_production(owner: 'str | int' = 'me') -> 'list'",
  "doc": "全部正在進行的生產 [(建築, Production)]。owner 同 units()：'me' / 'enemy' / 玩家編號 / 'all'。\n職業用法：看對手在訓練什麼兵、研究什麼科技、什麼時候升級主城（偵察到建築時）。"
 },
 {
  "name": "path_distance",
  "category": "observe",
  "status": "verified",
  "mechanism": "地圖區塊（引擎 IsTerrainPathable）+ 樹區塊 + 建築占地，SDK 端 A*（128 一格）",
  "latency": "推送快照 + 本機計算",
  "signature": "path_distance(a, b) -> 'float | None'",
  "doc": "地面單位從 a 走到 b 的路程（a、b 給單位或 (x,y)）；走不到則為 None。島嶼地圖上判斷「這個野點/分礦地面過不過得去」用它，\n比直線距離可靠（繞樹林、繞懸崖、繞建築）。精度為一格 128；窄於一格的縫隙判定為不通。"
 },
 {
  "name": "reachable",
  "category": "observe",
  "status": "verified",
  "mechanism": "同上",
  "latency": "推送快照 + 本機計算",
  "signature": "reachable(a, b) -> 'bool | None'",
  "doc": "地面能不能走到（地圖區塊還沒算好 = None）。"
 },
 {
  "name": "walk_path",
  "category": "observe",
  "status": "verified",
  "mechanism": "同上",
  "latency": "推送快照 + 本機計算",
  "signature": "walk_path(a, b) -> 'list | None'",
  "doc": "路徑轉折點 [(x,y)...]（最後一點是 b）；搭配 path(units, 點列表) 讓部隊沿這條路走（繞開塔、走小路）。"
 },
 {
  "name": "upkeep",
  "category": "observe",
  "status": "inferred",
  "mechanism": "1.27 固定規則：0~50 人口不收、51~80 收入 ×0.7、81~100 ×0.4",
  "latency": "推送快照",
  "signature": "upkeep(player: 'int | None' = None) -> 'dict | None'",
  "doc": "維護費檔位：{'level': 'none'/'low'/'high', 'income': 1.0/0.7/0.4, 'next_at': 下一檔的人口（沒有 = None）}。\n職業常識：升到第三級主城、做攻防升級時停在 50 人口，決戰前才上 80。"
 },
 {
  "name": "xp_to_next",
  "category": "observe",
  "status": "verified",
  "mechanism": "世界區塊 level/xp + MiscGame NeedHeroXP 公式",
  "latency": "推送快照",
  "signature": "xp_to_next(hero) -> 'int | None'",
  "doc": "英雄離下一級還差多少經驗（10 級 = 0）。"
 },
 {
  "name": "creep_camps",
  "category": "observe",
  "status": "verified",
  "mechanism": "推送快照（野怪依 600 的距離連成一群）+ units.json 等級",
  "latency": "推送快照",
  "signature": "creep_camps(link: 'float' = 600.0) -> 'list'",
  "doc": "把場上（看得見的）野怪聚成營地：[{'x','y','units','level','hp','max_level'}]，依離我方主基地由近到遠排序。\nlevel = 營地總等級（衡量打野難度的常用標準），hp = 總血量。搭配 time_to_kill / path_distance 挑點。"
 },
 {
  "name": "buff_info",
  "category": "observe",
  "status": "verified",
  "mechanism": "data/game/buffs.json（AbilityData.slk 的 BuffID -> 技能/效果/時長）",
  "latency": "本機資料",
  "signature": "buff_info(code: 'str') -> 'dict | None'",
  "doc": "buff 代碼是什麼：{'ability','effect','dur','hero_dur','targets'}（例 'Bslo' -> 減速）。一個代碼對應多行時給第一行。"
 },
 {
  "name": "stats",
  "category": "observe",
  "status": "verified",
  "mechanism": "資料表（UnitBalance/UnitWeapons/UpgradeData/MiscGame）+ 即時科技等級 + 英雄等級",
  "latency": "推送快照 + 快車道（5 秒一批）",
  "signature": "stats(u, player: 'int | None' = None)",
  "doc": "單位的戰鬥屬性 combat.UnitStats：生命/魔力上限、護甲（含攻防升級、英雄敏捷）、護甲類型、移動速度、白天/夜裡視野、\n武器（能打什麼、射程、攻擊間隔、傷害區間、攻擊類型、濺射）。u 給單位（自動用它擁有者的科技、英雄等級）或四字碼（player 預設為我方）。\n再搭配 .dps_vs(對方) / .hits_to_kill(對方) / combat.time_to_kill(一群, 對方)。⚠ 不含物品、光環、buff。"
 },
 {
  "name": "time_to_kill",
  "category": "observe",
  "status": "verified",
  "mechanism": "stats() + 即時血量",
  "latency": "推送快照",
  "signature": "time_to_kill(attackers, target) -> 'float | None'",
  "doc": "這群單位一起打 target 要幾遊戲秒（用 target 目前的血量；算入克制、護甲、攻防升級；不算走位、濺射、治療）。\n職業用法：集火先打「最快能打死」的那個（time_to_kill 最小），而不是最近的那個。打不到 = None。"
 },
 {
  "name": "time_of_day",
  "category": "observe",
  "status": "verified",
  "mechanism": "世界區塊擴充區：GetFloatGameState(GAME_STATE_TIME_OF_DAY)",
  "latency": "推送快照",
  "signature": "time_of_day() -> 'float | None'",
  "doc": "遊戲內時間（小時，0~24）。開局是早上 8 點；一整天 = 480 遊戲秒（白天、黑夜各 240 秒，依晝夜流速縮放）。\n讀不到（舊版執行環境 / 不在局內）時回傳 None。"
 },
 {
  "name": "is_night",
  "category": "observe",
  "status": "verified",
  "mechanism": "世界區塊擴充區（6~18 點為白天）",
  "latency": "推送快照",
  "signature": "is_night() -> 'bool | None'",
  "doc": "現在是不是夜裡（18:00~6:00）。職業打法：夜裡野怪睡著（先手打野不會被包圍）、所有單位視野變短（偷襲的好時機），\n夜精靈的哨兵/單位夜裡在樹旁會隱形。讀不到時回傳 None。"
 },
 {
  "name": "seconds_until",
  "category": "observe",
  "status": "verified",
  "mechanism": "世界區塊擴充區 + 一天 480 秒（實測 20 遊戲秒/小時）",
  "latency": "推送快照",
  "signature": "seconds_until(hour: 'float') -> 'float | None'",
  "doc": "離遊戲內時間 hour 點還有幾遊戲秒（例如 seconds_until(18) = 離天黑還有多久，規劃夜裡打野時用）。"
 },
 {
  "name": "items_on_ground",
  "category": "observe",
  "status": "verified",
  "mechanism": "世界區塊 items[]（只含地上的：持有者控制代碼全為 FF）",
  "latency": "推送快照",
  "signature": "items_on_ground() -> 'list'",
  "doc": "地上的物品 [Item(addr, handle_lo, handle_hi, type, x, y, life)]。撿走/用掉會發 item.removed 事件。"
 },
 {
  "name": "trees",
  "category": "observe",
  "status": "verified",
  "mechanism": "樹區塊 Local\\War3Trees_<pid>（每 2 秒更新）",
  "latency": "推送快照",
  "signature": "trees(x: 'float | None' = None, y: 'float | None' = None, limit: 'int' = 60) -> 'list'",
  "doc": "活著的樹（DestructableData 裡 targType 含 tree 的），給了 (x,y) 就依距離由近到遠排序，最多 limit 棵。\n每棵是 Tree(addr, handle_lo, handle_hi, type, x, y, life)，可以直接交給 gather 去伐木。"
 },
 {
  "name": "events",
  "category": "observe",
  "status": "verified",
  "mechanism": "事件環 Local\\War3Events_<pid>（發布比對 + 執行環境擷取的傷害事件）",
  "latency": "推送快照",
  "signature": "events() -> 'list'",
  "doc": "上次呼叫之後發生的事：unit.appeared / unit.died / unit.removed / unit.damaged / order.changed /\nhero.levelup / owner.changed / item.appeared / item.removed / game.started（這些依發布比對得出，精度 = 發布週期 50 ms），\n以及引擎層級的 damage / killed（執行環境在遊戲執行緒上當場記下，**每一下**都有）：\n    damage：handle = 挨打的，.source_addr = 打它的（用 snapshot().unit_by_addr 換成單位），.value = 實際扣掉的血，\n            .raw_damage = 護甲前的傷害，.attack_type（normal/pierce/siege/magic/chaos/hero/spell），.damage_type\n    killed：這一下把它打死了，.source_addr = 兇手\n以及執行環境追蹤生產表得出的 production.done（精度 = 發布週期）：單位 = 建築，.done_code = 完成的四字碼，\n    .done_kind = 'training'（兵/英雄/復活）/ 'research' / 'construction'（建築蓋好）/ 'upgrade'（升級主城/升級塔），.value = 花了幾遊戲秒\n09-25 補齊：\n    spell.cast：單位 = 施法者，.spell 技能四字碼，b 等級，value 冷卻秒數，x,y 施法點（在技能開始冷卻時辨識出來，精度 = 發布週期）\n    player.left：.player 離開 / 被判定落敗移除的玩家編號；game.ended：離開對局\n    selection.changed：本機玩家的選取變了（用 g.selection() 取得單位）\n    message：螢幕訊息框裡的一條（遊戲提示、聊天、系統）：.text 全文，.frame 訊息框編號，\n             .chat = {'channel', 'sender', 'text'}（是聊天時；玩家在聊天框輸入的文字就從這裡讀取）\n    ui.click / ui.hover / hotkey / mouse.world：介面與輸入（g.ui），.key 是畫板 key / 熱鍵寫法\n每筆是 Event(seq, kind, clock, addr, handle, type, owner, a, b, x, y, value, extra)。\n公平模式（fair=True）只給：自己單位的事件、此刻看得見（或 1 秒內還看得見）的單位的事件、打我方/我方打的傷害，\n以及本機的介面 / 訊息 / 對局類事件。"
 },
 {
  "name": "selection",
  "category": "observe",
  "status": "verified",
  "mechanism": "W3P 世界區塊擴充區 selAddrs（執行環境每次發布時帶上本機玩家的選取）",
  "latency": "推送快照",
  "signature": "selection() -> 'list'",
  "doc": "本機玩家目前選取的單位（主單位排第一；最多 12 個）。選取一有變化就會發出 selection.changed 事件。"
 },
 {
  "name": "messages",
  "category": "observe",
  "status": "verified",
  "mechanism": "共用記憶體 Local\\War3Msgs_<pid>（執行環境擷取的螢幕訊息）",
  "latency": "推送快照",
  "signature": "messages() -> 'list'",
  "doc": "上次呼叫之後螢幕訊息框裡新出現的訊息：[{'text', 'frame', 'repeat', 'seq', 'game_ms'}]。\n遊戲提示（「需要更多的農場」「不能在那裡建造」）、聊天、系統訊息都在這裡；frame 區分是哪一個訊息框。\n和事件流裡的 message 事件是同一批（各有各的游標）。"
 },
 {
  "name": "ui",
  "category": "control",
  "status": "verified",
  "mechanism": "W3P 74 input_enable + 共用記憶體 Local\\War3Input_<pid>（執行環境接收視窗輸入）",
  "latency": "共用記憶體",
  "signature": "ui()",
  "doc": "介面與輸入（openwar3.ui.UI）：可點擊的按鈕和選項卡片、熱鍵、點地面選位置、滑鼠指著哪裡。\n點在按鈕上的那一下遊戲收不到；純本機輸入 + 本機繪製，多人局也安全。"
 },
 {
  "name": "tech",
  "category": "observe",
  "status": "verified",
  "mechanism": "W3P 查詢 q_tech（引擎的玩家科技計數）",
  "latency": "快車道",
  "signature": "tech(code: 'str', player: 'int | None' = None) -> 'int | None'",
  "doc": "研究等級 / 已建成的建築數（升級鏈算在內：城堡也算 htow）。player 預設為我方，任何玩家都能查。"
 },
 {
  "name": "can_do",
  "category": "observe",
  "status": "verified",
  "mechanism": "W3P 查詢 q_feasible（引擎可行性檢查）",
  "latency": "快車道",
  "signature": "can_do(u, code: 'str') -> 'int | None'",
  "doc": "引擎的可行性裁決：0/220 可以下令；3 人口 8 缺金 9 缺木 32 佇列滿 183 缺前置 185 祭壇正在復活 221 沒有這一項/建造中。\n⚠ 對工人建造建築一律回 221，不能用來判斷落點（用 build_near）。"
 },
 {
  "name": "can_do_many",
  "category": "observe",
  "status": "verified",
  "mechanism": "W3P 查詢 q_feasible × N，一批提交",
  "latency": "快車道 × 1",
  "signature": "can_do_many(pairs) -> 'list'",
  "doc": "一次問很多個 can_do：pairs = [(單位, 四字碼), ...]，回傳同樣順序的裁決碼列表（問不到的是 None）。\n規劃一拍要蓋/訓練什麼時先整體問一遍，比逐個 can_do 快 N 倍（參考大腦 09-23：建造規劃 76 -> 25 ms）。"
 },
 {
  "name": "tech_many",
  "category": "observe",
  "status": "verified",
  "mechanism": "W3P 查詢 q_tech × N，一批提交",
  "latency": "快車道 × 1",
  "signature": "tech_many(codes, player: 'int | None' = None) -> 'dict'",
  "doc": "一次查很多個科技/建築計數：{四字碼: 數量或 None}。"
 },
 {
  "name": "visible",
  "category": "observe",
  "status": "verified",
  "mechanism": "W3P 查詢 q_visible（看得見 / 迷霧 / 黑區）",
  "latency": "快車道",
  "signature": "visible(x: 'float', y: 'float') -> 'bool | None'",
  "doc": "這一點我方現在看不看得見（不在迷霧/黑區裡）。公平模式的 bot 應該只用看得見的敵人。"
 },
 {
  "name": "gold_left",
  "category": "observe",
  "status": "inferred",
  "mechanism": "W3P 查詢 q_mine_gold（引擎的金礦剩餘量）",
  "latency": "快車道",
  "signature": "gold_left(mine) -> 'int | None'",
  "doc": "金礦還剩多少金。"
 },
 {
  "name": "enemy_ai_plan",
  "category": "observe",
  "status": "verified",
  "mechanism": "W3P 查詢 q_captain（敵兵跟隨的電腦隊長）",
  "latency": "快車道",
  "signature": "enemy_ai_plan(enemy_unit) -> 'dict | None'",
  "doc": "電腦 AI 的隊長：它帶兵要去哪裡（出門前就知道要打你家哪裡）。只對電腦對手有效；沒跟著隊長走時回傳 None。"
 },
 {
  "name": "batch",
  "category": "command",
  "status": "verified",
  "mechanism": "區塊裡的命令累積成一批，區塊結束時一次提交（同一幀執行、只等一次遊戲執行緒）",
  "latency": "快車道 × 1",
  "signature": "batch() -> 'Batch'",
  "doc": "把一拍裡的命令合成一批：\n\n    with g.batch() as b:\n        g.attack(archers, target)          # 回傳 Pending，區塊結束後才變成回執\n        g.move(wounded, *home)\n        g.cast(hero, \"thunderclap\")\n    print(b.sent, b.wait_ms, [r.reason for r in b.receipts])\n\n每條命令單獨送出都要等遊戲執行緒處理一次（約 10 ms）；一批只等一次 —— 參考大腦 09-23 靠這個把一輪從 48 -> 26 ms。\n* 仲裁照舊逐條進行（被占用的單位當場得到 held 回執，不進入批次）；\n* 區塊裡的命令回傳 Pending：區塊結束前讀它的 .ok 會拋出錯誤（回執還不存在），區塊結束後和 Receipt 用法一樣；\n* 區塊裡拋出例外 = 整批作廢（status 97 cancelled），被占用的單位會放回去；\n* 查詢（can_do / tech / visible …）和 build_near、buy 不進入批次，照舊當場詢問 —— 它們的結果當場就要用；\n  要一次問很多個就用 can_do_many / tech_many；\n* 巢狀的 with g.batch() 併入最外層的那一批；超過 16 條時執行環境會自動分成幾段（每段等待一次）。"
 },
 {
  "name": "order_of",
  "category": "observe",
  "status": "verified",
  "mechanism": "快照訂單 + 本行程剛被接下的命令（回執）",
  "latency": "推送快照",
  "signature": "order_of(u) -> 'int | None'",
  "doc": "單位目前的訂單，**含你這一拍剛下的**（快照還沒跟上時，用回執裡的新訂單）。\n⚠ 09-23 實機：hello_bot 剛派農民去蓋農場，同一拍 rush_bot 從快照裡看它「閒置」又派去蓋兵營，農場一次次半途而廢。\n  挑「閒著的/沒在蓋房子的」單位時，用這個而不是 u.order。"
 },
 {
  "name": "move",
  "category": "command",
  "status": "verified",
  "mechanism": "W3P point：move（extra 位元 = 排隊方式）",
  "latency": "快車道",
  "signature": "move(units, x: 'float', y: 'float', queue: 'str | None' = None)",
  "doc": "走到 (x,y)，路上不打人（撤退用這個）。可以傳一個單位或一個列表（同一幀一起下令）。\nqueue='after'：做完手上這件再去（接在目前訂單後面）。回執 values[0] = 下令後這個單位排著幾條訂單（含正在做的）。"
 },
 {
  "name": "attack_move",
  "category": "command",
  "status": "verified",
  "mechanism": "W3P point：attack 對點",
  "latency": "快車道",
  "signature": "attack_move(units, x: 'float', y: 'float', queue: 'str | None' = None)",
  "doc": "攻擊移動（A 地面）：路上遇敵就打。queue 同 move。"
 },
 {
  "name": "attack",
  "category": "command",
  "status": "verified",
  "mechanism": "W3P target：目標命令（右鍵 smart）",
  "latency": "快車道",
  "signature": "attack(units, target, force: 'bool' = False, queue: 'str | None' = None)",
  "doc": "打 target。預設用右鍵（對敵人 = 攻擊這一個，09-23 實測訂單目標/任務目標都是它）。\n⚠ 目標必須在視野內，看不見的會被拒（原因碼 1001）。\nforce=True 用攻擊令 0x0F（打自己人/中立小動物時需要它）—— 實測它只換上攻擊令、不記住目標，\n會去打附近別的敵人，要打特定目標時別用它。"
 },
 {
  "name": "stop",
  "category": "command",
  "status": "verified",
  "mechanism": "W3P immediate：stop",
  "latency": "快車道",
  "signature": "stop(units)",
  "doc": "停下手上的一切（訂單編號 0x000D0004），排著的訂單也會清掉。"
 },
 {
  "name": "hold",
  "category": "command",
  "status": "verified",
  "mechanism": "W3P immediate：holdposition",
  "latency": "快車道",
  "signature": "hold(units, queue: 'str | None' = None)",
  "doc": "原地待命（不追出去，只打射程內的）。"
 },
 {
  "name": "patrol",
  "category": "command",
  "status": "inferred",
  "mechanism": "W3P point：patrol",
  "latency": "快車道",
  "signature": "patrol(units, x: 'float', y: 'float', queue: 'str | None' = None)",
  "doc": "在目前位置和 (x,y) 之間巡邏。"
 },
 {
  "name": "attack_ground",
  "category": "command",
  "status": "verified",
  "mechanism": "W3P point：attackground（攻城單位 / 迫擊砲 / 投石車）",
  "latency": "快車道",
  "signature": "attack_ground(units, x: 'float', y: 'float', queue: 'str | None' = None)",
  "doc": "攻擊地面：用砲對一塊地方開火（打隱形單位、打樹林後面的敵人、封鎖路口）。只有能攻擊地面的單位接受。"
 },
 {
  "name": "cancel",
  "category": "command",
  "status": "verified",
  "mechanism": "W3P immediate：cancel",
  "latency": "快車道",
  "signature": "cancel(building)",
  "doc": "取消：訓練/研究佇列的最後一格（退錢）、正在蓋的建築（退 75%）、正在升級的大廳。"
 },
 {
  "name": "path",
  "category": "command",
  "status": "verified",
  "mechanism": "一批：第一段立即執行，其餘倒序用 queue='after' 插入（引擎只能插在目前訂單後面）",
  "latency": "快車道 × 1",
  "signature": "path(units, points, attack: 'bool' = False)",
  "doc": "依序走過一串點（Shift 連點：路徑點、繞開塔、偵察路線）。attack=True 時每段都是攻擊移動。\n一次提交；每個點一張回執（依 points 順序）。"
 },
 {
  "name": "gather",
  "category": "command",
  "status": "verified",
  "mechanism": "W3P target：harvest（金礦或樹）",
  "latency": "快車道",
  "signature": "gather(workers, target, queue: 'str | None' = None)",
  "doc": "採金/伐木（target 是金礦或 trees() 裡的樹）。⚠ 只派閒置的工人（idle_workers）：對有任務的工人重新下令會打斷採集週期。\n職業用法：蓋完房子回去採礦 = build(...) 之後 gather(worker, mine, queue='after')。"
 },
 {
  "name": "repair",
  "category": "command",
  "status": "verified",
  "mechanism": "W3P target：repair",
  "latency": "快車道",
  "signature": "repair(workers, building, queue: 'str | None' = None)",
  "doc": "修理 / 幫忙蓋（人類、獸人的工地沒人蓋會停工）。"
 },
 {
  "name": "build",
  "category": "command",
  "status": "verified",
  "mechanism": "W3P build：建造訂單，同一幀讀回工人訂單以確認",
  "latency": "快車道",
  "signature": "build(worker, code: 'str', x: 'float', y: 'float', queue: 'str | None' = None)",
  "doc": "讓工人在 (x,y) 蓋 code（座標對齊 32 格）。回執接下 = 工人的訂單已經是這座建築（或開工令）；\nqueue='after' 時 = 已排進工人的訂單佇列（回執 values[0] 為排隊數）。\n⚠ 接下 ≠ 蓋得成：樹林裡的點引擎也會當場接下，工人走到了才失敗（09-23 實測）；錢被別處花掉也會讓地基出不來。\n不知道哪裡放得下就用 build_near（它會追蹤結果、把失敗的點列入黑名單）。連蓋幾座用 build_queue。"
 },
 {
  "name": "build_queue",
  "category": "command",
  "status": "verified",
  "mechanism": "一批：第一座立即執行，其餘倒序 queue='after'",
  "latency": "快車道 × 1",
  "signature": "build_queue(worker, plan)",
  "doc": "一個工人依序連蓋幾座（Shift 連蓋）：plan = [(四字碼, x, y), ...]。一次提交；回執依 plan 順序。\n⚠ 錢是開工時才扣的（排隊時不扣）—— 排了 3 座但錢只夠 1 座，後兩座會在工人走到時失敗。"
 },
 {
  "name": "build_near",
  "category": "command",
  "status": "verified",
  "mechanism": "逐點 build + 追蹤（地基出現 = 成功；工人放棄訂單又沒有地基 = 這個點列入黑名單）",
  "latency": "快車道 × 嘗試的點數",
  "signature": "build_near(worker, code: 'str', x: 'float', y: 'float', min_r: 'float' = 450, max_r: 'float' = 1500, max_tries: 'int' = 24)",
  "doc": "在 (x,y) 周圍由近到遠找一個放得下的點蓋 code。**不阻塞**，每拍呼叫都可以：\n  * 這種建築有一次還在進行中（工人走在路上）-> 回傳那個點，不重複下令；\n  * 上一次成功了（地基出現）-> 這次視需要再找新點；\n  * 上一次失敗了（工人走到才發現放不下，訂單被引擎撤掉、沒有地基）-> 那個點列入黑名單 45 秒，換下一個；\n  * 錢不夠 -> 直接回傳 None（不嘗試、不列入黑名單）；全部試完了回傳 None。\n⚠ 為什麼要追蹤：09-23 實機，樹林裡的點引擎**當場接下**、工人走到了才失敗（同一幀的回執判斷不出來）；\n  而引擎的落點檢查對工人建造建築一律回 221，也沒辦法先「查」再蓋。只有明顯被占用的點（大廳正中央）會當場拒絕。"
 },
 {
  "name": "can_afford",
  "category": "observe",
  "status": "verified",
  "mechanism": "推送快照的我方資源 + units.json 的價格",
  "latency": "推送快照",
  "signature": "can_afford(code: 'str') -> 'bool'",
  "doc": "現在的金/木夠不夠買 code（單位、建築；依 units.json 的價格）。價格表裡沒有的一律當作買得起。\n⚠ 升級主城的四字碼在表裡是累計價格，這裡會偏保守；最終以引擎的回執為準。"
 },
 {
  "name": "train",
  "category": "command",
  "status": "verified",
  "mechanism": "W3P immediate：四字碼，被拒時帶有可行性原因碼",
  "latency": "快車道",
  "signature": "train(building, code: 'str')",
  "doc": "訓練單位 / 研究科技 / 升級大廳（升級主城 = 對大廳本身下目標大廳的四字碼，例如 'hkee'）。\n被拒時回執的 reason 會說明原因（人口不夠、缺金、缺木、佇列滿、缺前置……）。"
 },
 {
  "name": "learn",
  "category": "command",
  "status": "verified",
  "mechanism": "W3P learn：技能點減少才算學會",
  "latency": "快車道",
  "signature": "learn(hero, ability: 'str')",
  "doc": "英雄學技能（四字碼，例如 'AHbz' 暴風雪）。"
 },
 {
  "name": "cast",
  "category": "command",
  "status": "verified",
  "mechanism": "W3P target / point / immediate（依參數選擇）",
  "latency": "快車道",
  "signature": "cast(u, spell, target=None, x: 'float | None' = None, y: 'float | None' = None)",
  "doc": "施放技能。spell 是訂單名（'thunderbolt' 風暴之錘、'blizzard'、'holybolt' 聖光術…，見 data/order-ids.txt）或訂單編號。\n給 target = 對單位；給 x,y = 對地面；都不給 = 無目標（雷霆一擊、神聖護盾、召喚水元素）。\n回執接下只代表引擎接受了；有沒有放出來要看 cooldown() 有沒有進入冷卻、buffs() 有沒有出現。"
 },
 {
  "name": "rally",
  "category": "command",
  "status": "verified",
  "mechanism": "W3P rally",
  "latency": "快車道",
  "signature": "rally(building, x: 'float | None' = None, y: 'float | None' = None, target=None)",
  "doc": "設定集結點（對點，或對一個單位/金礦）。"
 },
 {
  "name": "revive",
  "category": "command",
  "status": "verified",
  "mechanism": "W3P revive：陣亡英雄表 -> 祭壇對陣亡英雄施放復活",
  "latency": "快車道",
  "signature": "revive(altar, hero=None)",
  "doc": "在祭壇復活陣亡的英雄（不給 hero 就復活表裡的第一個）。\n被拒的常見原因（回執 reason 裡會寫）：人口不夠（英雄也占人口）、錢不夠、剛陣亡不久（陣亡後約 3 遊戲秒才能復活）、\n復活已在進行（接下時引擎當場清掉那一格）。"
 },
 {
  "name": "pick_up",
  "category": "command",
  "status": "verified",
  "mechanism": "W3P target：右鍵物品",
  "latency": "快車道",
  "signature": "pick_up(hero, item)",
  "doc": "英雄去撿地上的物品（item 來自 items_on_ground）。撿到後物品欄裡會出現，地上發 item.removed 事件。"
 },
 {
  "name": "use_item",
  "category": "command",
  "status": "verified",
  "mechanism": "W3P use_item（依格位編號）",
  "latency": "快車道",
  "signature": "use_item(hero, slot: 'int', target=None, x: 'float | None' = None, y: 'float | None' = None)",
  "doc": "使用物品欄第 slot 格（0~5）的物品；可帶目標單位或目標點。\n⚠ 對點使用物品（例如象牙塔）引擎成功也回 0，回執一律算接下 —— 要看物品欄那一格空了沒有。"
 },
 {
  "name": "drop_item",
  "category": "command",
  "status": "verified",
  "mechanism": "W3P item_drop（照抄 JASS UnitDropItemPoint：dropitem 0xD0021 對點 + 物品即時目標）",
  "latency": "快車道",
  "signature": "drop_item(hero, slot: 'int', x: 'float', y: 'float')",
  "doc": "把物品欄第 slot 格的東西丟在 (x,y)（英雄走過去放下）。"
 },
 {
  "name": "give_item",
  "category": "command",
  "status": "verified",
  "mechanism": "W3P item_drop（照抄 JASS UnitDropItemTarget：dropitem 對單位）",
  "latency": "快車道",
  "signature": "give_item(hero, slot: 'int', to)",
  "doc": "把物品欄第 slot 格的東西交給 to（別的英雄/單位，走過去遞給它）。給商店 = 賣掉（見 sell_item）。"
 },
 {
  "name": "sell_item",
  "category": "command",
  "status": "verified",
  "mechanism": "同 give_item，目標是商店（實測避難權杖賣 125 金）",
  "latency": "快車道",
  "signature": "sell_item(hero, slot: 'int', shop)",
  "doc": "把物品欄第 slot 格的東西賣給商店（英雄要走到商店旁邊；可販售的物品才收，退回一半價錢）。"
 },
 {
  "name": "move_item",
  "category": "command",
  "status": "verified",
  "mechanism": "W3P target：訂單 0xD0022+格位編號，目標 = 物品（照抄 JASS UnitDropItemSlot）",
  "latency": "快車道",
  "signature": "move_item(hero, slot: 'int', to_slot: 'int')",
  "doc": "物品欄裡換格子（第 slot 格移到第 to_slot 格；兩格都有東西就互換）。整理快捷鍵位置時用。"
 },
 {
  "name": "buy",
  "category": "command",
  "status": "inferred",
  "mechanism": "W3P buy：商店賣給旁邊的英雄",
  "latency": "快車道",
  "signature": "buy(shop, item_code: 'str')",
  "doc": "在商店買物品（給站在商店旁邊的英雄）。缺少科技前置時引擎回 0、不扣錢。"
 },
 {
  "name": "call_to_arms",
  "category": "command",
  "status": "verified",
  "mechanism": "W3P immediate：townbellon/off",
  "latency": "快車道",
  "signature": "call_to_arms(hall, on: 'bool' = True)",
  "doc": "人類的戰鬥號召：農民變民兵（第一級的城鎮大廳沒有這個技能，只對主城/城堡有效）。"
 },
 {
  "name": "set_speed",
  "category": "control",
  "status": "verified",
  "mechanism": "動作 47（25~800%）",
  "latency": "控制通道",
  "signature": "set_speed(percent: 'int') -> 'bool'",
  "doc": "遊戲倍速（100 = 原速）。"
 },
 {
  "name": "pause",
  "category": "control",
  "status": "verified",
  "mechanism": "W3P pause",
  "latency": "快車道",
  "signature": "pause(on: 'bool' = True)",
  "doc": "暫停 / 繼續遊戲。暫停時引擎時鐘停止，快車道照常能下令（事件分派仍在運作）。"
 },
 {
  "name": "set_publish_period",
  "category": "control",
  "status": "verified",
  "mechanism": "世界區塊 requestedPeriodMs",
  "latency": "推送快照",
  "signature": "set_publish_period(ms: 'int') -> 'None'",
  "doc": "世界狀態的發布週期（16~1000 毫秒，預設 50）。一次採集約 0.5 ms，33 ms 也沒問題；整台機器共用一個值，以最後寫入的為準。"
 },
 {
  "name": "say",
  "category": "control",
  "status": "verified",
  "mechanism": "動作 56",
  "latency": "控制通道",
  "signature": "say(u, text: 'str', seconds: 'float' = 4.0) -> 'bool'",
  "doc": "單位頭頂冒出一個聊天氣泡（直播/除錯用，不影響遊戲）。沒冒出來會回傳 False，原因在 g.last_say_error。"
 },
 {
  "name": "message",
  "category": "control",
  "status": "inferred",
  "mechanism": "動作 45",
  "latency": "控制通道",
  "signature": "message(text: 'str') -> 'bool'",
  "doc": "在遊戲左下角的訊息區印出一行字（只有本機看得見）。要等遊戲自己先跳出過一條提示（DLL 從那一次抓取訊息框）。"
 },
 {
  "name": "end_game",
  "category": "control",
  "status": "verified",
  "mechanism": "動作 22",
  "latency": "控制通道",
  "signature": "end_game() -> 'bool'",
  "doc": "結束這個遊戲行程（farm.py --keep 會依 next_game.json 自動開下一局）。"
 },
 {
  "name": "canvas",
  "category": "control",
  "status": "verified",
  "mechanism": "W3P 73 canvas_enable + 共用記憶體 Local\\War3Canvas_<pid>（執行環境每幀在遊戲畫滑鼠游標之前繪製，游標蓋在上面）",
  "latency": "共用記憶體",
  "signature": "canvas()",
  "doc": "畫板：在遊戲畫面上畫文字框、面板、進度條、圖片、地上的圈和路線（openwar3.canvas.Canvas）。\n由執行環境自行繪製，不建立遊戲控制代碼、不改變遊戲狀態 —— 多人局也安全；樣式隨你定（中文、圓角、半透明）。"
 },
 {
  "name": "press_to_continue",
  "category": "control",
  "status": "verified",
  "mechanism": "PostMessage WM_KEYDOWN/UP 空白鍵到遊戲視窗（不搶焦點）",
  "latency": "視窗訊息",
  "signature": "press_to_continue() -> 'bool'",
  "doc": "在「按下任意鍵以繼續」的載入畫面上按一下空白鍵。很多 RPG / 劇情地圖載入完成後要按鍵才會開始（09-24 WarChasers 實測：\n不按就一直停在載入畫面，遊戲時鐘為 0、快車道不會清空）。openwar3.run 等待進入對局時會自己按，一般不用手動呼叫。"
 },
 {
  "name": "map_data",
  "category": "observe",
  "status": "verified",
  "mechanism": "地圖檔案（啟動器 --map 的路徑）：w3u/w3t/w3a + wts，受保護的地圖讀取圖內的 TXT",
  "latency": "讀取檔案（第一次約 0.1 秒）",
  "signature": "map_data()",
  "doc": "目前這張地圖的資料（openwar3.mapdata.MapData）：name_of('HC07') 自訂單位/物品/技能的名稱、hero_names、tooltip。\nRPG 地圖的單位大多是地圖自己做的，內建名稱表裡沒有；不是由啟動器開啟的遊戲（找不到地圖檔案）回傳 None。"
 },
 {
  "name": "jass",
  "category": "sandbox",
  "status": "verified",
  "mechanism": "W3P 70 jass（執行環境依名稱查詢 native 表，1291 個）",
  "latency": "快車道",
  "signature": "jass()",
  "doc": "依名稱呼叫任意 JASS native：g.jass.CreateUnit(g.jass.Player(1), \"Hpal\", x, y, 270.0)。\n參數 I/R/B/S/H 自動轉換（單位/物品物件直接傳入），多人局裡只能呼叫唯讀的。詳見 openwar3/jass.py 和 docs/COMPANION_ZH.md。"
 },
 {
  "name": "player_slots",
  "category": "sandbox",
  "status": "verified",
  "mechanism": "JASS GetPlayerController / GetPlayerSlotState / IsPlayerAlly",
  "latency": "快車道",
  "signature": "player_slots() -> 'list[dict]'",
  "doc": "16 個玩家槽位：controller（user 真人 / computer / neutral…）、state（empty / playing / left）、human、me、ally（和我是不是盟友）。\n在 RPG 地圖裡找空槽位放玩伴、判斷是不是單人局，都用它。"
 },
 {
  "name": "spawn",
  "category": "sandbox",
  "status": "verified",
  "mechanism": "JASS CreateUnit + W3P 72 控制代碼 -> 單位",
  "latency": "快車道",
  "signature": "spawn(code: 'str', x: 'float', y: 'float', player: 'int | None' = None, facing: 'float' = 270.0)",
  "doc": "在 (x,y) 建立一個單位（player 預設為本機玩家），回傳快照裡的單位（要等下一次世界發布，約 50 ms）；建立失敗時回傳 None。\n回傳的單位多一個屬性 jass_handle。⚠ 只能在單人局使用（多人局會不同步）。"
 },
 {
  "name": "set_alliance",
  "category": "sandbox",
  "status": "verified",
  "mechanism": "JASS SetPlayerAlliance",
  "latency": "快車道",
  "signature": "set_alliance(a: 'int', b: 'int', allied: 'bool' = True, vision: 'bool' = True, control: 'bool' = False, xp: 'bool' = False, both: 'bool' = True) -> 'None'",
  "doc": "設定玩家 a 對 b 的同盟關係：allied = 不互相攻擊 + 互相求援；vision 共享視野；control 共享單位控制權（b 能指揮 a 的單位）；\nxp 分享經驗。both=True 兩個方向一起設定（control 只設定 a -> b）。"
 },
 {
  "name": "set_player_name",
  "category": "sandbox",
  "status": "verified",
  "mechanism": "JASS SetPlayerName",
  "latency": "快車道",
  "signature": "set_player_name(player: 'int', name: 'str') -> 'None'",
  "doc": "修改玩家名稱（計分板、聊天、盟友面板裡顯示的那個）。用來幫玩伴取名字。"
 },
 {
  "name": "show_text",
  "category": "sandbox",
  "status": "verified",
  "mechanism": "JASS DisplayTimedTextToPlayer",
  "latency": "快車道",
  "signature": "show_text(text: 'str', seconds: 'float' = 6.0, player: 'int | None' = None) -> 'None'",
  "doc": "在畫面左下角顯示一行字（地圖觸發器用的那種文字），預設顯示給本機玩家。支援 |cffRRGGBB 顏色碼。"
 }
]