示例#1
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
示例#2
0
 def force_basic_move_to(self, target, creep_cond=lambda x: True):
     # type: (Union[RoomObject, RoomPosition], Callable[[Creep], bool]) -> bool
     """
     Tries to do a basic move in the direction, forcing place switching with an creep for which creep_cond(creep) returns True.
     :param target: The location (pos or object with pos property) to move to
     :param creep_cond: The condition with which this creep will take the place of another creep (default is "lambda x: True")
     :return: True if moved, False otherwise.
     """
     if self.creep.fatigue > 0:
         return True
     target = robjs.pos(target)
     if self.pos.isNearTo(target):
         return True
     adx = target.x - self.pos.x
     ady = target.y - self.pos.y
     dx = Math.sign(adx)
     dy = Math.sign(ady)
     if dx and dy:
         if self._try_force_move_to(self.pos.x + dx, self.pos.y + dy,
                                    creep_cond):
             return True
         elif adx == 1 and ady == 1:
             return False
         elif self._try_force_move_to(self.pos.x + dx, self.pos.y,
                                      creep_cond):
             return True
         elif self._try_force_move_to(self.pos.x, self.pos.y + dy,
                                      creep_cond):
             return True
     elif dx:
         if self._try_force_move_to(self.pos.x + dx, self.pos.y,
                                    creep_cond):
             return True
         elif adx == 1:
             return False
         elif self._try_force_move_to(self.pos.x + dx, self.pos.y + 1,
                                      creep_cond):
             return True
         elif self._try_force_move_to(self.pos.x + dx, self.pos.y - 1,
                                      creep_cond):
             return True
     elif dy:
         if self._try_force_move_to(self.pos.x, self.pos.y + dy,
                                    creep_cond):
             return True
         elif ady == 1:
             return False
         elif self._try_force_move_to(self.pos.x + 1, self.pos.y + dy,
                                      creep_cond):
             return True
         elif self._try_force_move_to(self.pos.x - 1, self.pos.y + dy,
                                      creep_cond):
             return True
     return False
示例#3
0
    def set_origin(self, origin):
        # type: (Union[RoomPosition, RoomObject]) -> None
        origin = robjs.pos(origin)
        origin = __new__(RoomPosition(origin.x, origin.y, origin.roomName))

        self.__origin = origin

        self.mem[squadmemkey_origin] = {
            'xy': positions.serialize_pos_xy(origin),
            'room': origin.roomName
        }
示例#4
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)
示例#5
0
    def move_to(self, _target, opts=None):
        # type: (Union[RoomPosition, RoomObject, RoleBase], Dict[str, Any]) -> None
        if self.creep.fatigue <= 0:
            target = robjs.pos(_target)
            result = self._try_move_to(target, opts)

            if result == ERR_NO_BODYPART:
                self.log("Couldn't move, all move parts dead!")
                if not (self.room.my and self.room.defense.healing_capable()) and \
                        not _.some(self.room.find(FIND_MY_CREEPS), lambda c: c.hasActiveBodyparts(HEAL)):
                    self.creep.suicide()
                    self.home.check_all_creeps_next_tick()
            elif result != OK:
                if result != ERR_NOT_FOUND and (
                        result != ERR_NO_PATH or
                    (self.pos.x != 49 and self.pos.y != 49 and self.pos.x != 0
                     and self.pos.y != 0)):
                    self.log(
                        "WARNING: Unknown result from ({} at {}:{},{}).moveTo({}:{},{} ({})): {}",
                        self.memory.role, self.pos.roomName, self.pos.x,
                        self.pos.y, target.roomName, target.x, target.y,
                        target, result)
示例#6
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
示例#7
0
 def basic_move_to(self, target):
     # type: (Union[RoomPosition, RoomObject]) -> bool
     if self.creep.fatigue > 0:
         return True
     pos = robjs.pos(target)
     if self.pos.isEqualTo(target):
         return False
     adx = pos.x - self.pos.x
     ady = pos.y - self.pos.y
     if pos.roomName != self.pos.roomName:
         room1x, room1y = movement.parse_room_to_xy(self.pos.roomName)
         room2x, room2y = movement.parse_room_to_xy(pos.roomName)
         adx += (room2x - room1x) * 50
         ady += (room2y - room1y) * 50
     dx = Math.sign(adx)
     dy = Math.sign(ady)
     if dx and dy:
         if movement.is_block_clear(self.room, self.pos.x + dx,
                                    self.pos.y + dy):
             self.creep.move(movement.dxdy_to_direction(dx, dy))
             return True
         elif adx == 1 and ady == 1:
             return False
         elif movement.is_block_clear(self.room, self.pos.x + dx,
                                      self.pos.y):
             self.creep.move(movement.dxdy_to_direction(dx, 0))
             return True
         elif movement.is_block_clear(self.room, self.pos.y + dy,
                                      self.pos.x):
             self.creep.move(movement.dxdy_to_direction(0, dy))
             return True
     elif dx:
         if movement.is_block_clear(self.room, self.pos.x + dx, self.pos.y):
             self.creep.move(movement.dxdy_to_direction(dx, 0))
             return True
         elif adx == 1:
             return False
         elif movement.is_block_clear(self.room, self.pos.x + dx,
                                      self.pos.y + 1):
             self.creep.move(movement.dxdy_to_direction(dx, 1))
             return True
         elif movement.is_block_clear(self.room, self.pos.x + dx,
                                      self.pos.y - 1):
             self.creep.move(movement.dxdy_to_direction(dx, -1))
             return True
     elif dy:
         if movement.is_block_clear(self.room, self.pos.x, self.pos.y + dy):
             self.creep.move(movement.dxdy_to_direction(0, dy))
             return True
         elif ady == 1:
             return False
         elif movement.is_block_clear(self.room, self.pos.x + 1,
                                      self.pos.y + dy):
             self.creep.move(movement.dxdy_to_direction(1, dy))
             return True
         elif movement.is_block_clear(self.room, self.pos.x - 1,
                                      self.pos.y + dy):
             self.creep.move(movement.dxdy_to_direction(-1, dy))
             return True
     if dx or dy:
         self.creep.move(movement.dxdy_to_direction(dx, dy))
     return False
示例#8
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