export interface BuildingDef { id: string name: string icon: string desc: string kind: 'produce' | 'function' maxLevel: number produceTable?: (level: number) => { stone?: number; lingcao?: number; lingkuang?: number; beastcore?: number } upgradeCost: (level: number) => { stones: number; lingkuang: number } extra?: Record } export const BUILDINGS: Record = { lingtian: { id: 'lingtian', name: '灵田', icon: '田', desc: '种植灵草,每月产出稳定。', kind: 'produce', maxLevel: 5, produceTable: (l) => ({ lingcao: 10 * l }), upgradeCost: (l) => ({ stones: 80 * Math.pow(1.7, l - 1), lingkuang: 12 * l }) }, yaoyuan: { id: 'yaoyuan', name: '药园', icon: '药', desc: '培育稀有药草以炼丹药。', kind: 'produce', maxLevel: 5, produceTable: (l) => ({ lingcao: 5 * l, beastcore: l >= 3 ? 1 : 0 }), upgradeCost: (l) => ({ stones: 110 * Math.pow(1.7, l - 1), lingkuang: 15 * l }) }, lingkuang: { id: 'lingkuang', name: '灵矿', icon: '矿', desc: '开采灵石矿脉,供给炼器布阵。', kind: 'produce', maxLevel: 5, produceTable: (l) => ({ lingkuang: 8 * l }), upgradeCost: (l) => ({ stones: 130 * Math.pow(1.7, l - 1), lingkuang: 10 * l }) }, fangshi: { id: 'fangshi', name: '坊市', icon: '市', desc: '设摊售货,每月进账灵石。', kind: 'produce', maxLevel: 5, produceTable: (l) => ({ stone: 55 * l }), upgradeCost: (l) => ({ stones: 150 * Math.pow(1.7, l - 1), lingkuang: 20 * l }) }, danfang: { id: 'danfang', name: '丹房', icon: '丹', desc: '炼制丹药,等级越高成丹率越高。', kind: 'function', maxLevel: 5, upgradeCost: (l) => ({ stones: 170 * Math.pow(1.7, l - 1), lingkuang: 18 * l }), extra: { craftChance: '0.5 + 0.1*L' } }, cangshu: { id: 'cangshu', name: '藏书阁', icon: '书', desc: '收藏功法典籍,等级越高越能寻得宝典。', kind: 'function', maxLevel: 5, upgradeCost: (l) => ({ stones: 160 * Math.pow(1.7, l - 1), lingkuang: 12 * l }), extra: { unlockGrade: '1 + L' } }, juling: { id: 'juling', name: '聚灵阵', icon: '阵', desc: '汇聚天地灵气,全族修炼加成。', kind: 'function', maxLevel: 5, upgradeCost: (l) => ({ stones: 200 * Math.pow(1.7, l - 1), lingkuang: 30 * l }), extra: { expBonus: '0.05 * L' } }, yanwu: { id: 'yanwu', name: '演武场', icon: '武', desc: '操练武艺,家族战力加成。', kind: 'function', maxLevel: 5, upgradeCost: (l) => ({ stones: 140 * Math.pow(1.7, l - 1), lingkuang: 25 * l }), extra: { powerBonus: '0.04 * L' } }, dongfu: { id: 'dongfu', name: '洞府', icon: '府', desc: '闭关修行之所,闭关者修为加成。', kind: 'function', maxLevel: 5, upgradeCost: (l) => ({ stones: 220 * Math.pow(1.7, l - 1), lingkuang: 35 * l }), extra: { expBonus: '0.08 * L' } }, zongci: { id: 'zongci', name: '宗祠', icon: '祠', desc: '供奉先祖,家族声望与生育兴旺。', kind: 'function', maxLevel: 5, upgradeCost: (l) => ({ stones: 120 * Math.pow(1.7, l - 1), lingkuang: 8 * l }), extra: { repBonus: '0.3 * L /年' } }, lingshou: { id: 'lingshou', name: '灵兽园', icon: '兽', desc: '豢养灵兽,战阵之助,偶得兽核。', kind: 'function', maxLevel: 5, upgradeCost: (l) => ({ stones: 190 * Math.pow(1.7, l - 1), lingkuang: 28 * l }), extra: { powerBonus: '0.05 * L' } } } export const BUILDING_IDS = Object.keys(BUILDINGS) export function buildingById(id: string): BuildingDef { return BUILDINGS[id] } /** 解析 extra 表达式(如 '0.5 + 0.1*L'):仅允许 数字/括号/四则/空格 与变量 L。 * 白名单校验后求值——所有数字加成以 extra 为单一权威。 */ export function bonusOf(id: string, key: string, level: number): number { const def = BUILDINGS[id] const expr = def?.extra?.[key] if (!expr) return 0 const sanitized = expr.replace(/L/g, String(level)) if (!/^[0-9.\s+\-*/()]+$/.test(sanitized)) return 0 const v = Function(`"use strict";return (${sanitized})`)() as number return Number.isFinite(v) ? v : 0 }