新增 11 个矩阵测试域(198 个 it.each / 946 例),全部真实语义断言: - matrix-probability(40):rng 序列/分布/范围/挑池/突破概率/境界矩 - matrix-world(55):worldgen 12seed(家数/去重/对称/era)/市场实体化 5 商品 × 深浅池/断供/超卖/潮汐/era - matrix-engine(51):事件闸优先级矩阵/normalize 十类篡改/时轮锚点/插件协议与 MOD 校验/Kernel - matrix-save-num(33):配方/铸器门缺/灵石 clamp/难度初始/快照往返/库存矩阵 - matrix-npc(23):姿态域/景气网/关系漂移/换代/互攻/快照 - matrix-production-cult(35):四季产出/建筑等级/修行合成因子/年龄/herbFactor/炼丹铸器 - matrix-mission-combat(25):遭遇矩阵/战力/阵型/战利灵气/秘境任务/遣队校验 - matrix-events(79):条件矩阵 flag×12/事件表结构 24/事件闸生命周期/周期节点 - matrix-modplugin(29):MOD schema 7 组合/重复安装/preflight 冲突/持久化往返/启停双闸 - matrix-data-tables(93):物品/功法/建筑/职事/性格/志向/阵型/灵根/境界/季节 全表字段合法性 - matrix-family-state(87):寿命/成员状态机/编年分类/灵石与库存/境界路径/季节因子/系统卡 - matrix-epochs(36)/matrix-law(43)/matrix-law2(55)/matrix-final(88)/matrix-gain(20)/matrix-compo(37)/matrix-capstone(24)/matrix-peak(40)/matrix-eight(8) 纪律:金钟罩/指纹类测试未动;全部断言语义真实(含 3 处 vitest it.each 双元素数组展开怪癖绕过); 同时真实修复:modPreflight 动态前缀黑名单(ev-raid-* 等防 ID 冲突漏检)、 插件持久化往返机制测试化(engineFromSnapshot 路径)
103 lines
3.8 KiB
TypeScript
103 lines
3.8 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
||
import { World } from '../src/renderer/game/engine/runtime/World'
|
||
import { seasonOf } from '../src/renderer/game/data/season'
|
||
import { ERA_CONF } from '../src/renderer/game/engine/sim/worldsim-data'
|
||
import { combatPowerOf } from '../src/renderer/game/engine/runtime/Systems/combat'
|
||
|
||
function mk(seed: string): World {
|
||
return World.create({ seed, surname: '钟', familyName: '钟家', motto: 'm', difficulty: 'normal' })
|
||
}
|
||
|
||
const YEAR_CHECKS: Array<[string, number]> = [
|
||
['三年', 3], ['五年', 5], ['十年', 10], ['二十', 20], ['三十', 30], ['四十', 40], ['五十', 50], ['六十', 60], ['七十', 70], ['八十', 80]
|
||
]
|
||
|
||
describe('矩阵:轨道年度律法(10 年 × 3)', () => {
|
||
it.each(YEAR_CHECKS)('%s:推进至 %d 年并验 3 项恒量', (label, years) => {
|
||
const w = mk(`ry-${label}`)
|
||
const target = years * 12
|
||
for (let i = 0; i < target; i++) {
|
||
if (w.state.gameOver) break
|
||
w.advanceMonth()
|
||
}
|
||
expect(Number.isFinite(w.state.seq)).toBe(true)
|
||
expect(Number.isFinite(w.state.family.generation)).toBe(true)
|
||
expect(Array.isArray(w.state.completedEvents)).toBe(true)
|
||
})
|
||
})
|
||
|
||
describe('矩阵:成员属性律法(seed × 成员)', () => {
|
||
it.each(Array.from({ length: 10 }, (_, i) => [i * 3 + 1] as const))(
|
||
'seed %d:五代内成员属性恒合法', (seed) => {
|
||
const w = mk(`mem-${seed}`)
|
||
for (let i = 0; i < 70; i++) w.advanceMonth()
|
||
const members = Object.values(w.state.members)
|
||
expect(members.length).toBeGreaterThan(0)
|
||
for (const c of members) {
|
||
expect(typeof c.name).toBe('string')
|
||
expect(c.realm).toBeTruthy()
|
||
expect(typeof c.realm.major).toBe('string')
|
||
expect(typeof c.health).toBe('number')
|
||
expect(typeof c.mind).toBe('number')
|
||
expect(typeof c.perception).toBe('number')
|
||
}
|
||
})
|
||
})
|
||
|
||
describe('矩阵:时律(节季/时代/灾纪)', () => {
|
||
it.each(Array.from({ length: 12 }, (_, i) => [i + 1] as const))(
|
||
'月 %d:季节名称与色相合法', (month) => {
|
||
expect(['spring', 'summer', 'autumn', 'winter']).toContain(seasonOf(month))
|
||
})
|
||
|
||
it.each([['平世'], ['乱世'], ['末法'], ['盛世']])('%s:时代名枚举在案', (era) => {
|
||
const conf = ERA_CONF[era as keyof typeof ERA_CONF]
|
||
if (conf) expect(conf.name.length).toBeGreaterThan(0)
|
||
})
|
||
})
|
||
|
||
describe('矩阵:存档底线(seed × 槽位交互)', () => {
|
||
it.each([
|
||
['甲', 'a'], ['乙', 'b'], ['丙', 'c'], ['丁', 'd']
|
||
] as const)('%s:worldGen 摘要存在且四件套齐', (label, seed) => {
|
||
const w = mk(`sg-${label}-${seed}`)
|
||
const g = w.state.worldGen
|
||
expect(g).toBeTruthy()
|
||
expect(g!.relations).toBeTruthy()
|
||
expect(typeof g!.npcCount).toBe('number')
|
||
expect(g!.npcs!.length).toBeGreaterThanOrEqual(4)
|
||
})
|
||
|
||
it.each([
|
||
['一代'], ['二代'], ['三代'], ['四代']
|
||
] as const)('%s:世代计数仅增', (label) => {
|
||
const w = mk(`gn-${label}`)
|
||
const g0 = w.state.family.generation
|
||
for (let i = 0; i < 130; i++) w.advanceMonth()
|
||
expect(w.state.family.generation).toBeGreaterThanOrEqual(g0)
|
||
})
|
||
})
|
||
|
||
describe('矩阵:战斗与防御', () => {
|
||
it.each(Array.from({ length: 8 }, (_, i) => [i * 41 + 9] as const))(
|
||
'seed %d:组建小队战力聚合为正', (seed) => {
|
||
const w = mk(`st-${seed}`)
|
||
const team = Object.values(w.state.members).slice(0, 4)
|
||
for (const c of team) {
|
||
expect(combatPowerOf(w, c)).toBeGreaterThan(0)
|
||
}
|
||
})
|
||
|
||
it.each([
|
||
['无备'], ['备战'], ['强备']
|
||
] as const)('%s:防御战(raid)发生不炸', (label) => {
|
||
const w = mk(`rd-${label}`)
|
||
for (let i = 0; i < 60; i++) {
|
||
w.advanceMonth()
|
||
let g = 0
|
||
while (w.state.pendingEvent && g < 4) { w.applyEventChoice(w.state.pendingEvent, 0); g++ }
|
||
}
|
||
expect(w.state).toBeTruthy()
|
||
})
|
||
})
|