refactor: use per-word-type tier selection for name generation

Changed from tier-then-mix approach to per-word-type selection:
- Before: Pick one tier, then optionally mix with abacus words
- After: Pick tier independently for adjective and noun

Benefits:
- Simpler, cleaner code
- More natural variety in name combinations
- Adjective and noun can come from different tiers naturally
- Examples: "Grinning Calculator" (emoji + global), "Ancient Smiler" (global + emoji)

Each word still uses weighted selection:
- 70% emoji-specific
- 20% category-specific
- 10% global abacus

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Thomas Hallock
2025-10-15 14:03:14 -05:00
parent 843b45b14e
commit 499ee525a8

View File

@@ -10,7 +10,6 @@ import {
EMOJI_SPECIFIC_WORDS,
EMOJI_TO_THEME,
THEMED_WORD_LISTS,
type ThemedWordList,
} from './themedWords'
// Generic abacus-themed words (used as ultimate fallback)
@@ -125,18 +124,17 @@ const NOUNS = [
]
/**
* Get themed word list for an emoji avatar using probabilistic tier selection
* Select a word list tier using weighted random selection
* Strongly prefers emoji-specific (70%), then category (20%), then global (10%)
* This adds variety while maintaining personality-matched theming
*/
function getThemedWordsForEmoji(emoji: string): ThemedWordList {
function selectWordListTier(emoji: string, wordType: 'adjectives' | 'nouns'): string[] {
// Collect available tiers
const availableTiers: Array<{ weight: number; words: ThemedWordList }> = []
const availableTiers: Array<{ weight: number; words: string[] }> = []
// Emoji-specific tier (70% preference)
const emojiSpecific = EMOJI_SPECIFIC_WORDS[emoji]
if (emojiSpecific) {
availableTiers.push({ weight: 70, words: emojiSpecific })
availableTiers.push({ weight: 70, words: emojiSpecific[wordType] })
}
// Category tier (20% preference)
@@ -144,12 +142,12 @@ function getThemedWordsForEmoji(emoji: string): ThemedWordList {
if (category) {
const categoryTheme = THEMED_WORD_LISTS[category]
if (categoryTheme) {
availableTiers.push({ weight: 20, words: categoryTheme })
availableTiers.push({ weight: 20, words: categoryTheme[wordType] })
}
}
// Global abacus tier (10% preference)
availableTiers.push({ weight: 10, words: { adjectives: ADJECTIVES, nouns: NOUNS } })
availableTiers.push({ weight: 10, words: wordType === 'adjectives' ? ADJECTIVES : NOUNS })
// Weighted random selection
const totalWeight = availableTiers.reduce((sum, tier) => sum + tier.weight, 0)
@@ -163,16 +161,16 @@ function getThemedWordsForEmoji(emoji: string): ThemedWordList {
}
// Fallback (should never reach here)
return { adjectives: ADJECTIVES, nouns: NOUNS }
return wordType === 'adjectives' ? ADJECTIVES : NOUNS
}
/**
* Generate a random player name by combining an adjective and noun
* Optionally themed based on avatar emoji for ultra-personalized names!
* Uses probabilistic tier selection and cross-tier mixing for abacus flavor
* Uses per-word-type probabilistic tier selection for natural variety
*
* @param emoji - Optional emoji avatar to theme the name around
* @returns A creative player name like "Grinning Calculator" or "Lightning Abacist"
* @returns A creative player name like "Grinning Calculator" or "Lightning Smiler"
*/
export function generatePlayerName(emoji?: string): string {
if (!emoji) {
@@ -182,31 +180,13 @@ export function generatePlayerName(emoji?: string): string {
return `${adjective} ${noun}`
}
// Get themed words using probabilistic tier selection
const themedWords = getThemedWordsForEmoji(emoji)
const abacusWords = { adjectives: ADJECTIVES, nouns: NOUNS }
// Select tier independently for each word type
// This creates natural mixing: adjective might be emoji-specific while noun is global
const adjectiveList = selectWordListTier(emoji, 'adjectives')
const nounList = selectWordListTier(emoji, 'nouns')
// 60% chance: Use themed words for both adjective and noun
// 30% chance: Mix themed adjective with abacus noun (infuses abacus flavor)
// 10% chance: Mix abacus adjective with themed noun (infuses abacus flavor)
const mixStrategy = Math.random()
let adjective: string
let noun: string
if (mixStrategy < 0.6) {
// Pure themed
adjective = themedWords.adjectives[Math.floor(Math.random() * themedWords.adjectives.length)]
noun = themedWords.nouns[Math.floor(Math.random() * themedWords.nouns.length)]
} else if (mixStrategy < 0.9) {
// Themed adjective + abacus noun
adjective = themedWords.adjectives[Math.floor(Math.random() * themedWords.adjectives.length)]
noun = abacusWords.nouns[Math.floor(Math.random() * abacusWords.nouns.length)]
} else {
// Abacus adjective + themed noun
adjective = abacusWords.adjectives[Math.floor(Math.random() * abacusWords.adjectives.length)]
noun = themedWords.nouns[Math.floor(Math.random() * themedWords.nouns.length)]
}
const adjective = adjectiveList[Math.floor(Math.random() * adjectiveList.length)]
const noun = nounList[Math.floor(Math.random() * nounList.length)]
return `${adjective} ${noun}`
}