我探索所有Tetris的旅程
摘要
来自Antithesis的一篇详细博客文章,描述了他们的软件测试工具如何用于探索并实现Tetris中的‘重生’(达到255级),在此过程中克服挑战并发现故障。
<p><a href="https://lobste.rs/s/2eyryl/my_quest_see_all_tetris">评论</a></p>
查看缓存全文
缓存时间: 2026/07/02 22:16
# 我追寻《俄罗斯方块》全貌的旅程 | Antithesis
来源:https://antithesis.com/blog/2026/tetris-quest/
2026年初,我满头大汗。几年前,我曾宣称 Antithesis 已经“打败”了《俄罗斯方块》。我们有个传统:用打败过的游戏来命名会议室。自2021年起,办公室里就有一间叫“Tetris”的会议室。
然而,我的胜利宣言已经被时代超越了。我们将会看到,青少年玩家们已经学会了如何将人类操作延伸至我们产品尚未触及的游戏领域。我把利用业余时间追赶这些青少年当作自己的支线任务。
目标是“重生”——通关《俄罗斯方块》的所有等级,直到等级计数器从255翻回到0。当这发生时,游戏会回到第0级的速度和配色方案,并再次开始升级之旅。如果我们能看遍《俄罗斯方块》的全部,那当然可以宣称我们打败了它。
不幸的是,我们的探索卡在了第160级。我即将加入一个新部门,我知道一旦如此,我可能再也没有时间研究《俄罗斯方块》了。但我却还卡在那里。
不过,我有点说远了。我想事先说明,尽管解决“卡关”的过程令人抓狂,但这确实是一个圆满的结局。我应该从头开始讲这个故事。
如果你只想看我们最终做了什么,以及途中发现的奇怪故障,可以直接跳转到[重生!](https://antithesis.com/blog/2026/tetris-quest/#rebirth)
## 为什么是《俄罗斯方块》?(https://antithesis.com/blog/2026/tetris-quest/#why-tetris)
在 Antithesis 早期,新工程师们要经历一个入职仪式:学习我们的系统,并用它来玩(最好能打败)一款来自80年代经典的任天堂娱乐系统(NES)游戏。随着时间的推移,我们攻克了许多经典作品,包括[《马里奥》](https://antithesis.com/blog/sdtalk/)、[《塞尔达传说》](https://antithesis.com/blog/zelda/)和[《银河战士》](https://antithesis.com/blog/2025/metroid/)。我在2019年加入时,选择了《打砖块》,因为它是我第二喜欢的NES游戏。我最喜欢的《俄罗斯方块》已经有人尝试过了。¹
我在90年代就有点沉迷于《俄罗斯方块》了,那时我正从欧洲拜访客户后飞回美国。当时堪称革命性的机上娱乐系统有一个版本可以在座位上玩。我很享受在飞行途中运用空间推理来思考如何旋转和放置方块。看着完整的行消失,分数增加,给我带来即时的成就感。
当然,《俄罗斯方块》不会让你舒服太久。正当你进入状态时,方块下落的速度会加快。如果你犯了个错误,比如用新方块盖住了一个空位,那么你就开始转入防守,不得不牺牲未来的健康来避免立即出局。游戏没有终点线:你只能一直玩直到输掉。没有人能全身而退。(也许这一切都是某种隐喻。)
我们之前尝试打败《俄罗斯方块》时取得了一些进展,但没能走得很远。但打败《俄罗斯方块》这个念头一直挥之不去,变成了一个(非常)长期的副项目。但“打败”到底是什么意思呢?
通常在 Antithesis,“打败”一个游戏意味着我们发现一组用户输入,能让游戏以胜利结局收场。由于《俄罗斯方块》没有胜利状态,准确定义什么算作打败游戏就有点模糊了。我们的理解在这个过程中不断发展(并且得到了青少年玩家的一些帮助)。
## Antithesis 如何玩游戏 (https://antithesis.com/blog/2026/tetris-quest/#how-antithesis-plays-games)
Antithesis 以一种不寻常的方式玩《俄罗斯方块》,所以我先解释一下它是如何工作的。我们不采用通常的[工具辅助速通](https://en.wikipedia.org/wiki/Tool-assisted_speedrun)方式来从头精心设计一组完美的用户输入。我们也不创建知道如何玩游戏、盯着屏幕并做出反应的机器人。
相反,我们在已知的起始游戏状态下运行小规模的随机输入试验,评估每次试验对游戏的影响,并记住那些我们认为对目标有意义的游戏情况。
我们利用了这样一个事实:NES 游戏中发生的事情完全由收到的用户输入决定,这让我们可以吝啬地保存游戏快照。只要我们保存了发送给游戏的每一个输入,我们就可以从状态历史中最接近的快照开始,并通过输入所需的输入来精确到达我们想要的游戏时刻,从而重新创建任意游戏状态。²
在一个典型的测试运行设置中,一个 Antithesis 模糊测试器会供给 32 个模拟的 NES 会话,每个会话都加载了我们正在模糊测试的游戏。我们使用 [fceux](https://fceux.com/web/home.html) 模拟器托管每个会话,并利用 fceux 的 Lua 集成创建一个脚本,在无头模式下运行模拟器。³
在模糊测试器内部,我们有一个称为“策略”的组件,用于生成针对被测试游戏的输入。然后,第二个“策略”组件观察输入的结果,并指导模糊测试器下一步该做什么。(更多信息请参见我们之前关于[打败《沙罗曼蛇》](https://antithesis.com/blog/2025/gradius/)的文章。)
要了解这一切如何协同工作,放大到单帧来看会有所帮助。NES 游戏以每秒 60 帧的速度循环。每个循环包含以下动作:
- 我们的脚本从输入管道接收来自模糊测试器的一个输入字节。
- 脚本读取该输入字节并将其发送到等待的模拟器。
- 模拟器处理输入字节,修改游戏内存,生成新的游戏画面,然后返回到脚本。
- 脚本询问模拟器并捕获特定游戏内存位置的值,以及可选的新游戏画面。结果被放入输出管道,返回给模糊测试器进行异步处理。
- 脚本循环回去处理下一个输入。
模糊测试器相对于这个循环是异步的。它会预先为脚本生成输入批次,并在脚本返回时观察结果。
有了这些机制,打败一个游戏归结为两件事:
- 找到正确的策略(生成输入的算法)
- 找到正确的策略来引导模糊测试器赢得游戏。
对于《俄罗斯方块》这样一个没有终点的游戏,我们最初的想法是,打败它意味着要做得和最好的人类玩家一样好。但我们没有考虑到其他所有人类玩家。
## 第一轮:学习 (https://antithesis.com/blog/2026/tetris-quest/#round-one-learning)
我的同事 Alex Pshenichkin 已经尝试过让模糊测试器玩《俄罗斯方块》。他通过读取模拟器内存弄清楚了如何获取当前方块布局的基础知识。他利用这来计算我们第一个“良好度”度量,这基于他找到的一些[研究](http://meatfighter.com/nintendotetrisai/)和[资料](https://web.archive.org/web/20180310153234/http://imake.ninja/el-tetris-an-improvement-on-pierre-dellacheries-algorithm/)。
这个版本玩起来很慢,因为生成输入的策略基本上是在生成随机输入。⁴ 当我们把运行结果转换成录像时,看着方块下落就像看着雪花在微风中飘荡。它们会慢慢地蜿蜒而下,来回摆动,最终随机落在一个地方。
我们的策略会测量每一帧的棋盘状态,并并行探索许多不同的棋盘布局模式。结合随机策略,我们得到了一种完全依赖随机性的方法。在我们投入运行的时间里,我们从未能消除超过几行。
Alex 在让核心设置工作起来方面做了出色的工作,但他的本职工作占用了他的时间,后来他成为了我们产品核心的[确定性虚拟机监控器](https://antithesis.com/blog/deterministic_hypervisor/)的关键人物。《俄罗斯方块》只能暂时搁置,直到全球疫情再次把它推到前台。⁵
## 第二轮:天真的成功 (https://antithesis.com/blog/2026/tetris-quest/#round-two-naive-success)
2020年,当我们因新冠疫情居家办公时,我开始把《俄罗斯方块》作为一个副项目来做。我想让我们的策略和策略表现得像最好的人类玩家那样。
我们的目标是彻底打败游戏,突破第29级——这个级别传统上难倒了人类玩家。在第29级,方块下落的速度突然翻倍,从每行2帧变为每行1帧,使得方块在大约三分之一秒内就能从场地顶部落到底部。在这种速度下,按住左或右的标准方法无法在方块到达底部之前将它从生成点一直移到远端。因此,几十年来,第29级被认为无法生存:一个“杀屏”,无论你多强,游戏都会自行结束。
我的新策略专门为《俄罗斯方块》生成输入字节。它模仿了顶级玩家遇到新方块时的做法——先旋转,然后向左或向右移动到特定列,然后不断向下直到方块就位。
我还结合了一个改进的策略。我采用了第一次尝试中的棋盘评估函数,并将其转换为一个目标函数,设计为在新方块准备下落时运行。目标函数考虑了方块堆叠的高度(越低越好)、方块锁定时的深度(越深越好),以及我们堆积起来的方块中留下的“气泡”数量——气泡是指被卡住无法填充的空格。气泡越多,麻烦越大。
我们使用的策略在游戏内存告诉我们有新方块时运行目标函数。对于每个新方块,我们还确定了我们达到了哪个“策略桶”。桶由以下元组定义:
*(游戏中到目前为止看到的方块数量,最后一个方块放置的列)*。
在每个桶中,我们存储了目标函数的分数以及一个可以用来回到该游戏点的游戏状态。
当策略选择要探索的桶时,模糊测试器将保存的游戏状态加载到一个模拟器中。然后,它调用策略生成随机的俄罗斯方块移动。我们不断地跳回到有趣的游戏状态并再次尝试。当我们回到一个已经填充过的桶时,目标函数决定是保留原有状态,还是用新发现的状态替换它。在成千上万次运行中,每个桶逐渐积累了针对每个*(方块数量,列)*组合找到的最佳游戏状态。
这个目标函数会随着我们消除越来越多的行而自然增加:满足它的唯一方法就是继续前进一点。随着我们玩的游戏越来越多,我们会改进为每个游戏位置保存的游戏状态。
同样的策略在其他NES游戏上也很有效。然而,《俄罗斯方块》却有所不同。我们最终取得了一些进展,但在第15级左右停滞不前。突破来自我的同事 Josh Reagan,他正在与我们的联合创始人 Dave Scherer 一起构建一个新策略:一种“图感知”策略。他们的洞察是停止将桶视为一堆孤立的点,而是将它们连接成一个图:每个桶变成一个节点,每条边承载着从一个节点到下一个节点的奖励。该策略会搜索通往最深节点的路径上每个节点的最高奖励路径。目标函数非常适合发放这些奖励。Josh 切换了系统,并启动了一次通宵运行。我们早上就会知道结果。⁶
我们达到了第41级,远远超过了第29级的“杀屏”。当我们回到办公室时,我们命名了一间会议室为“Tetris”。我们成功了!
## Antithesis 对阵各路青少年 (https://antithesis.com/blog/2026/tetris-quest/#antithesis-vs-various-teenagers)
从这篇博客帖子的剩余长度你可能已经猜到,我们实际上远远没有完成。
我们以为已经打败了人类玩家,但“打败”的定义正在我们脚下发生变化。我们恰好在玩家们正在突破旧极限的时候尝试打败《俄罗斯方块》。
即使在2020年,人类技术的最高水平也已经超越了第29级。奇怪的是,它*非常*接近我们达到的水平——青少年玩家 Eric Tolt [首次达到第38级](https://en.wikipedia.org/wiki/Eric_Tolt#Tetris_career)。
实现这一突破的是更高级的按键技术。不再按住左或右,而是极快地点击它们。第一个开发的技巧,超快速点击,依靠手臂肌肉颤抖来震动按钮。这就是 Tolt 在2020年使用的技巧。然而,超快速点击会导致很大的身体压力,因此仍然相当小众。
大约在同一时间,另一种技巧——滚动——被开发出来。滚动涉及将一根手指放在左或右上,同时用另一只手的手指敲击控制器背面,反复按下按钮。这种方法对身体的要求低得多,而且重要的是,速度更快。玩家们开始转向这种技巧,并打破更多记录。
2023年,13岁的玩家 Willis Gibson(网名“Blue Scuti”)使用滚动技术达到了第157级,成为有史以来第一个让游戏崩溃的人类玩家。随着游戏进入未知领域,[奇怪的故障](https://meatfighter.com/nintendotetrisai/#The_Kill_Screen)开始出现,导致游戏重置、死机或直接黑屏。
这大约是 Antithesis 结束隐身模式的时候。当我们的博客上线时,人们问:“嘿,我们打败了《俄罗斯方块》,对吧?你们应该写篇博客。”我不得不不好意思地承认:“嗯,有个13岁的孩子能胜过我们……还有,请别问那间会议室。”
然后在2024年底,16岁的 Michael Artiaga(网名“dogplayingtetris”,或简称“Dog”)实现了不可思议的事情。他用手在一个修改过的卡带上玩,这个卡带让他能够绕过崩溃触发器,达到了第255级,然后又前进了一级,将等级计数器翻回0。当这发生时,颜色、方块速度和分数增量都回到了游戏开始时的状态。这一成就被称为“重生”,曾在工具辅助速通中见过,但这是人类首次达到这一目标。
这项壮举尤其令人印象深刻的是他在高等级中必须绕过的[所有故障](https://en.wikipedia.org/wiki/Tetris_(NES_video_game)#Technical_problems_at_very_high_levels)。第235级有一个特别糟糕的故障,导致正常10行后等级计数器不再增加;相反,Artiaga 必须清除荒谬的810行。更糟糕的是,他遇到了一个无关的调色板故障,[将所有方块变成了深绿色](https://youtu.be/fXhbti5SneE?si=I0TUCN-MuJ7E1jqM&t=3410),使它们在黑色背景上很难看清。
青少年们再次移动了球门柱。我们爬上了一座山,却发现还有一座更大的山。我们*必须*实现重生。
## 第三轮:项目 999999 (https://antithesis.com/blog/2026/tetris-quest/#round-three-project-999999)
2025年4月:我在项目之间有一个空档,而市场部的人又在催要那篇俄罗斯方块的帖子。
在同事 Peter Stiglitz 的帮助下,我一直在研究人类玩《俄罗斯方块》的方式。我预计我们需要一些针对游戏中已知在深层等级会出现的故障的对策。
Peter 发现其中一些故障需要在某些游戏位置一次性清除多行。另外,我们还没有达到分数上限。
相似文章
BBC Tetris 伴侣
一位爱好者描述了一个正在进行的项目,为 BBC Bridge Companion(一款 1985 年基于 Z80 的游戏机)编写 Tetris 游戏,包括硬件规格和背景。
DeepSeek v4 Flash 0731 在 Windows XP 下一次性生成俄罗斯方块(NyoCoder 1.5.5 发布)
作者分享了一段 NyoCoder 1.5.5(AI 代码助手)在 Windows XP/VS2010 下使用 DeepSeek v4 Flash 0731 生成俄罗斯方块游戏的视频,并提供了 GitHub 链接。
苏联诞生的《俄罗斯方块》:一段扑朔迷离的历史
本文探讨了《俄罗斯方块》充满争议的历史,涵盖其方块图形的版权之争、早于游戏存在的数学渊源,以及近期因法律威胁而被下架的克隆游戏引发的政治事件。
Beyond Tetris: The Other Games of Alexey Pajitnov [video]
一篇视频内容回顾了《俄罗斯方块》之父 Alexey Pajitnov 在 Tetris 之外鲜为人知的游戏作品,包括苏联科学院时期仅存的两款小游戏 Shaw (1986) 和 Magnetic Crane (1989),以及他此后借助名声参与的众多项目。
反应式玩法:实现了!!Atari Breakout 实验 [R]
在 Atari Breakout 上进行了 123 次失败的 PPO 实验后,添加一个简单的接近奖励来追踪球的下落,最终实现了反应式的、非脚本化的玩法,并且能够迁移到不熟悉的砖块布局上。