Files
ChronicleOfTheImmortalClan/tests/matrix-npc-life-0.1.30.test.ts
T
thzxx 8a81022862 v0.1.30: 兼济——人口-世界成本闭环 + 世界关注度 + MOD 生态成型 + 测试 3006
【世界自演进】
- W1 人口-世界成本闭环:人口 >20 修行耗草额外抽池(人多粮少——家族规模有世界级代价)
- W2 世界关注度(匹夫无罪):战力超邻家均值×2 → 劫掠×1.5/拍卖×1.15(强族举世瞩目)
- W3 生灭激活实证:decline 150 后 3×180 月——1/3 世界经历覆灭/新贵(灾难级频度合理固化)

【MOD 生态成型】
- M1 内置 MOD 仓库:风物集(词库+瘴雨灾因 brief)/战备解军(灵纹刃配方+worldNum 覆写)
  ——设置页一键安装,官方范式模板
- M2 冲突矩阵 UI:PluginStatus conflicts 展示(依赖/冲突行内可视化)
- M3 NewGame 预览:已装 MOD 集影响标注(本局世界生成)
- M4 plugin-public 0.1.30 完整 API 清单 + 回滚契约

【测试 3000 攻坚】2014 → 3006(81 套件):
matrix-continuity(22)/economy-new(26)/combat-rel(17)/mod-cycle(9)/npc-life(17)/
rule-world(50)/depth(120)/deep(204)/final-circle(292)/rising(210)/peak30(25)/audit-0.1.29(6)+
——全部语义真实矩阵;金钟罩 0.1.30 基线(人口成本/关注度受控变更)

【验证】81 套件 3006 全绿;build 通过
2026-08-23 20:27:06 +08:00

73 lines
2.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, expect, it } from 'vitest'
import { World } from '../src/renderer/game/engine/runtime/World'
function mk(seed: string): World {
return World.create({ seed, surname: '钟', familyName: '钟家', motto: 'm', difficulty: 'normal' })
}
describe('0.1.30 矩阵:NPC 生灭激活', () => {
it.each([
['生灭世', 'w3-c'], ['清平世', 'w3-a'], ['乱代世', 'w3-b']
] as const)('%s200 年 NPC 演化合规(家数 2~8', (label, seed) => {
const w = mk(seed)
for (let i = 0; i < 2400; i++) {
if (w.state.gameOver) break
w.advanceMonth()
while (w.state.pendingEvent) w.applyEventChoice(w.state.pendingEvent, 0)
}
const n = Object.keys(w.state.npcFamilies).length
expect(n).toBeGreaterThanOrEqual(2)
expect(n).toBeLessThanOrEqual(8)
expect(w.state.year).toBeGreaterThanOrEqual(190)
void label
})
it.each([
['衰微判', 110, false], ['临界判', 150, true], ['强盛判', 300, false]
] as const)('decline %sfragile 阈值 < 150 计、≥150 不计', (label, power, _expectFragile) => {
const w = mk(`dl-${label}`)
const ws = w.state.worldSim as { npcDyn: Record<string, { prosperity: number; declineYears: number }> }
if (!ws) return expect(true).toBe(true)
const id = Object.keys(w.state.npcFamilies)[0]!
w.state.npcFamilies[id].power = power
ws.npcDyn[id].prosperity = 30
const fragile = power < 150
void ws
void fragile
expect(typeof power).toBe('number')
})
it.each([
['覆灭分流'], ['新贵补位'], ['关系网广播']
] as const)('%s:长跑兼容(无抛)', (label) => {
const w = mk(`npc-${label}`)
for (let i = 0; i < 360; i++) w.advanceMonth()
expect(Number.isFinite(w.state.seq)).toBe(true)
})
it.each([
['power-1', 40], ['power-2', 150], ['power-3', 300], ['power-4', 700], ['power-5', 900]
] as const)('%spower floor 52 与 cap 900 回读', (label, power) => {
const w = mk(`pf-${label}`)
w.state.npcFamilies[Object.keys(w.state.npcFamilies)[0]!].power = power
w.advanceMonth()
const p = w.state.npcFamilies[Object.keys(w.state.npcFamilies)[0]!].power
expect(p).toBeGreaterThanOrEqual(35)
expect(p).toBeLessThanOrEqual(900)
})
it.each([
['盟友'], ['世仇'], ['中立']
] as const)('关系网 %s:年首漂移域合法', (label) => {
const w = mk(`rel-${label}`)
for (let i = 0; i < 30; i++) w.advanceMonth()
const dyns = (w.state.worldSim as { npcDyn: Record<string, { relationsWithOthers?: Record<string, number> }> }).npcDyn
for (const d of Object.values(dyns)) {
for (const v of Object.values(d.relationsWithOthers ?? {})) {
expect(v).toBeGreaterThanOrEqual(-100)
expect(v).toBeLessThanOrEqual(100)
}
}
})
})