Example #1
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 #2
0
 def find_home(self):
     # type: () -> RoomPosition
     spawn = self.home.spawn
     if spawn:
         return spawn.pos
     else:
         return movement.find_an_open_space(self.home.name)
Example #3
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 #4
0
    def run(self):
        claim_room = self.find_claim_room()
        if not claim_room:
            self.creep.suicide()
            return

        if self.pos.roomName != claim_room:
            if Game.rooms[claim_room]:
                target = Game.rooms[claim_room].controller.pos
            else:
                target = movement.find_an_open_space(claim_room)
            self.follow_energy_path(self.home.spawn, target)
            self.check_move_parts()
            return

        controller = self.room.room.controller

        if not controller:
            del self.memory.claiming
            return True

        if controller.reservation and controller.reservation.ticksToEnd > 4999:
            if self.pos.isNearTo(controller):
                self.creep.suicide()
                return False
            else:
                del self.memory.claiming
                return True

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

        if controller.reservation and controller.reservation.username != self.creep.owner.username:
            self.log(
                "Remote reserve creep target owned by another player! {} has taken our reservation!",
                controller.reservation.username)
        else:
            self.creep.reserveController(controller)
            if Game.time % 5 == 2 and controller.reservation:
                stored_data.set_reservation_time(
                    self.pos.roomName, controller.reservation.ticksToEnd)
Example #5
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 #6
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 #7
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 #8
0
    def run(self):
        target_id = self.memory.attack_target
        if not target_id:
            best_id = None
            closest_distance = Infinity
            for hostile in self.room.defense.dangerous_hostiles():
                distance = movement.chebyshev_distance_room_pos(
                    self.pos, hostile.pos)
                if distance < closest_distance:
                    best_id = hostile.id
                    closest_distance = distance
            if not best_id:
                for mem_hostile in self.home.defense.remote_hostiles():
                    distance = movement.chebyshev_distance_room_pos(
                        self.pos,
                        positions.deserialize_xy_to_pos(
                            mem_hostile.pos, mem_hostile.room))
                    if mem_hostile.ranged and not mem_hostile.attack:
                        distance += 1000  # Don't go after kiting attackers
                    if distance < closest_distance:
                        best_id = mem_hostile.id
                        closest_distance = distance
            if best_id:
                target_id = best_id
                self.memory.attack_target = best_id
            else:
                self.memory.role = role_recycling
                self.memory.last_role = role_defender
                return False

        hostile_info = Memory.hostiles[target_id]
        if not hostile_info or Game.time >= hostile_info.dead:
            del self.memory.attack_target
            return True

        hostile_room = hostile_info.room
        hostile_pos = positions.deserialize_xy_to_pos(hostile_info.pos,
                                                      hostile_room)

        if self.pos.roomName != hostile_room:
            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)

            if 'enemy_checkpoint' in self.memory:
                enemy_checkpoint = self.memory.enemy_checkpoint
                if movement.chebyshev_distance_room_pos(
                        enemy_checkpoint, hostile_pos) > 10:
                    enemy_checkpoint = self.memory.enemy_checkpoint = hostile_pos
            else:
                enemy_checkpoint = self.memory.enemy_checkpoint = hostile_pos

            self.follow_military_path(
                _.create(RoomPosition.prototype, self.memory.checkpoint),
                _.create(RoomPosition.prototype, enemy_checkpoint),
                {'range': 1})
            return False

        target = cast(Creep, Game.getObjectById(target_id))

        if target is None or (self.room.hostile
                              and target.owner.username != INVADER_USERNAME):
            del self.memory.attack_target
            del Memory.hostiles[target_id]
            if hostile_room in Memory.rooms:
                room_hostiles = Memory.rooms[hostile_room][
                    rmem_key_stored_hostiles]
                index = _.findIndex(room_hostiles, lambda x: x.id == target_id)
                if index != -1:
                    room_hostiles.splice(index, 1)
            return True

        if self.pos.isNearTo(target):
            self.creep.attack(target)
        else:
            self.move_to(target, {'reusePath': 2})