# 用 LLM 寫一個 Bot

> 不會寫程式也能做：你負責說清楚想要它怎麼打，LLM 負責寫程式碼。複製提示詞範本，描述打法，跑起來，再讓它修改。

來源: https://war3ai.com/zh-tw/docs/ai-bot/

適合會玩魔獸、不會寫程式的人，也適合想省時間的開發者。整個過程就是一段對話：**你描述打法 → 模型寫程式碼 → 你跑一局 → 把看到的現象告訴模型 → 它修改**。

> **提示**
>
> 先依照 [快速開始](https://war3ai.com/zh-tw/docs/quickstart/) 把環境裝好，並跑通 `hello_bot`（看到農民去採礦）。這樣出問題時，你才分得清是環境的問題還是 Bot 的問題。

## 1. 幫模型準備資料

模型寫得好不好，八成取決於它有沒有讀到正確的資料。依你用的工具選一種：

| 你用的是 | 怎麼提供資料 |
|---|---|
| **能讀取儲存庫的 Coding Agent**（Claude Code、Cursor、Codex 等） | 在儲存庫目錄裡開啟它，讓它先讀 `docs/BOT_HANDBOOK_ZH.md`、`docs/api.json` 和一個範例（運營看 `brains/examples/macro_bot.py`，戰鬥看 `micro_bot.py`） |
| **能上網的對話模型** | 讓它先讀 [`https://war3ai.com/llms-full.txt`](https://war3ai.com/zh-tw/llms-full.txt)，全站文件都在這一個檔案裡 |
| **網頁對話、不能上網** | 把手冊、[`api.json`](https://war3ai.com/zh-tw/api.json) 和一個範例檔案貼在提示詞後面 |
| **本機模型**（LM Studio、Ollama） | 同上。上下文視窗建議 32K token 以上，否則放不下手冊和 API 目錄 |

想要某種職業打法，再把 [職業打法食譜](https://war3ai.com/zh-tw/docs/cookbook/) 裡對應的那一招貼上。

## 2. 複製這段提示詞

把最後的「我想要的打法」換成你自己的話，越具體越好：

```text
你要為《魔獸爭霸 III》1.27 寫一個 AI（Python）。只能使用 api.json 裡列出的 Game 方法，
不要編造不存在的方法。寫法參照 rush_bot.py：繼承 openwar3.Bot，實作 on_start(g) 和 on_tick(g)。

規則：
- on_tick 每秒大約呼叫 5 次，要快（別在裡面 sleep）。
- 讀不到的值是 None，不是 0，先判斷再使用。
- 命令會回傳一張回執（Receipt），`if r:` 就代表「引擎接下了」；沒接下時 `r.reason` 寫著原因
  （人口不夠、金不夠、目標看不見、這個英雄已經有了……），下一拍再試，或者換個做法。
- 攻擊一個具體的敵人用 g.attack(兵, 敵人)；敵人必須在視野內，看不見的會被拒。
- 英雄陣亡要用 g.revive(祭壇) 復活，不能再訓練一個。
- 蓋房子用 g.build_near(工人, 建築代碼, x, y)：它會自己找放得下的位置、追蹤結果，錢不夠時什麼也不做。
- 想知道「剛才發生了什麼」（誰死了、誰掉血、英雄升級、物品掉落）就實作 on_event(g, ev)。
- 不要每一拍都對同一個單位重複下同一條命令（會打斷它正在做的事）；只對「閒著的」下令。
- 採集只派 idle_workers() 裡的工人。一座金礦最多 5 個工人。
- 訓練佇列只排 1 個（g.queue(建築) 空了再排）；人口卡住看 g.production(建築).blocked。
- 一拍要下很多條命令時，包在 with g.batch(): 裡（只等一次遊戲執行緒）。
- 選打誰用 g.time_to_kill(我方一群, 敵人)（已算入克制和護甲）；選去哪裡用 g.path_distance（走不到會回傳 None）。
- 公平模式下只看得見視野內的東西；以前看到過的敵人用 g.last_seen()。
- 單位用四字碼表示（人類農民 hpea、步兵 hfoo、兵營 hbar……），技能用訂單名（thunderbolt 風暴之錘、
  blizzard 暴風雪、holybolt 聖光術……，完整列表在 data/order-ids.txt），學習技能用四字碼（AHtb、AHbz……）。

我想要的打法：
<在這裡用白話寫，例如：
  「人類，開局 5 個農民採金、1 個伐木；先出大魔導師；兩座兵營出步兵和火槍兵；
   存到 12 個兵帶著英雄去打對面分礦；英雄血量低於 30% 就撤回家；
   打野時優先打離家近的營地。」>
```

### 怎麼把打法說清楚

模型最怕含糊的要求。比起「打得兇一點」，下面這些資訊更有用：

- **種族和英雄**：先出哪個英雄、技能加點順序（例如大魔導師：水元素、暴風雪、水元素……）。
- **建造順序**：第幾個農民時蓋兵營、什麼時候升級主城、要幾座兵營。
- **出兵組合**：步兵 + 火槍兵？到多少數量出門？
- **進退條件**：存到多少兵出擊、英雄血量低於多少撤退、打殘了回家重新集結。
- **打野**：打不打、什麼時候打（天黑後？）、只打打得過的點？
- **是否公平**：將來要上擂台就說「只用視野內看得見的敵人」。

## 3. 跑起來

把模型給的程式碼存成 `brains/my_bot.py`，然後：

```bash
python tools/play.py --bot brains/my_bot.py --race 1 --difficulty 2
```

想快點看到結果，加上 `--speed 200`（2 倍速）。

## 4. 讓它修改

- **出錯了**：把**完整的錯誤訊息**原封不動貼回給模型，說「修一下」。
- **打得不好**：描述你**在遊戲裡看到了什麼**，而不是你猜的原因。例如「英雄一直站在家裡不動」「兵一個一個送上去」「農民擠在同一座礦上」。
- **想加新打法**：一次只加一件事，跑一局確認沒壞，再加下一件。

> **說明**
>
> 能自己執行命令的 Coding Agent 可以把第 3、4 步也接手：跑一局、讀日誌和回執、改程式碼、再跑。怎麼讓它看到足夠的資訊，見 [Agent 自主迭代](https://war3ai.com/zh-tw/docs/agent-loop/)。

## 5. 常見問題

| 現象 | 多半是 |
|---|---|
| 什麼都不動 | 實例編號不對（`--inst`），或者遊戲還沒進入對局 |
| 農民不採礦 | 對正在工作的農民下了令；只派 `idle_workers()` 裡的 |
| 一直蓋不出房子 | 用 `build_near`，別把座標寫死；看回執的 `reason` 是不是錢不夠 |
| 英雄出不來 | 看 `train` 的回執：人口不夠？還是英雄陣亡了（要 `revive`）？ |
| 英雄不放技能 | 沒學（`learn`）或者沒魔力；放完看 `cooldown()` 有沒有進入冷卻 |
| 兵一拍一拍地抽搐 | 每拍都在重新下命令；只對閒著的單位下令 |
| 兵出不來、錢一直漲 | 人口卡住了：看 `g.production(兵營).blocked` |
| 模型用了不存在的方法 | 在提示詞裡再強調一遍「只能用 api.json 裡的方法」，並把 api.json 完整貼上 |

## 進階

- 全部 API 和每個 API 的底層機制：[API 目錄](https://war3ai.com/zh-tw/api/)；
- 參考大腦（`brains/xwar3/strategy`）是一個完整的、會開礦打野出擊的 AI，可以讓模型讀它的思路，但它用的是更底層的 API，不建議直接照抄；
- 將來上 [對戰平台](https://war3ai.com/zh-tw/arena/) 時只能看見視野內的敵人 —— 現在就加上 `--fair` 自我約束，將來就不用改。
