# 回执与原因码

> 每条命令的回执都带状态码和原因码。它们是 Bot 和 Agent 自我纠错的依据：把「为什么没做成」变成机器可读的数字。

来源: https://war3ai.com/docs/reason-codes/

```python
r = g.train(barracks, "hfoo")
bool(r)        # False
r.status       # 1              -> rejected
r.verdict      # 3              -> 人口不够
r.reason       # 'rejected（人口不够）'
r.exec_us      # 这条在游戏线程上执行了几微秒
```

`if r:` 等价于 `r.status == 0`（引擎接下了）。

## 状态码 `status`

| 码 | 名字 | 含义 | 常见原因 |
|---|---|---|---|
| 0 | `accepted` | 引擎接下了 | —（但接下 ≠ 做成，见下） |
| 1 | `rejected` | 被引擎拒绝 | 看 `verdict` |
| 2 | `bad_unit` | 单位不存在或句柄对不上 | 单位已经死了；用了过期的单位对象 |
| 3 | `not_owner` | 不是你的单位 | 以 `player` 身份指挥别人的单位 |
| 4 | `fault` | 执行时异常（运行时已兜住，不会拖垮游戏） | 请带着复现步骤反馈 |
| 5 | `bad_args` | 参数错 | 坐标、格号、四字码写错 |
| 6 | `unsupported` | 不支持 | 这个版本的运行时没有这项能力 |
| 7 | `bad_target` | 目标无效 | 目标已经没了；目标类型不对 |
| 8 | `forbidden` | 车道角色不允许 | 以 `observer` 身份下令 |
| 97 | `cancelled` | 批量块里抛了异常，整批没发出去 | `with g.batch():` 块里的代码报错 |
| 98 | `held` | 单位被更高优先级的层握着，没发出去 | 参考大脑的毫秒层、指挥台的手动下令正握着这个单位 |
| 99 | `timeout` | 超时 | 游戏暂停 / 卡顿时超过了截止时间（过期的命令不会再执行） |

## 原因码 `verdict`

被拒时，运行时会用引擎自己的可行性检查说明原因。也可以不下令、先问：`g.can_do(单位, 四字码)` 返回同样的码。

| 码 | 含义 | 怎么办 |
|---|---|---|
| 0 / 220 | 可以 | — |
| 3 | 人口不够 | 盖人口建筑；看 `g.production(b).blocked` 提前发现 |
| 8 | 金不够 | 等钱；下令前用 `g.can_afford(code)` |
| 9 | 木不够 | 多派人砍树 |
| 32 | 训练队列满（7 格） | 队列只排 1 个：`g.queue(b)` 空了再排 |
| 183 | 缺前置科技 / 建筑 | 先盖前置建筑、升本 |
| 185 | 建筑正忙 | 祭坛正在复活英雄；大厅队列没空时不能升级 |
| 221 | 没有这一项 / 建造中 / 升级中 / 已存在 | 英雄已经有了（死了要 `revive`）；这家店不卖这个 |
| 89 | 商店还没到货 | 开局按物品表的上架时间才有货；现造的商店从造好那一刻才开始算 |
| 1001 | 目标看不见 | 目标在迷雾或黑区里；对它的位置 `attack_move` |

## 接下 ≠ 做成

回执只说明「引擎接了这条命令」，是同一帧里读回来的。之后可能发生的事情它管不到：

| 命令 | 回执接下之后仍可能失败 | 怎么确认 |
|---|---|---|
| 建造 | 树林里的点也当场接下，工人走到才失败 | 用 `build_near`（跟踪地基是否出现），或等 `production.done` |
| 施法 | 被打断、没蓝 | 下一拍看 `g.cooldown(u, 技能)` 有没有进冷却 |
| 训练 | 排进队列但人口不够、一直不开始 | `g.production(b).blocked` |
| 移动 / 攻击 | 被别的逻辑（或更高优先级的层）改掉 | `g.current_target(u)`、`g.order_of(u)` |

## 查询接口

以下接口不下令，只问引擎，结果也放在回执的 `value` 里（SDK 直接返回值）：

| 接口 | 返回 |
|---|---|
| `g.can_do(u, code)` / `g.can_do_many([(u, code), ...])` | 上表的原因码 |
| `g.tech(code, player=None)` / `g.tech_many([...])` | 研究等级 / 建完的建筑数（升级链算在内） |
| `g.visible(x, y)` | 这一点我方看不看得见 |
| `g.gold_left(mine)` | 金矿还剩多少金 |
| `g.enemy_ai_plan(敌兵)` | 电脑对手的队长要带兵去哪（只对电脑 AI 有效） |
