def _near_enough_to_aim(self, target): # Melee units (range <= 2) shouldn't attack units # on the other side of a wall. if not self._can_go(target.x, target.y) \ and self.range <= 2 * PRECISION \ and not target.blocked_exit: return False if self.minimal_range and square_of_distance(self.x, self.y, target.x, target.y) < self.minimal_range * self.minimal_range: return False d = target.aim_range(self) return square_of_distance(self.x, self.y, target.x, target.y) < d * d
def update(self): x, y = self.target u = self.unit subsquare = u.world.get_subsquare_id_from_xy d2 = square_of_distance(x, y, u.x, u.y) if subsquare(x, y) != subsquare(u.x, u.y): if u.go_to_xy(x, y): self.complete() else: # try as long as the distance is decreasing previous_d2 = square_of_distance(x, y, u.x, u.y) if u.go_to_xy( x, y) or square_of_distance(x, y, u.x, u.y) > previous_d2: self.complete()
def object_from_mousepos(self, pos): self._update_coefs() x, y = pos for o in self.interface.dobjets.values(): xo, yo = self._object_coords(o) if square_of_distance(x, y, xo, yo) <= R2 + 1: # XXX + 1 ? return o
def object_from_mousepos(self, pos): self._update_coefs() x, y = pos for o in self.interface.dobjets.values(): xo, yo = self._object_coords(o) if square_of_distance(x, y, xo, yo) <= R2 + 1: # is + 1 necessary? return o
def _near_enough_to_aim(self, target): # Melee units shouldn't attack units on the other side of a wall. if self.is_melee and not self._can_go( target.place) and not target.blocked_exit: return False if self.minimal_range and square_of_distance( self.x, self.y, target.x, target.y) < self.minimal_range * self.minimal_range: return False range = self.range if self.is_ballistic and self.height > target.height: # each height difference has a bonus of 1 bonus = (self.height - target.height) * PRECISION * 1 range += bonus d = max(self.radius + DISTANCE_MARGIN, range) + target.radius return square_of_distance(self.x, self.y, target.x, target.y) < d * d
def _already_walked(self, x, y): n = 0 radius_2 = self.radius * self.radius for lw, xw, yw, weight in self.walked: if self.place is lw and square_of_distance(x, y, xw, yw) < radius_2: n += weight return n
def _choose_enemy(self, place): known = self.player.known_enemies(place) reachable_enemies = [x for x in known if self.can_attack(x)] if reachable_enemies: reachable_enemies.sort(key=lambda x: ( -x.menace, square_of_distance(self.x, self.y, x.x, x.y), x.id)) self.action = AttackAction(self, reachable_enemies[0]) return True
def _choose_enemy(self, place): known = self.player.known_enemies(place) reachable_enemies = [x for x in known if self.can_attack(x)] if reachable_enemies: reachable_enemies.sort(key=lambda x: (- x.value, square_of_distance(self.x, self.y, x.x, x.y), x.id)) self.action_target = reachable_enemies[0] # attack nearest self.notify("attack") # XXX move this into set_action_target()? return True
def splash_aim(self, target): damage_radius_2 = self.damage_radius * self.damage_radius for o in target.place.objects[:]: if not self.is_an_enemy(o) and o is not target: pass # no friendly fire (unless o is the target) elif isinstance(o, Creature) \ and square_of_distance(o.x, o.y, target.x, target.y) <= damage_radius_2 \ and self.can_attack_if_in_range(o): self._hit_or_miss(o)
def splash_aim(self, target): damage_radius_2 = self.damage_radius * self.damage_radius for o in target.place.objects[:]: if not self.is_an_enemy(o): pass # no friendly fire elif isinstance(o, Creature) \ and square_of_distance(o.x, o.y, target.x, target.y) <= damage_radius_2 \ and self.can_attack_if_in_range(o): self.hit(o)
def _is_seeing(self, u): if (u.is_invisible or u.is_cloaked) and u not in self.detected_units: return x = u.x y = u.y for avp in self.allied_vision: for avu in self._potential_neighbors(x, y): radius2 = avu.sight_range * avu.sight_range if (square_of_distance(avu.x, avu.y, x, y) < radius2 and (avu.sight_range >= self.world.square_width or u.place in avu.get_observed_squares())): return True
def _is_seeing(self, u): if (u.is_invisible or u.is_cloaked) and u not in self.detected_units: return x = u.x y = u.y for avp in self.allied_vision: for avu in self._potential_neighbors(x, y): radius2 = avu.sight_range * avu.sight_range if (square_of_distance(avu.x, avu.y, x, y) < radius2 and (avu.sight_range >= self.world.square_width or u.place in avu.get_observed_squares())): return True
def _near_enough(self, target): # note: always returns False if the target is a square if target.place is self.place: d = self.radius + target.radius + DISTANCE_MARGIN return square_of_distance(self.x, self.y, target.x, target.y) < d * d
def nearest_water(self): places = [sq for sq in self.place.strict_neighbors if sq.is_water] if places: return min( places, key=lambda sq: square_of_distance(sq.x, sq.y, self.x, self.y))
def _near_enough_to_use(self, target): if self.is_an_enemy(target): return self._near_enough_to_aim(target) elif target.place is self.place: d = target.use_range(self) return square_of_distance(self.x, self.y, target.x, target.y) < d * d