import logging import datetime import random import math from typing import Any, Dict, List, Optional, Set, Tuple import uuid from config import config class VirtualObject: """Class representing an object in the virtual world.""" def __init__(self, name: str, position: Tuple[float, float], properties: Dict[str, Any] = None): """Initialize a virtual object with name, position, and properties.""" self.id = str(uuid.uuid4()) self.name = name self.position = position # (x, y) self.properties = properties or {} self.created_at = datetime.datetime.now().isoformat() def update_position(self, new_position: Tuple[float, float]) -> None: """Update the object's position.""" self.position = new_position def get_property(self, property_name: str, default: Any = None) -> Any: """Get a property value.""" return self.properties.get(property_name, default) def set_property(self, property_name: str, value: Any) -> None: """Set a property value.""" self.properties[property_name] = value def to_dict(self) -> Dict[str, Any]: """Convert object to dictionary.""" return { "id": self.id, "name": self.name, "position": self.position, "properties": self.properties, "created_at": self.created_at } class VirtualLocation: """Class representing a location in the virtual world.""" def __init__(self, name: str, position: Tuple[float, float], radius: float = 1.0, properties: Dict[str, Any] = None): """Initialize a virtual location with name, position, radius, and properties.""" self.id = str(uuid.uuid4()) self.name = name self.position = position # (x, y) self.radius = radius self.properties = properties or {} self.created_at = datetime.datetime.now().isoformat() def contains(self, position: Tuple[float, float]) -> bool: """Check if a position is within this location.""" x1, y1 = self.position x2, y2 = position distance = math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2) return distance <= self.radius def to_dict(self) -> Dict[str, Any]: """Convert location to dictionary.""" return { "id": self.id, "name": self.name, "position": self.position, "radius": self.radius, "properties": self.properties, "created_at": self.created_at } class VirtualAgent: """Class representing an agent's presence in the virtual world.""" def __init__(self, agent_id: str, position: Tuple[float, float], properties: Dict[str, Any] = None): """Initialize a virtual agent with agent_id, position, and properties.""" self.agent_id = agent_id self.position = position # (x, y) self.properties = properties or {} self.created_at = datetime.datetime.now().isoformat() def update_position(self, new_position: Tuple[float, float]) -> None: """Update the agent's position.""" self.position = new_position def get_property(self, property_name: str, default: Any = None) -> Any: """Get a property value.""" return self.properties.get(property_name, default) def set_property(self, property_name: str, value: Any) -> None: """Set a property value.""" self.properties[property_name] = value def to_dict(self) -> Dict[str, Any]: """Convert virtual agent to dictionary.""" return { "agent_id": self.agent_id, "position": self.position, "properties": self.properties, "created_at": self.created_at } class VirtualWorld: """Class representing a virtual world for agent interactions.""" def __init__(self, name: str, size: Tuple[float, float] = (100.0, 100.0)): """Initialize a virtual world with name and size.""" self.name = name self.size = size # (width, height) self.objects = {} # object_id -> VirtualObject self.locations = {} # location_id -> VirtualLocation self.virtual_agents = {} # agent_id -> VirtualAgent self.created_at = datetime.datetime.now().isoformat() self.logger = logging.getLogger(f"virtual_world.{name}") self.logger.info(f"Virtual world {name} initialized with size {size}") def add_object(self, obj: VirtualObject) -> str: """Add an object to the world.""" self.objects[obj.id] = obj self.logger.info(f"Added object {obj.name} at position {obj.position}") return obj.id def remove_object(self, object_id: str) -> bool: """Remove an object from the world.""" if object_id not in self.objects: return False obj = self.objects[object_id] del self.objects[object_id] self.logger.info(f"Removed object {obj.name}") return True def add_location(self, location: VirtualLocation) -> str: """Add a location to the world.""" self.locations[location.id] = location self.logger.info(f"Added location {location.name} at position {location.position}") return location.id def remove_location(self, location_id: str) -> bool: """Remove a location from the world.""" if location_id not in self.locations: return False location = self.locations[location_id] del self.locations[location_id] self.logger.info(f"Removed location {location.name}") return True def add_agent(self, agent_id: str, position: Tuple[float, float], properties: Dict[str, Any] = None) -> bool: """Add an agent to the world.""" if agent_id in self.virtual_agents: self.logger.warning(f"Agent {agent_id} is already in the world") return False virtual_agent = VirtualAgent(agent_id, position, properties) self.virtual_agents[agent_id] = virtual_agent self.logger.info(f"Added agent {agent_id} at position {position}") return True def remove_agent(self, agent_id: str) -> bool: """Remove an agent from the world.""" if agent_id not in self.virtual_agents: return False del self.virtual_agents[agent_id] self.logger.info(f"Removed agent {agent_id}") return True def move_agent(self, agent_id: str, new_position: Tuple[float, float]) -> bool: """Move an agent to a new position.""" if agent_id not in self.virtual_agents: self.logger.warning(f"Agent {agent_id} is not in the world") return False # Ensure position is within world bounds x, y = new_position width, height = self.size x = max(0, min(width, x)) y = max(0, min(height, y)) virtual_agent = self.virtual_agents[agent_id] old_position = virtual_agent.position virtual_agent.update_position((x, y)) self.logger.info(f"Moved agent {agent_id} from {old_position} to {(x, y)}") return True def get_objects_near(self, position: Tuple[float, float], radius: float) -> List[VirtualObject]: """Get objects near a position within a radius.""" nearby_objects = [] x1, y1 = position for obj in self.objects.values(): x2, y2 = obj.position distance = math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2) if distance <= radius: nearby_objects.append(obj) return nearby_objects def get_agents_near(self, position: Tuple[float, float], radius: float) -> List[str]: """Get agent IDs near a position within a radius.""" nearby_agents = [] x1, y1 = position for agent_id, virtual_agent in self.virtual_agents.items(): x2, y2 = virtual_agent.position distance = math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2) if distance <= radius: nearby_agents.append(agent_id) return nearby_agents def get_location_at(self, position: Tuple[float, float]) -> Optional[VirtualLocation]: """Get the location at a position.""" for location in self.locations.values(): if location.contains(position): return location return None def get_agent_location(self, agent_id: str) -> Optional[VirtualLocation]: """Get the location of an agent.""" if agent_id not in self.virtual_agents: return None virtual_agent = self.virtual_agents[agent_id] return self.get_location_at(virtual_agent.position) def get_distance(self, position1: Tuple[float, float], position2: Tuple[float, float]) -> float: """Calculate the distance between two positions.""" x1, y1 = position1 x2, y2 = position2 return math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2) def get_agent_distance(self, agent_id1: str, agent_id2: str) -> Optional[float]: """Calculate the distance between two agents.""" if agent_id1 not in self.virtual_agents or agent_id2 not in self.virtual_agents: return None pos1 = self.virtual_agents[agent_id1].position pos2 = self.virtual_agents[agent_id2].position return self.get_distance(pos1, pos2) def can_agents_interact(self, agent_id1: str, agent_id2: str, max_distance: float = 5.0) -> bool: """Check if two agents can interact based on distance.""" distance = self.get_agent_distance(agent_id1, agent_id2) if distance is None: return False return distance <= max_distance def get_random_position(self) -> Tuple[float, float]: """Get a random position within the world.""" width, height = self.size x = random.uniform(0, width) y = random.uniform(0, height) return (x, y) def to_dict(self) -> Dict[str, Any]: """Convert virtual world to dictionary representation.""" return { "name": self.name, "size": self.size, "object_count": len(self.objects), "location_count": len(self.locations), "agent_count": len(self.virtual_agents), "created_at": self.created_at }