Top

sc2.position module

from math import sqrt, pi, sin, cos, atan2
import random
import itertools
import math
from typing import List, Dict, Set, Tuple, Any, Optional, Union # for mypy type checking

FLOAT_DIGITS = 8
EPSILON = 10 ** (-FLOAT_DIGITS)

def _sign(num):
    if num == 0:
        return 0
    return 1 if num > 0 else -1

class Pointlike(tuple):
    @property
    def rounded(self) -> "Pointlike":
        return self.__class__(round(q) for q in self)

    @property
    def position(self) -> "Pointlike":
        return self

    def distance_to(self, p: Union["Unit", "Point2", "Point3"]) -> Union[int, float]:
        p = p.position
        assert isinstance(p, Pointlike)
        if self == p:
            return 0
        return (sum(self.__class__((b - a) ** 2 for a, b in itertools.zip_longest(self, p, fillvalue=0)))) ** 0.5

    def distance_to_point2(self, p2: "Point2") -> Union[int, float]:
        """ Same as the function above, but should be 3-4 times faster because of the dropped asserts and conversions and because it doesnt use a loop (itertools or zip). """
        return ((self[0] - p2[0]) ** 2 + (self[1] - p2[1]) ** 2) ** 0.5

    def _distance_squared(self, p2: "Point2") -> Union[int, float]:
        """ Function used to not take the square root as the distances will stay proportionally the same. This is to speed up the sorting process. """
        return (self[0] - p2[0]) ** 2 + (self[1] - p2[1]) ** 2

    def sort_by_distance(self, ps: Union["Units", List["Point2"]]) -> List["Point2"]:
        """ This returns the target points sorted as list. You should not pass a set or dict since those are not sortable.
        If you want to sort your units towards a point, use 'units.sorted_by_distance_to(point)' instead. """
        if len(ps) == 1:
            return ps[0]
        if ps and all(isinstance(p, Point2) for p in ps):
            return sorted(ps, key=lambda p: self._distance_squared(p))
        return sorted(ps, key=lambda p: self.distance_to(p))

    def closest(self, ps: Union["Units", List["Point2"], Set["Point2"]]) -> Union["Unit", "Point2"]:
        """ This function assumes the 2d distance is meant """
        assert ps
        if len(ps) == 1:
            return ps[0]
        closest_distance_squared = math.inf
        for p2 in ps:
            p2pos = p2
            if not isinstance(p2pos, Point2):
                p2pos = p2.position
            distance = (self[0] - p2pos[0]) ** 2 + (self[1] - p2pos[1]) ** 2
            if distance < closest_distance_squared:
                closest_distance_squared = distance
                closest_element = p2
        return closest_element

    def distance_to_closest(self, ps: Union["Units", List["Point2"], Set["Point2"]]) -> Union[int, float]:
        """ This function assumes the 2d distance is meant """
        assert ps
        closest_distance_squared = math.inf
        for p2 in ps:
            if not isinstance(p2, Point2):
                p2 = p2.position
            distance = (self[0] - p2[0]) ** 2 + (self[1] - p2[1]) ** 2
            if distance < closest_distance_squared:
                closest_distance_squared = distance
        return closest_distance_squared ** 0.5

    def furthest(self, ps: Union["Units", List["Point2"], Set["Point2"]]) -> Union["Unit", "Pointlike"]:
        """ This function assumes the 2d distance is meant """
        assert ps
        if len(ps) == 1:
            return ps[0]
        furthest_distance_squared = -math.inf
        for p2 in ps:
            p2pos = p2
            if not isinstance(p2pos, Point2):
                p2pos = p2.position
            distance = (self[0] - p2pos[0]) ** 2 + (self[1] - p2pos[1]) ** 2
            if furthest_distance_squared < distance:
                furthest_distance_squared = distance
                furthest_element = p2
        return furthest_element

    def distance_to_furthest(self, ps: Union["Units", List["Point2"], Set["Point2"]]) -> Union[int, float]:
        """ This function assumes the 2d distance is meant """
        assert ps
        furthest_distance_squared = -math.inf
        for p2 in ps:
            if not isinstance(p2, Point2):
                p2 = p2.position
            distance = (self[0] - p2[0]) ** 2 + (self[1] - p2[1]) ** 2
            if furthest_distance_squared < distance:
                furthest_distance_squared = distance
        return furthest_distance_squared ** 0.5

    def offset(self, p) -> "Pointlike":
        return self.__class__(a + b for a, b in itertools.zip_longest(self, p[: len(self)], fillvalue=0))

    def unit_axes_towards(self, p):
        return self.__class__(_sign(b - a) for a, b in itertools.zip_longest(self, p[:len(self)], fillvalue=0))

    def towards(self, p: Union["Unit", "Pointlike"], distance: Union[int, float]=1, limit: bool=False) -> "Pointlike":
        p = p.position
        assert self != p, f"self is {self}, p is {p}"
        d = self.distance_to(p)
        if limit:
            distance = min(d, distance)
        return self.__class__(a + (b - a) / d * distance for a, b in itertools.zip_longest(self, p[:len(self)], fillvalue=0))

    def __eq__(self, other):
        if not isinstance(other, tuple):
            return False
        return all(abs(a - b) < EPSILON for a, b in itertools.zip_longest(self, other, fillvalue=0))

    def __hash__(self):
        return hash(tuple(int(c * FLOAT_DIGITS)  for c in self))


class Point2(Pointlike):
    @classmethod
    def from_proto(cls, data):
        return cls((data.x, data.y))

    @property
    def x(self) -> Union[int, float]:
        return self[0]

    @property
    def y(self) -> Union[int, float]:
        return self[1]

    @property
    def to2(self) -> "Point2":
        return Point2(self[:2])

    @property
    def to3(self) -> "Point3":
        return Point3((*self, 0))

    def distance2_to(self, other: "Point2"):
        """Squared distance to a point."""
        assert isinstance(other, Point2)
        return (self[0] - other[0]) ** 2 + (self[1] - other[1]) ** 2

    def random_on_distance(self, distance):
        if isinstance(distance, (tuple, list)): # interval
            distance = distance[0] + random.random() * (distance[1] - distance[0])

        assert distance > 0
        angle = random.random() * 2 * pi

        dx, dy = cos(angle), sin(angle)
        return Point2((self.x + dx * distance, self.y + dy * distance))

    def towards_with_random_angle(self, p: Union["Point2", "Point3"], distance: Union[int, float]=1, max_difference: Union[int, float]=(pi / 4)) -> "Point2":
        tx, ty = self.to2.towards(p.to2, 1)
        angle = atan2(ty - self.y, tx - self.x)
        angle = (angle - max_difference) + max_difference * 2 * random.random()
        return Point2((self.x + cos(angle) * distance, self.y + sin(angle) * distance))

    def circle_intersection(self, p: "Point2", r: Union[int, float]) -> Set["Point2"]:
        """ self is point1, p is point2, r is the radius for circles originating in both points
        Used in ramp finding """
        assert self != p
        distanceBetweenPoints = self.distance_to(p)
        assert r > distanceBetweenPoints / 2
        # remaining distance from center towards the intersection, using pythagoras
        remainingDistanceFromCenter = (r ** 2 - (distanceBetweenPoints / 2) ** 2) ** 0.5
        # center of both points
        offsetToCenter = Point2(((p.x - self.x) / 2, (p.y - self.y) / 2))
        center = self.offset(offsetToCenter)

        # stretch offset vector in the ratio of remaining distance from center to intersection
        vectorStretchFactor = remainingDistanceFromCenter / (distanceBetweenPoints / 2)
        v = offsetToCenter
        offsetToCenterStretched = Point2((v.x * vectorStretchFactor, v.y * vectorStretchFactor))

        # rotate vector by 90° and -90°
        vectorRotated1 = Point2((offsetToCenterStretched.y, -offsetToCenterStretched.x))
        vectorRotated2 = Point2((-offsetToCenterStretched.y, offsetToCenterStretched.x))
        intersect1 = center.offset(vectorRotated1)
        intersect2 = center.offset(vectorRotated2)
        return {intersect1, intersect2}

    @property
    def neighbors4(self) -> set:
        return {
            Point2((self.x - 1, self.y)),
            Point2((self.x + 1, self.y)),
            Point2((self.x, self.y - 1)),
            Point2((self.x, self.y + 1)),
        }

    @property
    def neighbors8(self) -> set:
        return self.neighbors4 | {
            Point2((self.x - 1, self.y - 1)),
            Point2((self.x - 1, self.y + 1)),
            Point2((self.x + 1, self.y - 1)),
            Point2((self.x + 1, self.y + 1)),
        }

    def negative_offset(self, other: "Point2") -> "Point2":
        return self.__class__((self.x - other.x, self.y - other.y))

    def __add__(self, other: "Point2") -> "Point2":
        return self.offset(other)

    def __sub__(self, other: "Point2") -> "Point2":
        return self.negative_offset(other)

    def __neg__(self) -> "Point2":
        return self.__class__(-a for a in self)

    def __abs__(self) -> Union[int, float]:
        return math.hypot(self.x, self.y)

    def __bool__(self) -> bool:
        return self.x != 0 or self.y != 0

    def __mul__(self, other: Union[int, float, "Point2"]) -> "Point2":
        if isinstance(other, self.__class__):
            return self.__class__((self.x * other.x, self.y * other.y))
        return self.__class__((self.x * other, self.y * other))

    def __rmul__(self, other: Union[int, float, "Point2"]) -> "Point2":
        return self.__mul__(other)

    def __truediv__(self, other: Union[int, float, "Point2"]) -> "Point2":
        if isinstance(other, self.__class__):
            return self.__class__((self.x / other.x, self.y / other.y))
        return self.__class__((self.x / other, self.y / other))

    def is_same_as(self, other: "Point2", dist=0.1) -> bool:
        return self._distance_squared(other) <= dist ** 2

    def direction_vector(self, other: "Point2") -> "Point2":
        """ Converts a vector to a direction that can face vertically, horizontally or diagonal or be zero, e.g. (0, 0), (1, -1), (1, 0) """
        return self.__class__((_sign(other.x - self.x), _sign(other.y - self.y)))

    def manhattan_distance(self, other: "Point2") -> Union[int, float]:
        return abs(other.x - self.x) + abs(other.y - self.y)

    @staticmethod
    def center(a: Union[Set["Point2"], List["Point2"]]) -> "Point2":
        """ Returns the central point for points in list """
        s = Point2((0, 0))
        for p in a:
            s += p
        return s / len(a)


class Point3(Point2):
    @classmethod
    def from_proto(cls, data):
        return cls((data.x, data.y, data.z))

    @property
    def z(self) -> Union[int, float]:
        return self[2]

    @property
    def to3(self) -> "Point3":
        return Point3(self)

class Size(Point2):
    @property
    def width(self) -> Union[int, float]:
        return self[0]

    @property
    def height(self) -> Union[int, float]:
        return self[1]

class Rect(tuple):
    @classmethod
    def from_proto(cls, data):
        assert data.p0.x < data.p1.x and data.p0.y < data.p1.y
        return cls((data.p0.x, data.p0.y, data.p1.x - data.p0.x, data.p1.y - data.p0.y))

    @property
    def x(self) -> Union[int, float]:
        return self[0]

    @property
    def y(self) -> Union[int, float]:
        return self[1]

    @property
    def width(self) -> Union[int, float]:
        return self[2]

    @property
    def height(self) -> Union[int, float]:
        return self[3]

    @property
    def size(self) -> Size:
        return Size(self[2], self[3])

    @property
    def center(self) -> Point2:
        return Point2((self.x + self.width / 2, self.y + self.height / 2))

    def offset(self, p):
        return self.__class__((self[0] + p[0], self[1] + p[1], self[2], self[3]))

Module variables

var EPSILON

var FLOAT_DIGITS

var pi

Classes

class Point2

tuple() -> empty tuple tuple(iterable) -> tuple initialized from iterable's items

If the argument is a tuple, the return value is the same object.

class Point2(Pointlike):
    @classmethod
    def from_proto(cls, data):
        return cls((data.x, data.y))

    @property
    def x(self) -> Union[int, float]:
        return self[0]

    @property
    def y(self) -> Union[int, float]:
        return self[1]

    @property
    def to2(self) -> "Point2":
        return Point2(self[:2])

    @property
    def to3(self) -> "Point3":
        return Point3((*self, 0))

    def distance2_to(self, other: "Point2"):
        """Squared distance to a point."""
        assert isinstance(other, Point2)
        return (self[0] - other[0]) ** 2 + (self[1] - other[1]) ** 2

    def random_on_distance(self, distance):
        if isinstance(distance, (tuple, list)): # interval
            distance = distance[0] + random.random() * (distance[1] - distance[0])

        assert distance > 0
        angle = random.random() * 2 * pi

        dx, dy = cos(angle), sin(angle)
        return Point2((self.x + dx * distance, self.y + dy * distance))

    def towards_with_random_angle(self, p: Union["Point2", "Point3"], distance: Union[int, float]=1, max_difference: Union[int, float]=(pi / 4)) -> "Point2":
        tx, ty = self.to2.towards(p.to2, 1)
        angle = atan2(ty - self.y, tx - self.x)
        angle = (angle - max_difference) + max_difference * 2 * random.random()
        return Point2((self.x + cos(angle) * distance, self.y + sin(angle) * distance))

    def circle_intersection(self, p: "Point2", r: Union[int, float]) -> Set["Point2"]:
        """ self is point1, p is point2, r is the radius for circles originating in both points
        Used in ramp finding """
        assert self != p
        distanceBetweenPoints = self.distance_to(p)
        assert r > distanceBetweenPoints / 2
        # remaining distance from center towards the intersection, using pythagoras
        remainingDistanceFromCenter = (r ** 2 - (distanceBetweenPoints / 2) ** 2) ** 0.5
        # center of both points
        offsetToCenter = Point2(((p.x - self.x) / 2, (p.y - self.y) / 2))
        center = self.offset(offsetToCenter)

        # stretch offset vector in the ratio of remaining distance from center to intersection
        vectorStretchFactor = remainingDistanceFromCenter / (distanceBetweenPoints / 2)
        v = offsetToCenter
        offsetToCenterStretched = Point2((v.x * vectorStretchFactor, v.y * vectorStretchFactor))

        # rotate vector by 90° and -90°
        vectorRotated1 = Point2((offsetToCenterStretched.y, -offsetToCenterStretched.x))
        vectorRotated2 = Point2((-offsetToCenterStretched.y, offsetToCenterStretched.x))
        intersect1 = center.offset(vectorRotated1)
        intersect2 = center.offset(vectorRotated2)
        return {intersect1, intersect2}

    @property
    def neighbors4(self) -> set:
        return {
            Point2((self.x - 1, self.y)),
            Point2((self.x + 1, self.y)),
            Point2((self.x, self.y - 1)),
            Point2((self.x, self.y + 1)),
        }

    @property
    def neighbors8(self) -> set:
        return self.neighbors4 | {
            Point2((self.x - 1, self.y - 1)),
            Point2((self.x - 1, self.y + 1)),
            Point2((self.x + 1, self.y - 1)),
            Point2((self.x + 1, self.y + 1)),
        }

    def negative_offset(self, other: "Point2") -> "Point2":
        return self.__class__((self.x - other.x, self.y - other.y))

    def __add__(self, other: "Point2") -> "Point2":
        return self.offset(other)

    def __sub__(self, other: "Point2") -> "Point2":
        return self.negative_offset(other)

    def __neg__(self) -> "Point2":
        return self.__class__(-a for a in self)

    def __abs__(self) -> Union[int, float]:
        return math.hypot(self.x, self.y)

    def __bool__(self) -> bool:
        return self.x != 0 or self.y != 0

    def __mul__(self, other: Union[int, float, "Point2"]) -> "Point2":
        if isinstance(other, self.__class__):
            return self.__class__((self.x * other.x, self.y * other.y))
        return self.__class__((self.x * other, self.y * other))

    def __rmul__(self, other: Union[int, float, "Point2"]) -> "Point2":
        return self.__mul__(other)

    def __truediv__(self, other: Union[int, float, "Point2"]) -> "Point2":
        if isinstance(other, self.__class__):
            return self.__class__((self.x / other.x, self.y / other.y))
        return self.__class__((self.x / other, self.y / other))

    def is_same_as(self, other: "Point2", dist=0.1) -> bool:
        return self._distance_squared(other) <= dist ** 2

    def direction_vector(self, other: "Point2") -> "Point2":
        """ Converts a vector to a direction that can face vertically, horizontally or diagonal or be zero, e.g. (0, 0), (1, -1), (1, 0) """
        return self.__class__((_sign(other.x - self.x), _sign(other.y - self.y)))

    def manhattan_distance(self, other: "Point2") -> Union[int, float]:
        return abs(other.x - self.x) + abs(other.y - self.y)

    @staticmethod
    def center(a: Union[Set["Point2"], List["Point2"]]) -> "Point2":
        """ Returns the central point for points in list """
        s = Point2((0, 0))
        for p in a:
            s += p
        return s / len(a)

Ancestors (in MRO)

Static methods

def center(

a)

Returns the central point for points in list

@staticmethod
def center(a: Union[Set["Point2"], List["Point2"]]) -> "Point2":
    """ Returns the central point for points in list """
    s = Point2((0, 0))
    for p in a:
        s += p
    return s / len(a)

def circle_intersection(

self, p, r)

self is point1, p is point2, r is the radius for circles originating in both points Used in ramp finding

def circle_intersection(self, p: "Point2", r: Union[int, float]) -> Set["Point2"]:
    """ self is point1, p is point2, r is the radius for circles originating in both points
    Used in ramp finding """
    assert self != p
    distanceBetweenPoints = self.distance_to(p)
    assert r > distanceBetweenPoints / 2
    # remaining distance from center towards the intersection, using pythagoras
    remainingDistanceFromCenter = (r ** 2 - (distanceBetweenPoints / 2) ** 2) ** 0.5
    # center of both points
    offsetToCenter = Point2(((p.x - self.x) / 2, (p.y - self.y) / 2))
    center = self.offset(offsetToCenter)
    # stretch offset vector in the ratio of remaining distance from center to intersection
    vectorStretchFactor = remainingDistanceFromCenter / (distanceBetweenPoints / 2)
    v = offsetToCenter
    offsetToCenterStretched = Point2((v.x * vectorStretchFactor, v.y * vectorStretchFactor))
    # rotate vector by 90° and -90°
    vectorRotated1 = Point2((offsetToCenterStretched.y, -offsetToCenterStretched.x))
    vectorRotated2 = Point2((-offsetToCenterStretched.y, offsetToCenterStretched.x))
    intersect1 = center.offset(vectorRotated1)
    intersect2 = center.offset(vectorRotated2)
    return {intersect1, intersect2}

def closest(

self, ps)

This function assumes the 2d distance is meant

def closest(self, ps: Union["Units", List["Point2"], Set["Point2"]]) -> Union["Unit", "Point2"]:
    """ This function assumes the 2d distance is meant """
    assert ps
    if len(ps) == 1:
        return ps[0]
    closest_distance_squared = math.inf
    for p2 in ps:
        p2pos = p2
        if not isinstance(p2pos, Point2):
            p2pos = p2.position
        distance = (self[0] - p2pos[0]) ** 2 + (self[1] - p2pos[1]) ** 2
        if distance < closest_distance_squared:
            closest_distance_squared = distance
            closest_element = p2
    return closest_element

def direction_vector(

self, other)

Converts a vector to a direction that can face vertically, horizontally or diagonal or be zero, e.g. (0, 0), (1, -1), (1, 0)

def direction_vector(self, other: "Point2") -> "Point2":
    """ Converts a vector to a direction that can face vertically, horizontally or diagonal or be zero, e.g. (0, 0), (1, -1), (1, 0) """
    return self.__class__((_sign(other.x - self.x), _sign(other.y - self.y)))

def distance2_to(

self, other)

Squared distance to a point.

def distance2_to(self, other: "Point2"):
    """Squared distance to a point."""
    assert isinstance(other, Point2)
    return (self[0] - other[0]) ** 2 + (self[1] - other[1]) ** 2

def distance_to(

self, p)

def distance_to(self, p: Union["Unit", "Point2", "Point3"]) -> Union[int, float]:
    p = p.position
    assert isinstance(p, Pointlike)
    if self == p:
        return 0
    return (sum(self.__class__((b - a) ** 2 for a, b in itertools.zip_longest(self, p, fillvalue=0)))) ** 0.5

def distance_to_closest(

self, ps)

This function assumes the 2d distance is meant

def distance_to_closest(self, ps: Union["Units", List["Point2"], Set["Point2"]]) -> Union[int, float]:
    """ This function assumes the 2d distance is meant """
    assert ps
    closest_distance_squared = math.inf
    for p2 in ps:
        if not isinstance(p2, Point2):
            p2 = p2.position
        distance = (self[0] - p2[0]) ** 2 + (self[1] - p2[1]) ** 2
        if distance < closest_distance_squared:
            closest_distance_squared = distance
    return closest_distance_squared ** 0.5

def distance_to_furthest(

self, ps)

This function assumes the 2d distance is meant

def distance_to_furthest(self, ps: Union["Units", List["Point2"], Set["Point2"]]) -> Union[int, float]:
    """ This function assumes the 2d distance is meant """
    assert ps
    furthest_distance_squared = -math.inf
    for p2 in ps:
        if not isinstance(p2, Point2):
            p2 = p2.position
        distance = (self[0] - p2[0]) ** 2 + (self[1] - p2[1]) ** 2
        if furthest_distance_squared < distance:
            furthest_distance_squared = distance
    return furthest_distance_squared ** 0.5

def distance_to_point2(

self, p2)

Same as the function above, but should be 3-4 times faster because of the dropped asserts and conversions and because it doesnt use a loop (itertools or zip).

def distance_to_point2(self, p2: "Point2") -> Union[int, float]:
    """ Same as the function above, but should be 3-4 times faster because of the dropped asserts and conversions and because it doesnt use a loop (itertools or zip). """
    return ((self[0] - p2[0]) ** 2 + (self[1] - p2[1]) ** 2) ** 0.5

def furthest(

self, ps)

This function assumes the 2d distance is meant

def furthest(self, ps: Union["Units", List["Point2"], Set["Point2"]]) -> Union["Unit", "Pointlike"]:
    """ This function assumes the 2d distance is meant """
    assert ps
    if len(ps) == 1:
        return ps[0]
    furthest_distance_squared = -math.inf
    for p2 in ps:
        p2pos = p2
        if not isinstance(p2pos, Point2):
            p2pos = p2.position
        distance = (self[0] - p2pos[0]) ** 2 + (self[1] - p2pos[1]) ** 2
        if furthest_distance_squared < distance:
            furthest_distance_squared = distance
            furthest_element = p2
    return furthest_element

def is_same_as(

self, other, dist=0.1)

def is_same_as(self, other: "Point2", dist=0.1) -> bool:
    return self._distance_squared(other) <= dist ** 2

def manhattan_distance(

self, other)

def manhattan_distance(self, other: "Point2") -> Union[int, float]:
    return abs(other.x - self.x) + abs(other.y - self.y)

def negative_offset(

self, other)

def negative_offset(self, other: "Point2") -> "Point2":
    return self.__class__((self.x - other.x, self.y - other.y))

def offset(

self, p)

def offset(self, p) -> "Pointlike":
    return self.__class__(a + b for a, b in itertools.zip_longest(self, p[: len(self)], fillvalue=0))

def random_on_distance(

self, distance)

def random_on_distance(self, distance):
    if isinstance(distance, (tuple, list)): # interval
        distance = distance[0] + random.random() * (distance[1] - distance[0])
    assert distance > 0
    angle = random.random() * 2 * pi
    dx, dy = cos(angle), sin(angle)
    return Point2((self.x + dx * distance, self.y + dy * distance))

def sort_by_distance(

self, ps)

This returns the target points sorted as list. You should not pass a set or dict since those are not sortable. If you want to sort your units towards a point, use 'units.sorted_by_distance_to(point)' instead.

def sort_by_distance(self, ps: Union["Units", List["Point2"]]) -> List["Point2"]:
    """ This returns the target points sorted as list. You should not pass a set or dict since those are not sortable.
    If you want to sort your units towards a point, use 'units.sorted_by_distance_to(point)' instead. """
    if len(ps) == 1:
        return ps[0]
    if ps and all(isinstance(p, Point2) for p in ps):
        return sorted(ps, key=lambda p: self._distance_squared(p))
    return sorted(ps, key=lambda p: self.distance_to(p))

def towards(

self, p, distance=1, limit=False)

def towards(self, p: Union["Unit", "Pointlike"], distance: Union[int, float]=1, limit: bool=False) -> "Pointlike":
    p = p.position
    assert self != p, f"self is {self}, p is {p}"
    d = self.distance_to(p)
    if limit:
        distance = min(d, distance)
    return self.__class__(a + (b - a) / d * distance for a, b in itertools.zip_longest(self, p[:len(self)], fillvalue=0))

def towards_with_random_angle(

self, p, distance=1, max_difference=0.7853981633974483)

def towards_with_random_angle(self, p: Union["Point2", "Point3"], distance: Union[int, float]=1, max_difference: Union[int, float]=(pi / 4)) -> "Point2":
    tx, ty = self.to2.towards(p.to2, 1)
    angle = atan2(ty - self.y, tx - self.x)
    angle = (angle - max_difference) + max_difference * 2 * random.random()
    return Point2((self.x + cos(angle) * distance, self.y + sin(angle) * distance))

def unit_axes_towards(

self, p)

def unit_axes_towards(self, p):
    return self.__class__(_sign(b - a) for a, b in itertools.zip_longest(self, p[:len(self)], fillvalue=0))

Instance variables

var neighbors4

var neighbors8

var position

var rounded

var to2

var to3

var x

var y

Methods

def from_proto(

cls, data)

@classmethod
def from_proto(cls, data):
    return cls((data.x, data.y))

class Point3

tuple() -> empty tuple tuple(iterable) -> tuple initialized from iterable's items

If the argument is a tuple, the return value is the same object.

class Point3(Point2):
    @classmethod
    def from_proto(cls, data):
        return cls((data.x, data.y, data.z))

    @property
    def z(self) -> Union[int, float]:
        return self[2]

    @property
    def to3(self) -> "Point3":
        return Point3(self)

Ancestors (in MRO)

Static methods

def center(

a)

Returns the central point for points in list

@staticmethod
def center(a: Union[Set["Point2"], List["Point2"]]) -> "Point2":
    """ Returns the central point for points in list """
    s = Point2((0, 0))
    for p in a:
        s += p
    return s / len(a)

def circle_intersection(

self, p, r)

self is point1, p is point2, r is the radius for circles originating in both points Used in ramp finding

def circle_intersection(self, p: "Point2", r: Union[int, float]) -> Set["Point2"]:
    """ self is point1, p is point2, r is the radius for circles originating in both points
    Used in ramp finding """
    assert self != p
    distanceBetweenPoints = self.distance_to(p)
    assert r > distanceBetweenPoints / 2
    # remaining distance from center towards the intersection, using pythagoras
    remainingDistanceFromCenter = (r ** 2 - (distanceBetweenPoints / 2) ** 2) ** 0.5
    # center of both points
    offsetToCenter = Point2(((p.x - self.x) / 2, (p.y - self.y) / 2))
    center = self.offset(offsetToCenter)
    # stretch offset vector in the ratio of remaining distance from center to intersection
    vectorStretchFactor = remainingDistanceFromCenter / (distanceBetweenPoints / 2)
    v = offsetToCenter
    offsetToCenterStretched = Point2((v.x * vectorStretchFactor, v.y * vectorStretchFactor))
    # rotate vector by 90° and -90°
    vectorRotated1 = Point2((offsetToCenterStretched.y, -offsetToCenterStretched.x))
    vectorRotated2 = Point2((-offsetToCenterStretched.y, offsetToCenterStretched.x))
    intersect1 = center.offset(vectorRotated1)
    intersect2 = center.offset(vectorRotated2)
    return {intersect1, intersect2}

def closest(

self, ps)

This function assumes the 2d distance is meant

def closest(self, ps: Union["Units", List["Point2"], Set["Point2"]]) -> Union["Unit", "Point2"]:
    """ This function assumes the 2d distance is meant """
    assert ps
    if len(ps) == 1:
        return ps[0]
    closest_distance_squared = math.inf
    for p2 in ps:
        p2pos = p2
        if not isinstance(p2pos, Point2):
            p2pos = p2.position
        distance = (self[0] - p2pos[0]) ** 2 + (self[1] - p2pos[1]) ** 2
        if distance < closest_distance_squared:
            closest_distance_squared = distance
            closest_element = p2
    return closest_element

def direction_vector(

self, other)

Converts a vector to a direction that can face vertically, horizontally or diagonal or be zero, e.g. (0, 0), (1, -1), (1, 0)

def direction_vector(self, other: "Point2") -> "Point2":
    """ Converts a vector to a direction that can face vertically, horizontally or diagonal or be zero, e.g. (0, 0), (1, -1), (1, 0) """
    return self.__class__((_sign(other.x - self.x), _sign(other.y - self.y)))

def distance2_to(

self, other)

Squared distance to a point.

def distance2_to(self, other: "Point2"):
    """Squared distance to a point."""
    assert isinstance(other, Point2)
    return (self[0] - other[0]) ** 2 + (self[1] - other[1]) ** 2

def distance_to(

self, p)

def distance_to(self, p: Union["Unit", "Point2", "Point3"]) -> Union[int, float]:
    p = p.position
    assert isinstance(p, Pointlike)
    if self == p:
        return 0
    return (sum(self.__class__((b - a) ** 2 for a, b in itertools.zip_longest(self, p, fillvalue=0)))) ** 0.5

def distance_to_closest(

self, ps)

This function assumes the 2d distance is meant

def distance_to_closest(self, ps: Union["Units", List["Point2"], Set["Point2"]]) -> Union[int, float]:
    """ This function assumes the 2d distance is meant """
    assert ps
    closest_distance_squared = math.inf
    for p2 in ps:
        if not isinstance(p2, Point2):
            p2 = p2.position
        distance = (self[0] - p2[0]) ** 2 + (self[1] - p2[1]) ** 2
        if distance < closest_distance_squared:
            closest_distance_squared = distance
    return closest_distance_squared ** 0.5

def distance_to_furthest(

self, ps)

This function assumes the 2d distance is meant

def distance_to_furthest(self, ps: Union["Units", List["Point2"], Set["Point2"]]) -> Union[int, float]:
    """ This function assumes the 2d distance is meant """
    assert ps
    furthest_distance_squared = -math.inf
    for p2 in ps:
        if not isinstance(p2, Point2):
            p2 = p2.position
        distance = (self[0] - p2[0]) ** 2 + (self[1] - p2[1]) ** 2
        if furthest_distance_squared < distance:
            furthest_distance_squared = distance
    return furthest_distance_squared ** 0.5

def distance_to_point2(

self, p2)

Same as the function above, but should be 3-4 times faster because of the dropped asserts and conversions and because it doesnt use a loop (itertools or zip).

def distance_to_point2(self, p2: "Point2") -> Union[int, float]:
    """ Same as the function above, but should be 3-4 times faster because of the dropped asserts and conversions and because it doesnt use a loop (itertools or zip). """
    return ((self[0] - p2[0]) ** 2 + (self[1] - p2[1]) ** 2) ** 0.5

def furthest(

self, ps)

This function assumes the 2d distance is meant

def furthest(self, ps: Union["Units", List["Point2"], Set["Point2"]]) -> Union["Unit", "Pointlike"]:
    """ This function assumes the 2d distance is meant """
    assert ps
    if len(ps) == 1:
        return ps[0]
    furthest_distance_squared = -math.inf
    for p2 in ps:
        p2pos = p2
        if not isinstance(p2pos, Point2):
            p2pos = p2.position
        distance = (self[0] - p2pos[0]) ** 2 + (self[1] - p2pos[1]) ** 2
        if furthest_distance_squared < distance:
            furthest_distance_squared = distance
            furthest_element = p2
    return furthest_element

def is_same_as(

self, other, dist=0.1)

def is_same_as(self, other: "Point2", dist=0.1) -> bool:
    return self._distance_squared(other) <= dist ** 2

def manhattan_distance(

self, other)

def manhattan_distance(self, other: "Point2") -> Union[int, float]:
    return abs(other.x - self.x) + abs(other.y - self.y)

def negative_offset(

self, other)

def negative_offset(self, other: "Point2") -> "Point2":
    return self.__class__((self.x - other.x, self.y - other.y))

def offset(

self, p)

def offset(self, p) -> "Pointlike":
    return self.__class__(a + b for a, b in itertools.zip_longest(self, p[: len(self)], fillvalue=0))

def random_on_distance(

self, distance)

def random_on_distance(self, distance):
    if isinstance(distance, (tuple, list)): # interval
        distance = distance[0] + random.random() * (distance[1] - distance[0])
    assert distance > 0
    angle = random.random() * 2 * pi
    dx, dy = cos(angle), sin(angle)
    return Point2((self.x + dx * distance, self.y + dy * distance))

def sort_by_distance(

self, ps)

This returns the target points sorted as list. You should not pass a set or dict since those are not sortable. If you want to sort your units towards a point, use 'units.sorted_by_distance_to(point)' instead.

def sort_by_distance(self, ps: Union["Units", List["Point2"]]) -> List["Point2"]:
    """ This returns the target points sorted as list. You should not pass a set or dict since those are not sortable.
    If you want to sort your units towards a point, use 'units.sorted_by_distance_to(point)' instead. """
    if len(ps) == 1:
        return ps[0]
    if ps and all(isinstance(p, Point2) for p in ps):
        return sorted(ps, key=lambda p: self._distance_squared(p))
    return sorted(ps, key=lambda p: self.distance_to(p))

def towards(

self, p, distance=1, limit=False)

def towards(self, p: Union["Unit", "Pointlike"], distance: Union[int, float]=1, limit: bool=False) -> "Pointlike":
    p = p.position
    assert self != p, f"self is {self}, p is {p}"
    d = self.distance_to(p)
    if limit:
        distance = min(d, distance)
    return self.__class__(a + (b - a) / d * distance for a, b in itertools.zip_longest(self, p[:len(self)], fillvalue=0))

def towards_with_random_angle(

self, p, distance=1, max_difference=0.7853981633974483)

def towards_with_random_angle(self, p: Union["Point2", "Point3"], distance: Union[int, float]=1, max_difference: Union[int, float]=(pi / 4)) -> "Point2":
    tx, ty = self.to2.towards(p.to2, 1)
    angle = atan2(ty - self.y, tx - self.x)
    angle = (angle - max_difference) + max_difference * 2 * random.random()
    return Point2((self.x + cos(angle) * distance, self.y + sin(angle) * distance))

def unit_axes_towards(

self, p)

def unit_axes_towards(self, p):
    return self.__class__(_sign(b - a) for a, b in itertools.zip_longest(self, p[:len(self)], fillvalue=0))

Instance variables

var neighbors4

Inheritance: Point2.neighbors4

var neighbors8

var position

var rounded

var to2

var to3

var x

var y

var z

Methods

def from_proto(

cls, data)

@classmethod
def from_proto(cls, data):
    return cls((data.x, data.y, data.z))

class Pointlike

tuple() -> empty tuple tuple(iterable) -> tuple initialized from iterable's items

If the argument is a tuple, the return value is the same object.

class Pointlike(tuple):
    @property
    def rounded(self) -> "Pointlike":
        return self.__class__(round(q) for q in self)

    @property
    def position(self) -> "Pointlike":
        return self

    def distance_to(self, p: Union["Unit", "Point2", "Point3"]) -> Union[int, float]:
        p = p.position
        assert isinstance(p, Pointlike)
        if self == p:
            return 0
        return (sum(self.__class__((b - a) ** 2 for a, b in itertools.zip_longest(self, p, fillvalue=0)))) ** 0.5

    def distance_to_point2(self, p2: "Point2") -> Union[int, float]:
        """ Same as the function above, but should be 3-4 times faster because of the dropped asserts and conversions and because it doesnt use a loop (itertools or zip). """
        return ((self[0] - p2[0]) ** 2 + (self[1] - p2[1]) ** 2) ** 0.5

    def _distance_squared(self, p2: "Point2") -> Union[int, float]:
        """ Function used to not take the square root as the distances will stay proportionally the same. This is to speed up the sorting process. """
        return (self[0] - p2[0]) ** 2 + (self[1] - p2[1]) ** 2

    def sort_by_distance(self, ps: Union["Units", List["Point2"]]) -> List["Point2"]:
        """ This returns the target points sorted as list. You should not pass a set or dict since those are not sortable.
        If you want to sort your units towards a point, use 'units.sorted_by_distance_to(point)' instead. """
        if len(ps) == 1:
            return ps[0]
        if ps and all(isinstance(p, Point2) for p in ps):
            return sorted(ps, key=lambda p: self._distance_squared(p))
        return sorted(ps, key=lambda p: self.distance_to(p))

    def closest(self, ps: Union["Units", List["Point2"], Set["Point2"]]) -> Union["Unit", "Point2"]:
        """ This function assumes the 2d distance is meant """
        assert ps
        if len(ps) == 1:
            return ps[0]
        closest_distance_squared = math.inf
        for p2 in ps:
            p2pos = p2
            if not isinstance(p2pos, Point2):
                p2pos = p2.position
            distance = (self[0] - p2pos[0]) ** 2 + (self[1] - p2pos[1]) ** 2
            if distance < closest_distance_squared:
                closest_distance_squared = distance
                closest_element = p2
        return closest_element

    def distance_to_closest(self, ps: Union["Units", List["Point2"], Set["Point2"]]) -> Union[int, float]:
        """ This function assumes the 2d distance is meant """
        assert ps
        closest_distance_squared = math.inf
        for p2 in ps:
            if not isinstance(p2, Point2):
                p2 = p2.position
            distance = (self[0] - p2[0]) ** 2 + (self[1] - p2[1]) ** 2
            if distance < closest_distance_squared:
                closest_distance_squared = distance
        return closest_distance_squared ** 0.5

    def furthest(self, ps: Union["Units", List["Point2"], Set["Point2"]]) -> Union["Unit", "Pointlike"]:
        """ This function assumes the 2d distance is meant """
        assert ps
        if len(ps) == 1:
            return ps[0]
        furthest_distance_squared = -math.inf
        for p2 in ps:
            p2pos = p2
            if not isinstance(p2pos, Point2):
                p2pos = p2.position
            distance = (self[0] - p2pos[0]) ** 2 + (self[1] - p2pos[1]) ** 2
            if furthest_distance_squared < distance:
                furthest_distance_squared = distance
                furthest_element = p2
        return furthest_element

    def distance_to_furthest(self, ps: Union["Units", List["Point2"], Set["Point2"]]) -> Union[int, float]:
        """ This function assumes the 2d distance is meant """
        assert ps
        furthest_distance_squared = -math.inf
        for p2 in ps:
            if not isinstance(p2, Point2):
                p2 = p2.position
            distance = (self[0] - p2[0]) ** 2 + (self[1] - p2[1]) ** 2
            if furthest_distance_squared < distance:
                furthest_distance_squared = distance
        return furthest_distance_squared ** 0.5

    def offset(self, p) -> "Pointlike":
        return self.__class__(a + b for a, b in itertools.zip_longest(self, p[: len(self)], fillvalue=0))

    def unit_axes_towards(self, p):
        return self.__class__(_sign(b - a) for a, b in itertools.zip_longest(self, p[:len(self)], fillvalue=0))

    def towards(self, p: Union["Unit", "Pointlike"], distance: Union[int, float]=1, limit: bool=False) -> "Pointlike":
        p = p.position
        assert self != p, f"self is {self}, p is {p}"
        d = self.distance_to(p)
        if limit:
            distance = min(d, distance)
        return self.__class__(a + (b - a) / d * distance for a, b in itertools.zip_longest(self, p[:len(self)], fillvalue=0))

    def __eq__(self, other):
        if not isinstance(other, tuple):
            return False
        return all(abs(a - b) < EPSILON for a, b in itertools.zip_longest(self, other, fillvalue=0))

    def __hash__(self):
        return hash(tuple(int(c * FLOAT_DIGITS)  for c in self))

Ancestors (in MRO)

Static methods

def closest(

self, ps)

This function assumes the 2d distance is meant

def closest(self, ps: Union["Units", List["Point2"], Set["Point2"]]) -> Union["Unit", "Point2"]:
    """ This function assumes the 2d distance is meant """
    assert ps
    if len(ps) == 1:
        return ps[0]
    closest_distance_squared = math.inf
    for p2 in ps:
        p2pos = p2
        if not isinstance(p2pos, Point2):
            p2pos = p2.position
        distance = (self[0] - p2pos[0]) ** 2 + (self[1] - p2pos[1]) ** 2
        if distance < closest_distance_squared:
            closest_distance_squared = distance
            closest_element = p2
    return closest_element

def distance_to(

self, p)

def distance_to(self, p: Union["Unit", "Point2", "Point3"]) -> Union[int, float]:
    p = p.position
    assert isinstance(p, Pointlike)
    if self == p:
        return 0
    return (sum(self.__class__((b - a) ** 2 for a, b in itertools.zip_longest(self, p, fillvalue=0)))) ** 0.5

def distance_to_closest(

self, ps)

This function assumes the 2d distance is meant

def distance_to_closest(self, ps: Union["Units", List["Point2"], Set["Point2"]]) -> Union[int, float]:
    """ This function assumes the 2d distance is meant """
    assert ps
    closest_distance_squared = math.inf
    for p2 in ps:
        if not isinstance(p2, Point2):
            p2 = p2.position
        distance = (self[0] - p2[0]) ** 2 + (self[1] - p2[1]) ** 2
        if distance < closest_distance_squared:
            closest_distance_squared = distance
    return closest_distance_squared ** 0.5

def distance_to_furthest(

self, ps)

This function assumes the 2d distance is meant

def distance_to_furthest(self, ps: Union["Units", List["Point2"], Set["Point2"]]) -> Union[int, float]:
    """ This function assumes the 2d distance is meant """
    assert ps
    furthest_distance_squared = -math.inf
    for p2 in ps:
        if not isinstance(p2, Point2):
            p2 = p2.position
        distance = (self[0] - p2[0]) ** 2 + (self[1] - p2[1]) ** 2
        if furthest_distance_squared < distance:
            furthest_distance_squared = distance
    return furthest_distance_squared ** 0.5

def distance_to_point2(

self, p2)

Same as the function above, but should be 3-4 times faster because of the dropped asserts and conversions and because it doesnt use a loop (itertools or zip).

def distance_to_point2(self, p2: "Point2") -> Union[int, float]:
    """ Same as the function above, but should be 3-4 times faster because of the dropped asserts and conversions and because it doesnt use a loop (itertools or zip). """
    return ((self[0] - p2[0]) ** 2 + (self[1] - p2[1]) ** 2) ** 0.5

def furthest(

self, ps)

This function assumes the 2d distance is meant

def furthest(self, ps: Union["Units", List["Point2"], Set["Point2"]]) -> Union["Unit", "Pointlike"]:
    """ This function assumes the 2d distance is meant """
    assert ps
    if len(ps) == 1:
        return ps[0]
    furthest_distance_squared = -math.inf
    for p2 in ps:
        p2pos = p2
        if not isinstance(p2pos, Point2):
            p2pos = p2.position
        distance = (self[0] - p2pos[0]) ** 2 + (self[1] - p2pos[1]) ** 2
        if furthest_distance_squared < distance:
            furthest_distance_squared = distance
            furthest_element = p2
    return furthest_element

def offset(

self, p)

def offset(self, p) -> "Pointlike":
    return self.__class__(a + b for a, b in itertools.zip_longest(self, p[: len(self)], fillvalue=0))

def sort_by_distance(

self, ps)

This returns the target points sorted as list. You should not pass a set or dict since those are not sortable. If you want to sort your units towards a point, use 'units.sorted_by_distance_to(point)' instead.

def sort_by_distance(self, ps: Union["Units", List["Point2"]]) -> List["Point2"]:
    """ This returns the target points sorted as list. You should not pass a set or dict since those are not sortable.
    If you want to sort your units towards a point, use 'units.sorted_by_distance_to(point)' instead. """
    if len(ps) == 1:
        return ps[0]
    if ps and all(isinstance(p, Point2) for p in ps):
        return sorted(ps, key=lambda p: self._distance_squared(p))
    return sorted(ps, key=lambda p: self.distance_to(p))

def towards(

self, p, distance=1, limit=False)

def towards(self, p: Union["Unit", "Pointlike"], distance: Union[int, float]=1, limit: bool=False) -> "Pointlike":
    p = p.position
    assert self != p, f"self is {self}, p is {p}"
    d = self.distance_to(p)
    if limit:
        distance = min(d, distance)
    return self.__class__(a + (b - a) / d * distance for a, b in itertools.zip_longest(self, p[:len(self)], fillvalue=0))

def unit_axes_towards(

self, p)

def unit_axes_towards(self, p):
    return self.__class__(_sign(b - a) for a, b in itertools.zip_longest(self, p[:len(self)], fillvalue=0))

Instance variables

var position

var rounded

class Rect

tuple() -> empty tuple tuple(iterable) -> tuple initialized from iterable's items

If the argument is a tuple, the return value is the same object.

class Rect(tuple):
    @classmethod
    def from_proto(cls, data):
        assert data.p0.x < data.p1.x and data.p0.y < data.p1.y
        return cls((data.p0.x, data.p0.y, data.p1.x - data.p0.x, data.p1.y - data.p0.y))

    @property
    def x(self) -> Union[int, float]:
        return self[0]

    @property
    def y(self) -> Union[int, float]:
        return self[1]

    @property
    def width(self) -> Union[int, float]:
        return self[2]

    @property
    def height(self) -> Union[int, float]:
        return self[3]

    @property
    def size(self) -> Size:
        return Size(self[2], self[3])

    @property
    def center(self) -> Point2:
        return Point2((self.x + self.width / 2, self.y + self.height / 2))

    def offset(self, p):
        return self.__class__((self[0] + p[0], self[1] + p[1], self[2], self[3]))

Ancestors (in MRO)

  • Rect
  • builtins.tuple
  • builtins.object

Static methods

def offset(

self, p)

def offset(self, p):
    return self.__class__((self[0] + p[0], self[1] + p[1], self[2], self[3]))

Instance variables

var center

var height

var size

var width

var x

var y

Methods

def from_proto(

cls, data)

@classmethod
def from_proto(cls, data):
    assert data.p0.x < data.p1.x and data.p0.y < data.p1.y
    return cls((data.p0.x, data.p0.y, data.p1.x - data.p0.x, data.p1.y - data.p0.y))

class Size

tuple() -> empty tuple tuple(iterable) -> tuple initialized from iterable's items

If the argument is a tuple, the return value is the same object.

class Size(Point2):
    @property
    def width(self) -> Union[int, float]:
        return self[0]

    @property
    def height(self) -> Union[int, float]:
        return self[1]

Ancestors (in MRO)

Static methods

def center(

a)

Returns the central point for points in list

@staticmethod
def center(a: Union[Set["Point2"], List["Point2"]]) -> "Point2":
    """ Returns the central point for points in list """
    s = Point2((0, 0))
    for p in a:
        s += p
    return s / len(a)

def circle_intersection(

self, p, r)

self is point1, p is point2, r is the radius for circles originating in both points Used in ramp finding

def circle_intersection(self, p: "Point2", r: Union[int, float]) -> Set["Point2"]:
    """ self is point1, p is point2, r is the radius for circles originating in both points
    Used in ramp finding """
    assert self != p
    distanceBetweenPoints = self.distance_to(p)
    assert r > distanceBetweenPoints / 2
    # remaining distance from center towards the intersection, using pythagoras
    remainingDistanceFromCenter = (r ** 2 - (distanceBetweenPoints / 2) ** 2) ** 0.5
    # center of both points
    offsetToCenter = Point2(((p.x - self.x) / 2, (p.y - self.y) / 2))
    center = self.offset(offsetToCenter)
    # stretch offset vector in the ratio of remaining distance from center to intersection
    vectorStretchFactor = remainingDistanceFromCenter / (distanceBetweenPoints / 2)
    v = offsetToCenter
    offsetToCenterStretched = Point2((v.x * vectorStretchFactor, v.y * vectorStretchFactor))
    # rotate vector by 90° and -90°
    vectorRotated1 = Point2((offsetToCenterStretched.y, -offsetToCenterStretched.x))
    vectorRotated2 = Point2((-offsetToCenterStretched.y, offsetToCenterStretched.x))
    intersect1 = center.offset(vectorRotated1)
    intersect2 = center.offset(vectorRotated2)
    return {intersect1, intersect2}

def closest(

self, ps)

This function assumes the 2d distance is meant

def closest(self, ps: Union["Units", List["Point2"], Set["Point2"]]) -> Union["Unit", "Point2"]:
    """ This function assumes the 2d distance is meant """
    assert ps
    if len(ps) == 1:
        return ps[0]
    closest_distance_squared = math.inf
    for p2 in ps:
        p2pos = p2
        if not isinstance(p2pos, Point2):
            p2pos = p2.position
        distance = (self[0] - p2pos[0]) ** 2 + (self[1] - p2pos[1]) ** 2
        if distance < closest_distance_squared:
            closest_distance_squared = distance
            closest_element = p2
    return closest_element

def direction_vector(

self, other)

Converts a vector to a direction that can face vertically, horizontally or diagonal or be zero, e.g. (0, 0), (1, -1), (1, 0)

def direction_vector(self, other: "Point2") -> "Point2":
    """ Converts a vector to a direction that can face vertically, horizontally or diagonal or be zero, e.g. (0, 0), (1, -1), (1, 0) """
    return self.__class__((_sign(other.x - self.x), _sign(other.y - self.y)))

def distance2_to(

self, other)

Squared distance to a point.

def distance2_to(self, other: "Point2"):
    """Squared distance to a point."""
    assert isinstance(other, Point2)
    return (self[0] - other[0]) ** 2 + (self[1] - other[1]) ** 2

def distance_to(

self, p)

def distance_to(self, p: Union["Unit", "Point2", "Point3"]) -> Union[int, float]:
    p = p.position
    assert isinstance(p, Pointlike)
    if self == p:
        return 0
    return (sum(self.__class__((b - a) ** 2 for a, b in itertools.zip_longest(self, p, fillvalue=0)))) ** 0.5

def distance_to_closest(

self, ps)

This function assumes the 2d distance is meant

def distance_to_closest(self, ps: Union["Units", List["Point2"], Set["Point2"]]) -> Union[int, float]:
    """ This function assumes the 2d distance is meant """
    assert ps
    closest_distance_squared = math.inf
    for p2 in ps:
        if not isinstance(p2, Point2):
            p2 = p2.position
        distance = (self[0] - p2[0]) ** 2 + (self[1] - p2[1]) ** 2
        if distance < closest_distance_squared:
            closest_distance_squared = distance
    return closest_distance_squared ** 0.5

def distance_to_furthest(

self, ps)

This function assumes the 2d distance is meant

def distance_to_furthest(self, ps: Union["Units", List["Point2"], Set["Point2"]]) -> Union[int, float]:
    """ This function assumes the 2d distance is meant """
    assert ps
    furthest_distance_squared = -math.inf
    for p2 in ps:
        if not isinstance(p2, Point2):
            p2 = p2.position
        distance = (self[0] - p2[0]) ** 2 + (self[1] - p2[1]) ** 2
        if furthest_distance_squared < distance:
            furthest_distance_squared = distance
    return furthest_distance_squared ** 0.5

def distance_to_point2(

self, p2)

Same as the function above, but should be 3-4 times faster because of the dropped asserts and conversions and because it doesnt use a loop (itertools or zip).

def distance_to_point2(self, p2: "Point2") -> Union[int, float]:
    """ Same as the function above, but should be 3-4 times faster because of the dropped asserts and conversions and because it doesnt use a loop (itertools or zip). """
    return ((self[0] - p2[0]) ** 2 + (self[1] - p2[1]) ** 2) ** 0.5

def furthest(

self, ps)

This function assumes the 2d distance is meant

def furthest(self, ps: Union["Units", List["Point2"], Set["Point2"]]) -> Union["Unit", "Pointlike"]:
    """ This function assumes the 2d distance is meant """
    assert ps
    if len(ps) == 1:
        return ps[0]
    furthest_distance_squared = -math.inf
    for p2 in ps:
        p2pos = p2
        if not isinstance(p2pos, Point2):
            p2pos = p2.position
        distance = (self[0] - p2pos[0]) ** 2 + (self[1] - p2pos[1]) ** 2
        if furthest_distance_squared < distance:
            furthest_distance_squared = distance
            furthest_element = p2
    return furthest_element

def is_same_as(

self, other, dist=0.1)

def is_same_as(self, other: "Point2", dist=0.1) -> bool:
    return self._distance_squared(other) <= dist ** 2

def manhattan_distance(

self, other)

def manhattan_distance(self, other: "Point2") -> Union[int, float]:
    return abs(other.x - self.x) + abs(other.y - self.y)

def negative_offset(

self, other)

def negative_offset(self, other: "Point2") -> "Point2":
    return self.__class__((self.x - other.x, self.y - other.y))

def offset(

self, p)

def offset(self, p) -> "Pointlike":
    return self.__class__(a + b for a, b in itertools.zip_longest(self, p[: len(self)], fillvalue=0))

def random_on_distance(

self, distance)

def random_on_distance(self, distance):
    if isinstance(distance, (tuple, list)): # interval
        distance = distance[0] + random.random() * (distance[1] - distance[0])
    assert distance > 0
    angle = random.random() * 2 * pi
    dx, dy = cos(angle), sin(angle)
    return Point2((self.x + dx * distance, self.y + dy * distance))

def sort_by_distance(

self, ps)

This returns the target points sorted as list. You should not pass a set or dict since those are not sortable. If you want to sort your units towards a point, use 'units.sorted_by_distance_to(point)' instead.

def sort_by_distance(self, ps: Union["Units", List["Point2"]]) -> List["Point2"]:
    """ This returns the target points sorted as list. You should not pass a set or dict since those are not sortable.
    If you want to sort your units towards a point, use 'units.sorted_by_distance_to(point)' instead. """
    if len(ps) == 1:
        return ps[0]
    if ps and all(isinstance(p, Point2) for p in ps):
        return sorted(ps, key=lambda p: self._distance_squared(p))
    return sorted(ps, key=lambda p: self.distance_to(p))

def towards(

self, p, distance=1, limit=False)

def towards(self, p: Union["Unit", "Pointlike"], distance: Union[int, float]=1, limit: bool=False) -> "Pointlike":
    p = p.position
    assert self != p, f"self is {self}, p is {p}"
    d = self.distance_to(p)
    if limit:
        distance = min(d, distance)
    return self.__class__(a + (b - a) / d * distance for a, b in itertools.zip_longest(self, p[:len(self)], fillvalue=0))

def towards_with_random_angle(

self, p, distance=1, max_difference=0.7853981633974483)

def towards_with_random_angle(self, p: Union["Point2", "Point3"], distance: Union[int, float]=1, max_difference: Union[int, float]=(pi / 4)) -> "Point2":
    tx, ty = self.to2.towards(p.to2, 1)
    angle = atan2(ty - self.y, tx - self.x)
    angle = (angle - max_difference) + max_difference * 2 * random.random()
    return Point2((self.x + cos(angle) * distance, self.y + sin(angle) * distance))

def unit_axes_towards(

self, p)

def unit_axes_towards(self, p):
    return self.__class__(_sign(b - a) for a, b in itertools.zip_longest(self, p[:len(self)], fillvalue=0))

Instance variables

var height

var neighbors4

var neighbors8

var position

var rounded

var to2

var to3

var width

var x

var y

Methods

def from_proto(

cls, data)

@classmethod
def from_proto(cls, data):
    return cls((data.x, data.y))