hrxdev
简体中文

幕后制作

一位开发者,一个 AI 编程助手,以及大量由机器检查的规则。

作者:Nick

Prison Life 是我和 Claude Code(Anthropic 的编程代理)一起写的。游戏是什么、选哪条路线,由我来定;大部分敲代码的活由助手完成。因为除了我和一个负责评审的 AI 代理,没有别人会看这些代码,所以我依靠自动化:规则靠自动检查和构建来强制执行,而不是靠自觉。

任务委派

Claude Code 的主会话负责规划工作,并维护任务跟踪器、设计选择的书面记录和变更历史。它自己不写代码:每一项改动,哪怕再小,都会交给专门的 AI 代理。每个代理都有一份书面定义,规定它的角色和所用的模型。

角色模型档位职责
架构Opus数据模型、tick、线程、寻路、决策
模拟代码Opus模拟系统、角色 AI、热点循环
性能Opus性能分析、基准测试回退
评审(只读)Opus评审代码差异;不能编辑文件
客户端与工具SonnetGodot 客户端、界面、工具
测试Sonnet根据验收标准编写测试
内容数据Sonnet依据模式定义生成 JSON 数据
搜索、运行检查Haiku代码搜索;运行检查并总结失败原因

难的活交给最强的模型,常规的活交给更便宜的模型。如果较便宜的 AI 代理两次没通过检查,任务就升一档;如果最高一档也两次失败,就会停下来问我。

会说“不”的钩子

Claude Code 的钩子(hook)是在助手操作前后运行的脚本。我的钩子强制执行三条规则:

这些防的是失误,不是蓄意绕过:有心人靠一点 shell 技巧就能绕开;而且其中一个钩子能看到 AI 代理里的红灯,却拦不住它(主会话的停止钩子仍会把它抓出来)。我宁愿把这一点直说。

书面决策与检查

确定性核心

模拟存在于一个不含任何 Godot 引用的纯 .NET 库中;Godot 客户端只读取它的状态并发送命令。核心遵循固定的规则:世界只通过命令改变,时间是整数 tick,随机性只来自世界的带种子生成器。相同的种子和相同的命令日志,必须得到相同的世界。这些规则由编译器和测试来检查,而不只靠评审;具体怎么做,见开发日志 #1,世界、存档与回放见开发日志 #2。

模拟核心架构命令进入队列。每个 tick 依次运行阶段 0(命令,写入命令日志)、阶段 1(按固定顺序运行各系统)和阶段 2(tick 结束)。命令日志与世界状态(含瓦片地图和带种子的随机流)共同输入状态哈希。 命令输入 玩家、测试、场景 命令队列 Enqueue 是线程安全的 Tick T(单线程,整数时间) 阶段 0:命令 序列化,打上 (tick, seq) 戳 校验、写入日志、Apply 被拒绝的命令同样会记入日志 阶段 1:系统 按代码中设定的固定顺序运行 (目前尚未注册任何系统) 阶段 2:tick 结束 结构性变更(尚未使用) 然后 tick 计数器加 1 命令日志 每条命令, 连同其结果 线路字节 + 摘要 回放 = 种子 + 日志 世界状态 种子、tick 瓦片地图(楼层) 种子派生的 4 个 RNG 流: Commands、Needs、 Ai、Events 状态哈希 种子、tick、地图、RNG 流、日志摘要
模拟核心目前的样子。还没有任何系统和角色;世界里只有一张带楼层的瓦片地图,哈希除了被绘制的内容,也涵盖了地图。

设计目标是在每秒 20 个 tick 下容纳最多 1000 名囚犯和狱警。这只是目标:现在还没有角色,所以基准测试运行器虽然存在,但在这个规模上还没有测过任何数据。