Cython Extensions SC2
cy_adjust_moving_formation(our_units, target, fodder_tags, unit_multiplier, retreat_angle)
¶
Adjust units formation.
Big thanks to idontcodethisgame for the original code in Eris
The idea here is that we give UnitTypeId's a fodder value, and this cython function works out which unit we want at the front to absorb damage. This works by returning a dictionary containing tags of the non fodder units that need to move backwards behind the fodder and the position they should move to.
TIP: Don't use this when combat is already active, will probably lead to anti-micro. Use this while moving across the map and pre combat.
Example:
import numpy as np
from cython_extensions import cy_find_aoe_position, cy_find_units_center_mass
from sc2.ids.ability_id import AbilityId
from sc2.ids.unit_typeid import UnitTypeId
from sc2.position import Point2
from sc2.units import Units
from sc2.unit import Unit
def detect_fodder_value(self, units) -> int:
# zealot will always be fodder
# if no zealot this will pick the next best unit type
# stalker will never be fodder in this example
unit_fodder_values: dict[UnitTypeId, int] = {
UnitTypeId.STALKER: 4,
UnitTypeId.ZEALOT: 1,
UnitTypeId.ADEPT: 2,
UnitTypeId.PROBE: 3,
}
# establish how many fodder levels there are
unit_type_fodder_values: set[int] = {
unit_fodder_values[u.type_id]
for u in units
if u.type_id in unit_fodder_values
}
# if there's only one fodder level, no units are fodder
if len(unit_type_fodder_values) > 1:
return min(unit_type_fodder_values)
else:
return 0
async def on_step(self, iteration: int):
if not self.enemy_units:
return
# find lowest fodder value among our units
# will return 0 if our army only has one fodder level
fodder_value: int = self.detect_fodder_value(self.units)
fodder_tags = []
units_that_need_to_move = dict()
# there are fodder levels, calculate unit adjustment
if fodder_value > 0:
for unit in self.units:
if (
unit.type_id in self.unit_fodder_values
and self.unit_fodder_values[unit.type_id] == fodder_value
):
fodder_tags.append(unit.tag)
units_that_need_to_move = cy_adjust_moving_formation(
self.units,
cy_find_units_center_mass(self.enemy_units, 5.0)[0],
fodder_tags,
1.0,
0.25,
)
for unit in self.units:
if (
unit.tag in units_that_need_to_move
and unit.distance_to(self.enemy_units.center) > 9.0
):
# in practise check this position is valid (pathable, in bounds etc)
# left out here for example clarity
unit.move(Point2(units_that_need_to_move[unit.tag]))
else:
unit.attack(self.enemy_units.center)
324 µs ± 9.44 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
Parameters:
Name | Type | Description | Default |
---|---|---|---|
our_units
|
Union[Units, list[Unit]]
|
All our squad units, including core and fodder. |
required |
target
|
Union[Point2, tuple[float, float]]
|
The target we want the fodder to lead us to. |
required |
fodder_tags
|
list[int]
|
A list of fodder unit tags. |
required |
unit_multiplier
|
float
|
How far core units should retreat when adjusting during combat. |
required |
retreat_angle
|
float
|
Angle (in radians) for diagonal retreat of core units. |
required |
Returns:
Type | Description |
---|---|
dict[int, tuple[float, float]]
|
A dictionary where keys are unit tags requiring movement |
dict[int, tuple[float, float]]
|
and values are tuples of x, y coordinates. |
Source code in cython_extensions/combat_utils.pyi
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 |
|
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:
Type | Description |
---|---|
bool
|
True if the unit is ready to attack the target, False otherwise. |
Source code in cython_extensions/combat_utils.pyi
cy_find_aoe_position(effect_radius, targets, bonus_tags=None)
¶
Find best splash target given a group of enemies.
Big thanks to idontcodethisgame for the original code in Eris
WARNING: Please don't spam this function, it's fine to use as required but is costly. For example: only use this if unit ability is ready, only if enemy are in combat range etc.
Example:
import numpy as np
from cython_extensions import cy_find_aoe_position
from sc2.ids.ability_id import AbilityId
from sc2.ids.unit_typeid import UnitTypeId
from sc2.position import Point2
from sc2.units import Units
from sc2.unit import Unit
enemies: Units = self.enemy_units
for unit in self.units:
if unit.type_id == UnitTypeId.RAVAGER:
# in practice, don't do this query for every individual unit
abilities = await self.get_available_abilities(unit)
if AbilityId.EFFECT_CORROSIVEBILE in abilities:
target: Optional[np.ndarray] = cy_find_aoe_position(effect_radius=1.375, targets=enemies)
# in practise in some scenarios, you should do an extra check to
# count how many units you would hit, this only finds position, not amount
if pos is not None:
unit(AbilityId.EFFECT_CORROSIVEBILE, Point2(pos))
Parameters:
Name | Type | Description | Default |
---|---|---|---|
effect_radius
|
float
|
The radius of the effect (range). |
required |
targets
|
Union[Units, list[Unit]]
|
All enemy units we would like to check. |
required |
bonus_tags
|
set[int]
|
If provided, give more value to these enemy tags. |
None
|
Returns:
Type | Description |
---|---|
Optional[ndarray]
|
A 1D numpy array containing x and y coordinates of aoe position, |
Optional[ndarray]
|
or None. |
Source code in cython_extensions/combat_utils.pyi
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 unit we are checking. |
required |
other_unit
|
int
|
The unit type ID integer value. |
required |
angle_error
|
float
|
Some leeway when deciding if a unit is facing the other unit. |
required |
Returns:
Type | Description |
---|---|
bool
|
True if the unit is facing the other unit, False otherwise. |
Source code in cython_extensions/combat_utils.pyi
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:
Type | Description |
---|---|
Unit
|
The best unit to target. |
Source code in cython_extensions/combat_utils.pyi
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
)
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
|
float
|
If less than 1.0, check near pending pylons. Default is 1.0. |
required |
Returns:
Type | Description |
---|---|
bool
|
True if |
Source code in cython_extensions/general_utils.pyi
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:
Type | Description |
---|---|
int
|
How many unit_type are currently building. |
Source code in cython_extensions/general_utils.pyi
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
|
Difference between the two angles. |
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
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
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
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:
Type | Description |
---|---|
float
|
Average angle in radians between the reference |
float
|
point and the given points. |
Source code in cython_extensions/geometry.pyi
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[float]
|
First element is the coefficients of Ax + By + C = 0. |
tuple[float]
|
Second element is the point used to form the line. |
Source code in cython_extensions/geometry.pyi
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:
Type | Description |
---|---|
float
|
The angle between the two points. |
Source code in cython_extensions/geometry.pyi
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:
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]
|
The new position as a tuple of x and y coordinates. |
Source code in cython_extensions/geometry.pyi
cy_translate_point_along_line(point, a_value, distance)
¶
Translates a point along a line defined by a slope value.
This function moves a given point along a line in a direction
determined by the slope a_value
, by a specified distance
.
The new point after translation is returned.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
point
|
Union[Point2, tuple[float, float]]
|
The point to be translated, given as either a |
required |
a_value
|
float
|
The slope of the line along which the point will be moved. |
required |
distance
|
float
|
The distance to move the point along the line. |
required |
Returns:
Type | Description |
---|---|
float
|
A tuple representing the new position of the point |
float
|
after translation. |
Source code in cython_extensions/geometry.pyi
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¶
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 of tuple of 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(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
|
set[Point2]
|
The points around which the bounding box should be drawn. |
required |
Returns:
Type | Description |
---|---|
tuple[float, float]
|
A tuple containing two tuples: |
tuple[float, float]
|
|
tuple[tuple[float, float], tuple[float, float]]
|
(xmin, xmax). |
tuple[tuple[float, float], tuple[float, float]]
|
|
tuple[tuple[float, float], tuple[float, float]]
|
(ymin, ymax). |
Source code in cython_extensions/map_analysis.pyi
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:
Type | Description |
---|---|
bool
|
Are all points_to_check below value? |
Source code in cython_extensions/numpy_helper.pyi
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:
Type | Description |
---|---|
bool
|
Are all points equal value? |
Source code in cython_extensions/numpy_helper.pyi
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 |
required |
value
|
int
|
The value we are looking for. |
required |
points
|
list[tuple[int, int]]
|
Points we want to check |
required |
Returns:
Type | Description |
---|---|
int
|
The last index in |
Source code in cython_extensions/numpy_helper.pyi
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
|
float
|
(default = 1.0) We want to check if the point is less than or equal to this. |
1.0
|
Returns:
Type | Description |
---|---|
bool
|
The last index in |
Source code in cython_extensions/numpy_helper.pyi
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 |
Source code in cython_extensions/numpy_helper.pyi
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
|
bool
|
Ensure this is False if checking Zerg structures. |
True
|
include_addon
|
bool
|
Check if there is room for addon too. |
False
|
Returns:
Type | Description |
---|---|
bool
|
Can we place structure at building_origin? |
Source code in cython_extensions/placement_solver.pyi
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
|
bool
|
Ensure this is False if checking Zerg structures. |
True
|
include_addon
|
bool
|
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(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]]
|
Units we want to check |
required |
Returns:
Type | Description |
---|---|
tuple[float, float]
|
Centroid of all units positions |
Source code in cython_extensions/units_utils.pyi
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:
Type | Description |
---|---|
Unit
|
Unit closest to |
Source code in cython_extensions/units_utils.pyi
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]]
|
Collection of units we want to check. |
required |
distance
|
float
|
The distance to check from the center mass. |
required |
Returns:
Type | Description |
---|---|
tuple[tuple[float, float], int]
|
The center mass, and how many units are within |
Source code in cython_extensions/units_utils.pyi
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
|
The unit to measure distance from. |
required |
units
|
Union[Units, list[Unit]]
|
Collection of units we want to check. |
required |
bonus_distance
|
float
|
Additional distance to consider. |
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(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. |