Files
AIHostingTycoon/packages/game-engine/src/tick.ts
T
josh 0ff8a32b95 Add Week 4 social features, regulation, and safety tradeoffs
Leaderboard page with category tabs and score submission, shareable
company stats card with clipboard copy, dynamic regulation system
(compliance costs scale with capability and era, regulatory standing
tracks safety research), 6 geopolitical events (export controls, energy
crisis, natural disaster, AI safety summit, immigration policy, data
sovereignty), safety-capability tradeoff (safety score affects benchmark,
low safety triggers incidents with reputation damage), and enhanced
event consequence handling for regulation and talent types.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-24 18:02:30 -04:00

174 lines
5.6 KiB
TypeScript

import type { GameState, EventDefinition, AchievementDefinition } from '@ai-tycoon/shared';
import { processEconomy } from './systems/economySystem';
import { processInfrastructure } from './systems/infrastructureSystem';
import { processCompute } from './systems/computeSystem';
import { processResearch } from './systems/researchSystem';
import { processModels } from './systems/modelSystem';
import { processMarket } from './systems/marketSystem';
import { processReputation } from './systems/reputationSystem';
import { processTalent } from './systems/talentSystem';
import { processEvents } from './systems/eventSystem';
import { processCompetitors } from './systems/competitorSystem';
import { processData } from './systems/dataSystem';
import { checkEraTransition } from './systems/eraSystem';
import { processAchievements } from './systems/achievementSystem';
import { computeValuation } from './systems/fundingSystem';
export interface TickResult {
state: Partial<GameState>;
notifications: TickNotification[];
}
export interface TickNotification {
title: string;
message: string;
type: 'info' | 'success' | 'warning' | 'danger';
}
let cachedEventDefs: EventDefinition[] | null = null;
let cachedAchievementDefs: AchievementDefinition[] | null = null;
export function setEventDefinitions(defs: EventDefinition[]) {
cachedEventDefs = defs;
}
export function setAchievementDefinitions(defs: AchievementDefinition[]) {
cachedAchievementDefs = defs;
}
export function processTick(state: GameState): Partial<GameState> {
const notifications: TickNotification[] = [];
const infrastructure = processInfrastructure(state);
const stateWithInfra = { ...state, infrastructure };
const modelResult = processModels(stateWithInfra);
if (modelResult.modelCompleted) {
notifications.push({
title: 'Training Complete',
message: `${modelResult.modelCompleted.name} is ready! Benchmark: ${modelResult.modelCompleted.benchmarkScore.toFixed(1)}/100`,
type: 'success',
});
}
const stateWithModels = { ...stateWithInfra, models: modelResult.modelsState };
const market = processMarket(stateWithModels, state.compute);
const compute = processCompute(state, infrastructure);
compute.tokensPerSecondDemand = market.totalTokenDemand;
compute.inferenceUtilization = compute.tokensPerSecondCapacity > 0
? Math.min(1, market.totalTokenDemand / compute.tokensPerSecondCapacity)
: 0;
const talent = processTalent(stateWithModels);
const stateWithTalent = { ...stateWithModels, talent };
const researchResult = processResearch(stateWithTalent, compute);
if (researchResult.researchCompleted) {
notifications.push({
title: 'Research Complete',
message: `${researchResult.researchCompleted} has been unlocked!`,
type: 'success',
});
}
const reputationResult = processReputation(stateWithTalent);
const { _safetyIncident, ...reputation } = reputationResult;
if (_safetyIncident) {
notifications.push({
title: 'Safety Incident!',
message: 'Your AI model caused a safety incident. Public trust and safety record damaged.',
type: 'danger',
});
}
const economy = processEconomy(stateWithTalent, market, infrastructure);
const data = processData(stateWithTalent);
const competitors = processCompetitors(stateWithTalent);
const eventResult = cachedEventDefs
? processEvents(stateWithTalent, cachedEventDefs)
: { events: state.events, newEvents: [] };
for (const evt of eventResult.newEvents) {
notifications.push({
title: evt.title,
message: evt.description,
type: evt.category === 'regulatory' ? 'warning' : 'info',
});
}
const tickCount = state.meta.tickCount + 1;
let meta = {
...state.meta,
tickCount,
lastTickTimestamp: Date.now(),
totalPlayTime: state.meta.totalPlayTime + 1,
};
const newEra = checkEraTransition({ ...stateWithTalent, economy, reputation, research: researchResult.research });
if (newEra) {
meta = { ...meta, currentEra: newEra };
notifications.push({
title: 'Era Transition!',
message: `Your company has entered the ${newEra === 'scaleup' ? 'Scale-up' : newEra === 'bigtech' ? 'Big Tech' : 'AGI'} era!`,
type: 'success',
});
}
const valuation = computeValuation({ ...stateWithTalent, economy, reputation, research: researchResult.research });
const updatedEconomy = {
...economy,
funding: { ...economy.funding, valuation },
};
const stateForAchievements: GameState = {
...stateWithTalent,
meta,
economy: updatedEconomy,
infrastructure,
compute,
research: researchResult.research,
models: modelResult.modelsState,
market: market.marketState,
reputation,
data,
competitors,
events: eventResult.events,
achievements: state.achievements,
};
const achievementResult = cachedAchievementDefs
? processAchievements(stateForAchievements, cachedAchievementDefs)
: { achievements: state.achievements, newAchievements: [] };
for (const name of achievementResult.newAchievements) {
notifications.push({
title: 'Achievement Unlocked!',
message: name,
type: 'success',
});
}
const result: Partial<GameState> = {
meta,
economy: updatedEconomy,
infrastructure,
compute,
research: researchResult.research,
models: modelResult.modelsState,
market: market.marketState,
talent,
reputation,
data,
competitors,
events: eventResult.events,
achievements: achievementResult.achievements,
};
(result as Record<string, unknown>)['_notifications'] = notifications;
return result;
}