|
1 | 1 | from collections import deque |
2 | 2 | from typing import Any, Deque, Dict, FrozenSet, Generator, List, Optional, Sequence, Set, Tuple, Union |
3 | 3 |
|
| 4 | +import numpy as np |
| 5 | + |
4 | 6 | from .cache import property_immutable_cache, property_mutable_cache |
5 | 7 | from .pixel_map import PixelMap |
6 | 8 | from .player import Player |
@@ -168,22 +170,38 @@ def __init__(self, proto): |
168 | 170 | self.playable_area = Rect.from_proto(self._proto.start_raw.playable_area) |
169 | 171 | self.map_center = self.playable_area.center |
170 | 172 | self.map_ramps: List[Ramp] = None # Filled later by BotAI._prepare_first_step |
| 173 | + self.vision_blockers: Set[Point2] = None # Filled later by BotAI._prepare_first_step |
171 | 174 | self.player_races: Dict[int, "Race"] = { |
172 | 175 | p.player_id: p.race_actual or p.race_requested for p in self._proto.player_info |
173 | 176 | } |
174 | 177 | self.start_locations: List[Point2] = [Point2.from_proto(sl) for sl in self._proto.start_raw.start_locations] |
175 | 178 | self.player_start_location: Point2 = None # Filled later by BotAI._prepare_first_step |
176 | 179 |
|
177 | | - def _find_ramps(self) -> List[Ramp]: |
178 | | - """Calculate (self.pathing_grid - self.placement_grid) (for sets) and then find ramps by comparing heights.""" |
| 180 | + def _find_ramps_and_vision_blockers(self) -> Tuple[List[Ramp], Set[Point2]]: |
| 181 | + """ Calculate points that are pathable but not placeable. |
| 182 | + Then devide them into ramp points if not all points around the points are equal height |
| 183 | + and into vision blockers if they are. """ |
| 184 | + |
| 185 | + def equal_height_around(tile): |
| 186 | + # mask to slice array 1 around tile |
| 187 | + sliced = self.terrain_height.data_numpy[tile[1] - 1 : tile[1] + 2, tile[0] - 1 : tile[0] + 2] |
| 188 | + return len(np.unique(sliced)) == 1 |
| 189 | + |
179 | 190 | map_area = self.playable_area |
180 | | - rampPoints = ( |
181 | | - Point2((x, y)) |
182 | | - for x in range(map_area.x, map_area.x + map_area.width) |
183 | | - for y in range(map_area.y, map_area.y + map_area.height) |
184 | | - if self.placement_grid[(x, y)] == 0 and self.pathing_grid[(x, y)] == 1 |
185 | | - ) |
186 | | - return [Ramp(group, self) for group in self._find_groups(rampPoints)] |
| 191 | + # all points in the playable area that are pathable but not placable |
| 192 | + points = [ |
| 193 | + Point2((b, a)) |
| 194 | + for (a, b), value in np.ndenumerate(self.pathing_grid.data_numpy) |
| 195 | + if value == 1 |
| 196 | + and map_area.x <= a < map_area.x + map_area.width |
| 197 | + and map_area.y <= b < map_area.y + map_area.height |
| 198 | + and self.placement_grid[(b, a)] == 0 |
| 199 | + ] |
| 200 | + # devide points into ramp points and vision blockers |
| 201 | + rampPoints = [point for point in points if not equal_height_around(point)] |
| 202 | + visionBlockers = set(point for point in points if equal_height_around(point)) |
| 203 | + ramps = [Ramp(group, self) for group in self._find_groups(rampPoints)] |
| 204 | + return ramps, visionBlockers |
187 | 205 |
|
188 | 206 | def _find_groups(self, points: Set[Point2], minimum_points_per_group: int = 8): |
189 | 207 | """ |
|
0 commit comments