decouple scenario, add structure to memories

This commit is contained in:
2026-04-11 22:00:25 +05:30
parent cf6653afbd
commit 48f02e7d44
7 changed files with 689 additions and 122 deletions

109
scenario_loader.py Normal file
View File

@@ -0,0 +1,109 @@
import json
import logging
from dataclasses import dataclass
from pathlib import Path
from engine import Entity, MemoryEntry, Player
logger = logging.getLogger(__name__)
@dataclass
class Scenario:
metadata: dict
entities: dict
player_id: str | None = None
def load_scenario(path: Path) -> Scenario:
logger.info("Loading scenario from %s", path)
payload = json.loads(path.read_text())
metadata = payload.get("scenario", {})
player_id = metadata.get("player_id")
world_time = metadata.get("world_time", "Unknown")
location = metadata.get("location", "Unknown")
raw_entities = payload.get("entities", [])
if not raw_entities:
raise ValueError(f"No entities found in scenario: {path}")
entities = {}
for raw in raw_entities:
entity_id = (raw.get("id") or raw["name"]).strip().lower()
if entity_id in entities:
raise ValueError(f"Duplicate Entity id '{entity_id}' in {path}")
entity_class = Player if player_id and entity_id == player_id else Entity
entity = entity_class(
name=raw["name"],
traits=list(raw["traits"]),
stats=dict(raw["stats"]),
voice_sample=raw["voice_sample"],
current_mood=raw.get("current_mood", "Neutral"),
entity_id=entity_id,
)
for memory in raw.get("memories", []):
if isinstance(memory, str):
entry = MemoryEntry(
content=memory,
event_type="observation",
timestamp_str=world_time,
location=location,
entities=[],
)
else:
entry = MemoryEntry(
content=memory["content"],
event_type=memory["event_type"],
timestamp_str=memory["timestamp"],
location=memory["location"],
entities=[
normalized
for entity_ref in memory.get("entities", [])
if (normalized := str(entity_ref).strip().lower())
and normalized != entity_id
],
)
entity.perceive(entry)
entities[entity_id] = entity
logger.info("Loaded %s entities from scenario.", len(entities))
return Scenario(metadata=metadata, entities=entities, player_id=player_id)
def dump_scenario(scenario: Scenario) -> dict:
entity_payloads = []
for entity_id in sorted(scenario.entities.keys()):
entity = scenario.entities[entity_id]
entity_payloads.append(
{
"id": entity_id,
"name": entity.name,
"traits": list(entity.traits),
"stats": dict(entity.stats),
"voice_sample": entity.voice_sample,
"current_mood": entity.current_mood,
"memories": [
entry.to_dict() for entry in entity.memory.dump_entries()
],
}
)
metadata = dict(scenario.metadata)
if scenario.player_id and metadata.get("player_id") != scenario.player_id:
metadata["player_id"] = scenario.player_id
return {
"scenario": metadata,
"entities": entity_payloads,
}
def dumps_scenario(scenario: Scenario) -> str:
return json.dumps(dump_scenario(scenario), indent=2)
def save_scenario(path: Path, scenario: Scenario) -> str:
dumped = dumps_scenario(scenario)
path.write_text(f"{dumped}\n")
logger.info("Saved scenario to %s", path)
return dumped