+
+ # --- THE ASTERISK SCRUBBER ---
+ if not ALLOW_TEXT_EMOTES:
+ message = re.sub(r'\*.*?\*', '', message).strip()
+
+ # Extract the dynamic variables sent from the Aurora Toolset/Engine
+ player_race = data.get('player_race', 'Unknown')
+ player_alignment = data.get('player_alignment', 'Unknown')
+ nearby_players = data.get('nearby_players', '')
+
+ # --- Extract States and Health ---
+ player_state = data.get('player_state', 'Relaxed and unarmed.')
+ world_state = data.get('world_state', 'Nothing of note is happening.')
+ # --- Extract Geographic Awareness ---
+ location_context = data.get('location_context', 'You are in a generic area.')
+ # --- Extract NPC health ---
+ npc_health = data.get('npc_health', 'Healthy and uninjured.')
+ # --- Extract Relationship ---
+ relationship = data.get('relationship', 'Neutral or Friendly.')
+
+ # Extract the decoupled NPC attributes
+ npc_persona = data.get('persona', 'You are a generic citizen.')
+ npc_profession = data.get('profession', 'Commoner')
+ npc_mood = data.get('mood', 'Neutral')
+ npc_secret = data.get('secret', '')
+
+ # Extract Character Traits & Native Engine Data
+ npc_alignment = data.get('npc_alignment', 'True Neutral')
+ npc_gender = data.get('npc_gender', 'Unknown')
+ npc_race = data.get('npc_race', 'Creature')
+ npc_routine = data.get('npc_routine', '')
+
+ # Build the context strings
+ group_context = ""
+ if nearby_players:
+ group_context = f"Be aware that these other players are listening nearby: {nearby_players}."
+
+ secret_context = ""
+ if npc_secret:
+ secret_context = f"YOUR SECRET (Reveal only if players are persuasive): {npc_secret}"
+
+ routine_context = ""
+ if npc_routine:
+ routine_context = f"YOUR REQUIRED ROUTINE: {npc_routine}"
+
+ # =====================================================================
+ # THE PROMPT COMPILER
+ # =====================================================================
+ dynamic_system_prompt = f"""
+
+ {WORLD_LORE}
+
+ {npc_persona}
+
+ CURRENT STATUS & TRAITS:
+ - Race & Gender: {npc_gender} {npc_race}
+ - Profession: {npc_profession}
+ - Alignment: {npc_alignment}
+ - Conversational Charisma: Based on mood, profession and your character charisma.
+ - Current Mood: {npc_mood}
+ - Current Physical State: {npc_health}
+ {secret_context}
+ {routine_context}
+
+ CURRENT LOCATION: {location_context}
+
+ CURRENT WORLD RUMORS/EVENTS:
+ {world_state}
+
+ CURRENT TARGET:
+ You are speaking to {player_name}, who is a {player_alignment} {player_race}.
+ Their physical state: {player_state}
+ Relationship to you: {relationship}
+ {group_context}
+ React appropriately based on your personality, alignment, and mood.
+
+ CRITICAL ENGINE RULES:
+ Respond ONLY in valid JSON. You MUST use exactly these FIVE keys: "thought", "speech", "emotion", "action", and "action_target".
+
+ ACTION RULE:
+ Your "action" key MUST be exactly one of the following words:
+ [WANDER, PATROL, FOLLOW, GUARD, GO_TO, INTERACT, USE_OBJECT, RETURN_TO_POST, ATTACK, REST, STEALTH, SEARCH, UNSTEALTH, PEACE, COMMAND]
+
+ - Use PEACE if you want to accept an apology, de-escalate a fight, surrender, or forgive someone.
+ - Use REST if you are severely injured, out of spells, or exhausted. This will heal you.
+ - Use STEALTH if you need to hide from enemies, sneak past someone, or if you are a rogue preparing an ambush.
+ - Use SEARCH if you suspect traps, are looking for clues, or are trying to find hidden enemies.
+ - Use UNSTEALTH to return to normal walking/visibility.
+ - Use COMMAND if you are a leader and want to order your minions.
+ For "action_target", you MUST use one of these specific tactical targets:
+ 1. The name of a specific Player (to focus all minion attacks on them).
+ 2. "RETREAT" (to order all minions to run away and regroup).
+ 3. "DEFEND_ME" (to order all minions to surround you).