0.1.39 P4: purgeNpc 清理 worldGen.npcs/relations 僵尸定义 + 金钟罩重算 + 4例测试

This commit is contained in:
2026-09-13 13:01:00 +08:00
parent e2070c8fcb
commit fdc9d750f2
3 changed files with 88 additions and 4 deletions
+3 -3
View File
@@ -7,11 +7,11 @@ import { World } from '../src/renderer/game/engine/runtime/World'
* 任何改动(重构日程/调平衡/加系统)若改变了确定性序列或结果,此测试立刻报红。
* 更新规则:仅当**有意**变更序列逻辑时,三枚 seed 指纹同版更新并注明原因。
*/
// 0.1.37 天人感应基线:因果系统(karma衰减/灾年调制/NPC姿态调制/渡劫调制) + 飞升试炼三阶段 + 世界奇观(种子派生零rng)——
// 受控变更重算(karma入指纹/assessStance karma调制/WorldSim.tick新增D-0.8/D-0.9段)。
// 0.1.39 淬体·洗髓基线:purgeNpc 清理 worldGen.npcs/relations 僵尸定义(存档体积精简——时序内更改)。
// 受控变更重算(bell-seed-2 三档:NPC 灭亡后 worldGen 摘要缩小→指纹变;其余 seed 无 NPC 灭亡→零漂)。
const GOLDEN: Record<string, Record<number, string>> = {
'bell-seed-1': { 560: '45b0c17a', 1200: '62e037c1', 2160: 'b85dd7c7' },
'bell-seed-2': { 560: '1279a1da', 1200: '3439bd8f', 2160: 'a29efe9f' },
'bell-seed-2': { 560: 'be278aba', 1200: '01126e70', 2160: 'fd03f9b2' },
'bell-seed-3': { 560: 'f24480f4', 1200: 'e52bed85', 2160: 'abb2a5d2' }
}
+69
View File
@@ -0,0 +1,69 @@
/**
* 0.1.39 P4purgeNpc 清理 worldGen.npcs/relations 僵尸定义测试
* 验证 NPC 灭亡后 worldGen.npcs 和 worldGen.relations 中的对应条目被同步移除。
*/
import { describe, expect, it } from 'vitest'
import { World } from '../src/renderer/game/engine/runtime/World'
import { resetSaveBus, attachLogSink } from './world.helpers'
import { stateFingerprint, longRun } from './fingerprint.helper'
function baseWorld(seed: string): World {
const w = World.create({ seed, surname: '封', familyName: '封家', motto: 'm', difficulty: 'normal' })
resetSaveBus()
attachLogSink(w)
return w
}
describe('0.1.39 purgeNpc 存档体积精简', () => {
it('开局 worldGen.npcs 非空且与 npcFamilies 一一对应', () => {
const w = baseWorld('purge-1')
const genNpcs = w.state.worldGen?.npcs ?? []
const famIds = Object.keys(w.state.npcFamilies)
expect(genNpcs.length).toBe(famIds.length)
for (const n of genNpcs) {
expect(famIds).toContain(n.id)
}
})
it('长跑后灭亡 NPC 不残留于 worldGen.npcs', () => {
// 用长跑让 NPC 有机会灭亡(180 年 = 2160 月)
const w = longRun('purge-2', 2160)
if (w.state.gameOver) return // 族灭则跳过
const genNpcs = w.state.worldGen?.npcs ?? []
const famIds = new Set(Object.keys(w.state.npcFamilies))
// 所有 worldGen.npcs 中的 id 必须在 npcFamilies 中仍然存活
for (const n of genNpcs) {
expect(famIds.has(n.id)).toBe(true)
}
// 反过来,所有存活 NPC 必须在 worldGen.npcs 中有定义
for (const fid of famIds) {
expect(genNpcs.some((n) => n.id === fid)).toBe(true)
}
})
it('长跑后灭亡 NPC 不残留于 worldGen.relations', () => {
const w = longRun('purge-3', 2160)
if (w.state.gameOver) return
const famIds = new Set(Object.keys(w.state.npcFamilies))
const rels = w.state.worldGen?.relations ?? {}
// relations 的 key 必须都是存活 NPC
for (const rid of Object.keys(rels)) {
expect(famIds.has(rid)).toBe(true)
// relations 的 value 中的 key 也必须都是存活 NPC
for (const oid of Object.keys(rels[rid] ?? {})) {
expect(famIds.has(oid)).toBe(true)
}
}
})
it('确定性:同 seed 同月数 worldGen.npcs 内容一致', () => {
const a = longRun('purge-4', 1200)
const b = longRun('purge-4', 1200)
expect(JSON.stringify(a.state.worldGen?.npcs)).toBe(JSON.stringify(b.state.worldGen?.npcs))
expect(stateFingerprint(a.state)).toBe(stateFingerprint(b.state))
})
})