文档 指南
调试与性能
一拍为什么慢、命令为什么没生效、游戏为什么不动。按现象排查,再用自带的实机核对脚本确认。
看回执
每条命令的回执就是第一手线索:
r = g.cast(hero, "blizzard", x=tx, y=ty)
if not r:
print(r.reason, r.verdict) # rejected(…) 以及原因码
print(r.exec_us, r.engine_us) # 这条在游戏线程上执行了多少微秒 / 其中引擎下令函数本身花了多少
正常情况下一条命令在游戏线程上花几微秒到几百微秒。批量块结束后,g.last_receipts 是这一批每条的回执。
在游戏里看
g.say(unit, "撤") # 单位头顶冒一个聊天气泡(不影响游戏)
g.message("开始打野") # 左下角消息区打一行字(只有本机看得见)
print 的内容会出现在运行 Bot 的终端里。把每拍的关键决策打印出来,配合头顶气泡,比看代码快得多。
一拍很慢
先看是不是这几种情况:
| 原因 | 改法 |
|---|---|
| 一条一条发命令,每条都等一帧 | 包进 with g.batch():,几十条只等一次 |
逐个调 g.visible() / g.can_do()(每次都走快车道等一帧) | 可见性用快照里的 u.visible_to();可行性用 g.can_do_many([...]) 一批问 |
在 on_tick 里 sleep 或等待 | 记下游戏时间,下一拍再判断 |
| 每拍重算很贵的东西(寻路、全图扫描) | 缓存结果,隔几拍再算。g.grid() 自带 2 秒缓存,g.stats() 的科技等级 5 秒缓存一次 |
游戏不动 / Bot 等不到进局
| 现象 | 多半是 |
|---|---|
| 一直「等进局」 | 实例号不对;或者游戏窗口最小化了 —— 最小化时游戏模拟是停着的(时钟不走) |
| 游戏在跑、Bot 下令没反应 | 在给别人的单位下令(回执 not_owner);或者 Bot 以 observer 身份连接(forbidden) |
命令被 held | 这个单位被更高优先级的层握着(参考大脑的毫秒层、指挥台的手动下令),没发出去 |
| 暂停后命令还能下 | 正常:暂停时引擎时钟停住,但事件分发照跑、命令照常执行 |
连一下看状态
python -m openwar3 status --inst 5
输出连接状态:游戏 pid、世界发布周期和每次采集耗时、快车道计数、是否在局里、单位数、游戏时钟。
实机核对脚本
开一个演练实例,逐项核对 SDK 能力是否在你的机器上正常:
python tools/sdk_live_check.py --inst 20 # 全部
python tools/sdk_live_check.py --inst 20 --only prod # 只核对一节
分节:批量、时间、生产、排队下令、战斗属性、寻路、公平模式。每一节都会在真实对局里下命令、读回效果,打印通过数。
离线测试不需要开游戏:
python tools/run_tests.py
常见的「看起来像 bug」
- 盖房子回执接下了,但一直没地基:树林里的点引擎也当场接下,工人走到才失败。用
build_near,它会跟踪并把失败的点拉黑一段时间。 - 技能回执接下了,但没放出来:被打断了,或者没蓝。放完下一拍看
g.cooldown()有没有进冷却。 - 攻击令接下了,但兵去打别人:对具体目标攻击要用
g.attack(兵, 敌人)(右键语义)。原始的攻击令对目标只换订单、不记目标,会去打附近别的。 - 工人数对不上:进了金矿的工人不在快照里。
- 死了的英雄训练不出来:英雄唯一,要
g.revive(祭坛);复活要人口,死后约 3 游戏秒才能复活。