Skip to content

Cython Extensions SC2

cy_attack_ready

cy_attack_ready(ai, unit, target)

Check if the unit is ready to attack the target.

Takes into account turn rate and unit speeds

Example:

from cython_extensions import cy_attack_ready

worker = self.workers[0]
target = self.enemy_units[0]

attack_ready: bool = cy_attack_ready(self, worker, target)

1.46 µs ± 5.45 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

Python alternative:
5.66 µs ± 21.2 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)

Parameters:

Name Type Description Default
ai BotAI

Bot object that will be running the game.

required
unit Unit

The unit we want to check.

required
target Unit

The thing we want to shoot.

required

Returns:

Name Type Description
bool bool

Is the unit ready to attack the target?

Source code in cython_extensions/combat_utils.pyi
def cy_attack_ready(ai: BotAI, unit: Unit, target: Unit) -> bool:
    """Check if the unit is ready to attack the target.

    Takes into account turn rate and unit speeds

    Example:
    ```py
    from cython_extensions import cy_attack_ready

    worker = self.workers[0]
    target = self.enemy_units[0]

    attack_ready: bool = cy_attack_ready(self, worker, target)
    ```

    ```
    1.46 µs ± 5.45 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

    Python alternative:
    5.66 µs ± 21.2 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
    ```

    Parameters
    ----------
    ai :
        Bot object that will be running the game.
    unit :
        The unit we want to check.
    target :
        The thing we want to shoot.

    Returns
    -------
    bool :
        Is the unit ready to attack the target?

    """
    ...

cy_is_facing

cy_is_facing(unit, other_unit, angle_error)

Get turn speed of unit in radians

Example:

from cython_extensions import cy_is_facing

unit: Unit = self.workers[0]
other_unit: Unit = self.townhalls[0]
is_facing: bool = cy_is_facing(unit, other_unit)
323 ns ± 3.93 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

Python-sc2's `unit.is_facing(other_unit)` alternative:
2.94 µs ± 8 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)

Parameters:

Name Type Description Default
unit Unit

The actual sc2.Unit object we are checking.

required
other_unit int

The unit type id integer value.

required
angle_error (default=0.3)

Some leeway when deciding a unit is facing.

required

Returns:

Name Type Description
bool bool

Is facing the other unit?

Source code in cython_extensions/combat_utils.pyi
def cy_is_facing(unit: Unit, other_unit: int, angle_error: float) -> bool:
    """Get turn speed of unit in radians

    Example:
    ```py
    from cython_extensions import cy_is_facing

    unit: Unit = self.workers[0]
    other_unit: Unit = self.townhalls[0]
    is_facing: bool = cy_is_facing(unit, other_unit)
    ```
    ```
    323 ns ± 3.93 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

    Python-sc2's `unit.is_facing(other_unit)` alternative:
    2.94 µs ± 8 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
    ```

    Parameters
    ----------
    unit :
        The actual sc2.Unit object we are checking.
    other_unit :
        The unit type id integer value.
    angle_error : (default=0.3)
        Some leeway when deciding a unit is facing.

    Returns
    -------
    bool :
        Is facing the other unit?
    """
    ...

cy_pick_enemy_target

cy_pick_enemy_target(enemies)

Pick the best thing to shoot at out of all enemies.

Example:

from cython_extensions import cy_pick_enemy_target
from sc2.units import Units
from sc2.unit import Unit

enemies: Units = self.enemy_units

target: Unit = cy_pick_enemy_target(enemies)
70.5 µs ± 818 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)

Python alternative:
115 µs ± 766 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)

Parameters:

Name Type Description Default
enemies Union[Units, list[Unit]]

All enemy units we would like to check.

required

Returns:

Name Type Description
Unit Unit

The best unit to target.

Source code in cython_extensions/combat_utils.pyi
def cy_pick_enemy_target(enemies: Union[Units, list[Unit]]) -> Unit:
    """Pick the best thing to shoot at out of all enemies.

    Example:
    ```py
    from cython_extensions import cy_pick_enemy_target
    from sc2.units import Units
    from sc2.unit import Unit

    enemies: Units = self.enemy_units

    target: Unit = cy_pick_enemy_target(enemies)
    ```
    ```
    70.5 µs ± 818 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)

    Python alternative:
    115 µs ± 766 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
    ```

    Parameters
    ----------
    enemies :
        All enemy units we would like to check.

    Returns
    -------
    Unit :
        The best unit to target.
    """
    ...

cy_pylon_matrix_covers

cy_pylon_matrix_covers(
    position, pylons, height_grid, pylon_build_progress
)

Check if a position is powered by a pylon.

Example:

from cython_functions import cy_pylon_matrix_covers
from sc2.position import Point2

# check if start location is powered by pylon
position: Point2 = self.start_location

can_place_structure_here: bool = cy_pylon_matrix_covers(
    position,
    self.structures(UnitTypeId.PYLON),
    self.game_info.terrain_height.data_numpy
)

1.85 µs ± 8.72 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

Parameters:

Name Type Description Default
position Union[Point2, tuple[float, float]]

Position to check for power.

required
pylons Union[Units, list[Unit]]

The pylons we want to check.

required
height_grid ndarray

Height grid supplied from python-sc2 as a numpy array.

required
pylon_build_progress Optional(default=1.0)

If less than 1.0, check near pending pylons.

required

Returns:

Name Type Description
bool bool

True if position has power.

Source code in cython_extensions/general_utils.pyi
def cy_pylon_matrix_covers(
    position: Union[Point2, tuple[float, float]],
    pylons: Union[Units, list[Unit]],
    height_grid: np.ndarray,
    pylon_build_progress: float,
) -> bool:
    """Check if a position is powered by a pylon.

    Example:
    ```py
    from cython_functions import cy_pylon_matrix_covers
    from sc2.position import Point2

    # check if start location is powered by pylon
    position: Point2 = self.start_location

    can_place_structure_here: bool = cy_pylon_matrix_covers(
        position,
        self.structures(UnitTypeId.PYLON),
        self.game_info.terrain_height.data_numpy
    )
    ```

    ```
    1.85 µs ± 8.72 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
    ```

    Parameters
    ----------
    position :
        Position to check for power.
    pylons :
        The pylons we want to check.
    height_grid :
        Height grid supplied from `python-sc2` as a numpy array.
    pylon_build_progress : Optional (default=1.0)
        If less than 1.0, check near pending pylons.

    Returns
    -------
    bool :
        True if `position` has power.
    """

cy_unit_pending

cy_unit_pending(ai, unit_type)

Check how many unit_type are pending.

Faster unit specific alternative to python-sc2's already_pending

Example:

from cython_functions import cy_unit_pending
from sc2.ids.unit_typeid import UnitTypeId

num_marines_pending: int = cy_unit_pending(UnitTypeId.MARINE)
453 ns ± 9.35 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

Python-sc2 `already_pending` alternative:
2.82 µs ± 29 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)

Parameters:

Name Type Description Default
ai BotAI

Bot object that will be running the game.

required
unit_type UnitTypeId

Unit type we want to check.

required

Returns:

Name Type Description
int int

How many unit_type are currently building.

Source code in cython_extensions/general_utils.pyi
def cy_unit_pending(ai: "BotAI", unit_type: UnitID) -> int:
    """Check how many unit_type are pending.

    Faster unit specific alternative to `python-sc2`'s `already_pending`

    Example:
    ```py
    from cython_functions import cy_unit_pending
    from sc2.ids.unit_typeid import UnitTypeId

    num_marines_pending: int = cy_unit_pending(UnitTypeId.MARINE)
    ```
    ```
    453 ns ± 9.35 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

    Python-sc2 `already_pending` alternative:
    2.82 µs ± 29 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
    ```

    Parameters
    ----------
    ai :
        Bot object that will be running the game.
    unit_type :
        Unit type we want to check.

    Returns
    -------
    int :
        How many unit_type are currently building.

    """
    ...

cy_angle_diff

cy_angle_diff(a, b)

Absolute angle difference between 2 angles

Parameters:

Name Type Description Default
a float

First angle.

required
b float

Second angle.

required

Returns:

Name Type Description
angle_difference float
Source code in cython_extensions/geometry.pyi
def cy_angle_diff(a: float, b: float) -> float:
    """Absolute angle difference between 2 angles

    Parameters
    ----------
    a : float
        First angle.
    b : float
        Second angle.

    Returns
    -------
    angle_difference : float
    """
    ...

cy_angle_to

cy_angle_to(from_pos, to_pos)

Angle from point to other point in radians

Parameters:

Name Type Description Default
from_pos Union[Point2, tuple[float, float]]

First 2D point.

required
to_pos Union[Point2, tuple[float, float]]

Measure angle to this 2D point.

required

Returns:

Name Type Description
angle float

Angle in radians.

Source code in cython_extensions/geometry.pyi
def cy_angle_to(
    from_pos: Union[Point2, tuple[float, float]],
    to_pos: Union[Point2, tuple[float, float]],
) -> float:
    """Angle from point to other point in radians

    Parameters
    ----------
    from_pos : Union[Point2, tuple[float, float]]
        First 2D point.
    to_pos : Union[Point2, tuple[float, float]]
        Measure angle to this 2D point.

    Returns
    -------
    angle : float
        Angle in radians.
    """
    ...

cy_distance_to

cy_distance_to(p1, p2)

Check distance between two Point2 positions.

Example:

from cython_functions import cy_distance_to

dist: float = cy_distance_to(
    self.start_location, self.game_info.map_center
)
cy_distance_to(Point2, Point2)
157 ns ± 2.69 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)

cy_distance_to(unit1.position, unit2.position)
219 ns ± 10.5 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

Python alternative:

Point1.distance_to(Point2)
386 ns ± 2.71 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

unit1.distance_to(unit2)
583 ns ± 7.89 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

Parameters:

Name Type Description Default
p1 Union[Point2, tuple[float, float]]

First point

required
p2 Union[Point2, tuple[float, float]]

Measure to this point

required

Returns:

Name Type Description
distance float

Distance in tiles

Source code in cython_extensions/geometry.pyi
def cy_distance_to(
    p1: Union[Point2, tuple[float, float]], p2: Union[Point2, tuple[float, float]]
) -> float:
    """Check distance between two Point2 positions.

    Example:
    ```py
    from cython_functions import cy_distance_to

    dist: float = cy_distance_to(
        self.start_location, self.game_info.map_center
    )
    ```
    ```
    cy_distance_to(Point2, Point2)
    157 ns ± 2.69 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)

    cy_distance_to(unit1.position, unit2.position)
    219 ns ± 10.5 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

    Python alternative:

    Point1.distance_to(Point2)
    386 ns ± 2.71 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

    unit1.distance_to(unit2)
    583 ns ± 7.89 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
    ```

    Parameters
    ----------
    p1 : Union[Point2, tuple[float, float]]
        First point
    p2 : Union[Point2, tuple[float, float]]
        Measure to this point

    Returns
    -------
    distance : float
        Distance in tiles

    """
    ...

cy_distance_to_squared

cy_distance_to_squared(p1, p2)

Similar to cy_distance_to but without a square root operation. Use this for ~1.3x speedup

Example:

from cython_functions import cy_distance_to_squared

dist: float = cy_distance_to_squared(
    self.start_location, self.game_info.map_center
)

Parameters:

Name Type Description Default
p1 Union[Point2, tuple[float, float]]

First point

required
p2 Union[Point2, tuple[float, float]]

Measure to this point

required

Returns:

Name Type Description
distance float

Distance in tiles, squared

Source code in cython_extensions/geometry.pyi
def cy_distance_to_squared(
    p1: Union[Point2, tuple[float, float]], p2: Union[Point2, tuple[float, float]]
) -> float:
    """Similar to `cy_distance_to` but without a square root operation.
    Use this for ~1.3x speedup

    Example:
    ```python
    from cython_functions import cy_distance_to_squared

    dist: float = cy_distance_to_squared(
        self.start_location, self.game_info.map_center
    )
    ```

    Parameters
    ----------
    p1 : Union[Point2, tuple[float, float]]
        First point
    p2 : Union[Point2, tuple[float, float]]
        Measure to this point

    Returns
    -------
    distance : float
        Distance in tiles, squared

    """
    ...

cy_find_average_angle

cy_find_average_angle(start_point, reference_point, points)

Find the average angle between the points and the reference point.

Given a starting point, a reference point, and a list of points, find the average angle between the vectors from the starting point to the reference point and the starting point to the points.

Example:

from cython_extensions import cy_find_average_angle

angle: float = cy_get_angle_between_points(
    self.start_location,
    self.game_info.map_center,
    [w.position for w in self.workers]
)

Parameters:

Name Type Description Default
start_point Union[Point2, tuple[float, float]]

Origin for the vectors to the other given points.

required
reference_point Union[Point2, tuple[float, float]]

Vector forming one leg of the angle.

required
points list[Point2]

Points to calculate the angle between relative to the reference point.

required

Returns:

Name Type Description
float float

Average angle in radians between the reference point and the given points.

Source code in cython_extensions/geometry.pyi
def cy_find_average_angle(
    start_point: Union[Point2, tuple[float, float]],
    reference_point: Union[Point2, tuple[float, float]],
    points: list[Point2],
) -> float:
    """Find the average angle between the points and the reference point.

    Given a starting point, a reference point, and a list of points, find the average
    angle between the vectors from the starting point to the reference point and the
    starting point to the points.

    Example:
    ```py
    from cython_extensions import cy_find_average_angle

    angle: float = cy_get_angle_between_points(
        self.start_location,
        self.game_info.map_center,
        [w.position for w in self.workers]
    )
    ```

    Parameters
    ----------
    start_point :
        Origin for the vectors to the other given points.
    reference_point :
        Vector forming one leg of the angle.
    points :
        Points to calculate the angle between relative to the reference point.

    Returns
    -------
    float :
        Average angle in radians between the reference point and the given points.
    """
    ...

cy_find_correct_line

cy_find_correct_line(points, base_location)

Given a list of points and a center point, find if there's a line such that all other points are above or below the line. Returns the line in the form Ax + By + C = 0 and the point that was used.

If no such line is found, it returns ((0, 0, 0), ).

Parameters:

Name Type Description Default
points list[Point2]

Points that need to be on one side of the line.

required
base_location Union[Point2, tuple[float, float]]

Starting point for the line.

required

Returns:

Type Description
Tuple[Tuple[float, float, float], Tuple[float, float]] :

First element is the coefficients of Ax + By + C = 0. Second element is the point used to form the line.

Source code in cython_extensions/geometry.pyi
def cy_find_correct_line(
    points: list[Point2], base_location: Union[Point2, tuple[float, float]]
) -> tuple[tuple[float], tuple[float]]:
    """
    Given a list of points and a center point, find if there's a line such that all
    other points are above or below the line. Returns the line in the form
    Ax + By + C = 0 and the point that was used.

    If no such line is found, it returns ((0, 0, 0), <last_point_checked>).

    Parameters
    ----------
    points :
        Points that need to be on one side of the line.
    base_location :
        Starting point for the line.

    Returns
    -------
    Tuple[Tuple[float, float, float], Tuple[float, float]] :
        First element is the coefficients of Ax + By + C = 0.
        Second element is the point used to form the line.
    """
    ...

cy_get_angle_between_points

cy_get_angle_between_points(point_a, point_b)

Get the angle between two points as if they were vectors from the origin.

Example:

from cython_functions import cy_get_angle_between_points

angle: float = cy_get_angle_between_points(
    self.start_location, self.game_info.map_center
)

Parameters:

Name Type Description Default
point_a Union[Point2, tuple[float, float]]

First point

required
point_b Union[Point2, tuple[float, float]]

Measure to this point

required

Returns:

Name Type Description
float float
Source code in cython_extensions/geometry.pyi
def cy_get_angle_between_points(
    point_a: Union[Point2, tuple[float, float]],
    point_b: Union[Point2, tuple[float, float]],
) -> float:
    """Get the angle between two points as if they were vectors from the origin.

    Example:
    ```py
    from cython_functions import cy_get_angle_between_points

    angle: float = cy_get_angle_between_points(
        self.start_location, self.game_info.map_center
    )
    ```

    Parameters
    ----------
    point_a :
        First point
    point_b :
        Measure to this point

    Returns
    -------
    float :

    """
    ...

cy_towards

cy_towards(start_pos, target_pos, distance)

Get position from start_pos towards target_pos based on distance.

Example:

from cython_functions import cy_towards

new_pos: Tuple[float, float] = cy_towards(
    self.start_location,
    self.game_info.map_center,
    12.0
)

Note: For performance reasons this returns the point2 as a tuple, if a python-sc2 Point2 is required it's up to the user to convert it.

Example:

new_pos: Point2 = Point2(
    cy_towards(
        self.start_location, self.enemy_start_locations, 10.0
    )
)

Though for best performance it is recommended to simply work with the tuple if possible:

new_pos: tuple[float, float] = cy_towards(
    self.start_location, self.enemy_start_locations, 10.0
)

191 ns ± 0.855 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)

Python-sc2's `start_pos.towards(target_pos, distance)` alternative:
2.73 µs ± 18.9 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)

Parameters:

Name Type Description Default
start_pos Point2

Start from this 2D position.

required
target_pos Point2

Go towards this 2D position.

required
distance float

How far we go towards target_pos.

required

Returns:

Type Description
tuple[float, float] :
Source code in cython_extensions/geometry.pyi
def cy_towards(
    start_pos: Point2, target_pos: Point2, distance: float
) -> tuple[float, float]:
    """Get position from start_pos towards target_pos based on distance.

    Example:
    ```py
    from cython_functions import cy_towards

    new_pos: Tuple[float, float] = cy_towards(
        self.start_location,
        self.game_info.map_center,
        12.0
    )
    ```

    Note: For performance reasons this returns the point2 as a tuple, if a
    python-sc2 Point2 is required it's up to the user to convert it.

    Example:
    ```py
    new_pos: Point2 = Point2(
        cy_towards(
            self.start_location, self.enemy_start_locations, 10.0
        )
    )
    ```

    Though for best performance it is recommended to simply work with the tuple if possible:
    ```py
    new_pos: tuple[float, float] = cy_towards(
        self.start_location, self.enemy_start_locations, 10.0
    )
    ```

    ```
    191 ns ± 0.855 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)

    Python-sc2's `start_pos.towards(target_pos, distance)` alternative:
    2.73 µs ± 18.9 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
    ```


    Parameters
    ----------
    start_pos :
        Start from this 2D position.
    target_pos :
        Go towards this 2D position.
    distance :
        How far we go towards target_pos.

    Returns
    -------
    tuple[float, float] :

    """
    ...

cy_translate_point_along_line

cy_translate_point_along_line(point, a_value, distance)

Parameters:

Name Type Description Default
point Union[Point2, tuple[float, float]]
required
a_value float
required
distance float
required

Returns:

Type Description
Tuple[float, float]]
Source code in cython_extensions/geometry.pyi
def cy_translate_point_along_line(
    point: Union[Point2, tuple[float, float]], a_value: float, distance: float
) -> tuple[float, float]:
    """

    Parameters
    ----------
    point :
    a_value :
    distance :

    Returns
    -------
    Tuple[float, float]]
    """
    ...

cy_flood_fill_grid

cy_flood_fill_grid(
    start_point,
    terrain_grid,
    pathing_grid,
    max_distance,
    cutoff_points,
)

Given a set of coordinates, draw a box that fits all the points.

Example:

from cython_extensions import cy_flood_fill_grid

all_points = terrain_flood_fill(
    start_point=self.start_location.rounded,
    terrain_grid=self.game_info.terrain_height.data_numpy.T,
    pathing_grid=self.game_info.pathing_grid.data_numpy.T,
    max_distance=40,
    choke_points={}
)

Parameters:

Name Type Description Default
start_point Union[Point2, tuple]

Start algorithm from here.

required
terrain_grid ndarray

Numpy array containing heights for the map.

required
pathing_grid ndarray

Numpy array containing pathing values for the map.

required
max_distance int

The maximum distance the flood fill should reach before halting.

required
cutoff_points set

Points which we don't want the algorithm to pass. Choke points are a good use case.

required

Returns:

Type Description
Tuple[Tuple[float, float], Tuple[float, float]] :

A pair of coordinates that determine the box in the following format: ((xmin, xmax), (ymin, ymax))

Source code in cython_extensions/map_analysis.pyi
def cy_flood_fill_grid(
    start_point: Union[Point2, tuple],
    terrain_grid: np.ndarray,
    pathing_grid: np.ndarray,
    max_distance: int,
    cutoff_points: set,
) -> set[tuple]:
    """Given a set of coordinates, draw a box that fits
    all the points.

    Example:
    ```py
    from cython_extensions import cy_flood_fill_grid

    all_points = terrain_flood_fill(
        start_point=self.start_location.rounded,
        terrain_grid=self.game_info.terrain_height.data_numpy.T,
        pathing_grid=self.game_info.pathing_grid.data_numpy.T,
        max_distance=40,
        choke_points={}
    )

    ```

    Parameters
    ----------
    start_point :
        Start algorithm from here.
    terrain_grid :
        Numpy array containing heights for the map.
    pathing_grid :
        Numpy array containing pathing values for the map.
    max_distance :
        The maximum distance the flood fill should reach
        before halting.
    cutoff_points :
        Points which we don't want the algorithm to pass.
        Choke points are a good use case.


    Returns
    -------
    Tuple[Tuple[float, float], Tuple[float, float]] :
        A pair of coordinates that determine the box in the following format:
        ((xmin, xmax), (ymin, ymax))

    """
    ...

cy_get_bounding_box

cy_get_bounding_box(coordinates)

Given a set of coordinates, draw a box that fits all the points.

Example:

from cython_extensions import cy_get_bounding_box

points: set[Point2] = {w.position for w in self.workers}
raw_x_bounds, raw_y_bounds = cy_get_bounding_box(points)

Parameters:

Name Type Description Default
coordinates The points we want to draw a box around.
required

Returns:

Type Description
Tuple[Tuple[float, float], Tuple[float, float]] :

A pair of coordinates that determine the box in the following format: ((xmin, xmax), (ymin, ymax))

Source code in cython_extensions/map_analysis.pyi
def cy_get_bounding_box(
    coordinates: set[Point2],
) -> tuple[tuple[float, float], tuple[float, float]]:
    """Given a set of coordinates, draw a box that fits
    all the points.

    Example:
    ```py
    from cython_extensions import cy_get_bounding_box

    points: set[Point2] = {w.position for w in self.workers}
    raw_x_bounds, raw_y_bounds = cy_get_bounding_box(points)

    ```

    Parameters
    ----------
    coordinates : The points we want to draw a box around.

    Returns
    -------
    Tuple[Tuple[float, float], Tuple[float, float]] :
        A pair of coordinates that determine the box in the following format:
        ((xmin, xmax), (ymin, ymax))

    """
    ...

cy_all_points_below_max_value

cy_all_points_below_max_value(grid, value, points_to_check)

Check points on grid, and return True if they are all below value.

Example:

from cython_extensions import cy_all_points_below_max_value

# pretend grid has enemy influence added
grid = self.game_info.pathing_grid.data_numpy.T
all_safe: bool = cy_all_points_below_max_value(
    grid, 1.0, [self.start_location.rounded]
)

Parameters:

Name Type Description Default
grid ndarray

The grid to check.

required
value float

The max value.

required
points_to_check list[tuple[int, int]]

List of points we are checking.

required

Returns:

Name Type Description
bool bool

Are all points_to_check below value?.

Source code in cython_extensions/numpy_helper.pyi
def cy_all_points_below_max_value(
    grid: np.ndarray, value: float, points_to_check: list[tuple[int, int]]
) -> bool:
    """Check points on grid, and return True if they are all below
    `value`.

    Example:
    ```py
    from cython_extensions import cy_all_points_below_max_value

    # pretend grid has enemy influence added
    grid = self.game_info.pathing_grid.data_numpy.T
    all_safe: bool = cy_all_points_below_max_value(
        grid, 1.0, [self.start_location.rounded]
    )

    ```

    Parameters
    ----------
    grid :
        The grid to check.
    value :
        The max value.
    points_to_check :
        List of points we are checking.
    Returns
    -------
    bool :
        Are all points_to_check below value?.

    """
    ...

cy_all_points_have_value

cy_all_points_have_value(grid, value, points)

Check points on grid, and return True if they are all equal value.

Example:

from cython_extensions import cy_all_points_have_value

# pretend grid has enemy influence added
grid = self.game_info.pathing_grid.data_numpy.T
all_safe: bool = cy_all_points_have_value(
    grid, 1.0, [self.start_location.rounded]
)

Parameters:

Name Type Description Default
grid ndarray

The grid to check.

required
value float

The max value.

required
points list[tuple[int, int]]

List of points we are checking.

required

Returns:

Name Type Description
bool bool

Are all points equal value?.

Source code in cython_extensions/numpy_helper.pyi
def cy_all_points_have_value(
    grid: np.ndarray, value: float, points: list[tuple[int, int]]
) -> bool:
    """Check points on grid, and return True if they are all equal
    `value`.

    Example:
    ```py
    from cython_extensions import cy_all_points_have_value

    # pretend grid has enemy influence added
    grid = self.game_info.pathing_grid.data_numpy.T
    all_safe: bool = cy_all_points_have_value(
        grid, 1.0, [self.start_location.rounded]
    )

    ```

    Parameters
    ----------
    grid :
        The grid to check.
    value :
        The max value.
    points :
        List of points we are checking.
    Returns
    -------
    bool :
        Are all points equal value?.

    """
    ...

cy_last_index_with_value

cy_last_index_with_value(grid, value, points)

Finds the last index with the matching value, stopping as soon as a value doesn't match. Returns -1 if points is empty or the first value doesn't match

Example:

from cython_extensions import cy_last_index_with_value

grid = self.game_info.pathing_grid.data_numpy.T
points: list[Point2] = [w.position.rounded for w in self.workers]
last_pathable_index = cy_last_index_with_value(grid, 1, points)

Parameters:

Name Type Description Default
grid ndarray

The grid to check points on.

required
value int

The value we are looking for.

required
points list[tuple[int, int]]

Points we want to check

required

Returns:

Name Type Description
int int

The last index in points that has value

Source code in cython_extensions/numpy_helper.pyi
def cy_last_index_with_value(
    grid: np.ndarray, value: int, points: list[tuple[int, int]]
) -> int:
    """Finds the last index with the matching value, stopping as soon as a
    value doesn't match.
    Returns -1 if points is empty or the first value doesn't match

    Example:
    ```py
    from cython_extensions import cy_last_index_with_value

    grid = self.game_info.pathing_grid.data_numpy.T
    points: list[Point2] = [w.position.rounded for w in self.workers]
    last_pathable_index = cy_last_index_with_value(grid, 1, points)

    ```

    Parameters
    ----------
    grid :
        The grid to check `points` on.
    value :
        The value we are looking for.
    points :
        Points we want to check

    Returns
    -------
    int :
        The last index in `points` that has `value`

    """
    ...

cy_point_below_value

cy_point_below_value(
    grid, position, weight_safety_limit=1.0
)

Check a position on a 2D grid. Is it below weight_safety_limit? Useful for checking enemy influence on a position.

Example:

from cython_extensions import cy_point_below_value

# pretend grid has enemy influence added
grid = self.game_info.pathing_grid.data_numpy.T
safe: bool = cy_point_below_value(grid, self.start_location.rounded)

987 ns ± 10.1 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

Python alternative:
4.66 µs ± 64.8 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)

Parameters:

Name Type Description Default
grid ndarray

The grid to check.

required
position tuple[int, int]

2D coordinate to check on grid.

required
weight_safety_limit (default = 1.0)

We want to check of point is less or equal to this.

1.0

Returns:

Name Type Description
int bool

The last index in points that has value

Source code in cython_extensions/numpy_helper.pyi
def cy_point_below_value(
    grid: np.ndarray, position: tuple[int, int], weight_safety_limit: float = 1.0
) -> bool:
    """Check a position on a 2D grid.
    Is it below `weight_safety_limit`?
    Useful for checking enemy influence on a position.

    Example:
    ```py
    from cython_extensions import cy_point_below_value

    # pretend grid has enemy influence added
    grid = self.game_info.pathing_grid.data_numpy.T
    safe: bool = cy_point_below_value(grid, self.start_location.rounded)
    ```

    ```
    987 ns ± 10.1 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

    Python alternative:
    4.66 µs ± 64.8 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
    ```

    Parameters
    ----------
    grid :
        The grid to check.
    position :
        2D coordinate to check on grid.
    weight_safety_limit : (default = 1.0)
        We want to check of point is less or equal to this.
    Returns
    -------
    int :
        The last index in `points` that has `value`

    """
    ...

cy_points_with_value

cy_points_with_value(grid, value, points)

Check points on grid, and return those that equal value

Example:

from cython_extensions import cy_points_with_value
import numpy as np

# pretend grid has enemy influence added
grid: np.ndarray = self.game_info.pathing_grid.data_numpy.T
safe: bool = cy_points_with_value(
    grid, 1.0, [self.start_location.rounded]
)

Parameters:

Name Type Description Default
grid ndarray

The grid to check.

required
value float

2D coordinate to check on grid.

required
points list[tuple[int, int]]

List of points we are checking.

required

Returns:

Type Description
list[tuple[int, int]] :

All points that equal value on grid.

Source code in cython_extensions/numpy_helper.pyi
def cy_points_with_value(
    grid: np.ndarray, value: float, points: list[tuple[int, int]]
) -> list[tuple[int, int]]:
    """Check points on grid, and return those that equal `value`

    Example:
    ```py
    from cython_extensions import cy_points_with_value
    import numpy as np

    # pretend grid has enemy influence added
    grid: np.ndarray = self.game_info.pathing_grid.data_numpy.T
    safe: bool = cy_points_with_value(
        grid, 1.0, [self.start_location.rounded]
    )

    ```

    Parameters
    ----------
    grid :
        The grid to check.
    value :
        2D coordinate to check on grid.
    points :
        List of points we are checking.
    Returns
    -------
    list[tuple[int, int]] :
        All points that equal `value` on grid.

    """
    ...

cy_can_place_structure

cy_can_place_structure(
    building_origin,
    building_size,
    creep_grid,
    placement_grid,
    pathing_grid,
    avoid_creep=True,
    include_addon=False,
)

Simulate whether a structure can be placed at building_origin Fast alternative to python-sc2 can_place

Example:

from cython_extensions import cy_can_place_structure

can_place: bool = cy_can_place_structure(
    (155, 45),
    (3, 3),
    self.ai.state.creep.data_numpy,
    self.ai.game_info.placement_grid.data_numpy,
    self.ai.game_info.pathing_grid.data_numpy,
    avoid_creep=self.race != Race.Zerg,
    include_addon=False,
)

1.21 µs ± 891 ns per loop (mean ± std. dev. of 1000 runs, 10 loops each)

Parameters:

Name Type Description Default
building_origin tuple[int, int]

The top left corner of the intended structure.

required
building_size tuple[int, int]

For example: (3, 3) for barracks. (2, 2) for depot (5, 5) for command center

required
creep_grid ndarray

Creep grid

required
placement_grid ndarray
required
pathing_grid ndarray
required
avoid_creep (default = True)

ENSURE THIS IS FALSE IF CHECKING ZERG STRUCTURES

True
include_addon (default = False)

Check if there is room for addon too?

False

Returns:

Name Type Description
bool bool

Can we place structure at building_origin?.

Source code in cython_extensions/placement_solver.pyi
def cy_can_place_structure(
    building_origin: tuple[int, int],
    building_size: tuple[int, int],
    creep_grid: np.ndarray,
    placement_grid: np.ndarray,
    pathing_grid: np.ndarray,
    avoid_creep: bool = True,
    include_addon: bool = False,
) -> bool:
    """Simulate whether a structure can be placed at `building_origin`
    Fast alternative to python-sc2 `can_place`

    Example:
    ```py
    from cython_extensions import cy_can_place_structure

    can_place: bool = cy_can_place_structure(
        (155, 45),
        (3, 3),
        self.ai.state.creep.data_numpy,
        self.ai.game_info.placement_grid.data_numpy,
        self.ai.game_info.pathing_grid.data_numpy,
        avoid_creep=self.race != Race.Zerg,
        include_addon=False,
    )
    ```

    ```
    1.21 µs ± 891 ns per loop (mean ± std. dev. of 1000 runs, 10 loops each)
    ```

    Parameters
    ----------
    building_origin :
        The top left corner of the intended structure.
    building_size :
        For example: (3, 3) for barracks.
        (2, 2) for depot
        (5, 5) for command center
    creep_grid :
        Creep grid
    placement_grid :
    pathing_grid :
    avoid_creep : (default = True)
        ENSURE THIS IS FALSE IF CHECKING ZERG STRUCTURES
    include_addon : (default = False)
        Check if there is room for addon too?


    Returns
    -------
    bool :
        Can we place structure at building_origin?.

    """
    ...

cy_find_building_locations

cy_find_building_locations(
    kernel,
    x_stride,
    y_stride,
    x_bounds,
    y_bounds,
    creep_grid,
    placement_grid,
    pathing_grid,
    points_to_avoid_grid,
    avoid_creep=True,
    include_addon=False,
)

Use a convolution pass to find all possible building locations in an area Check ares-sc2 for a full example of using this to calculate building formations.

https://github.com/AresSC2/ares-sc2/blob/main/src/ares/managers/placement_manager.py

Example:

from cython_extensions import cy_find_building_locations

# find 3x3 locations, making room for addons.
# check out map_analysis.cy_get_bounding_box to calculate
# raw_x_bounds and raw_x_bounds
three_by_three_positions = cy_find_building_locations(
    kernel=np.ones((5, 3), dtype=np.uint8),
    x_stride=5,
    y_stride=3,
    x_bounds=raw_x_bounds,
    y_bounds=raw_y_bounds,
    creep_grid=creep_grid,
    placement_grid=placement_grid,
    pathing_grid=pathing_grid,
    points_to_avoid_grid=self.points_to_avoid_grid,
    building_width=3,
    building_height=3,
    avoid_creep=True
)

64.8 µs ± 4.05 µs per loop (mean ± std. dev. of 1000 runs, 10 loops each)

Parameters:

Name Type Description Default
kernel ndarray

The size of the sliding window that scans this area.

required
x_stride int

The x distance the kernel window moves each step.

required
y_stride int

The y distance the kernel window moves downwards.

required
x_bounds tuple[int, int]

The starting point of the algorithm.

required
y_bounds tuple[int, int]

The end point of the algorithm.

required
creep_grid ndarray
required
placement_grid ndarray
required
pathing_grid ndarray
required
points_to_avoid_grid ndarray

Grid containing 1s where we shouldn't place anything.

required
avoid_creep (default = True)

ENSURE THIS IS FALSE IF CHECKING ZERG STRUCTURES

True
include_addon (default = False)

Check if there is room for addon too?

False

Returns:

Type Description
list[tuple[float, float]] :

Final list of positions that make up the building formation.

Source code in cython_extensions/placement_solver.pyi
def cy_find_building_locations(
    kernel: np.ndarray,
    x_stride: int,
    y_stride: int,
    x_bounds: tuple[int, int],
    y_bounds: tuple[int, int],
    creep_grid: np.ndarray,
    placement_grid: np.ndarray,
    pathing_grid: np.ndarray,
    points_to_avoid_grid: np.ndarray,
    avoid_creep: bool = True,
    include_addon: bool = False,
) -> list[tuple[float, float]]:
    """Use a convolution pass to find all possible building locations in an area
    Check `ares-sc2` for a full example of using this to calculate
    building formations.

    https://github.com/AresSC2/ares-sc2/blob/main/src/ares/managers/placement_manager.py

    Example:
    ```py
    from cython_extensions import cy_find_building_locations

    # find 3x3 locations, making room for addons.
    # check out map_analysis.cy_get_bounding_box to calculate
    # raw_x_bounds and raw_x_bounds
    three_by_three_positions = cy_find_building_locations(
        kernel=np.ones((5, 3), dtype=np.uint8),
        x_stride=5,
        y_stride=3,
        x_bounds=raw_x_bounds,
        y_bounds=raw_y_bounds,
        creep_grid=creep_grid,
        placement_grid=placement_grid,
        pathing_grid=pathing_grid,
        points_to_avoid_grid=self.points_to_avoid_grid,
        building_width=3,
        building_height=3,
        avoid_creep=True
    )

    ```

    ```
    64.8 µs ± 4.05 µs per loop (mean ± std. dev. of 1000 runs, 10 loops each)
    ```

    Parameters
    ----------
    kernel :
        The size of the sliding window that scans this area.
    x_stride :
        The x distance the kernel window moves each step.
    y_stride :
        The y distance the kernel window moves downwards.
    x_bounds :
        The starting point of the algorithm.
    y_bounds :
        The end point of the algorithm.
    creep_grid :
    placement_grid :
    pathing_grid :
    points_to_avoid_grid :
        Grid containing `1`s where we shouldn't place anything.
    avoid_creep : (default = True)
        ENSURE THIS IS FALSE IF CHECKING ZERG STRUCTURES
    include_addon : (default = False)
        Check if there is room for addon too?


    Returns
    -------
    list[tuple[float, float]] :
        Final list of positions that make up the building formation.

    """
    ...

cy_center

cy_center(units)

Given some units, find the center point.

Example:

from ares.cython_functions.units_utils import cy_center

centroid: Tuple[float, float] = cy_center(self.workers)

# centroid_point2 = Point2(centroid)

54.2 µs ± 137 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)

`python-sc2`'s `units.center` alternative:
107 µs ± 255 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)

Parameters:

Name Type Description Default
units Union[Units, list[Unit]]
required

Returns:

Type Description
tuple[float, float] :

Centroid of all units positions

Source code in cython_extensions/units_utils.pyi
def cy_center(units: Union[Units, list[Unit]]) -> tuple[float, float]:
    """Given some units, find the center point.


    Example:
    ```py
    from ares.cython_functions.units_utils import cy_center

    centroid: Tuple[float, float] = cy_center(self.workers)

    # centroid_point2 = Point2(centroid)
    ```

    ```
    54.2 µs ± 137 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)

    `python-sc2`'s `units.center` alternative:
    107 µs ± 255 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
    ```

    Parameters
    ----------
    units :

    Returns
    -------
    tuple[float, float] :
        Centroid of all units positions
    """
    ...

cy_closest_to

cy_closest_to(position, units)

Iterate through units to find closest to position.

Example:

from cython_functions import cy_closest_to
from sc2.unit import Unit

closest_unit: Unit = cy_closest_to(self.start_location, self.workers)

14.3 µs ± 135 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)

python-sc2's `units.closest_to()` alternative:
98.9 µs ± 240 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)

If using python-sc2's `units.closest_to(Point2):
200 µs ± 1.02 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

Parameters:

Name Type Description Default
position Union[Point2, tuple[float, float]]

Position to measure distance from.

required
units Union[Units, list[Unit]]

Collection of units we want to check.

required

Returns:

Name Type Description
Unit Unit

Unit closest to position.

Source code in cython_extensions/units_utils.pyi
def cy_closest_to(
    position: Union[Point2, tuple[float, float]], units: Union[Units, list[Unit]]
) -> Unit:
    """Iterate through `units` to find closest to `position`.

    Example:
    ```py
    from cython_functions import cy_closest_to
    from sc2.unit import Unit

    closest_unit: Unit = cy_closest_to(self.start_location, self.workers)
    ```

    ```
    14.3 µs ± 135 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)

    python-sc2's `units.closest_to()` alternative:
    98.9 µs ± 240 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)

    If using python-sc2's `units.closest_to(Point2):
    200 µs ± 1.02 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
    ```

    Parameters
    ----------
    position :
        Position to measure distance from.
    units :
        Collection of units we want to check.

    Returns
    -------
    Unit :
        Unit closest to `position`.

    """
    ...

cy_find_units_center_mass

cy_find_units_center_mass(units, distance)

Given some units, find the center mass

Example:

from cython_functions import cy_find_units_center_mass
from sc2.position import Point2

center_mass: Point2
num_units: int
center_mass, num_units = cy_find_units_center_mass(self.units, 10.0)

47.8 ms ± 674 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

python alternative:
322 ms ± 5.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

Parameters:

Name Type Description Default
units Union[Units, list[Unit]]

Position to measure distance from.

required
distance float

Collection of units we want to check.

required

Returns:

Type Description
Tuple[Point2, int] :

The center mass, and how many units are within distance of the center mass.

Source code in cython_extensions/units_utils.pyi
def cy_find_units_center_mass(
    units: Union[Units, list[Unit]], distance: float
) -> Unit:
    """Given some units, find the center mass

    Example:
    ```py
    from cython_functions import cy_find_units_center_mass
    from sc2.position import Point2

    center_mass: Point2
    num_units: int
    center_mass, num_units = cy_find_units_center_mass(self.units, 10.0)
    ```

    ```
    47.8 ms ± 674 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

    python alternative:
    322 ms ± 5.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
    ```

    Parameters
    ----------
    units :
        Position to measure distance from.
    distance :
        Collection of units we want to check.

    Returns
    -------
    Tuple[Point2, int] :
        The center mass, and how many units are within `distance`
        of the center mass.

    """
    ...

cy_in_attack_range

cy_in_attack_range(unit, units, bonus_distance=0.0)

Find all units that unit can shoot at.

Doesn't check if the unit weapon is ready. See: cython_functions.attack_ready

Example:

from cython_functions import cy_in_attack_range
from sc2.unit import Unit

in_attack_range: list[Unit] = cy_in_attack_range(self.workers[0], self.enemy_units)

7.28 µs ± 26.3 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)

python-sc2's `units.in_attack_range_of(unit)` alternative:
30.4 µs ± 271 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)

Parameters:

Name Type Description Default
unit Unit

Position to measure distance from.

required
units Union[Units, list[Unit]]

Collection of units we want to check.

required
bonus_distance float
0.0

Returns:

Type Description
list[Unit] :

Units that are in attack range of unit.

Source code in cython_extensions/units_utils.pyi
def cy_in_attack_range(
    unit: Unit, units: Union[Units, list[Unit]], bonus_distance: float = 0.0
) -> list[Unit]:
    """Find all units that unit can shoot at.

    Doesn't check if the unit weapon is ready. See:
    `cython_functions.attack_ready`

    Example:
    ```py
    from cython_functions import cy_in_attack_range
    from sc2.unit import Unit

    in_attack_range: list[Unit] = cy_in_attack_range(self.workers[0], self.enemy_units)
    ```

    ```
    7.28 µs ± 26.3 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)

    python-sc2's `units.in_attack_range_of(unit)` alternative:
    30.4 µs ± 271 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
    ```

    Parameters
    ----------
    unit :
        Position to measure distance from.
    units :
        Collection of units we want to check.
    bonus_distance :

    Returns
    -------
    list[Unit] :
        Units that are in attack range of `unit`.

    """
    ...

cy_sorted_by_distance_to

cy_sorted_by_distance_to(units, position, reverse=False)

Sort units by distance to position

Example:

from cython_functions import cy_sorted_by_distance_to
from sc2.unit import Unit

sorted_by_distance: list[Unit] = cy_sorted_by_distance_to(
    self.workers, self.start_location
)

33.7 µs ± 190 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)

python-sc2's `units.sorted_by_distance_to(position)` alternative:
246 µs ± 830 ns per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

Parameters:

Name Type Description Default
units Union[Units, list[Unit]]

Units we want to sort.

required
position Point2

Sort by distance to this position.

required
reverse bool

Not currently used.

False

Returns:

Type Description
list[Unit] :

Units sorted by distance to position.

Source code in cython_extensions/units_utils.pyi
def cy_sorted_by_distance_to(
    units: Union[Units, list[Unit]], position: Point2, reverse: bool = False
) -> list[Unit]:
    """Sort units by distance to `position`

    Example:
    ```py
    from cython_functions import cy_sorted_by_distance_to
    from sc2.unit import Unit

    sorted_by_distance: list[Unit] = cy_sorted_by_distance_to(
        self.workers, self.start_location
    )
    ```

    ```
    33.7 µs ± 190 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)

    python-sc2's `units.sorted_by_distance_to(position)` alternative:
    246 µs ± 830 ns per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
    ```

    Parameters
    ----------
    units :
        Units we want to sort.
    position :
        Sort by distance to this position.
    reverse :
        Not currently used.
    Returns
    -------
    list[Unit] :
        Units sorted by distance to position.

    """
    ...