import { describe, expect, it } from 'vitest' import { World } from '../src/renderer/game/engine/runtime/World' import { MAJOR_RATE } from '../src/renderer/game/data/pacing' import { marketPrice, buyItem, sellItem } from '../src/renderer/game/engine/sim/Market' function mk(seed: string): World { return World.create({ seed, surname: '钟', familyName: '钟家', motto: 'm', difficulty: 'normal' }) } describe('矩阵:增益守恒(板块×境界)', () => { it.each(Object.entries(MAJOR_RATE))('%s:MAJOR_RATE 值正', (major, rate) => { expect(rate).toBeGreaterThan(0) void major }) it('MAJOR_RATE 自 spirit 递减链成立', () => { const chain = ['qi', 'foundation', 'core', 'nascent', 'spirit'].map((m) => MAJOR_RATE[m as keyof typeof MAJOR_RATE]!) for (let i = 1; i < chain.length; i++) expect(chain[i]!).toBeLessThan(chain[i - 1]!) }) it.each([ ['采购-大额', 40], ['采购-小额', 4], ['抛售-足', 30] ] as const)('%s:市场回写守恒(买后价升卖后价降)', (label, count) => { const w = mk(`ms-${label}`) w.advanceMonth() w.state.family.stones = 999999 w.state.family.inventory['lingcao'] = 100 const ws = w.state.worldSim as { marketPool: Record } const pool0 = ws.marketPool['lingcao']! buyItem(w, 'lingcao', count) const pool1 = ws.marketPool['lingcao']! expect(pool1).toBeLessThan(pool0) sellItem(w, 'lingcao', count) const pool2 = ws.marketPool['lingcao']! expect(pool2).toBeGreaterThan(pool1) }) it.each([ ['炼丹', 'qiyuan'], ['炼丹', 'ningyuan'], ['武器', 'weapon-qi'] ] as const)('%s:craft/forge 增守恒——库存可增可减', (label, item) => { const w = mk(`cs-${label}`) const fam = w.state.family fam.inventory['lingcao'] = 999 fam.inventory['beastcore'] = 99 fam.inventory['lingkuang'] = 999 fam.stones = 99999 fam.buildings = { danfang: 5 } if (item === 'weapon-qi') { const ok = w.forgeArtifact(item) expect(typeof ok).toBe('boolean') } else { const ok = w.craftPill(item as never) expect(typeof ok).toBe('boolean') } }) }) describe('矩阵:终局路径', () => { it.each([ ['灭族'], ['飞升'], ['定鼎'], ['坐化'] ] as const)('%s:gameOver 状态可置且不抛', (label) => { const w = mk(`go-${label}`) w.state.gameOver = false w.advanceMonth() expect(typeof w.state.gameOver).toBe('boolean') }) it.each([ ['一'], ['二'], ['三'] ] as const)('生路 %s:50 年无覆灭也是合法人生', (label) => { const w = mk(`ok-${label}`) for (let i = 0; i < 600; i++) { if (w.state.gameOver) break w.advanceMonth() } expect(typeof w.state.family.reputation).toBe('number') }) })