import type { GeneralActionDefinition, GeneralTurnCommandKey, NationTurnCommandKey, ScenarioConfig, TurnCommandEnv, TurnCommandProfile, UnitSetDefinition, } from '@sammo-ts/logic'; import { loadGeneralTurnCommandSpecs, loadNationTurnCommandSpecs, createItemActionModules, createItemModuleRegistry, ITEM_KEYS, loadItemModules, createInheritBuffModules, } from '@sammo-ts/logic'; import { asRecord } from '@sammo-ts/common'; const DEFAULT_GENERAL_GOLD = 1000; const DEFAULT_GENERAL_RICE = 1000; const DEFAULT_CREW_TYPE_ID = 1100; const normalizeCode = (value: string | null | undefined): string | null => { if (!value || value === 'None') { return null; } return value; }; const resolveNumber = (source: Record, keys: string[], fallback: number): number => { for (const key of keys) { const value = source[key]; if (typeof value === 'number' && Number.isFinite(value)) { return value; } } return fallback; }; const resolveOptionalString = (source: Record, keys: string[]): string | null => { for (const key of keys) { const value = source[key]; if (typeof value === 'string') { return normalizeCode(value); } } return null; }; export const buildCommandEnv = (config: ScenarioConfig, unitSet?: UnitSetDefinition): TurnCommandEnv => { const constValues = asRecord(config.const); return { develCost: resolveNumber(constValues, ['develCost', 'develcost', 'develrate'], 0), trainDelta: resolveNumber(constValues, ['trainDelta'], 0), atmosDelta: resolveNumber(constValues, ['atmosDelta'], 0), maxTrainByCommand: resolveNumber(constValues, ['maxTrainByCommand'], 0), maxAtmosByCommand: resolveNumber(constValues, ['maxAtmosByCommand'], 0), sabotageDefaultProb: resolveNumber(constValues, ['sabotageDefaultProb'], 0), sabotageProbCoefByStat: resolveNumber(constValues, ['sabotageProbCoefByStat'], 0), sabotageDefenceCoefByGeneralCount: resolveNumber(constValues, ['sabotageDefenceCoefByGeneralCount'], 0), sabotageDamageMin: resolveNumber(constValues, ['sabotageDamageMin'], 0), sabotageDamageMax: resolveNumber(constValues, ['sabotageDamageMax'], 0), openingPartYear: resolveNumber(constValues, ['openingPartYear'], 0), maxGeneral: resolveNumber(constValues, ['defaultMaxGeneral', 'maxGeneral'], 0), defaultNpcGold: resolveNumber(constValues, ['defaultNpcGold', 'defaultGold'], DEFAULT_GENERAL_GOLD), defaultNpcRice: resolveNumber(constValues, ['defaultNpcRice', 'defaultRice'], DEFAULT_GENERAL_RICE), defaultCrewTypeId: resolveNumber( constValues, ['defaultCrewTypeId'], unitSet?.defaultCrewTypeId ?? DEFAULT_CREW_TYPE_ID ), defaultSpecialDomestic: resolveOptionalString(constValues, ['defaultSpecialDomestic']), defaultSpecialWar: resolveOptionalString(constValues, ['defaultSpecialWar']), initialNationGenLimit: resolveNumber(constValues, ['initialNationGenLimit'], 0), maxTechLevel: resolveNumber(constValues, ['maxTechLevel'], 0), baseGold: resolveNumber(constValues, ['baseGold', 'basegold'], 0), baseRice: resolveNumber(constValues, ['baseRice', 'baserice'], 0), maxResourceActionAmount: resolveNumber(constValues, ['maxResourceActionAmount'], 0), }; }; const ensureGeneralFallback = async ( definitions: Map, fallbackKey: GeneralTurnCommandKey, env: TurnCommandEnv ): Promise => { if (definitions.has(fallbackKey)) { return; } const [spec] = await loadGeneralTurnCommandSpecs([fallbackKey]); if (!spec) { return; } definitions.set(fallbackKey, spec.createDefinition(env)); }; export const buildReservedTurnDefinitions = async (options: { env: TurnCommandEnv; commandProfile: TurnCommandProfile; defaultActionKey: GeneralTurnCommandKey & NationTurnCommandKey; }): Promise<{ general: Map; nation: Map; }> => { const itemModules = await loadItemModules([...ITEM_KEYS]); const itemRegistry = createItemModuleRegistry(itemModules); const itemActionModules = createItemActionModules(itemRegistry); const inheritBuffModules = createInheritBuffModules(); options.env.generalActionModules = [...(options.env.generalActionModules ?? []), ...itemActionModules.general]; options.env.warActionModules = [...(options.env.warActionModules ?? []), ...itemActionModules.war]; options.env.generalActionModules.push(inheritBuffModules.general); options.env.warActionModules.push(inheritBuffModules.war); const generalSpecs = await loadGeneralTurnCommandSpecs(options.commandProfile.general); const nationSpecs = await loadNationTurnCommandSpecs(options.commandProfile.nation); const general = new Map(generalSpecs.map((spec) => [spec.key, spec.createDefinition(options.env)])); const nation = new Map(nationSpecs.map((spec) => [spec.key, spec.createDefinition(options.env)])); await ensureGeneralFallback(general, options.defaultActionKey, options.env); if (!nation.has(options.defaultActionKey)) { const [spec] = await loadNationTurnCommandSpecs([options.defaultActionKey]); if (spec) { nation.set(spec.key, spec.createDefinition(options.env)); } } return { general, nation }; };