Files
ChronicleOfTheImmortalClan/tests/audit-regression.test.ts
T
thzxx a99420da09 v0.1.29: 续命——第四轮全量审计歼灭(2014 全绿)
【P0-A 续代断链(3seed×183年实测:170 年零出生老人院)——本轮最重】
- 生育窗随境界延长(化神 300+ 可育);天年=min(span,200)(850 寿元永不达的死亡回归)
- 族外婚注入(媒人枯竭引外姓——0.1.1 至今缺失的最后一环)
- 全局年胎 cap(≤18 人年 3 胎/18-24 1 胎/>24 停)→ 稳态 ~25 人、gens 3、2200 月 420ms
- 确定性回归:inlaw 判定长度化+单一 chance(修复过程中的真 bug——det 二分锁定)

【P1 七件】legacypass 年锚(同一年 12 连发 224 次实测)/敌强度相对化(0.35+rel×0.55,
cap 2.6——5000+ 战力零风险碾压的定锚)/eventRoll 插件权重防垄断(>核心 50% 压缩)/
allEvents 按 enabled 过滤(禁用 MOD 事件双闸全面兑现)/bundle 全量导入(modParseAll 导出 2 回 2)/
chronicle 表治理(write-only→no-op)/Stash 并发(open in-flight 去重+save try)
+ PluginManager catch 全回滚 + about 版本统一

【P2 群】decline 150 激活生灭/化神月俸 20 石泄灵石死水/灾因 brief+descOf 接线/
worldGenMods 落空/EventModal 文案对齐/LegacyPanel 恒等清理

【测试】70 套件 2014 全绿(audit-0.1.29 六例:人口曲线/传薪年锚/强度公式/bundle 全量/异常回滚/灾因 brief);
【金钟罩】0.1.29 基线重算(续代/战斗/事件数值受控变更);build 通过
2026-08-23 20:14:42 +08:00

89 lines
3.7 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import { World } from '../src/renderer/game/engine/runtime/World'
import { newCharacter } from '../src/renderer/game/engine/runtime/pcgen'
import { Rng, seedToRng } from '../src/renderer/game/engine/kernel/rng'
import { PACK } from '../src/renderer/game/data/registry'
import { buildApprentice } from '../src/renderer/game/engine/runtime/Systems/tournament'
import { sendMission } from '../src/renderer/game/engine/runtime/Systems/missions'
import { buyItem, marketPrice } from '../src/renderer/game/engine/sim/Market'
import { findEvent } from '../src/renderer/game/engine/runtime/Systems/events'
import { runTournament } from '../src/renderer/game/engine/runtime/Systems/tournament'
import { stateFingerprint, longRun } from './fingerprint.helper'
import { resetSaveBus, attachLogSink } from './world.helpers'
function baseWorld(seed: string): World {
const w = World.create({ seed, surname: '佘', familyName: '佘家', motto: 'm', difficulty: 'normal' })
resetSaveBus()
attachLogSink(w)
return w
}
describe('审计回归:P0 修复固化', () => {
it('单亲 rollRoots 不再崩溃(pcgen TypeError 修复)', () => {
const r = new Rng(seedToRng('single'))
const dad = newCharacter(r, { name: '父', gender: 'male', generation: 1, bornYear: -30, age: 30, realm: { major: 'qi', minor: 1 } })
dad.roots = { grade: 3, primary: '火', secondary: [] }
const child = newCharacter(r, { name: '子', gender: 'male', generation: 2, bornYear: 0, age: 0, father: dad })
expect(child.roots.grade).toBeGreaterThanOrEqual(0)
})
it('插件事件池事件可被 findEvent 解析(软锁修复)', () => {
const w = baseWorld('aud-find')
w.installPlugin({
id: 'aud-event-plugin',
name: '审计事件',
version: '1',
kind: 'events',
install(ctx) {
ctx.addEventPool('aud', [
{ id: 'id-evt-aud', name: '试炼', category: 'daily', weight: 1, text: '审计副本。', options: [{ label: '收下', eff: { rep: 1 } }] }
])
}
})
// 直接模拟抽到该事件后 UI 路径解析
const def = findEvent('id-evt-aud', w)
expect(def).toBeTruthy()
})
it('packOverride 经插件上下文真实生效(死实现修复)', () => {
const w = baseWorld('aud-pack')
w.installPlugin({
id: 'aud-data-plugin',
name: '货币更替',
version: '1',
kind: 'data',
install(ctx) {
ctx.overridePack({ items: { ...PACK.current().items, lingcao: { ...PACK.current().items['lingcao'], basePrice: 500 } } })
}
})
expect(marketPrice(w, 'lingcao')).toBeGreaterThan(100)
expect(buyItem(w, 'lingcao', 2)).toBe(false) // 1000 > 800,双份买不起
})
it('buildApprentice 空候选不再抛错(守卫修复)', () => {
const w = baseWorld('aud-appr')
for (const c of Object.values(w.state.members)) c.state = 'apprentice'
buildApprentice(w) // 此前 Rng.pick([]) 抛错
expect(w.state.family.stones).toBe(800)
})
it('sendMission 无效 id(回档残留)不再抛错', () => {
const w = baseWorld('aud-squad')
const ok = sendMission(w, 'm-anmoku', ['x-not-exist'])
expect(ok).toBe(false)
})
it('tournament 越过能力开关后休赛(未启时无副作用)', () => {
const w = baseWorld('aud-tourney')
w.toggleSystem('tournament')
const before = w.state.battles.length
runTournament(w, ['x3'])
expect(w.state.battles.length).toBe(before)
})
it('防御性修补后金钟罩不变(行为等价确认)', () => {
expect(stateFingerprint(longRun('bell-seed-1').state)).toBe('184a2203')
expect(stateFingerprint(longRun('bell-seed-3').state)).toBe('a80ce621')
})
})