1. 从一条标题说起:让模型独立打完一局《文明7》到底难在哪
第一次看到“让模型独立玩130回合《文明7》”这个说法,我脑子里冒出来的不是“哇好酷”,而是三个很实际的问题:它怎么知道当前局面?它怎么把决策变成游戏里的操作?130回合这么长的链路,中间断了怎么办?这三个问题,恰恰就是这类“让大模型接管一款复杂策略游戏”项目的全部难点所在。
先把结论摆前面:让一个语言模型“玩”《文明7》,本质上不是让它去理解游戏画面,而是把它当成一个决策大脑,外面套一层感知层(读游戏状态)和一层执行层(把决策变成键鼠或接口调用)。真正的工作量,八成花在感知和执行这两层,模型本身反而只占两成。很多人一上来就想着怎么调提示词,结果发现模型答得挺好,但游戏根本没动——因为没人把它的回答翻译成游戏能接受的操作。
这篇东西适合三类人看:一是想拿大模型做自动化决策、Agent 编排的开发者;二是对“AI 玩游戏”这类实验感兴趣、想自己复现的折腾党;三是单纯好奇长链路 Agent 到底会崩在哪、怎么兜底的人。我会把整个思路、关键环节、参数取舍、踩坑记录都摊开讲,尽量让你看完能自己搭一个能跑起来的版本,而不是只停留在“听起来很厉害”。
需要提前说明的是,下面涉及的具体实现细节,有一部分是基于这类项目的常见工程实践做的合理补全,因为原始描述只给了一个标题和结果(130回合),没有给技术栈。我会明确标注哪些是通用做法、哪些是我个人的取舍建议,你按自己环境调整即可。
2. 整体设计思路:为什么是“外挂大脑”而不是“端到端”
2.1 核心架构:感知、决策、执行三段式
让模型玩游戏,最容易想到的是“端到端”——直接把游戏画面喂给多模态模型,让它输出操作。这条路理论上最优雅,但实际做起来坑最多:画面里信息密度极高(单位、地形、资源、外交面板、回合数),模型很容易看漏;而且每一步都要传图,Token 消耗和延迟都扛不住 130 回合这种长局。
所以我更推荐、也是这类项目里更常见的是三段式架构:
- 感知层:从游戏里把“结构化状态”抠出来,比如当前回合数、我的城市列表、每个城市的产出、可见敌方单位、科技进度、外交关系。能读内存就读内存,读不了就用截图加 OCR/模板匹配,再不行就人工喂状态。
- 决策层:把结构化状态整理成一段模型能读懂的“局面简报”,连同可执行动作列表一起发给模型,让它输出一个动作。
- 执行层:把模型输出的动作解析成游戏内的具体操作——点哪个按钮、移动哪个单位、选哪个科技。
这么拆的好处是每一层都能单独调试。感知层错了,你能立刻发现是状态读错了;决策层错了,你能回看简报和模型输出;执行层错了,你能看操作有没有落下去。端到端方案一旦出错,你根本不知道是“看错了”“想错了”还是“点错了”。
2.2 为什么选《文明7》而不是别的游戏
《文明》系列是回合制的,这一点太关键了。回合制意味着决策是离散的、有明确边界的——你不需要在毫秒级做反应,模型有充足时间“思考”。如果是即时战略或者动作游戏,模型输出的延迟直接决定成败,那套架构就完全不一样了。
但《文明7》也有它的麻烦:单局回合数多(130回合只是中前期),状态维度高(城市、单位、科技、文化、外交、宗教……),而且很多决策是长周期回报的——你这回合选了个科技,可能二十回合后才见效。这对模型的“规划能力”是巨大考验,也是这个实验最有意思的地方:它测的不只是模型会不会操作,而是它能不能在长周期里保持策略一致性。
2.3 130回合这个数字意味着什么
130回合不是随便定的。以《文明》系列的节奏,这个回合数大概覆盖了从开局铺城、早期扩张、到中期科技/文化发力的阶段。它足够长,能暴露“长链路崩溃”问题——比如模型在第 40 回合忘了自己之前定的战略,或者状态读取在第 80 回合因为某个 UI 弹窗而失效。但它又没长到让整局跑不完,适合做实验。
从工程角度看,130 回合意味着至少 130 次完整的“感知-决策-执行”循环,如果每回合还有多个单位要操作,实际循环次数可能是几百次。这就要求整套流程必须足够稳定、可恢复、可观测,否则跑到一半崩了你都不知道崩在哪。
3. 感知层怎么搭:把游戏状态变成模型能读的文字
3.1 状态读取的三条路:内存、截图、人工
先说最硬核的——读内存。很多策略游戏的状态在内存里是有结构的,理论上可以定位到城市列表、单位坐标这些数据。但这条路门槛高:需要逆向、需要处理版本更新导致的偏移变化,而且涉及游戏本身的机制,风险和工作量都不小。对于个人项目,我不太推荐一上来就走这条。
第二条路是截图 + 图像识别。这是最通用的方案:定时截取游戏画面,用模板匹配找固定 UI 元素(比如回合数、资源图标),用 OCR 读文字(城市名、数值)。它的优点是跟游戏版本解耦,缺点是识别率受分辨率、UI 缩放、弹窗影响很大。我实测下来,固定分辨率 + 关闭动态 UI 效果能显著提升识别稳定性。
第三条路是人工喂状态,听起来很土,但在验证决策层逻辑时极其有用。你可以先手动把局面写成文字,只测模型决策,等决策逻辑跑通了再补感知层。这样能把问题拆开,避免“感知和决策一起调,出了错不知道怪谁”。
3.2 状态简报的字段设计
不管用哪条路,最后都要整理成一段模型能读的“局面简报”。字段设计直接决定模型决策质量。我建议至少包含这几类:
| 类别 | 字段示例 | 为什么需要 |
|---|---|---|
| 全局 | 当前回合、时代、我的总分 | 让模型知道进度和阶段 |
| 城市 | 城市名、人口、产出、正在建造 | 决定内政决策 |
| 单位 | 单位类型、位置、剩余移动力、状态 | 决定军事和探索决策 |
| 科技/文化 | 当前研究、可选列表、已解锁 | 决定发展方向 |
| 外交 | 已知文明、关系状态、是否有战争 | 决定外交决策 |
| 资源 | 战略资源、奢侈品、金币、信仰 | 决定交易和扩张 |
字段不是越多越好。信息过载会让模型抓不住重点,反而做出糟糕决策。我的经验是:每类只给最关键的 3-5 个字段,把细节留给模型主动询问(如果支持工具调用的话)。
3.3 把状态“翻译”成模型友好的格式
结构化数据直接丢给模型效果一般,因为它不擅长从表格里推断局势。更好的做法是用自然语言描述局面,再附上结构化数据作为补充。比如:
当前是第 47 回合,古典时代。你有 3 座城市,首都人口 5,正在建造粮仓。东侧发现了一个邻国,关系中立。你的科技正在研究“书写”,还需 3 回合。当前金币 120,每回合 +8。
这种描述比一堆 JSON 字段更容易让模型进入“决策状态”。我一般会把自然语言简报放前面,结构化数据放后面作为精确参考,两者结合效果最好。
提示:简报里一定要包含“上一回合做了什么”,否则模型容易重复决策或者前后矛盾。长局里这一点尤其重要。
4. 决策层:提示词、动作空间与长局一致性
4.1 动作空间怎么定义
模型不能输出“随便你怎么打”,必须给它一个封闭的动作空间。比如这一回合它只能从这些动作里选:
- 移动单位 A 到坐标 (x, y)
- 让城市 B 生产 C
- 研究科技 D
- 与文明 E 提出交易
- 结束回合
动作空间定义得越清晰,模型越不容易输出无法执行的内容。我建议每个动作都带参数说明和约束,比如“移动单位时,目标坐标必须在单位移动力范围内”。这些约束最好在提示词里写清楚,让模型自己先过滤一遍,减少执行层的报错。
4.2 提示词的分层结构
我习惯把提示词分成四层:
- 角色与目标:告诉模型它是什么、这局的目标是什么(比如“你是一个稳健的扩张型玩家,优先科技胜利”)。
- 规则与约束:动作空间、每回合能做的操作数量、禁止事项。
- 当前局面:上一节说的局面简报。
- 输出格式:强制要求模型输出结构化动作,比如 JSON,方便解析。
分层的好处是每一层都能单独迭代。比如发现模型太激进,就改第一层的目标描述;发现它老输出非法动作,就加强第二层的约束。
4.3 长局一致性:130回合不跑偏的关键
这是整个项目最难的部分。模型没有真正的“记忆”,每一回合它看到的只是当前简报。如果不做处理,它很容易在第 60 回合做出和第 20 回合完全矛盾的决策。
我的解法是维护一份战略备忘录:每 N 回合(比如 10 回合)让模型总结一次当前战略,写进备忘录,之后每回合的简报里都带上这份备忘录。这样模型每次决策时都能看到“我之前定的是什么方向”,保持连贯。
另一个技巧是关键决策留痕:把重大决策(比如“决定走科技胜利”“决定和某文明开战”)单独记下来,在后续简报里高亮提醒。实测下来,这能明显减少“战略漂移”。
4.4 Token 用量控制
130 回合,每回合都带完整历史,Token 会爆炸。我的做法是:
- 只保留最近 3-5 回合的详细操作记录
- 更早的历史压缩成战略备忘录
- 局面简报只给当前状态,不给历史快照
这样单次请求的 Token 能控制在合理范围。如果你用的是按 Token 计费的接口,这一点直接决定项目能不能跑完——130 回合乘以每回合的 Token 数,很容易就上千次调用。
5. 执行层:把模型的回答变成游戏里的真实操作
5.1 解析与校验
模型输出的动作必须先解析和校验,不能直接执行。校验包括:动作类型是否在允许列表里、参数是否完整、目标是否合法(比如单位是否真的能移动到那个坐标)。校验失败的动作用什么兜底?我的做法是回退到安全动作,比如“结束回合”或者“让当前单位原地待命”,保证流程不中断。
5.2 操作落地:键鼠模拟 vs 接口调用
如果游戏没有开放接口,就只能靠键鼠模拟。这需要:
- 知道每个 UI 元素在屏幕上的位置(固定分辨率下相对稳定)
- 处理弹窗、动画、加载这些“意外”
- 操作后等待游戏响应,不能连续点击
键鼠模拟最烦的是时序问题:点太快游戏没反应过来,点太慢效率低。我的经验是每个操作后加一个状态确认——截图看操作有没有生效,生效了再继续。这比固定 sleep 靠谱得多。
5.3 异常处理与断点续跑
130 回合不可能一帆风顺。常见的异常有:弹窗挡住了 UI、单位被消灭导致后续动作失效、游戏卡顿。我的处理原则是:
- 每回合结束保存状态快照,包括回合数、备忘录、最近操作
- 异常时先尝试恢复到安全状态(关闭弹窗、重新截图)
- 恢复失败就暂停并记录,人工介入后从快照续跑
这套机制让我能在跑长局时不用一直盯着,出问题也能定位到具体回合。
6. 常见问题与排查技巧实录
6.1 状态读取类问题
| 现象 | 可能原因 | 排查方向 |
|---|---|---|
| 回合数读错 | OCR 把相似字符认错 | 换字体、提高截图分辨率 |
| 城市列表缺项 | UI 滚动导致部分城市不可见 | 分页读取或滚动截图 |
| 单位坐标偏移 | 分辨率或 UI 缩放变化 | 锁定分辨率、关闭动态缩放 |
6.2 决策类问题
模型输出非法动作是最常见的。排查时先看提示词里的约束够不够明确,再看局面简报有没有歧义。我遇到过模型把“移动力 2”理解成“可以移动 2 格任意方向”,结果输出了超出范围的坐标——后来在约束里明确写了“移动力是曼哈顿距离上限”,问题就解决了。
6.3 执行类问题
键鼠模拟最坑的是焦点丢失:游戏窗口没在前台,点击就落空了。我的做法是每次操作前先确认窗口焦点,必要时用系统 API 把游戏窗口置顶。另外,游戏内的动画会阻塞操作,最好在操作前检测“是否处于可操作状态”。
6.4 长局稳定性问题
跑到 100 回合以后,最容易出现的是状态累积错误:某一回合读错了一个数值,后面基于错误状态做的决策全歪了。我的对策是定期做一致性校验,比如每 20 回合核对一次总分、城市数这些关键指标,发现异常就回滚到上一个快照。
提示:不要迷信“一次跑通”。长局项目里,能稳定复现和恢复比一次成功重要得多。
7. 我个人的几点实操体会
跑完这 130 回合,最大的感受是:模型的能力不是瓶颈,工程的稳定性才是。模型在单回合决策上表现相当不错,能根据局势做出合理选择;真正拖后腿的是感知层的识别错误、执行层的时序问题、以及长局里的状态漂移。
另一个体会是日志要记全。每回合的简报、模型输出、执行结果、状态快照,全都存下来。出问题时这些日志就是你的“黑匣子”,能帮你快速定位是哪一层出的错。我一开始图省事只记了模型输出,结果排查执行问题时两眼一抹黑,后来补上执行日志才顺畅。
最后分享一个小技巧:如果你也想做类似实验,先用人工喂状态 + 手动执行的方式跑通决策逻辑,确认模型能做出合理决策后,再逐步补上感知和执行自动化。这样能把复杂度分摊到不同阶段,避免一上来就被工程问题淹没。等这套跑顺了,你甚至可以把它扩展到其他回合制策略游戏,架构基本是通用的。