import { describe, expect, it } from 'vitest' import { World } from '../src/renderer/game/engine/runtime/World' import { applyEventChoice } from '../src/renderer/game/engine/runtime/Systems/events' import { computeUrgency } from '../src/renderer/game/engine/kernel/urgency' import { monthlyRate } from '../src/renderer/game/engine/runtime/Systems/cultivation' import { resetSaveBus, attachLogSink } from './world.helpers' function baseWorld(seed: string): World { const w = World.create({ seed, surname: '凌', familyName: '凌家', motto: 'm', difficulty: 'normal' }) resetSaveBus() attachLogSink(w) return w } describe('0.1.11 审计修复回归', () => { it('大比 once:一季只触一次(不会整年刷 12 场)', () => { const w = baseWorld('tourn-once') w.state.year = 9 w.state.month = 12 w.advanceMonth() // year10 monthly const seen: string[] = [] for (let i = 0; i < 24; i++) { if (w.state.pendingEvent) { if (w.state.pendingEvent.startsWith('ev-tournament-')) seen.push(w.state.pendingEvent) applyEventChoice(w, w.state.pendingEvent, 0) w.state.pendingEvent = undefined } w.advanceMonth() } expect(seen.filter((x) => x === 'ev-tournament-10').length).toBe(1) }) it('飞升离世累加 feishengCount(可入飞升之资档)', () => { const w = baseWorld('fs-count') const c = w.state.members['x4'] c.realm = { major: 'spirit', minor: 1 } applyEventChoice(w, 'ev-feisheng', 1) // 云游 expect(w.state.stats.feishengCount).toBe(1) expect(w.state.family.flag['fengFeiBless']).toBe(true) }) it('圣者护族对幼童有效(hasPatriarch 消费)', () => { const w = baseWorld('patriarch') const c = w.state.members['x5'] c.bornYear = 1 // 1 岁 const elder = w.state.members['x4'] elder.bornYear = 1 - 70 elder.realm = { major: 'foundation', minor: 1 } const rate = monthlyRate(w, c) expect(rate).toBeGreaterThan(0) // 幼童本身速率低(<8 → ×0.65),此处只保证不为负 expect(rate).toBeGreaterThanOrEqual(0.1) }) it('年份 flag 3 年后清理(pruneYearFlags)', () => { const w = baseWorld('prune') w.state.year = 50 w.state.family.flag['auction-45'] = true w.state.family.flag['auction-49'] = true w.advanceMonth() expect(w.state.family.flag['auction-45']).toBeUndefined() expect(w.state.family.flag['auction-49']).toBe(true) }) it('急事徽章 derived 正确(无继承人/重伤/瓶颈)', () => { const w = baseWorld('urgent') // 无继承人:除 x2 都死 w.state.members['x1'].alive = false w.state.members['x3'].alive = false w.state.members['x5'].alive = false w.state.members['x4'].alive = false const u = computeUrgency(w) expect(u.noHeir).toBe(true) // 重伤 const w2 = baseWorld('urgent2') w2.state.members['x3'].health = 20 const u2 = computeUrgency(w2) expect(u2.injuredCount).toBeGreaterThanOrEqual(1) // 瓶颈 const w3 = baseWorld('urgent3') w3.state.members['x3'].realmProgress = 100 const u3 = computeUrgency(w3) expect(u3.blockedCount).toBeGreaterThanOrEqual(1) }) it('王座 dead 成员不再显示活动 state(标签层修复)', () => { const w = baseWorld('deadlabel') const c = w.state.members['x3'] c.alive = false // MemberCard 逻辑由 STATE_LABEL['dead'] 处理,引擎侧保证 alive=false 时 state 不变 expect(c.state === 'idle' || c.state === 'wounded' || c.state === 'meditation').toBe(true) }) })