下载 App
08 · 我差点把一个可以解决的问题写进"已知限制"
==============================
《临界》开发者日志 · 第八篇
上一篇我承认了失败。这一篇讲我怎么把它救回来的——以及我上一轮到底错在哪。
---
【我先放弃了】
第七篇里我写过这样一段:
要真正实现这个设计,需要重新设计驱动/耗散的关系 ——
那是需要单独一轮设计的工作,不该在投稿前动。
于是我把它标成"未竟目标",写进 ROADMAP,然后停下来了。
我当时的理由是"时间紧张"。但事实是——距离截稿还有 13 天。
我不是没时间,我是没找到方向,然后把"没找到方向"包装成了"不该现在做"。
---
【转折:我换了一个指标】
真正让我突破的,不是更多努力,而是换了一个测量对象。
前几轮我一直在测危险度——毕竟那是游戏 HUD 上显示的数值,看起来最相关。
DANGER L4 被动 max=0.45 | 主动 max=0.45
DANGER L5 被动 max=0.45 | 主动 max=0.45
永远相同。
这一轮我换成了总雪量——山体上到底有多少雪:
SNOW L1 被动 dSnow=+5530 avalanches=0
SNOW L1 主动 dSnow=+5544 avalanches=8
答案瞬间清楚了。
---
【一笔账】
每天 Load(0.10) x 6 天 x 9216 格 = 5530 ← 被动:账完全对得上
主动:8 次雪崩只带走 14 单位(0.25%) ← 雪崩根本没在搬雪
雪崩没有从山体带走雪。
那"释放压力"当然毫无意义——压力根本没有被释放,只是被重新摆放了一下。
---
【而我上一轮调错了参数】
第七篇里我写过,我试过 edgeLoss(边界耗散)但没用。
原因现在很清楚:
if self.tuning.spillEdge and #nb < DIRS then -- 只对边界格生效
96×96 的网格,边界格只有 4×96-4 = 380 格,占 4.1%。
随机位置的雪崩大多在内部就停住了,根本到不了边界。
我花了大量轮次去调一个影响面只有 4% 的参数。
---
【修复:三处,缺一不可】
【① 新增 Snowfield:ShedAvalanche(frac)】
按 av.cells(本次雪崩影响到的格子)等比带走一部分雪。
【② 位置:必须放在 Relax 的完成路径里】
我第一次把它放在 Game:OnAvalancheEnd——完全没有效果。
查了半天才发现:
-- Snowfield.lua 完成路径
self.avalancheLog[#self.avalancheLog + 1] = { ... }
self.avalanche = nil -- ← 记录已经没了
上层拿到的是 nil,av.cells 根本读不到。加完毫无效果,而且不报错。
---
【后记(2026-10-06 夜补)】
本文里那个 「主动玩法少累积 13~34% 的雪」 是无头批量测试的结论。
投稿前用交互式运行在第 5 关复测:被动 / 适度 / 全狂炸三种打法的终局村子积雪都是 5 / 7。
HUD 只显示整数(第 5 关上限 7.40,分辨率约 13%),所以:
小于 ~13% 的差异分辨不出,而 34%(≈2.5 格)如果存在应当看得见。
已在 submission.md / STATUS.md 上把这条数字标为「待重新测量」。
不删除,但也不再当作公开主张的重点。
【✅ 后记的后续:测出来了(2026-10-06 深夜)】
交互式复测之所以测不出来,是因为 HUD 只显示整数。那就绕开它 —— 用无头模拟直接读浮点值。
结果发现两件事:
1. 采样必须带上 Presets.CRITICAL。 少了它,山体从空山开始,整季十二天只积到约 1.9/格,
阈值却是 4 —— 整季都到不了临界,危险度恒为 0。这时测出来的是「主动管理毫无作用」,
一个假结论(我先踩了这个坑,是靠「它和长跑日志里的自然崩塌次数矛盾」才觉察的)。
2. 带上预设、5 关 × 5 种子跑完整季之后,真实幅度是:
山体总雪量 少 11 ~ 13%
危险度(第3~5关) 0.44~0.45 -> 0.28~0.31 (相对降 30~39%;第 1~2 关恒为 0)
自然崩塌 被动 0~2.4 次/季(第5关最高) -> 主动 0 次(五关皆为零)
带下山的雪 2824 ~ 3834 单位/季(五关的主动打法区间)
所以那个「13~34%」:下半段成立,上段(34%)复现不出来。
公开文案已按实测收窄为 11~13%,并换用更硬的一组数字(危险度与自然崩塌次数)——
它们比一个百分比更能说明设计意图。
脚本:tests/experiment_village.lua(node tests/run.js tests/experiment_village.lua 可复跑)。
《临界》· 2026 TapTap 聚光灯游戏创作挑战
移到 Relax 完成路径、置空之前,立刻生效。
【③ 强度:0.12 不够,要 0.40】
带雪比例 0.12 只带来 7.4% 的差异——方向对了,量不够。
改成 0.40 后,主动玩法少积累 13~34% 的雪。
---
【结果】
V L1 | 被动 +5530 危险0.00 nat=0 | 主动 +4141 危险0.00 nat=0
V L2 | 被动 +8110 危险0.00 nat=0 | 主动 +5313 危险0.00 nat=0
V L3 | 被动 +9685 危险0.00 nat=1 | 主动 +8291 危险0.00 nat=0
V L4 | 被动 +11713 危险0.45 nat=1 | 主动 +10160 危险0.35 nat=0
V L5 | 被动 +15215 危险0.45 nat=1 | 主动 +11844 危险0.27 nat=0
危险度终于出现差异了(L4: 0.45→0.35,L5: 0.45→0.27)。
自然雪崩全部消失(被动 3 关有,主动 0)。
"频繁释放压力 → 山体更安全 → 自然大雪崩不再发生"——五个关卡全部成立。
---
【但我必须做一件危险的事】
搬走雪会改变自组织临界性。 如果为了修玩法而毁掉了游戏的灵魂(幂律分布),那是得不偿失。
所以我复验了经典 BTW 基准:
700 样本,含带雪: bins=[208, 130, 127, 66] ← 单调下降 ✓
幂律还在。 临界性没有被破坏。
---
【我学到的事】
【1. 指标选错,努力全废】
危险度看起来是最该测的——它是游戏里显示的数值,玩家能看见。
但它在自组织临界态下会饱和:系统自动稳定在临界点,亚稳格比例就是个常数。
总雪量才是真正的状态量。
我为此付出了十几轮。换指标只花了十分钟,定位问题只花了一次测量。
【2. "不该现在做"经常是"我还没想明白"的伪装】
我在第七篇里写下"不该在投稿前动"的时候,其实是没找到方向,然后给它找了一个体面的理由。
如果那天我真的停下了,这个游戏的核心承诺就永远是假的。
【3. 加完没效果 → 先怀疑"代码没被执行",而不是"参数不够"】
ShedAvalanche 第一次加完完全没有效果,而且不报错。
我第一反应是"比例太小",差点去调大参数。幸好我回头查了调用时机——原来是记录已经置空了。
Lua 里"静默无效"的坑,比报错的坑危险得多。
【4. 修玩法之前,先想清楚会不会毁掉灵魂】
搬走雪是最容易想到的修法,但它可能直接破坏临界性。
我先修,然后立刻复验。 这一步不能省——否则我可能修好了一个小问题,毁掉了一个大卖点。
---
【后记(2026-10-07 补,正文不动)】
这篇里那组数(「11~13%」「危险度 0.44~0.45 → 0.28~0.31」「被动 0~2.4 次/季」)测于阀门修复之前。
当天 01:05 我修掉了「被 240 帧阀门掐断的雪崩从不被记录」—— 而那些恰恰是最大的雪崩。
修复后同口径重测:山体总雪少 10.6~21.4%、季末危险度 0.343 → 0.176 / 0.095 / 0.038、自然崩塌 1.0 → 0 次。
这篇的结论没变,反而更硬了:主动管理确实在降低危险度 —— 而且「带下山的雪」从 2973~3834 涨到 3834~15024,
因为最大的那些雪崩终于被数进去了。我当时以为自己已经把数字收窄到了诚实的位置,其实还差一次修复。
---
《临界》· 2026 TapTap 聚光灯游戏创作挑战




