Overhaul market system with shared TAM competition, multi-tier pricing, enterprise pipeline, and developer ecosystem
CI / build-and-push (push) Successful in 42s

Replaces the simplified single-subscriber market with a full competitive simulation:
shared TAM with softmax market shares across 4 segments, multi-tier consumer
subscriptions (Free/Plus/Pro/Team) and API tiers (Free/PAYG/Scale/Enterprise),
enterprise sales pipeline (Lead→Qualification→POC→Negotiation→Active→Renewal)
with SLA tracking, developer ecosystem flywheel, technology obsolescence pressure,
seasonal demand cycles, and two new product lines (Code Assistant, AI Agents Platform).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-25 08:30:24 -04:00
parent 4c1c0e9ff2
commit 09a5cb69a7
34 changed files with 2851 additions and 408 deletions
@@ -1,4 +1,6 @@
import type { DCTier, DCTierConfig, RackSkuId, RackSkuConfig, SwitchTier, SwitchTierConfig, CampusTierCost, ClusterCostConfig, CoolingType, CoolingTypeConfig, NetworkFabric, NetworkFabricConfig } from '../types/infrastructure';
import type { Era } from '../types/gameState';
import type { ConsumerTierId, ApiTierId, SeasonalPhase, EnterprisePipelineStage, EnterpriseSegment, TAMSegmentId } from '../types/market';
export const TICK_INTERVAL_MS = 1000;
export const MAX_OFFLINE_TICKS = 86_400;
@@ -776,3 +778,214 @@ export const REGULATION_COMPLIANCE_PER_CAPABILITY = 0.5;
export const SAFETY_INCIDENT_PROBABILITY_BASE = 0.0002;
export const SAFETY_INCIDENT_REPUTATION_HIT = 15;
export const LOW_SAFETY_THRESHOLD = 40;
// ========================================================================
// MARKET SYSTEM v2 — Shared TAM, Tiered Products, Enterprise Pipeline
// ========================================================================
// --- Shared TAM ---
export const TAM_BASE_SIZES: Record<Era, Record<TAMSegmentId, number>> = {
startup: { consumer: 50_000, developer: 5_000, enterprise: 500, government: 50 },
scaleup: { consumer: 5_000_000, developer: 200_000, enterprise: 5_000, government: 500 },
bigtech: { consumer: 50_000_000, developer: 2_000_000, enterprise: 50_000, government: 5_000 },
agi: { consumer: 500_000_000, developer: 20_000_000, enterprise: 200_000, government: 20_000 },
};
export const TAM_GROWTH_PER_TICK = 0.0001;
export const SHARE_TEMPERATURE = 4.0;
export const SHARE_MIGRATION_SPEED = 0.03;
// --- Attractiveness Weights ---
export const ATTRACTIVENESS_WEIGHTS: Record<TAMSegmentId, Record<string, number>> = {
consumer: { quality: 0.30, price: 0.35, reputation: 0.15, ecosystem: 0.05, freshness: 0.10, freeTier: 0.05 },
developer: { quality: 0.25, price: 0.25, reputation: 0.10, ecosystem: 0.25, freshness: 0.10, freeTier: 0.05 },
enterprise: { quality: 0.35, price: 0.15, reputation: 0.25, ecosystem: 0.10, freshness: 0.10, freeTier: 0.05 },
government: { quality: 0.25, price: 0.10, reputation: 0.35, ecosystem: 0.05, freshness: 0.10, freeTier: 0.15 },
};
// --- Consumer Tier Defaults ---
export const CONSUMER_TIER_DEFAULTS: Record<ConsumerTierId, { price: number; tokenAllowance: number; requiredQuality: number }> = {
free: { price: 0, tokenAllowance: 5_000, requiredQuality: 0 },
plus: { price: 20, tokenAllowance: 50_000, requiredQuality: 20 },
pro: { price: 50, tokenAllowance: 200_000, requiredQuality: 40 },
team: { price: 30, tokenAllowance: 100_000, requiredQuality: 30 },
};
export const CONSUMER_TIER_ORDER: ConsumerTierId[] = ['free', 'plus', 'pro', 'team'];
export const CONVERSION_RATES: Record<string, number> = {
'free->plus': 0.002,
'plus->pro': 0.0008,
'pro->team': 0.0003,
};
export const TIER_CHURN_RATES: Record<ConsumerTierId, number> = {
free: 0.0005,
plus: 0.001,
pro: 0.0006,
team: 0.0004,
};
export const FREE_TIER_ADOPTION_RATE = 0.05;
// --- API Tier Defaults ---
export const API_TIER_DEFAULTS: Record<ApiTierId, { monthlyFee: number; inputPrice: number; outputPrice: number; rateLimit: number }> = {
free: { monthlyFee: 0, inputPrice: 0, outputPrice: 0, rateLimit: 10 },
payg: { monthlyFee: 0, inputPrice: 1.0, outputPrice: 3.0, rateLimit: 100 },
scale: { monthlyFee: 500, inputPrice: 0.8, outputPrice: 2.4, rateLimit: 1000 },
'enterprise-api': { monthlyFee: 5000, inputPrice: 0.6, outputPrice: 1.8, rateLimit: 10000 },
};
export const API_TIER_ORDER: ApiTierId[] = ['free', 'payg', 'scale', 'enterprise-api'];
export const API_TIER_CHURN_RATES: Record<ApiTierId, number> = {
free: 0.0003,
payg: 0.001,
scale: 0.0005,
'enterprise-api': 0.0003,
};
export const API_CONVERSION_RATES: Record<string, number> = {
'free->payg': 0.003,
'payg->scale': 0.001,
'scale->enterprise-api': 0.0004,
};
export const API_TOKENS_PER_DEVELOPER_PER_TICK: Record<ApiTierId, number> = {
free: 0.5,
payg: 5,
scale: 50,
'enterprise-api': 200,
};
// --- Code Assistant ---
export const CODE_ASSISTANT_MIN_CODING_SCORE = 40;
export const CODE_ASSISTANT_DEFAULT_PRICE = 20;
export const CODE_ASSISTANT_BASE_ADOPTION_RATE = 0.003;
export const CODE_ASSISTANT_CHURN_RATE = 0.0008;
// --- Agents Platform ---
export const AGENTS_PLATFORM_MIN_AGENTS_SCORE = 50;
export const AGENTS_PLATFORM_DEFAULT_PRICE = 100;
export const AGENTS_PLATFORM_BASE_ADOPTION_RATE = 0.002;
export const AGENTS_PLATFORM_CHURN_RATE = 0.0005;
// --- Enterprise Pipeline ---
export const BASE_LEAD_RATE = 0.005;
export const LEAD_EXPIRY_TICKS = 600;
export const PIPELINE_STAGE_TIMEOUTS: Record<EnterprisePipelineStage, number> = {
lead: 300,
qualification: 200,
poc: 400,
negotiation: 300,
};
export const PIPELINE_TRANSITION_RATES: Record<string, number> = {
'lead->qualification': 0.02,
'qualification->poc': 0.015,
'poc->negotiation': 0.01,
'negotiation->active': 0.008,
};
export const SLA_PENALTY_FRACTION = 0.02;
export const CONTRACT_BASE_DURATION_TICKS = 2400;
export const ENTERPRISE_DEAL_VALUES: Record<EnterpriseSegment, { min: number; max: number }> = {
startup: { min: 5_000, max: 50_000 },
'mid-market': { min: 50_000, max: 500_000 },
enterprise: { min: 500_000, max: 5_000_000 },
government: { min: 1_000_000, max: 10_000_000 },
};
export const ENTERPRISE_SLA_REQUIREMENTS: Record<EnterpriseSegment, number> = {
startup: 0.95,
'mid-market': 0.97,
enterprise: 0.99,
government: 0.995,
};
export const ENTERPRISE_CAPABILITY_REQUIREMENTS: Record<EnterpriseSegment, number> = {
startup: 15,
'mid-market': 30,
enterprise: 50,
government: 45,
};
export const ENTERPRISE_TOKENS_PER_TICK: Record<EnterpriseSegment, { min: number; max: number }> = {
startup: { min: 50, max: 500 },
'mid-market': { min: 500, max: 5_000 },
enterprise: { min: 5_000, max: 50_000 },
government: { min: 2_000, max: 20_000 },
};
export const CONTRACT_DURATION_BY_SEGMENT: Record<EnterpriseSegment, number> = {
startup: 1200,
'mid-market': 2400,
enterprise: 4800,
government: 7200,
};
// --- Developer Ecosystem ---
export const BASE_DEV_GROWTH = 0.001;
export const FREE_TIER_DEV_MULTIPLIER = 0.0005;
export const OPEN_SOURCE_DEV_BOOST = 0.05;
export const DEV_REL_EFFECTIVENESS = 0.00001;
export const SDK_GROWTH_BONUS = 0.01;
export const DEV_ECOSYSTEM_WEIGHTS = {
communitySize: 0.30,
activeRatio: 0.20,
sdkCoverage: 0.20,
docQuality: 0.15,
openSource: 0.15,
};
export const STARTUP_ADOPTION_PER_DEV = 0.005;
export const ENTERPRISE_REFERRAL_PER_STARTUP = 0.01;
// --- Seasonal Demand ---
export const SEASONAL_CYCLE_TICKS = 360;
export const SEASONAL_MULTIPLIERS: Record<SeasonalPhase, Record<string, number>> = {
q1: { consumer: 0.90, api: 0.85, enterprise: 0.75 },
q2: { consumer: 1.00, api: 1.00, enterprise: 1.00 },
q3: { consumer: 0.95, api: 0.95, enterprise: 0.85 },
q4: { consumer: 1.10, api: 1.05, enterprise: 1.40 },
};
// --- Technology Obsolescence ---
export const OBSOLESCENCE_BASELINE_GROWTH = 0.01;
export const OBSOLESCENCE_ERA_ACCELERATOR: Record<Era, number> = {
startup: 1,
scaleup: 1.5,
bigtech: 2.5,
agi: 4,
};
export const FRESHNESS_DECAY_RATE = 0.001;
export const NEW_MODEL_BOOST_VALUE = 0.15;
export const NEW_MODEL_BOOST_TICKS = 200;
export const OBSOLESCENCE_PENALTY_WEIGHT = 0.5;
// --- Competitor Market Behavior ---
export const COMPETITOR_PRODUCT_THRESHOLDS = {
freeTierAndChat: 20,
apiAndCodeAssistant: 40,
proTierAndEnterprise: 60,
agentsPlatform: 80,
};
export const COMPETITOR_CATCHUP_SHARE_THRESHOLD = 0.05;
export const COMPETITOR_CATCHUP_PRICE_CUT = 0.3;
+23
View File
@@ -16,6 +16,13 @@ export interface Competitor {
latestModelName: string;
completedMilestones: string[];
nextMilestoneAtTick: number;
products: CompetitorProducts;
pricingStrategy: CompetitorPricing;
modelFreshness: number;
lastModelReleaseTick: number;
developerEcosystemScore: number;
marketShares: Record<string, number>;
}
export type CompetitorArchetype = 'safety-first' | 'move-fast' | 'big-tech' | 'open-source' | 'stealth-startup';
@@ -29,6 +36,22 @@ export interface CompetitorPersonality {
riskTolerance: number;
}
export interface CompetitorProducts {
hasFreeTier: boolean;
chatPrice: number;
apiInputPrice: number;
apiOutputPrice: number;
hasCodeAssistant: boolean;
codeAssistantPrice: number;
hasAgentsPlatform: boolean;
agentsPlatformPrice: number;
}
export interface CompetitorPricing {
aggressiveness: number;
premiumPositioning: number;
}
export const INITIAL_COMPETITORS: CompetitorState = {
rivals: [],
industryBenchmark: 0,
+1 -1
View File
@@ -58,4 +58,4 @@ export const INITIAL_SETTINGS: GameSettings = {
sfxVolume: 0.7,
};
export const SAVE_VERSION = 6;
export const SAVE_VERSION = 7;
+279 -29
View File
@@ -1,48 +1,177 @@
export interface MarketState {
consumers: ConsumerMarket;
enterprise: EnterpriseMarket;
overloadPolicy: OverloadPolicy;
openSourcedModels: string[];
subscriberHistory: { tick: number; subscribers: number }[];
import type { Era } from './gameState';
// --- Seasonal ---
export type SeasonalPhase = 'q1' | 'q2' | 'q3' | 'q4';
// --- TAM (Total Addressable Market) ---
export type TAMSegmentId = 'consumer' | 'developer' | 'enterprise' | 'government';
export interface TAMSegment {
totalSize: number;
shares: MarketShareEntry[];
}
export interface ConsumerMarket {
totalSubscribers: number;
churnRatePerTick: number;
growthRatePerTick: number;
export interface MarketShareEntry {
playerId: string;
sharePercent: number;
customers: number;
attractivenessScore: number;
}
export interface TotalAddressableMarket {
segments: Record<TAMSegmentId, TAMSegment>;
}
// --- Consumer Tiers ---
export type ConsumerTierId = 'free' | 'plus' | 'pro' | 'team';
export interface ConsumerTierConfig {
id: ConsumerTierId;
name: string;
price: number;
tokenAllowance: number;
requiredModelQuality: number;
isActive: boolean;
}
export interface ConsumerTierRuntime {
config: ConsumerTierConfig;
userCount: number;
conversionRateFromBelow: number;
churnRate: number;
}
export interface ConsumerTierState {
tiers: Record<ConsumerTierId, ConsumerTierRuntime>;
totalUsers: number;
satisfaction: number;
viralCoefficient: number;
}
export interface EnterpriseMarket {
activeContracts: EnterpriseContract[];
pendingRFPs: EnterpriseRFP[];
totalApiCallsPerTick: number;
averageTokensPerCall: number;
// --- API Tiers ---
export type ApiTierId = 'free' | 'payg' | 'scale' | 'enterprise-api';
export interface ApiTierConfig {
id: ApiTierId;
name: string;
monthlyFee: number;
inputTokenPrice: number;
outputTokenPrice: number;
rateLimit: number;
isActive: boolean;
}
export interface ApiTierRuntime {
config: ApiTierConfig;
developerCount: number;
tokensPerTick: number;
churnRate: number;
}
export interface ApiTierState {
tiers: Record<ApiTierId, ApiTierRuntime>;
totalDevelopers: number;
totalTokensPerTick: number;
}
// --- New Product Lines ---
export interface CodeAssistantState {
isUnlocked: boolean;
isActive: boolean;
pricePerSeat: number;
seats: number;
qualityScore: number;
satisfaction: number;
}
export interface AgentsPlatformState {
isUnlocked: boolean;
isActive: boolean;
pricePerSeat: number;
seats: number;
qualityScore: number;
satisfaction: number;
}
// --- Enterprise Pipeline ---
export type EnterprisePipelineStage = 'lead' | 'qualification' | 'poc' | 'negotiation';
export type EnterpriseSegment = 'startup' | 'mid-market' | 'enterprise' | 'government';
export interface EnterpriseLead {
id: string;
companyName: string;
segment: EnterpriseSegment;
stage: EnterprisePipelineStage;
enteredStageAtTick: number;
dealValue: number;
tokensPerTick: number;
requiredCapability: number;
requiredSlaUptime: number;
requiredSafetyScore: number;
winProbability: number;
expiresAtTick: number;
}
export interface EnterpriseContract {
id: string;
customerName: string;
segment: 'startup' | 'mid-market' | 'enterprise' | 'government';
segment: EnterpriseSegment;
tokensPerTick: number;
pricePerMToken: number;
slaUptime: number;
startTick: number;
durationTicks: number;
satisfaction: number;
renewalProbability: number;
slaViolations: number;
slaPenaltiesPaid: number;
uptimeTicks: number;
totalTicks: number;
}
export interface EnterpriseRFP {
id: string;
customerName: string;
segment: 'startup' | 'mid-market' | 'enterprise' | 'government';
requiredCapability: number;
offeredPricePerMToken: number;
requiredSlaUptime: number;
expiresAtTick: number;
export interface EnterpriseState {
pipeline: EnterpriseLead[];
activeContracts: EnterpriseContract[];
totalApiCallsPerTick: number;
averageTokensPerCall: number;
leadGenerationRate: number;
}
// --- Developer Ecosystem ---
export interface DeveloperEcosystem {
communitySize: number;
activeDevelopers: number;
sdkCoverage: number;
documentationQuality: number;
openSourceContributions: number;
devRelSpending: number;
communityGrowthRate: number;
ecosystemScore: number;
startupsAdopted: number;
enterpriseReferrals: number;
}
// --- Technology Obsolescence ---
export interface ObsolescenceState {
marketQualityBaseline: number;
baselineGrowthRate: number;
playerModelFreshness: number;
lastModelReleaseTick: number;
freshnessDecayRate: number;
newModelBoostRemaining: number;
}
// --- Overload Policy (kept from original) ---
export interface OverloadPolicy {
maxQueueDepth: number;
rateLimitPerCustomer: number;
@@ -50,19 +179,140 @@ export interface OverloadPolicy {
prioritizeEnterprise: boolean;
}
// --- Root Market State ---
export interface MarketState {
tam: TotalAddressableMarket;
consumerTiers: ConsumerTierState;
apiTiers: ApiTierState;
codeAssistant: CodeAssistantState;
agentsPlatform: AgentsPlatformState;
enterprise: EnterpriseState;
developerEcosystem: DeveloperEcosystem;
seasonalPhase: SeasonalPhase;
seasonalMultiplier: number;
obsolescence: ObsolescenceState;
overloadPolicy: OverloadPolicy;
openSourcedModels: string[];
subscriberHistory: { tick: number; subscribers: number }[];
}
// --- Initial State ---
function makeInitialTAMSegment(): TAMSegment {
return {
totalSize: 0,
shares: [
{ playerId: 'player', sharePercent: 0, customers: 0, attractivenessScore: 0 },
],
};
}
function makeConsumerTierRuntime(
id: ConsumerTierId,
name: string,
price: number,
tokenAllowance: number,
requiredModelQuality: number,
): ConsumerTierRuntime {
return {
config: { id, name, price, tokenAllowance, requiredModelQuality, isActive: id === 'free' },
userCount: 0,
conversionRateFromBelow: 0,
churnRate: 0,
};
}
function makeApiTierRuntime(
id: ApiTierId,
name: string,
monthlyFee: number,
inputTokenPrice: number,
outputTokenPrice: number,
rateLimit: number,
): ApiTierRuntime {
return {
config: { id, name, monthlyFee, inputTokenPrice, outputTokenPrice, rateLimit, isActive: id === 'free' },
developerCount: 0,
tokensPerTick: 0,
churnRate: 0,
};
}
export const INITIAL_MARKET: MarketState = {
consumers: {
totalSubscribers: 0,
churnRatePerTick: 0.001,
growthRatePerTick: 0,
tam: {
segments: {
consumer: makeInitialTAMSegment(),
developer: makeInitialTAMSegment(),
enterprise: makeInitialTAMSegment(),
government: makeInitialTAMSegment(),
},
},
consumerTiers: {
tiers: {
free: makeConsumerTierRuntime('free', 'Free', 0, 5_000, 0),
plus: makeConsumerTierRuntime('plus', 'Plus', 20, 50_000, 20),
pro: makeConsumerTierRuntime('pro', 'Pro', 50, 200_000, 40),
team: makeConsumerTierRuntime('team', 'Team', 30, 100_000, 30),
},
totalUsers: 0,
satisfaction: 0.5,
viralCoefficient: 0,
},
apiTiers: {
tiers: {
free: makeApiTierRuntime('free', 'Free', 0, 0, 0, 10),
payg: makeApiTierRuntime('payg', 'Pay-as-you-go', 0, 1.0, 3.0, 100),
scale: makeApiTierRuntime('scale', 'Scale', 500, 0.8, 2.4, 1000),
'enterprise-api': makeApiTierRuntime('enterprise-api', 'Enterprise API', 5000, 0.6, 1.8, 10000),
},
totalDevelopers: 0,
totalTokensPerTick: 0,
},
codeAssistant: {
isUnlocked: false,
isActive: false,
pricePerSeat: 20,
seats: 0,
qualityScore: 0,
satisfaction: 0,
},
agentsPlatform: {
isUnlocked: false,
isActive: false,
pricePerSeat: 100,
seats: 0,
qualityScore: 0,
satisfaction: 0,
},
enterprise: {
pipeline: [],
activeContracts: [],
pendingRFPs: [],
totalApiCallsPerTick: 0,
averageTokensPerCall: 500,
leadGenerationRate: 0,
},
developerEcosystem: {
communitySize: 0,
activeDevelopers: 0,
sdkCoverage: 0,
documentationQuality: 0.1,
openSourceContributions: 0,
devRelSpending: 0,
communityGrowthRate: 0,
ecosystemScore: 0,
startupsAdopted: 0,
enterpriseReferrals: 0,
},
seasonalPhase: 'q2',
seasonalMultiplier: 1.0,
obsolescence: {
marketQualityBaseline: 0,
baselineGrowthRate: 0.01,
playerModelFreshness: 0,
lastModelReleaseTick: 0,
freshnessDecayRate: 0.001,
newModelBoostRemaining: 0,
},
overloadPolicy: {
maxQueueDepth: 100,