Files
ChronicleOfTheImmortalClan/tests/era-world-0.1.18.test.ts
T
thzxx 2f62eecb08 v0.1.18: 时代绘卷 + 特效入引擎(双主线完成,1002 测试破千)
【主线一:世界自演进深化《时代绘卷》】
- 世纪弧 era 状态机:盛世/平世/乱世/末法四态(ERA_CONF 全参数化)。
  灾年概率×0.5~1.6、世界供需×0.7~1.25、拍卖概率×0.6~1.3、tide 偏置 ±0.09;
  ERA_DURA 控制转换节奏(15~45年),转移时史官快讯+log。世界有大节律了
- NPC 景气仓廪:npcDyn.prosperity(8~100)月结余——买卖+0.5~0.8、断供-2、灾年-3;
  >75 景气 power+1、<30 衰闷 power-1;换代焕新(55~75)。NPC 在过日子
- 蝴蝶效应:互攻胜率 power 加权(强者恒强)、打残广播(败家邻望-8/胜家+4);
  玩家劫掠胜利/结盟直接写 NPC·NPC 关系网(-6/-3)——玩家行动推进世界历史
- 天下十年一鉴:每十年史官综述(灾/换代/行情/灵潮聚合,kind='annal')
- 灾年↔秘境:灾年灵脉恢复减半(末法感)
- WorldPanel 天下志:era 徽标(悬停描述)/史官十年鉴/群雄势衡柱状图/衰微标注

【主线二:特效系统并入引擎(架构升级)】
- WorldEventBus.onFx + Kernel 转发 + World.emitFx 语义发射(零 rng 消耗)
- 12 个语义发射点:突破/化神/渡劫/劫掠胜负/遭遇战/拍卖/大比/灾年起散/换代
  —— 取代 UI log 文本正则猜测(spark/blade 双源锁死)
- makeBus 桥接 FxGate(kind→gate.emit),gate 挡位/密度/reduced 逻辑保留在 UI

【测试】1002 全绿(40 套件):fxqueue-semantic 3 例 + era-world 5 例;
金钟罩 0.1.18 基线固化(era/prosperity/蝴蝶效应受控变更)
2026-08-23 14:38:27 +08:00

65 lines
2.9 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 { ERA_CONF, WorldSimState } from '../src/renderer/game/engine/sim/worldsim-data'
import { combatPowerOf } from '../src/renderer/game/engine/runtime/Systems/combat'
describe('0.1.18 时代绘卷', () => {
it('世纪弧状态机恒定在四态内且会转移', () => {
const w = World.create({ seed: 'era-1', surname: '姜', familyName: '姜家', motto: 'm', difficulty: 'normal' })
let seen = new Set<string>()
let lastEra = ''
for (let i = 0; i < 2400; i++) {
if (w.state.gameOver) break
w.advanceMonth()
const ws = w.state.worldSim as WorldSimState
const e = ws.era ?? 'pingshi'
expect(Object.keys(ERA_CONF)).toContain(e)
if (e !== lastEra) {
seen.add(e)
lastEra = e
}
}
expect(seen.size).toBeGreaterThanOrEqual(2) // 200 年内至少转移过一次
})
it('NPC 景气存在且随断供/灾年受挫(值域 8~100)', () => {
const w = World.create({ seed: 'era-2', surname: '路', familyName: '路家', motto: 'm', difficulty: 'normal' })
for (let i = 0; i < 600; i++) w.advanceMonth()
const dyns = (w.state.worldSim as WorldSimState).npcDyn
for (const d of Object.values(dyns)) {
expect(d.prosperity).toBeGreaterThanOrEqual(8)
expect(d.prosperity).toBeLessThanOrEqual(100)
}
})
it('十年鉴每十年一条史官快讯', () => {
const w = World.create({ seed: 'era-3', surname: '柴', familyName: '柴家', motto: 'm', difficulty: 'normal' })
for (let i = 0; i < 1200; i++) w.advanceMonth()
const news = (w.state.worldSim as WorldSimState).newsFeed
const annals = news.filter((r) => r.kind === 'annal')
expect(annals.length).toBeGreaterThanOrEqual(3)
expect(annals[0]!.text).toContain('史官')
})
it('玩家战力排位随局势变化(群雄谱输入有效)', () => {
const w = World.create({ seed: 'era-4', surname: '宋', familyName: '宋家', motto: 'm', difficulty: 'normal' })
for (let i = 0; i < 120; i++) w.advanceMonth()
const myPower = w.aliveMembers().reduce((a, c) => a + combatPowerOf(w, c), 0)
expect(myPower).toBeGreaterThan(0)
})
it('灾年时秘境恢复减半(灵脉闭锁)', () => {
const w = World.create({ seed: 'era-5', surname: '吕', familyName: '吕家', motto: 'm', difficulty: 'normal' })
w.advanceMonth() // 先实例化 worldSimsecretQi 各处 50
const ws = w.state.worldSim as WorldSimState
if (!ws) throw new Error('worldSim 未初始化')
// 钉死灾年后观察恢复量(此时灵气从 50 起,减值格 >70 规则不触发)
ws.calamity = '旱灾'
ws.calamityLeft = 3
const before = ws.secretQi['m-anmoku'] ?? 50
w.advanceMonth()
const after = (w.state.worldSim as WorldSimState).secretQi['m-anmoku'] ?? 0
expect(after - before).toBeLessThanOrEqual(3) // 灾年恢复 0.5x=1~2.5 上限
})
})