Cython Extensions SC2
cy_attack_ready ¶
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
cy_is_facing ¶
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
cy_pick_enemy_target ¶
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
cy_pylon_matrix_covers ¶
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
)
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 |
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 |
Source code in cython_extensions/general_utils.pyi
cy_unit_pending ¶
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
cy_angle_diff ¶
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
cy_angle_to ¶
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
cy_distance_to ¶
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
cy_distance_to_squared ¶
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
cy_find_average_angle ¶
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
cy_find_correct_line ¶
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
cy_get_angle_between_points ¶
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
cy_towards ¶
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:
Though for best performance it is recommended to simply work with the tuple if possible:
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
cy_translate_point_along_line ¶
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
cy_flood_fill_grid ¶
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
cy_get_bounding_box ¶
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
cy_all_points_below_max_value ¶
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
cy_all_points_have_value ¶
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
cy_last_index_with_value ¶
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 |
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 |
Source code in cython_extensions/numpy_helper.pyi
cy_point_below_value ¶
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 |
Source code in cython_extensions/numpy_helper.pyi
cy_points_with_value ¶
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 |
Source code in cython_extensions/numpy_helper.pyi
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,
)
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
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
)
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 |
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
cy_center ¶
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
cy_closest_to ¶
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 |
Source code in cython_extensions/units_utils.pyi
cy_find_units_center_mass ¶
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 |
Source code in cython_extensions/units_utils.pyi
cy_in_attack_range ¶
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 |
Source code in cython_extensions/units_utils.pyi
cy_sorted_by_distance_to ¶
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. |