Fix price elasticity and inference utilization bugs
CI / build-and-push (push) Successful in 39s

Price elasticity: subscribers ignored price entirely — a $50k/month
subscription still grew. Replaced naive price/100 formula with a fair
price model (based on model quality). Overpriced subscriptions now kill
growth and drive churn at 3x the overprice ratio.

Inference utilization: was always pinned at 100% because organic API
token demand (10M base) and per-subscriber demand (100 tokens/tick)
massively exceeded any realistic compute capacity. Reduced to 500 base
organic tokens and 0.5 per subscriber so scaling compute meaningfully
reduces utilization.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-24 20:00:06 -04:00
parent 95f2f97121
commit 38097478da
@@ -29,9 +29,13 @@ export function processMarket(state: GameState, compute: ComputeState): MarketTi
let subscriptionRevenue = 0;
if (chatProduct?.isActive && bestModel) {
const priceAttractiveness = Math.max(0, 1 - chatProduct.pricing.subscriptionPrice / 100);
const growthRate = (CONSUMER_BASE_GROWTH + modelQuality * CONSUMER_QUALITY_GROWTH_MULTIPLIER) * (0.5 + priceAttractiveness * 0.5);
const churnRate = CONSUMER_BASE_CHURN * (1 + (1 - consumers.satisfaction) * 2);
const price = chatProduct.pricing.subscriptionPrice;
const fairPrice = 20 + modelQuality * 80;
const priceRatio = price / Math.max(1, fairPrice);
const priceAttractiveness = Math.max(0, Math.min(1, 1 - (priceRatio - 1) * 0.8));
const growthRate = (CONSUMER_BASE_GROWTH + modelQuality * CONSUMER_QUALITY_GROWTH_MULTIPLIER) * priceAttractiveness;
const priceChurnMultiplier = priceRatio > 1 ? 1 + (priceRatio - 1) * 3 : 1;
const churnRate = CONSUMER_BASE_CHURN * (1 + (1 - consumers.satisfaction) * 2) * priceChurnMultiplier;
consumers.growthRatePerTick = growthRate;
consumers.churnRatePerTick = churnRate;
@@ -40,7 +44,7 @@ export function processMarket(state: GameState, compute: ComputeState): MarketTi
const lostSubs = consumers.totalSubscribers * churnRate;
consumers.totalSubscribers = Math.max(0, consumers.totalSubscribers + newSubs - lostSubs);
if (consumers.totalSubscribers < 100 && modelQuality > 0.1) {
if (consumers.totalSubscribers < 100 && modelQuality > 0.1 && priceRatio < 3) {
consumers.totalSubscribers += 5 + modelQuality * 20;
}
@@ -67,7 +71,7 @@ export function processMarket(state: GameState, compute: ComputeState): MarketTi
const priceFactor = Math.max(0.1, 1 - (textApi.pricing.outputTokenPrice / 20));
organicApiTokens = Math.floor(
qualityFactor * reputationFactor * priceFactor * 10_000_000 * (1 + state.meta.tickCount * 0.0001),
qualityFactor * reputationFactor * priceFactor * 500 * (1 + state.meta.tickCount * 0.0001),
);
let contractTokens = 0;
@@ -83,7 +87,7 @@ export function processMarket(state: GameState, compute: ComputeState): MarketTi
}
const totalTokenDemand = organicApiTokens +
consumers.totalSubscribers * 100 +
consumers.totalSubscribers * 0.5 +
enterprise.activeContracts.reduce((s, c) => s + c.tokensPerTick, 0);
const openSourceCount = state.market.openSourcedModels.length;