// ==================== 全流程生命周期测试 ==================== import { createInitialState, resetForRebirth } from '../src/engine/state.js'; import { setCareerConfig } from '../src/engine/careerEngine.js'; import { setEventConfig } from '../src/engine/eventEngine.js'; import { setShopConfig } from '../src/engine/shopEngine.js'; import { tick } from '../src/engine/tickLoop.js'; import { applyEffect } from '../src/engine/effectApplier.js'; import { processDeath } from '../src/engine/deathEngine.js'; import { evaluateCondition } from '../src/engine/conditionEvaluator.js'; import fs from 'fs'; function assert(cond, msg) { if (!cond) throw new Error(msg); } // 加载配置 const careers = JSON.parse(fs.readFileSync('./src/config/careers.json', 'utf8')); const events = JSON.parse(fs.readFileSync('./src/config/events.json', 'utf8')); const shop = JSON.parse(fs.readFileSync('./src/config/shop.json', 'utf8')); const identities = JSON.parse(fs.readFileSync('./src/config/identities.json', 'utf8')); const talents = JSON.parse(fs.readFileSync('./src/config/talents.json', 'utf8')); setCareerConfig(careers); setEventConfig(events); setShopConfig(shop); function log(msg) { console.log(` ${msg}`); } // 辅助函数:自动处理选择事件(测试中不暂停) function autoResolveChoice(state) { if (state.paused && state.currentEvent && state.currentEvent.choices) { // 找到第一个满足条件的选择,否则选最后一个 let choice = state.currentEvent.choices.find(c => !c.requirements || evaluateCondition(c.requirements, state)); if (!choice) choice = state.currentEvent.choices[state.currentEvent.choices.length - 1]; if (choice && choice.effects) { for (const effect of choice.effects) applyEffect(effect, state); } state.paused = false; state.currentEvent = null; } } // ====== 测试1:第1世基础流程 ====== console.log('\n=== Test 1: 第1世基础流程 ==='); { const state = createInitialState(); state.identity = 'peasant'; state.stats = { body: 4, wisdom: 3, charm: 3, destiny: 3, business: 1, intelligence: 2 }; // 运行到10岁 for (let i = 0; i < 365 * 10; i++) { tick(state, 1, careers, events, shop); autoResolveChoice(state); if (!state.alive) break; } log(`年龄: ${state.age}岁`); log(`银两: ${Math.floor(state.money)}`); log(`职业: ${Object.keys(state.careers).join(', ') || '无'}`); assert(state.age >= 9, '应该活到接近10岁'); assert(Object.keys(state.careers).includes('student'), '应该解锁学童'); assert(state.money > 0, '应该有银两收入'); log('第1世基础流程 PASS'); } // ====== 测试2:职业解锁链 ====== console.log('\n=== Test 2: 职业解锁链 ==='); { const state = createInitialState(); state.age = 10; state.stats = { body: 20, wisdom: 30, charm: 10, destiny: 5, business: 5, intelligence: 10 }; // 设置学童100级 state.careers.student = { level: 100, exp: 0 }; // tick一次检查解锁 tick(state, 1, careers, events, shop); autoResolveChoice(state); log(`解锁职业: ${Object.keys(state.careers).join(', ')}`); assert(Object.keys(state.careers).includes('book_boy'), '学童100级应解锁书童'); // 设置学童250级 + 14岁 state.careers.student.level = 250; state.age = 14; tick(state, 1, careers, events, shop); autoResolveChoice(state); log(`解锁职业: ${Object.keys(state.careers).join(', ')}`); assert(Object.keys(state.careers).includes('scholar'), '学童250级+14岁应解锁书生'); // 士兵解锁 state.stats.body = 15; tick(state, 1, careers, events, shop); autoResolveChoice(state); assert(Object.keys(state.careers).includes('soldier'), '14岁+体质15应解锁士兵'); log('职业解锁链 PASS'); } // ====== 测试3:银两系统 ====== console.log('\n=== Test 3: 银两系统 ==='); { const state = createInitialState(); state.age = 10; state.stats = { body: 10, wisdom: 10, charm: 10, destiny: 10, business: 50, intelligence: 10 }; state.careers.student = { level: 0, exp: 0 }; tick(state, 1, careers, events, shop); autoResolveChoice(state); const income = state.money; log(`经商50时每日收入: ${income.toFixed(2)}`); assert(income > 1, '经商50应增加收入(1.5倍)'); log('银两系统 PASS'); } // ====== 测试4:经验系统 + 升级 ====== console.log('\n=== Test 4: 经验系统 + 升级 ==='); { const state = createInitialState(); state.age = 10; state.stats = { body: 10, wisdom: 50, charm: 10, destiny: 10, business: 10, intelligence: 10 }; state.careers.student = { level: 0, exp: 0 }; // 运行一段时间 for (let i = 0; i < 100; i++) { tick(state, 1, careers, events, shop); autoResolveChoice(state); } log(`学童等级: ${state.careers.student.level}`); log(`学童经验: ${Math.floor(state.careers.student.exp)}`); assert(state.careers.student.level > 0, '应该升级了'); log('经验系统 PASS'); } // ====== 测试5:入侵事件触发 ====== console.log('\n=== Test 5: 入侵事件触发 ==='); { const state = createInitialState(); state.age = 39; state.stats = { body: 50, wisdom: 50, charm: 50, destiny: 50, business: 50, intelligence: 50 }; state.careers.soldier = { level: 100, exp: 0 }; // 在40岁生日时触发入侵 state.day = 364; state.year = 39; tick(state, 1, careers, events, shop); log(`年龄: ${state.age}`); log(`暂停状态: ${state.paused}`); log(`当前事件: ${state.currentEvent?.id || '无'}`); assert(state.age === 40, '应该刚满40岁'); assert(state.paused === true, '选择事件应暂停游戏'); assert(state.currentEvent?.id === 'invasion_military_40', '应触发军事入侵事件'); log('入侵事件触发 PASS'); } // ====== 测试6:跨轮继承 ====== console.log('\n=== Test 6: 跨轮继承 ==='); { const state = createInitialState(); state.identity = 'peasant'; state.stats = { body: 4, wisdom: 3, charm: 3, destiny: 3, business: 1, intelligence: 2 }; // 模拟一轮游戏,获得一些积累 state.metaExp = { student: 500 }; state.artifacts = { immortal_sword: 3 }; state.memories = ['wisdom_boost']; state.unlockedEntries = new Set(['sword_bone']); state.reincarnation = 0; // 运行30年,然后手动触发死亡(测试重点是跨轮继承,不是等自然死亡) for (let i = 0; i < 365 * 30; i++) { tick(state, 1, careers, events, shop); autoResolveChoice(state); if (!state.alive) break; } // 手动死亡以测试结算 applyEffect({ type: 'die', reason: '测试死亡' }, state); assert(state.alive === false, '应该已死亡'); // 死亡结算 processDeath(state, careers, talents); log(`死亡前元经验: ${JSON.stringify(state.metaExp)}`); // 重生 resetForRebirth(state); log(`重生后轮次: ${state.reincarnation}`); log(`重生后神器: ${JSON.stringify(state.artifacts)}`); log(`重生后记忆: ${JSON.stringify(state.memories)}`); log(`重生后元经验: ${JSON.stringify(state.metaExp)}`); log(`重生后银两: ${state.money}`); log(`重生后职业: ${JSON.stringify(state.careers)}`); assert(state.reincarnation === 1, '轮次应为1'); assert(state.artifacts.immortal_sword === 3, '神器应保留'); assert(state.metaExp.student > 500, '元经验应增加'); assert(state.money === 0, '银两应重置'); assert(Object.keys(state.careers).length === 0, '职业应重置'); log('跨轮继承 PASS'); } // ====== 测试7:商铺购买 ====== console.log('\n=== Test 7: 商铺购买 ======'); { const state = createInitialState(); state.money = 1000; state.age = 15; state.stats = { body: 10, wisdom: 10, charm: 10, destiny: 10, business: 10, intelligence: 10 }; import('../src/engine/shopEngine.js').then(({ buyItem, canBuyItem }) => { // 购买大力丸 const canBuy = canBuyItem(shop, state, 'power_pill'); assert(canBuy === true, '应该能买大力丸'); const result = buyItem(shop, state, 'power_pill'); assert(result === true, '购买应成功'); assert(state.stats.body === 15, '体质应+5'); assert(state.money === 950, '银两应-50'); log('商铺购买 PASS'); }); } console.log('\n=== 所有全流程测试通过 ===\n');