v0.1.19: 八方风雨 + 孤立系统归并(双主线,1002 全绿)
【主线一:世界自演进深化《八方风雨》】 - NPC 战略姿态 stance:守成/扩张/隐忍/结盟四态,年首评估(era>景气>power>relation) 全行为调制:raid 概率×2/×0.4/×0、互攻阈值 -40/-70/不攻、贸量 ×1.3/×0.7、 赠礼收益 ally×1.3、结盟门槛 ally 放宽至30——NPC 从统计物理到行为战略 - 超卖潮(谷贱伤农):池>1.8×base 世界产能回调×0.7 + 年度播报(防玩家玩崩市场) - 盟约连坐:结盟令世仇(rel<-50)对玩家-20;盟者世仇 raid 概率×2 - 盟友求援:互攻失利盟友告急(distress 旗标)——WorldPanel 响应(出资200/见死不救) - 干预天下:调停(50灵石令世仇-60→-25、声望+2)/ 资助盟友;恩怨网情报视图(各家关系展开+调停钮) 【主线二:孤立系统归并引擎】 - P0 兜底修复:empty() 收敛 makeWorldSimState 单源 + normalize 补 tideTicks/calamityLeft/ era/eraStartYear/prosperity/distress/overfluxYear(旧档 NaN 级联防死) - FxGate 从 engine/kernel/fxqueue.ts 并入 ui/fx.ts(kernel 清纯引擎;deltas 顶层导出, 3 处引用 10 行改动);engine 侧零 UI 依赖再下一城 - 音效语义补充:onFx→blade/pulse/spark→sWar/sGong/sBell;onLog kind 兜底保留(不静音) - store.advance drift/season 段左移 fx.ts(fxSeason 复活接管 season 检测) - 死码清除:timesense.tideOf/tintLabel、tideDir 全链(类型/初始/写入/domain) - domain.ts worldSim 局部类型补全 0.1.18/0.1.19 全部新字段(断言类型安全) 【测试】1002 全绿(41 套件):stance-world 7 例(兜底/姿态/raid/超卖/连坐/调停/求援)
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { World } from '../src/renderer/game/engine/runtime/World'
|
||||
import { normalizeGameState } from '../src/renderer/game/engine/runtime/World'
|
||||
import { WorldSimState } from '../src/renderer/game/engine/sim/worldsim-data'
|
||||
|
||||
describe('0.1.19 八方风雨', () => {
|
||||
it('兜底:空 worldSim 的旧档 normalize 后 tideTicks 有值(P0 修复)', () => {
|
||||
const w = World.create({ seed: 'p0-1', surname: '甯', familyName: '甯家', motto: 'm', difficulty: 'normal' })
|
||||
const state = w.state as never
|
||||
const fixed = normalizeGameState({
|
||||
...(state as Record<string, unknown>),
|
||||
worldSim: { marketPool: {}, npcDyn: {}, secretQi: {}, newsFeed: [] }
|
||||
} as never) as { worldSim: { tideTicks: number; era: string; calamityLeft: number } }
|
||||
expect(fixed.worldSim.tideTicks).toBe(0)
|
||||
expect(fixed.worldSim.era).toBe('pingshi')
|
||||
expect(fixed.worldSim.calamityLeft).toBe(0)
|
||||
})
|
||||
|
||||
it('stance:四姿态值域 + 年首(约8年)可再评估', () => {
|
||||
const w = World.create({ seed: 'st-1', surname: '冀', familyName: '冀家', motto: 'm', difficulty: 'normal' })
|
||||
const seen = new Set<string>()
|
||||
for (let i = 0; i < 1600; i++) {
|
||||
if (w.state.gameOver) break
|
||||
w.advanceMonth()
|
||||
const dyns = (w.state.worldSim as WorldSimState).npcDyn
|
||||
for (const d of Object.values(dyns)) {
|
||||
expect(['guardian', 'expand', 'endure', 'ally']).toContain(d.stance ?? 'guardian')
|
||||
if (d.stance) seen.add(d.stance)
|
||||
}
|
||||
}
|
||||
expect(seen.size).toBeGreaterThanOrEqual(2)
|
||||
})
|
||||
|
||||
it('姿态影响 raid 概率标尺(expand 双倍、endure 打折)', () => {
|
||||
const w = World.create({ seed: 'st-2', surname: '邱', familyName: '邱家', motto: 'm', difficulty: 'normal' })
|
||||
w.advanceMonth()
|
||||
const dyns = w.state.worldSim as WorldSimState
|
||||
dyns.npcDyn['n-nulei'] = { ...dyns.npcDyn['n-nulei']!, stance: 'expand', stanceSinceYear: 1 }
|
||||
// 关系拉到仇深 + 伪造 raidCD 前一年,跑 240 月计数
|
||||
const npc = w.state.npcFamilies['n-nulei']
|
||||
npc.relation = -70
|
||||
npc.allied = false
|
||||
let evcount = 0
|
||||
for (let i = 0; i < 600; i++) {
|
||||
npc.relation = -70 // 钉死(diplomacy drift 会拉回)
|
||||
dyns.npcDyn['n-nulei'] = { ...dyns.npcDyn['n-nulei'], stance: 'expand', stanceSinceYear: w.state.year }
|
||||
w.advanceMonth()
|
||||
// 任何 pending 顶住事件闸则先清场(否则后续 raid 无法 fire)
|
||||
while (w.state.pendingEvent) {
|
||||
if (w.state.pendingEvent.startsWith('ev-raid-')) evcount++
|
||||
w.applyEventChoice(w.state.pendingEvent, 0)
|
||||
}
|
||||
}
|
||||
// 0.06×12月×10年 ≈ 7 次期待,≥1 稳
|
||||
expect(evcount).toBeGreaterThanOrEqual(1)
|
||||
})
|
||||
|
||||
it('超卖潮:库存过剩时世界产能乘0.7回调且播报一次/年', () => {
|
||||
const w = World.create({ seed: 'st-3', surname: '盛', familyName: '盛家', motto: 'm', difficulty: 'normal' })
|
||||
w.advanceMonth()
|
||||
const ws = w.state.worldSim as WorldSimState
|
||||
ws.marketPool['lingcao'] = 2000 // 远超 600*1.8
|
||||
const before = ws.marketPool['lingcao']
|
||||
w.advanceMonth()
|
||||
const after = ws.marketPool['lingcao']
|
||||
expect(after).toBeLessThan(before)
|
||||
expect(ws.newsFeed.some((r) => r.text.includes('谷贱伤农'))).toBe(true)
|
||||
})
|
||||
|
||||
it('结盟连坐:世仇得闻而暗恨(玩家关系-20)', () => {
|
||||
const w = World.create({ seed: 'st-4', surname: '方', familyName: '方家', motto: 'm', difficulty: 'normal' })
|
||||
w.advanceMonth()
|
||||
const dyns = w.state.worldSim as WorldSimState
|
||||
dyns.npcDyn['n-xuanying']!.relationsWithOthers['n-nulei'] = -70
|
||||
w.state.npcFamilies['n-xuanying'].relation = 60
|
||||
const before = w.state.npcFamilies['n-nulei'].relation
|
||||
expect(w.setAlliance('n-xuanying', true)).toBe(true)
|
||||
expect(w.state.npcFamilies['n-nulei'].relation).toBeLessThan(before)
|
||||
})
|
||||
|
||||
it('调停:花50灵石令世仇回暖、声望+2', () => {
|
||||
const w = World.create({ seed: 'st-5', surname: '凌', familyName: '凌家', motto: 'm', difficulty: 'normal' })
|
||||
w.advanceMonth()
|
||||
const dyns = w.state.worldSim as WorldSimState
|
||||
dyns.npcDyn['n-danxin']!.relationsWithOthers['n-sihai'] = -60
|
||||
w.state.family.stones = 500
|
||||
const r0 = dyns.npcDyn['n-danxin']!.relationsWithOthers['n-sihai']
|
||||
expect(w.mediateNpcs('n-danxin', 'n-sihai')).toBe(true)
|
||||
const r1 = dyns.npcDyn['n-danxin']!.relationsWithOthers['n-sihai']
|
||||
expect(r1).toBeGreaterThan(r0)
|
||||
expect(w.state.family.reputation).toBeGreaterThanOrEqual(2)
|
||||
})
|
||||
|
||||
it('盟友求援:互攻失利盟友告急 → assistAlly 可应', () => {
|
||||
const w = World.create({ seed: 'st-6', surname: '古', familyName: '古家', motto: 'm', difficulty: 'normal' })
|
||||
w.advanceMonth()
|
||||
const ws = w.state.worldSim as WorldSimState
|
||||
ws.npcDyn['n-xuanying']!.relationsWithOthers['n-nulei'] = -80
|
||||
ws.npcDyn['n-nulei']!.relationsWithOthers['n-xuanying'] = -80
|
||||
w.state.npcFamilies['n-xuanying'].allied = true
|
||||
w.state.family.stones = 1000
|
||||
// 手动挂求援(互攻触发具随机性,此处测响应链)
|
||||
ws.distress = { id: 'n-xuanying', year: w.state.year, month: w.state.month }
|
||||
const p0 = w.state.npcFamilies['n-xuanying'].power
|
||||
expect(w.assistAlly('n-xuanying')).toBe(true)
|
||||
expect(w.state.npcFamilies['n-xuanying'].power).toBeGreaterThan(p0)
|
||||
expect(ws.distress).toBeUndefined()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user