结构(旧 game/core+engine → 新 engine/ 域): - engine/kernel/ 时钟/随机/插件协议/fxqueue/timesense/format/urgency/guide/names(原 core) - engine/narrative/ legacy/报告/列传/谱系/年轴(原 core 叙事族) - engine/runtime/ World/creation/pcgen/ApiFacade/capabilities/pluginManager/boot/clocks + Systems/*(12 系统) - engine/sim/ Market(未来 WorldSim 同行) - 旧 game/core、engine/systems、engine/world.ts 等路径全部废弃(无 re-export 兼容层) 验证:35 套件/967 测试全绿(金钟罩三档零漂移=纯搬迁无行为变化) typecheck 0 error
94 lines
3.5 KiB
TypeScript
94 lines
3.5 KiB
TypeScript
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)
|
||
})
|
||
})
|