def open_spaces_around(self, flag): # type: (Flag) -> int if 'osa' not in flag.memory: osa = 0 room = self.hive.get_room(flag.pos.roomName) for x in range(flag.pos.x - 1, flag.pos.x + 2): for y in range(flag.pos.y - 1, flag.pos.y + 2): if room: if movement.is_block_empty(room, x, y): osa += 1 else: if Game.map.getTerrainAt(x, y, flag.pos.roomName) != 'wall': osa += 1 flag.memory.osa = osa return flag.memory.osa
def run(self): destination = cast( Flag, self.targets.get_existing_target(self, target_single_flag)) if not destination: if not self.memory.idle_for: self.log("WARNING: Scout does not have destination set!") self.memory.idle_for = 1 else: self.memory.idle_for += 1 if self.memory.idle_for >= 10: self.log("Scout idle for 10 ticks, committing suicide.") self.creep.suicide() return still_exploring = ('explored_at' not in destination.memory) \ or positions.serialize_xy_room_pos(destination.pos) != destination.memory.explored_at recalc = False if still_exploring: # recalculate_path if self.memory.rp: self.log( "Recalculating path due to circumstances in {}.".format( self.memory.rp)) self.recalc_military_path(self.home.spawn.pos, destination.pos, { "ignore_swamp": True, "use_roads": False, }) del self.memory.rp if self.memory.last_room != self.pos.roomName: self.memory.last_room = self.pos.roomName if self.room.enemy and self.pos.roomName != destination.pos.roomName: self.recalc_military_path(self.home.spawn.pos, destination.pos, { "ignore_swamp": True, "use_roads": False, }) last_updated = stored_data.get_last_updated_tick( self.pos.roomName) if not last_updated or Game.time - last_updated > 100: if movement.is_room_inner_circle_of_sector( self.pos.roomName): lair_count = 0 # should be a source keeper room for lair in cast( List[Structure], self.room.find(FIND_HOSTILE_STRUCTURES)): if lair.structureType == STRUCTURE_KEEPER_LAIR: lair_count += 1 if lair_count > 0: # recalculate_path_next recalc = True self.memory.rp = self.pos.roomName else: self.log( "WARNING: Scout found no lairs in supposed source keeper room {}! Logic error?" .format(self.pos.roomName)) stored_data.update_data(self.room.room) self.log("scouted room: {}".format(self.pos.roomName)) if self.pos.isEqualTo(destination) or \ (self.pos.isNearTo(destination) and not movement.is_block_empty(self.room, destination.pos.x, destination.pos.y)): if still_exploring: destination.memory.travel_time = CREEP_LIFE_TIME - self.creep.ticksToLive self.log("Arrived at {} ({}), traveling from {} in {} ticks.". format(destination, destination.pos, self.home.spawn, destination.memory.travel_time)) destination.memory.explored_at = positions.serialize_xy_room_pos( destination.pos) elif self.pos.isNearTo(destination): self.basic_move_to(destination) else: self.follow_military_path(self.home.spawn.pos, destination.pos, { "ignore_swamp": True, "use_roads": False, }) if recalc: self.log("Recalculating path due.") self.recalc_military_path(self.home.spawn.pos, destination.pos, { "ignore_swamp": True, "use_roads": False }) if self.pos.roomName == destination.pos.roomName and destination.memory.activate_attack_in: if len(self.room.defense.dangerous_hostiles()) and _.sum( self.room.defense.dangerous_hostiles(), lambda h: h.owner.username != INVADER_USERNAME and _.sum( h.body, lambda p: p.type == ATTACK or p.type == RANGED_ATTACK or p.type == HEAL)) >= 10: rooms_newly_activated = [] for name in destination.memory.activate_attack_in: activate_attack_in = self.hive.get_room(name) if activate_attack_in: activate_attack_in.defense.activate_live_defenses() rooms_newly_activated.push(name) else: self.log( "WARNING: Couldn't find room {} which flag {} is supposed to alert for attack." .format(name, destination.name)) if len(rooms_newly_activated): with_mining_op_shutdowns = _.filter( rooms_newly_activated, lambda r: not _.get( Memory, ["rooms", r, "remotes_safe"], False)) hostiles = self.room.defense.dangerous_hostiles() message = ( "\nDANGER: -----" "\nHostile belonging to player {} detected in room {}. Game time: {}" "\n" "\n{}" "\n" "\nThis has triggered active-defense mode in rooms {}{}." "\nDANGER: -----" ).format( hostiles[0].owner.username, self.pos.roomName, Game.time, "\n".join([ "Found hostile with hits {}/{}, owner {}, body [{}]" .format(h.hits, h.hitsMax, h.owner.username, [("{}:{}".format(p.boost, p.type) if p.boost else p.type) for p in h.body]) for h in hostiles ]), rooms_newly_activated, (", and shut down mining operations in rooms {}". format(with_mining_op_shutdowns) if len(with_mining_op_shutdowns) else ""), ) print(message) Game.notify(message)
def run(self): link = self.home.links.main_link storage = self.home.room.storage if not link or not storage: self.log( "ERROR: Link manager can't find main link or storage in {}.". format(self.home.name)) self.go_to_depot() return False # Note: this does assume storage is directly within one space of the main link. if 'station_pos' not in self.memory: secondary = self.home.links.secondary_link best_priority = 0 best = None for x in range(link.pos.x - 1, link.pos.x + 2): for y in range(link.pos.y - 1, link.pos.y + 2): if -1 <= x - storage.pos.x <= 1 and -1 <= y - storage.pos.y <= 1 \ and (storage.pos.x != x or storage.pos.y != y) \ and (link.pos.x != x or link.pos.y != y): if not movement.is_block_empty(self.home, x, y): continue creeps = cast(List[Creep], self.home.look_at(LOOK_CREEPS, x, y)) if len(creeps) != 0: creep = creeps[0] if creep.memory.role == role_link_manager: if self.creep.ticksToLive > creep.ticksToLive: creep.suicide() else: self.creep.suicide() return False pos = __new__(RoomPosition(x, y, self.home.name)) priority = 1 if secondary and movement.chebyshev_distance_xy( secondary.pos.x, secondary.pos.y, x, y) <= 1: priority += 20 if link.pos.x == storage.pos.x == pos.x: priority += 5 elif link.pos.y == storage.pos.y == pos.y: priority += 5 if priority >= best_priority: best = pos best_priority = priority if best is None: self.go_to_depot() return False self.memory.station_pos = best.x | best.y << 6 current_pos = (self.pos.x | self.pos.y << 6) if current_pos != self.memory.station_pos: self.move_to( __new__( RoomPosition(self.memory.station_pos & 0x3F, self.memory.station_pos >> 6 & 0x3F, self.home.name))) return False if self.ensure_no_minerals(): return False half_capacity = int(self.creep.carryCapacity / 2) if self.creep.carry[RESOURCE_ENERGY] != half_capacity: # this is not the norm. if self.creep.carry[RESOURCE_ENERGY] > half_capacity: target = storage result = self.creep.transfer( target, RESOURCE_ENERGY, self.creep.carry[RESOURCE_ENERGY] - half_capacity) if result == ERR_FULL: target = self.home.links.main_link result = self.creep.transfer( target, RESOURCE_ENERGY, self.creep.carry[RESOURCE_ENERGY] - half_capacity) if result == ERR_FULL: secondary = self.home.links.secondary_link if secondary: target = secondary result = self.creep.transfer( target, RESOURCE_ENERGY, self.creep.carry[RESOURCE_ENERGY] - half_capacity) self.ensure_ok(result, "transfer", target, RESOURCE_ENERGY) else: target = storage result = self.creep.withdraw( target, RESOURCE_ENERGY, half_capacity - self.creep.carry[RESOURCE_ENERGY]) if result == ERR_NOT_ENOUGH_RESOURCES: target = self.home.links.main_link result = self.creep.withdraw( target, RESOURCE_ENERGY, half_capacity - self.creep.carry[RESOURCE_ENERGY]) if result == ERR_NOT_ENOUGH_RESOURCES: secondary = self.home.links.secondary_link if secondary: target = secondary result = self.creep.withdraw( target, RESOURCE_ENERGY, half_capacity - self.creep.carry[RESOURCE_ENERGY]) self.ensure_ok(result, "withdraw", target, RESOURCE_ENERGY) return False self.home.links.note_link_manager(self) return False
def run(self): source_flag = cast( Flag, self.targets.get_existing_target(self, target_support_miner_mine)) if not source_flag: if not self.memory.idle_for: self.log("WARNING: Support miner has no target.") self.memory.idle_for = 1 else: self.memory.idle_for += 1 if self.memory.idle_for >= 10: self.log( "Support miner idle for 10 ticks, committing suicide.") self.creep.suicide() return if self.creep.hits < self.creep.hitsMax: if not len(flags.find_flags(self.room.name, RANGED_DEFENSE)) \ or not _.some(self.room.find(FIND_CREEPS), lambda creep: creep.hasActiveBodyparts(HEAL)): if self.home.defense.healing_capable() and ( self.pos.roomName != self.home.name or self.pos.x > 40 or self.pos.y > 40 or self.pos.x < 10 or self.pos.y < 10): self.follow_energy_path(source_flag, self.home.spawn) return elif not self.creep.getActiveBodyparts(WORK): self.creep.suicide() return if self.memory.container_pos: sitting_target = positions.deserialize_xy_to_pos( self.memory.container_pos, source_flag.pos.roomName) else: sitting_target = source_flag.pos distance_away = self.pos.getRangeTo(source_flag) if distance_away > 2: if self.pos.roomName == source_flag.pos.roomName: if distance_away <= 3: total_mass = self.home.mining.get_ideal_miner_workmass_for( source_flag) if self.creep.getActiveBodyparts(WORK) >= total_mass: other_miner = cast( Dict[str, Creep], _.find( self.room.look_for_in_area_around( LOOK_CREEPS, source_flag.pos, 1), lambda c: c.creep.my and c.creep.memory .role == role_support_miner and c.creep. ticksToLive < self.creep.ticksToLive)) if other_miner: other_miner[LOOK_CREEPS].suicide() del self.memory._move self.move_to(sitting_target) else: self.follow_energy_path(self.home.spawn, sitting_target) return False elif distance_away > 1: creep = cast( Optional[Creep], _.find(self.room.look_at(LOOK_CREEPS, sitting_target), lambda c: c.my)) if creep and creep.memory.role == role_support_miner and creep.ticksToLive > 100: self.memory.container_pos = None sitting_target = source_flag.pos self.move_to(sitting_target) return False if 'container_pos' not in self.memory: container = _.find( self.room.find_in_range(FIND_STRUCTURES, 1, source_flag.pos), lambda s: s.structureType == STRUCTURE_CONTAINER) if container: self.memory.container_pos = container.pos.x | ( container.pos.y << 6) else: biggest_pile = _.max( self.room.find_in_range(FIND_DROPPED_RESOURCES, 1, source_flag.pos), lambda e: e.amount) if biggest_pile != -Infinity: self.memory.container_pos = biggest_pile.pos.x | ( biggest_pile.pos.y << 6) else: self.memory.container_pos = None if Game.time % 10 == 0 and self.memory.container_pos is not None: this_pos_to_check = self.pos.x | self.pos.y << 6 # Transcrypt does this incorrectly in an if statement. if this_pos_to_check != self.memory.container_pos: pos = __new__( RoomPosition(self.memory.container_pos & 0x3F, self.memory.container_pos >> 6 & 0x3F, self.pos.roomName)) if _.find( self.room.look_at(LOOK_CREEPS, pos), lambda c: c.my and c.memory. role == role_support_miner and c.ticksToLive > 15): self.memory.container_pos = self.pos.x | self.pos.y << 6 else: self.basic_move_to(pos) sources_list = cast(List[Source], source_flag.pos.lookFor(LOOK_SOURCES)) if not len(sources_list): self.log("Remote mining source flag {} has no sources under it!", source_flag.name) return False source = sources_list[0] # if Game.time % 3 == 2: # ideal_work = source.energyCapacity / ENERGY_REGEN_TIME / HARVEST_POWER # current_work = self.creep.getActiveBodyparts(WORK) # extra_work = current_work - ideal_work # if extra_work != 0: # if extra_work < 0: # current_work = _.sum(self.room.find_in_range(FIND_MY_CREEPS, 1, source_flag.pos), # lambda c: c.memory.role == role_miner and c.getActiveBodyparts(WORK)) # if current_work > source.energy / (source.ticksToRegeneration - 1) / HARVEST_POWER: # return False # skip a tick, to spread it out result = self.creep.harvest(source) if result != OK and result != ERR_NOT_ENOUGH_RESOURCES: self.log("Unknown result from mining-creep.harvest({}): {}", source, result) if self.creep.carryCapacity: if 'link' in self.memory: if self.memory.link is None: return False else: link = cast(StructureLink, Game.getObjectById(self.memory.link)) if link is None or not self.pos.isNearTo(link): del self.memory.link return False else: all_possible_links = cast( List[Union[StructureStorage, StructureLink]], _.filter( self.room.find(FIND_MY_STRUCTURES), lambda s: (s.structureType == STRUCTURE_LINK or s.structureType == STRUCTURE_STORAGE) and abs( s.pos.x - source_flag.pos.x) <= 2 and abs( s.pos.y - source_flag.pos.y) <= 2)) best_priority = 0 # 1-3 best_spot = None link = None for x in range(source_flag.pos.x - 1, source_flag.pos.x + 2): for y in range(source_flag.pos.y - 1, source_flag.pos.y + 2): if movement.is_block_empty(self.room, x, y): link_here = _.find( all_possible_links, lambda s: abs(s.pos.x - x) <= 1 and abs(s.pos.y - y) <= 1) if link_here: if not flags.look_for( self.room, __new__( RoomPosition( x, y, self.pos.roomName)), UPGRADER_SPOT): if _.find( self.room.look_at( LOOK_STRUCTURES, x, y), lambda s: s.structureType == STRUCTURE_RAMPART): priority_here = 3 else: priority_here = 2 else: priority_here = 1 if priority_here > best_priority: best_priority = priority_here best_spot = x | y << 6 link = link_here if best_priority >= 3: break if best_priority >= 3: break if link: self.memory.link = link.id self.memory.container_pos = best_spot else: self.memory.link = None return False if self.creep.carry[ RESOURCE_ENERGY] + self.creep.getActiveBodyparts( WORK) > self.creep.carryCapacity: if link.structureType == STRUCTURE_LINK: self.home.links.register_target_deposit( link, self, self.creep.carry[RESOURCE_ENERGY], 1) self.creep.transfer(link, RESOURCE_ENERGY) return False
def run(self): minerals = cast(List[Mineral], self.home.find(FIND_MINERALS)) if len(minerals) != 1: self.log( "MineralMiner's home has an incomprehensible number of minerals: {}! To the depot it is." .format(len(minerals))) self.go_to_depot() return False mineral = minerals[0] extractor = cast( Optional[StructureExtractor], _.find(self.home.look_at(LOOK_STRUCTURES, mineral.pos), {'structureType': STRUCTURE_EXTRACTOR})) if not extractor or not extractor.my: self.log( "MineralMiner's mineral at {} does not have an extractor. D:". format(mineral.pos)) self.go_to_depot() return False if not self.pos.isNearTo(mineral): self.move_to(mineral) return False if extractor.cooldown <= 0 and self.creep.carryCapacity - self.carry_sum() \ >= 1 * self.creep.getActiveBodyparts(WORK): # let's be sure not to drop any on the ground result = self.creep.harvest(mineral) if result == ERR_NOT_ENOUGH_RESOURCES: self.log("Mineral depleted, going to recycle now!") self.memory.role = role_recycling self.memory.last_role = role_mineral_miner elif result != OK: self.log("Unknown result from creep.harvest({}): {}".format( mineral, result)) else: if 'container' not in self.memory: container = cast( Dict[str, Structure], _.find( self.room.look_for_in_area_around( LOOK_STRUCTURES, mineral.pos, 2), lambda c: c. structure.structureType == STRUCTURE_CONTAINER)) if container: self.memory.container = container[LOOK_STRUCTURES].id if self.memory.container: transfer_target = Game.getObjectById(self.memory.container) if not self.pos.isNearTo(transfer_target): pos = None for x in range(mineral.pos.x - 1, mineral.pos.x + 2): for y in range(mineral.pos.y - 1, mineral.pos.y + 2): if abs(x - transfer_target.pos.x) <= 1 and abs(y - transfer_target.pos.y) <= 1 \ and movement.is_block_empty(self.room, x, y): pos = __new__( RoomPosition(x, y, mineral.pos.roomName)) break if pos: break if pos: self.basic_move_to(pos) return else: hauler = _.find( cast( List[Dict[str, Creep]], self.room.look_for_in_area_around( LOOK_CREEPS, self.pos, 1)), lambda c: c.creep.memory.role == role_mineral_hauler) if hauler: transfer_target = hauler[LOOK_CREEPS] else: return resource = _.findKey(self.creep.carry) if resource: self.creep.transfer(transfer_target, resource)
def move_to_stage_2(self, target): # type: (RoomPosition) -> None """ Stage 2 movement, where we're near the enemy base and we need to keep tight formation. The default method is a tight line, recommended to replace this with something more intricate. """ ordered_members = self.members_movement_order() self.log("Members {} moving to {} - stage 2.", _.pluck(ordered_members, 'name'), target) movement_opts = self.new_movement_opts() for i in range(len(ordered_members) - 1, -1, -1): if i == 0: if not ordered_members[i].pos.isEqualTo(target): if target == self.location: ordered_members[i].follow_military_path( self.find_origin(), target, movement_opts) else: ordered_members[i].move_to(target, movement_opts) else: next_drone = ordered_members[i - 1] this_drone = ordered_members[i] if this_drone.pos.isNearTo( next_drone.pos) or movement.is_edge_position( next_drone.pos): if this_drone.creep.fatigue and not movement.is_edge_position( next_drone.pos): self.log("drone {} at {},{} breaking due to fatigue", i, this_drone.pos.x, this_drone.pos.y) break direction = movement.diff_as_direction( this_drone.pos, next_drone.pos) this_drone.creep.move(direction) this_drone.creep.__direction_moved = direction elif movement.is_edge_position(this_drone.pos): this_drone.move_to(next_drone) elif movement.chebyshev_distance_room_pos( this_drone.pos, next_drone.pos) > 3 or ( movement.chebyshev_distance_room_pos( this_drone.pos, next_drone.pos) > 1 and not movement.is_edge_position(next_drone.pos)): this_drone.move_to(next_drone) self.log("drone {} at {},{} breaking due to distance", i, this_drone.pos.x, this_drone.pos.y) break else: # for j in range(len(ordered_members) - 1, i, -1): # ordered_members[j].creep.move( # movement.diff_as_direction(ordered_members[j], ordered_members[j - 1])) moved = False if movement.chebyshev_distance_room_pos( this_drone.pos, next_drone.pos) == 2: # Note: we are guaranteed not to be in an edge position because if we were, the above # if would be triggered instead! This allows us to ignore the room name of the next pos. next_pos = movement.next_pos_in_direction_to( this_drone.pos, next_drone.pos) if movement.is_block_empty(this_drone.room, next_pos.x, next_pos.y): other_creeps_there = cast( List[Creep], this_drone.room.look_at(LOOK_CREEPS, next_pos)) other_drone = _.find(other_creeps_there, 'my') if other_drone: other_drone.move( movement.diff_as_direction( other_drone.pos, this_drone.pos)) this_drone.creep.move( movement.diff_as_direction( this_drone.pos, next_drone.pos)) moved = True elif not len(other_creeps_there): direction = movement.diff_as_direction( this_drone.pos, next_drone.pos) this_drone.creep.move(direction) this_drone.creep.__direction_moved = direction moved = True if not moved: this_drone.move_to(next_drone)