import { describe, expect, it } from 'vitest' import { World } from '../src/renderer/game/engine/runtime/World' import { PILL_RECIPES, FORGE_RECIPES, pillRecipeByOutput, forgeRecipeByOutput } from '../src/renderer/game/data/items' import { bonusOf } from '../src/renderer/game/data/buildings' import { MAJOR_RATE } from '../src/renderer/game/data/pacing' function mk(seed: string): World { return World.create({ seed, surname: '钟', familyName: '钟家', motto: 'm', difficulty: 'normal' }) } describe('矩阵:资源与配方边界', () => { it.each(PILL_RECIPES.map((r) => [r.output, r.name, r.lingcao, r.beastcore, r.stones, r.danfangLevel] as const))( '丹方 %s:门槛与产出可测(craftPill 路径)', (output, name, lingcao, beastcore, stones, lvl) => { const w = mk(`pill-${output}`) w.state.family.buildings = { danfang: lvl } const fam = w.state.family fam.inventory['lingcao'] = lingcao + 5 fam.inventory['beastcore'] = beastcore + 2 fam.stones = stones + 20 const ok = w.craftPill(output.replace('pill-', '') as never) // L5 丹房必成;其余至少不抛且库存守恒 expect(typeof ok).toBe('boolean') expect(fam.inventory['lingcao']).toBeLessThanOrEqual(lingcao + 5) void name }) it.each(FORGE_RECIPES.map((r) => [r.output, r.name, r.lingkuang, r.beastcore, r.stones] as const))( '铸器 %s:材料即成入库', (output, name, lingkuang, beastcore, stones) => { const w = mk(`forge-${output}`) const fam = w.state.family fam.inventory['lingkuang'] = lingkuang + 3 fam.inventory['beastcore'] = beastcore + 3 fam.stones = stones + 30 expect(w.forgeArtifact(output as never)).toBe(true) expect(fam.inventory[output]).toBe(1) void name }) it.each([ ['聚灵', 'juling', 'expBonus'], ['洞府', 'dongfu', 'expBonus'], ['丹房', 'danfang', 'craftChance'] ])('bonusOf %s:表达式求值单调随等级', (_id, building, key) => { const lows = bonusOf(building, key, 1) const highs = bonusOf(building, key, 5) expect(highs).toBeGreaterThan(lows) }) it.each(Array.from({ length: 6 }, (_, i) => [i * 4 + 1]))('灵石 clamp:%d 步负值非无穷', (_seed) => { const w = mk('clamp-m') w.state.family.stones = -50 w.advanceMonth() expect(w.state.family.stones).toBeLessThan(100000) }) it.each([ 'mortal', 'qi', 'foundation', 'core', 'nascent', 'spirit' ] as const)('MAJOR_RATE %s:进度因子为正', (major) => { expect(MAJOR_RATE[major]).toBeGreaterThan(0) }) }) describe('矩阵:存档快照往返', () => { it.each([['s1'], ['s2'], ['s3']])('快照往返 %s:JSON 往返后世界年仍演进', (seed) => { const w = mk(`snap-${seed}`) for (let i = 0; i < 12; i++) w.advanceMonth() const snap = JSON.parse(JSON.stringify(w.state)) const w2 = World.create({ seed, surname: '钟', familyName: '钟家', motto: 'm', difficulty: 'normal' }) w2.state = snap as never w2.advanceMonth() expect(w2.state.seq).toBeGreaterThan(0) }) it.each([ ['世界生灭', 'worldSim'], ['插件清单', 'plugins'], ['天下史表', 'worldGen'] ] as const)('关键字段 %s:快照往返保持', (label, key) => { const w = mk(`keep-${label}`) for (let i = 0; i < 30; i++) w.advanceMonth() const snap = JSON.parse(JSON.stringify(w.state)) const w2 = World.create({ seed: `keep-${label}`, surname: '钟', familyName: '钟家', motto: 'm', difficulty: 'normal' }) w2.state = snap as never const v = (w2.state as Record)[key] if (key !== 'plugins') expect(v !== undefined).toBe(true) // plugins 装后才有——快照往返非增 }) }) describe('矩阵:难度与初始态', () => { it.each([['easy', 1200, 0.9], ['normal', 800, 1], ['hard', 550, 1.15]] as const)( '%s:初始灵石 %d / 强度 %d', (diff, stones, strength) => { const w = World.create({ seed: `diff-${diff}`, surname: '钟', familyName: '钟家', motto: 'm', difficulty: diff }) expect(w.state.family.stones).toBe(stones) const id = Object.keys(w.state.npcFamilies)[0]! expect(w.state.npcFamilies[id].power).toBeGreaterThan(0) void strength }) it.each([ ['默认零储物', {}], ['少资源', { lingcao: 10 }], ['满资源', { lingcao: 999, lingkuang: 999, beastcore: 99 }] ])('初始库存 %s:产出推进不崩', (label, inv) => { const w = mk(`inv-${label}`) w.state.family.inventory = { ...w.state.family.inventory, ...inv } for (let i = 0; i < 30; i++) w.advanceMonth() expect(w.state.year).toBeGreaterThanOrEqual(3) }) })