把卡尔玛牵线和潘森跳大加进来之后,固定时间表太容易猜,完全独立的随机又可能挤成一团。这次我试着在两者之间找一个节奏。

先留一段确定不会发生的空窗

每种干扰都有自己的最短冷却,并加上 0 到 1200 毫秒的抖动。在下一次检测时间之前,事件不会开始。这样刚处理完一个威胁,不会立刻又被同一种事件追着打。

没来过,就慢慢提高概率

进入检测阶段后,初始触发概率是 18%。一次没触发,下一次就提高 20 个百分点,并在 900 到 1600 毫秒后重试。到达最晚时间时,只要没有其他约束阻拦,就允许触发。

const chance = Math.min(1, .18 + threat.misses * .2);
if (this.elapsedMs >= threat.deadline || this.random() < chance) {
  this.threatGapUntil = this.elapsedMs + 2200
    + Math.floor(this.random() * 1401);
  return true;
}
threat.misses++;
threat.nextAt = this.elapsedMs + 900
  + Math.floor(this.random() * 701);

事件之间,也得互相看一眼

所有威胁的起手共用一段 2.2 到 3.6 秒的间隔。卡尔玛牵线和潘森跳大还加了互斥:一方正在执行时,另一方暂缓起手,避免玩家被定在落点里却没有合理的逃跑机会。斧头仍可能与已开始的事件重叠,所以画面里的预警依然很重要。

最晚触发时间也不能越过这些约束。换句话说,“到点必出”仍要服从公平性检查,而不是强行把事件塞进去。

随机逻辑怎么检查?

引擎允许从外部传入 random 函数。测试时换成带种子的随机序列,就能重复同一段过程,检查是否真的有冷却、三种威胁能否长期重复出现、起手之间是否留了间隔。

这套方法不会让每一局都恰到好处,但比只看一两次游玩更容易找到长时间不出现、接连触发或暂停后计时出错的问题。节奏最后仍需要实际玩过再调。