戏剧性的数字,通常是 bug——我审了一遍 AI 交给我的掼蛋研究

掼蛋这几年打的人多了。它是两副牌、四个人、两两组队的升级扑克:每局定一个”级牌”,比如打 5,那这局所有的 5 就成了仅次于王的大牌;谁先出完牌叫”头游”,赢的一方按赢的程度往上升级,从 2 一路打到 A,通关才算赢下一整场。

这游戏的技巧全靠口口相传。牌桌上永远有人说得斩钉截铁:被人进贡了一张大牌就等于被压死;手里有炸弹得沉住气,不到最后不能动;还牌的时候要卡住对手最需要的那个点数。说法多,反例也多,谁也拿不出证据。

我想知道哪些是真的。

把口口相传的说法,交给几十万局去判

有个笨办法:直接问大模型”掼蛋该怎么打”。这没用——它只会把网上那些口水话重新组织一遍,我自己也能写。

换个问法。让它别回答问题,去写一套模拟引擎:把掼蛋的规则完整实现成代码,牌型识别、理牌拆分、出牌逻辑、整场的升级和进贡流程,然后造出四个电脑玩家,各自装上不同的策略,互相打几十万局,用统计结果说话。

这个转换是整件事的关键。牌桌上的争论之所以永远没有结论,是因为样本太小——你打一晚上不过二十来局,运气盖过一切。但如果同一个策略和同一个对手打三千场,一两个百分点的胜率差异也能测得清清楚楚。争论就从”我觉得”变成了”跑出来是多少”。

它花了不少工夫,最后交出来的东西相当像样:一套纯 Python 的引擎,十八组实验,一份完整的结论报告,还有一份排好版、可以直接发给牌友的分享版 PDF。起手牌那组实验一口气发了四十万手牌,统计出手里平均能理出几手牌、多大概率至少摸到一颗炸弹。

工程质量也说得过去。一百一十七项单元测试全部通过;指定同一个随机种子重跑,结果精确重现;报告里的数字,九成以上能在原始 CSV 里逐个对上号。就”AI 交付的分析”这件事而言,数字层是干净的——没有编造,没有对不上账的引用。

真正让我停下来的,是一组太好看的数字。

一组太好看的数字

掼蛋打到 A 这一级有个坎,叫”过 A”:级牌升到 A 之后还得再赢一局才算通关,赢不下来,打若干局之后级牌要退回去重打。这条”打 A 退回”是各地牌规里争议最多的一条,有的桌打,有的桌不打。

报告里说,这条规则把先到 A 一方的最终胜率从 87% 压到了 77%,同时把落后三级以上一方的翻盘率从 9.9% 抬到了 20.7%。

一条民间牌规,一次改动,同时把两个指标掀翻:压制的那头正好降十个点,落后的那头正好翻倍。这读起来不像牌桌上自己长出来的规矩,倒像是哪家游戏公司的数值策划坐下来设计过的平衡器。

牌桌上的规矩很少这么优雅。

让另一批 AI 去查这批 AI

我没有自己一行行读代码——那套引擎连实验脚本有好几千行,真读完这事就黄了。我做的是把它拆成七个维度,每个维度派一个智能体去查:规则实现和官方牌规对不对得上、统计方法有没有滥用、报告里的数字和原始数据能不能一一对应、实验脚本和引擎有没有各自演化到对不上、有没有哪个结论的样本量根本撑不住它的语气。查完之后再开一批,任务只有一个:把上一批的结论逐条驳倒,驳不倒的才留下。

结果分成很清楚的两层。

数字那一层是干净的:抽样复跑精确重现,报告结论和 CSV 吻合,没有一处编造。

硬伤全在下面一层——规则底座。而这一层,恰恰是所有测试都没有覆盖到的地方。

三处硬伤

第一处:非级牌的 2 被排在了 A 之上。

这是斗地主的排序。掼蛋里 2 只要不是本局级牌,就是最小的单张,比 3 还小。排错了这一档,牵连的不止是比大小——进贡的时候要交出手里”最大的单张”,还牌的时候只能还”10 以下的小牌”,这两个动作都要用到这张排序表。2 站错了位置,整个进贡还贡系统跟着歪。

第二处:过 A 不查级牌归属。

过 A 有个前提:得是打自己的 A 那一局赢下来才算数。引擎没查这个,打着对方级牌的那一局,头游也被算作过 A 获胜。实测下来,17.7% 的对局以错误的方式终局——每六场就有一场,赢家是判错的。

第三处:连对和钢板允许无限长。

掼蛋里三个连续的对子叫”连对”,两个连续的三张叫”钢板”,都恰好这么长,再长的组合官方牌型里不存在。引擎却允许任意长,于是理牌的时候,约四分之一的手牌被理成了牌桌上根本打不出去的组合——手里看着牌很顺,实际全是废的。

一百一十七项测试,为什么一项都没响

这是我从这件事里学到最多的一点。

因为测试和实现是同一套理解的两面。写实现的时候认为 2 大过 A,写测试的时候当然也照这个写,于是”2 大过 A”被一百多项测试反复确认、牢牢焊死,成了整套系统里最稳定的部分。它稳定,但它是错的。

全绿的测试只回答一个问题:我有没有前后一致地实现我以为的规则。至于我以为的规则对不对,它一个字也没说。一套系统内部越自洽,它固化的错误前提就越难被自己发现——查错的人和犯错的人共用同一套先验,怎么查都是圆的。

这也解释了为什么问题偏偏出在规则层。统计方法有教科书可对,代码有测试可跑,唯独”掼蛋到底怎么打”这件事,没有任何一处是可以在系统内部验证的。它必须去系统外面找答案。

修完之后,戏剧性消失了

三处全部改掉,加上顺带修掉的一个潜伏崩溃和一处实验脚本的漂移,测试补到一百一十八项,同一个随机种子,整套重跑约十九分钟。

87% 和 9.9% 都没了。

结论 修复前 修复后
先到 A 一方的锁定率(不打退回) 87.0% 77.1%
落后三级以上的翻盘率(不打退回) 9.9% 20.5%
“打 A 退回”对锁定率的影响 −10 个百分点 −2.5 个百分点
“打 A 退回”对翻盘率的影响 翻倍 +2.1 个百分点

真实规则下,先到 A 的一方本来就只能锁住 77%,落后方本来就有两成翻盘机会。这两个数字原本就是这样,与那条争议规则毫无关系。”打 A 退回”的真实效果,只剩锁定率降两个半百分点、翻盘率升两个百分点、场均多打半局——一条温和的过程调节规则罢了。

那份戏剧性从头到尾属于第二处硬伤:打对方级牌也能算过 A,先到 A 一方的赢面被人为放大了整整十个百分点,”退回规则”于是显得像是在纠正一个本不存在的失衡。

同一次重跑还杀掉了两条结论。”还牌时切断对手最需要的那个点数”原本记着三个多百分点的优势,重跑后归零——它的全部优势来自第一处硬伤:还牌池里没有 2,可还的牌少一档,这条策略于是凭空占了便宜;真规则下大家都还 2,差异消失。”被进贡一张就会滚雪球”原本 52.3%,重跑后 50.7%,掉进噪声里;倒是”被双下”依然实打实地疼。

活下来的,和后来补跑的

也必须说另一面。真正的大效应扛住了。

还牌优先还孤张、不拆自己的对子和连牌,重跑后仍有九个百分点的优势,八个标准差,是所有还贡技巧里唯一一条量级足够大的。审计的时候我最担心的恰恰是它——它的旧数字是十个多百分点,万一也建立在”池子里没有 2″之上呢?实测只缩水一个百分点出头。同样扛住的还有”贡局别硬拆牌造单张”,效应量与修复前分毫不差。

真效应扛得住底座被换掉。这句话反过来正好能当判据用。

修完之后我又追着补跑了两个问题,两次的答案都印证了同一件事。

一个是用炸弹的时机。旧报告说”对手剩五到八张牌就该动炸”,可那是两千轮跑出来的粗话,五和九根本分不开。细扫十个门槛、每个一万八千轮,结果没有什么”魔法张数”:八到十二张是一片分不出高低的平原,五张才动确实慢半拍,亏一个半百分点,见炸就炸最差,攥着不放到最后也崩。它是一条平缓的坡,不是一个精确的开关。

另一个是有人提的疑问:优先还孤张,会不会正好帮对手凑成炸弹?我让它开了个天眼版本——偷看对手手牌,专门避开会帮对方凑成炸的点数。结果是这机制确实存在,还孤张送成炸的概率从三成升到近四成;但送出去的都是小炸,边际伤害只有两个百分点。而那个开了天眼的版本,把送炸率压掉七成,胜率反而比老老实实还孤张低了三个半百分点——为防送炸付出的结构代价,远大于省下来的那点损失。

两次追问,两次都是温和的答案。这倒过来让我更确信:那组 87% 到 77% 的漂亮数字,本来就不该出现在一副民间牌里。

带得走的三句话

效应量太大的时候,先怀疑方法学,别先高兴。真实世界里的效应大多温和,一个改动同时把两个指标掀翻,最可能的解释是底座错了,而不是你发现了什么规律。

校验点必须落在系统外面。官方规则、真人的经验、另一套独立实现——任何在系统内部转圈的验证,都只能证明它自己前后一致。测试全绿、复跑重现、数字对得上账,这些都好,但它们只覆盖了执行,覆盖不了前提。

结论要在底座重换之后再看一眼。修复之前的所有数字,无论跑了多少万轮、算到小数点后几位,都只是在精确地回答一个提错了的问题。

这几年我在临床上养出一个近乎反射的习惯:某个指标突然特别漂亮,第一反应是标本、机器还是单位出了问题,极少是病人真的好了那么多。这条本能挪到牌桌的模拟里,一样管用。

让 AI 跑分析,省掉的是执行的时间,省不掉的是替它定前提的那部分。前提错了,它会非常勤奋、非常自洽地把错误一路算到小数点后两位。


了解 创见思考 的更多信息

Subscribe to get the latest posts sent to your email.


已发布

分类

来自

标签:

了解 创见思考——怎样度过这一生 的更多信息

立即订阅以继续阅读并访问完整档案。

继续阅读

开往