def pathfinder_enemy_array_for_room(room_name): # type: (str) -> List[Dict[str, Any]] cache = volatile_cache.mem("enemy_lists") if cache.has(room_name): return cache.get(room_name) my = is_room_mostly_safe(room_name) enemy_positions = [] for h in defense.stored_hostiles_near(room_name): if not is_room_mostly_safe(room_name): if h.user == INVADER_USERNAME: if my: enemy_range = 2 else: enemy_range = 5 elif h.ranged or h.attack: enemy_range = 10 else: continue elif h.user == INVADER_USERNAME: enemy_range = 5 elif h.ranged: enemy_range = 7 elif h.attack: enemy_range = 5 else: continue pos = __new__(RoomPosition(h.pos & 0x3F, h.pos >> 6 & 0x3F, h.room)) # NOTE: here we multiply by two, so that when we pass this array to the PathFinder we'll get a better path. enemy_positions.append({"pos": pos, "range": enemy_range * 4}) cache.set(room_name, enemy_positions) return enemy_positions
def find_new_target_extension(targets, creep): # type: (TargetMind, RoleBase) -> Optional[str] closest_distance = Infinity best_id = None stealing_from = None structures = cast( List[Union[StructureExtension, StructureSpawn]], _.filter( creep.home.find(FIND_MY_STRUCTURES), lambda s: ((s.structureType == STRUCTURE_EXTENSION or s.structureType == STRUCTURE_SPAWN) and s.energy < s.energyCapacity))) if len(structures): for structure in structures: structure_id = structure.id if volatile_cache.mem("extensions_filled").has(structure_id): continue current_carry = targets.workforce_of(target_spawn_deposit, structure_id) distance = movement.distance_squared_room_pos( structure.pos, creep.creep.pos) if distance < closest_distance: max_to_deposit = structure.energyCapacity / 50.0 if not current_carry or current_carry < max_to_deposit: closest_distance = distance best_id = structure_id stealing_from = None else: targeting = targets.reverse_targets[target_spawn_deposit][ structure_id] if len(targeting): for name in targeting: if not Game.creeps[ name] or movement.distance_squared_room_pos( Game.creeps[name].pos, structure.pos) > distance * 2.25: # If we're at least 1.5x closer than them, let's steal their place. # Note that 1.5^2 is 2.25, which is what we should be using since we're comparing # squared distances. d1 > d2 * 1.5 is equivalent to d1^2 > d2^2 * 1.5^2 which is # equivalent to d1^2 > d2^2 * 2.25 closest_distance = distance best_id = structure_id stealing_from = name break else: closest_distance = distance best_id = structure_id stealing_from = None if stealing_from is not None: targets.unregister_name(stealing_from, target_spawn_deposit) elif creep.home.full_storage_use: flag_list = flags.find_flags(creep.home, SPAWN_FILL_WAIT) if len(flag_list): best_id = _(flag_list).map(lambda f: "flag-{}".format(f.name)) \ .min(lambda fid: targets.reverse_targets[target_spawn_deposit][fid] or 0) if best_id is Infinity: best_id = None return best_id
def room_hostile(room_name): # type: (str) -> bool cache = volatile_cache.mem("rua") if cache.has(room_name): return cache.get(room_name) # This will only get "active" hostiles, which doesn't count source keepers, or non-ATTACK/RANGED_ATTACK creeps in # owned rooms. room_under_attack = not not len(defense.stored_hostiles_in(room_name)) cache.set(room_name, room_under_attack) return room_under_attack
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)
def enemy_purposes_cost_matrix(room_name): # type: (str) -> PathFinder.CostMatrix cache = volatile_cache.mem("super_simple_cost_matrix") if cache.has(room_name): return cache.get(room_name) room = context.hive().get_room(room_name) if not room: return __new__(PathFinder.CostMatrix()) cost_matrix = __new__(PathFinder.CostMatrix()) for struct in cast(List[Structure], room.find(FIND_STRUCTURES)): if struct.structureType != STRUCTURE_ROAD and struct.structureType != STRUCTURE_CONTAINER \ and (struct.structureType != STRUCTURE_RAMPART or cast(StructureRampart, struct).my): cost_matrix.set(struct.pos.x, struct.pos.y, 255) cache.set(room_name, cost_matrix) return cost_matrix
def simple_cost_matrix(room_name): # type: (str) -> Union[PathFinder.CostMatrix, bool] cache = volatile_cache.mem("enemy_cost_matrix") # TODO: some of this is duplicated in honey.HoneyTrails room = context.hive().get_room(room_name) if not room: if room_hostile(room_name) or hostile_utils.enemy_using_room( room_name): return False else: return __new__(PathFinder.CostMatrix()) # The basic cost matrix already has impassable things on it, and already has SK lairs avoided, but does not # have any non-hostile creeps. It also already has exits marked. cost_matrix = walkby_move.get_basic_cost_matrix(room_name, False) def wall_at(x, y): return Game.map.getTerrainAt(x, y, room_name) == 'wall' def set_in_range(pos, drange, value, increase_by_center): for x in range(pos.x - drange, pos.x + drange + 1): for y in range(pos.y - drange, pos.y + drange + 1): if not wall_at(x, y) and cost_matrix.get(x, y) < value: cost_matrix.set(x, y, value) if increase_by_center > 0 and drange > 0: set_in_range(pos, drange - 1, value + increase_by_center, increase_by_center) for creep in room.find(FIND_CREEPS): set_in_range(creep.pos, 1, 5, 0) cost_matrix.set(creep.pos.x, creep.pos.y, 255) for creep in room.find(FIND_HOSTILE_CREEPS): set_in_range(creep.pos, 7, 2, 7) cost_matrix.set(creep.pos.x, creep.pos.y, 255) cache.set(room_name, cost_matrix) return cost_matrix
def kiting_cost_matrix(room_name, target): # type: (str, Flag) -> Union[PathFinder.CostMatrix, bool] cache = volatile_cache.mem("kiting_cost_matrix") if cache.has(room_name): return cache.get(room_name) if hostile_utils.enemy_using_room(room_name) and room_name != target.pos.roomName: return False # TODO: some of this is duplicated in honey.HoneyTrails cost_matrix = __new__(PathFinder.CostMatrix()) def set_in_range_xy(initial_x, initial_y, distance, value, increase_by_center): for x in range(initial_x - distance, initial_x + distance + 1): for y in range(initial_y - distance, initial_y + distance + 1): if increase_by_center: value_here = value + increase_by_center \ * (distance - movement.chebyshev_distance_xy(initial_x, initial_y, x, y)) else: value_here = value existing_cost = cost_matrix.get(x, y) if existing_cost == 0: terrain_here = Game.map.getTerrainAt(x, y, room_name) if terrain_here[0] == 'p': existing_cost = 1 elif terrain_here[0] == 's': existing_cost = 25 elif terrain_here[0] == 'w': continue cost_matrix.set(x, y, existing_cost + value_here) def set_in_range(pos, distance, value, increase_by_center): pos = pos.pos or pos set_in_range_xy(pos.x, pos.y, distance, value, increase_by_center) room = context.hive().get_room(room_name) if room: any_lairs = False for struct in cast(List[OwnedStructure], room.find(FIND_STRUCTURES)): if struct.structureType == STRUCTURE_ROAD: cost_matrix.set(struct.pos.x, struct.pos.y, 1) elif struct.structureType != STRUCTURE_CONTAINER and (struct.structureType != STRUCTURE_RAMPART or not struct.my): if struct.structureType == STRUCTURE_KEEPER_LAIR: any_lairs = True cost_matrix.set(struct.pos.x, struct.pos.y, 255) for creep in room.find(FIND_MY_CREEPS): cost_matrix.set(creep.pos.x, creep.pos.y, 255) if any_lairs: for source in room.find(FIND_SOURCES): set_in_range(source.pos, 4, 255, 0) for mineral in room.find(FIND_MINERALS): set_in_range(mineral.pos, 4, 255, 0) else: data = stored_data.get_data(room_name) if data: for obstacle in data.obstacles: if obstacle.type == StoredObstacleType.ROAD: cost_matrix.set(obstacle.x, obstacle.y, 1) elif obstacle.type == StoredObstacleType.SOURCE_KEEPER_LAIR \ or obstacle.type == StoredObstacleType.SOURCE_KEEPER_SOURCE \ or obstacle.type == StoredObstacleType.SOURCE_KEEPER_MINERAL: set_in_range(obstacle, 4, 255, 0) else: cost_matrix.set(obstacle.x, obstacle.y, 255) for info in defense.stored_hostiles_in(room_name): x, y = positions.deserialize_xy(info.pos) set_in_range_xy(x, y, 3, 5, 10) cost_matrix.set(x, y, 255) for x in [0, 49]: for y in range(0, 49): existing = cost_matrix.get(x, y) if existing == 0: terrain = Game.map.getTerrainAt(x, y, room_name) if terrain[0] == 'p': existing = 1 elif terrain[0] == 's': existing = 25 else: continue # wall cost_matrix.set(x, y, existing + 5) for y in [0, 49]: for x in range(0, 49): existing = cost_matrix.get(x, y) if existing == 0: terrain = Game.map.getTerrainAt(x, y, room_name) if terrain[0] == 'p': existing = 1 elif terrain[0] == 's': existing = 25 else: continue # wall cost_matrix.set(x, y, existing + 5) cache.set(room_name, cost_matrix) return cost_matrix
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))
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
def refill_creeps(self): # type: () -> bool if not self.creep.carry[RESOURCE_ENERGY]: self.memory.filling = True return True target = cast(Union[Creep, Structure, None], self.targets.get_new_target(self, target_refill)) if target: full = robjs.capacity( target) and robjs.energy(target) >= robjs.capacity(target) if full: self.targets.untarget(self, target_refill) target = self.targets.get_new_target(self, target_refill) if target: if not self.pos.isNearTo(target): self.move_to(target) if Game.cpu.bucket >= 4000: other = _.find( self.home.find_in_range(FIND_MY_STRUCTURES, 1, self.pos), lambda c: (c.energyCapacity and c.energy < c.energyCapacity) or (c.storeCapacity and _.sum(c.store) < c.storeCapacity)) if not other: other = _.find( self.home.find_in_range(FIND_MY_CREEPS, 1, self.pos), lambda c: c.name != self.name and (c.memory.role == role_builder or c.memory.role == role_upgrader) and _.sum(c.carry ) < c.carryCapacity) if other: result = self.creep.transfer(cast(Structure, other), RESOURCE_ENERGY) if result == ERR_NOT_ENOUGH_RESOURCES: self.memory.filling = True return True elif result != OK: self.log( "Unknown result from passingby refill.transfer({}): {}", other, result) return False latched = False target_creep = cast(Creep, target) if self.creep.hasActiveBodyparts( WORK ) and target_creep.memory and not target_creep.memory.filling: # Let's latch on and work on whatever they're working on role = target_creep.memory.role result = None latched_target = None if role == role_builder: sc_last_action = target_creep.memory.la if sc_last_action == "r": latched_target = cast( Structure, self.targets.get_existing_target( target_creep, target_repair)) if latched_target: result = self.creep.repair(latched_target) elif sc_last_action == "c": latched_target = cast( ConstructionSite, self.targets.get_existing_target( target_creep, target_construction)) if latched_target: result = self.creep.build(latched_target) elif sc_last_action == "b": latched_target = cast( Structure, self.targets.get_existing_target( target_creep, target_big_repair)) if latched_target: result = self.creep.repair(latched_target) elif role == role_upgrader: latched_target = self.home.room.controller result = self.creep.upgradeController(latched_target) if result is not None: if result == OK: latched = True elif result == ERR_NOT_IN_RANGE: self.basic_move_to(latched_target) if Game.cpu.bucket >= 8000 and target_creep.carry: min_cap = 0 other = target_creep for obj in cast( List[Dict[str, Creep]], self.home.look_for_in_area_around( LOOK_CREEPS, self.pos, 1)): creep = obj[LOOK_CREEPS] if (creep.memory.role == role_builder or creep.memory.role == role_upgrader) \ and creep.name != self.name: empty_percent = (creep.carryCapacity - _.sum( creep.carry)) / creep.carryCapacity if empty_percent > min_cap: other = creep min_cap = empty_percent for obj in cast( List[Dict[str, Structure]], self.home.look_for_in_area_around( LOOK_STRUCTURES, self.pos, 1)): structure = obj[LOOK_STRUCTURES] if structure.structureType == STRUCTURE_EXTENSION or structure.structureType == STRUCTURE_SPAWN: structure = cast( Union[StructureSpawn, StructureExtension], structure) empty_percent = 0.1 * ( structure.energyCapacity - structure.energy) / structure.energyCapacity if empty_percent > 0.1 and empty_percent > min_cap: other = structure min_cap = empty_percent if other != target: result = self.creep.transfer(other, RESOURCE_ENERGY) if result != OK: self.log( "Unknown result from passingby refill.transfer({}): {}", other, result) return False result = self.creep.transfer(target, RESOURCE_ENERGY) if result == OK: target_empty = robjs.capacity(target) - robjs.energy(target) if not latched and self.creep.carry[ RESOURCE_ENERGY] > target_empty: volatile_cache.mem("extensions_filled").set( target.id, True) if self.creep.carry[RESOURCE_ENERGY] - target_empty > 0: self.targets.untarget(self, target_refill) new_target = self.targets.get_new_target( self, target_refill) if new_target and not self.pos.isNearTo(new_target): self.move_to(new_target) elif result == ERR_FULL: if not latched: self.targets.untarget(self, target_refill) return True else: self.log("Unknown result from refill.transfer({}): {}", target, result) self.targets.untarget(self, target_refill) return False else: self.go_to_depot() if not self.home.spawn: return False # haha, total hack... if not self.home.spawn.spawning and self.home.get_next_role( ) is None: self.home.mem[ rmem_key_planned_role_to_spawn] = generate_role_obj( self.home) else: v = volatile_cache.volatile() if v.has("refills_idle"): idle = v.get("refills_idle") + 1 else: idle = 1 if idle >= 3: role = self.home.get_next_role() if not role or ( (role[roleobj_key_role] == role_hauler or role[roleobj_key_role] == role_spawn_fill) and (self.home.get_target_builder_work_mass() or self.home.get_target_upgrader_work_mass()) ) or idle >= 7: self.home.mem[ rmem_key_planned_role_to_spawn] = generate_role_obj( self.home) v.set("refills_idle", -Infinity) else: v.set("refills_idle", idle)
def find_new_target_refill_destination(targets, creep): # type: (TargetMind, RoleBase) -> Optional[str] best_priority = Infinity best_id = None stealing_from = None structures = _.filter( creep.home.find(FIND_MY_STRUCTURES), lambda s: (s.structureType == STRUCTURE_EXTENSION or s.structureType == STRUCTURE_SPAWN or s.structureType == STRUCTURE_CONTAINER or s. structureType == STRUCTURE_TOWER) and s.energy < s.energyCapacity) creeps = _.filter( creep.home.creeps, lambda c: (c.memory.role == role_upgrader or c.memory.role == role_builder ) and c.carry.energy < c.carryCapacity) extra = creep.home.get_extra_fill_targets() for structure in structures.concat(extra).concat(creeps): structure_id = structure.id if volatile_cache.mem("extensions_filled").has(structure_id): continue current_carry = targets.workforce_of(target_spawn_deposit, structure_id) \ + targets.workforce_of(target_refill, structure_id) empty = ((structure.energyCapacity or structure.carryCapacity or structure.storeCapacity) - ((structure.store and _.sum(structure.store.energy)) or (structure.carry and _.sum(structure.carry.energy)) or structure.energy or 0)) empty_percent = empty / (structure.energyCapacity or structure.carryCapacity or structure.storeCapacity) \ * 30 if empty <= 0 or (empty <= 2 and not structure.structureType): continue distance = movement.chebyshev_distance_room_pos( structure.pos, creep.creep.pos) priority = distance - empty_percent if structure.memory and not structure.memory.filling: priority -= 15 elif structure.structureType == STRUCTURE_CONTAINER: priority -= 40 elif structure.structureType: priority -= 25 if priority < best_priority: max_work_mass = empty / 50 if not current_carry or current_carry < max_work_mass: best_priority = priority best_id = structure_id stealing_from = None else: targeting = targets.reverse_targets[target_refill][ structure_id] if len(targeting): for name in targeting: if not Game.creeps[ name] or movement.chebyshev_distance_room_pos( Game.creeps[name].pos, structure.pos) > distance * 1.5: # If we're at least 1.5x closer than them, let's steal their place. best_priority = priority best_id = structure_id stealing_from = name break if stealing_from is not None: targets.unregister_name(stealing_from, target_refill) return best_id