def __init__(self, response_observation, previous_observation=None): """ :param response_observation: """ # Only filled in realtime=True in case the bot skips frames self.previous_observation = previous_observation self.response_observation = response_observation # https://github.com/Blizzard/s2client-proto/blob/51662231c0965eba47d5183ed0a6336d5ae6b640/s2clientprotocol/sc2api.proto#L575 self.observation = response_observation.observation self.observation_raw = self.observation.raw_data self.player_result = response_observation.player_result self.common: Common = Common(self.observation.player_common) # Area covered by Pylons and Warpprisms self.psionic_matrix: PsionicMatrix = PsionicMatrix.from_proto( self.observation_raw.player.power_sources) # 22.4 per second on faster game speed self.game_loop: int = self.observation.game_loop # https://github.com/Blizzard/s2client-proto/blob/33f0ecf615aa06ca845ffe4739ef3133f37265a9/s2clientprotocol/score.proto#L31 self.score: ScoreDetails = ScoreDetails(self.observation.score) self.abilities = self.observation.abilities # abilities of selected units self.upgrades: Set[UpgradeId] = { UpgradeId(upgrade) for upgrade in self.observation_raw.player.upgrade_ids } # self.visibility[point]: 0=Hidden, 1=Fogged, 2=Visible self.visibility: PixelMap = PixelMap( self.observation_raw.map_state.visibility, mirrored=False) # self.creep[point]: 0=No creep, 1=creep self.creep: PixelMap = PixelMap(self.observation_raw.map_state.creep, in_bits=True, mirrored=False) # Effects like ravager bile shot, lurker attack, everything in effect_id.py self.effects: Set[EffectData] = { EffectData(effect) for effect in self.observation_raw.effects } """ Usage:
def get_upgrade_abilities(data): ability_data = data["Ability"] unit_data = data["Unit"] upgrade_data = data["Upgrade"] ability_to_upgrade_dict: Dict[AbilityId, UpgradeId] = OrderedDict2() """ We want to be able to research an upgrade by doing await self.can_research(UpgradeId, return_idle_structures=True) -> returns list of idle structures that can research it So we need to assign each upgrade id one building type, and its research ability and requirements (e.g. armory for infantry level 2) """ # Collect all upgrades and their corresponding abilities entry: dict for entry in ability_data: if isinstance(entry.get("target", {}), str): continue ability_id: AbilityId = AbilityId(entry["id"]) researched_ability_id: UnitTypeId upgrade_id_value: int = entry.get("target", {}).get("Research", {}).get("upgrade", 0) if upgrade_id_value: upgrade_id: UpgradeId = UpgradeId(upgrade_id_value) ability_to_upgrade_dict[ability_id] = upgrade_id """ unit_research_abilities = { UnitTypeId.ENGINEERINGBAY: { UpgradeId.TERRANINFANTRYWEAPONSLEVEL1: { "ability": AbilityId.ENGINEERINGBAYRESEARCH_TERRANINFANTRYWEAPONSLEVEL1, "required_building": None, "requires_power": False, # If a pylon nearby is required }, UpgradeId.TERRANINFANTRYWEAPONSLEVEL2: { "ability": AbilityId.ENGINEERINGBAYRESEARCH_TERRANINFANTRYWEAPONSLEVEL2, "required_building": UnitTypeId.ARMORY, "requires_power": False, # If a pylon nearby is required }, } } """ unit_research_abilities = OrderedDict2() for entry in unit_data: unit_abilities = entry.get("abilities", []) unit_type = UnitTypeId(entry["id"]) if unit_type == UnitTypeId.TECHLAB: continue current_unit_research_abilities = OrderedDict2() for ability_info in unit_abilities: ability_id_value: int = ability_info.get("ability", 0) if ability_id_value: ability_id: AbilityId = AbilityId(ability_id_value) # Upgrade is not a known upgrade ability if ability_id not in ability_to_upgrade_dict: continue required_building = None required_upgrade = None requirements = ability_info.get("requirements", []) if requirements: req_building_id_value = next( (req["building"] for req in requirements if req.get("building", 0)), None) if req_building_id_value: req_building_id = UnitTypeId(req_building_id_value) required_building = req_building_id req_upgrade_id_value = next( (req["upgrade"] for req in requirements if req.get("upgrade", 0)), None) if req_upgrade_id_value: req_upgrade_id = UpgradeId(req_upgrade_id_value) required_upgrade = req_upgrade_id requires_power = entry.get("needs_power", False) resulting_upgrade = ability_to_upgrade_dict[ability_id] research_info = {"ability": ability_id} if required_building: research_info["required_building"] = required_building if required_upgrade: research_info["required_upgrade"] = required_upgrade if requires_power: research_info["requires_power"] = requires_power current_unit_research_abilities[ resulting_upgrade] = research_info if current_unit_research_abilities: unit_research_abilities[ unit_type] = current_unit_research_abilities return unit_research_abilities
def main(): unit_count = defaultdict(int) with open("build_order.json", "r") as f: raw_order = json.load(f) race = get_race(raw_order) unit_count[UnitTypeId.OVERLORD] = 1 if race == Race.Protoss: worker = UnitTypeId.PROBE townhall = UnitTypeId.NEXUS elif race == Race.Terran: worker = UnitTypeId.SCV townhall = UnitTypeId.COMMANDCENTER elif race == Race.Zerg: unit_count[UnitTypeId.OVERLORD] = 1 worker = UnitTypeId.DRONE townhall = UnitTypeId.HATCHERY else: print("Unknown race") return unit_count[worker] = 12 unit_count[townhall] = 1 text_timings = "WarnBuildMacro([" text = "" last_line: Optional[str] = None last_id: Optional[Union[UnitTypeId, UpgradeId]] = None replacer_dict = action_replacement_dict() for order in raw_order: line = "" if order["type"] in {"unit", "structure", "worker"}: id = UnitTypeId(order["id"]) unit_count[id] += 1 line += f"BuildId({str(id)}, to_count={unit_count[id]})" if order["type"] == "structure": text_timings += f"({str(id)}, {unit_count[id]}, {order['frame'] // 22.4})," elif order["type"] == "upgrade": id = UpgradeId(order["id"]) line += f"Tech({str(id)})" elif order["type"] == "action" and order["name"] in replacer_dict: id = None line += replacer_dict[order["name"]] else: id = None line += "# " + order["name"] line += "," if last_line is not None and (last_id is None or last_id != id): text += last_line + "\n" last_line = line last_id = id text += last_line + "\n" text_timings += "], [])," print(text_timings) print(text)
def __init__(self, response_observation): self.response_observation = response_observation self.actions = response_observation.actions # successful actions since last loop self.action_errors = response_observation.action_errors # error actions since last loop # https://github.com/Blizzard/s2client-proto/blob/51662231c0965eba47d5183ed0a6336d5ae6b640/s2clientprotocol/sc2api.proto#L575 # TODO: implement alerts https://github.com/Blizzard/s2client-proto/blob/51662231c0965eba47d5183ed0a6336d5ae6b640/s2clientprotocol/sc2api.proto#L640 self.observation = response_observation.observation self.observation_raw = self.observation.raw_data self.dead_units: Set[ int] = self.observation_raw.event.dead_units # returns set of tags of units that died self.alerts = self.observation.alerts self.player_result = response_observation.player_result self.chat = response_observation.chat self.common: Common = Common(self.observation.player_common) # Area covered by Pylons and Warpprisms self.psionic_matrix: PsionicMatrix = PsionicMatrix.from_proto( self.observation_raw.player.power_sources) self.game_loop: int = self.observation.game_loop # 22.4 per second on faster game speed # https://github.com/Blizzard/s2client-proto/blob/33f0ecf615aa06ca845ffe4739ef3133f37265a9/s2clientprotocol/score.proto#L31 self.score: ScoreDetails = ScoreDetails(self.observation.score) self.abilities = self.observation.abilities # abilities of selected units self._blipUnits = [] self.own_units: Units = Units([]) self.enemy_units: Units = Units([]) self.mineral_field: Units = Units([]) self.vespene_geyser: Units = Units([]) self.resources: Units = Units([]) self.destructables: Units = Units([]) self.watchtowers: Units = Units([]) self.units: Units = Units([]) for unit in self.observation.raw_data.units: if unit.is_blip: self._blipUnits.append(unit) else: unit_obj = Unit(unit) self.units.append(unit_obj) alliance = unit.alliance # Alliance.Neutral.value = 3 if alliance == 3: unit_type = unit.unit_type # XELNAGATOWER = 149 if unit_type == 149: self.watchtowers.append(unit_obj) # mineral field enums elif unit_type in mineral_ids: self.mineral_field.append(unit_obj) self.resources.append(unit_obj) # geyser enums elif unit_type in geyser_ids: self.vespene_geyser.append(unit_obj) self.resources.append(unit_obj) # all destructable rocks else: self.destructables.append(unit_obj) # Alliance.Self.value = 1 elif alliance == 1: self.own_units.append(unit_obj) # Alliance.Enemy.value = 4 elif alliance == 4: self.enemy_units.append(unit_obj) self.upgrades: Set[UpgradeId] = { UpgradeId(upgrade) for upgrade in self.observation_raw.player.upgrade_ids } # Set of unit tags that died this step self.dead_units: Set[int] = { dead_unit_tag for dead_unit_tag in self.observation_raw.event.dead_units } # Set of enemy units detected by own sensor tower, as blips have less unit information than normal visible units self.blips: Set[Blip] = {Blip(unit) for unit in self._blipUnits} # self.visibility[point]: 0=Hidden, 1=Fogged, 2=Visible self.visibility: PixelMap = PixelMap( self.observation_raw.map_state.visibility, mirrored=True) # HSPARK 수정 시작 # self.creep[point]: 0=No creep, 1=creep # self.creep: PixelMap = PixelMap(self.observation_raw.map_state.creep, mirrored=True) self.creep: PixelMap = PixelMap(self.observation_raw.map_state.creep, mirrored=True, in_bits=True) # HSPARK 수정 끝 # Effects like ravager bile shot, lurker attack, everything in effect_id.py self.effects: Set[EffectData] = { EffectData(effect) for effect in self.observation_raw.effects } """ Usage: