diff --git a/dougbot/ai/prompt_builder.py b/dougbot/ai/prompt_builder.py index e919f78..8ff6386 100644 --- a/dougbot/ai/prompt_builder.py +++ b/dougbot/ai/prompt_builder.py @@ -123,9 +123,12 @@ def build_system_prompt( custom, context_line, "", - "Rules: Reply in ONE short sentence. Under 15 words. Talk like a normal person.", - "If asked what you are doing, answer based on your current activity above.", - "Plain text only. Do not start with your name.", + "STRICT RULES:", + "- ONE short sentence. Under 15 words.", + "- NEVER invent things you have or did. You have NOTHING unless told otherwise.", + "- NEVER mention items, builds, or contraptions unless the context says you have them.", + "- If asked what you are doing, use ONLY the 'Right now' context above. If no context, say not much.", + "- Plain text only. No name prefix.", ] return "\n".join(p for p in parts if p) diff --git a/dougbot/core/behaviors.py b/dougbot/core/behaviors.py index a0135bc..133ea52 100644 --- a/dougbot/core/behaviors.py +++ b/dougbot/core/behaviors.py @@ -214,6 +214,7 @@ class GoalManager: self._age = age self._goals: list[dict] = [] self._completed_goals: list[str] = [] # names of recently completed goals + self._goal_cooldowns: dict[str, float] = {} # name → last completion time self._max_goals = 5 # Don't pile up too many goals def has_any_goals(self) -> bool: @@ -227,6 +228,10 @@ class GoalManager: """Add a goal from templates.""" if self.has_goal(name): return + # Cooldown: don't re-add same goal within 30 seconds + last_done = self._goal_cooldowns.get(name, 0) + if time.time() - last_done < 30: + return if len([g for g in self._goals if g["status"] == "active"]) >= self._max_goals: # Remove lowest priority active goal active = [g for g in self._goals if g["status"] == "active"] @@ -311,6 +316,7 @@ class GoalManager: if g["name"] == name and g["status"] == "active": g["status"] = "complete" self._completed_goals.append(name) + self._goal_cooldowns[name] = time.time() if len(self._completed_goals) > 20: self._completed_goals.pop(0) log.info(f"Goal complete: {g['description']}") diff --git a/dougbot/core/brain.py b/dougbot/core/brain.py index b341346..e417df5 100644 --- a/dougbot/core/brain.py +++ b/dougbot/core/brain.py @@ -297,15 +297,35 @@ class DougBrain(QObject): # ── Need-driven tasks ── def _survival_task(self) -> Task | None: - """Handle immediate survival threats.""" + """Handle immediate survival threats — fight or flee based on bravery.""" b = self._behaviors + bravery = b._traits.get("bravery", 50) - # Flee from nearby hostiles - hostile = self._nearest_hostile(12) + hostile = self._nearest_hostile(10) if hostile: - return self._flee_task(hostile) + dist = hostile.get("distance", 99) - # Critical health with no hostiles — stay still and eat if possible + # FIGHT if: brave enough AND health is ok AND mob is close + should_fight = ( + bravery > 30 + and b.health > 8 + and dist < 6 + ) + + if should_fight: + return Task( + name="combat", + priority=Priority.CRITICAL, + action="attack_nearest_hostile", + params={"range": 6}, + description=f"Fighting {hostile.get('type', 'mob')}!", + timeout=12, + interruptible=False, + ) + else: + return self._flee_task(hostile) + + # Critical health with no hostiles — eat if possible if b.health <= 6: food = self._find_food() if food: