# 十五条规矩

> 每一条都是在真实对局里踩出来的。写 Bot 时对照一遍，能省掉大部分排查时间。

来源: https://war3ai.com/docs/rules/

> **提示**
>
> 把这一页和 [`api.json`](https://war3ai.com/api.json) 一起交给大模型，它写出来的 Bot 会少走很多弯路。

## 读状态

### 1. 读不到是 `None`，不是 0

`resources()`、`time_of_day()`、`production()`、`cooldown()` 都可能返回 `None`（载入中、单位没有细节、建筑没在生产……）。先判断再用：

```python
res = g.resources()
if res is None:
    return
```

### 2. 用句柄认单位，别用地址

地址会被新单位复用：旧地址可能指到一个新出生的单位上。要跨拍记住某个单位，存 `u.handle`，用 `g.unit(handle)` 找回来。

### 3. 事件流是全局的

`production.done`、`unit.died` 里有对手的、野怪的。按 `ev.owner`（或建筑句柄）过滤：

```python
if ev.kind == "production.done" and ev.owner == g.me():
    ...
```

### 4. 进了金矿的工人不在快照里

工人进金矿那一下会从快照里消失（`unit.removed`，不是死了）。要统计每座矿几个人，**自己记账**，别按快照剪账 —— 否则会往满矿里多派人。

## 下命令

### 5. 回执「接下」≠ 做成

树林里的建造点引擎也当场接下，工人走到才失败；技能可能被打断。效果看快照和事件：盖房子用 `build_near`（它跟踪地基是否出现），放技能看 `g.cooldown()` 有没有进冷却。

### 6. 看不见的目标不能打

对迷雾里的敌人下目标命令会被拒，原因码 **1001**。想追迷雾里的敌人，对它最后出现的位置 `attack_move`。

### 7. 只给闲着的单位下令

每拍给同一个单位重下同一条命令会打断它：兵在原地抽搐，农民的采集周期归零。判断「闲不闲」用 `g.order_of(u)`（含你这一拍刚下的），别用快照里的 `u.order`（快照还没追上）。

### 8. Shift 只有「插在当前后面」

引擎没有「追加到末尾」：连着用 `queue='after'` 发 B、C，会得到 A、C、B。按顺序走一串点用 `g.path(units, 点列表)`，一个工人连造几座用 `g.build_queue(worker, 计划)` —— 它们会倒序插入，替你处理好。

### 9. 一拍的命令一批发

几十条命令逐条发，要等几十次游戏线程；包进 `with g.batch():` 只等一次。

## 经济与生产

### 10. 一矿最多 5 个工人

再多不涨收入。工人目标跟着矿数走：每座矿 5 个采金，再加几个伐木。

### 11. 训练队列只排 1 个

排满 7 格会把钱锁在队列里（实测大厅排了 4 个农民、300 金锁住，开局慢一大截）。`g.queue(b)` 空了再排下一个。

### 12. 人口卡住看生产表

`g.production(b).blocked` = 有排队但没开始，多半是人口不够。它比「人口快满了再盖」早一步：打仗掉了一片兵、补兵时队列一卡就知道。

### 13. 英雄唯一，大厅队列没空时不能升本

- 英雄死了只能 `g.revive(祭坛)`，再训练会被拒（221）；复活也要人口（英雄占 5）。
- 大厅队列里还有东西时不能升级大厅（原因码 185，「建筑正忙」）。

## 时间与空间

### 14. 2 倍速下别按墙钟等

想等 3 游戏秒，就看 `g.clock()` 涨了 3，不是 `sleep(1.5)`。倍速下引擎时钟比墙钟走得快。

### 15. 岛图、树林图别用直线距离

选野点、选分矿用 `g.path_distance(a, b)`（地面 A*，绕树林、悬崖、建筑），走不到返回 `None`。直线最近的那个点，可能在海对面。

## 还有一条：按公平模式写

`--fair` 下只看得见视野里的单位、物品、生产和事件，擂台就是这个规则。现在就按公平模式写，将来上 [对战平台](https://war3ai.com/arena/) 不用改。详见 [公平模式](https://war3ai.com/docs/fair-mode/)。
