Files
ChronicleOfTheImmortalClan/tests/gameengine.test.ts
T
thzxx 9571c58c07 version: 0.1.35→0.1.36——补齐版本流程(0.1.36a 修复已存在,版本未升是我的疏漏)
package.json/ApiFacade/SettingsPanel/storeHelper/slots(GAME_VERSION)/facade-registry/gameengine 断言 6 处同步;
AGENTS 版本头同步(三问题处置状态诚实口径):弹框双排名已修,推进/白屏根因待真实环境错文;
build 绿 7007 测试绿
2026-08-24 22:11:45 +08:00

138 lines
5.1 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 { GameEngine } from '../src/renderer/game/engine/GameEngine'
import { makeKernel } from '../src/renderer/game/engine/kernel/Kernel'
import { WorldSim } from '../src/renderer/game/engine/sim/WorldSim'
import { WORLDSIM } from '../src/renderer/game/engine/sim/worldsim-data'
describe('GameEngine 引擎门面', () => {
it('构造:内核注入世界 + 门面 + 数据包', () => {
const e = new GameEngine({ seed: 'engine-1' })
expect(e.world).toBeTruthy()
expect(e.facade).toBeTruthy()
expect(e.kernel.clock.subscriptionCount()).toBeGreaterThanOrEqual(10)
expect(e.status()).toBe('running')
})
it('advance 驱动内核时钟(确定单源)', () => {
const e = new GameEngine({ seed: 'engine-2' })
const y0 = e.view().year
const m0 = e.view().month
e.advance()
const crossed = e.view().month === 1 && e.view().year === y0 + 1
const normal = e.view().month === m0 + 1
expect(crossed || normal).toBe(true)
})
it('act/query/subscribe 全链路', () => {
const e = new GameEngine({ seed: 'engine-3' })
const events: string[] = []
const unsub = e.subscribe((ev) => events.push(ev.type))
expect(e.act('member.post', { memberId: 'x3', post: 'elder' })).toBe(true)
e.advance()
// 一次 advance 必然产生内核事件流(log/pending/paper 至少其一)
expect(events.length).toBeGreaterThan(0)
unsub()
const fam = e.query('family') as { year: number }
expect(fam.year).toBeGreaterThanOrEqual(1)
})
it('datapack 覆写生效 + restore 可回放', () => {
const e = new GameEngine({ seed: 'engine-4' })
e.datapack.override({
items: { ...e.datapack.current().items, lingcao: { ...e.datapack.current().items['lingcao'], basePrice: 250 } }
})
const snap = e.snapshot()
expect(snap.family.stones).toBeGreaterThanOrEqual(0)
e.restore(snap)
expect(e.status()).toBe('running')
})
it('about 元数据含 plugins(≥3)与版本透传', () => {
const e = new GameEngine({ seed: 'engine-5' })
const a = e.about()
expect(a.plugins).toBeGreaterThanOrEqual(3)
expect(a.version).toContain('0.1.36')
})
})
describe('Kernel 三合一', () => {
it('时钟/随机协同(同 seed 同随机序列);bus 已并入 World.out', () => {
const k1 = makeKernel('kernel-a')
const k2 = makeKernel('kernel-a')
expect(k1.rng.next()).toBe(k2.rng.next())
expect(k1.clock).toBeTruthy()
expect((k1 as unknown as { bus?: unknown }).bus).toBeUndefined()
})
})
function runEngine(e: GameEngine, months: number): void {
for (let i = 0; i < months; i++) {
if (e.view().gameOver) break
e.advance()
// 引擎语义:遇到待决事件停下来等处理;自动化直接取第一个选项继续
let guard = 0
while (e.view().pendingEvent && guard < 4) {
e.resolvePending(0)
guard++
}
}
}
describe('WorldSim 世界健康(长跑)', () => {
it.each(['ws-1', 'ws-2', 'ws-3'].map((s) => [s] as const))('%s:1000 月市场池/灵气在界、世界不崩', (seed) => {
const e = new GameEngine({ seed })
runEngine(e, 1000)
const ws = e.view().worldSim as (Record<string, unknown> & {
marketPool: Record<string, number>
secretQi: Record<string, number>
tide: number
}) | undefined
expect(ws).toBeTruthy()
if (ws) {
for (const v of Object.values(ws.marketPool)) expect(v).toBeGreaterThan(0)
for (const v of Object.values(ws.secretQi ?? {})) expect(v).toBeGreaterThanOrEqual(0)
expect(ws.tide).toBeGreaterThan(0.5)
expect(ws.tide).toBeLessThan(1.4)
}
})
it('NPC 换代至少发生一次(世界在演化)', () => {
const e = new GameEngine({ seed: 'ws-evolve' })
runEngine(e, 1200)
const ws = e.view().worldSim as { npcSuccessions?: number } | undefined
expect(ws?.npcSuccessions ?? 0).toBeGreaterThan(0)
})
it('快讯持有且裁剪符合 N(≤120', () => {
const e = new GameEngine({ seed: 'ws-news' })
runEngine(e, 400)
const ws = e.view().worldSim as { newsFeed?: unknown[] } | undefined
expect(ws?.newsFeed.length ?? 0).toBeLessThanOrEqual(WORLDSIM.newsKeep)
})
})
describe('Sim 与外层联动', () => {
it('tideMult 在界(0.5-1.4)且随年景变化', () => {
const e = new GameEngine({ seed: 'ws-tide-link' })
const sim = new WorldSim(e.world)
const before = sim.tideMult()
expect(before).toBeGreaterThanOrEqual(0.5)
expect(before).toBeLessThan(1.4)
})
})
describe('GameEngine 建档参数', () => {
it('姓氏透传:新档用玩家输入的姓氏/家号(0.1.22 修复)', () => {
const e = new GameEngine({ seed: 'name-fix', surname: '慕容', familyName: '慕容家', motto: '铁血丹心', difficulty: 'normal' })
expect(e.world.state.family.name).toBe('慕容家')
const head = Object.values(e.world.state.members).find((c) => c.isHead)
expect(head?.name.startsWith('慕容')).toBe(true)
expect(e.world.state.family.motto ?? '').toBeTruthy()
})
it('缺省建档仍为林氏(兜底不破)', () => {
const e = new GameEngine({ seed: 'name-default' })
expect(e.world.state.family.name).toBe('林氏')
})
})