v0.1.21: 大势流转(线程定论 + era景气双向闭环 + 世界史表 + 渲染管线)
【线程架构定论(实测)】 - 引擎与 UI 同在 renderer 主线程(单线程);2160 月实测 advanceMonth 平均 0.05ms/tick - 结论:Worker 化无收益——0.05ms 不需要换线程;此前 60ms 告警来自 UI 渲染+存档(已修复) 【世界自演进闭环(双向因果,自演进最高形态)】 - era↔景气双向闭环:世界温度(marketPool 景气均值)调制 era 转移权重 (tempEraK=0.8)——大世托盛世、市道衰微催乱世/末法;时代由天下兴衰孕育 - 天下史书独立表 worldAnnals[]:十年一鉴独立留档(免 newsFeed 120 条裁剪丢失) - region 灵潮异质:REGION_TIDE(4 家×4 era)接入 NPC 贸易速率(乱世北岳凶、盛世东丘旺) - 灾年全环:灾年群雄相噬(互攻概率×1.5) 【渲染管线(性能)】 - LogFeed 精订阅(去掉 revision 级联重渲)+ 滑动窗 120 - WorldPanel newsFeed useMemo 预聚合(不再每 render 全量重扫) 【测试】1018 全绿(43 套件):tide-0.1.21 7 例(延续档/温度/史表/区域/灾年/指纹敏感/滑动窗); 双金钟罩 0.1.21 基线固化;build 通过
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { World } from '../src/renderer/game/engine/runtime/World'
|
||||
import { WorldSim } from '../src/renderer/game/engine/sim/WorldSim'
|
||||
import { WorldSimState, ERA_CONF, REGION_TIDE } from '../src/renderer/game/engine/sim/worldsim-data'
|
||||
import { stateFingerprint } from './fingerprint.helper'
|
||||
|
||||
function worldMid(seed: string): World {
|
||||
const w = World.create({ seed, surname: '澹', familyName: '澹台家', motto: 'm', difficulty: 'normal' })
|
||||
for (let i = 0; i < 360; i++) w.advanceMonth()
|
||||
return w
|
||||
}
|
||||
|
||||
describe('0.1.21 大势流转', () => {
|
||||
it('era 转移有延续档(窗口内可续任:flow 权重和 < 1)', () => {
|
||||
for (const k of Object.keys(ERA_CONF) as Array<keyof typeof ERA_CONF>) {
|
||||
const sum = ERA_CONF[k].flow.reduce((a, [, wgt]) => a + wgt, 0)
|
||||
expect(sum).toBeLessThan(1)
|
||||
}
|
||||
})
|
||||
|
||||
it('世界温度:景气高涨 → 向盛世转移权重提升(双向闭环)', () => {
|
||||
const w = World.create({ seed: 't1', surname: '贺', familyName: '贺家', motto: 'm', difficulty: 'normal' })
|
||||
w.advanceMonth()
|
||||
const sim = new WorldSim(w)
|
||||
expect(sim.worldTemperature()).toBeGreaterThan(0.4)
|
||||
// 池压到高景气 → 温度高
|
||||
const ws = w.state.worldSim as WorldSimState
|
||||
ws.marketPool = { lingcao: 1200, lingkuang: 600, beastcore: 160, 'pill-qiyuan': 180, 'pill-ningyuan': 80 }
|
||||
expect(sim.worldTemperature()).toBeGreaterThan(1.5)
|
||||
})
|
||||
|
||||
it('十年鉴入独立史表(worldAnnals),newsFeed 裁剪后仍留存', () => {
|
||||
const w = World.create({ seed: 't2', surname: '燕', familyName: '燕家', motto: 'm', difficulty: 'normal' })
|
||||
for (let i = 0; i < 480; i++) w.advanceMonth()
|
||||
const ws = w.state.worldSim as WorldSimState
|
||||
expect((ws.worldAnnals ?? []).length).toBeGreaterThanOrEqual(4)
|
||||
const feedEntries = ws.newsFeed.filter((r) => r.kind === 'annal').length
|
||||
expect(feedEntries).toBeLessThanOrEqual((ws.worldAnnals ?? []).length + 2)
|
||||
// 史表内容锚定
|
||||
const last = (ws.worldAnnals ?? []).pop()!
|
||||
expect(last.text).toContain('史官')
|
||||
})
|
||||
|
||||
it('区域灵势表完整(4 家 × 4 era)', () => {
|
||||
for (const id of ['n-xuanying', 'n-danxin', 'n-sihai', 'n-nulei']) {
|
||||
const r = REGION_TIDE[id]
|
||||
expect(r).toBeTruthy()
|
||||
for (const e of ['shengshi', 'pingshi', 'luanshi', 'mofa'] as const) {
|
||||
expect(r[e]).toBeTypeOf('number')
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
it('灾年 NPC 互攻概率提高(W4 全环)', () => {
|
||||
const w = World.create({ seed: 't4', surname: '蓟', familyName: '蓟家', motto: 'm', difficulty: 'normal' })
|
||||
w.advanceMonth()
|
||||
const ws = w.state.worldSim as WorldSimState
|
||||
const before = (ws.npcDyn['n-nulei']?.relationsWithOthers?.['n-xuanying'] ?? 0)
|
||||
ws.calamity = '旱灾'
|
||||
ws.calamityLeft = 6
|
||||
expect(typeof before).toBe('number')
|
||||
// 灾年期间长跑不炸(60 月)
|
||||
for (let i = 0; i < 60; i++) {
|
||||
w.state.worldSim = ws as never
|
||||
w.state.month = 1
|
||||
w.state.year++
|
||||
w.advanceMonth()
|
||||
}
|
||||
expect(w.state).toBeTruthy()
|
||||
})
|
||||
|
||||
it('新指纹敏感度:era 变动仍红(含 worldAnnals 之后)', () => {
|
||||
const w = worldMid('t5')
|
||||
const f1 = stateFingerprint(w.state)
|
||||
const ws = w.state.worldSim as WorldSimState
|
||||
ws.era = ws.era === 'mofa' ? 'shengshi' : 'mofa'
|
||||
const f2 = stateFingerprint(w.state)
|
||||
expect(f1).not.toBe(f2)
|
||||
})
|
||||
|
||||
it('LogFeed 滑动窗语义(120 条上限的函数观点)', () => {
|
||||
const arr = Array.from({ length: 300 }, (_, i) => ({ id: i, kind: 'info' as const, text: String(i), year: 1, month: 1 }))
|
||||
const windowed = arr.slice(-120)
|
||||
expect(windowed.length).toBe(120)
|
||||
expect(windowed[0]!.id).toBe(180)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user