项目概览
Xs of Y 是一款由开发者 nooga(GitHub: marcingas)创作的肉鸽类游戏(roguelike),其独特之处在于每次运行都会生成一个独特的游戏名称,格式为 "Xs of Y"—— 例如 "Amulet of Lost Semicolons"。这款游戏使用作者自创的类 Clojure 编程语言 let-go 编写,代码量仅约 4000 行,却完整实现了地牢生成、战斗系统、符文附魔等核心机制。
从技术角度看,Xs of Y 最引人注目的特性是其自命名系统:游戏不仅程序生成地图和物品,连自身的标题都由算法决定。这种设计将程序化内容生成(PCG)推向了元层面,让每次运行都成为独一无二的 "作品"。
程序化命名的技术实现
模板驱动的组合系统
Xs of Y 的命名系统采用经典的模板组合模式。游戏维护两个词库:
- X 词库:包含神器、概念、抽象名词(如 Amulet、Blade、Echo)
- Y 词库:包含描述性短语、状态、属性(如 Lost Semicolons、Eternal Flame、Broken Chains)
每次新游戏启动时,系统从各自的词库中随机抽取一个元素,按 "{X} of {Y}" 的模板拼接成完整标题。这种设计看似简单,却能在有限的词库规模下产生指数级的组合可能性。
可复现的随机性
作为肉鸽类游戏的核心要求,Xs of Y 的命名系统必须保证可复现性—— 相同的随机种子应产生相同的名称。作者通过 let-go 语言的纯函数特性实现这一点:游戏状态完全由持久化数据结构(persistent data structures)计算得出,每次 tick 重新计算整个世界状态,确保命名的确定性和可复现性。
这种设计选择带来了额外的工程优势:由于整个游戏状态都是纯函数计算的结果,存档系统可以极度简化 —— 只需保存随机种子和玩家操作序列,即可完整还原任意游戏时刻。
符文系统的命名扩展
游戏内的符文(runes)系统进一步展示了程序化命名的深度应用。符文以北欧古文字(如 ᛟ、ᛉ、ᛋ)表示,每个符文对应一个词义(如 "ice"、"fire"、"shadow")。玩家可以将符文铭刻在武器和护甲上,系统会根据符文组合生成物品的描述性名称。
这种设计将命名从游戏元层延伸到游戏内物品层,形成统一的程序化命名体验。
工程实践要点
词库设计的约束
从 Xs of Y 的实现可以提炼出词库设计的几个关键参数:
| 参数 | 建议值 | 说明 |
|---|---|---|
| X 词库大小 | 30-50 个 | 保证多样性同时避免生僻词 |
| Y 词库大小 | 50-100 个 | 描述性短语需要更大空间 |
| 语音兼容性检查 | 必须 | 避免辅音冲突导致的难读组合 |
| 主题一致性过滤 | 推荐 | 排除语义冲突的组合(如 "Joy of Despair") |
性能优化策略
在 4000 行代码的限制下,Xs of Y 采用了以下优化策略:
- 惰性计算:词库加载采用惰性初始化,仅在首次需要时加载
- 结构共享:利用 Clojure 风格的持久化数据结构,命名生成过程中共享底层词库数据
- 缓存策略:已生成的名称组合缓存哈希值,避免重复计算
可扩展性设计
对于希望实现类似系统的开发者,建议采用分层架构:
命名生成器
├── 模板层:定义命名模式("X of Y", "The X Y", "Y's X")
├── 词库层:按主题分类的名词、形容词、动词库
├── 过滤器层:语音规则、语义一致性检查
└── 输出层:格式化与本地化
这种分层设计允许在不修改核心逻辑的情况下扩展新的命名风格或语言支持。
对游戏体验的影响
记忆点与叙事感
程序生成的独特名称赋予每次运行独特的身份感。玩家会记住 "那次在 Amulet of Lost Semicolons 中的冒险",而非简单的 "第三局游戏"。这种设计巧妙地利用了叙事心理学—— 人类天生倾向于为随机事件赋予意义。
社区传播优势
独特的运行名称天然适合社交媒体传播。当玩家分享 "我在 Blade of Eternal Flame 中死于火魔" 时,其他玩家能立即识别这是某次特定运行的引用,形成共享的 "梗" 文化。
局限与风险
Xs of Y 的作者自承该项目目前仍是 "技术演示"(tech demo),存在一些未解决的边界情况:
- 词库耗尽:长期运行后可能产生重复名称
- 语义冲突:某些随机组合可能产生荒谬或冒犯性的结果
- 本地化困难:基于英语的模板难以直接翻译到语法结构差异大的语言
可落地的实现参数
对于希望在项目中实现类似程序化命名系统的开发者,以下是可直接应用的参数清单:
词库构建
- 每个主题类别至少准备 20 个高质量词条
- 建立词条的元数据标签(主题、情感色彩、稀有度)
- 实现语音相似度检测,避免连续辅音(如 "Blade of Frost" 优于 "Blade of Strength")
随机性控制
- 使用确定性的伪随机数生成器(如 PCG、xorshift)
- 将随机种子暴露给玩家(支持 "种子分享" 功能)
- 实现名称历史记录,避免短期内重复
质量保证
- 建立禁用词列表,过滤不当组合
- 实现人工审核流程,定期更新词库
- 收集玩家反馈,识别 "好" 与 "坏" 的生成结果
资料来源
- Hacker News 讨论: Xs of Y – roguelike that names itself every run
- GitHub 仓库: nooga/xs-of-y
- let-go 编程语言: nooga/let-go
内容声明:本文无广告投放、无付费植入。
如有事实性问题,欢迎发送勘误至 i@hotdrydog.com。