From a8ad54aeb17a5e0dab919b18cfd72d888e7c3624 Mon Sep 17 00:00:00 2001 From: Max Sandholm Date: Tue, 22 Dec 2020 22:15:54 +0200 Subject: [PATCH] fixing ramps coming from burnysc2 --- MapAnalyzer/MapData.py | 10 +++++++++- MapAnalyzer/utils.py | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/MapAnalyzer/MapData.py b/MapAnalyzer/MapData.py index 10601ad3..93000538 100644 --- a/MapAnalyzer/MapData.py +++ b/MapAnalyzer/MapData.py @@ -13,7 +13,7 @@ from MapAnalyzer.Debugger import MapAnalyzerDebugger from MapAnalyzer.Pather import MapAnalyzerPather from MapAnalyzer.Region import Region -from MapAnalyzer.utils import get_sets_with_mutual_elements +from MapAnalyzer.utils import get_sets_with_mutual_elements, fix_map_ramps from .constants import BINARY_STRUCTURE, CORNER_MIN_DISTANCE, MAX_REGION_AREA, MIN_REGION_AREA @@ -41,6 +41,11 @@ def __init__(self, bot: BotAI, loglevel: str = "ERROR", arcade: bool = False, corner_distance: int = CORNER_MIN_DISTANCE) -> None: # store relevant data from api self.bot = bot + # temporary fix to set ramps correctly if they are broken in burnysc2 due to having + # destructables on them. ramp sides don't consider the destructables now, + # should update them during the game + self.bot.game_info.map_ramps, self.bot.game_info.vision_blockers = fix_map_ramps(self.bot) + self.corner_distance = corner_distance # the lower this value is, the sharper the corners will be self.arcade = arcade self.version = __version__ @@ -691,6 +696,9 @@ def _calc_grid(self) -> None: self.vision_blockers_labels = np.unique(vb_labeled_array) def _set_map_ramps(self): + # some ramps coming from burnysc2 have broken data and the bottom_center and top_center + # may even be the same. by removing them they should be tagged as chokes in the c extension + # if they really are ones viable_ramps = list(filter(lambda x: x.bottom_center.distance_to(x.top_center) >= 1, self.bot.game_info.map_ramps)) self.map_ramps = [MDRamp(map_data=self, diff --git a/MapAnalyzer/utils.py b/MapAnalyzer/utils.py index abcdc970..b165fbb1 100644 --- a/MapAnalyzer/utils.py +++ b/MapAnalyzer/utils.py @@ -1,13 +1,17 @@ import lzma import os import pickle +import numpy as np +from skimage import draw as skdraw + from typing import List, Optional, TYPE_CHECKING, Union from s2clientprotocol.sc2api_pb2 import Response, ResponseObservation from sc2.bot_ai import BotAI from sc2.game_data import GameData -from sc2.game_info import GameInfo +from sc2.game_info import GameInfo, Ramp from sc2.game_state import GameState +from sc2.position import Point2 from MapAnalyzer.constructs import MDRamp, VisionBlockerArea from .cext import CMapChoke @@ -16,6 +20,34 @@ if TYPE_CHECKING: from MapAnalyzer.MapData import MapData +# following https://github.com/BurnySc2/python-sc2/blob/ffb9bd43dcbeb923d848558945a8c59c9662f435/sc2/game_info.py#L246 +# to fix burnysc2 ramp objects by removing destructables +def fix_map_ramps(bot: BotAI): + pathing_grid = bot.game_info.pathing_grid.data_numpy.T + for dest in bot.destructables: + ri, ci = skdraw.disk(center=dest.position, radius=dest.radius, shape=pathing_grid.shape) + pathing_grid[ri, ci] = 1 + + pathing = np.ndenumerate(pathing_grid.T) + + def equal_height_around(tile): + sliced = bot.game_info.terrain_height.data_numpy[tile[1] - 1: tile[1] + 2, tile[0] - 1: tile[0] + 2] + return len(np.unique(sliced)) == 1 + + map_area = bot.game_info.playable_area + points = [ + Point2((a, b)) + for (b, a), value in pathing + if value == 1 + and map_area.x <= a < map_area.x + map_area.width + and map_area.y <= b < map_area.y + map_area.height + and bot.game_info.placement_grid[(a, b)] == 0 + ] + ramp_points = [point for point in points if not equal_height_around(point)] + vision_blockers = set(point for point in points if equal_height_around(point)) + ramps = [Ramp(group, bot.game_info) for group in bot.game_info._find_groups(ramp_points)] + return ramps, vision_blockers + def get_sets_with_mutual_elements(list_mdchokes: List[CMapChoke], area: Optional[Union[MDRamp, VisionBlockerArea]] = None,