Files
ChronicleOfTheImmortalClan/tests/echo.test.ts
T
thzxx 106db18017 v0.1.5: 人物志(志向/渡劫/列传/契合/回声)
- 志向系统:七向(求道/镇族/承宗/商略/兵略/耕读/云游)成年礼自动定志,
  量化加成入修炼/战力/坊市/灵田/添丁/声望,云游减修但际遇更频
- 大境界渡劫:炼气→筑基起,晋升改走劫难事件三选——硬渡/请护法(100灵石)/
  压制来年;护法失败或受牵连;渡劫成败与心性、气血挂勾,高阶有小陨落率
- 灵根本命契合:功法元素×主灵根,契合者修炼+6%/战力+4%,详情页「本命」徽章
- 人物列传:自动列传生成器(生平/修行脉络/历险/姻缘/子嗣/大比/墓志铭),
  成员详情小传分页 + 春秋原列传长卷
- 四邻回声:每两年一桩——友好赠礼/敌视暗桩/中立传闻三态动态事件
- 修复:回声事件 npcId 解析错误、事件优先级(惯例>传闻)
- 测试 176→197(志向加成/契合/渡劫三轨/压制通道/列传结构/回声三态)
2026-08-23 09:08:16 +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/world'
import { applyEventChoice, eventRoll } from '../src/renderer/game/engine/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()
})
})