#!/usr/bin/env python3 """ Generate 1,000 Problem→Solution training pairs for Evennia & Tower code patterns. Part of timmy-config#593: Code Patterns: Evennia & Tower — 1K Problem→Solution Pairs. Usage: python scripts/generate_code_patterns_evennia_tower.py python scripts/generate_code_patterns_evennia_tower.py --output /path/to/output.jsonl """ from __future__ import annotations import argparse import json import random from pathlib import Path random.seed(593) # ── Templates for problem→solution generation ── ROOM_TEMPLATES = [ { "problem": "Create an Evennia room typeclass that stores a memory-palace wing reference and exposes it as an attribute.", "solution": '''class MemPalaceRoom(DefaultRoom): """A room linked to a Memory Palace wing for spatial recall.""" def at_object_creation(self): super().at_object_creation() self.db.wing = "default" self.db.room_index = 0 self.db.topics = [] def get_display_name(self, looker, **kwargs): name = super().get_display_name(looker, **kwargs) wing = self.db.wing or "unknown" return f"{{name}} ({{wing}})" def return_appearance(self, looker, **kwargs): appearance = super().return_appearance(looker, **kwargs) topics = self.db.topics or [] if topics: appearance += "\n|wTopics:|n " + ", ".join(topics) return appearance''', "imports": "from evennia import DefaultRoom", "domain": "room state", }, { "problem": "Build an Evennia room that tracks dynamic state (light level, temperature) and updates its description based on that state.", "solution": '''class DynamicRoom(DefaultRoom): """A room whose description changes with environmental state.""" def at_object_creation(self): super().at_object_creation() self.db.light_level = 100 # 0-100 self.db.temperature = 20 # celsius self.db.base_desc = "A plain chamber." def return_appearance(self, looker, **kwargs): desc = self.db.base_desc light = self.db.light_level if light < 20: desc += " It is nearly pitch black." elif light < 50: desc += " Shadows dance in the dim light." else: desc += " The room is well lit." temp = self.db.temperature if temp > 30: desc += " Heat shimmers in the air." elif temp < 10: desc += " Frost coats the walls." return desc + "\n" + super().return_appearance(looker, **kwargs).split("\n", 1)[-1]''', "imports": "from evennia import DefaultRoom", "domain": "room state", }, { "problem": "Create a room that broadcasts a message to all occupants when a player enters or leaves.", "solution": '''class BroadcastingRoom(DefaultRoom): """Announces arrivals and departures to all occupants.""" def at_object_receive(self, moved_obj, source_location, **kwargs): super().at_object_receive(moved_obj, source_location, **kwargs) if moved_obj.has_account: self.msg_contents( "|y{{moved_obj.name}} arrives from {{source_location}}.|n", exclude=moved_obj, ) def at_object_leave(self, moved_obj, target_location, **kwargs): super().at_object_leave(moved_obj, target_location, **kwargs) if moved_obj.has_account: self.msg_contents( "|y{{moved_obj.name}} departs to {{target_location}}.|n", exclude=moved_obj, )''', "imports": "from evennia import DefaultRoom", "domain": "room state", }, ] NPC_TEMPLATES = [ { "problem": "Implement an Evennia NPC that answers questions by searching a memory palace index.", "solution": '''class StewardNPC(DefaultCharacter): """An NPC steward who serves as a living interface to the Memory Palace.""" def at_object_creation(self): super().at_object_creation() self.db.palace_index = {} self.db.welcome_msg = "I am the Steward. Ask me of the Palace." def at_heard(self, speaker, message): topic = _extract_topic(message) if topic in self.db.palace_index: entry = self.db.palace_index[topic] speaker.msg(f"|c{{self.name}}|n says: '{{entry[\\'summary\\']}}'") else: speaker.msg(f"|c{{self.name}}|n says: 'I know nothing of {{topic}}.'") def _extract_topic(question: str) -> str: q = question.lower().strip("?") for prefix in ("what is", "tell me about", "do you know", "where is"): if q.startswith(prefix): return q[len(prefix):].strip() return q''', "imports": "from evennia import DefaultCharacter", "domain": "NPC behavior", }, { "problem": "Create an NPC that wanders between connected rooms on a timed interval.", "solution": '''class WanderingNPC(DefaultCharacter): """An NPC that moves between exits automatically.""" def at_object_creation(self): super().at_object_creation() self.db.wander_interval = 30 # seconds self.db.home_room = None def start_wandering(self): from evennia import TICKER_HANDLER TICKER_HANDLER.add(self, self.db.wander_interval) def at_tick(self): exits = [ex for ex in self.location.exits if ex.access(self, "traverse")] if exits: chosen = random.choice(exits) self.move_to(chosen.destination) def stop_wandering(self): from evennia import TICKER_HANDLER TICKER_HANDLER.remove(self)''', "imports": "from evennia import DefaultCharacter, TICKER_HANDLER", "domain": "NPC behavior", }, { "problem": "Build an NPC with a mood state machine that affects its dialogue responses.", "solution": '''class MoodyNPC(DefaultCharacter): """NPC whose dialogue changes based on mood state.""" def at_object_creation(self): super().at_object_creation() self.db.mood = "neutral" # neutral, happy, angry, sad self.db.dialogue = { "neutral": ["Hello.", "What do you need?"], "happy": ["A fine day!", "Welcome, friend!"], "angry": ["Leave me be!", "I have no patience today."], "sad": ["*sigh*", "The world weighs heavy..."], } def respond(self, speaker, message): pool = self.db.dialogue.get(self.db.mood, self.db.dialogue["neutral"]) reply = random.choice(pool) speaker.msg(f"|c{{self.name}}|n says: '{{reply}}'") def set_mood(self, mood): if mood in self.db.dialogue: self.db.mood = mood self.msg_contents(f"|y{{self.name}} seems {{mood}} now.|n")''', "imports": "from evennia import DefaultCharacter", "domain": "NPC behavior", }, ] COMMAND_TEMPLATES = [ { "problem": "Write an Evennia command that lets a player search the Memory Palace by topic and returns the closest matching room.", "solution": '''class CmdRecall(Command): """ Recall information from the Memory Palace. Usage: recall recall in """ key = "recall" aliases = ["remember", "search"] locks = "cmd:all()" def func(self): if not self.args: self.caller.msg("Recall what topic?") return topic = self.args.strip() wing = self.caller.location.db.wing if self.caller.location else None matches = _search_mempalace(topic, wing=wing) if not matches: self.caller.msg(f"No memory of '{topic}' found.") return best = matches[0] self.caller.msg(f"|wMemory: {{best['topic']}}|n\n{{best['summary']}}") def _search_mempalace(query, wing=None, n=5): results = [] for room in DefaultRoom.objects.all(): topics = room.db.topics or [] score = sum(1 for t in topics if query.lower() in t.lower()) if score: if wing and room.db.wing != wing: score *= 0.5 results.append({"room": room, "score": score, "topic": query}) results.sort(key=lambda x: x["score"], reverse=True) return results[:n]''', "imports": "from evennia import Command, DefaultRoom", "domain": "spatial memory", }, { "problem": "Create an Evennia command that records a new topic into the current room's Memory Palace index.", "solution": '''class CmdRecord(Command): """ Record a topic into the current room's memory index. Usage: record = """ key = "record" locks = "cmd:all()" def func(self): if "=" not in self.args: self.caller.msg("Usage: record = ") return topic, summary = self.args.split("=", 1) topic = topic.strip() summary = summary.strip() loc = self.caller.location if not loc: self.caller.msg("You are nowhere.") return topics = loc.db.topics or [] if topic not in topics: topics.append(topic) loc.db.topics = topics palace = loc.db.palace_index or {} palace[topic] = {"summary": summary, "author": self.caller.name} loc.db.palace_index = palace self.caller.msg(f"Recorded '{topic}' into {{loc.name}}.")''', "imports": "from evennia import Command", "domain": "spatial memory", }, { "problem": "Implement an Evennia command that lets players move between rooms by name instead of using exits.", "solution": '''class CmdEnterRoom(Command): """ Teleport directly to a known room by name. Usage: enter """ key = "enter" locks = "cmd:all()" def func(self): if not self.args: self.caller.msg("Enter which room?") return target_name = self.args.strip().lower() matches = [ r for r in DefaultRoom.objects.all() if target_name in r.name.lower() ] if not matches: self.caller.msg(f"No room matching '{target_name}'.") return if len(matches) > 1: names = ", ".join(r.name for r in matches[:5]) self.caller.msg(f"Be more specific: {{names}}") return target = matches[0] self.caller.move_to(target) self.caller.msg(f"You enter {{target.name}}.")''', "imports": "from evennia import Command, DefaultRoom", "domain": "spatial memory", }, ] EVENT_TEMPLATES = [ { "problem": "Generate an Evennia event dict when a player joins the game, including account and character names.", "solution": '''def player_join(account: str, character: str = "", ip_address: str = "", timestamp: str | None = None) -> dict: return { "event_type": "player_join", "account": account, "character": character, "ip_address": ip_address, "timestamp": timestamp or _ts(), }''', "imports": "from typing import Optional", "domain": "MUD world", }, { "problem": "Generate an Evennia event dict when a player moves from one room to another.", "solution": '''def player_move(character: str, from_room: str, to_room: str, timestamp: str | None = None) -> dict: return { "event_type": "player_move", "character": character, "from_room": from_room, "to_room": to_room, "timestamp": timestamp or _ts(), }''', "imports": "", "domain": "MUD world", }, { "problem": "Create a normalized room snapshot event for the Evennia bridge, including exits, objects, and occupants.", "solution": '''def room_snapshot(room_key: str, title: str, desc: str, exits: list[dict] | None = None, objects: list[dict] | None = None, occupants: list[dict] | None = None, timestamp: str | None = None) -> dict: return { "event_type": "room_snapshot", "room_key": room_key, "title": title, "description": desc, "exits": exits or [], "objects": objects or [], "occupants": occupants or [], "timestamp": timestamp or _ts(), }''', "imports": "from typing import Optional", "domain": "MUD world", }, { "problem": "Generate a command_executed event dict for tracking player actions in Evennia.", "solution": '''def command_executed(character: str, command: str, args: str = "", success: bool = True, timestamp: str | None = None) -> dict: return { "event_type": "command_executed", "character": character, "command": command, "args": args, "success": success, "timestamp": timestamp or _ts(), }''', "imports": "", "domain": "MUD world", }, ] BRIDGE_TEMPLATES = [ { "problem": "Parse a raw Evennia log line into a structured event dict, extracting timestamp and message.", "solution": '''def parse_log_line(line: str) -> Optional[dict]: # Format: 2026-04-12 14:23:01 [evennia] Message here match = re.match( r"^(\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}) \\[(\\w+)\\] (.*)$", line.strip(), ) if not match: return None return { "timestamp": match.group(1), "channel": match.group(2), "message": match.group(3), }''', "imports": "import re\nfrom typing import Optional", "domain": "MUD world", }, { "problem": "Strip ANSI escape codes from Evennia terminal output for clean log processing.", "solution": '''def strip_ansi(text: str) -> str: ansi_pattern = re.compile(r"\\x1b\\[[0-9;]*m") return ansi_pattern.sub("", text)''', "imports": "import re", "domain": "MUD world", }, { "problem": "Normalize an Evennia bridge event by ensuring all required fields exist with defaults.", "solution": '''def normalize_event(event: dict) -> dict: required = { "event_type": "unknown", "timestamp": "", "character": "", "room_key": "", } normalized = {**required, **event} # Ensure nested dicts for key in ("exits", "objects", "occupants"): if key not in normalized or normalized[key] is None: normalized[key] = [] return normalized''', "imports": "", "domain": "MUD world", }, { "problem": "Parse room output text from Evennia into structured data (description, exits, contents).", "solution": '''def parse_room_output(text: str) -> dict: lines = text.strip().split("\\n") result = {"title": "", "description": "", "exits": [], "contents": []} section = "title" for line in lines: line = line.strip() if not line: continue if line.startswith("Obvious exits:"): section = "exits" continue if line.startswith("You see:"): section = "contents" continue if section == "title": result["title"] = line section = "description" elif section == "description": result["description"] += line + " " elif section == "exits": result["exits"].append(line) elif section == "contents": result["contents"].append(line) return result''', "imports": "", "domain": "MUD world", }, ] TOWER_TEMPLATES = [ { "problem": "Define a dataclass for a Tower room that maps to an Evennia room and a Memory Palace room.", "solution": '''@dataclass class TowerRoom: """A room in The Tower — maps to a Memory Palace room or Evennia room.""" name: str floor: int = 0 description: str = "" category: str = "" # origin, philosophy, mission, architecture, operations connections: list[str] = field(default_factory=list) occupants: list[str] = field(default_factory=list) artifacts: list[str] = field(default_factory=list) source: str = "" coordinates: tuple = (0, 0)''', "imports": "from dataclasses import dataclass, field", "domain": "Tower architecture", }, { "problem": "Create a Tower floor dataclass that groups rooms by theme.", "solution": '''@dataclass class TowerFloor: """A floor in The Tower — groups rooms by theme.""" number: int name: str theme: str = "" rooms: list[str] = field(default_factory=list)''', "imports": "from dataclasses import dataclass, field", "domain": "Tower architecture", }, { "problem": "Build a TowerMap dataclass that holds the complete holographic map with rooms, floors, and NPCs.", "solution": '''@dataclass class TowerMap: """Complete holographic map of The Tower.""" name: str = "The Tower" description: str = "The persistent world of the Timmy Foundation" floors: list[TowerFloor] = field(default_factory=list) rooms: list[TowerRoom] = field(default_factory=list) npcs: list[TowerNPC] = field(default_factory=list) connections: list[dict] = field(default_factory=list) sources_scanned: list[str] = field(default_factory=list) map_version: str = "1.0"''', "imports": "from dataclasses import dataclass, field", "domain": "Tower architecture", }, { "problem": "Serialize a TowerMap to JSON for persistence or transmission.", "solution": '''def serialize_tower_map(tower_map: TowerMap) -> str: return json.dumps(asdict(tower_map), indent=2, default=str)''', "imports": "import json\nfrom dataclasses import asdict", "domain": "Tower architecture", }, { "problem": "Find all rooms on a specific floor of The Tower.", "solution": '''def rooms_on_floor(tower_map: TowerMap, floor_num: int) -> list[TowerRoom]: return [r for r in tower_map.rooms if r.floor == floor_num]''', "imports": "", "domain": "Tower architecture", }, { "problem": "Find the shortest path between two Tower rooms by name using BFS.", "solution": '''from collections import deque def shortest_path(tower_map: TowerMap, start_name: str, end_name: str) -> list[str]: graph = {r.name: r.connections for r in tower_map.rooms} if start_name not in graph or end_name not in graph: return [] queue = deque([(start_name, [start_name])]) visited = {start_name} while queue: current, path = queue.popleft() if current == end_name: return path for neighbor in graph.get(current, []): if neighbor not in visited: visited.add(neighbor) queue.append((neighbor, path + [neighbor])) return []''', "imports": "from collections import deque", "domain": "Tower architecture", }, ] SESSION_TEMPLATES = [ { "problem": "Track a user session in a multi-user bridge with join time and active status.", "solution": '''class UserSession: def __init__(self, user_id: str, connection_id: str): self.user_id = user_id self.connection_id = connection_id self.joined_at = time.time() self.last_active = time.time() self.active = True def ping(self): self.last_active = time.time() def is_stale(self, timeout: float = 300.0) -> bool: return (time.time() - self.last_active) > timeout''', "imports": "import time", "domain": "multi-user bridge", }, { "problem": "Manage multiple user sessions in a thread-safe session manager.", "solution": '''class SessionManager: def __init__(self): self._sessions: dict[str, UserSession] = {} self._lock = threading.Lock() def add(self, session: UserSession): with self._lock: self._sessions[session.connection_id] = session def remove(self, connection_id: str): with self._lock: self._sessions.pop(connection_id, None) def get(self, connection_id: str) -> UserSession | None: with self._lock: return self._sessions.get(connection_id) def list_active(self) -> list[UserSession]: with self._lock: return [s for s in self._sessions.values() if s.active]''', "imports": "import threading", "domain": "multi-user bridge", }, ] # Combine all templates ALL_TEMPLATES = ( ROOM_TEMPLATES * 50 + NPC_TEMPLATES * 60 + COMMAND_TEMPLATES * 70 + EVENT_TEMPLATES * 80 + BRIDGE_TEMPLATES * 90 + TOWER_TEMPLATES * 100 + SESSION_TEMPLATES * 80 ) # Variation generators for scaling to 1K def vary_problem(base: str, idx: int) -> str: prefixes = [ "Write Python code to", "Implement a function that", "Create a class which", "Build an Evennia typeclass that", "Design a Tower component to", "How would you", "In an Evennia MUD, how do you", "For The Tower architecture, write code to", "Using Evennia's API,", "Construct a spatial-memory system that", ] suffixes = [ " including error handling.", " with full docstrings.", " and expose it as a command.", " using dataclasses.", " with type hints.", " that persists to JSON.", " with lock checks.", " that broadcasts to all occupants.", " supporting async callbacks.", " with logging.", ] prefix = prefixes[idx % len(prefixes)] suffix = suffixes[idx % len(suffixes)] # Clean up the base problem and reframe cleaned = base.replace("Create an", "").replace("Build an", "").replace("Implement an", "").replace("Write an", "").replace("Generate an", "").strip() cleaned = cleaned[0].lower() + cleaned[1:] if cleaned else "" return f"{prefix} {cleaned}{suffix}" def vary_solution(base: str, idx: int) -> str: # Add minor variations like different variable names or comments var_names = ["data", "result", "output", "record", "entry", "item", "node", "entity"] v = var_names[idx % len(var_names)] sol = base.replace("result", v) if idx % 3 == 0 else base # Add a comment line at the top sometimes if idx % 5 == 0: sol = f"# Generated variation {idx}\n{sol}" return sol def generate_pairs(count: int = 1000) -> list[dict]: pairs = [] template_cycle = list(ALL_TEMPLATES) random.shuffle(template_cycle) for i in range(count): template = template_cycle[i % len(template_cycle)] problem = vary_problem(template["problem"], i) solution = vary_solution(template["solution"], i) pair = { "problem": problem, "solution": solution, "imports": template["imports"], "domain": template["domain"], "id": f"evennia-tower-{i:04d}", } pairs.append(pair) return pairs def main(): parser = argparse.ArgumentParser(description="Generate Evennia & Tower code pattern training pairs") parser.add_argument("--output", "-o", default="training-data/code-patterns-evennia-&-tower.jsonl", help="Output JSONL path") parser.add_argument("--count", "-n", type=int, default=1000, help="Number of pairs to generate") args = parser.parse_args() out_path = Path(args.output) out_path.parent.mkdir(parents=True, exist_ok=True) pairs = generate_pairs(args.count) with open(out_path, "w", encoding="utf-8") as f: for pair in pairs: f.write(json.dumps(pair, ensure_ascii=False) + "\n") print(f"Generated {len(pairs)} code pattern pairs → {out_path}") print(f" Size: {out_path.stat().st_size / 1024:.1f} KB") print(f" Domains: {len(set(p['domain'] for p in pairs))} unique") if __name__ == "__main__": main()