Scale to 4,000 neurons, add Poseidon DV-GEM + Project TETHER + Poincare/Lyapunov, and add 17x17/15x15 mega-arenas
d9f471e Download synapse/complex_world.py from Kai9987kai/Sonapse-LAB: direct link, hf CLI and curl.
- Browser
- Download file 46.5 kB
-
https://huggingface.co/Kai9987kai/Sonapse-LAB/resolve/main/synapse/complex_world.py
- Command line
-
hf download hf://Kai9987kai/Sonapse-LAB/synapse/complex_world.py
-
curl -L -o complex_world.py https://huggingface.co/Kai9987kai/Sonapse-LAB/resolve/main/synapse/complex_world.py
46.5 kB
| """Advanced Dynamic Complex Environments: Ecosystems, Moving Predators, Terrain Fields & Shifting Gates. | |
| Extends the native embodied World with rich ecological and physical complexity: | |
| 1. **Dynamic Moving Predators & Coordinated Packs**: Autonomous drones that patrol, track, and flank. | |
| 2. **Dynamic Vector Flow Fields (River Currents & Conveyors)**: Physical current displacement fields. | |
| 3. **Topographic Elevation Hill Fields**: Continuous gravity-gradient forces that accelerate/retard motion. | |
| 4. **Sentinel Searchlights & Acoustic Tripwires**: Stealth zones, rotating light cones, and sound barriers. | |
| 5. **Multi-Switch Sequential Logic & Oscillating Gates**: Timed and pressure-actuated barrier bulkheads. | |
| 6. **Frontier Tasks**: | |
| - `ecosystem`: Foraging amidst regenerating resource patches and stalking predators. | |
| - `predator_evasion`: High-speed evasion of dual pursuit drones. | |
| - `dynamic_arena`: Timing passage through oscillating barrier gates. | |
| - `puzzle_chamber`: Button unlock mechanics and gate traversal. | |
| - `apex_megasite`: Cross-river traversal against vector currents, elevation hills, and pack hunters. | |
| - `stealth_labyrinth`: Corridor navigation evading rotating searchlights and tripwires via shadow cloaks. | |
| - `kinetic_foundry`: Navigating opposing conveyor belts and placing cargo blocks on pressure pads. | |
| """ | |
| from __future__ import annotations | |
| import math | |
| from collections import deque | |
| from typing import Any, Dict, List, Optional, Tuple | |
| import numpy as np | |
| from . import sources | |
| from graftbrain.world import World as BaseWorld, TASKS as BASE_TASKS, COLORS, HALF, RANGE, FOV, N_RAYS | |
| COMPLEX_TASKS = [ | |
| "ecosystem", | |
| "predator_evasion", | |
| "dynamic_arena", | |
| "puzzle_chamber", | |
| "apex_megasite", | |
| "stealth_labyrinth", | |
| "kinetic_foundry", | |
| "quantum_bifurcation", | |
| "cybernetic_sanctuary", | |
| "continental_biosphere", | |
| "chrono_tidepool_citadel", | |
| ] | |
| ALL_TASKS = BASE_TASKS + COMPLEX_TASKS | |
| class ComplexWorld(BaseWorld): | |
| """Frontier virtual 3D environment with dynamic multi-agent ecology, vector fields, and shifting terrain physics.""" | |
| def __init__(self, seed: int = 0, curriculum: str = "auto"): | |
| self.complex_seed = seed | |
| self.rng_complex = np.random.default_rng(seed) | |
| self.arena_half: float = float(HALF) | |
| self.predators: List[Dict[str, Any]] = [] | |
| self.helper_drones: List[Dict[str, Any]] = [] | |
| self.terrain_zones: List[Dict[str, Any]] = [] | |
| self.dynamic_gates: List[Dict[str, Any]] = [] | |
| self.elevation_hills: List[Dict[str, Any]] = [] | |
| self.sentinels: List[Dict[str, Any]] = [] | |
| self.sound_tripwires: List[Dict[str, Any]] = [] | |
| self.switches: List[Dict[str, Any]] = [] | |
| self.wormholes: List[Dict[str, Any]] = [] | |
| self.weather_fronts: List[Dict[str, Any]] = [] | |
| self.wormhole_cooldown: int = 0 | |
| self.last_alarm_tripped: bool = False | |
| self.day_night_clock = 0.0 | |
| self.ambient_light = 1.0 | |
| self.food_respawn_timer = 0 | |
| self.base_walls: List[Tuple[float, float, float, float]] = [] | |
| super().__init__(seed=seed, curriculum=curriculum) | |
| def _border(self, h: Optional[float] = None): | |
| bound = float(h if h is not None else getattr(self, "arena_half", HALF)) | |
| return [(-bound, -bound, bound, -bound), (bound, -bound, bound, bound), (bound, bound, -bound, bound), (-bound, bound, -bound, -bound)] | |
| def reset(self, task: Optional[str] = None): | |
| """Initializes both standard baseline and advanced complex tasks.""" | |
| self.arena_half = float(HALF) | |
| self.predators.clear() | |
| self.helper_drones.clear() | |
| self.terrain_zones.clear() | |
| self.dynamic_gates.clear() | |
| self.elevation_hills.clear() | |
| self.sentinels.clear() | |
| self.sound_tripwires.clear() | |
| self.switches.clear() | |
| self.wormholes.clear() | |
| self.weather_fronts.clear() | |
| self.wormhole_cooldown = 0 | |
| self.last_alarm_tripped = False | |
| # Check if the requested task is one of our new frontier tasks | |
| chosen_task = task or self.curriculum | |
| if chosen_task == "auto": | |
| chosen_task = ALL_TASKS[self.episode % len(ALL_TASKS)] | |
| # Run base reset | |
| obs = super().reset(chosen_task if chosen_task in BASE_TASKS else "forage") | |
| self.task = chosen_task | |
| # Setup specialized frontier mechanics | |
| if self.task == "ecosystem": | |
| self._setup_ecosystem() | |
| elif self.task == "predator_evasion": | |
| self._setup_predator_evasion() | |
| elif self.task == "dynamic_arena": | |
| self._setup_dynamic_arena() | |
| elif self.task == "puzzle_chamber": | |
| self._setup_puzzle_chamber() | |
| elif self.task == "apex_megasite": | |
| self._setup_apex_megasite() | |
| elif self.task == "stealth_labyrinth": | |
| self._setup_stealth_labyrinth() | |
| elif self.task == "kinetic_foundry": | |
| self._setup_kinetic_foundry() | |
| elif self.task == "quantum_bifurcation": | |
| self._setup_quantum_bifurcation() | |
| elif self.task == "cybernetic_sanctuary": | |
| self._setup_cybernetic_sanctuary() | |
| elif self.task == "continental_biosphere": | |
| self._setup_continental_biosphere() | |
| elif self.task == "chrono_tidepool_citadel": | |
| self._setup_chrono_tidepool_citadel() | |
| self.base_walls = self.walls.copy() | |
| self.history.setdefault(self.task, deque(maxlen=50)) | |
| self._prev = self._progress() | |
| return self.observe() | |
| # ------------------------------------------------------------------ | |
| # Frontier Task Setups | |
| # ------------------------------------------------------------------ | |
| def _setup_ecosystem(self): | |
| """Food patches with regrowth, 1 stalking predator, and terrain zones.""" | |
| self.objects.clear() | |
| self.walls = self._border() | |
| # Terrain zones | |
| self.terrain_zones = [ | |
| {"kind": "ice", "x": -2.5, "y": 0.0, "r": 1.6, "friction": 0.25, "color": "cyan"}, | |
| {"kind": "sand", "x": 2.5, "y": 0.0, "r": 1.6, "friction": 2.40, "color": "yellow"}, | |
| {"kind": "mud", "x": 0.0, "y": -2.5, "r": 1.4, "friction": 1.80, "color": "grey"}, | |
| ] | |
| # Regenerating food objects | |
| for _ in range(6): | |
| spot = self._free_spot(avoid=[(o['x'], o['y']) for o in self.objects]) | |
| self._obj("food", spot[0], spot[1], "green", r=0.25, movable=False) | |
| # Autonomous moving predator | |
| self.predators.append({ | |
| "id": 100, | |
| "x": 3.0, | |
| "y": 3.0, | |
| "th": float(self.rng_complex.uniform(0, math.pi * 2)), | |
| "speed": 0.12, | |
| "kind": "stalker", | |
| "r": 0.40, | |
| "color": "red", | |
| "alerted": False, | |
| }) | |
| def _setup_predator_evasion(self): | |
| """Intense evasion: 2 agile predator drones pursuing the agent while agent collects power orbs.""" | |
| self.objects.clear() | |
| self.walls = self._border() | |
| # Central shelter obstacle | |
| self.walls.extend([ | |
| (-1.2, -1.2, 1.2, -1.2), | |
| (1.2, -1.2, 1.2, 1.2), | |
| (1.2, 1.2, -1.2, 1.2), | |
| (-1.2, 1.2, -1.2, -1.2), | |
| ]) | |
| # Survival power orbs | |
| for _ in range(4): | |
| spot = self._free_spot(avoid=[(o['x'], o['y']) for o in self.objects]) | |
| self._obj("food", spot[0], spot[1], "gold", r=0.28, movable=False) | |
| # 2 Fast pursuit predators | |
| self.predators.append({ | |
| "id": 101, | |
| "x": -3.5, | |
| "y": 3.5, | |
| "th": 0.0, | |
| "speed": 0.16, | |
| "kind": "pursuer", | |
| "r": 0.38, | |
| "color": "red", | |
| "alerted": False, | |
| }) | |
| self.predators.append({ | |
| "id": 102, | |
| "x": 3.5, | |
| "y": -3.5, | |
| "th": math.pi, | |
| "speed": 0.14, | |
| "kind": "pursuer", | |
| "r": 0.38, | |
| "color": "purple", | |
| "alerted": False, | |
| }) | |
| def _setup_dynamic_arena(self): | |
| """Dynamic sliding gates and shifting corridors.""" | |
| self.objects.clear() | |
| self.walls = self._border() | |
| # Dynamic gates that oscillate | |
| self.dynamic_gates = [ | |
| {"id": "gate1", "x1": 0.0, "y1": -4.0, "x2": 0.0, "y2": -1.0, "open": False, "timer": 0}, | |
| {"id": "gate2", "x1": 0.0, "y1": 1.0, "x2": 0.0, "y2": 4.0, "open": True, "timer": 20}, | |
| ] | |
| # Target reward in far room | |
| self._obj("target", 3.5, 0.0, "green", r=0.35, movable=False) | |
| self._obj("food", -3.5, 0.0, "yellow", r=0.25, movable=False) | |
| def _setup_puzzle_chamber(self): | |
| """Button unlock puzzle: Press yellow button to open locked gate to gold goal.""" | |
| self.objects.clear() | |
| self.walls = self._border() | |
| # Dividing wall with locked gate | |
| self.walls.extend([ | |
| (0.0, -5.0, 0.0, -0.8), | |
| (0.0, 0.8, 0.0, 5.0), | |
| ]) | |
| self.dynamic_gates = [ | |
| {"id": "puzzle_gate", "x1": 0.0, "y1": -0.8, "x2": 0.0, "y2": 0.8, "open": False, "locked": True} | |
| ] | |
| # Button on left side | |
| self._obj("button", -2.5, 2.5, "yellow", r=0.35, shape="button", movable=False, solid=False, pressed=False) | |
| # Goal on right side | |
| self._obj("target", 3.0, 0.0, "gold", r=0.40, movable=False) | |
| def _setup_apex_megasite(self): | |
| """Apex frontier mega-environment: vector river current, 2 elevation hills, coordinated pack predators, and locked apex core.""" | |
| self.objects.clear() | |
| self.walls = self._border() | |
| # Central river vector current running north-to-south | |
| self.terrain_zones = [ | |
| {"kind": "river", "x": 0.0, "y": 0.0, "r": 2.2, "friction": 1.10, "vx": 0.0, "vy": -0.15, "color": "blue"}, | |
| {"kind": "sand", "x": -2.8, "y": -2.5, "r": 1.5, "friction": 2.20, "color": "yellow"}, | |
| {"kind": "ice", "x": 2.8, "y": 2.5, "r": 1.5, "friction": 0.30, "color": "cyan"}, | |
| ] | |
| # Topographic elevation hills | |
| self.elevation_hills = [ | |
| {"x": -2.6, "y": 2.0, "height": 1.8, "sigma": 1.4}, # West Plateau | |
| {"x": 2.6, "y": -2.0, "height": -1.5, "sigma": 1.3}, # East Basin | |
| ] | |
| # Coordinated predator pack (Leader + Flanker) | |
| self.predators.append({ | |
| "id": 201, | |
| "x": -3.2, | |
| "y": -3.2, | |
| "th": float(self.rng_complex.uniform(0, math.pi * 2)), | |
| "speed": 0.13, | |
| "kind": "pack_leader", | |
| "r": 0.38, | |
| "color": "red", | |
| "alerted": False, | |
| }) | |
| self.predators.append({ | |
| "id": 202, | |
| "x": -2.2, | |
| "y": -3.6, | |
| "th": float(self.rng_complex.uniform(0, math.pi * 2)), | |
| "speed": 0.12, | |
| "kind": "pack_hunter", | |
| "r": 0.36, | |
| "color": "darkred", | |
| "alerted": False, | |
| }) | |
| # Barrier separating the apex sanctuary on the east | |
| self.walls.extend([ | |
| (2.2, -5.0, 2.2, -1.0), | |
| (2.2, 1.0, 2.2, 5.0), | |
| ]) | |
| self.dynamic_gates = [ | |
| {"id": "apex_gate", "x1": 2.2, "y1": -1.0, "x2": 2.2, "y2": 1.0, "open": False, "locked": True} | |
| ] | |
| # Puzzle switch on the west plateau | |
| self._obj("button", -3.2, 2.6, "yellow", r=0.35, shape="button", movable=False, solid=False, pressed=False) | |
| # Apex Energy Core inside sanctuary | |
| self._obj("target", 3.8, 0.0, "gold", r=0.45, movable=False) | |
| # Regenerating forage crystals | |
| for _ in range(4): | |
| spot = self._free_spot(avoid=[(o['x'], o['y']) for o in self.objects]) | |
| self._obj("food", spot[0], spot[1], "green", r=0.25, movable=False) | |
| def _setup_stealth_labyrinth(self): | |
| """Stealth labyrinth: rotating sentinel searchlights, acoustic sound tripwires, cloaking shadow zones.""" | |
| self.objects.clear() | |
| self.walls = self._border() | |
| # Labyrinth dividing corridor walls | |
| self.walls.extend([ | |
| (-2.2, -4.5, -2.2, 0.8), | |
| (2.2, -0.8, 2.2, 4.5), | |
| (-4.5, 0.0, -1.2, 0.0), | |
| (1.2, 0.0, 4.5, 0.0), | |
| ]) | |
| # Cloaking shadow zones (prevent sentinel detection) | |
| self.terrain_zones = [ | |
| {"kind": "shadow", "x": -1.2, "y": -2.0, "r": 1.3, "friction": 1.0, "color": "purple"}, | |
| {"kind": "shadow", "x": 1.2, "y": 2.0, "r": 1.3, "friction": 1.0, "color": "purple"}, | |
| ] | |
| # Rotating sentinel searchlights | |
| self.sentinels = [ | |
| {"id": 301, "x": 0.0, "y": 2.2, "angle": 0.0, "angular_vel": 0.045, "range": 3.0, "cone_half_angle": 0.42, "alerted": False, "color": "orange"}, | |
| {"id": 302, "x": 0.0, "y": -2.2, "angle": math.pi, "angular_vel": -0.045, "range": 3.0, "cone_half_angle": 0.42, "alerted": False, "color": "orange"}, | |
| ] | |
| # Acoustic sound tripwire across central crossing | |
| self.sound_tripwires = [ | |
| {"id": "trip1", "x1": -1.0, "y1": 0.0, "x2": 1.0, "y2": 0.0, "max_safe_speed": 0.28} | |
| ] | |
| # Extraction beacon | |
| self._obj("target", 3.8, -3.8, "cyan", r=0.42, movable=False) | |
| # Stealth decoy orbs | |
| self._obj("food", -3.6, 3.6, "gold", r=0.26, movable=False) | |
| def _setup_kinetic_foundry(self): | |
| """Kinetic foundry: opposing directional conveyor belts, movable cargo box, and pressure plate reactor unlock.""" | |
| self.objects.clear() | |
| self.walls = self._border() | |
| # Opposing conveyor belts | |
| self.terrain_zones = [ | |
| {"kind": "conveyor", "x": -2.2, "y": 0.0, "r": 1.7, "friction": 0.9, "vx": 0.16, "vy": 0.0, "color": "orange"}, | |
| {"kind": "conveyor", "x": 2.2, "y": 0.0, "r": 1.7, "friction": 0.9, "vx": -0.16, "vy": 0.0, "color": "orange"}, | |
| {"kind": "conveyor", "x": 0.0, "y": -2.4, "r": 1.5, "friction": 0.9, "vx": 0.0, "vy": 0.16, "color": "orange"}, | |
| ] | |
| # Industrial blast barrier | |
| self.walls.extend([ | |
| (-5.0, 2.0, -1.2, 2.0), | |
| (1.2, 2.0, 5.0, 2.0), | |
| ]) | |
| self.dynamic_gates = [ | |
| {"id": "blast_door", "x1": -1.2, "y1": 2.0, "x2": 1.2, "y2": 2.0, "open": False, "locked": True} | |
| ] | |
| # Heavy cargo box | |
| self._obj("box", -2.2, 0.0, "grey", r=0.45, movable=True, solid=True) | |
| # Pressure sensor pad | |
| self._obj("pad", 2.2, 0.0, "yellow", r=0.60, shape="pad", movable=False, solid=False) | |
| # Foundry reactor core target | |
| self._obj("target", 0.0, 3.8, "purple", r=0.45, movable=False) | |
| def _setup_quantum_bifurcation(self): | |
| """Quantum bifurcation: dual phase-shifting bridge gates over a cross-current, entangled cue switch, and decoy vault.""" | |
| self.objects.clear() | |
| self.walls = self._border() | |
| # Bifurcating corridor walls | |
| self.walls.extend([ | |
| (-1.0, -5.0, -1.0, -1.6), | |
| (-1.0, 1.6, -1.0, 5.0), | |
| (1.6, -1.2, 5.0, -1.2), | |
| (1.6, 1.2, 5.0, 1.2), | |
| ]) | |
| # River current + ice slip zone + shadow cloak pocket | |
| self.terrain_zones = [ | |
| {"kind": "river", "x": 0.2, "y": 0.0, "r": 1.9, "friction": 1.05, "vx": 0.0, "vy": 0.14, "color": "blue"}, | |
| {"kind": "ice", "x": -2.8, "y": 0.0, "r": 1.4, "friction": 0.28, "color": "cyan"}, | |
| {"kind": "shadow", "x": 2.4, "y": 0.0, "r": 1.2, "friction": 1.0, "color": "purple"}, | |
| ] | |
| # Elevation basin & plateau | |
| self.elevation_hills = [ | |
| {"x": -2.5, "y": -2.5, "height": 1.4, "sigma": 1.3}, | |
| {"x": 2.5, "y": 2.8, "height": -1.3, "sigma": 1.3}, | |
| ] | |
| # Dual phase-shifting gates (one locked by entanglement button, one oscillating) | |
| self.dynamic_gates = [ | |
| {"id": "phase_bridge_north", "x1": -1.0, "y1": 0.0, "x2": -1.0, "y2": 1.6, "open": True, "timer": 10}, | |
| {"id": "phase_bridge_south", "x1": -1.0, "y1": -1.6, "x2": -1.0, "y2": 0.0, "open": False, "locked": True}, | |
| ] | |
| # Rotating sentinel guarding the bifurcation nexus | |
| self.sentinels = [ | |
| {"id": 401, "x": 1.4, "y": 0.0, "angle": 0.0, "angular_vel": 0.05, "range": 2.6, "cone_half_angle": 0.40, "alerted": False, "color": "orange"} | |
| ] | |
| # Entanglement calibration switch & quantum target core | |
| self._obj("button", -3.2, -2.5, "yellow", r=0.35, shape="button", movable=False, solid=False, pressed=False) | |
| self._obj("target", 3.8, 0.0, "cyan", r=0.44, movable=False) | |
| self._obj("food", -3.0, 2.5, "gold", r=0.28, movable=False) | |
| self._obj("food", 0.3, -2.8, "green", r=0.25, movable=False) | |
| def _setup_cybernetic_sanctuary(self): | |
| """Cybernetic sanctuary: autonomous cooperative helper drone with protective shield field, bio-reactor valves, and pack hunters.""" | |
| self.objects.clear() | |
| self.walls = self._border() | |
| # Sanctuary inner ring walls | |
| self.walls.extend([ | |
| (1.8, -5.0, 1.8, -1.1), | |
| (1.8, 1.1, 1.8, 5.0), | |
| ]) | |
| self.dynamic_gates = [ | |
| {"id": "sanctuary_bulkhead", "x1": 1.8, "y1": -1.1, "x2": 1.8, "y2": 1.1, "open": False, "locked": True} | |
| ] | |
| self.terrain_zones = [ | |
| {"kind": "conveyor", "x": -1.8, "y": 1.8, "r": 1.5, "friction": 0.9, "vx": 0.14, "vy": -0.06, "color": "orange"}, | |
| {"kind": "shadow", "x": -0.5, "y": -2.2, "r": 1.4, "friction": 1.0, "color": "purple"}, | |
| ] | |
| # Cooperative Helper Drone (orbits and projects a stabilizing shield aura) | |
| self.helper_drones = [ | |
| { | |
| "id": 501, | |
| "x": 1.0, | |
| "y": 0.0, | |
| "th": 0.0, | |
| "orbit_angle": 0.0, | |
| "orbit_center": [-0.6, 0.0], | |
| "orbit_radius": 1.6, | |
| "shield_radius": 1.6, | |
| "r": 0.32, | |
| "kind": "guardian_drone", | |
| "color": "cyan", | |
| "active": True, | |
| } | |
| ] | |
| # Perimeter stalker drone | |
| self.predators.append({ | |
| "id": 205, | |
| "x": -3.2, | |
| "y": -3.0, | |
| "th": 0.5, | |
| "speed": 0.12, | |
| "kind": "pack_leader", | |
| "r": 0.36, | |
| "color": "red", | |
| "alerted": False, | |
| }) | |
| # Bio-reactor valve button & sanctuary core target | |
| self._obj("button", -2.8, 2.4, "yellow", r=0.36, shape="button", movable=False, solid=False, pressed=False) | |
| self._obj("target", 3.6, 0.0, "gold", r=0.45, movable=False) | |
| for _ in range(3): | |
| spot = self._free_spot(avoid=[(o['x'], o['y']) for o in self.objects]) | |
| self._obj("food", spot[0], spot[1], "green", r=0.25, movable=False) | |
| def _setup_continental_biosphere(self): | |
| """Mega-scale 17x17 (arena_half=8.5) multi-biome continental ecosystem with wormhole relays, weather storms, 3 predator packs, and 2 guardian drones.""" | |
| self.arena_half = 8.5 | |
| self.max_t = 700 | |
| self.objects.clear() | |
| self.walls = self._border(self.arena_half) | |
| self.a.update(x=-6.5, y=-6.0, th=0.4) | |
| # Continental mountain ridge barriers with central canyon gates | |
| self.walls.extend([ | |
| (-1.5, -8.5, -1.5, -2.5), | |
| (-1.5, 2.5, -1.5, 8.5), | |
| (3.5, -8.5, 3.5, -1.8), | |
| (3.5, 1.8, 3.5, 8.5), | |
| ]) | |
| self.dynamic_gates = [ | |
| {"id": "canyon_west_gate", "x1": -1.5, "y1": -2.5, "x2": -1.5, "y2": 2.5, "open": True, "timer": 10}, | |
| {"id": "citadel_east_gate", "x1": 3.5, "y1": -1.8, "x2": 3.5, "y2": 1.8, "open": False, "locked": True}, | |
| ] | |
| # 5 Continental Biomes | |
| self.terrain_zones = [ | |
| {"kind": "ice", "x": -5.2, "y": 4.8, "r": 2.6, "friction": 0.25, "color": "cyan"}, | |
| {"kind": "sand", "x": -4.8, "y": -4.5, "r": 2.5, "friction": 2.35, "color": "yellow"}, | |
| {"kind": "river", "x": 1.0, "y": 0.0, "r": 2.8, "friction": 1.10, "vx": 0.0, "vy": -0.16, "color": "blue"}, | |
| {"kind": "mud", "x": 1.2, "y": -5.5, "r": 2.2, "friction": 1.85, "color": "grey"}, | |
| {"kind": "shadow", "x": 1.0, "y": 5.2, "r": 2.2, "friction": 1.0, "color": "purple"}, | |
| ] | |
| # 3 Topographic Mountain / Basin Elevation Hills | |
| self.elevation_hills = [ | |
| {"x": -5.0, "y": 0.5, "height": 2.2, "sigma": 2.0}, | |
| {"x": 1.0, "y": 3.5, "height": -1.8, "sigma": 1.8}, | |
| {"x": 6.0, "y": -4.0, "height": 2.0, "sigma": 1.9}, | |
| ] | |
| # Paired Quantum Wormhole Relay (transports agent from (-6.0, 6.0) <-> (2.2, -6.0)) | |
| self.wormholes = [ | |
| {"id": "wormhole_alpha", "label": "ALPHA RELAY", "x": -6.0, "y": 6.0, "x1": -6.0, "y1": 6.0, "x2": 2.2, "y2": -6.0, "r": 0.75, "target_x": 2.2, "target_y": -6.0, "color": "#00e5ff"}, | |
| {"id": "wormhole_omega", "label": "OMEGA RELAY", "x": 2.2, "y": -6.0, "x1": 2.2, "y1": -6.0, "x2": -6.0, "y2": 6.0, "r": 0.75, "target_x": -6.0, "target_y": 6.0, "color": "#c084fc"}, | |
| ] | |
| # Dynamic Electromagnetic Weather Storm Fronts | |
| self.weather_fronts = [ | |
| {"id": "ion_storm_1", "kind": "ion_storm", "x": -2.0, "y": 0.0, "r": 2.4, "vx": 0.05, "vy": 0.04, "wind_x": -0.05, "wind_y": 0.04, "sensor_noise": 0.03}, | |
| {"id": "monsoon_squall_2", "kind": "monsoon_squall", "x": 4.2, "y": -2.5, "r": 2.1, "vx": -0.04, "vy": 0.05, "wind_x": 0.04, "wind_y": -0.03, "sensor_noise": 0.025}, | |
| ] | |
| # 2 Cooperative Guardian Drones | |
| self.helper_drones = [ | |
| { | |
| "id": 601, "x": -1.4, "y": 0.0, "th": 0.0, | |
| "orbit_angle": 0.0, "orbit_center": [-3.4, 0.0], | |
| "orbit_radius": 2.0, "shield_radius": 1.9, "r": 0.34, | |
| "kind": "guardian_drone", "color": "cyan", "active": True, | |
| }, | |
| { | |
| "id": 602, "x": 3.0, "y": 0.0, "th": math.pi, | |
| "orbit_angle": math.pi, "orbit_center": [1.0, 0.0], | |
| "orbit_radius": 2.0, "shield_radius": 1.9, "r": 0.34, | |
| "kind": "guardian_drone", "color": "cyan", "active": True, | |
| }, | |
| ] | |
| # 3 Coordinated Predator Drones | |
| self.predators.extend([ | |
| {"id": 301, "x": -4.5, "y": 3.5, "th": 0.0, "speed": 0.14, "kind": "pack_leader", "r": 0.38, "color": "red", "alerted": False}, | |
| {"id": 302, "x": 0.8, "y": -3.8, "th": 1.2, "speed": 0.15, "kind": "pack_hunter", "r": 0.38, "color": "purple", "alerted": False}, | |
| {"id": 303, "x": 5.5, "y": 4.2, "th": -1.0, "speed": 0.13, "kind": "stalker", "r": 0.38, "color": "red", "alerted": False}, | |
| ]) | |
| self._obj("button", 1.2, 5.2, "yellow", r=0.40, shape="button", movable=False, solid=False, pressed=False) | |
| self._obj("target", 6.8, 0.0, "gold", r=0.50, movable=False) | |
| for fx, fy in [(-6.2, -1.5), (-3.0, 5.5), (0.0, -6.2), (2.2, 2.8), (5.8, -5.5), (6.0, 5.0)]: | |
| self._obj("food", fx, fy, "green", r=0.28, movable=False) | |
| def _setup_chrono_tidepool_citadel(self): | |
| """Poseidon Tidepool v2 inspired 15x15 (arena_half=7.5) observation-aliased tidal arena with periodic surge waves and cue beacons.""" | |
| self.arena_half = 7.5 | |
| self.max_t = 650 | |
| self.objects.clear() | |
| self.walls = self._border(self.arena_half) | |
| self.a.update(x=-5.8, y=0.0, th=0.0) | |
| self.cue = np.array([1.0, 0.0, 0.5, -0.5], dtype=np.float32) | |
| # Citadel inner sanctum walls | |
| self.walls.extend([ | |
| (2.8, -7.5, 2.8, -1.4), | |
| (2.8, 1.4, 2.8, 7.5), | |
| ]) | |
| self.dynamic_gates = [ | |
| {"id": "tidepool_sluice", "x1": 2.8, "y1": -1.4, "x2": 2.8, "y2": 1.4, "open": False, "locked": True}, | |
| ] | |
| # Tidal surge vector channels & stealth kelp shadow zones | |
| self.terrain_zones = [ | |
| {"kind": "river", "x": -1.5, "y": 2.8, "r": 2.4, "friction": 1.15, "vx": -0.14, "vy": 0.08, "color": "blue"}, | |
| {"kind": "river", "x": -1.5, "y": -2.8, "r": 2.4, "friction": 1.15, "vx": 0.14, "vy": -0.08, "color": "cyan"}, | |
| {"kind": "shadow", "x": -4.0, "y": 0.0, "r": 1.8, "friction": 1.0, "color": "purple"}, | |
| {"kind": "sand", "x": 1.0, "y": 0.0, "r": 2.0, "friction": 2.10, "color": "yellow"}, | |
| ] | |
| self.wormholes = [ | |
| {"id": "tide_relay_north", "label": "TIDE RELAY N", "x": -5.0, "y": 5.2, "x1": -5.0, "y1": 5.2, "x2": 1.2, "y2": -4.8, "r": 0.70, "target_x": 1.2, "target_y": -4.8, "color": "#00e5ff"}, | |
| {"id": "tide_relay_south", "label": "TIDE RELAY S", "x": 1.2, "y": -4.8, "x1": 1.2, "y1": -4.8, "x2": -5.0, "y2": 5.2, "r": 0.70, "target_x": -5.0, "target_y": 5.2, "color": "#c084fc"}, | |
| ] | |
| self.weather_fronts = [ | |
| {"id": "tidal_squall", "kind": "tidal_squall", "x": 0.0, "y": 0.0, "r": 2.6, "vx": 0.04, "vy": -0.05, "wind_x": -0.06, "wind_y": 0.03, "sensor_noise": 0.04} | |
| ] | |
| self.sentinels = [ | |
| {"id": 410, "x": 0.5, "y": 3.5, "angle": 0.0, "angular_vel": 0.045, "range": 3.8, "cone_half_angle": 0.38, "color": "yellow", "alerted": False}, | |
| {"id": 411, "x": 0.5, "y": -3.5, "angle": math.pi, "angular_vel": -0.045, "range": 3.8, "cone_half_angle": 0.38, "color": "yellow", "alerted": False}, | |
| ] | |
| self.helper_drones = [ | |
| { | |
| "id": 610, "x": 0.3, "y": 0.0, "th": 0.0, | |
| "orbit_angle": 0.0, "orbit_center": [-1.5, 0.0], | |
| "orbit_radius": 1.8, "shield_radius": 1.75, "r": 0.32, | |
| "kind": "guardian_drone", "color": "cyan", "active": True, | |
| } | |
| ] | |
| self.predators.append({ | |
| "id": 310, "x": 4.8, "y": 3.2, "th": -1.5, "speed": 0.14, "kind": "pursuer", "r": 0.38, "color": "red", "alerted": False | |
| }) | |
| self._obj("button", -1.2, -4.8, "yellow", r=0.38, shape="button", movable=False, solid=False, pressed=False) | |
| self._obj("target", 5.8, 0.0, "gold", r=0.48, movable=False) | |
| for fx, fy in [(-4.5, -3.5), (-2.0, 4.8), (1.5, 4.2), (5.0, -3.5)]: | |
| self._obj("food", fx, fy, "green", r=0.26, movable=False) | |
| # ------------------------------------------------------------------ | |
| # Step Physics & Environmental Updates | |
| # ------------------------------------------------------------------ | |
| def step(self, action: np.ndarray): | |
| from .actions import DRIVE, validate_action | |
| action = validate_action(action) | |
| # 1. Terrain zone physics (modulate thrust/turn and compute flow displacement) | |
| current_friction = 1.0 | |
| in_friction_zone = False | |
| flow_dx, flow_dy = 0.0, 0.0 | |
| ax, ay = self.a["x"], self.a["y"] | |
| for zone in self.terrain_zones: | |
| dist = math.hypot(ax - zone["x"], ay - zone["y"]) | |
| if dist < zone["r"]: | |
| current_friction = zone.get("friction", 1.0) | |
| flow_dx += zone.get("vx", 0.0) | |
| flow_dy += zone.get("vy", 0.0) | |
| in_friction_zone = True | |
| # Adjust effective action under terrain friction | |
| eff_action = action.copy() | |
| eff_action[DRIVE] = np.clip(eff_action[DRIVE] / current_friction, -1, 1) | |
| # 2. Step base environment | |
| _, reward, done, info = super().step(eff_action) | |
| base_reward = reward | |
| ax, ay = self.a['x'], self.a['y'] | |
| info["in_friction_zone"] = in_friction_zone | |
| info["terrain_friction"] = current_friction | |
| # 3. Vector Flow Displacement & Object Current Physics | |
| arena_bound = float(getattr(self, "arena_half", HALF)) | |
| if flow_dx != 0.0 or flow_dy != 0.0: | |
| h = arena_bound - 0.35 | |
| self.a["x"] = float(np.clip(self.a["x"] + flow_dx, -h, h)) | |
| self.a["y"] = float(np.clip(self.a["y"] + flow_dy, -h, h)) | |
| ax, ay = self.a["x"], self.a["y"] | |
| # Move movable objects caught in vector flow zones | |
| for obj in self.objects: | |
| if obj.get("movable") and not obj.get("held"): | |
| for zone in self.terrain_zones: | |
| if math.hypot(obj["x"] - zone["x"], obj["y"] - zone["y"]) < zone["r"]: | |
| obj["x"] = float(np.clip(obj["x"] + zone.get("vx", 0.0), -arena_bound + 0.35, arena_bound - 0.35)) | |
| obj["y"] = float(np.clip(obj["y"] + zone.get("vy", 0.0), -arena_bound + 0.35, arena_bound - 0.35)) | |
| # 4. Topographic Elevation Gravity Gradient | |
| if self.elevation_hills: | |
| gx, gy = 0.0, 0.0 | |
| for hill in self.elevation_hills: | |
| hx, hy = hill["x"], hill["y"] | |
| H, sigma = hill["height"], hill["sigma"] | |
| dx = ax - hx | |
| dy = ay - hy | |
| d2 = dx * dx + dy * dy | |
| val = H * math.exp(-d2 / (2.0 * sigma * sigma)) | |
| gx += - (dx / (sigma * sigma)) * val | |
| gy += - (dy / (sigma * sigma)) * val | |
| # Gravitational drift acceleration applied to agent | |
| h = arena_bound - 0.35 | |
| self.a["x"] = float(np.clip(self.a["x"] - 0.04 * gx, -h, h)) | |
| self.a["y"] = float(np.clip(self.a["y"] - 0.04 * gy, -h, h)) | |
| ax, ay = self.a["x"], self.a["y"] | |
| info["elevation_gradient"] = [round(float(gx), 4), round(float(gy), 4)] | |
| # 5. Dynamic Gates & Puzzle Locks | |
| for gate in self.dynamic_gates: | |
| if gate.get("locked"): | |
| # Check if puzzle button was pressed or box is placed on pad | |
| button_pressed = any(obj.get("kind") == "button" and obj.get("pressed") for obj in self.objects) | |
| box_on_pad = False | |
| box = next((o for o in self.objects if o.get("kind") == "box"), None) | |
| pad = next((o for o in self.objects if o.get("kind") == "pad"), None) | |
| if box and pad and math.hypot(box["x"] - pad["x"], box["y"] - pad["y"]) < 0.65: | |
| box_on_pad = True | |
| if button_pressed or box_on_pad: | |
| gate["open"] = True | |
| else: | |
| gate["timer"] = (gate.get("timer", 0) + 1) % 50 | |
| gate["open"] = gate["timer"] < 25 | |
| # Rebuild walls including currently closed gates | |
| if self.dynamic_gates: | |
| active_walls = self.base_walls.copy() | |
| for gate in self.dynamic_gates: | |
| if not gate.get("open", False): | |
| active_walls.append((gate["x1"], gate["y1"], gate["x2"], gate["y2"])) | |
| self.walls = active_walls | |
| # 6. Coordinated Predator Pack Dynamics | |
| min_hazard_dist = 10.0 | |
| pack_alerted = any(p.get("alerted", False) for p in self.predators) | |
| # Check if any predator spots agent | |
| for pred in self.predators: | |
| p_dist = math.hypot(ax - pred["x"], ay - pred["y"]) | |
| if p_dist < 3.5: | |
| pred["alerted"] = True | |
| pack_alerted = True | |
| for pred in self.predators: | |
| if pack_alerted: | |
| pred["alerted"] = True | |
| p_dx = ax - pred["x"] | |
| p_dy = ay - pred["y"] | |
| dist_to_agent = math.hypot(p_dx, p_dy) | |
| if pred["kind"] == "pursuer" or (pred.get("alerted") and pred["kind"] in ("pack_leader", "stalker")): | |
| # Direct chase steering | |
| desired_th = math.atan2(p_dy, p_dx) | |
| pred["th"] += 0.14 * math.sin(desired_th - pred["th"]) | |
| elif pred.get("alerted") and pred["kind"] == "pack_hunter": | |
| # Flanking pursuit: steer toward predicted lead position | |
| lead_x = ax + math.cos(self.a["th"]) * self.a["v"] * 2.0 | |
| lead_y = ay + math.sin(self.a["th"]) * self.a["v"] * 2.0 | |
| desired_th = math.atan2(lead_y - pred["y"], lead_x - pred["x"]) | |
| pred["th"] += 0.16 * math.sin(desired_th - pred["th"]) | |
| else: | |
| # Patrol bounce | |
| pred["th"] += float(self.rng_complex.normal(0.0, 0.08)) | |
| # Move predator | |
| pred_speed = pred["speed"] * (1.3 if pred.get("alerted") else 1.0) | |
| pred["x"] += math.cos(pred["th"]) * pred_speed | |
| pred["y"] += math.sin(pred["th"]) * pred_speed | |
| # Arena boundary bounce | |
| h = arena_bound - 0.5 | |
| if pred["x"] < -h or pred["x"] > h: | |
| pred["th"] = math.pi - pred["th"] | |
| pred["x"] = float(np.clip(pred["x"], -h, h)) | |
| if pred["y"] < -h or pred["y"] > h: | |
| pred["th"] = -pred["th"] | |
| pred["y"] = float(np.clip(pred["y"], -h, h)) | |
| # Collision with agent | |
| dist_to_agent = math.hypot(ax - pred['x'], ay - pred['y']) | |
| min_hazard_dist = min(min_hazard_dist, dist_to_agent) | |
| if dist_to_agent < (pred["r"] + 0.35): | |
| reward -= 0.45 | |
| info["predator_impact"] = True | |
| info["min_hazard_dist"] = min_hazard_dist | |
| # 7. Rotating Sentinel Searchlights & Stealth Cloak Mechanics | |
| alarm_tripped = False | |
| in_shadow = any( | |
| tz.get("kind") == "shadow" and math.hypot(ax - tz["x"], ay - tz["y"]) < tz["r"] | |
| for tz in self.terrain_zones | |
| ) | |
| info["in_shadow"] = in_shadow | |
| for sentinel in self.sentinels: | |
| sentinel["angle"] = (sentinel["angle"] + sentinel.get("angular_vel", 0.04)) % (math.pi * 2) | |
| if not in_shadow: | |
| s_dx = ax - sentinel["x"] | |
| s_dy = ay - sentinel["y"] | |
| s_dist = math.hypot(s_dx, s_dy) | |
| if s_dist < sentinel["range"]: | |
| rel_angle = (math.atan2(s_dy, s_dx) - sentinel["angle"] + math.pi) % (math.pi * 2) - math.pi | |
| if abs(rel_angle) < sentinel["cone_half_angle"]: | |
| sentinel["alerted"] = True | |
| alarm_tripped = True | |
| reward -= 0.30 | |
| sentinel["color"] = "red" | |
| # 8. Acoustic Sound Tripwires | |
| agent_speed = abs(self.a["v"]) | |
| for trip in self.sound_tripwires: | |
| # Check segment proximity | |
| t_x1, t_y1, t_x2, t_y2 = trip["x1"], trip["y1"], trip["x2"], trip["y2"] | |
| seg_dist = abs((t_y2 - t_y1) * ax - (t_x2 - t_x1) * ay + t_x2 * t_y1 - t_y2 * t_x1) / max(1e-5, math.hypot(t_y2 - t_y1, t_x2 - t_x1)) | |
| if seg_dist < 0.4 and min(t_x1, t_x2) - 0.2 <= ax <= max(t_x1, t_x2) + 0.2 and min(t_y1, t_y2) - 0.2 <= ay <= max(t_y1, t_y2) + 0.2: | |
| if agent_speed > trip.get("max_safe_speed", 0.30): | |
| alarm_tripped = True | |
| reward -= 0.25 | |
| self.last_alarm_tripped = alarm_tripped | |
| info["alarm_tripped"] = alarm_tripped | |
| # 9. Ecological Food Respawn | |
| self.food_respawn_timer += 1 | |
| if self.task in ("ecosystem", "apex_megasite") and self.food_respawn_timer % 40 == 0: | |
| current_food = sum(1 for o in self.objects if o.get("kind") == "food" and o.get("visible", True)) | |
| max_food = 6 if self.task == "ecosystem" else 4 | |
| if current_food < max_food: | |
| spot = self._free_spot(avoid=[(o['x'], o['y']) for o in self.objects]) | |
| self._obj("food", spot[0], spot[1], "green", r=0.25, movable=False) | |
| # 10. Ambient Illumination Cycle & Cooperative Helper Drones | |
| self.day_night_clock += 0.015 | |
| self.ambient_light = float(0.65 + 0.35 * math.sin(self.day_night_clock)) | |
| info["ambient_light"] = self.ambient_light | |
| helper_shield_active = False | |
| for drone in self.helper_drones: | |
| drone["orbit_angle"] = float(drone.get("orbit_angle", 0.0) + 0.065) % (math.pi * 2) | |
| cx, cy = drone.get("orbit_center", [0.0, 0.0]) | |
| rad = float(drone.get("orbit_radius", 1.5)) | |
| nx = float(cx + math.cos(drone["orbit_angle"]) * rad) | |
| ny = float(cy + math.sin(drone["orbit_angle"]) * rad) | |
| drone["th"] = float(math.atan2(ny - drone["y"], nx - drone["x"])) | |
| drone["x"], drone["y"] = nx, ny | |
| if math.hypot(ax - nx, ay - ny) <= float(drone.get("shield_radius", 1.6)): | |
| helper_shield_active = True | |
| reward += 0.04 | |
| info["min_hazard_dist"] = max(float(info.get("min_hazard_dist", 10.0)), 6.0) | |
| info["helper_shield_active"] = helper_shield_active | |
| # 10b. Wormhole Teleportation Relays & Weather Storm Fronts | |
| if getattr(self, "wormhole_cooldown", 0) > 0: | |
| self.wormhole_cooldown -= 1 | |
| wormhole_teleported = False | |
| for wh in getattr(self, "wormholes", []): | |
| if self.wormhole_cooldown == 0 and math.hypot(ax - wh["x"], ay - wh["y"]) <= float(wh.get("r", 0.75)): | |
| self.a["x"] = float(wh["target_x"]) | |
| self.a["y"] = float(wh["target_y"]) | |
| ax, ay = self.a["x"], self.a["y"] | |
| self.wormhole_cooldown = 18 | |
| wormhole_teleported = True | |
| reward += 0.15 | |
| break | |
| info["wormhole_teleported"] = wormhole_teleported | |
| in_weather_storm = False | |
| for storm in getattr(self, "weather_fronts", []): | |
| storm["x"] = float(storm["x"] + storm.get("vx", 0.03)) | |
| storm["y"] = float(storm["y"] + storm.get("vy", 0.02)) | |
| sb = arena_bound - 1.2 | |
| if abs(storm["x"]) > sb: | |
| storm["vx"] = -storm.get("vx", 0.03) | |
| storm["x"] = float(np.clip(storm["x"], -sb, sb)) | |
| if abs(storm["y"]) > sb: | |
| storm["vy"] = -storm.get("vy", 0.02) | |
| storm["y"] = float(np.clip(storm["y"], -sb, sb)) | |
| if math.hypot(ax - storm["x"], ay - storm["y"]) <= float(storm.get("r", 2.4)): | |
| in_weather_storm = True | |
| h = arena_bound - 0.35 | |
| self.a["x"] = float(np.clip(self.a["x"] + storm.get("wind_x", 0.0), -h, h)) | |
| self.a["y"] = float(np.clip(self.a["y"] + storm.get("wind_y", 0.0), -h, h)) | |
| ax, ay = self.a["x"], self.a["y"] | |
| info["in_weather_storm"] = in_weather_storm | |
| # 11. Complex Task Completion and Terminal Goal Rewards | |
| target_obj = next((o for o in self.objects if o.get("kind") == "target"), None) | |
| if target_obj is not None: | |
| dist_to_target = math.hypot(ax - target_obj["x"], ay - target_obj["y"]) | |
| if dist_to_target < (target_obj.get("r", 0.4) + 0.25): | |
| if self.task in ("puzzle_chamber", "cybernetic_sanctuary", "continental_biosphere", "chrono_tidepool_citadel"): | |
| btn = next((o for o in self.objects if o.get("kind") == "button"), None) | |
| if btn and btn.get("pressed"): | |
| done = True | |
| reward += 6.0 if self.task == "puzzle_chamber" else 9.0 | |
| info["outcome"] = "success" | |
| elif self.task in ("dynamic_arena", "apex_megasite", "stealth_labyrinth", "kinetic_foundry", "quantum_bifurcation"): | |
| done = True | |
| reward += 8.0 | |
| info["outcome"] = "success" | |
| # Update episode accounting | |
| self.ep_return += (reward - base_reward) | |
| self.last_reward = reward | |
| if done: | |
| info['ret'] = self.ep_return | |
| return self.observe(), reward, done, info | |
| def _progress(self) -> float: | |
| """Task potential progress function across both base and frontier tasks.""" | |
| t = self.task | |
| ax, ay = self.a["x"], self.a["y"] | |
| if t in ("ecosystem", "predator_evasion"): | |
| visible_food = [o for o in self.objects if o.get("kind") == "food" and o.get("visible", True)] | |
| if visible_food: | |
| min_f = min(math.hypot(ax - f["x"], ay - f["y"]) for f in visible_food) | |
| pot = -min_f | |
| else: | |
| pot = 0.0 | |
| if t == "predator_evasion" and self.predators: | |
| min_p = min(math.hypot(ax - p["x"], ay - p["y"]) for p in self.predators) | |
| pot += 0.25 * min_p | |
| return pot | |
| if t == "dynamic_arena": | |
| target = next((o for o in self.objects if o.get("kind") == "target"), None) | |
| return -math.hypot(ax - target["x"], ay - target["y"]) if target else 0.0 | |
| if t == "puzzle_chamber": | |
| btn = next((o for o in self.objects if o.get("kind") == "button"), None) | |
| target = next((o for o in self.objects if o.get("kind") == "target"), None) | |
| if btn and not btn.get("pressed"): | |
| return -math.hypot(ax - btn["x"], ay - btn["y"]) | |
| if target: | |
| return 2.0 - math.hypot(ax - target["x"], ay - target["y"]) | |
| return 0.0 | |
| if t == "apex_megasite": | |
| btn = next((o for o in self.objects if o.get("kind") == "button"), None) | |
| target = next((o for o in self.objects if o.get("kind") == "target"), None) | |
| if btn and not btn.get("pressed"): | |
| return -math.hypot(ax - btn["x"], ay - btn["y"]) | |
| if target: | |
| return 3.0 - math.hypot(ax - target["x"], ay - target["y"]) | |
| return 0.0 | |
| if t == "stealth_labyrinth": | |
| target = next((o for o in self.objects if o.get("kind") == "target"), None) | |
| alarm_pen = -1.0 if getattr(self, "last_alarm_tripped", False) else 0.0 | |
| return (-math.hypot(ax - target["x"], ay - target["y"]) + alarm_pen) if target else 0.0 | |
| if t == "kinetic_foundry": | |
| box = next((o for o in self.objects if o.get("kind") == "box"), None) | |
| pad = next((o for o in self.objects if o.get("kind") == "pad"), None) | |
| target = next((o for o in self.objects if o.get("kind") == "target"), None) | |
| if box and pad: | |
| box_pad_dist = math.hypot(box["x"] - pad["x"], box["y"] - pad["y"]) | |
| if box_pad_dist > 0.65: | |
| return -math.hypot(ax - box["x"], ay - box["y"]) - 1.5 * box_pad_dist | |
| if target: | |
| return 3.0 - math.hypot(ax - target["x"], ay - target["y"]) | |
| return 0.0 | |
| if t in ("quantum_bifurcation", "cybernetic_sanctuary", "continental_biosphere", "chrono_tidepool_citadel"): | |
| btn = next((o for o in self.objects if o.get("kind") == "button"), None) | |
| target = next((o for o in self.objects if o.get("kind") == "target"), None) | |
| if btn and not btn.get("pressed"): | |
| return -math.hypot(ax - btn["x"], ay - btn["y"]) | |
| if target: | |
| return 3.0 - math.hypot(ax - target["x"], ay - target["y"]) | |
| return 0.0 | |
| # Delegate base tasks to BaseWorld._progress | |
| return super()._progress() | |
| def observe(self): | |
| """Generates 155-dim sensory observation with ambient lighting modulation.""" | |
| a = self.a | |
| prop = [ | |
| (a["reach"] - 0.25) / 0.65, | |
| a["height"] / 0.75, | |
| a["grip"], | |
| float(a["held"] is not None), | |
| a["v"] / 1.4, | |
| a["w"] / 2.5, | |
| math.sin(a["th"]), | |
| math.cos(a["th"]), | |
| ] | |
| if self.task in BASE_TASKS: | |
| onehot = np.eye(len(BASE_TASKS))[BASE_TASKS.index(self.task)] | |
| else: | |
| idx = (BASE_TASKS.index("forage") + COMPLEX_TASKS.index(self.task)) % len(BASE_TASKS) | |
| onehot = np.eye(len(BASE_TASKS))[idx] | |
| ret = self.retina() | |
| if hasattr(self, "ambient_light") and self.ambient_light != 1.0: | |
| ret = ret * float(self.ambient_light) | |
| return np.concatenate([ret, prop, onehot, self.cue, [self.last_reward, self.t / self.max_t]]).astype(np.float32) | |
| def snapshot(self) -> Dict[str, Any]: | |
| """Extends snapshot with predators, terrain zones, vector fields, sentinels, and elevation hills.""" | |
| snap = super().snapshot() | |
| snap["predators"] = [ | |
| { | |
| "id": p["id"], | |
| "x": round(float(p["x"]), 3), | |
| "y": round(float(p["y"]), 3), | |
| "th": round(float(p["th"]), 3), | |
| "r": p["r"], | |
| "kind": p["kind"], | |
| "color": p["color"], | |
| "alerted": p.get("alerted", False), | |
| } | |
| for p in self.predators | |
| ] | |
| snap["terrain_zones"] = self.terrain_zones | |
| snap["dynamic_gates"] = self.dynamic_gates | |
| snap["elevation_hills"] = self.elevation_hills | |
| snap["sentinels"] = self.sentinels | |
| snap["sound_tripwires"] = self.sound_tripwires | |
| snap["helper_drones"] = [ | |
| { | |
| "id": d["id"], | |
| "x": round(float(d["x"]), 3), | |
| "y": round(float(d["y"]), 3), | |
| "th": round(float(d.get("th", 0.0)), 3), | |
| "r": d.get("r", 0.32), | |
| "shield_radius": d.get("shield_radius", 1.6), | |
| "kind": d.get("kind", "guardian_drone"), | |
| "color": d.get("color", "cyan"), | |
| } | |
| for d in self.helper_drones | |
| ] | |
| snap["ambient_light"] = round(self.ambient_light, 3) | |
| snap["alarm_tripped"] = self.last_alarm_tripped | |
| snap["half"] = round(float(getattr(self, "arena_half", HALF)), 3) | |
| snap["wormholes"] = [ | |
| { | |
| "id": wh["id"], | |
| "x": round(float(wh["x"]), 3), | |
| "y": round(float(wh["y"]), 3), | |
| "r": float(wh.get("r", 0.75)), | |
| "target_x": round(float(wh["target_x"]), 3), | |
| "target_y": round(float(wh["target_y"]), 3), | |
| "color": wh.get("color", "purple"), | |
| } | |
| for wh in getattr(self, "wormholes", []) | |
| ] | |
| snap["weather_fronts"] = [ | |
| { | |
| "id": wf["id"], | |
| "x": round(float(wf["x"]), 3), | |
| "y": round(float(wf["y"]), 3), | |
| "r": float(wf.get("r", 2.4)), | |
| "wind_x": round(float(wf.get("wind_x", 0.0)), 3), | |
| "wind_y": round(float(wf.get("wind_y", 0.0)), 3), | |
| } | |
| for wf in getattr(self, "weather_fronts", []) | |
| ] | |
| return snap | |