This commit is contained in:
alphanerd2021
2025-03-03 11:40:44 -04:00
parent 9a8dbff54f
commit 5aef1c3767
3 changed files with 88 additions and 46 deletions

View File

@@ -962,6 +962,68 @@ async function generateSocialPost(npcContent, objectId) {
}
}
/**
* Analyzes NPC content and reassigns the biome if needed based on the description
* @param {Object} npcContent - The generated NPC content
* @returns {Object} The appropriate biome for this NPC
*/
function matchBiomeToNpcDescription(npcContent) {
// Get all textual content to analyze
const textToAnalyze = [
npcContent.description,
npcContent.backstory,
npcContent.culturalBackground,
npcContent.currentRole
].join(' ').toLowerCase();
// Define environment keywords for each biome
const biomeKeywords = {
'tropical rainforest': ['jungle', 'rainforest', 'tropical', 'humid', 'lush vegetation', 'tropical forest', 'canopy'],
'desert': ['desert', 'sand', 'dune', 'arid', 'dry', 'barren', 'cactus', 'oasis', 'sandstorm'],
'savanna': ['savanna', 'grassland', 'prairie', 'plains', 'open field', 'savannah'],
'mountain range': ['mountain', 'peak', 'alpine', 'cliff', 'rocky', 'summit', 'highland', 'cave', 'cavern'],
'taiga/boreal forest': ['taiga', 'boreal', 'pine forest', 'coniferous', 'pine', 'spruce', 'fir', 'evergreen'],
'temperate forest': ['temperate forest', 'woodland', 'deciduous', 'oak', 'maple', 'forest', 'woods'],
'coastal region': ['coast', 'beach', 'shore', 'ocean', 'sea', 'aquatic', 'maritime', 'marine', 'underwater', 'coral', 'tide', 'island', 'bay'],
'island': ['island', 'archipelago', 'atoll', 'isolated', 'surrounded by water'],
'tundra': ['tundra', 'snow', 'ice', 'frozen', 'arctic', 'cold', 'frost', 'glacier', 'blizzard', 'winter', 'icy'],
'ancient ruins': ['ruins', 'ancient', 'temple', 'forgotten', 'archaeological', 'historic', 'abandoned', 'stone', 'crumbling']
};
// Count keyword matches for each biome
const biomeScores = {};
Object.keys(biomeKeywords).forEach(biomeName => {
biomeScores[biomeName] = 0;
biomeKeywords[biomeName].forEach(keyword => {
if (textToAnalyze.includes(keyword)) {
biomeScores[biomeName]++;
}
});
});
// Find the biome with the highest score
let bestMatch = null;
let highestScore = 0;
Object.keys(biomeScores).forEach(biomeName => {
if (biomeScores[biomeName] > highestScore) {
highestScore = biomeScores[biomeName];
bestMatch = biomeName;
}
});
// If we have a match with at least one keyword, return that biome
if (bestMatch && highestScore > 0) {
const matchedBiome = EARTH_BIOMES.find(biome => biome.name === bestMatch);
if (matchedBiome) {
return matchedBiome;
}
}
// If no environmental cues found, return a random biome (original behavior)
return EARTH_BIOMES[Math.floor(Math.random() * EARTH_BIOMES.length)];
}
/**
* Main job for generating a single NPC
* Can be triggered daily or on demand
@@ -970,9 +1032,9 @@ Parse.Cloud.job('generateDailyNPC', async (request) => {
try {
logger.info('🚀 Starting daily NPC generation...');
// Select a random biome and location for the NPC
const selectedBiome = EARTH_BIOMES[Math.floor(Math.random() * EARTH_BIOMES.length)];
logger.info(`🌍 Selected biome: ${chalk.green(selectedBiome.name)}`);
// Select a random biome initially - this may be updated later based on NPC description
const initialBiome = EARTH_BIOMES[Math.floor(Math.random() * EARTH_BIOMES.length)];
logger.info(`🌍 Initial biome selection: ${chalk.green(initialBiome.name)}`);
// Balance villager and magical NPC types - Increase the chance of villager NPCs
// Use a weighted selection to ensure we get more villagers
@@ -991,56 +1053,33 @@ Parse.Cloud.job('generateDailyNPC', async (request) => {
totalWeight += categoryWeights[category];
}
let randomWeight = Math.random() * totalWeight;
let selectedCategory = null;
// Generate the NPC content initially using the random biome
const npcContent = await generateNPCContent(initialBiome);
for (const category in categoryWeights) {
randomWeight -= categoryWeights[category];
if (randomWeight <= 0) {
selectedCategory = category;
break;
}
// Now analyze the content and match to the appropriate biome
const matchedBiome = matchBiomeToNpcDescription(npcContent);
if (matchedBiome.name !== initialBiome.name) {
logger.info(`🔄 Updated biome based on NPC description: ${chalk.yellow(initialBiome.name)}${chalk.green(matchedBiome.name)}`);
// Update the location data to match the new biome
npcContent.location = generateLocationInBiome(matchedBiome);
} else {
logger.info(`✅ Initial biome ${chalk.green(initialBiome.name)} matches NPC description`);
}
// Find the category index in NPC_TYPES
const categoryIndex = NPC_TYPES.findIndex(cat => cat.category === selectedCategory);
// Continue with the rest of the process using the matched biome
const imageFile = await generateNPCImage(npcContent, matchedBiome);
const npcObject = await saveNPCToDatabase(npcContent, imageFile);
// Select a random type from that category
const type = NPC_TYPES[categoryIndex].types[Math.floor(Math.random() * NPC_TYPES[categoryIndex].types.length)];
// Generate and post to social media with appropriate hashtags
await generateSocialPost(npcContent, npcObject.id);
logger.info(`👤 Selected NPC type: ${chalk.cyan(type)} (${selectedCategory} category)`);
// Generate NPC content with specified category and type
logger.progress('🧠 Generating NPC content with OpenAI...');
const npcContent = await generateNPCContent(selectedBiome, {
type: type,
category: selectedCategory
});
logger.npc(`✨ Generated NPC: ${chalk.cyan(npcContent.name)} - ${npcContent.title}`);
// Generate NPC image
logger.progress('🎨 Generating NPC image with DALL-E...');
const imageFile = await generateNPCImage(npcContent, selectedBiome);
logger.image('🖼️ Image generation complete');
// Save to database
logger.progress('💾 Saving NPC to database...');
const savedItem = await saveNPCToDatabase(npcContent, imageFile);
// Trigger social media post if enabled
if (process.env.ENABLE_SOCIAL_POSTS === 'true') {
logger.webhook('📤 Triggering IFTTT webhook...');
await triggerIFTTTWebhook(savedItem);
}
logger.success(`✨ Daily NPC generation complete: ${chalk.cyan(npcContent.name)} - ${chalk.yellow(npcContent.title)}`);
return {
success: true,
name: npcContent.name,
title: npcContent.title,
socialPost: savedItem.get("socialPost")
message: `Generated NPC '${npcContent.name}' in ${matchedBiome.name}`,
npcId: npcObject.id
};
} catch (error) {
logger.error(`Daily NPC generation failed: ${error.message}`);
logger.error(`Stack trace: ${error.stack}`);

View File

@@ -17,7 +17,8 @@ Parse.Cloud.define("searchAssets", async (request) => {
.toLowerCase()
.split(/\s+/)
.filter(term => term.length > 0)
.map(term => term.trim());
.map(term => term.trim()
);
console.log(`Processing search terms: ${searchTerms.join(', ')}`);

View File

@@ -0,0 +1,2 @@
SSUUMMMMAARRYY OOFF LLEESSSS CCOOMMMMAANNDDSS