def select_idle_workers(self, game_state, number=None):
        # TODO: Select according to race
        worker_id = "SCV"

        idle_workers = game_state.player_units.filter(name=worker_id, orders=[])

        # Returning workers
        harvest_return_abilities = [
            ability.value
            for ability in AbilityId
            if ability.name.startswith("HARVEST_RETURN")
        ]
        for ability_id in harvest_return_abilities:
            idle_workers += game_state.player_units.filter(
                name=worker_id, orders__ability_id=ability_id
            )

        # Gathering workers
        harvest_return_abilities = [
            ability.value
            for ability in AbilityId
            if ability.name.startswith("HARVEST_GATHER")
        ]
        for ability_id in harvest_return_abilities:
            idle_workers += game_state.player_units.filter(
                name=worker_id, orders__ability_id=ability_id
            )

        # Return manager with idle workers
        if number is not None:
            return UnitManager(idle_workers[:number])
        else:
            return UnitManager(idle_workers)
 def determine_action_state(self, game_state, units_queue, upgrades_queue):
     available_builders = UnitManager(
         get_available_building_unit(self.unit_id, game_state))
     builder_orders = len(
         list(
             itertools.chain(
                 *available_builders.values('orders', flat_list=True))))
     no_space_in_queue = builder_orders >= 5 * len(available_builders)
     if available_builders and no_space_in_queue:
         return Action.MISSING_SPACE_IN_QUEUE, []
     else:
         return super(Train,
                      self).determine_action_state(game_state, units_queue,
                                                   upgrades_queue)
Exemple #3
0
def get_closing_enemies(game_state):
    from game_data.units import UnitManager

    town_halls = game_state.player_units.filter(unit_type__in=[
        UnitTypeIds.COMMANDCENTER.value,
        UnitTypeIds.ORBITALCOMMAND.value,
        UnitTypeIds.PLANETARYFORTRESS.value,
    ])
    min_distance = 30
    dangerous_units = UnitManager([])
    for th in town_halls:
        e_units = game_state.enemy_units \
            .add_calculated_values(distance_to={"unit": th}) \
            .filter(last_distance_to__lte=min_distance)
        dangerous_units += e_units
    return dangerous_units.values('tag', flat_list=True)
 def prepare_unit_composition(self, composition, distance_args, game_state):
     base_manager = UnitManager([])
     for unit_type, amount in composition.items():
         units = game_state.player_units.filter(unit_type=unit_type)
         if distance_args:
             units = units.add_calculated_values(distance_to=distance_args)
         base_manager += units[:amount]
     return base_manager
    def get_action_units(self, game_state, target):
        distance_args = None
        if target.get('target_unit'):
            distance_args = {"unit": target.get('target_unit')}
        elif target.get('target_point'):
            distance_args = {"pos": target.get('target_point')}

        # Get units performing the action
        base_manager = UnitManager([])

        composition = self.unit_group.get('composition')
        query_params = self.unit_group.get('query')

        if query_params:
            base_manager = game_state.player_units.filter(**query_params)
            if distance_args:
                base_manager = base_manager.add_calculated_values(
                    distance_to=distance_args)

        elif composition:
            base_manager = self.prepare_unit_composition(
                composition, distance_args, game_state)

        return base_manager
Exemple #6
0
    async def process_order(self, ws, game_state):
        if self.unit_index:
            index = self.unit_index
            units = UnitManager(
                game_state.player_units.filter(
                    **self.unit_filters)[index:index + 1])
        else:
            units = game_state.player_units.filter(**self.unit_filters)

        target_unit = None
        target_point = None
        if self.target:
            if self.target.get("unit"):
                # Select unit manager given the target's alliance
                if self.target['unit'].get("alliance"):
                    if self.target['unit']["alliance"] == Alliance.Value(
                            "Enemy"):
                        unit_manager = game_state.enemy_units
                    else:
                        unit_manager = game_state.player_units
                else:
                    unit_manager = game_state.player_units

                unit = unit_manager.filter(
                    **self.target['unit']['filter_params'])[self.target['unit']
                                                            ['index']]
                if self.target.get("diff"):
                    diff = self.target["diff"]
                    target_point = (unit.get_attribute("pos").x + diff[0],
                                    unit.get_attribute("pos").y + diff[1])
                elif self.target['unit'].get("pos"):
                    target_point = (unit.get_attribute("pos").x,
                                    unit.get_attribute("pos").y)
                else:
                    target_unit = unit
            elif self.target.get("point"):
                target_point = self.target['point']
        if self.ability_id in BUILD_ABILITIES:
            target_point = await find_placement(ws, self.ability_id,
                                                target_point)
        result = await units.give_order(ws,
                                        ability_id=self.ability_id,
                                        target_point=target_point,
                                        target_unit=target_unit)
        return result
    def distribute_workers_throughout_resources(
        self,
        workers: UnitManager,
        resources_missing_workers: List[Tuple[Unit, int]],
    ) -> Dict[Unit, UnitManager]:
        worker_distribution = {}
        taken_workers = []
        for resource, missing_workers in resources_missing_workers:
            # Filter workers to take
            workers = workers.filter(
                mode=UnitManager.EXCLUDE_AND_MODE,
                tag__in=taken_workers).add_calculated_values(distance_to={
                    'unit': resource
                }).sort_by('last_distance_to')

            # Take workers
            workers_to_resource = workers[:missing_workers]
            worker_distribution[resource] = workers_to_resource
            taken_workers = workers_to_resource.values('tag', flat_list=True)
        return worker_distribution
    def get_action_units(self, game_state, target):
        target_unit = target.get('target_unit')
        missing_workers = self.ideal_workers - self.assigned_workers

        # If target unit is None or no workers required, return empty list of workers
        if target_unit is None or missing_workers <= 0:
            return []

        workers = UnitManager([])

        composition = self.unit_group.get('composition')
        query_params = self.unit_group.get('query')

        if query_params:
            type_workers = game_state.player_units.filter(
                **query_params).add_calculated_values(
                    distance_to={
                        "unit": target_unit
                    },
                    unit_availability={},
                ).sort_by('last_unit_availability', 'last_distance_to')

            assignable_workers = missing_workers
            workers += type_workers[:assignable_workers]
            missing_workers -= assignable_workers

        elif composition:
            for worker_type, worker_amount in composition.items():
                type_workers = game_state.player_units.filter(
                    unit_type=worker_type).add_calculated_values(
                        distance_to={
                            "unit": target_unit
                        },
                        unit_availability={},
                    ).sort_by('last_unit_availability', 'last_distance_to')

                assignable_workers = min(missing_workers, worker_amount)
                workers += type_workers[:assignable_workers]
                missing_workers -= assignable_workers

        return workers
    def __init__(self, observation, game_data, game_info, actions=()):
        # Set game info
        self.game_info = game_info.game_info

        # Set player data
        self.player_info = PlayerCommon(
            observation.player_common, observation.raw_data.player, game_data
        )

        # Set game units
        self.all_units = UnitManager(
            [Unit(unit, game_data) for unit in observation.raw_data.units]
        )
        self.player_units = UnitManager(
            [
                Unit(unit, game_data)
                for unit in observation.raw_data.units
                if unit.alliance == api_data.Alliance.Value("Self")
            ]
        )
        self.allied_units = UnitManager(
            [
                Unit(unit, game_data)
                for unit in observation.raw_data.units
                if unit.alliance == api_data.Alliance.Value("Ally")
            ]
        )
        self.enemy_units = UnitManager(
            [
                Unit(unit, game_data)
                for unit in observation.raw_data.units
                if unit.alliance == api_data.Alliance.Value("Enemy")
            ]
        )
        self.neutral_units = UnitManager(
            [
                Unit(unit, game_data)
                for unit in observation.raw_data.units
                if unit.alliance == api_data.Alliance.Value("Neutral")
            ]
        )
        self.all_units = UnitManager(
            [Unit(unit, game_data) for unit in observation.raw_data.units]
        )
        self.enemy_currently_seeing_units = self.enemy_units.filter(display=1)
        self.enemy_snapshot = self.enemy_units.filter(display=2)

        # Effects and events data
        self.game_event = observation.raw_data.event
        self.game_effects = observation.raw_data.effects

        # Observation's game loop
        self.game_loop = observation.game_loop
        self.game_data = game_data
        self.actions = actions
        self.parsed_actions = []
        for action in self.actions:
            ac = action.action_raw
            if not ac.unit_command:
                continue
            else:
                identifier = ac.unit_command.ability_id
                types_grouped = {}
                if ac.unit_command.target_unit_tag:
                    tag = ac.unit_command.target_unit_tag
                    unit = self.all_units.filter(tag=tag)
                    if unit:
                        position = unit[0].get_attribute("pos")
                        if unit[0].proto_unit_data:
                            target_unit_type = unit[0].proto_unit_data.unit_id
                            target_unit_name = unit[0].proto_unit_data.name
                        targetx = position.x
                        targety = position.y
                    else:
                        continue
                else:
                    targetx, targety = (
                        ac.unit_command.target_world_space_pos.x,
                        ac.unit_command.target_world_space_pos.y,
                    )
                    target_unit_type = None
                    target_unit_name = None
                for tag in list(ac.unit_command.unit_tags):
                    if self.player_units.filter(tag=tag):
                        unitType = self.player_units.filter(tag=tag)[0].proto_unit_data
                        if unitType:
                            order = types_grouped.get(unitType.unit_id, 0)
                            order += 1
                            types_grouped[unitType.unit_id] = order

                if types_grouped.items():
                    for key in types_grouped.keys():
                        item = {
                            "unit_type_id": key,
                            "amount": types_grouped[key],
                            "action_id": identifier,
                            "x": targetx,
                            "y": targety,
                            "target_type": target_unit_type,
                        }
                        self.parsed_actions.append(item)
        self.visibility_data = observation.raw_data.map_state.visibility
        self.discovery_percentage = sum(
            filter(lambda x: x >= 1, self.visibility_data.data)
        ) / len(self.visibility_data.data)
        self.creep_data = observation.raw_data.map_state.creep
        self.creep_percentage = sum(
            filter(lambda x: x >= 1, self.creep_data.data)
        ) / len(self.creep_data.data)
class DecodedObservation:
    def __init__(self, observation, game_data, game_info, actions=()):
        # Set game info
        self.game_info = game_info.game_info

        # Set player data
        self.player_info = PlayerCommon(
            observation.player_common, observation.raw_data.player, game_data
        )

        # Set game units
        self.all_units = UnitManager(
            [Unit(unit, game_data) for unit in observation.raw_data.units]
        )
        self.player_units = UnitManager(
            [
                Unit(unit, game_data)
                for unit in observation.raw_data.units
                if unit.alliance == api_data.Alliance.Value("Self")
            ]
        )
        self.allied_units = UnitManager(
            [
                Unit(unit, game_data)
                for unit in observation.raw_data.units
                if unit.alliance == api_data.Alliance.Value("Ally")
            ]
        )
        self.enemy_units = UnitManager(
            [
                Unit(unit, game_data)
                for unit in observation.raw_data.units
                if unit.alliance == api_data.Alliance.Value("Enemy")
            ]
        )
        self.neutral_units = UnitManager(
            [
                Unit(unit, game_data)
                for unit in observation.raw_data.units
                if unit.alliance == api_data.Alliance.Value("Neutral")
            ]
        )
        self.all_units = UnitManager(
            [Unit(unit, game_data) for unit in observation.raw_data.units]
        )
        self.enemy_currently_seeing_units = self.enemy_units.filter(display=1)
        self.enemy_snapshot = self.enemy_units.filter(display=2)

        # Effects and events data
        self.game_event = observation.raw_data.event
        self.game_effects = observation.raw_data.effects

        # Observation's game loop
        self.game_loop = observation.game_loop
        self.game_data = game_data
        self.actions = actions
        self.parsed_actions = []
        for action in self.actions:
            ac = action.action_raw
            if not ac.unit_command:
                continue
            else:
                identifier = ac.unit_command.ability_id
                types_grouped = {}
                if ac.unit_command.target_unit_tag:
                    tag = ac.unit_command.target_unit_tag
                    unit = self.all_units.filter(tag=tag)
                    if unit:
                        position = unit[0].get_attribute("pos")
                        if unit[0].proto_unit_data:
                            target_unit_type = unit[0].proto_unit_data.unit_id
                            target_unit_name = unit[0].proto_unit_data.name
                        targetx = position.x
                        targety = position.y
                    else:
                        continue
                else:
                    targetx, targety = (
                        ac.unit_command.target_world_space_pos.x,
                        ac.unit_command.target_world_space_pos.y,
                    )
                    target_unit_type = None
                    target_unit_name = None
                for tag in list(ac.unit_command.unit_tags):
                    if self.player_units.filter(tag=tag):
                        unitType = self.player_units.filter(tag=tag)[0].proto_unit_data
                        if unitType:
                            order = types_grouped.get(unitType.unit_id, 0)
                            order += 1
                            types_grouped[unitType.unit_id] = order

                if types_grouped.items():
                    for key in types_grouped.keys():
                        item = {
                            "unit_type_id": key,
                            "amount": types_grouped[key],
                            "action_id": identifier,
                            "x": targetx,
                            "y": targety,
                            "target_type": target_unit_type,
                        }
                        self.parsed_actions.append(item)
        self.visibility_data = observation.raw_data.map_state.visibility
        self.discovery_percentage = sum(
            filter(lambda x: x >= 1, self.visibility_data.data)
        ) / len(self.visibility_data.data)
        self.creep_data = observation.raw_data.map_state.creep
        self.creep_percentage = sum(
            filter(lambda x: x >= 1, self.creep_data.data)
        ) / len(self.creep_data.data)

    def get_visibility_map(self):
        image_data = map(lambda x: 100 * x, self.visibility_data.data)
        image = Image.frombytes(
            "L",
            (self.visibility_data.size.x, self.visibility_data.size.y),
            bytes(image_data),
            "raw",
        )
        return image

    def get_creep_map(self):
        image_data = map(lambda x: 100 * x, self.creep_data.data)
        image = Image.frombytes(
            "L",
            (self.creep_data.size.x, self.creep_data.size.y),
            bytes(image_data),
            "raw",
        )
        return image

    def to_case(self, replay_info):
        json_dict = {
            "minerals": self.player_info.minerals,
            "vespene": self.player_info.vespene,
            "game_loop": self.game_loop,
            "food_cap": self.player_info.food_cap,
            "food_used": self.player_info.food_used,
            "food_army": self.player_info.food_army,
            "food_workers": self.player_info.food_workers,
            "idle_worker_count": self.player_info.idle_worker_count,
            "visibility_percentage": round(self.discovery_percentage, 2),
            "creep_percentage": round(self.creep_percentage, 2),
            "army_count": self.player_info.army_count,
            "warp_gate_count": self.player_info.warp_gate_count,
            "units": self.count_units(self.player_units),
            "enemy_units": self.count_units(self.enemy_units),
            "upgrades": list(map(lambda x: x.upgrade_id, self.player_info.upgrades)),
            "visible_enemy_units": self.count_units(self.enemy_currently_seeing_units),
            "known_invisible_enemy_units": self.count_units(self.enemy_snapshot),
            "map": replay_info["map"],
            "actions": self.parsed_actions,
        }
        return json_dict

    def count_units(self, units):
        type_amount = {}
        for unit in units:
            val = type_amount.get(unit.proto_unit.unit_type, 0)
            val += 1
            type_amount[unit.proto_unit.unit_type] = val
        result = []
        for key in type_amount.keys():
            item = {"unit_type_ id": key, "amount": type_amount[key]}
            result.append(item)
        return result

    def terrain_height(self, position):
        terrain_height_data = self.game_info.start_raw.terrain_height
        bytes_per_pixel = terrain_height_data.bits_per_pixel // 8
        width = terrain_height_data.size.x
        data = terrain_height_data.data

        x, y = position
        index = -width * round(y) + round(x)
        start = index * bytes_per_pixel
        data = data[start: start + bytes_per_pixel]
        return int.from_bytes(data, byteorder="little", signed=False)
Exemple #11
0
 def geysers(self):
     from game_data.units import UnitManager
     return UnitManager(self._geysers)
Exemple #12
0
 def mineral_fields(self):
     from game_data.units import UnitManager
     return UnitManager(self._mineral_fields)
Exemple #13
0
 def get_available_hubs(self, game_state):
     harvesting_hubs = game_state.player_units.filter(build_progress=1, unit_type__in=self.HARVESTING_HUBS)
     return UnitManager(list(filter(lambda hub: hub.assigned_harvesters < hub.ideal_harvesters, harvesting_hubs)))
Exemple #14
0
 def match_query_output(self, game_state):
     town_halls = game_state.player_units.filter(build_progress=1, unit_type__in=self.HARVESTING_HUBS)
     return UnitManager(list(filter(lambda th: th.assigned_harvesters > th.ideal_harvesters, town_halls)))