文档 参考
回执与原因码
每条命令的回执都带状态码和原因码。它们是 Bot 和 Agent 自我纠错的依据:把「为什么没做成」变成机器可读的数字。
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 有效) |