Hotdry.

Article

从一行代码到十字节:极简迷宫生成算法的工程启示

解析8位机时代10 PRINT迷宫生成器的技术原理,探讨极简算法如何启发现代程序化内容生成,并提供可落地的地牢生成参数清单。

2026-05-28systems

1980 年代的 Commodore 64 家用电脑上,一行 BASIC 代码改变了人们对程序化生成的认知:10 PRINT CHR$(205.5+RND(1)); : GOTO 10。这行代码运行时,屏幕上会源源不断地输出由斜杠组成的图案,视觉上呈现出迷宫般的复杂结构。令人惊讶的是,这种 "迷宫" 并非真正的可解迷宫,而是由最简单的随机选择机制产生的视觉幻象。然而,正是这种极简主义的算法思维,为现代游戏开发中的程序化内容生成奠定了哲学基础。

10 PRINT:一行代码的魔法

Commodore 64 的 PETSCII 字符集中,字符 205 和 206 分别对应左斜杠和右斜杠(/\)。这行代码的核心逻辑极其简单:生成一个随机数,如果小于 0.5 则选择 205,否则选择 206,然后无限循环。从算法角度看,这甚至不能称之为 "迷宫生成器"—— 它既没有起点终点,也没有通路和死胡同的区分,只是随机字符的堆砌。

但人类的大脑是地球上最强大的模式识别引擎。当这些斜杠字符在屏幕上累积时,我们的视觉系统会自动寻找边界和通道,将其解读为迷宫结构。这种 "涌现" 特性揭示了一个重要原理:复杂可玩结构的感知,有时只需要最基础的随机元素组合

2012 年, demoscene 开发者 Trixter 接受了一个更具挑战性的任务:将这行 BASIC 代码移植到 x86 汇编,并尽可能压缩体积。初始的 "友好版本" 有 42 字节,遵循所有编程规范:使用硬件定时器获取随机数、正确初始化寄存器、清理退出。但在 size coding 的竞技场上,每一字节都是战场。

从 42 字节到 10 字节:优化的艺术

优化的第一步是简化随机数生成。原版使用 8253 定时器读取硬件计数器,但 Trixter 发现 "随机性" 的质量要求可以降低 —— 用LODSB指令直接读取内存中的任意字节(实际上是程序代码本身和内存残留数据)作为随机源,这一步将代码压缩到 25 字节。

接下来的突破来自对 x86 指令集的深入理解。SCASB指令原本用于在字符串中搜索字符,它会比较 AL 寄存器与 ES:DI 指向的内存字节,并设置标志位。关键在于,这个比较操作会设置奇偶标志位(Parity Flag),而我们可以利用这一点来替代显式的随机位判断

最终的 13 字节版本代码如下:

init:   mov     ah,0eh          ; 设置BIOS字符输出功能
getrnd: scasb                   ; 读取内存并比较,设置标志位
pickch: mov     al,'\\'          ; 默认选择反斜杠
        jp      writec          ; 奇偶标志为1则直接输出
        mov     al,'/'          ; 否则选择正斜杠
writec: int     10h             ; 调用BIOS输出字符
        jmp     getrnd          ; 无限循环

社区随后展开了激烈的 "字节战争"。Peter Ferrie 通过合并指令将代码缩减到 12 字节,herm1t 利用 DOS 未公开中断int 29h达到 11 字节,而最终的 10 字节版本使用了salc(Set AL from Carry)这一仅在 Intel 处理器上有效的未公开指令,将字符选择逻辑压缩到极致。

这场竞赛揭示了一个工程真理:约束条件往往是创新的催化剂。当字节数成为硬约束时,开发者被迫深入理解硬件的每一个细节,发现指令的隐藏能力。

从视觉幻象到可玩结构

回到现代游戏开发,真正的程序化地牢生成需要比 10 PRINT 复杂得多的算法。RogueBasin 社区总结的标准地牢生成流程包括:

  1. 房间放置:在网格上随机放置不重叠的矩形房间
  2. 中心点连接:记录每个房间的中心坐标
  3. 走廊开凿:用 L 形走廊连接相邻房间的中心
  4. 连通性保证:通过最小生成树算法确保所有房间可达

这种 "房间 + 走廊" 模型自 1980 年代的 Rogue 游戏以来一直是 roguelike 类型的标准做法。与 10 PRINT 的纯随机不同,这类算法需要维护显式的数据结构(房间列表、网格状态、连通图)并执行约束检查(碰撞检测、连通性验证)。

然而,10 PRINT 的精神在现代算法中仍有回响。Perlin 噪声、波函数坍缩(Wave Function Collapse)等现代程序化生成技术,本质上也是在简单规则约束下的随机选择过程。它们的复杂度来自于规则系统的层次叠加,而非单个规则的复杂性。

可落地的地牢生成参数清单

基于 RogueBasin 和经典 roguelike 实现,以下是一套可直接使用的地牢生成参数:

网格配置

  • 地图尺寸:40×40 至 80×80 单元格
  • 单元格类型:墙 (0)、地板 (1)、门 (2)、陷阱 (3)

房间参数

  • 最小房间尺寸:4×4 单元格
  • 最大房间尺寸:10×8 单元格(长宽比保持 1.25 以内)
  • 最大房间数量:8-12 个(根据地图尺寸调整)
  • 房间间距:至少 1 单元格墙厚

生成策略

  • 放置尝试次数:最大房间数 ×3(允许失败重试)
  • 走廊宽度:1 单元格(标准)或 2 单元格(宽走廊变体)
  • 连接算法:按房间创建顺序连接,或随机选择最小生成树

质量控制阈值

  • 地板覆盖率:20%-40%(过低显得空旷,过高失去探索感)
  • 死胡同比例:不超过总走廊节点数的 30%
  • 最长走廊长度:不超过地图最短维度的 50%

随机种子管理

  • 使用确定性种子(如关卡编号 + 全局种子)保证可重现性
  • 为关键房间(如 BOSS 房、宝藏房)预留固定位置区域

极简主义的现代启示

10 PRINT 算法虽然简单,但它提出的问题至今仍有价值:在资源受限的环境中,如何用最小代价产生最大的感知复杂度

现代游戏引擎提供了强大的程序化生成工具,但开发者仍面临类似的权衡。过度复杂的算法可能导致生成时间过长、内存占用过高,或者产生 "算法感" 过强、缺乏自然变化的关卡。在某些场景下,适当简化算法并依赖玩家的模式补全能力,反而能获得更好的游戏体验。

Trixter 的 13 字节迷宫生成器最终成为 demoscene 的经典案例,不是因为它的实用性,而是因为它展示了当技术约束被推到极致时,代码可以成为一种艺术形式。这种追求极致的精神,无论是在 8 位机的汇编代码中,还是在现代游戏的地牢生成器里,都是推动创新的核心动力。


资料来源

  • Trixter, "Maze Generation In Thirteen Bytes", Oldskooler Ramblings, 2012
  • RogueBasin, "Dungeon-Building Algorithm", roguelike 开发社区文档

systems

内容声明:本文无广告投放、无付费植入。

如有事实性问题,欢迎发送勘误至 i@hotdrydog.com