你见过最离谱的《毁灭战士》移植版长啥样?验孕棒上的黑白画面、电子烟那块指甲盖大的屏幕、甚至打印机慢吞吞吐出的一帧帧字符——这些已经够邪门了。但最近 Reddit 上的一个新项目直接给我整不会了:一位开发者用查找替换功能,硬是把 DOOM 跑了起来。没写一行传统意义上的计算指令,没有图形引擎,整个游戏的状态全塞进一个 96.6MB 的纯文本字符串里,然后靠着 544 条正则表达式规则在那里一句一句“替换文字”,生生把画面给憋出来了。
这个项目叫 doom-regex,由程序员 Artem Lytkin 在 7 月 26 日发布,GitHub 上连源码带 Windows 可玩 Demo 都放出来了。最直观的说法就是:他把整台虚拟计算机做成了一个超级长的字符串,CPU 寄存器、内存、帧缓冲、程序逻辑,甚至 WAD 地图数据全写进这个文本文件里。然后,游戏每往前走一步,就全靠正则表达式去匹配这个字符串的某些部分,匹配到了就把对应部分替换成新的内容,一步接一步,一帧接一帧,活活把 DOOM 的原版游戏逻辑给模拟了出来。
可能很多朋友和我一样,平时用正则表达式顶多就是搜一下日志里的报错、批量改改文件名。但在 doom-regex 里,正则被硬生生逼成了真正的“处理器”。之所以能这么玩,是因为按照理论,正则表达式的替换规则本身就可以实现图灵完备——也就是说理论上它能模拟任何计算过程。Lytkin 显然就是冲着这个理论极限去的,用 544 条规则构建了一套完整的虚拟机,不含任何外部解释器,也没有加减乘除的算术单元,所有计算都揉进了这堆字符串替换之中。
整个机制的运转其实很有规律。那个 96.6MB 的大字符串时刻记录着当前虚拟机的全部状态,开头长得像这样:RVM1|ST:run|PH:0|CI:02000000fffe|PC:00000000|R0:00000000|R1:00000000|……。其中 PH 字段表示当前执行到哪个阶段,CI 是当前指令,后面的 PC 是程序计数器,R0、R1 这些就是寄存器。所有规则都会先检查 ST、PH 等状态标签,只有标签对得上的指令才会触发进一步的替换,这样一圈圈筛下来,尽可能降低了每次试探 544 条规则的开销。
拿一条具体的 MOVI 指令举例,假如当前 CI 的值是 02000000fffe,开头两位“02”就代表这是一个把立即数塞进寄存器的操作;第三位“0”指定操作对象是 R0 寄存器,末尾八位“0000fffe”就是待写入的值。一旦某条正则规则匹配到这个指令结构,它就会把原字符串里的“R0:00000000”这部分替换成“R0:0000fffe”,同时把阶段 PH 从 0 改成 1,这台虚拟 CPU 就算走完了一步。接下来,下一轮正则又会去匹配新的状态,接着跑下一条指令。
当然这么做的代价就是时间。项目文档里给的实测数据非常诚实:跑 100 帧画面,总共执行了大约 12.5 亿次替换,平均一帧要大约 1250 万步,折合下来一帧要花差不多 3 分钟。也就是说,如果你想亲手用这个版本把 DOOM 第一关打穿,可能得抱着电脑陪它慢慢熬一宿。而且演示版虽然支持 WASD 移动、Ctrl 射击、Space 开门这些基础操作,但按下键盘之后你得耐心等画面刷新出来,毫无实时爽感可言。
但话说回来,整个事情本身就不是冲着“能玩”去的。作为 DOOM 的骨灰级整活对象,1993 年 id Software 在 MS-DOS 上放出这款 FPS 鼻祖后,源码就以 GPL-2.0 协议公开,全球的极客们翻来覆去地把它往各种古怪平台上移植。扫码认证的二维码里、智能冰箱屏幕上,甚至某些音响的小显示屏上,都曾有 DOOM 的枪口闪过。而 doom-regex 这股“全用替换文字跑游戏”的劲儿,恰好踩在好玩的点上:它不是让游戏适配新硬件,而是连“硬件”本身都省了,让逻辑单纯依附在文本的变形之上。
看到这个项目的时候,我满脑子都是一个画面:一个玩家蹲在电脑前,打完一枪就去泡杯咖啡,回来正好看到下一帧子弹打中怪物,然后又可以去倒第二杯。这种节奏在今天的游戏圈简直像行为艺术,但你不得不佩服背后那个“只要图灵完备我就能让你跑起来”的纯粹乐趣。对于不满足于单纯打游戏、总想看看技术还能怎么胡来的兄弟来说,这个挂在 GitHub 上的字符串版 DOOM,大概就是最近最邪门也最浪漫的一个脑洞了。
热门跟贴