async def query_pathing( self, start: Union[Unit, Point2, Point3], end: Union[Point2, Point3]) -> Optional[Union[int, float]]: """ Caution: returns "None" when path not found Try to combine queries with the function below because the pathing query is generally slow. :param start: :param end: """ assert isinstance(start, (Point2, Unit)) assert isinstance(end, Point2) if isinstance(start, Point2): result = await self._execute(query=query_pb.RequestQuery(pathing=[ query_pb.RequestQueryPathing( start_pos=common_pb.Point2D(x=start.x, y=start.y), end_pos=common_pb.Point2D(x=end.x, y=end.y), ) ])) else: result = await self._execute(query=query_pb.RequestQuery(pathing=[ query_pb.RequestQueryPathing(unit_tag=start.tag, end_pos=common_pb.Point2D( x=end.x, y=end.y)) ])) distance = float(result.query.pathing[0].distance) if distance <= 0.0: return None return distance
async def query_pathings( self, zipped_list: List[List[Union[Unit, Point2, Point3]]] ) -> List[Union[float, int]]: """ Usage: await self.query_pathings([[unit1, target2], [unit2, target2]]) -> returns [distance1, distance2] Caution: returns 0 when path not found Might merge this function with the function above """ assert isinstance(zipped_list, list) assert len(zipped_list) > 0 assert isinstance(zipped_list[0], list) assert len(zipped_list[0]) == 2 assert isinstance(zipped_list[0][0], (Point2, Unit)) assert isinstance(zipped_list[0][1], Point2) if isinstance(zipped_list[0][0], Point2): results = await self._execute(query=query_pb.RequestQuery(pathing=[ query_pb.RequestQueryPathing( start_pos=common_pb.Point2D(x=p1.x, y=p1.y), end_pos=common_pb.Point2D(x=p2.x, y=p2.y)) for p1, p2 in zipped_list ])) else: results = await self._execute(query=query_pb.RequestQuery(pathing=[ query_pb.RequestQueryPathing( unit_tag=p1.tag, end_pos=common_pb.Point2D(x=p2.x, y=p2.y)) for p1, p2 in zipped_list ])) results = [float(d.distance) for d in results.query.pathing] return results
async def query_pathings( self, zipped_list: List[List[Union[Unit, Point2, Point3]]] ) -> List[Union[float, int]]: """ Usage: await self.query_pathings([[unit1, target2], [unit2, target2]]) -> returns [distance1, distance2] Caution: returns 0 when path not found :param zipped_list: """ assert zipped_list, "No zipped_list" assert isinstance(zipped_list, list), f"{type(zipped_list)}" assert isinstance(zipped_list[0], list), f"{type(zipped_list[0])}" assert len(zipped_list[0]) == 2, f"{len(zipped_list[0])}" assert isinstance(zipped_list[0][0], (Point2, Unit)), f"{type(zipped_list[0][0])}" assert isinstance(zipped_list[0][1], Point2), f"{type(zipped_list[0][1])}" if isinstance(zipped_list[0][0], Point2): results = await self._execute(query=query_pb.RequestQuery( pathing=(query_pb.RequestQueryPathing( start_pos=common_pb.Point2D(x=p1.x, y=p1.y), end_pos=common_pb.Point2D(x=p2.x, y=p2.y)) for p1, p2 in zipped_list))) else: results = await self._execute(query=query_pb.RequestQuery( pathing=(query_pb.RequestQueryPathing( unit_tag=p1.tag, end_pos=common_pb.Point2D(x=p2.x, y=p2.y)) for p1, p2 in zipped_list))) return [float(d.distance) for d in results.query.pathing]
async def query_pathing( self, start: Union[Unit, Point2, Point3], end: Union[Point2, Point3] ) -> Optional[Union[int, float]]: """ Caution: returns 0 when path not found """ assert isinstance(start, (Point2, Unit)) assert isinstance(end, Point2) if isinstance(start, Point2): result = await self._execute( query=query_pb.RequestQuery( pathing=[ query_pb.RequestQueryPathing( start_pos=common_pb.Point2D(x=start.x, y=start.y), end_pos=common_pb.Point2D(x=end.x, y=end.y), ) ] ) ) else: result = await self._execute( query=query_pb.RequestQuery( pathing=[ query_pb.RequestQueryPathing(unit_tag=start.tag, end_pos=common_pb.Point2D(x=end.x, y=end.y)) ] ) ) distance = float(result.query.pathing[0].distance) if distance <= 0.0: return None return distance
async def query_available_abilities( self, units: Union[List[Unit], "Units"], ignore_resource_requirements: bool = False ) -> List[List[AbilityId]]: """ Query abilities of multiple units """ if not isinstance(units, list): """ Deprecated, accepting a single unit may be removed in the future, query a list of units instead """ assert isinstance(units, Unit) units = [units] input_was_a_list = False else: input_was_a_list = True assert len(units) > 0 result = await self._execute(query=query_pb.RequestQuery( abilities=[ query_pb.RequestQueryAvailableAbilities(unit_tag=unit.tag) for unit in units ], ignore_resource_requirements=ignore_resource_requirements)) """ Fix for bots that only query a single unit """ if not input_was_a_list: return [[AbilityId(a.ability_id) for a in b.abilities] for b in result.query.abilities][0] return [[AbilityId(a.ability_id) for a in b.abilities] for b in result.query.abilities]
async def query_available_abilities(self, unit): assert isinstance(unit, Unit) result = await self._execute(query=query_pb.RequestQuery( abilities=[query_pb.RequestQueryAvailableAbilities( unit_tag=unit.tag )] )) return [AbilityId(a.ability_id) for a in result.query.abilities[0].abilities]
async def query_building_placement(self, ability: AbilityId, positions: List[Union[Unit, Point2, Point3]], ignore_resources: bool=True) -> List[ActionResult]: assert isinstance(ability, AbilityData) result = await self._execute(query=query_pb.RequestQuery( placements=[query_pb.RequestQueryBuildingPlacement( ability_id=ability.id.value, target_pos=common_pb.Point2D(x=position.x, y=position.y) ) for position in positions], ignore_resource_requirements=ignore_resources )) return [ActionResult(p.result) for p in result.query.placements]
async def query_pathing(self, start, end): assert isinstance(start, (Point2, Unit)) assert isinstance(end, Point2) if isinstance(start, Point2): result = await self._execute(query=query_pb.RequestQuery(pathing=[ query_pb.RequestQueryPathing( start_pos=common_pb.Point2D(x=start.x, y=start.y), end_pos=common_pb.Point2D(x=end.x, y=end.y)) ])) else: result = await self._execute(query=query_pb.RequestQuery(pathing=[ query_pb.RequestQueryPathing(unit_tag=start.tag, end_pos=common_pb.Point2D( x=end.x, y=end.y)) ])) distance = float(result.query.pathing[0].distance) if distance <= 0.0: return None return distance
async def query_building_placement(ws, ability_id, point): if not isinstance(point, common.Point2D): point = common.Point2D(x=point[0], y=point[1]) api_request = api.Request(query=api_query.RequestQuery(placements=[ api_query.RequestQueryBuildingPlacement(ability_id=ability_id, target_pos=point) ])) await ws.send(api_request.SerializeToString()) result = await ws.recv() response = api.Response.FromString(result) return response.query.placements[0].result == 1
async def query_available_abilities(self, units, ignore_resource_requirements=False): if not isinstance(units, list): assert isinstance(units, Unit) units = [units] assert len(units) > 0 result = await self._execute(query=query_pb.RequestQuery( abilities=[ query_pb.RequestQueryAvailableAbilities(unit_tag=unit.tag) for unit in units ], ignore_resource_requirements=ignore_resource_requirements)) return [[AbilityId(a.ability_id) for a in b.abilities] for b in result.query.abilities]
async def query_available_abilities_with_tag( self, units: Union[List[Unit], Units], ignore_resource_requirements: bool = False ) -> Dict[Set[AbilityId]]: """ Query abilities of multiple units """ result = await self._execute(query=query_pb.RequestQuery( abilities=(query_pb.RequestQueryAvailableAbilities( unit_tag=unit.tag) for unit in units), ignore_resource_requirements=ignore_resource_requirements, )) return { b.unit_tag: {AbilityId(a.ability_id) for a in b.abilities} for b in result.query.abilities }
async def query_building_placement( self, ability: AbilityData, positions: List[Union[Point2, Point3]], ignore_resources: bool = True) -> List[ActionResult]: """This function might be deleted in favor of the function above (_query_building_placement_fast). :param ability: :param positions: :param ignore_resources:""" assert isinstance(ability, AbilityData) result = await self._execute(query=query_pb.RequestQuery( placements=(query_pb.RequestQueryBuildingPlacement( ability_id=ability.id.value, target_pos=position.as_Point2D) for position in positions), ignore_resource_requirements=ignore_resources, )) # Unnecessary converting to ActionResult? return [ActionResult(p.result) for p in result.query.placements]
async def _query_building_placement_fast( self, ability: AbilityData, positions: List[Union[Point2, Point3]], ignore_resources: bool = True) -> List[ActionResult]: """ :param ability: :param positions: :param ignore_resources: """ result = await self._execute(query=query_pb.RequestQuery( placements=(query_pb.RequestQueryBuildingPlacement( ability_id=ability.id.value, target_pos=position.as_Point2D) for position in positions), ignore_resource_requirements=ignore_resources, )) # Success enum value is 1, see https://github.com/Blizzard/s2client-proto/blob/9906df71d6909511907d8419b33acc1a3bd51ec0/s2clientprotocol/error.proto#L7 return [p.result == 1 for p in result.query.placements]
async def query_alvailable_actions(self, ws, game_state): units = game_state.player_units available_actions = [] for unit in units: lookup = api.Request(query=query.RequestQuery()) request_available = lookup.query.abilities.add() request_available.unit_tag = unit.tag await ws.send(lookup.SerializeToString()) data = await ws.recv() data = api.Response.FromString(data) abilities = data.query.abilities for ability in abilities: for ab in ability.abilities: if hasattr(ab, "requires_point"): action = Action( unit=unit, ability_id=ab.ability_id, require_target=True ) else: action = Action(unit=unit, ability_id=ab.ability_id) available_actions.append(action) return available_actions