结构(旧 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
116 lines
4.4 KiB
TypeScript
116 lines
4.4 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
||
import { World } from '../src/renderer/game/engine/runtime/World'
|
||
import { monthlyRate } from '../src/renderer/game/engine/runtime/Systems/cultivation'
|
||
import { MAJORS } from '../src/renderer/game/data/realms'
|
||
import { applyEventChoice } from '../src/renderer/game/engine/runtime/Systems/events'
|
||
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.10 数值重建验收', () => {
|
||
it('修炼速率比 0.1.9 基线快(感知7 qi 期 ≥1.5/月)', () => {
|
||
const w = baseWorld('pace-a')
|
||
const c = w.state.members['x5']
|
||
c.realm = { major: 'qi', minor: 0 }
|
||
c.perception = 7
|
||
c.roots = { grade: 3, primary: '火', secondary: [] }
|
||
c.techniqueId = undefined
|
||
const r = monthlyRate(w, c)
|
||
expect(r).toBeGreaterThanOrEqual(1.5)
|
||
})
|
||
|
||
it('qi 层间累计修为窗口 < 30 年(感知7+凡品+无功法)', () => {
|
||
const w = baseWorld('pace-b')
|
||
const c = w.state.members['x5']
|
||
c.realm = { major: 'qi', minor: 0 }
|
||
c.perception = 7
|
||
c.roots = { grade: 2, primary: '火', secondary: [] }
|
||
c.state = 'idle'
|
||
const r = monthlyRate(w, c)
|
||
// 9 层总月数 = 100/r × 9(近似)
|
||
const months = (100 / r) * 9
|
||
expect(months).toBeLessThan(30 * 12)
|
||
})
|
||
|
||
it('寿元梯度放宽:凡人75 → 化神850', () => {
|
||
expect(MAJORS['mortal'].lifespan).toBe(75)
|
||
expect(MAJORS['qi'].lifespan).toBe(150)
|
||
expect(MAJORS['foundation'].lifespan).toBe(220)
|
||
expect(MAJORS['core'].lifespan).toBe(340)
|
||
expect(MAJORS['nascent'].lifespan).toBe(520)
|
||
expect(MAJORS['spirit'].lifespan).toBe(850)
|
||
})
|
||
|
||
it('小层突破失败跌损收窄(26-44%而非40-65%)', () => {
|
||
const w = baseWorld('pace-c')
|
||
const c = w.state.members['x3']
|
||
c.realm = { major: 'qi', minor: 1 }
|
||
// 多次失败模拟,跌损应明显小于旧值:检查 resolveBreakthrough 失败后的 progress ≥ 55%
|
||
// 直接构造必失败环境(心性/健康低)
|
||
c.realmProgress = 100
|
||
c.health = 100
|
||
c.mind = 1
|
||
c.traits = ['jizao'] // 急躁加大失败伤害
|
||
resolveBreakthrough(w, c, -0.4)
|
||
if (c.realm.minor === 1) {
|
||
// 若失败在层内,跌损后应 ≥ 45%(旧 40-65 可能到 35%)
|
||
expect(c.realmProgress).toBeGreaterThanOrEqual(45)
|
||
}
|
||
})
|
||
|
||
it('渡劫成功率上调(筑基期望>0.5)', () => {
|
||
const w = baseWorld('trib-rate')
|
||
const c = w.state.members['x5']
|
||
c.realm = { major: 'qi', minor: 8 }
|
||
c.mind = 6
|
||
c.health = 100
|
||
expect(perTribChance(w, c)).toBeGreaterThan(0.5)
|
||
})
|
||
})
|
||
|
||
import { resolveBreakthrough } from '../src/renderer/game/engine/runtime/Systems/cultivation'
|
||
import { perTribChance } from '../src/renderer/game/engine/runtime/Systems/tribulation'
|
||
|
||
describe('事件悬置与周期(0.1.10)', () => {
|
||
it('大比征召 FIFO 不被拍卖/传薪挤掉(20 年三年都触发)', () => {
|
||
const w = World.create({ seed: 'tourney-q', surname: '龚', familyName: '龚家', motto: 'm', difficulty: 'normal' })
|
||
resetSaveBus()
|
||
attachLogSink(w)
|
||
const seen: string[] = []
|
||
w.out.push({
|
||
onLog: () => undefined,
|
||
onChronicle: () => undefined,
|
||
onBattle: () => undefined,
|
||
onPendingEvent: (id) => { if (id.startsWith('ev-tournament-')) seen.push(id) },
|
||
onGameOver: () => undefined
|
||
})
|
||
for (let i = 0; i < 20 * 12; i++) {
|
||
if (w.state.pendingEvent) { applyEventChoice(w, w.state.pendingEvent, 0); w.state.pendingEvent = undefined }
|
||
w.advanceMonth()
|
||
}
|
||
expect(seen).toContain('ev-tournament-10')
|
||
expect(seen).toContain('ev-tournament-15')
|
||
expect(seen).toContain('ev-tournament-20')
|
||
})
|
||
|
||
it('渡劫玩家处理能晋升(qi8→筑基)', () => {
|
||
const w = World.create({ seed: 'trib-jump', surname: '桑', familyName: '桑家', motto: 'm', difficulty: 'normal' })
|
||
const c = w.state.members['x5']
|
||
c.realm = { major: 'qi', minor: 8 }
|
||
c.realmProgress = 100
|
||
c.mind = 9
|
||
c.perception = 9
|
||
for (let i = 0; i < 60; i++) {
|
||
if (w.state.pendingEvent) { applyEventChoice(w, w.state.pendingEvent, 0); w.state.pendingEvent = undefined }
|
||
w.advanceMonth()
|
||
if (c.realm.major === 'foundation') break
|
||
}
|
||
expect(c.realm.major).toBe('foundation')
|
||
})
|
||
})
|