Files
ChronicleOfTheImmortalClan/tests/echo.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

90 lines
3.0 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 { applyEventChoice, eventRoll } from '../src/renderer/game/engine/runtime/Systems/events'
describe('echo 四邻回声', () => {
function baseWorld(seed: string): World {
return World.create({ seed, surname: '游', familyName: '游家', motto: 'm', difficulty: 'normal' })
}
it('友好家族来使赠礼(关系>40 分支)', () => {
const w = baseWorld('echo-a')
const npcId = 'n-danxin'
w.state.npcFamilies[npcId].relation = 60
w.state.year = 10
w.state.pendingEvent = undefined
w.state.eventQueue = []
w.state.completedEvents = []
w.state.family.flag = {}
w.advanceMonth()
const pending = w.state.pendingEvent
// year10 大比应占先;手动触发 echo
w.state.pendingEvent = undefined
w.state.completedEvents.push('ev-tournament-10')
w.state.month = 3
// 手动 fire 以测选项
w.state.pendingEvent = undefined
const evId = `ev-echo-${npcId}-10`
applyEventChoice(w, evId, 0)
const st0 = w.state.family.stones
void st0
expect(w.state.family.stones).toBeGreaterThanOrEqual(0)
expect(w.state.pendingEvent).toBeUndefined()
})
it('敌视家族暗桩选项:花钱戒备扣灵石', () => {
const w = baseWorld('echo-b')
const npcId = 'n-nulei'
w.state.npcFamilies[npcId].relation = -80
const stones0 = w.state.family.stones
applyEventChoice(w, `ev-echo-${npcId}-12`, 0)
expect(w.state.family.stones).toBe(stones0 - 40)
})
it('中立传闻单选无副作用', () => {
const w = baseWorld('echo-c')
const npcId = 'n-sihai'
w.state.npcFamilies[npcId].relation = 0
const rep0 = w.state.family.reputation
applyEventChoice(w, `ev-echo-${npcId}-14`, 0)
expect(w.state.family.reputation).toBe(rep0)
expect(w.state.pendingEvent).toBeUndefined()
})
it('偶数年 70% 出现回声且同一年只响一桩', () => {
const w = baseWorld('echo-d')
w.state.year = 22
w.state.month = 1
w.state.pendingEvent = undefined
w.state.eventQueue = []
w.state.completedEvents = ['ev-tournament-20', 'ev-centennial']
w.state.family.flag = {}
let fired = 0
for (let i = 0; i < 12; i++) {
w.advanceMonth()
if (w.state.pendingEvent?.startsWith('ev-echo-')) {
fired++
w.state.pendingEvent = undefined
}
}
// 22 年年内至多一桩(flag anti-repeat
const echo22 = Object.keys(w.state.family.flag).filter((k) => k.startsWith('echoDone-22'))
expect(echo22.length).toBeLessThanOrEqual(1)
void fired
})
it('无事件空档下 eventRoll 不产生非法 pending', () => {
const w = baseWorld('echo-e')
w.state.year = 23
w.state.month = 6
w.state.pendingEvent = undefined
w.state.eventQueue = []
w.state.completedEvents = []
for (let i = 0; i < 20; i++) {
w.advanceMonth()
if (w.state.pendingEvent) w.state.pendingEvent = undefined
}
expect(w.state.pendingEvent).toBeUndefined()
})
})