def attack(self, robot_id): """ Attacking is modelled on a Claymore. Damage is determined by the `inverse square`_ of the distance. .. _inverse square: http://en.wikipedia.org/wiki/Inverse-square_law """ loop = asyncio.get_event_loop() now = loop.time() attacker = self._robots[robot_id] if ( attacker['attacked_at'] is not None and (now - attacker['attacked_at']) * 1000 < settings['attack_interval'] ): # Attacker must wait a second before firing logger.info('{robot} unable to attack yet'.format(robot=attacker['instance'])) return attacker['attacked_at'] = now logger.info('{robot} attack'.format(robot=attacker['instance'])) for target in self.active_robots(): if is_in_angle(attacker['coords'], attacker['heading'], settings['attack_angle'], target['coords']): dist = get_dist(attacker['coords'], target['coords']) dist = max(dist, 1) # Make sure distance between robots is reasonable # Inverse square law. Drop values < 0 damage = int(settings['attack_damage'] / dist ** 2) if damage: logger.info('{robot} suffered {damage} damage'.format( robot=target['instance'], damage=damage)) target['damage'] += damage target['instance'].attacked().send(attacker['instance'].__class__.__name__)
def radar_updated(self): """ Stops when the robot is close to the middle """ while True: _ = yield # Are we there yet? dist = get_dist(self.coords, self._get_middle()) # TODO: Reduce speed as we approach if dist < 10: # Stop self.speed = 0
def _find_closest(self, radar, coords=None): """ Find the closest other robot. Returns coordinates, distance. """ if coords is None: coords = self.coords dist = closest = None for robot in radar: name = robot['name'] if name == self.__class__.__name__: continue d = get_dist(coords, robot['coords']) if dist is None or d < dist: dist = d closest = robot['coords'] return closest, dist