Files
ChronicleOfTheImmortalClan/tests/rebuild-0.1.10.test.ts
T
thzxx ff6df8054c refactor(0.1.14-P1): 内核归位——game/ 按引擎架构重排(零行为漂移)
结构(旧 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
2026-08-23 13:23:25 +08:00

116 lines
4.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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')
})
})