feat: simple reply agent that tells private whispers that i am a bot

This commit is contained in:
Daniel Eder 2025-09-27 08:36:05 +02:00
parent ed4e697ad0
commit 1daffc871e
3 changed files with 41 additions and 6 deletions

4
.env
View file

@ -4,5 +4,5 @@ MISTLE_USER=mistle
MISTLE_PASSWORD=sl-mudbot MISTLE_PASSWORD=sl-mudbot
MISTLE_LOGIN_PROMPT=Wie heisst Du denn ("neu" fuer neuen Spieler) ? MISTLE_LOGIN_PROMPT=Wie heisst Du denn ("neu" fuer neuen Spieler) ?
MISTLE_EXIT_COMMAND=schlaf ein MISTLE_EXIT_COMMAND=schlaf ein
MISTLE_AGENT_MODE=false MISTLE_AGENT_MODE=true
MISTLE_AGENT=explore MISTLE_AGENT=communication

View file

@ -4,7 +4,7 @@ import re
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from collections import deque from collections import deque
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import Deque, Optional, Pattern, Set from typing import Deque, Optional, Pattern, Set, Tuple
class Agent(ABC): class Agent(ABC):
@ -79,3 +79,38 @@ class ExploreAgent(Agent):
return f"{self.inspect_command} {target}" return f"{self.inspect_command} {target}"
return None return None
@dataclass
class CommunicationAgent(Agent):
"""Agent that replies to private tells."""
reply_template: str = "teile {player} mit Hallo! Ich bin Mistle und ein Bot."
tell_pattern: Pattern[str] = field(
default_factory=lambda: re.compile(
r"^(?P<player>[^\s]+) teilt (d|D)ir mit: (?P<message>.+)$",
re.MULTILINE,
)
)
last_output: str = field(default="", init=False)
pending_replies: Deque[Tuple[str, str]] = field(default_factory=deque, init=False)
def observe(self, output: str) -> None:
if not output:
return
self.last_output = output
for match in self.tell_pattern.finditer(output):
player = match.group("player").strip()
message = match.group("message").strip()
if not player:
continue
self.pending_replies.append((player, message))
print(f"[Agent] Received message from {player}: {message}")
def decide(self) -> Optional[str]:
if not self.pending_replies:
return None
player, _ = self.pending_replies.popleft()
reply = self.reply_template.format(player=player)
print(f"[Agent] Replying to {player}")
return reply

6
app.py
View file

@ -152,12 +152,12 @@ def build_agent(agent_spec: str) -> Agent:
if key == "simple": if key == "simple":
return SimpleAgent() return SimpleAgent()
if key == "explore": if key in {"explore", "communication"}:
try: try:
module = import_module("agent") module = import_module("agent")
agent_cls = getattr(module, "ExploreAgent") agent_cls = getattr(module, f"{key.capitalize()}Agent")
except AttributeError as exc: # pragma: no cover - optional dependency except AttributeError as exc: # pragma: no cover - optional dependency
raise RuntimeError("ExploreAgent is not available in agent module") from exc raise RuntimeError(f"{key.capitalize()}Agent is not available in agent module") from exc
return _instantiate_agent(agent_cls, normalized) return _instantiate_agent(agent_cls, normalized)
if ":" in normalized: if ":" in normalized: