416b6bfe8d
Research now costs money (drained per-tick) with ~2.5-3.5x longer durations by category. Early-game talent budget costs reduced via era multiplier (startup 0.2x → bigtech 1.0x). New seed-driven PersonaStrategy with 8 axes of variation for meaningful multi-run testing. CI multi-run switched from greedy to persona strategy. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
68 lines
2.4 KiB
TypeScript
68 lines
2.4 KiB
TypeScript
import type { GameState, EconomyState, InfrastructureState } from '@ai-tycoon/shared';
|
|
import { FINANCIAL_SNAPSHOT_INTERVAL, MAX_FINANCIAL_HISTORY, REGULATION_COMPLIANCE_PER_CAPABILITY } from '@ai-tycoon/shared';
|
|
import { TECH_TREE } from '../data/techTree';
|
|
import type { MarketTickResult } from './marketSystem';
|
|
|
|
export function processEconomy(
|
|
state: GameState,
|
|
market: MarketTickResult,
|
|
infrastructure: InfrastructureState,
|
|
extraCosts: number = 0,
|
|
): EconomyState {
|
|
const revenue = market.apiRevenue + market.subscriptionRevenue;
|
|
|
|
let infraExpenses = 0;
|
|
for (const cluster of infrastructure.clusters) {
|
|
for (const campus of cluster.campuses) {
|
|
for (const dc of campus.dataCenters) {
|
|
infraExpenses += dc.energyCostPerTick + dc.maintenanceCostPerTick;
|
|
}
|
|
}
|
|
}
|
|
|
|
const talentExpenses = state.talent.totalSalaryPerTick;
|
|
const dataExpenses = state.data.partnerships.reduce((sum, p) => sum + p.costPerTick, 0);
|
|
|
|
const bestCapability = state.models.bestDeployedModelScore;
|
|
const eraIdx = ['startup', 'scaleup', 'bigtech', 'agi'].indexOf(state.meta.currentEra);
|
|
const complianceCost = bestCapability > 30 ? bestCapability * REGULATION_COMPLIANCE_PER_CAPABILITY * (1 + eraIdx * 0.5) / 100 : 0;
|
|
|
|
const devRelExpenses = state.market.developerEcosystem.devRelSpending;
|
|
|
|
let researchExpenses = 0;
|
|
if (state.research.activeResearch) {
|
|
const node = TECH_TREE.find(n => n.id === state.research.activeResearch!.researchId);
|
|
if (node) {
|
|
researchExpenses = node.cost.money / node.cost.ticks;
|
|
}
|
|
}
|
|
|
|
const expenses = infraExpenses + talentExpenses + dataExpenses + complianceCost + devRelExpenses + researchExpenses + extraCosts;
|
|
|
|
const money = state.economy.money + revenue - expenses;
|
|
|
|
const financialHistory = [...state.economy.financialHistory];
|
|
if (state.meta.tickCount % FINANCIAL_SNAPSHOT_INTERVAL === 0) {
|
|
financialHistory.push({
|
|
tick: state.meta.tickCount,
|
|
money,
|
|
revenue,
|
|
expenses,
|
|
valuation: state.economy.funding.valuation,
|
|
});
|
|
if (financialHistory.length > MAX_FINANCIAL_HISTORY) {
|
|
financialHistory.shift();
|
|
}
|
|
}
|
|
|
|
return {
|
|
...state.economy,
|
|
money: Math.max(0, money),
|
|
totalRevenue: state.economy.totalRevenue + revenue,
|
|
totalExpenses: state.economy.totalExpenses + expenses,
|
|
revenuePerTick: revenue,
|
|
expensesPerTick: expenses,
|
|
financialHistory,
|
|
};
|
|
}
|