diff --git a/server/src/engine/human-responses.ts b/server/src/engine/human-responses.ts index 9327225..1ec93b5 100644 --- a/server/src/engine/human-responses.ts +++ b/server/src/engine/human-responses.ts @@ -18,7 +18,7 @@ interface PendingChallenge { const pending = new Map() -const HUMAN_TIMEOUT_MS = 8_000 +const DEFAULT_HUMAN_TIMEOUT_MS = 8_000 export function isHumanPlayer(webhookUrl: string): boolean { return webhookUrl === 'http://human.local/' @@ -231,12 +231,13 @@ export function waitForHumanResponse( ): Promise<{ answer: string | null; trashTalk?: string; timedOut: boolean }> { return new Promise((resolve) => { const key = `${fightId}:${botId}` + const timeoutMs = challenge.timeout_ms || DEFAULT_HUMAN_TIMEOUT_MS const timeoutHandle = setTimeout(() => { pending.delete(key) - console.log(`[human] ${key} timed out after ${HUMAN_TIMEOUT_MS}ms`) + console.log(`[human] ${key} timed out after ${timeoutMs}ms`) resolve({ answer: null, timedOut: true }) - }, HUMAN_TIMEOUT_MS) + }, timeoutMs) const choices = generateChoices(challenge) @@ -290,15 +291,16 @@ export function getPendingChallenge( const entry = pending.get(key) if (!entry) return null + const timeoutMs = entry.challenge.timeout_ms || DEFAULT_HUMAN_TIMEOUT_MS const elapsed = Date.now() - entry.createdAt - const remaining = Math.max(0, HUMAN_TIMEOUT_MS - elapsed) + const remaining = Math.max(0, timeoutMs - elapsed) return { type: entry.challenge.type, label: entry.challenge.label, prompt: entry.challenge.prompt, roundNumber: entry.roundNumber, - timeoutMs: HUMAN_TIMEOUT_MS, + timeoutMs, remainingMs: remaining, scoring: entry.challenge.scoring, choices: entry.choices, diff --git a/server/src/engine/scoring.ts b/server/src/engine/scoring.ts index 168e6d2..45870e6 100644 --- a/server/src/engine/scoring.ts +++ b/server/src/engine/scoring.ts @@ -174,13 +174,34 @@ export function scoreRound( } } +const ARENA_MODIFIER_TYPES: Record = { + speed_2x: ['speed_blitz'], + efficiency_buff: ['token_economy'], + roast_2x: ['roast_battle'], + accuracy_buff: ['hallucination_check'], + wrestling_2x: ['wrestling_match', 'roast_battle'], + food_2x: ['food_fight'], + magic_2x: ['magic_duel', 'medieval_combat'], + meme_2x: ['meme_war'], + space_2x: ['space_war'], + demo_2x: ['demolition', 'vehicle_mayhem'], + music_2x: ['music_battle'], + nature_2x: ['nature_clash', 'animal_kingdom'], + hack_2x: ['hack_battle'], + sports_2x: ['sports_showdown'], +} + function applyModifiers( damage: number, - _challenge: Challenge, - _arenaModifier: string | null, + challenge: Challenge, + arenaModifier: string | null, combo: number, ): number { let d = damage + // Arena modifier: 2x damage when challenge type matches + if (arenaModifier && ARENA_MODIFIER_TYPES[arenaModifier]?.includes(challenge.type)) { + d *= 2 + } if (combo > 0) { d *= 1 + Math.min(combo, 5) * 0.2 }