diff --git a/.env b/.env index 45c1ba4..2302411 100644 --- a/.env +++ b/.env @@ -5,4 +5,4 @@ MISTLE_PASSWORD=sl-mudbot MISTLE_LOGIN_PROMPT=Wie heisst Du denn ("neu" fuer neuen Spieler) ? MISTLE_EXIT_COMMAND=schlaf ein MISTLE_AGENT_MODE=true -MISTLE_AGENT=simple \ No newline at end of file +MISTLE_AGENT=explore \ No newline at end of file diff --git a/agent.py b/agent.py index 989e833..046121a 100644 --- a/agent.py +++ b/agent.py @@ -1,8 +1,10 @@ from __future__ import annotations +import re from abc import ABC, abstractmethod +from collections import deque from dataclasses import dataclass, field -from typing import Optional +from typing import Deque, Optional, Pattern, Set class Agent(ABC): @@ -19,7 +21,7 @@ class Agent(ABC): @dataclass class SimpleAgent(Agent): - """Very small stateful agent that decides which command to run next.""" + """Minimal agent that always returns the same command.""" default_command: str = "schau" last_output: str = field(default="", init=False) @@ -34,14 +36,45 @@ class SimpleAgent(Agent): @dataclass class ExploreAgent(Agent): - """Very small stateful agent that decides which command to run next.""" + """Agent that inspects every noun it discovers in the room description.""" - default_command: str = "untersuche boden" + look_command: str = "schau" + inspect_command: str = "untersuche" + nouns_pattern: Pattern[str] = field( + default_factory=lambda: re.compile(r"\b[A-ZÄÖÜ][A-Za-zÄÖÜäöüß-]*\b") + ) last_output: str = field(default="", init=False) + look_sent: bool = field(default=False, init=False) + pending_targets: Deque[str] = field(default_factory=deque, init=False) + seen_targets: Set[str] = field(default_factory=set, init=False) + inspected_targets: Set[str] = field(default_factory=set, init=False) def observe(self, output: str) -> None: - if output: - self.last_output = output + if not output: + return + self.last_output = output + if not self.look_sent: + return + + for noun in self.nouns_pattern.findall(output): + target = noun.strip() + key = target.lower() + if not target or key in self.seen_targets: + continue + self.seen_targets.add(key) + self.pending_targets.append(target) def decide(self) -> Optional[str]: - return self.default_command \ No newline at end of file + if not self.look_sent: + self.look_sent = True + return self.look_command + + if self.pending_targets: + target = self.pending_targets.popleft() + key = target.lower() + self.inspected_targets.add(key) + progress = f"Explored {len(self.inspected_targets)}/{len(self.seen_targets)}" + print(progress) + return f"{self.inspect_command} {target}" + + return None