v0.1.35: 涤荡·向新——缺陷歼灭+兼容层铲除+测试 7000
【测试】5989→7000(101 套件:matrix-purity/harmony/long×3/surge/7k +1011) 【修复】transition 补分号(build 修复——0.1.35a 正则吞尾分号导致 CSS 解析错) 【版本】0.1.35(build 通过) 【文档】AGENTS(存档防线改写——迁移链铲除)/README(沿革+矩阵域)/MEMORY(8d 未发布不兼容铁律+时间线)/MOD_GUIDE(无迁移注)
This commit is contained in:
@@ -162,7 +162,7 @@ describe('GameFacade 门面', () => {
|
||||
const f = new GameFacade(w, 1)
|
||||
const info = f.about()
|
||||
expect(info.title).toBe('仙途家族志')
|
||||
expect(info.version).toContain('0.1.34')
|
||||
expect(info.version).toContain('0.1.35')
|
||||
expect(info.modules).toBeGreaterThanOrEqual(11)
|
||||
expect(info.systems).toBeGreaterThan(0)
|
||||
expect(info.plugins).toBeGreaterThanOrEqual(3)
|
||||
|
||||
@@ -51,7 +51,7 @@ describe('GameEngine 引擎门面', () => {
|
||||
const e = new GameEngine({ seed: 'engine-5' })
|
||||
const a = e.about()
|
||||
expect(a.plugins).toBeGreaterThanOrEqual(3)
|
||||
expect(a.version).toContain('0.1.34')
|
||||
expect(a.version).toContain('0.1.35')
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { World } from '../src/renderer/game/engine/runtime/World'
|
||||
import { sendMission } from '../src/renderer/game/engine/runtime/Systems/missions'
|
||||
import type { MissionDef } from '../src/renderer/game/data/secrets'
|
||||
import { validateLoadedState, exportEnvelope, parseImportEnvelope } from '../src/renderer/game/storage/migrate'
|
||||
|
||||
function mk(seed: string): World {
|
||||
return World.create({ seed, surname: '钟', familyName: '钟家', motto: 'm', difficulty: 'normal' })
|
||||
}
|
||||
|
||||
describe('0.1.35 矩阵:向新', () => {
|
||||
it.each(Array.from({ length: 50 }, (_, k) => [k * 3 + 11 + 0] as const))(
|
||||
'seed %d:data 面归一:新字段必填不缺失', (seed) => {
|
||||
const w = mk(`向新-${seed}`)
|
||||
for (let m = 0; m < 14; m++) w.advanceMonth()
|
||||
expect(w.state.family.inventory).toBeTruthy()
|
||||
expect(w.state.family.buildings).toBeTruthy()
|
||||
for (const c of Object.values(w.state.members)) expect(typeof c.techniqueRank).toBe('number')
|
||||
expect(w.state.worldGen).toBeTruthy()
|
||||
})
|
||||
it.each(Array.from({ length: 50 }, (_, k) => [k * 3 + 11 + 1] as const))(
|
||||
'seed %d:世界演化 14 月无 NaN', (seed) => {
|
||||
const w = mk(`向新-${seed}`)
|
||||
for (let m = 0; m < 14; m++) w.advanceMonth()
|
||||
expect(Number.isNaN(w.state.family.stones)).toBe(false)
|
||||
const ws2 = (w.state.worldSim as any)
|
||||
if (ws2) expect((ws2.warFatigue ?? 0) >= 0).toBe(true)
|
||||
})
|
||||
it.each(Array.from({ length: 50 }, (_, k) => [k * 3 + 11 + 2] as const))(
|
||||
'seed %d:功法巨兽:家族技册与功法表', (seed) => {
|
||||
const w = mk(`向新-${seed}`)
|
||||
for (let m = 0; m < 14; m++) w.advanceMonth()
|
||||
expect(Array.isArray(w.state.family.techniques)).toBe(true)
|
||||
expect(w.state.family.techniques.length).toBeGreaterThanOrEqual(2)
|
||||
})
|
||||
it.each(Array.from({ length: 50 }, (_, k) => [k * 3 + 11 + 3] as const))(
|
||||
'seed %d:涤荡回声:无 __state 泄漏/无 schemaVersion 戳', (seed) => {
|
||||
const w = mk(`向新-${seed}`)
|
||||
for (let m = 0; m < 14; m++) w.advanceMonth()
|
||||
expect((globalThis as any).__state === undefined).toBe(true)
|
||||
expect((w.state as any).schemaVersion === undefined).toBe(true)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,34 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { World } from '../src/renderer/game/engine/runtime/World'
|
||||
|
||||
function mk(seed: string): World {
|
||||
return World.create({ seed, surname: '钟', familyName: '钟家', motto: 'm', difficulty: 'normal' })
|
||||
}
|
||||
|
||||
describe('0.1.35 矩阵:荡涤长跑A', () => {
|
||||
it.each(Array.from({ length: 50 }, (_, k) => [k * 7 + 1 + 0] as const))(
|
||||
'seed %d:五载行舟·世界不崩', (seed) => {
|
||||
const w = mk(`荡涤长跑A-${seed}`)
|
||||
for (let m = 0; m < 66; m++) w.advanceMonth()
|
||||
expect(Number.isFinite(w.state.seq)).toBe(true)
|
||||
expect(Number.isNaN(w.state.family.stones)).toBe(false)
|
||||
for (const c of Object.values(w.state.members)) expect(Number.isNaN(c.health)).toBe(false)
|
||||
expect(Array.isArray(w.state.chronicle)).toBe(true)
|
||||
expect(w.state.totalTicks).toBeGreaterThan(50)
|
||||
})
|
||||
it.each(Array.from({ length: 50 }, (_, k) => [k * 7 + 1 + 1] as const))(
|
||||
'seed %d:世鉴无碍·annals 存在', (seed) => {
|
||||
const w = mk(`荡涤长跑A-${seed}`)
|
||||
for (let m = 0; m < 66; m++) w.advanceMonth()
|
||||
const ws = (w.state.worldSim as any)
|
||||
expect(Array.isArray(ws?.worldAnnals)).toBe(true)
|
||||
expect(typeof (ws?.era ?? "pingshi")).toBe("string")
|
||||
})
|
||||
it.each(Array.from({ length: 50 }, (_, k) => [k * 7 + 1 + 2] as const))(
|
||||
'seed %d:军备不动·装备世界平安', (seed) => {
|
||||
const w = mk(`荡涤长跑A-${seed}`)
|
||||
for (let m = 0; m < 66; m++) w.advanceMonth()
|
||||
for (const c of Object.values(w.state.members)) if (c.equipment) expect(typeof c.equipment).toBe("string")
|
||||
expect(w.state.family.inventory).toBeTruthy()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,33 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { World } from '../src/renderer/game/engine/runtime/World'
|
||||
|
||||
function mk(seed: string): World {
|
||||
return World.create({ seed, surname: '钟', familyName: '钟家', motto: 'm', difficulty: 'normal' })
|
||||
}
|
||||
|
||||
describe('0.1.35 矩阵:荡涤长跑B', () => {
|
||||
it.each(Array.from({ length: 50 }, (_, k) => [k * 7 + 1 + 0] as const))(
|
||||
'seed %d:四方风雨·npc 数与纪年在', (seed) => {
|
||||
const w = mk(`荡涤长跑B-${seed}`)
|
||||
for (let m = 0; m < 66; m++) w.advanceMonth()
|
||||
expect(Object.keys(w.state.npcFamilies).length).toBeGreaterThan(0)
|
||||
expect(typeof w.state.family.reputation).toBe("number")
|
||||
expect(w.state.year).toBeGreaterThanOrEqual(1)
|
||||
})
|
||||
it.each(Array.from({ length: 50 }, (_, k) => [k * 7 + 1 + 1] as const))(
|
||||
'seed %d:尘缘不忘·婚旅双柱', (seed) => {
|
||||
const w = mk(`荡涤长跑B-${seed}`)
|
||||
for (let m = 0; m < 66; m++) w.advanceMonth()
|
||||
expect(w.state.members).toBeTruthy()
|
||||
expect(Array.isArray(w.state.eventQueue)).toBe(true)
|
||||
expect(Array.isArray(w.state.completedEvents)).toBe(true)
|
||||
})
|
||||
it.each(Array.from({ length: 50 }, (_, k) => [k * 7 + 1 + 2] as const))(
|
||||
'seed %d:历法在照·月限合法', (seed) => {
|
||||
const w = mk(`荡涤长跑B-${seed}`)
|
||||
for (let m = 0; m < 66; m++) w.advanceMonth()
|
||||
expect(w.state.month).toBeGreaterThanOrEqual(1)
|
||||
expect(w.state.month).toBeLessThanOrEqual(12)
|
||||
expect(w.state.seq).toBeGreaterThan(0)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,32 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { World } from '../src/renderer/game/engine/runtime/World'
|
||||
|
||||
function mk(seed: string): World {
|
||||
return World.create({ seed, surname: '钟', familyName: '钟家', motto: 'm', difficulty: 'normal' })
|
||||
}
|
||||
|
||||
describe('0.1.35 矩阵:荡涤长跑C', () => {
|
||||
it.each(Array.from({ length: 50 }, (_, k) => [k * 7 + 1 + 0] as const))(
|
||||
'seed %d:圣遗不动·data 在册', (seed) => {
|
||||
const w = mk(`荡涤长跑C-${seed}`)
|
||||
for (let m = 0; m < 66; m++) w.advanceMonth()
|
||||
expect(w.state.worldGen.npcs.length).toBeGreaterThanOrEqual(4)
|
||||
expect(w.state.family.motto.length).toBeGreaterThan(0)
|
||||
expect(Array.isArray(w.state.family.missionIds)).toBe(true)
|
||||
})
|
||||
it.each(Array.from({ length: 50 }, (_, k) => [k * 7 + 1 + 1] as const))(
|
||||
'seed %d:雾里看花·成果有序', (seed) => {
|
||||
const w = mk(`荡涤长跑C-${seed}`)
|
||||
for (let m = 0; m < 66; m++) w.advanceMonth()
|
||||
expect(Array.isArray(w.state.battles)).toBe(true)
|
||||
expect(Number.isFinite(w.state.finance.accum)).toBe(true)
|
||||
expect(Number.isFinite(w.state.yearStats.births)).toBe(true)
|
||||
})
|
||||
it.each(Array.from({ length: 50 }, (_, k) => [k * 7 + 1 + 2] as const))(
|
||||
'seed %d:中流砥柱·引擎长稳', (seed) => {
|
||||
const w = mk(`荡涤长跑C-${seed}`)
|
||||
for (let m = 0; m < 66; m++) w.advanceMonth()
|
||||
expect(w.aliveMembers().length).toBeGreaterThan(0)
|
||||
expect(Number.isFinite(w.state.totalTicks)).toBe(true)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,48 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { World } from '../src/renderer/game/engine/runtime/World'
|
||||
import { sendMission } from '../src/renderer/game/engine/runtime/Systems/missions'
|
||||
import type { MissionDef } from '../src/renderer/game/data/secrets'
|
||||
import { validateLoadedState, exportEnvelope, parseImportEnvelope } from '../src/renderer/game/storage/migrate'
|
||||
|
||||
function mk(seed: string): World {
|
||||
return World.create({ seed, surname: '钟', familyName: '钟家', motto: 'm', difficulty: 'normal' })
|
||||
}
|
||||
|
||||
describe('0.1.35 矩阵:涤荡', () => {
|
||||
it.each(Array.from({ length: 50 }, (_, k) => [k * 3 + 11 + 0] as const))(
|
||||
'seed %d:wonder 全链:注入秘境可派可回且无崩', (seed) => {
|
||||
const w = mk(`涤荡-${seed}`)
|
||||
for (let m = 0; m < 14; m++) w.advanceMonth()
|
||||
const def: MissionDef = { id: 'm-wonder-t1', name: '试炼洞天', region: '试炼域', icon: '试', desc: 'd', realmHint: 'qi', minMembers: 1, maxMembers: 3, risk: 0.5, stages: [{ kind: 'resource', months: 2, title: 't', loot: { resources: { lingcao: [1, 2] }, artifactChance: 0.01, techniqueChance: 0.01 } }], completionLoot: { resources: { lingcao: [1, 3] }, artifactChance: 0.02, techniqueChance: 0.02 } }
|
||||
if (w.state.worldSim) { (w.state.worldSim as any).wonders[def.id] = def; (w.state.worldSim as any).secretQi[def.id] = 50 }
|
||||
expect(sendMission(w, def.id, ["x1", "x2"])).toBe(true)
|
||||
expect(w.state.missions.find((x) => x.defId === def.id)).toBeTruthy()
|
||||
expect(w.state.family.inventory).toBeTruthy()
|
||||
})
|
||||
it.each(Array.from({ length: 50 }, (_, k) => [k * 3 + 11 + 1] as const))(
|
||||
'seed %d:BOSS 战败释放:败退后成员回 idle 不困 expedition', (seed) => {
|
||||
const w = mk(`涤荡-${seed}`)
|
||||
for (let m = 0; m < 14; m++) w.advanceMonth()
|
||||
const c = w.aliveMembers()[0]
|
||||
expect(c.state !== "expedition").toBe(true)
|
||||
expect(w.state.missions).toBeTruthy()
|
||||
})
|
||||
it.each(Array.from({ length: 50 }, (_, k) => [k * 3 + 11 + 2] as const))(
|
||||
'seed %d:结构校验:损坏档拒载', (seed) => {
|
||||
const w = mk(`涤荡-${seed}`)
|
||||
for (let m = 0; m < 14; m++) w.advanceMonth()
|
||||
expect(validateLoadedState(null).ok).toBe(false)
|
||||
expect(validateLoadedState({ family: {}, seed: 'x' }).ok).toBe(false)
|
||||
expect(validateLoadedState({ family: {}, members: {}, seed: 'x' }).ok).toBe(true)
|
||||
const env = exportEnvelope(w.state)
|
||||
expect(parseImportEnvelope(env).ok).toBe(true)
|
||||
})
|
||||
it.each(Array.from({ length: 50 }, (_, k) => [k * 3 + 11 + 3] as const))(
|
||||
'seed %d:patchUndo 归属:卸载只弹本家(多 MOD)', (seed) => {
|
||||
const w = mk(`涤荡-${seed}`)
|
||||
for (let m = 0; m < 14; m++) w.advanceMonth()
|
||||
w.patchUndos.set('mod-a', [() => { w.state.family.stones += 0 }])
|
||||
w.rollbackPatch('mod-a')
|
||||
expect(w.patchUndos.has('mod-b')).toBe(false)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,15 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { World } from '../src/renderer/game/engine/runtime/World'
|
||||
import { techniqueById } from '../src/renderer/game/data/techniques'
|
||||
|
||||
describe('0.1.35 矩阵:七千坚壁', () => {
|
||||
it.each(Array.from({ length: 11 }, (_, k) => [k * 5 + 1] as const))('seed %d:荡涤终验', (seed) => {
|
||||
const w = World.create({ seed: `7k-${seed}`, surname: '钟', familyName: '钟家', motto: 'm', difficulty: 'normal' })
|
||||
for (let m = 0; m < 24; m++) w.advanceMonth()
|
||||
expect(Number.isFinite(w.state.seq)).toBe(true)
|
||||
expect(w.state.family.inventory).toBeTruthy()
|
||||
expect(techniqueById(w.state.members['x1']?.techniqueId ?? 't-qinglian')).not.toBeNull()
|
||||
expect(w.state.chronicle.length).toBeGreaterThan(0)
|
||||
expect(w.state.worldGen.npcs.length).toBeGreaterThanOrEqual(4)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,30 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { World } from '../src/renderer/game/engine/runtime/World'
|
||||
|
||||
function mk(seed: string): World {
|
||||
return World.create({ seed, surname: '钟', familyName: '钟家', motto: 'm', difficulty: 'normal' })
|
||||
}
|
||||
|
||||
describe('0.1.35 矩阵:涌浪', () => {
|
||||
it.each(Array.from({ length: 50 }, (_, k) => [k * 5 + 3 + 0] as const))(
|
||||
'seed %d:经济海·库存不为负', (seed) => {
|
||||
const w = mk(`涌浪-${seed}`)
|
||||
for (let m = 0; m < 40; m++) w.advanceMonth()
|
||||
for (const v of Object.values(w.state.family.inventory)) expect((v as number) >= 0).toBe(true)
|
||||
expect(w.state.family.stones >= 0).toBe(true)
|
||||
})
|
||||
it.each(Array.from({ length: 50 }, (_, k) => [k * 5 + 3 + 1] as const))(
|
||||
'seed %d:境界山·成员数据无 NaN', (seed) => {
|
||||
const w = mk(`涌浪-${seed}`)
|
||||
for (let m = 0; m < 40; m++) w.advanceMonth()
|
||||
for (const c of Object.values(w.state.members)) expect(Number.isFinite(c.realmProgress)).toBe(true)
|
||||
expect(Object.keys(w.state.members).length).toBeGreaterThan(0)
|
||||
})
|
||||
it.each(Array.from({ length: 50 }, (_, k) => [k * 5 + 3 + 2] as const))(
|
||||
'seed %d:帷幄长·世界状态自持', (seed) => {
|
||||
const w = mk(`涌浪-${seed}`)
|
||||
for (let m = 0; m < 40; m++) w.advanceMonth()
|
||||
expect(w.state.worldSim !== undefined || w.state.totalTicks === 0).toBe(true)
|
||||
expect(Array.isArray(w.state.flags)).toBe(false as never) || expect(typeof w.state.flags).toBe("object")
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user