def _agent_teleports(self, arbiter, space, data): agent = self._get_agent_from_shape(arbiter.shapes[0]) teleport = self._get_scene_element_from_shape(arbiter.shapes[1]) if teleport is None or teleport.target is None or ( agent, teleport) in self._teleported: return True if agent.is_teleporting: return True if teleport.target.traversable: agent.position = teleport.target.position else: area_shape = teleport.target.physical_shape if area_shape == 'rectangle': width = teleport.target.width + agent.base_platform.radius * 2 + 1 length = teleport.target.length + agent.base_platform.radius * 2 + 1 angle = teleport.target.angle sampler = CoordinateSampler( center=teleport.target.position, area_shape=area_shape, angle=angle, width_length=[width + 2, length + 2], excl_width_length=[width, length], ) else: radius = teleport.target.radius + agent.base_platform.radius + 1 sampler = CoordinateSampler( center=teleport.target.position, area_shape='circle', radius=radius, excl_radius=radius, ) agent.coordinates = sampler.sample() if (agent, teleport.target) not in self._teleported: self._teleported.append((agent, teleport.target)) agent.is_teleporting = True return True
class Dispenser(InteractiveSceneElement): """Dispenser produces a new entity in an area of the playground when activated. """ entity_type = SceneElementTypes.DISPENSER interactive = True def __init__(self, entity_produced, entity_produced_params=None, production_area=None, **kwargs): """ Default: pink circle of radius 15. Args: entity_produced: Class of the entity produced by the dispenser. entity_produced_params: Dictionary of additional parameters for the entity_produced. production_area: PositionAreaSampler. If no production_area has been set, the entities will be produced around the dispenser. **kwargs: other params to configure entity. Refer to Entity class. Keyword Args: production_limit: maximum number of entities produced. Default: 15. """ default_config = parse_configuration('element_interactive', self.entity_type) entity_params = {**default_config, **kwargs} super().__init__(**entity_params) self.pm_interaction_shape.collision_type = CollisionTypes.INTERACTIVE self.entity_produced = entity_produced if entity_produced_params is None: self.entity_produced_params = {} else: self.entity_produced_params = entity_produced_params if production_area is None: self.local_dispenser = True self.location_sampler = CoordinateSampler(area_shape='circle', center=[0, 0], radius=self.radius + 10) else: self.local_dispenser = False self.location_sampler = production_area self.production_limit = entity_params['production_limit'] self.produced_entities = [] @property def reward(self): return 0 def activate(self, _): elem_add = None if len(self.produced_entities ) < self.production_limit and self.activated is False: if self.local_dispenser: initial_coordinate = self.location_sampler.sample( self.position) else: initial_coordinate = self.location_sampler.sample() obj = self.entity_produced(is_temporary_entity=True, **self.entity_produced_params) self.produced_entities.append(obj) elem_add = (obj, initial_coordinate) self.activated = True return None, elem_add def reset(self): self.produced_entities = [] super().reset()