import { describe, expect, it } from 'vitest' import { World } from '../src/renderer/game/engine/runtime/World' import { generateWorld } from '../src/renderer/game/engine/sim/worldgen' import { npcById } from '../src/renderer/game/data/npcs' import { engineFromSnapshot } from '../src/renderer/game/engine/GameEngine' describe('0.1.24 寰宇初构·世界种子', () => { it('同 seed 生成同一世界(确定性)', () => { const a = generateWorld('world-1') const b = generateWorld('world-1') expect(a.npcs.length).toBe(b.npcs.length) expect(a.npcs[0]!.id).toBe(b.npcs[0]!.id) expect(a.feuds).toEqual(b.feuds) }) it('不同 seed 生成不同世界(势力随机 4~8 家)', () => { const seen = new Set() for (const s of ['w1', 'w2', 'w3', 'w4', 'w5']) { const g = generateWorld(s) expect(g.npcs.length).toBeGreaterThanOrEqual(4) expect(g.npcs.length).toBeLessThanOrEqual(8) seen.add(g.npcs[0]!.id) } expect(seen.size).toBeGreaterThan(1) }) it('势力名单无重名(去重保证)', () => { for (const s of ['n1', 'n2', 'n3', 'n4']) { const g = generateWorld(s) const names = g.npcs.map((n) => n.name) expect(new Set(names).size).toBe(names.length) } }) it('初始关系网:世仇/盟友对存在且对称', () => { const g = generateWorld('wrel') expect(g.feuds.length).toBeGreaterThanOrEqual(1) expect(g.alliances.length).toBeGreaterThanOrEqual(1) for (const [a, b] of [...g.feuds, ...g.alliances]) { expect(g.relations[a]?.[b]).toBe(g.relations[b]?.[a]) expect(g.relations[a]?.[b]).toBeDefined() } }) it('开局时界(era 三态合法)与市场偏移存在', () => { const g = generateWorld('wera') expect(['shengshi', 'pingshi', 'luanshi']).toContain(g.eras) expect(Object.keys(g.marketOffset).length).toBe(9) }) it('世界创建即随机:同 seed 同势力、不同 seed 不同势力', () => { const w1 = World.create({ seed: 'now-1', surname: '钟', familyName: '钟家', motto: 'm', difficulty: 'normal' }) const w2 = World.create({ seed: 'now-1', surname: '钟', familyName: '钟家', motto: 'm', difficulty: 'normal' }) const w3 = World.create({ seed: 'now-2', surname: '钟', familyName: '钟家', motto: 'm', difficulty: 'normal' }) expect(Object.keys(w1.state.npcFamilies).join()).toBe(Object.keys(w2.state.npcFamilies).join()) expect(Object.keys(w1.state.npcFamilies).join()).not.toBe(Object.keys(w3.state.npcFamilies).join()) }) it('开局即恩怨:关系网入档并生效(首月快讯/大样)', () => { const w = World.create({ seed: 'now-3', surname: '钟', familyName: '钟家', motto: 'm', difficulty: 'normal' }) w.advanceMonth() const ws = w.state.worldSim as { npcDyn: Record }> } const first = Object.keys(w.state.npcFamilies)[0]! const rels = ws.npcDyn[first]?.relationsWithOthers ?? {} expect(Object.keys(rels).length).toBeGreaterThan(0) }) }) describe('0.1.25 P0:worldGen 存档稳固', () => { it('动态家族 def 落档:读档后 npcById 永命中(P0 修复)', async () => { let w: World | null = null for (const s of ['dg-1', 'dg-2', 'dg-3', 'dg-4', 'dg-5', 'dg-6']) { const t = World.create({ seed: s, surname: '钟', familyName: '钟家', motto: 'm', difficulty: 'normal' }) if (Object.keys(t.state.npcFamilies).some((k) => k.startsWith('n-g'))) { w = t; break } } if (!w) return // 都无动态家(seed 未抽中)→ 等价通过 const snap = JSON.parse(JSON.stringify(w.state)) const e2 = engineFromSnapshot(snap as never) const ids = Object.keys(e2.world.state.npcFamilies) for (const k of ids) { expect(npcById(k)).toBeTruthy() } }) })