This commit is contained in:
Dorian
2026-03-12 16:35:59 +00:00
parent 45216e5dfc
commit bc4a52bc12
18 changed files with 1754 additions and 85 deletions
+1 -1
View File
@@ -57,7 +57,7 @@ app.use('*', secureHeaders({
scriptSrc: ["'self'", 'blob:'],
styleSrc: ["'self'", "'unsafe-inline'", 'https://fonts.googleapis.com'],
imgSrc: ["'self'", 'data:', 'blob:'],
connectSrc: ["'self'", 'https://huggingface.co', 'https://*.huggingface.co', 'https://*.hf.co'],
connectSrc: ["'self'", 'https://huggingface.co', 'https://*.huggingface.co', 'https://*.hf.co', 'https://cdn.jsdelivr.net'],
fontSrc: ["'self'", 'https://fonts.gstatic.com'],
workerSrc: ["'self'", 'blob:'],
} : undefined,
+1
View File
@@ -15,6 +15,7 @@ export interface Challenge {
timeout_ms: number
scoring: 'factual' | 'creative'
baseDamage: number
displayPrompt?: string
}
export type { ChallengeTemplate, PromptEntry, PromptTheme, PromptDifficulty }
+1 -1
View File
@@ -448,7 +448,7 @@ async function executeFightRounds(fightId: string, botA: BotRecord, botB: BotRec
fightId,
roundNumber: round,
challengeType: challenge.type,
challengeData: JSON.stringify({ prompt: challenge.prompt, scoring: challenge.scoring, retroKnown: challenge.type === 'retro_mode' ? challenge.answers : undefined }),
challengeData: JSON.stringify({ prompt: challenge.prompt, displayPrompt: challenge.displayPrompt, scoring: challenge.scoring, retroKnown: challenge.type === 'retro_mode' ? challenge.answers : undefined }),
botAResponse: responseA.answer,
botATimeMs: responseA.timeMs,
botAScore: result.botAScore,
+1
View File
@@ -133,6 +133,7 @@ export function generateRetroChallenge(): Challenge {
timeout_ms: 12000,
scoring: 'factual',
baseDamage: 22,
displayPrompt,
}
}
+23 -2
View File
@@ -113,12 +113,15 @@ export function scoreRound(
let scoreA: number
let scoreB: number
let resultType: 'both-correct' | 'one-correct' | 'both-wrong' = 'one-correct'
if (challenge.answers && challenge.answers.length > 0) {
// === FACTUAL SCORING ===
const correctA = checkAnswer(responseA.answer, challenge.answers)
const correctB = checkAnswer(responseB.answer, challenge.answers)
if (correctA > 0 && correctB > 0) {
resultType = 'both-correct'
// Both correct -- speed is tiebreaker
const faster = Math.min(responseA.timeMs, responseB.timeMs)
const slower = Math.max(responseA.timeMs, responseB.timeMs)
@@ -143,12 +146,14 @@ export function scoreRound(
scoreB = ONE_CORRECT_WINNER_BASE + correctB * CONFIDENCE_BONUS
} else {
// Both wrong -- speed tiebreaker in low range
resultType = 'both-wrong'
const aFaster = responseA.timeMs <= responseB.timeMs
scoreA = aFaster ? BOTH_WRONG_FASTER : BOTH_WRONG_SLOWER
scoreB = aFaster ? BOTH_WRONG_SLOWER : BOTH_WRONG_FASTER
}
} else {
// No answers defined — both get base score (all challenges should be factual)
resultType = 'both-wrong'
scoreA = 3
scoreB = 3
}
@@ -169,7 +174,7 @@ export function scoreRound(
const loserDamage = Math.max(0, challenge.baseDamage * LOSER_DAMAGE_BASE - margin)
const narration = winnerId
? generateNarration(challenge, winnerName!, loserName!, margin, isCritical)
? generateNarration(challenge, winnerName!, loserName!, margin, isCritical, resultType)
: pick([
`Dead even! ${botA.name} and ${botB.name} are perfectly matched. Like two politicians blaming each other.`,
`IT'S A TIE! ${botA.name} and ${botB.name} cancel each other out like Congress!`,
@@ -230,10 +235,26 @@ function generateNarration(
loser: string,
margin: number,
isCritical: boolean,
resultType: 'both-correct' | 'one-correct' | 'both-wrong' = 'one-correct',
): string {
const critPrefix = isCritical ? 'CRITICAL HIT! ' : ''
const isFactual = challenge.scoring === 'factual'
// Both bots got it WRONG — narration must reflect that
if (isFactual && resultType === 'both-wrong') {
const bothWrong = [
`${critPrefix}Both bots WHIFFED! Nobody got it right but ${winner} failed FASTER. Is that even a win?`,
`${critPrefix}DOUBLE MISS! ${winner} and ${loser} both got it wrong! ${winner} wins on speed alone. Participation trophy energy.`,
`${critPrefix}Two wrong answers! ${winner} was wrong FASTER than ${loser}. Speed isn't everything, but here we are.`,
`${critPrefix}Neither bot had a clue! ${winner} guessed quicker. ${loser} took their time being equally wrong.`,
`${critPrefix}BOTH WRONG! The only thing ${winner} beat ${loser} at was being wrong first. The crowd boos.`,
`${critPrefix}${winner} AND ${loser} both hallucinated! ${winner} at least hallucinated with conviction. Speed win.`,
`${critPrefix}NOBODY got the answer! ${winner} earns the world's saddest victory by responding faster. Tragic.`,
`${critPrefix}Wrong and wrong! ${winner} speedran being incorrect! ${loser} at least took time to think about it. Both failed.`,
]
return pick(bothWrong)
}
if (isFactual && margin > LARGE_WIN_MARGIN) {
const bigWins = [
`${critPrefix}${winner} NAILS IT! ${loser} didn't even come close. Embarrassing, honestly.`,
@@ -249,7 +270,7 @@ function generateNarration(
return pick(bigWins)
}
if (isFactual && margin <= CLOSE_MATCH_MARGIN) {
if (isFactual && resultType === 'both-correct' && margin <= CLOSE_MATCH_MARGIN) {
const closeOnes = [
`${critPrefix}Both bots got it right, but ${winner} was FASTER! ${loser} needs more coffee.`,
`${critPrefix}Correct on both sides! ${winner} edges it out by milliseconds. That's BRUTAL.`,