Example #1
0
def find_new_target_rampart_defense_spot(targets, creep):
    # type: (TargetMind, RoleBase) -> Optional[str]
    hot_spots, cold_spots = creep.home.defense.get_current_defender_spots()
    nearest = None
    nearest_distance = Infinity
    for location in hot_spots:
        if not targets.targets[target_rampart_defense][location.name]:
            distance = movement.chebyshev_distance_room_pos(
                location, creep.pos)
            if distance < nearest_distance:
                nearest = location
                nearest_distance = distance
    if nearest is None:
        for location in cold_spots:
            if not targets.targets[target_rampart_defense][location.name]:
                distance = movement.chebyshev_distance_room_pos(
                    location, creep.pos)
                if distance < nearest_distance:
                    nearest = location
                    nearest_distance = distance
        if nearest is None:
            for location in creep.home.defense.get_old_defender_spots():
                if not targets.targets[target_rampart_defense][location.name]:
                    distance = movement.chebyshev_distance_room_pos(
                        location, creep.pos)
                    if distance < nearest_distance:
                        nearest = location
                        nearest_distance = distance
    if nearest:
        return nearest.name
    else:
        return None
Example #2
0
        def move_to_closest_of(c, targets):
            # type: (SquadDrone, List[Union[RoomPosition, RoomObject, SquadDrone]]) -> bool
            target = None
            distance = Infinity
            for test_target in targets:
                test_distance = movement.chebyshev_distance_room_pos(
                    c.pos, robjs.pos(test_target))
                if test_distance < distance:
                    distance = test_distance
                    target = test_target

            target = robjs.pos(target)
            if c.pos.roomName == target.roomName:
                if c.pos.isNearTo(target):
                    return False
                else:
                    c.move_to(target)
                    return True
            elif movement.chebyshev_distance_room_pos(c.pos, target) < 100:
                c.move_to(target)
                return True
            else:
                # TODO: this should accommodate reroutes _faster_?
                reroute = portals.recommended_reroute(c.pos, target)
                if reroute is not None:
                    target = reroute[0]
                c.move_to(target)
                return True
Example #3
0
def mark_creeps(room):
    # type: (RoomMind) -> None
    """
    :type room: rooms.room_mind.RoomMind
    """
    all_hostiles = room.room.find(FIND_HOSTILE_CREEPS)
    hostiles = []
    for creep in cast(List[Creep], all_hostiles):
        if creep.hasActiveOffenseBodyparts():
            hostiles.append(creep)
    count = len(hostiles)
    if count > 3:
        for creep in cast(List[Creep], room.find(FIND_MY_CREEPS)):
            Memory.deathwatch.append([
                creep.name,
                creep.memory.home,
                _(hostiles).map(lambda h: _.get(h, ['owner', 'username'],
                                                'unknown')).uniq().value(),
                room.name,
            ])
    elif count > 0:
        for creep in cast(List[Creep], room.find(FIND_MY_CREEPS)):
            if _.some(
                    hostiles, lambda h: movement.chebyshev_distance_room_pos(
                        h.pos, creep.pos) < 4):
                Memory.deathwatch.append([
                    creep.name,
                    creep.memory.home,
                    _(hostiles).filter(
                        lambda h: movement.chebyshev_distance_room_pos(
                            h.pos, creep.pos) < 4).map(
                                lambda h: _.get(h, ['owner', 'username'],
                                                'unknown')).uniq().value(),
                    room.name,
                ])
Example #4
0
    def closest_deposit_point_to_mine(self, flag):
        # type: (Flag) -> Optional[Structure]
        """
        Gets the closest deposit point to the mine. Currently just returns storage or spawn, since we need to do more
        changes in order to support links well anyways.
        :param flag:
        :return:
        """
        key = "mine_{}_deposit".format(flag.name)
        target_id = self.room.get_cached_property(key)
        if target_id:
            target = cast(Structure, Game.getObjectById(target_id))
            if target:
                return target
        # Even if we don't have a link manager active right now, we will soon if there is a main link
        if self.room.links.main_link and flag.pos.roomName == self.room.name:
            main_link_id = self.room.links.main_link.id
            upgrader_link = self.room.get_upgrader_energy_struct()
            upgrader_link_id = upgrader_link and upgrader_link.id or None
            storage = self.room.room.storage
            if storage and storage.storeCapacity > 0:
                # TODO: see if this produces an error...? it should
                distance = movement.chebyshev_distance_room_pos(
                    storage.pos, flag.pos)
                if distance <= 2:
                    best_priority = -40
                    best = storage
                else:
                    best_priority = 0
                    best = storage
            else:
                best_priority = Infinity
                best = None
            if best_priority > -40:
                for link in self.room.links.links:
                    if link.energyCapacity <= 0 or link.id == main_link_id:
                        continue
                    distance = movement.chebyshev_distance_room_pos(
                        link.pos, flag.pos)
                    if distance <= 2:
                        priority = -20
                    elif link.id == upgrader_link_id:
                        continue
                    else:
                        priority = distance
                    if priority < best_priority:
                        best_priority = priority
                        best = link
            target = best
        elif self.room.room.storage and self.room.room.storage.storeCapacity > 0:
            target = self.room.room.storage
        elif self.room.spawn:
            target = self.room.spawn
        else:
            return None

        target_id = target.id
        self.room.store_cached_property(key, target_id, 50)
        return target
Example #5
0
    def move_to(self, target):
        # type: (RoomPosition) -> None
        """
        Method that judges distance to target, and then delegates to stage_0, stage_1 or stage_2 movement.
        """
        hive = self.home.hive
        home = self.find_home()
        origin = self.find_origin()

        total_distance = hive.honey.find_path_length(origin, target,
                                                     self.new_movement_opts())

        min_distance_from_home = Infinity
        min_distance_to_origin = Infinity
        min_distance_to_target = movement.chebyshev_distance_room_pos(
            self.members_movement_order()[0].pos, target)
        max_distance_to_target = -Infinity
        any_hostiles = False
        for member in self.members:
            distance_to_home = movement.chebyshev_distance_room_pos(
                member.pos, home)
            distance_to_origin = movement.chebyshev_distance_room_pos(
                member.pos, origin)
            distance_to_target = movement.chebyshev_distance_room_pos(
                member.pos, target)
            if distance_to_home < min_distance_from_home:
                min_distance_from_home = distance_to_home
            if distance_to_target > max_distance_to_target:
                max_distance_to_target = distance_to_target
            if distance_to_origin < min_distance_to_origin:
                min_distance_to_origin = distance_to_origin
            if len(member.room.find(FIND_HOSTILE_CREEPS)):
                any_hostiles = True

        if min_distance_to_origin > 100:
            mv_order = self.members_movement_order()
            self.set_origin(mv_order[len(mv_order) - 1].pos)
        if min_distance_from_home < 50 and (max_distance_to_target <
                                            total_distance / 2):
            self.log(
                "move_to: chose stage 0 (minimum distance from home: {}, maximum distance from home: {},"
                " total distance: {})".format(min_distance_from_home,
                                              max_distance_to_target,
                                              total_distance))
            self.move_to_stage_0(target)
        elif min_distance_to_target < 300 and any_hostiles:
            self.move_to_stage_2(target)
        elif min_distance_to_target > 60 or max_distance_to_target > 200:
            # self.log("move_to: chose stage 1 (minimum distance from home: {}, total distance: {}, "
            #          "minimum distance to target: {}, maximum distance to target: {})"
            #          .format(min_distance_from_home, total_distance,
            #                  min_distance_to_target, max_distance_to_target))
            self.move_to_stage_1(target, any_hostiles)
        else:
            # self.log("move_to: chose stage 2 (minimum distance from home: {}, total distance: {}, "
            #          "minimum distance to target: {}, maximum distance to target: {})"
            #          .format(min_distance_from_home, total_distance,
            #                  min_distance_to_target, max_distance_to_target))
            self.move_to_stage_2(target)
Example #6
0
 def recalc_military_path(self, origin, target, opts = None):
     # type: (RoomPosition, RoomPosition, Dict[str, Any]) -> None
     # TODO: separate the majority of the code this shares with follow_military_path into a new module
     if opts and "to_home" in opts:
         to_home = opts["to_home"]
     else:
         to_home = False
     if not origin:
         origin = movement.find_an_open_space(self.memory.home)
     if self.creep.fatigue > 0:
         return
     if self.pos.getRangeTo(target) < 10 or self.pos.roomName == target.roomName:
         self.move_to(target)
         return
     path_opts = {
         'current_room': self.pos.roomName,
     }
     if opts:
         path_opts = _.merge(path_opts, opts)
     # TODO: this is all stupid, PathFinder is stupid for multiple rooms!
     if chebyshev_distance_room_pos(origin, target) > 900 \
             and not is_path_portal(origin, target):
         path_opts['max_ops'] = chebyshev_distance_room_pos(origin, target) * 150
         path_opts['max_rooms'] = math.ceil(chebyshev_distance_room_pos(origin, target) / 5)
         path_opts['use_roads'] = False
         # TODO: handle this better (this is for not having multiple super-duper-long cached paths)
         if to_home:
             intermediate = find_an_open_space(origin.roomName)
             origin = intermediate
         else:
             intermediate = center_pos(target.roomName)
             if self.pos.roomName != intermediate.roomName:
                 target = intermediate
                 path_opts.range = 10
             else:
                 # If we're this far away, let's just get to the room using a cached path and then do
                 # basic pathfinding to get to our actual target.
                 self.move_to(target)
                 return
         if not is_path_portal(origin, target):
             origin_midpoint = find_midpoint(self.pos, self.pos, origin)
             if origin_midpoint is not None:
                 origin = origin_midpoint
             dest_midpoint = find_midpoint(self.pos, origin, target)
             if dest_midpoint is not None:
                 if self.pos.roomName == dest_midpoint.roomName:
                     origin = dest_midpoint
                 else:
                     target = dest_midpoint
                     path_opts.range = 10
     honey.clear_cached_path(origin, target, path_opts)
Example #7
0
def find_new_target_source(targets, creep):
    # type: (TargetMind, RoleBase) -> Optional[str]
    has_work = not not creep.creep.hasActiveBodyparts(WORK)
    any_miners = not not creep.home.role_count(role_miner)
    highest_priority = -Infinity
    best_source = None
    for source in creep.home.sources:
        if not has_work and not _.some(
                creep.home.find_in_range(FIND_MY_CREEPS, 1, source.pos),
                lambda c: c.memory.role == role_miner):
            continue
        distance = movement.chebyshev_distance_room_pos(source.pos, creep.pos)
        current_work_force = targets.workforce_of(target_source, source.id)
        if any_miners:
            energy = _.sum(
                creep.home.find_in_range(FIND_DROPPED_RESOURCES, 1,
                                         source.pos), 'amount')
            priority = energy - current_work_force * 100 - distance * 2
        else:
            oss = creep.home.get_open_source_spaces_around(source)
            priority = oss * 10 - 100 * current_work_force / oss - distance
        if source.energy <= 0:
            priority -= 200
        if not priority:
            print("[targets] Strange priority result for source {}: {}".format(
                source, priority))
        if priority > highest_priority:
            best_source = source.id
            highest_priority = priority

    return best_source
Example #8
0
 def run_squad(self, members, target):
     # type: (List[SquadDrone], Location) -> None
     best_near_rank = -Infinity
     best_near = None
     best_damaged_rank = -Infinity
     best_damaged_near = None
     for to_check in members:
         if self.pos.isNearTo(to_check.pos):
             specialty = to_check.findSpecialty()
             if specialty == HEAL and to_check.creep.hits < to_check.creep.hitsMax * 0.7:
                 rank = 7
             elif specialty == RANGED_ATTACK or specialty == ATTACK or specialty == WORK:
                 rank = 5
             else:
                 rank = 1
             if to_check.creep.hits < to_check.creep.hitsMax:
                 rank += (to_check.creep.hitsMax - to_check.creep.hits) / to_check.creep.hitsMax
                 if best_damaged_rank < rank:
                     best_damaged_near = to_check
                     best_damaged_rank = rank
             if best_near_rank < rank:
                 best_near = to_check
                 best_near_rank = rank
     if best_damaged_near:
         result = self.creep.heal(best_damaged_near.creep)
         if result != OK:
             self.log("Unknown result using {}.heal({}): {}"
                      .format(self.creep, best_damaged_rank.creep, result))
     elif movement.chebyshev_distance_room_pos(self.pos, target) < 100 and best_near:
         result = self.creep.heal(best_near.creep)
         if result != OK:
             self.log("Unknown result using {}.heal({}): {}"
                      .format(self.creep, best_near.creep, result))
Example #9
0
    def run(self):
        claim_flag = self.targets.get_new_target(self, target_single_flag,
                                                 CLAIM_LATER)
        if not claim_flag:
            self.memory.last_role = self.memory.role
            self.memory.role = role_recycling
            return
        if self.pos.roomName != claim_flag.pos.roomName:
            target = claim_flag.pos
            if 'checkpoint' not in self.memory or \
                            movement.chebyshev_distance_room_pos(self.memory.checkpoint, self.pos) > 50:
                self.memory.checkpoint = self.pos

            opts = {'range': 15}
            if self.creep.getActiveBodyparts(MOVE) >= len(
                    self.creep.body) * 5 / 7:
                opts.ignore_swamp = True
                opts.use_roads = False
            elif self.creep.getActiveBodyparts(MOVE) >= len(
                    self.creep.body) / 2:
                opts.use_roads = False
            self.follow_military_path(
                _.create(RoomPosition.prototype, self.memory.checkpoint),
                target, opts)
            return False

        target = self.creep.room.controller
        if not target:
            self.log("ERROR: Claim can't find controller in room {}!".format(
                self.creep.room.name))
            self.targets.untarget_all(self)
            return True

        if target.my:
            self.memory.home = self.pos.roomName
            self.targets.untarget_all(self)
            # I guess we can try and claim something else, if we have the life? otherwise this will go and activate the
            # recycle code.
            return True

        if not self.pos.isNearTo(target):
            self.move_to(target)
            return False

        if target.owner:
            self.creep.attackController(target)
        else:
            self.creep.claimController(target)
        room = self.hive.get_room(target.pos.roomName)
        room.mem.sponsor = self.home.name
        if _.get(
                flags.find_flags(room, CLAIM_LATER)[0], 'memory.prio_walls',
                False):
            room.mem.prio_walls = True
        if _.get(
                flags.find_flags(room, CLAIM_LATER)[0], 'memory.prio_spawn',
                False):
            room.mem.prio_spawn = True
Example #10
0
    def run(self):
        # flag to other creeps
        if 'filling' in self.memory:
            del self.memory.filling
        if self.pos.roomName != self.home.name:
            target = None
            if self.carry_sum() > 0:
                target = self.home.room.storage
            if target == undefined:
                target = self.home.spawn
            if target == undefined or self.creep.ticksToLive < movement.chebyshev_distance_room_pos(
                    self.pos, target.pos):
                self.creep.suicide()
                return False
            if 'checkpoint' not in self.memory or \
                            movement.chebyshev_distance_room_pos(self.memory.checkpoint, self.pos) > 50:
                self.memory.checkpoint = self.pos
            self.follow_military_path(
                _.create(RoomPosition.prototype, self.memory.checkpoint),
                target.pos, {'range': 1})
            return False
        if self.carry_sum() > 0:
            storage = self.home.room.storage
            if storage and _.sum(storage.store) < storage.storeCapacity:
                if self.pos.isNearTo(storage):
                    for rtype in Object.keys(self.creep.carry):
                        if self.creep.carry[rtype] > 0:
                            result = self.creep.transfer(storage, rtype)
                            if result == OK:
                                break
                            else:
                                self.log(
                                    "Unknown result from recycling-creep.transfer({}, {}): {}"
                                    .format(storage, rtype, result))
                elif self.creep.ticksToLive <= self.pos.getRangeTo(
                        storage.pos):
                    self.creep.suicide()
                else:
                    self.move_to(storage)
                return False
            elif self.creep.carry[RESOURCE_ENERGY] > 0:
                return self.refill_creeps()

        self.recycle_me()
Example #11
0
 def move_to_can_reach(self, target):
     # type: (RoomPosition) -> bool
     self.move_to(target)
     path = Room.deserializePath(self.memory['_move']['path'])
     # If we can't reach the target, let's find a new one
     pos = __new__(
         RoomPosition(path[len(path) - 1].x, path[len(path) - 1].y,
                      self.pos.roomName))
     return len(path) and movement.chebyshev_distance_room_pos(pos,
                                                               target) <= 1
Example #12
0
 def get_military_path_length(self, spawn, target, opts = None):
     # type: (RoomPosition, RoomPosition, Dict[str, Any]) -> int
     spawn = robjs.pos(spawn)
     target = robjs.pos(target)
     if opts:
         path_opts = opts
     else:
         path_opts = {}
     # if distance_squared_room_pos(spawn, target) > math.pow(200, 2):
     #     # TODO: handle this better (this is for not having multiple super-duper-long cached paths)
     #     intermediate = __new__(RoomPosition(25, 25, target.roomName))
     #     path_opts.max_ops = 30000
     #     path_opts.max_rooms = 30
     #     path_opts.use_roads = False
     #     path1 = self.hive.honey.find_path(spawn, intermediate, path_opts)
     #     path2 = self.hive.honey.find_path(intermediate, target, path_opts)
     #     return len(path1) + 20 + len(path2)
     # else:
     path_opts.max_ops = chebyshev_distance_room_pos(spawn, target) * 150
     path_opts.max_rooms = math.ceil(chebyshev_distance_room_pos(spawn, target) / 5)
     return self.hive.honey.find_path_length(spawn, target, path_opts)
Example #13
0
def find_new_target_energy_site(targets, creep, pos):
    # type: (TargetMind, RoleBase, Optional[RoomPosition]) -> Optional[str]
    if not pos:
        pos = creep.pos
    if creep.home.full_storage_use:
        best = creep.home.room.storage
        # Still usually prefer storage over any links, unless a lot longer distance (>13 more away)
        best_priority = movement.chebyshev_distance_room_pos(pos,
                                                             best.pos) - 13
        if creep.home.links.enabled:
            for struct in creep.home.links.links:
                current_targets = targets.targets[target_closest_energy_site][
                    struct.id]
                priority = movement.chebyshev_distance_room_pos(
                    pos, struct.pos)
                if priority < best_priority and (not current_targets
                                                 or current_targets < 2):
                    best = struct
                    best_priority = priority
        return best.id
    else:
        return None
Example #14
0
 def run_boosts(self):
     # type: () -> None
     for specialty, creeps in list(self._boost_registered.entries()):
         mineral = _boosts_to_use[specialty]
         creeps = _.sortBy(creeps, lambda c: c.ticksToLive)
         original_labs = self.room.minerals.labs_for(mineral)
         labs = _.clone(original_labs)
         while len(creeps):
             creep = creeps.js_pop()
             closest_lab = None
             closest_distance = Infinity
             if len(labs):
                 for lab in labs:
                     distance = movement.chebyshev_distance_room_pos(
                         lab.pos, creep.pos)
                     if distance < closest_distance:
                         closest_lab = lab
                         closest_distance = distance
                 _.pull(labs, [closest_lab])
                 boost_if_close = True
             else:
                 for lab in original_labs:
                     distance = movement.chebyshev_distance_room_pos(
                         lab.pos, creep.pos)
                     if distance < closest_distance:
                         closest_lab = lab
                         closest_distance = distance
                 boost_if_close = False
             if creep.pos.isNearTo(closest_lab) and (
                     boost_if_close or not closest_lab.__boosted):
                 result = closest_lab.boostCreep(creep.creep)
                 closest_lab.__boosted = True
                 if result != OK:
                     print(
                         "[{}][squads] Unknown result from {}.boostCreep({}): {}"
                         .format(self.room.name, closest_lab, creep.creep,
                                 result))
             else:
                 creep.move_to(closest_lab)
Example #15
0
    def run_lab_drop_off(self):
        mind = self.home.minerals

        best_lab = None
        best_resource = None
        closest_distance = Infinity

        for lab, mineral, amount in mind.get_lab_targets():
            if lab.mineralAmount < amount and self.creep.carry[mineral]:
                distance = movement.chebyshev_distance_room_pos(
                    self.pos, lab.pos)
                if distance < closest_distance:
                    closest_distance = distance
                    best_lab = lab
                    best_resource = mineral
        if not best_lab:
            for lab in mind.labs():
                if lab.energy < lab.energyCapacity and self.creep.carry[
                        RESOURCE_ENERGY]:
                    distance = movement.chebyshev_distance_room_pos(
                        self.pos, lab.pos)
                    if distance < closest_distance:
                        closest_distance = distance
                        best_lab = lab
                        best_resource = RESOURCE_ENERGY
        if not best_lab:
            if self.memory.debug:
                self.log("Untargeting labs: no minerals needed that we have.")
            del self.memory.state
            return

        if not self.pos.isNearTo(best_lab):
            self.move_to(best_lab)
            return False

        result = self.creep.transfer(best_lab, best_resource)
        if result != OK:
            self.log("Unknown result from mineral-hauler.transfer({}, {}): {}".
                     format(best_lab, best_resource, result))
Example #16
0
def find_new_target_small_repair_site(
        targets, creep, max_hits, max_work=_default_maximum_repair_workforce):
    # type: (TargetMind, RoleBase, int, int) -> Optional[str]
    repair_targets = creep.home.building.get_repair_targets()
    if not len(repair_targets):
        return None
    # closest_distance = Infinity
    # smallest_num_builders = Infinity
    # best_id = None
    if len(repair_targets) <= 1 and not len(
            creep.home.building.get_construction_targets()):
        max_work = Infinity
    best_id = None
    second_best_id = None
    for struct_id in repair_targets:
        structure = cast(Structure, Game.getObjectById(struct_id))
        if not structure:
            continue
        # TODO: merge this logic with ConstructionMind _efficiently!_
        this_hits_max = min(structure.hitsMax, max_hits)
        if structure and structure.hits < this_hits_max * 0.9:
            distance = movement.chebyshev_distance_room_pos(
                structure.pos, creep.pos)
            ticks_to_repair = (structure.hitsMax - structure.hits) \
                              / (creep.creep.getActiveBodyparts(WORK) * REPAIR_POWER)
            if ticks_to_repair < 10 and distance < 3:
                return structure.id
            elif distance + ticks_to_repair < 15:
                best_id = structure.id
            if second_best_id:
                continue
            if max_work is Infinity:
                current_max = Infinity
            else:
                current_max = min(
                    max_work, math.ceil((this_hits_max - structure.hits) / 50))
            current_workforce = targets.workforce_of(target_repair, struct_id)
            if not current_workforce or current_workforce < current_max:
                #     or current_workforce < smallest_num_builders + 1:
                # Already priority sorted
                second_best_id = structure.id
                # distance = movement.distance_squared_room_pos(structure.pos, creep.creep.pos)
                # if distance < closest_distance:
                #     smallest_num_builders = current_workforce
                #     closest_distance = distance
                #     best_id = struct_id
    if best_id:
        return best_id
    else:
        return second_best_id
Example #17
0
 def get_main_link(self):
     # type: () -> Optional[StructureLink]
     if self._main_link is undefined:
         if self.room.my and self.room.room.storage and len(
                 self.links) >= 2:
             for link in self.links:
                 if movement.chebyshev_distance_room_pos(
                         self.room.room.storage.pos, link.pos) <= 2:
                     if self._main_link is undefined:
                         self._main_link = link
                     else:
                         self._second_link = link
         if self._main_link is undefined:
             self._main_link = None
         if self._second_link is undefined:
             self._second_link = None
     return self._main_link
Example #18
0
 def run_squad(self, members, target):
     # type: (List[SquadDrone], Location) -> None
     attacked = False
     here = cast(List[Creep], self.room.find(FIND_HOSTILE_CREEPS))
     if len(here):
         directly_nearby = 0
         best = None
         best_range = Infinity
         best_rank = -Infinity
         for enemy in here:
             enemy_range = movement.chebyshev_distance_room_pos(enemy.pos, self.pos)
             if enemy_range <= 3:
                 specialty = enemy.findSpecialty()
                 if specialty == ATTACK or specialty == RANGED_ATTACK:
                     rank = 40
                 elif specialty == WORK:
                     rank = 35
                 else:
                     rank = 30
                 if _.some(self.room.look_at(LOOK_STRUCTURES, enemy.pos),
                           lambda s: s.structureType == STRUCTURE_RAMPART and not s.my):
                     rank -= 20
                 rank += (enemy.hitsMax - enemy.hits) / enemy.hitsMax * 5
                 if enemy_range < 1:
                     directly_nearby += rank
                 if rank > best_rank:
                     best_rank = rank
                     best_range = enemy_range
                     best = enemy
         if directly_nearby > 65 or best_range <= 1:
             result = self.creep.rangedMassAttack()
             if result != OK:
                 self.log("Unknown result from {}.rangedMassAttack(): {}"
                          .format(self.creep, result))
             attacked = True
         elif best:
             result = self.creep.rangedAttack(best)
             if result != OK:
                 self.log("Unknown result from {}.rangedAttack({}): {}"
                          .format(self.creep, best, result))
             attacked = True
     if not attacked:
         to_dismantle = volatile_cache.mem('dismantle_squad_dismantling').get(target.name)
         if to_dismantle:
             self.creep.rangedAttack(to_dismantle)
Example #19
0
 def find_depot(self):
     # type: () -> RoomPosition
     depots = flags.find_flags(self.home, DEPOT)
     if len(depots):
         depot = depots[0].pos
     else:
         self.log("WARNING: No depots found in {}!".format(self.home.name))
         self.home.building.place_depot_flag()
         depots = flags.find_flags_global(DEPOT)
         if len(depots):
             depot = _.min(
                 depots, lambda d: movement.chebyshev_distance_room_pos(
                     self.pos, d.pos)).pos
         elif self.home.spawn:
             depot = self.home.spawn.pos
         else:
             depot = movement.find_an_open_space(self.home.name)
     return depot
Example #20
0
    def get_ordered(self,
                    target: RoomPosition,
                    serialized_obj: Dict[str, str],
                    dismantle: List[SquadDismantle],
                    heal: List[SquadDrone],
                    attack: List[SquadDrone],
                    already_repathed: bool = False) -> Tuple[bool, bool]:
        rebuilt = robjs.concat_lists(dismantle, heal, attack)
        first_creep = rebuilt[0]

        serialized_path_this_room = serialized_obj[first_creep.pos.roomName]
        if serialized_path_this_room:
            path_this_room = Room.deserializePath(serialized_path_this_room)
            total_positions_this_room = len(path_this_room)
        else:
            total_positions_this_room = 0
            path_this_room = None
        if path_this_room is not None and total_positions_this_room >= len(
                self.members) + 4:
            if total_positions_this_room >= len(self.members) * 2 + 4:
                first_index = int(len(path_this_room) / 2)
            else:
                first_index = len(path_this_room) - 2
            any_off = False
            for index in range(0, len(rebuilt)):
                pos = path_this_room[first_index - index]
                creep = rebuilt[index]
                pos = __new__(
                    RoomPosition(pos.x, pos.y, first_creep.pos.roomName))
                if creep.pos.isEqualTo(pos):
                    continue
                else:
                    any_off = True
                    creep.move_to(pos)
            if not any_off:
                self.mem[dismemkey_ordered] = True
                return True, already_repathed
        else:
            next_intermediate_goal = target
            origin = _.max(
                self.members, lambda m: movement.chebyshev_distance_room_pos(
                    m.pos, next_intermediate_goal)).pos
            reroute = portals.recommended_reroute(origin, target)
            if reroute is not None:
                next_intermediate_goal = reroute[0]
                origin = _.max(
                    self.members,
                    lambda m: movement.chebyshev_distance_room_pos(
                        m, next_intermediate_goal))
            self.set_origin(origin)
            serialized_obj = self.home.hive.honey.get_serialized_path_obj(
                origin, target, self.new_movement_opts())
            if not serialized_obj[first_creep.pos.roomName]:
                self.log(
                    "Uh-oh - path from furthest creep to target did not include the room the first creep is in."
                    " Setting origin to first creep's pos.")
                self.set_origin(first_creep.pos)
                serialized_obj = self.home.hive.honey.get_serialized_path_obj(
                    origin, target, self.new_movement_opts())
                if not serialized_obj[first_creep.pos.roomName]:
                    self.log(
                        "Path from first creep {} to {} did not include room {}! ...",
                        first_creep.pos, target, first_creep.pos.roomName)
                    return False, False
                return self.get_ordered(target, serialized_obj, dismantle,
                                        heal, attack, True)
        return False, already_repathed
Example #21
0
    def run(self):
        if self.creep.ticksToLive > 1450 and not (self.memory.boosted >= 2):
            if 'boosted' not in self.memory:
                self.memory.boosted = 0
            if self.boost():
                return False

        hostiles_nearby = defense.stored_hostiles_near(self.pos.roomName)
        if self.creep.hits < self.creep.hitsMax or \
                (len(hostiles_nearby)
                 and _.find(hostiles_nearby,
                            lambda h: movement.chebyshev_distance_room_pos(
                                self.pos, positions.deserialize_xy_to_pos(h.pos, h.room)) <= 3)):
            self.creep.heal(self.creep)

        marker_flag = cast(Flag, self.targets.get_new_target(self, target_single_flag, RANGED_DEFENSE))
        if marker_flag is None:
            if self.pos.roomName == self.home.name and len(flags.find_flags(self.home, RAID_OVER)):
                if len(hostiles_nearby) or self.creep.hits < self.creep.hitsMax:
                    self.creep.heal(self.creep)
                return False
            else:
                marker_flag = cast(Flag, {'pos': self.find_depot()})

        if len(hostiles_nearby):
            if _.find(hostiles_nearby, lambda h: h.offensive and movement.chebyshev_distance_room_pos(
                    self.pos, positions.deserialize_xy_to_pos(h.pos, h.room)) <= 5):
                hostiles_nearby = _.filter(hostiles_nearby, 'offensive')
            nearby = _.filter(hostiles_nearby,
                              lambda h: movement.chebyshev_distance_room_pos(
                                  self.pos, positions.deserialize_xy_to_pos(h.pos, h.room)) <= 5)
            closest = _.min(
                hostiles_nearby,
                lambda h: movement.chebyshev_distance_room_pos(self.pos, positions.deserialize_xy_to_pos(h.pos, h.room))
                          - (5 if h.offensive else 0)
            )
            closest_pos = positions.deserialize_xy_to_pos(closest.pos, closest.room)
            harmless = not _.some(nearby, lambda x: x.attack or x.ranged)
            ranged = _.some(nearby, lambda x: x.ranged and x.ranged > x.attack)
            only_ranged = not _.some(nearby,
                                     lambda h: movement.chebyshev_distance_room_pos(
                                         self.pos, positions.deserialize_xy_to_pos(h.pos, h.room)) <= 4 and h.attack)
            mass_attack = _.some(nearby, lambda h: movement.chebyshev_distance_room_pos(
                self.pos, positions.deserialize_xy_to_pos(h.pos, h.room)) <= 1
                                                   and h.room == self.pos.roomName)
        else:
            enemies = self.room.find(FIND_HOSTILE_CREEPS)
            if len(enemies):
                if self.pos.roomName != marker_flag.pos.roomName:
                    enemies = _.filter(enemies, lambda h: hostile_utils.is_offensive(h)
                                                          and hostile_utils.not_sk(h))
                else:
                    any_offensive = _.find(enemies, hostile_utils.is_offensive)
                    if any_offensive:
                        enemies = _.filter(enemies, lambda h: hostile_utils.is_offensive(h)
                                                              and hostile_utils.not_sk(h))
                    else:
                        enemies = _.filter(enemies, hostile_utils.not_sk)
            if len(enemies):
                closest = _.min(enemies, lambda h: movement.chebyshev_distance_room_pos(self.pos, h.pos))
                closest_pos = closest.pos
                nearby = _.filter(enemies, lambda h: movement.chebyshev_distance_room_pos(h.pos, self.pos) <= 5)
                harmless = not _.some(nearby,
                                      lambda h: h.hasActiveBodyparts(ATTACK) or h.hasActiveBodyparts(RANGED_ATTACK)) \
                           and self.creep.hits >= self.creep.hitsMax
                ranged = _.some(nearby, lambda h: h.hasActiveBodyparts(RANGED_ATTACK)
                                                  and h.getActiveBodyparts(RANGED_ATTACK)
                                                      > h.getActiveBodyparts(ATTACK))
                only_ranged = not _.some(nearby,
                                         lambda h:
                                         movement.chebyshev_distance_room_pos(self.pos, h.pos) <= 4
                                         and h.hasBodyparts(ATTACK))
                mass_attack = _.some(nearby, lambda h: self.pos.isNearTo(h.pos) and self.pos.roomName == h.pos.roomName)
            else:
                closest = None
                closest_pos = None
                harmless = False
                ranged = False
                only_ranged = True
                mass_attack = False

        if not closest or (closest_pos.roomName != self.pos.roomName
                           and movement.chebyshev_distance_room_pos(closest_pos, self.pos) > 10):
            del self.memory.last_enemy_pos
            # self.creep.say("🐾 💚 🐾", True)
            if self.pos.roomName == marker_flag.pos.roomName and self.creep.hits >= self.creep.hitsMax:
                hurt = cast(List[Creep], self.room.find(PYFIND_HURT_CREEPS))
                if len(hurt):
                    damaged = _.min(hurt, lambda p: movement.chebyshev_distance_room_pos(p.pos, self.pos))
                    if self.pos.isNearTo(damaged):
                        self.creep.heal(damaged)
                    else:
                        self.move_to(damaged, _MOVE_TO_OPTIONS)
                    return False
            # TODO: turn this into part of a large generic cross-room movement module
            if not self.pos.isEqualTo(marker_flag.pos):
                distance = movement.chebyshev_distance_room_pos(self.pos, marker_flag.pos)
                if distance > 50:
                    if 'checkpoint' not in self.memory or \
                                    movement.chebyshev_distance_room_pos(self.memory.checkpoint, self.pos) > 50:
                        self.memory.checkpoint = self.pos
                    if self.memory.next_ppos \
                            and movement.chebyshev_distance_room_pos(self.pos, self.memory.next_ppos) > 10 \
                            and not hostile_utils.enemy_owns_room(self.pos.roomName):
                        self.memory.checkpoint = self.pos
                        del self.memory.next_ppos
                        del self.memory.off_path_for
                        del self.memory.lost_path_at
                        del self.memory._move

                    if hostile_utils.enemy_owns_room(self.memory.checkpoint.roomName):
                        self.memory.checkpoint = self.home.spawn or movement.find_an_open_space(self.home.name)

                    self.follow_military_path(_.create(RoomPosition.prototype, self.memory.checkpoint),
                                              marker_flag.pos, {'range': 1})
                    self.creep.say("G1")
                elif distance >= 1:
                    self.move_to(marker_flag, _MOVE_TO_OPTIONS)
                    self.creep.say("G2")
                else:
                    self.basic_move_to(marker_flag)
                    self.creep.say("G3")
            return False
        closest_creep = cast(Creep, Game.getObjectById(closest.id))
        min_distance = movement.chebyshev_distance_room_pos(closest_pos, self.pos)
        if Game.time % 2:
            self.creep.say("{},{}: {}".format(closest_pos.x, closest_pos.y, min_distance))
        else:
            self.creep.say("🐾 🏹 🐾", True)
        fatigue = (closest_creep and (closest_creep.fatigue or not closest_creep.hasActiveBodyparts(MOVE)))
        if self.memory.healing:
            self.memory.healing = self_damaged = self.creep.hits < self.creep.hitsMax
        else:
            # If 1/4 of our ranged attack parts are dead.
            total_ra = self.creep.getBodyparts(RANGED_ATTACK)
            alive_ra = self.creep.getActiveBodyparts(RANGED_ATTACK)
            self.memory.healing = self_damaged = (total_ra < 10 and alive_ra < total_ra / 2) or alive_ra < total_ra / 3

        if closest_pos.roomName == self.pos.roomName and min_distance <= 3:
            if mass_attack:
                self.creep.rangedMassAttack()
            else:
                self.creep.rangedAttack(closest_creep)

        if (min_distance <= 6) and self.pos.roomName != closest_pos.roomName:
            self.memory.countdown = (self.memory.countdown or 10) - 1
            if self.memory.countdown <= 0:
                if self.memory.countdown == 0:
                    self.memory.countdown -= 1
                if self.memory.countdown <= 5:
                    del self.memory.countdown
                self.move_to(marker_flag, _MOVE_TO_OPTIONS)
            return
        if ranged and self_damaged:
            safe_distance = 5
        elif ranged and only_ranged:
            safe_distance = 0
        else:
            safe_distance = 3
        should_run = (not _.some(self.pos.lookFor(LOOK_STRUCTURES), {'structureType': STRUCTURE_RAMPART, 'my': True})
                      and not harmless
                      and (min_distance < safe_distance or (min_distance == safe_distance and not fatigue)))

        should_approach = not should_run and (harmless or min_distance > safe_distance)
        if should_approach:
            # NOTE: this depends on our custom moveTo function not checking for instanceof RoomPosition
            self.move_to(closest_pos, _MOVE_TO_OPTIONS)
        elif should_run:
            kiting_path = errorlog.try_exec(
                'kiting-offense',
                kiting_away_raw_path,
                lambda pos: "Error calculating or moving by kiting path at pos {}.".format(pos),
                self.pos,
                [{
                    'pos': positions.deserialize_xy_to_pos(h.pos, h.room),
                    'range': 10,
                } for h in hostiles_nearby],
                marker_flag
            )
            if kiting_path is True:
                # errored
                self.creep.say("Err")
                self.go_to_depot()
            elif len(kiting_path):
                self.creep.move(self.pos.getDirectionTo(kiting_path[0]))
            else:
                self.log("WARNING: kiting offense has no path at position {}!".format(self.pos))
Example #22
0
    def run(self):
        if self.memory.dismantling and self.creep.hits < self.creep.hitsMax / 2:
            self.memory.dismantling = False
            self.targets.untarget(self, target_single_flag2)
        if not self.memory.dismantling and self.creep.hits >= self.creep.hitsMax:
            self.memory.dismantling = True
            self.targets.untarget(self, target_single_flag2)

        if self.memory.dismantling:
            target = cast(
                Optional[Flag],
                self.targets.get_new_target(self, target_single_flag,
                                            ATTACK_DISMANTLE))
            if not target:
                if len(flags.find_flags(self.home, RAID_OVER)):
                    if self.creep.ticksToLive < 300:
                        self.creep.suicide()
                    else:
                        self.memory.last_role = self.memory.role
                        self.memory.role = role_recycling
                else:
                    self.log("Dismantler has no target!")
                    self.go_to_depot()
                return
            if target.name in Memory.flags and target.memory.civilian:
                self.memory.running = 'idle'
            if self.pos.roomName == target.pos.roomName:
                new_target = False
                dismantled = False
                structure = cast(
                    Optional[Structure],
                    self.room.look_at(LOOK_STRUCTURES, target.pos)[0])
                if structure:
                    new_target, dismantled = self.do_dismantle(structure)
                else:
                    site = cast(
                        Optional[ConstructionSite],
                        self.room.look_at(LOOK_CONSTRUCTION_SITES,
                                          target.pos)[0])
                    if site and not site.my:
                        self.move_to(site)
                    elif self.memory.dt:  # dismantler target
                        mem_pos = positions.deserialize_xy_to_pos(
                            self.memory.dt, target.pos.roomName)
                        structure = cast(
                            Optional[Structure],
                            self.room.look_at(LOOK_STRUCTURES, mem_pos)[0])
                        if structure:
                            new_target, dismantled = self.do_dismantle(
                                structure)
                        else:
                            site = self.room.look_at(LOOK_CONSTRUCTION_SITES,
                                                     mem_pos)[0]
                            if site:
                                self.move_to(site)
                            else:
                                new_target = True
                    else:
                        new_target = True

                if new_target:
                    if target.name in Memory.flags and 'dismantle_all' in target.memory and \
                            not target.memory['dismantle_all']:
                        self.remove_target(target)
                        return
                    structures = self.room.find(FIND_STRUCTURES)
                    sites = self.room.find(FIND_CONSTRUCTION_SITES)
                    best_priority = -Infinity
                    best = None
                    hits_per_tick = DISMANTLE_POWER * self.creep.getActiveBodypartsBoostEquivalent(
                        WORK, 'dismantle')
                    for structure in cast(
                            List[Union[Structure, ConstructionSite]],
                            structures.concat(sites)):
                        stype = structure.structureType
                        if structure.my or stype == STRUCTURE_CONTROLLER or stype == STRUCTURE_PORTAL \
                                or (stype == STRUCTURE_EXTRACTOR and not structure.hits) \
                                or (cast(StructureContainer, structure).store
                                    and _.findKey(cast(StructureContainer, structure).store,
                                                  lambda amount, key: amount > 100
                                                  and (key != RESOURCE_ENERGY or amount > 10 * 1000))):
                            continue
                        distance = movement.chebyshev_distance_room_pos(
                            self.pos, structure.pos)

                        priority = -distance
                        if stype == STRUCTURE_WALL or stype == STRUCTURE_RAMPART:
                            if structure.hits:
                                priority -= structure.hits / hits_per_tick
                        if structure.progressTotal:  # a construction site
                            priority -= 50
                        if stype == STRUCTURE_ROAD and distance > 1:
                            priority -= 500 * distance
                        if priority > best_priority:
                            best_priority = priority
                            best = structure
                    if best:
                        self.memory.dt = positions.serialize_pos_xy(
                            best.pos)  # dismantler target
                        if __pragma__('js',
                                      '(best instanceof ConstructionSite)'):
                            self.move_to(best)
                        elif not dismantled:
                            self.do_dismantle(best)
                        else:
                            self.move_to(best)
                    else:
                        self.remove_target(target)
                        return
            else:
                if self.memory.dt:  # dismantler target
                    target = positions.deserialize_xy_to_pos(
                        self.memory.dt, target.pos.roomName)
                if 'checkpoint' not in self.memory or \
                                movement.chebyshev_distance_room_pos(self.memory.checkpoint, self.pos) > 50:
                    self.memory.checkpoint = self.pos
                if hostile_utils.enemy_owns_room(
                        self.memory.checkpoint.roomName):
                    self.memory.checkpoint = self.home.spawn or movement.find_an_open_space(
                        self.home.name)

                self.follow_military_path(
                    _.create(RoomPosition.prototype, self.memory.checkpoint),
                    target)

        else:
            target = self.targets.get_new_target(self, target_single_flag2,
                                                 TD_H_D_STOP)
            if not target:
                if len(flags.find_flags(self.home, RAID_OVER)):
                    if self.creep.ticksToLive < 300:
                        self.creep.suicide()
                    else:
                        self.recycle_me()
                else:
                    self.log("Dismantler has no healer target!")
                    self.go_to_depot()
                return
            if self.pos.roomName != target.pos.roomName:
                self.creep.moveTo(target)
            else:
                room = self.hive.get_room(target.pos.roomName)
                if room and _.find(room.find(FIND_MY_CREEPS),
                                   lambda c: c.memory.role == role_td_healer):
                    if not self.pos.isEqualTo(target):
                        self.creep.moveTo(target)
                        self.follow_military_path(self.home.spawn.pos, target)
                else:
                    self.go_to_depot()
Example #23
0
    def run_squad(self, members, target, do_things = False):
        """
        :type members: list[SquadDrone]
        :type target: position_management.locations.Location
        :type do_things: bool
        """
        if not do_things:
            return
        hostiles_nearby = defense.stored_hostiles_near(self.pos.roomName)
        if self.creep.hits < self.creep.hitsMax or \
                (len(hostiles_nearby)
                 and _.find(hostiles_nearby,
                            lambda h: movement.chebyshev_distance_room_pos(
                                self.pos, positions.deserialize_xy_to_pos(h.pos, h.room)) <= 3)):
            self.creep.heal(self.creep)

        marker_flag = target

        if len(hostiles_nearby):
            if _.find(hostiles_nearby, lambda h: h.offensive and movement.chebyshev_distance_room_pos(
                    self.pos, positions.deserialize_xy_to_pos(h.pos, h.room)) <= 5):
                hostiles_nearby = _.filter(hostiles_nearby, 'offensive')
            nearby = _.filter(hostiles_nearby,
                              lambda h: movement.chebyshev_distance_room_pos(
                                  self.pos, positions.deserialize_xy_to_pos(h.pos, h.room)) <= 5)
            closest = _.min(
                hostiles_nearby,
                lambda h: movement.chebyshev_distance_room_pos(self.pos, positions.deserialize_xy_to_pos(h.pos, h.room))
                          - (5 if h.offensive else 0)
            )
            closest_pos = positions.deserialize_xy_to_pos(closest.pos, closest.room)
            harmless = not _.some(nearby, lambda x: x.attack or x.ranged)
            ranged = _.some(nearby, lambda x: x.ranged)
            only_ranged = not _.some(nearby,
                                     lambda h: movement.chebyshev_distance_room_pos(
                                         self.pos, positions.deserialize_xy_to_pos(h.pos, h.room)) <= 4 and h.attack)
            mass_attack = _.some(nearby, lambda h: movement.chebyshev_distance_room_pos(
                self.pos, positions.deserialize_xy_to_pos(h.pos, h.room)) <= 1
                                                   and h.room == self.pos.roomName)
        else:
            enemies = self.room.find(FIND_HOSTILE_CREEPS)
            if len(enemies):
                if self.pos.roomName != marker_flag.roomName:
                    enemies = _.filter(enemies, lambda h: hostile_utils.is_offensive(h)
                                                          and hostile_utils.not_sk(h))
                else:
                    any_offensive = _.find(enemies, hostile_utils.is_offensive)
                    if any_offensive:
                        enemies = _.filter(enemies, lambda h: hostile_utils.is_offensive(h)
                                                              and hostile_utils.not_sk(h))
                    else:
                        enemies = _.filter(enemies, hostile_utils.not_sk)
            if len(enemies):
                closest = _.min(enemies, lambda h: movement.chebyshev_distance_room_pos(self.pos, h.pos))
                closest_pos = closest.pos
                nearby = _.filter(enemies, lambda h: movement.chebyshev_distance_room_pos(h.pos, self.pos) <= 5)
                harmless = not _.some(nearby,
                                      lambda h: h.hasActiveBodyparts(ATTACK) or h.hasActiveBodyparts(RANGED_ATTACK)) \
                           and self.creep.hits >= self.creep.hitsMax
                ranged = _.some(nearby, lambda h: h.hasActiveBodyparts(RANGED_ATTACK))
                only_ranged = not _.some(nearby,
                                         lambda h:
                                         movement.chebyshev_distance_room_pos(self.pos, h.pos) <= 4
                                         and h.hasBodyparts(ATTACK))
                mass_attack = _.some(nearby, lambda h: self.pos.isNearTo(h.pos) and self.pos.roomName == h.pos.roomName)
            else:
                closest = None
                closest_pos = None
                nearby = []
                harmless = False
                ranged = False
                only_ranged = True
                mass_attack = False
        if not closest:
            self.move_to(target)
            return
        closest_creep = cast(Creep, Game.getObjectById(closest.id))
        min_distance = movement.chebyshev_distance_room_pos(closest_pos, self.pos)
        if Game.time % 2:
            self.creep.say("{},{}: {}".format(closest_pos.x, closest_pos.y, min_distance))
        else:
            self.creep.say("🏹", True)
        fatigue = (closest_creep and (closest_creep.fatigue or not closest_creep.hasActiveBodyparts(MOVE)))
        if self.memory.healing:
            self.memory.healing = self_damaged = self.creep.hits < self.creep.hitsMax
        else:
            # If 1/4 of our ranged attack parts are dead.
            total_ra = self.creep.getBodyparts(ATTACK)
            alive_ra = self.creep.getActiveBodyparts(ATTACK)
            self.memory.healing = self_damaged = (total_ra < 10 and alive_ra < total_ra / 2) or alive_ra < total_ra / 3

        if closest_pos.roomName == self.pos.roomName and min_distance <= 1:
            self.creep.attack(closest_creep)

        if (min_distance <= 6) and self.pos.roomName != closest_pos.roomName:
            self.memory.countdown = (self.memory.countdown or 10) - 1
            if self.memory.countdown <= 0:
                if self.memory.countdown == 0:
                    self.memory.countdown -= 1
                if self.memory.countdown <= 5:
                    del self.memory.countdown
                self.move_to(marker_flag, _MOVE_TO_OPTIONS)
            return
        if ranged and self_damaged:
            safe_distance = 5
        elif ranged and only_ranged:
            safe_distance = 0
        elif self_damaged:
            safe_distance = 3
        else:
            safe_distance = 0
        should_run = (not _.some(self.pos.lookFor(LOOK_STRUCTURES), {'structureType': STRUCTURE_RAMPART, 'my': True})
                      and not harmless
                      and (min_distance < safe_distance or (min_distance == safe_distance and not fatigue)))

        should_approach = not should_run and (harmless or min_distance > safe_distance)
        if should_approach:
            # NOTE: this depends on our custom moveTo function not checking for instanceof RoomPosition
            self.move_to(closest_pos, _MOVE_TO_OPTIONS)
        elif should_run:
            kiting_path = errorlog.try_exec(
                'kiting-offense',
                kiting_away_raw_path,
                lambda pos: "Error calculating or moving by kiting path at pos {}.".format(pos),
                self.pos,
                [{
                    'pos': positions.deserialize_xy_to_pos(h.pos, h.room),
                    'range': 10,
                } for h in hostiles_nearby], marker_flag
            )
            if kiting_path is True:
                # errored
                self.creep.say("Err")
                self.go_to_depot()
            elif len(kiting_path):
                self.creep.move(self.pos.getDirectionTo(kiting_path[0]))
            else:
                self.log("WARNING: kiting offense has no path at position {}!".format(self.pos))
Example #24
0
def run_away_check(creep, hostile_path_targets):
    # type: (Creep, List[Dict[str, Any]]) -> bool

    check_path = is_room_mostly_safe(creep.pos.roomName)

    if check_path and not creep.memory._safe or not creep.memory._safe_from \
            or movement.chebyshev_distance_room_pos(creep.memory._safe_from, creep.pos) > 2:
        creep.memory._safe = []
        creep.memory._safe_from = creep.pos

    any_unsafe = False
    for obj in hostile_path_targets:
        target = obj['pos']
        target_range = obj['range']
        # NOTE: target_range here is twice what we actually want, so that when passing to PathFinder we get a better
        # path. See NOTE above.
        distance = movement.chebyshev_distance_room_pos(target, creep.pos)
        if distance > target_range * 0.25 + 1:
            continue
        if check_path:
            safe = False
            for safe_pos in creep.memory._safe:
                if movement.chebyshev_distance_room_pos(safe_pos, target) < 2:
                    safe = True
                    break
            if safe:
                continue
            enemy_path = PathFinder.search(
                target,
                {
                    "pos": creep.pos,
                    "range": 1
                },
                {
                    "roomCallback": enemy_purposes_cost_matrix,
                    "maxRooms": 5,
                    "plainCost": 1,
                    "swampCost": 1,  # for speed purposes
                    "maxCost": 10,
                })
            if enemy_path.incomplete:
                creep.memory._safe.push(target)
                continue

        distance = movement.chebyshev_distance_room_pos(target, creep.pos)
        if distance <= target_range * 0.25:
            break
        else:
            # elif distance <= target_range * 0.25 + 1: # We check this above
            any_unsafe = True
    else:
        return any_unsafe and random.randint(
            0, 3
        ) < 3  # if we're between target_range and target_range + 1, just pause

    path = get_cached_away_path(creep, hostile_path_targets)

    if len(path):
        del creep.memory.was_on_the_path
        result = creep.moveByPath(path)
        if result == ERR_NO_PATH or result == ERR_NOT_FOUND:
            # del creep.memory._away_path
            # path = get_cached_away_path(creep, hostile_path_targets)
            # result = creep.creep.moveByPath(path)
            # I had the above enabled previously, and I don't think it really helped any... the ERR_NOT_FOUND would just
            # happen with the newly-generated path too.
            return True
        if result != OK:
            print("[{}][{}] Unknown result from moving when running away: {}".
                  format(creep.memory.home, creep.name, result))
        return True
    else:
        # we're a safe distance away from all enemies
        return False
Example #25
0
    def find_target_here(self, target):
        # type: (Location) -> Optional[RoomPosition]
        opts = get_opts(self.pos.roomName)
        if self.memory.tloctimeout > Game.time:
            pos = positions.deserialize_xy_to_pos(self.memory.tloc,
                                                  target.roomName)
            if pos:
                if _.some(self.room.look_at(LOOK_STRUCTURES, pos),
                          get_dismantle_condition_not_a_road(opts)):
                    return pos
        structure_target = _.find(self.room.look_at(LOOK_STRUCTURES, target),
                                  get_dismantle_condition_not_a_road(opts))
        if structure_target:
            self.memory.tloc = positions.serialize_pos_xy(structure_target.pos)
            self.memory.tloctimeout = Game.time + 50
            return structure_target.pos

        if self.pos.roomName != target.roomName:
            return None

        best_target = None
        best_rank = -Infinity
        enemy_structures = cast(List[OwnedStructure],
                                self.room.find(FIND_HOSTILE_STRUCTURES))
        opts = get_opts(self.pos.roomName)
        for struct in enemy_structures:
            structure_type = struct.structureType
            if not can_target_struct(struct, opts):
                continue
            if structure_type == STRUCTURE_SPAWN:
                rank = 50
            elif structure_type == STRUCTURE_LAB:
                rank = 40
            elif structure_type == STRUCTURE_TOWER:
                rank = 30
            elif structure_type == STRUCTURE_EXTENSION:
                rank = 20
            elif structure_type != STRUCTURE_RAMPART:
                rank = 10
            else:
                rank = 0
            rank -= movement.chebyshev_distance_room_pos(self.pos,
                                                         struct.pos) / 20
            if structure_type != STRUCTURE_RAMPART:
                rampart = cast(
                    StructureRampart,
                    _.find(self.room.look_at(LOOK_STRUCTURES, struct.pos),
                           {'structureType': STRUCTURE_RAMPART}))
                if rampart:
                    rank -= 10 * rampart.hits / (DISMANTLE_POWER *
                                                 MAX_CREEP_SIZE / 2 *
                                                 CREEP_LIFE_TIME * 0.9)
            if rank > best_rank:
                best_target = struct
                best_rank = rank

        if best_target:
            self.memory.tloc = positions.serialize_pos_xy(best_target.pos)
            self.memory.tloctimeout = Game.time + 100
            return best_target.pos
        else:
            if self.pos.isNearTo(target):
                flag = flags.look_for(self.room, target,
                                      SQUAD_DISMANTLE_RANGED)
                if flag:
                    msg = "[dismantle squad][{}][{}] Dismantle job in {} completed at {}! Removing flag {} ({})." \
                        .format(self.home.name, self.name, self.pos.roomName, Game.time, flag, flag.pos)
                    self.log(msg)
                    Game.notify(msg)
                    flag.remove()
            self.memory.tloc = positions.serialize_pos_xy(target)
            self.memory.tloctimeout = Game.time + 20
            return target
Example #26
0
    def follow_military_path(self, origin, target, opts = None):
        # type: (RoomPosition, RoomPosition, Dict[str, Any]) -> None
        origin = robjs.pos(origin)
        target = robjs.pos(target)
        if opts and "to_home" in opts:
            to_home = opts["to_home"]
        else:
            to_home = False
        if not origin:
            origin = movement.find_an_open_space(self.memory.home)
        if self.creep.fatigue > 0:
            return
        if self.pos.getRangeTo(target) < 10 or self.pos.roomName == target.roomName:
            self.move_to(target)
            return
        path_opts = {
            'current_room': self.pos.roomName,
        }
        if opts:
            path_opts = _.merge(path_opts, opts)
        # TODO: this is all stupid, PathFinder is stupid for multiple rooms!
        if chebyshev_distance_room_pos(origin, target) > 900 \
                and not is_path_portal(origin, target) and target.roomName != 'W11S56':
            path_opts.max_ops = chebyshev_distance_room_pos(origin, target) * 150
            path_opts.max_rooms = math.ceil(chebyshev_distance_room_pos(origin, target) / 5)

            # TODO: handle this better (this is for not having multiple super-duper-long cached paths)
            if to_home:
                intermediate = find_an_open_space(origin.roomName)
                origin = intermediate
            else:
                intermediate = center_pos(target.roomName)
                if self.pos.roomName != intermediate.roomName:
                    target = intermediate
                    path_opts.range = max(path_opts.range or 0, 10)
                else:
                    # If we're this far away, let's just get to the room using a cached path and then do
                    # basic pathfinding to get to our actual target.
                    self.move_to(target)
                    return
            pass
            origin_midpoint = find_midpoint(self.pos, self.pos, origin)
            if origin_midpoint is not None:
                origin = origin_midpoint
            dest_midpoint = find_midpoint(self.pos, origin, target)
            if dest_midpoint is not None:
                if self.pos.roomName == dest_midpoint.roomName:
                    origin = dest_midpoint
                else:
                    target = dest_midpoint
                    path_opts.range = max(path_opts.range or 0, 10)

        path = self.hive.honey.find_serialized_path(origin, target, path_opts)
        # TODO: manually check the next position, and if it's a creep check what direction it's going
        result = self.creep.moveByPath(path)
        if result == ERR_NOT_FOUND:
            if self.memory.manual:
                self.move_to(target)
            elif not self.memory.next_ppos or movement.chebyshev_distance_room_pos(self.pos, self.memory.next_ppos) \
                    > CREEP_LIFE_TIME:
                all_positions = self.hive.honey.list_of_room_positions_in_path(origin, target, path_opts)
                closest = None
                closest_distance = Infinity
                for pos in all_positions:
                    distance = chebyshev_distance_room_pos(self.pos, pos)
                    if distance < closest_distance:
                        closest_distance = distance
                        closest = pos
                if closest and closest_distance < CREEP_LIFE_TIME:
                    self.memory.next_ppos = closest
                    if closest.isEqualTo(self.pos):
                        self.log("WARNING: ERR_NOT_FOUND when actually still on military path! Path retrieved:\n{}"
                                 "\nPos: {}.".format(path, self.pos))
                        if chebyshev_distance_room_pos(self.pos, target) <= 50:
                            self.memory.manual = True
                            self.move_to(target)
                            return
                else:
                    portals = cast(List[StructurePortal], _.filter(self.room.find(FIND_STRUCTURES),
                                                                   {'structureType': STRUCTURE_PORTAL}))
                    if len(portals) and movement.chebyshev_distance_room_pos(self.pos, portals[0].pos) \
                            + movement.chebyshev_distance_room_pos(portals[0].destination, target) \
                            < movement.chebyshev_distance_room_pos(self.pos, target):
                        self.memory.next_ppos = self.pos.findClosestByRange(portals).pos
                    else:
                        self.log("WARNING: Couldn't find closest position on path from {} to {} near {}!"
                                 "\nMoving manually... (all pos: {})"
                                 .format(origin, target, self.pos, all_positions))
                        self.memory.next_ppos = target
            mtarget = self.memory.next_ppos
            if mtarget:
                new_target = __new__(RoomPosition(mtarget.x, mtarget.y, mtarget.roomName))
                if self.pos.isNearTo(new_target):
                    self.creep.move(self.pos.getDirectionTo(new_target))
                else:
                    if self.memory.checkpoint and movement.chebyshev_distance_room_pos(self.pos, new_target) > 20:
                        del self.memory.checkpoint
                        del self.memory.next_ppos
                        del self.memory.lost_path_at
                        del self.memory.off_path_for
                        return
                    self.move_to(new_target)
                if self.pos.isEqualTo(new_target):
                    del self.memory.next_ppos
                if not self.memory.off_path_for:
                    self.memory.off_path_for = 1
                    self.memory.lost_path_at = self.pos
                else:
                    if not self.memory.lost_path_at:
                        self.memory.lost_path_at = self.pos
                    self.memory.off_path_for += 1
                    if self.memory.off_path_for > 10:
                        if chebyshev_distance_room_pos(self.memory.lost_path_at, self.pos) < 5 \
                                and not self.pos.isEqualTo(new_target) \
                                and not self.pos.isEqualTo(get_entrance_for_exit_pos(new_target)):
                            honey.clear_cached_path(origin, target, path_opts)
                            del self.memory.off_path_for
                            del self.memory.lost_path_at
                            del self.memory.next_ppos

                        self.log("Lost the path from {} to {}! Pos: {}. Retargeting to: {} (path: {})".format(
                            origin, target, self.pos, new_target, ', '.join([
                                "({},{})".format(p.x, p.y) for p in Room.deserializePath(
                                    _.get(self.memory, ['_move', 'path'], ''))
                            ])))
        elif result != OK:
            self.log("Unknown result from follow_military_path: {}".format(result))
        else:
            # String.fromCodePoint(pos.x | (pos.y << 6));
            # var val = str.charCodeAt(i);
            # var x = (val & 0x3F);
            # var y = ((val >> 6) & 0x3F);
            # return {x: x, y: y};
            if self.memory.off_path_for:
                del self.memory.next_ppos
                del self.memory.off_path_for
                del self.memory.lost_path_at
        serialized_pos = self.pos.x | (self.pos.y << 6)
        if self.memory.last_pos == serialized_pos:
            self.log("standstill! at: {}", self.pos)
            if self.memory.standstill_for:
                self.memory.standstill_for += 1
            else:
                self.memory.standstill_for = 1
            if self.memory.standstill_for == 5:
                del self.memory.next_ppos
                found_mine = False
                for pos in self.hive.honey.find_path(origin, target, path_opts):
                    if pos.x == self.pos.x and pos.y == self.pos.y:
                        found_mine = True
                    elif found_mine:
                        if is_block_clear(self.room, pos.x, pos.y):
                            self.memory.next_ppos = {"x": pos.x, "y": pos.y, "roomName": self.pos.roomName}
                            self.move_to(__new__(RoomPosition(pos.x, pos.y, self.pos.roomName)))
                            break
            if self.memory.standstill_for > 10:
                del self.memory.last_position
                del self.memory.standstill_for
                del self.memory.next_ppos
                honey.clear_cached_path(origin, target, path_opts)
                self.move_to(target)
        else:
            self.memory.last_pos = serialized_pos
            del self.memory.standstill_for
Example #27
0
    def run(self):
        if 'goading' not in self.memory:
            self.memory.goading = False
        if self.memory.goading and self.creep.hits < self.creep.hitsMax / 2:
            self.memory.goading = False
            self.targets.untarget_all(self)
        if not self.memory.goading and self.creep.hits >= self.creep.hitsMax:
            self.memory.goading = True
            self.targets.untarget_all(self)
        goad_target = self.targets.get_new_target(self, target_single_flag,
                                                  TD_D_GOAD)
        if not goad_target:
            self.log("TowerDrainer has no target!")
            self.memory.last_role = self.memory.role
            self.memory.role = role_recycling
            return

        def set_max_avoid_regular_matrix(room_name, cost_matrix):
            # type: (str, PathFinder.CostMatrix) -> None
            if room_name == goad_target.pos.roomName:
                for x in range(0, 50):
                    for y in range(0, 50):
                        existing = cost_matrix.get(x, y)
                        if existing == 0:
                            terrain = Game.map.getTerrainAt(x, y, room_name)
                            if terrain[0] == 'p':
                                existing = 2
                            elif terrain[0] == 's':
                                existing = 10
                            else:
                                continue
                        cost_matrix.set(x, y, existing + 20)

        if self.memory.goading:
            if self.pos.isEqualTo(goad_target):
                pass
            elif movement.chebyshev_distance_room_pos(self.pos,
                                                      goad_target) < 50:
                self.move_to(goad_target,
                             {'costCallback': set_max_avoid_regular_matrix})
            else:
                self.follow_military_path(
                    self.home.spawn.pos, goad_target,
                    {'avoid_rooms': [goad_target.pos.roomName]})
        else:
            heal_target = self.targets.get_new_target(self,
                                                      target_single_flag2,
                                                      TD_H_D_STOP)
            if not heal_target:
                if len(flags.find_flags(self.home, RAID_OVER)):
                    self.recycle_me()
                else:
                    self.go_to_depot()
                return
            if self.pos.isEqualTo(heal_target):
                pass
            elif movement.chebyshev_distance_room_pos(self.pos,
                                                      heal_target) < 50:
                # TODO: make a military moveTo method like this
                self.move_to(heal_target,
                             {'costCallback': set_max_avoid_regular_matrix})
            else:
                self.follow_military_path(
                    self.home.spawn.pos, heal_target,
                    {'avoid_rooms': [goad_target.pos.roomName]})

        autoactions.instinct_do_attack(self)
Example #28
0
    def run(self):
        if self.creep.ticksToLive < recycle_time and not self.home.under_siege(
        ):
            self.memory.role = role_recycling
            self.memory.last_role = role_spawn_fill
            return False
        if self.memory.filling and self.creep.carry[
                RESOURCE_ENERGY] >= self.creep.carryCapacity:
            self.memory.filling = False
            if self.memory.role == role_spawn_fill or self.memory.role == role_tower_fill:
                self.targets.untarget_all(self)
            else:
                return True
        elif not self.memory.filling and (
                self.creep.carry[RESOURCE_ENERGY] <= 0 or
            (self.creep.carry[RESOURCE_ENERGY] <= 20 and self.home.room.storage
             and movement.chebyshev_distance_room_pos(
                 self.pos, self.home.room.storage.pos) < 5)):
            self.memory.filling = True
            del self.memory.running
            if self.memory.role == role_spawn_fill or self.memory.role == role_tower_fill:
                self.targets.untarget_all(self)
            else:
                return True

        if self.memory.filling:
            return self.harvest_energy()
        else:
            if 'running' in self.memory:
                if self.memory.running == role_upgrader:
                    return upgrading.Upgrader.run(self)
                elif self.memory.running == role_builder:
                    return building.Builder.run(self)
                elif self.memory.running == "refill":
                    return self.refill_creeps()
                elif self.memory.running != role_spawn_fill and self.memory.running != "spawn_wait":
                    self.log("WARNING: Unknown running value: {}",
                             self.memory.running)
                    del self.memory.running
            elif self.home.room.energyCapacityAvailable < 550 and self.home.room.energyAvailable < 300 \
                    and self.home.next_role is None:
                if self.creep.hasActiveBodyparts(WORK):
                    self.memory.running = role_builder
                    return building.Builder.run(self)
                else:
                    self.memory.running = "refill"
                    return self.refill_creeps()
            target = cast(
                Union[StructureExtension, Flag, None],
                self.targets.get_new_target(self, target_spawn_deposit))
            if target:
                if cast(Flag, target).color:  # it's a spawn fill wait flag
                    assert isinstance(target, Flag)
                    self.memory.running = "spawn_wait"
                    rwc_cache = volatile_cache.mem("sfrwc")
                    if not rwc_cache.has(self.pos.roomName):
                        rwc_cache.set(
                            self.pos.roomName, not not _.find(
                                self.room.find(FIND_MY_STRUCTURES), lambda s:
                                (s.structureType == STRUCTURE_EXTENSION or s.
                                 structureType == STRUCTURE_SPAWN) and s.energy
                                < s.energyCapacity))
                    if rwc_cache.get(self.pos.roomName):
                        self.targets.untarget(self, target_spawn_deposit)
                        return True
                    if self.creep.carry[
                            RESOURCE_ENERGY] < self.creep.carryCapacity:
                        self.memory.filling = True
                        return True
                    if not self.home.full_storage_use:
                        self.memory.running = "refill"
                        return self.refill_creeps()
                    if not self.pos.isEqualTo(target):
                        self.move_to(target)
                    return False
                else:
                    assert isinstance(target, StructureExtension)
                    if self.memory.running == "spawn_wait":
                        del self.memory.running
                    if target.energy >= target.energyCapacity:
                        self.targets.untarget(self, target_spawn_deposit)
                        return True
                    else:
                        if not self.pos.isNearTo(target):
                            self.move_to(target)
                            return False
                        del self.memory.nbm

                        result = self.creep.transfer(target, RESOURCE_ENERGY)

                        if result == OK:
                            if self.creep.carry[
                                    RESOURCE_ENERGY] > target.energyCapacity - target.energy:
                                volatile_cache.mem("extensions_filled").set(
                                    target.id, True)
                                if self.creep.carry[
                                        RESOURCE_ENERGY] + target.energy - target.energyCapacity > 0:
                                    self.targets.untarget(
                                        self, target_spawn_deposit)
                                    new_target = self.targets.get_new_target(
                                        self, target_spawn_deposit)
                                    if new_target and not self.pos.isNearTo(
                                            new_target):
                                        self.move_to(new_target)
                                else:
                                    self.harvest_energy(
                                    )  # Get a head start on this too!
                        elif result == ERR_FULL:
                            self.targets.untarget(self, target_spawn_deposit)
                            return True
                        else:
                            self.log(
                                "Unknown result from spawn_fill-creep.transfer({}): {}",
                                target, result)
                            self.targets.untarget(self, target_spawn_deposit)
                            return True
                        return False

            if self.home.full_storage_use and self.memory.role == role_spawn_fill_backup \
                    and self.home.carry_mass_of(role_tower_fill) + self.home.carry_mass_of(role_spawn_fill) \
                            >= self.home.get_target_total_spawn_fill_mass():
                self.memory.role = role_builder
                return building.Builder.run(self)
            elif self.memory.role == role_spawn_fill_backup:
                if _.find(self.room.building.get_construction_targets(),
                          lambda s: s.structureType == STRUCTURE_EXTENSION
                          ) or self.home.upgrading_deprioritized():
                    self.memory.running = role_builder
                    return building.Builder.run(self)
                else:
                    self.memory.running = role_upgrader
                    return upgrading.Upgrader.run(self)
            elif not self.home.full_storage_use or self.home.room.storage.storeCapacity <= 0:
                self.memory.running = "refill"
                return self.refill_creeps()
            elif self.creep.carry[RESOURCE_ENERGY] < self.creep.carryCapacity:
                self.memory.filling = True
                return self.harvest_energy()
        return False
Example #29
0
    def follow_energy_path(self, origin, target, mine=None):
        # type: (Union[RoomObject, RoomPosition], Union[RoomObject, RoomPosition], Any) -> None
        origin = robjs.pos(origin)
        target = robjs.pos(target)
        if self.creep.fatigue > 0:
            return
        if origin.isNearTo(target):
            if self.pos.roomName == target.roomName:
                self.move_to(target)
                return
            else:
                origin = self.home.spawn.pos

        if mine:
            opts = {
                'current_room': self.pos.roomName,
                'paved_for': mine,
            }
        elif self.carry_sum() == 0:
            opts = {'current_room': self.pos.roomName, 'use_roads': False}
        else:
            opts = {'current_room': self.pos.roomName}
        path = self.hive.honey.find_serialized_path(origin, target, opts)
        # TODO: manually check the next position, and if it's a creep check what direction it's going
        result = self.creep.moveByPath(path)
        if result == ERR_NOT_FOUND or result == ERR_NO_PATH:
            if self.pos.isNearTo(target):
                self.basic_move_to(target)
                return
            if not self.memory.next_ppos or self.memory.off_path_for > 10 or movement.chebyshev_distance_room_pos(
                    self.pos, self.memory.next_ppos) > CREEP_LIFE_TIME:
                self.memory.off_path_for = 0  # Recalculate next_ppos if we're off path for a long time
                all_positions = self.hive.honey.list_of_room_positions_in_path(
                    origin, target, opts)
                closest = None
                closest_distance = Infinity
                for index, pos in enumerate(all_positions):
                    if movement.chebyshev_distance_room_pos(pos, origin) < 3 \
                            or movement.chebyshev_distance_room_pos(pos, target) < 3:
                        room = self.hive.get_room(pos.roomName)
                        if room and not movement.is_block_clear(
                                room, pos.x, pos.y):
                            continue  # Don't try and target where the miner is right now!
                    # subtract how far we are on the path!
                    # NOTE: 0.7 is used in building._repath_roads_for and should be changed there if changed here.
                    distance = movement.chebyshev_distance_room_pos(
                        self.pos, pos) - index * 0.7
                    if pos.roomName != self.pos.roomName or pos.x < 2 or pos.x > 48 or pos.y < 2 or pos.y > 48:
                        distance += 10
                    if distance < closest_distance:
                        closest_distance = distance
                        closest = pos
                if not closest or closest_distance >= CREEP_LIFE_TIME:
                    portals = cast(
                        List[StructurePortal],
                        _.filter(self.room.find(FIND_STRUCTURES),
                                 {'structureType': STRUCTURE_PORTAL}))
                    if len(portals) and movement.chebyshev_distance_room_pos(self.pos, portals[0].pos) \
                            + movement.chebyshev_distance_room_pos(portals[0].destination, target) \
                            < movement.chebyshev_distance_room_pos(self.pos, target):
                        self.memory.next_ppos = self.pos.findClosestByRange(
                            portals).pos
                    else:
                        self.log(
                            "WARNING: Transport creep off path, with no positions to return to. I'm at {}, going"
                            " from {} to {}. All positions: {}!".format(
                                self.pos, origin, target, all_positions))
                        if mine and self.home.mining.is_mine_linked(mine):
                            self.log(
                                "I'm a hauler for a linked mine! Suiciding.")
                            self.memory.role = role_recycling
                        if not len(all_positions):
                            if Game.time % 20 == 10:
                                honey.clear_cached_path(origin, target)
                        return
                self.memory.next_ppos = closest
            mtarget = self.memory.next_ppos
            new_target = __new__(
                RoomPosition(mtarget.x, mtarget.y, mtarget.roomName))
            if self.pos.isEqualTo(new_target):
                del self.memory.next_ppos
                if not self.memory.tried_new_next_ppos:
                    self.memory.tried_new_next_ppos = True
                else:
                    del self.memory.tried_new_next_ppos
                    # the path is incorrect!
                    self.log(
                        "WARNING: Path from {} to {} found to be cached incorrectly - it should contain {}, but"
                        " it doesn't.".format(origin, target, new_target))
                    self.log(
                        "Path (tbd) retrieved from HoneyTrails with options ({}):\n{}"
                        .format(opts, JSON.stringify(path, 0, 4)))
                    honey.clear_cached_path(origin, target, opts)
            elif self.pos.isNearTo(new_target):
                if movement.is_block_clear(self.room, new_target.x,
                                           new_target.y):
                    self.basic_move_to(new_target)
                else:
                    del self.memory.next_ppos
                    del self.memory.tried_new_next_ppos
                return
            else:
                del self.memory.tried_new_next_ppos
            self.move_to(new_target)
            if not self.memory.off_path_for:
                self.memory.off_path_for = 1
            else:
                self.memory.off_path_for += 1
        elif result != OK:
            self.log(
                "Unknown result from follow_energy_path: {}. Going from {} to {} (path {}, in {})"
                .format(result, origin, target, path, self.pos.roomName))
        else:
            del self.memory.tried_new_next_ppos
            if self.memory.off_path_for:
                self.memory.on_path_for = 1
                del self.memory.off_path_for
            elif self.memory.on_path_for:
                self.memory.on_path_for += 1
                if self.memory.on_path_for >= 2:
                    del self.memory.next_ppos
                    del self.memory.on_path_for

            serialized_pos = self.pos.x | (self.pos.y << 6)
            if self.memory.last_pos == serialized_pos:
                if 'standstill_for' in self.memory:
                    self.memory.standstill_for += 1
                else:
                    self.memory.standstill_for = 1
                if self.memory.standstill_for % 10 == 5 and \
                        (not self.memory.filling
                         or not _.find(self.room.find_in_range(FIND_MY_CREEPS, 1, self.pos),
                                       lambda c: c.memory.role != role_hauler and c.memory.role != role_miner)):
                    del self.memory.next_ppos
                    found_mine = False
                    for pos in self.hive.honey.find_path(origin, target, opts):
                        if pos.x == self.pos.x and pos.y == self.pos.y:
                            found_mine = True
                        elif found_mine:
                            if movement.is_block_clear(self.room, pos.x,
                                                       pos.y):
                                self.memory.next_ppos = {
                                    "x": pos.x,
                                    "y": pos.y,
                                    "roomName": self.pos.roomName
                                }
                                self.move_to(
                                    __new__(
                                        RoomPosition(pos.x, pos.y,
                                                     self.pos.roomName)))
                                break
            elif not self.creep.fatigue:
                self.memory.last_pos = serialized_pos
                del self.memory.standstill_for
Example #30
0
    def run_squad(self, members, target):
        # type: (List[SquadDrone], Location) -> None
        if movement.chebyshev_distance_room_pos(self.pos, target) > 150:
            return
        opts = get_opts(self.pos.roomName)
        self.log("running with opts {}", JSON.stringify(opts))
        owner = stored_data._find_room_owner(self.room.room)
        if (owner and (Memory.meta.friends.includes(owner.name.lower())
                       or owner.name == self.creep.owner.username)):
            return

        next_pos = None

        path = _.get(self.memory, ['_move', 'path'])
        if path:
            next_pos = self.creep.findNextPathPos(path)
            if not _.isObject(next_pos) or not self.pos.isNearTo(next_pos):
                next_pos = None

        if next_pos is None and self.creep.__direction_moved:
            next_pos = movement.apply_direction(self.pos,
                                                self.creep.__direction_moved)

        if next_pos is not None:
            best_structure = cast(
                Structure,
                _.find(self.room.look_at(LOOK_STRUCTURES, next_pos),
                       get_dismantle_condition_not_a_road(opts)))
            if best_structure:
                result = self.creep.dismantle(best_structure)
                if result != OK:
                    self.log("Unknown result from {}.dismantle({}): {}",
                             self.creep, best_structure, result)
                if result != ERR_NOT_IN_RANGE:
                    return
        elif next_pos == ERR_NOT_FOUND:
            del self.memory['_move']
        structures_around = cast(
            List[Dict[str, Structure]],
            self.room.look_for_in_area_around(LOOK_STRUCTURES, self.pos, 1))
        best_structure = None
        our_dismantle_power = DISMANTLE_POWER * self.creep.getActiveBodypartsBoostEquivalent(
            WORK, 'dismantle')
        if len(structures_around) > 1:
            ramparts_at = None
            for structure_obj in structures_around:
                if structure_obj[
                        LOOK_STRUCTURES].structureType == STRUCTURE_RAMPART:
                    if ramparts_at is None:
                        ramparts_at = {}
                    ramparts_at[positions.serialize_pos_xy(structure_obj[LOOK_STRUCTURES].pos)] \
                        = structure_obj[LOOK_STRUCTURES].hits
            best_rank = -Infinity
            for structure_obj in cast(
                    List[Dict[str, Structure]],
                    self.room.look_for_in_area_around(LOOK_STRUCTURES,
                                                      self.pos, 1)):
                structure = structure_obj[LOOK_STRUCTURES]
                if not can_target_struct(structure, opts):
                    continue
                structure_type = structure.structureType
                if structure_type == STRUCTURE_TOWER:
                    rank = 55
                elif structure_type == STRUCTURE_SPAWN:
                    rank = 50
                elif structure_type == STRUCTURE_LAB:
                    rank = 45
                elif structure_type == STRUCTURE_EXTENSION:
                    rank = 40
                elif structure_type == STRUCTURE_LINK:
                    rank = 30
                else:
                    rank = 10

                hits = structure.hits

                if structure_type != STRUCTURE_RAMPART and ramparts_at:
                    rampart = ramparts_at[positions.serialize_pos_xy(
                        structure.pos)]
                    if rampart and rampart.hits:
                        hits += rampart.hits

                if hits < our_dismantle_power:
                    rank -= hits / our_dismantle_power
                if rank > best_rank:
                    best_rank = rank
                    best_structure = structure
        elif len(structures_around):
            best_structure = structures_around[0][LOOK_STRUCTURES]
            if not can_target_struct(best_structure, opts):
                return
        else:
            return

        if best_structure:
            result = self.creep.dismantle(best_structure)
            volatile_cache.mem('dismantle_squad_dismantling').set(
                target.name, best_structure)
            if result == OK:
                if best_structure.hits < our_dismantle_power \
                        or best_structure.hits < our_dismantle_power + _.sum(
                            members, lambda x: x.creep.getActiveBodypartsBoostEquivalent(RANGED_ATTACK, 'rangedAttack')
                                    * RANGED_ATTACK_POWER):
                    del self.memory._move
            else:
                self.log("Unknown result from {}.dismantle({}): {}".format(
                    self.creep, best_structure, result))