刚入职网易的时候,有一道作业是给坦克大战写自动化脚本。那时我就想:能不能用强化学习,让坦克自己学会打?想法有了,可惜一直不会做。

最近借助 Claude Code,我终于把这份拖了很久的作业重新捡了起来。我想试一试:现在有 AI 帮忙写代码,当年那个只停在脑子里的想法,能不能一路做成一个真正跑得起来的东西?

这次前后用了大约 100 美元的 Claude Code 额度。标题里的「100 美元」说的就是这笔 AI 编程工具的用量,花在实现、修改和排查问题的过程中,不是强化学习训练的算力费用。

过程从强化学习开始,后来转向规则和模拟搜索,中间不断回头检查:眼前的实现,离完成这份作业还有多远?先玩一局,再按这条线看看我是怎么走过来的。

先看做出来的版本:和 AI 同守一个基地

点击下面的「运行实验」就能玩。金色坦克是你,绿色坦克是 AI。你们各有生命和得分,共用底部的基地,但各打各的:AI 不会配合你,也不会替你挡子弹。

坦克大战双人协作驾驶你的坦克,与 AI 队友并肩作战,守护基地、一起闯关。
  1. 你来驾驶
  2. AI 协作
  3. 守护基地

从第 1 关出发,与 AI 并肩作战 · 支持键盘与触控

先点击游戏画面,用 WASD 或方向键移动,空格或 J 开火;手机可以同时按住方向键和开火键。画面太小,可以点「放大」。

玩的时候,可以留意右侧「AI 正在做什么」:它什么时候追敌人,什么时候回防,什么时候躲子弹。观察这些具体行为,比只看程序有没有运行、分数有没有上涨,更容易发现接下来该改哪里。

网页里的 AI 边玩边决策,用的是后面讲的「规则 + 前瞻检查」。原项目还有一个先规划整关路线的自动闯关模式,没有搬到网页上,后面单独说。

先让 AI 帮我试一试当年的想法

当年一直惦记的是强化学习,这次也从这里开始。借助 Claude Code 把想法落实成程序,我尝试用 PPO 训练坦克:让它反复玩,根据结果一点点调整打法。过去卡在「不会实现」的地方,总算有了一个可以跑、可以观察的起点。

但程序运行起来以后,新的问题也就出现了。我想要的「会打坦克」,得变成程序能接收的观察、能执行的动作和能衡量的结果。AI 可以帮忙实现这些东西,每一项究竟有没有表达清楚,还是要放回游戏里看。

一点背景:强化学习和 PPO 在做什么

假如要教一个没玩过坦克大战的人,你可以让他反复尝试,再告诉他哪些结果值得鼓励。强化学习做的事情有点像这样:程序观察局面、选择动作,游戏给出反馈,它再根据这些经历调整打法。

  • 观察:坦克在哪,敌人在哪,子弹往哪飞,基地附近是否安全。

  • 动作:往哪个方向走,要不要开火;也可以先把动作封装成「追击」「回防」等任务。

  • 奖励:用数字表达好坏,例如击毁敌人加分、自己阵亡扣分、基地被毁重扣分。这是训练用的信号,可以和游戏原本的得分不同。

  • 策略:根据当前观察决定下一步怎么做。训练就是逐渐调整这个决策办法。

关键是,它追求的是一段过程里累计的奖励。眼前躲开一颗子弹可能不错,但如果一路躲到地图上方,把基地让给敌人,最后还是输了。奖励需要让它逐渐学会这种取舍。基本概念可以参考 Spinning Up 的强化学习入门。

这次尝试的是 PPO,一种常见的强化学习算法。可以先把它理解成:让坦克玩一批游戏,根据结果调整一点打法,再去玩下一批。

代码跑起来以后,问题才具体起来

杀敌、保命、守家,会互相打架

想象这样一个局面:上方有一辆快被打掉的敌人,下方另一辆正在靠近基地。追上去,很可能马上拿到杀敌奖励;回头守家,却可能暂时什么分也拿不到。

如果奖励太看重杀敌,它可能追得很开心,回头发现家没了;如果太看重保命或守家,它又可能缩在基地附近,迟迟清不完敌人。项目里就遇到过保命和防守奖励失衡的问题。

所以,下一轮该让 AI 帮我改什么,不能只说「让它聪明一点」。得先说清楚:基地和一条命哪个更重要?什么时候应该冒险?这些取舍写进奖励后,还要通过坦克的实际表现反复校正。

通一关和连过 35 关,是两个目标

在这次探索里,我又把目标推到了连续闯关。单关训练可以每次重新给三条命,连续闯关却要把剩余生命带到下一关。如果为了快速过第一关花掉两条命,单关成绩看着不错,后面就很难打了。

打个简化的比方:假设每关都独立地有 95% 的通关概率,连续过 35 关的概率也只有约 17%。真实游戏里的各关并不独立,生命和得分还会延续;这个例子只是说明,局部表现好,离稳定打完整局还有很远。

而且,基地被击毁时,真正的错误可能早在几秒前就发生了:那时坦克离家太远,或者放任敌人打穿了围墙。训练需要把最后的失败和之前的决策联系起来。

接下来,是继续调,还是换条路?

这次训练出来的策略,在连续通关上没有超过后来的规则与搜索方案。它让我开始重新考虑:接下来继续调奖励,还是先换一种能把任务做成的办法?这份旧作业终于能动手做了,具体路线也可以随着实际结果调整。

调好奖励与鼓励探索的参数尺度以后,训练策略在连续通关上仍未超过规则与搜索,于是我把重点转向了更容易检查的方案。对这份作业来说,训练曲线变了还不够,得看坦克是否真的更能守家、活下来、继续闯关。项目的 AI 说明记录了这段取舍。

这次尝试能说明什么

强化学习往往需要大量交互,奖励设计和评估也需要反复调整。Stable Baselines3 的实践指南同样建议从简单环境起步,并用独立的测试环境评估。这次有限的探索,只能说明当时那套实现的表现,不能替整个方法下结论。

换条路,先把这份作业做出来

回头看,原来的作业是给坦克大战写自动化脚本,强化学习是我当时想尝试的办法。现在手里已经有游戏规则和源码,还能复制当前局面,让一个模拟副本先跑几步。于是,接下来借助 AI 实现的方向,就变成把已有的游戏经验写成规则,再用模拟检查照着做会发生什么。

先把经验写出来

规则策略会检查附近的子弹、敌人与基地的距离、围墙缺口和道具,再决定当前要做的事。例如:

  • 附近有迫近的弹道,先尝试躲避。

  • 敌人靠近基地,考虑拦截;围墙有缺口时,必要时用坦克堵住射线。

  • 有值得拿的道具,就考虑拾取;有合适的射击目标,就对齐开火。

  • 没有更紧急的任务,再追击附近敌人或回防。

再让每个决定都能先试一下

只写规则还不够。规则可能判断「这辆敌人最近,去追它」,但拐过墙角才发现一颗子弹正好迎面飞来。前瞻护盾就是在行动之前,把这个方案放进模拟副本里先演一遍。

规则提出动作 → 模拟接下来会发生什么 → 检查危险 → 执行或换一个动作

这条路线对继续修改程序很有帮助:看到坦克做了一个糟糕的决定,可以沿着「规则选了什么、模拟看到了什么、最后为什么执行」往回找。接下来要改的对象,也就具体到了某条规则、某次危险判断或一个候选动作。

实现细节:宏动作和前瞻窗口

这些是「宏动作」:先决定一个短期任务,再由控制器落实成每一帧的移动和开火。当前实现通常每 10 帧重新选一次任务。这样就能把「现在该守家还是追人」和「这一帧向左还是向右」分开处理。

默认的前瞻窗口是 120 帧;按游戏每帧 20 毫秒算,大约是往前看 2.4 秒。如果模拟发现动作会导致阵亡或基地被毁,就比较躲避、回防等候选方案;普通方案都危险时,还会尝试更细的规避动作。

这里的「护盾」是决策检查,不是给坦克套上无敌道具。它只能帮助减少看得见的危险,无法保证所有局面都有解。坦克已经离基地太远时,就算提前看到了危险,也可能赶不回来。

回到游戏里,看看护盾的作用

试玩时,可以先保持第 1 关和 1× 速度,观察 AI 的动作,再切换护盾模式:

  • 关闭:看看只靠规则时,哪些决定会让它陷入危险。

  • 前瞻否决:看看它是否会放弃危险动作,右侧「护盾改判」也会记录调整次数。

  • 逐关调优:使用按关卡调整的参数,部分局面会做更多模拟搜索。

切换护盾或起始关卡会重新开局,调整速度和决策叠加层可以继续当前对局。因为你也参与操作,两次试玩很难做到条件完全相同;适合观察行为差异,别把一局输赢当成严格的算法对比。

接着把目标推到连续闯关

原项目的自动闯关模式在此基础上,又增加了整关轨迹搜索:从关卡起点复制状态,尝试不同的动作路线,找到能过关、又尽量少丢命的路线,再交给真正的游戏执行。

像下棋时先在脑中推演几条变化,选好以后才落子。试错发生在模拟副本中,真实对局按选定路线走;关卡之间继续携带生命、得分和随机数状态。

走到这一步,检查的重点又变了:模拟器里的结果,能不能在真正的游戏里重现?相同的状态、动作和随机数状态,应该产生相同的后续局面。因此项目还会把动作放回原版游戏逐帧核对。模拟里打得好、实际一执行就走样,那条路线就没有用。

历史通关记录,以及它的适用范围

原项目的历史验收中,整关规划方案曾在 20 个连续测试种子上全部打通 35 关,真实对局没有失败后重试或读档。具体结果见 连续通关记录。这说明当时那批测试有效,不能推成任何局面都能过。

这些数字来自修复原版定时器等问题之前的游戏版本。修复改变了敌人开火、出生和随机数消耗,旧的通关率需要重新测;它也不是上面这个网页版的胜率。

放进网页,方案也要跟着条件变

后来把它放进网页,让读者也能上手,原来的条件又变了。整关规划需要先找到一条可以复现的路线;但你一上手,每一次移动和开火都会改变局面,提前算好的路线就可能对不上。所以网页里的 AI 只用规则和前瞻检查,随当前局面不断决策。它仍可能犯错,也可能输掉一局。

网页版的「逐关调优」和整关规划有什么区别

这也是它和护盾里「逐关调优」的区别。逐关调优在关键时刻也会把整关模拟到底,但只是为了挑出眼前这一步,走出去就收不回;整关规划则是先在副本里把这一关打赢,再照着打,失败的尝试都只发生在副本里。

同一份代码,换一个使用方式,就要重新考虑哪些假设还成立。这个网页版保留了一个可以直接观察的结果:你既能和它一起玩,也能看到它什么时候做对、什么时候没来得及守住基地。

补完旧作业,也走了一遍和 AI 一起做事的过程

回头看,这次探索里反复做的事,是把一个模糊的想法变成具体目标,借助 Claude Code 写出实现,运行起来看表现,再决定下一步改什么。从 PPO 换到规则和搜索,也是这个过程里的一次调整。

AI 帮我把当年不会实现的想法变成了可以尝试的东西。至于坦克应该优先守家还是追人,怎样才算完成任务,哪些测试结果还能相信,这些问题都得在做的过程中逐个想清楚。代码有了,探索才真正展开。

大约 100 美元的 Claude Code 额度,最后留下了一个可以玩、也能解释的坦克程序,还有这次从想法到实现、再不断调整方向的经历。拖了很久的作业,总算补上了。有兴趣的话,回到上面的游戏,和这个有时机灵、有时也会犯错的 AI 一起打一局。

源码:syntomic/battle-city。

全文评论

0

正在加载评论…