0ff8a32b95
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>
174 lines
5.6 KiB
TypeScript
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;
|
|
}
|