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('矩阵:月度不变量(8 seed × 18 月)', () => { it.each(Array.from({ length: 8 }, (_, i) => [i * 29 + 5] as const))( 'seed %d:18 月连续推进恒定不变量', (seed) => { const w = mk(`law-${seed}`) for (let i = 0; i < 18; i++) { w.advanceMonth() expect(w.state.month).toBeGreaterThanOrEqual(1) expect(w.state.month).toBeLessThanOrEqual(12) expect(Number.isFinite(w.state.family.stones)).toBe(true) expect(w.state.family.stones).toBeGreaterThanOrEqual(0) expect(Number.isFinite(w.state.seq)).toBe(true) expect(w.state.year).toBeGreaterThan(0) for (const v of Object.values(w.state.family.inventory)) { expect(Number.isFinite(v)).toBe(true) expect(v).toBeGreaterThanOrEqual(0) } } }) it.each(Array.from({ length: 8 }, (_, i) => [i * 13 + 2] as const))( 'seed %d:年度报告逐年生(year≥2 且 reports 增)', (seed) => { const w = mk(`yr-${seed}`) const before = w.state.yearlyReports.length for (let i = 0; i < 30; i++) w.advanceMonth() expect(w.state.yearlyReports.length).toBeGreaterThanOrEqual(before) if (w.state.yearlyReports.length > 0) { const last = w.state.yearlyReports.slice(-1)[0]! expect(typeof last.year).toBe('number') expect(typeof last.rep).toBe('number') } }) it.each(Array.from({ length: 10 }, (_, i) => [i + 1] as const))( '成员 x%d:为期 30 月的状态健康', (idx) => { const w = mk(`mb-${idx}`) for (let i = 0; i < 30; i++) w.advanceMonth() const c = w.state.members[`x${idx}`] if (c) { expect(c.alive === true || c.alive === false).toBe(true) expect(typeof c.realmProgress).toBe('number') expect(c.realmProgress).toBeGreaterThanOrEqual(0) expect(c.realmProgress).toBeLessThanOrEqual(100) } }) it.each(Array.from({ length: 6 }, (_, i) => [i * 7 + 4] as const))( 'seed %d:60 月后编年史/战报/日志三类载体并存', (seed) => { const w = mk(`cr-${seed}`) for (let i = 0; i < 60; i++) w.advanceMonth() expect(Array.isArray(w.state.chronicle)).toBe(true) expect(Array.isArray(w.state.battles)).toBe(true) expect(Array.isArray(w.state.missions)).toBe(true) expect(w.state.chronicle.filter((e) => e.category === 'breakthrough').length >= 0).toBe(true) }) it.each([ ['周流'], ['月次'], ['岁暮'], ['世更'], ['道兴'] ] as const)('%s:五载生存冒烟(120 月连续)', (label) => { const w = mk(`ls-${label}`) for (let i = 0; i < 120; i++) { if (w.state.gameOver) break w.advanceMonth() } expect(w.state.year).toBeGreaterThanOrEqual(9) }) it.each([ ['一'], ['二'], ['三'], ['四'], ['五'], ['六'] ] as const)('长路 %s:50 年未见确定性破损(年/月/蓄/纪年皆有限)', (label) => { const w = mk(`ll-${label}`) let guards = 0 for (let i = 0; i < 600 && !w.state.gameOver; i++) { w.advanceMonth() let g = 0 while (w.state.pendingEvent && g < 4) { w.applyEventChoice(w.state.pendingEvent, 0); g++; guards++ } } void guards expect(Number.isFinite(w.state.year)).toBe(true) expect(Number.isFinite(w.state.family.reputation)).toBe(true) expect(Array.isArray(w.state.completedEvents)).toBe(true) }) })