def solve_combat(self, goal: CombatGoal, command: CombatAction, enemies: EnemyData) -> List[CombatAction]: disruptor = goal.unit goal.ready_to_shoot = False # Kite away time = self.knowledge.ai.time relevant_enemies = enemies.close_enemies.not_structure.not_flying if time < self.last_used_any + INTERVAL or len(relevant_enemies) < 4: return [] center = relevant_enemies.center if self.cd_manager.is_ready(disruptor.tag, AbilityId.EFFECT_PURIFICATIONNOVA): if center.distance_to(disruptor.position) < 11: self.last_used_any = time return [ CombatAction(disruptor, center, False, AbilityId.EFFECT_PURIFICATIONNOVA) ] else: goal.ready_to_shoot = True else: backstep: Point2 = disruptor.position.towards( enemies.enemy_center, -3) return [CombatAction(disruptor, backstep, False)] return []
def FinalSolve(self, goal: CombatGoal, command: CombatAction, enemies: EnemyData) -> CombatAction: ground_units: Units = enemies.our_units.not_flying x: Unit healable_targets = enemies.our_units.filter( lambda x: (x.health_percentage < 1 and not x.is_flying and ( x.is_biological or x.type_id == UnitTypeId.HELLIONTANK))) if healable_targets.exists: return CombatAction(goal.unit, healable_targets.closest_to(goal.unit), False, AbilityId.MEDIVACHEAL_HEAL) if ground_units.exists: position: Point2 = ground_units.closest_to(goal.unit).position medivac: Unit for medivac in enemies.our_units(UnitTypeId.MEDIVAC).closer_than( 5, goal.unit): if medivac.tag != goal.unit.tag: raven_position: Point2 = medivac.position if raven_position == goal.unit.position: position = position.towards_with_random_angle( self.knowledge.own_main_zone.center_location, 4) else: position = position.towards(raven_position, -4) return CombatAction(goal.unit, position, False) return command
def solve_combat(self, goal: CombatGoal, command: CombatAction, enemies: EnemyData) -> List[CombatAction]: time = self.ai.time shuffler = goal.unit.tag % 10 if self.used_dict.get(goal.unit.tag, 0) + self.cooldown > time: return [command] # Skips all else if enemies.enemy_power.power > 10: best_score = 0 target: Unit = None enemy: Unit for enemy in enemies.close_enemies: d = enemy.distance_to(goal.unit) if d < 9: score = d * 0.2 - enemy.movement_speed + enemy.radius + self.unit_values.power(enemy) score += 0.1 * (enemy.tag % (shuffler + 2)) if score > best_score: target = enemy best_score = score if target is not None: self.used_dict[goal.unit.tag] = time return [CombatAction(goal.unit, target.position, False, AbilityId.EFFECT_CORROSIVEBILE)] return [command] # Skips all else
def solve_combat(self, goal: CombatGoal, command: CombatAction, enemies: EnemyData) -> List[CombatAction]: relevant_enemies = enemies.close_enemies.not_structure.not_flying if relevant_enemies.exists: target = relevant_enemies.closest_to(enemies.enemy_center) else: target = enemies.close_enemies.closest_to(enemies.enemy_center) return [CombatAction(goal.unit, target, False)]
def PanicRetreat(self, goal: CombatGoal, command: CombatAction, enemies: EnemyData) -> CombatAction: oracle = goal.unit time = self.knowledge.ai.time if oracle.has_buff(BuffId.ORACLEWEAPON): return self.disable_beam(oracle)[0] pos = self.knowledge.pathing_manager.find_influence_air_path(oracle.position, goal.target) return CombatAction(oracle, pos, False)
def solve_combat(self, goal: CombatGoal, command: CombatAction, enemies: EnemyData) -> List[CombatAction]: if enemies.enemy_power.power > 10 and goal.unit.energy >= 50: enemy: Unit for enemy in enemies.close_enemies: if enemy.is_psionic or enemy.is_mechanical and enemy.distance_to( goal.unit) < 9.5: return [ CombatAction(goal.unit, enemy, False, AbilityId.EFFECT_INTERFERENCEMATRIX) ] if goal.unit.energy >= 75 and enemies.closest.distance_to( goal.unit) < 9.5: return [ CombatAction(goal.unit, enemies.closest, False, AbilityId.EFFECT_ANTIARMORMISSILE) ] return [command] # Skips all else
def FinalSolve(self, goal: CombatGoal, command: CombatAction, enemies: EnemyData) -> CombatAction: bc = goal.unit if bc.health < 50 and self.cd_manager.is_ready( bc.tag, AbilityId.EFFECT_TACTICALJUMP, self.cooldown): zones = self.knowledge.our_zones_with_minerals if zones: position = zones[0].behind_mineral_position_center self.cd_manager.used_ability(bc.tag, AbilityId.EFFECT_TACTICALJUMP) return CombatAction(bc, position, False, AbilityId.EFFECT_TACTICALJUMP) if not self.cd_manager.is_ready( bc.tag, AbilityId.EFFECT_TACTICALJUMP, self.cooldown) and bc.health_percentage < 0.9: scvs: Units = self.knowledge.unit_cache.own(UnitTypeId.SCV) if len(scvs) > 0 and scvs.closest_distance_to(bc) < 4: # Stay put! return CombatAction(bc, bc.position, False) return command
def solve_combat(self, goal: CombatGoal, command: CombatAction, enemies: EnemyData) -> List[CombatAction]: if not enemies.powered_enemies.exists: return [] stalker = goal.unit if self.cd_manager.is_ready(stalker.tag, AbilityId.EFFECT_BLINK_STALKER, self.cooldown): if enemies.our_power.is_enough_for(enemies.enemy_power, 1.3): # We have the advantage, enable offensive blink distance = enemies.closest.distance_to(stalker) own_range = self.unit_values.real_range( stalker, enemies.closest, self.knowledge) enemy_range = self.unit_values.real_range( stalker, enemies.closest, self.knowledge) if distance > own_range and own_range < enemy_range and distance < own_range + 5: # Blink to tanks, colossi and tempest self.cd_manager.used_ability( stalker.tag, AbilityId.EFFECT_BLINK_STALKER) target = stalker.position.towards(enemies.closest.position, 8) return [ CombatAction(stalker, target, False, AbilityId.EFFECT_BLINK_STALKER) ] if stalker.shield_percentage < 0.1: self.cd_manager.used_ability(stalker.tag, AbilityId.EFFECT_BLINK_STALKER) target = stalker.position.towards(enemies.enemy_center, -8) return [ CombatAction(stalker, target, False, AbilityId.EFFECT_BLINK_STALKER) ] return []
def FinalSolve(self, goal: CombatGoal, command: CombatAction, enemies: EnemyData) -> CombatAction: is_fighter = goal.unit.type_id == UnitTypeId.VIKINGFIGHTER if not enemies.enemies_exist: if is_fighter: return command else: return CombatAction(goal.unit, None, False, AbilityId.MORPH_VIKINGFIGHTERMODE) if is_fighter: if (not enemies.close_enemies(UnitTypeId.COLOSSUS).exists and not enemies.close_enemies.flying.exists and enemies.close_enemies.not_flying.exists): return CombatAction(goal.unit, None, False, AbilityId.MORPH_VIKINGASSAULTMODE) else: if enemies.enemy_power.air_presence > 0 or enemies.close_enemies( UnitTypeId.COLOSSUS).exists: return CombatAction(goal.unit, None, False, AbilityId.MORPH_VIKINGFIGHTERMODE) return command
def FinalSolve(self, goal: CombatGoal, command: CombatAction, enemies: EnemyData) -> CombatAction: phoenix: Unit = goal.unit if command.is_attack and isinstance(command.target, Unit): range = self.unit_values.real_range(phoenix, command.target, self.knowledge) check_point = (phoenix.position + command.target.position) * 0.5 pathing_result = self.knowledge.pathing_manager.find_weak_influence_air( check_point, 4) direction = sc2math.point_normalize(pathing_result - command.target.position) destination = command.target.position + direction * (range - 0.5) return CombatAction(phoenix, destination, False) return super().FinalSolve(goal, command, enemies)
def solve_combat(self, goal: CombatGoal, command: CombatAction, enemies: EnemyData) -> List[CombatAction]: time = self.ai.time voidray = goal.unit if (goal.move_type == MoveType.SearchAndDestroy or goal.move_type == MoveType.Assault): if self.cd_manager.is_ready(voidray.tag, AbilityId.EFFECT_VOIDRAYPRISMATICALIGNMENT, self.cooldown): close_enemies = enemies.close_enemies.closer_than(7, voidray) if close_enemies.exists: for enemy in close_enemies: if enemy.is_armored: # there is a armored enemy in the vicinity self.cd_manager.used_ability(voidray.tag, AbilityId.EFFECT_VOIDRAYPRISMATICALIGNMENT) return [CombatAction(voidray, None, False, AbilityId.EFFECT_VOIDRAYPRISMATICALIGNMENT)] return [command] # Skips all else
def relay_order(self, tank: Unit, order: AbilityId, time: float) -> List[CombatAction]: if order is None: self.clear_order() return [] if self.requested_status == order: # Do the change when delay matches request delay = self.delay if order == AbilityId.SIEGEMODE_SIEGEMODE: delay = delay * 0.25 if time > self.requested_time + delay: return [CombatAction(tank, None, False, self.requested_status)] else: self.requested_status = order self.requested_time = time return []
def solve_combat(self, goal: CombatGoal, command: CombatAction, enemies: EnemyData) -> List[CombatAction]: if not self.knowledge.known_enemy_units.exists: return [] for adept in self.ai.units(sc2.UnitTypeId.ADEPT).tags_not_in( self.knowledge.roles.roles[UnitTask.Scouting.value].tags): if adept.shield_percentage < 0.75: if self.tag_shift_used_dict.get( adept.tag, 0) + self.cooldown < self.ai.time: self.tag_shift_used_dict[adept.tag] = self.ai.time target = adept.position.towards( self.knowledge.known_enemy_units.closest_to( adept.position), -10) return [ CombatAction(goal.unit, target, False, AbilityId.ADEPTPHASESHIFT_ADEPTPHASESHIFT) ] return []
def FinalSolve(self, goal: CombatGoal, command: CombatAction, enemies: EnemyData) -> CombatAction: ground_units: Units = enemies.our_units.not_flying x: Unit if ground_units.exists: position: Point2 = ground_units.closest_to(goal.unit).position observer: Unit for observer in enemies.our_units(UnitTypeId.OBSERVER).closer_than( 5, goal.unit): if observer.tag != goal.unit.tag: observer_position: Point2 = observer.position if observer_position == goal.unit.position: position = position.towards_with_random_angle( self.knowledge.own_main_zone.center_location, 4) else: position = position.towards(observer_position, -4) return CombatAction(goal.unit, position, False) return command
def FinalSolve(self, goal: CombatGoal, command: CombatAction, enemies: EnemyData) -> CombatAction: ground_units: Units = enemies.our_units.not_flying x: Unit if command.ability is not None: return command if ground_units.exists: position: Point2 = ground_units.closest_to(goal.unit).position raven: Unit for raven in enemies.our_units(UnitTypeId.RAVEN).closer_than( 5, goal.unit): if raven.tag != goal.unit.tag: raven_position: Point2 = raven.position if raven_position == goal.unit.position: position = position.towards_with_random_angle( self.knowledge.own_main_zone.center_location, 4) else: position = position.towards(raven_position, -4) return CombatAction(goal.unit, position, False) return command
def solve_combat(self, goal: CombatGoal, command: CombatAction, enemies: EnemyData) -> List[CombatAction]: oracle = goal.unit if not oracle.has_buff(BuffId.ORACLEWEAPON): goal.ready_to_shoot = False air_shooter_enemies = Units([], self.ai) enemy: Unit power = ExtendedPower(self.unit_values) for enemy in enemies.close_enemies: if self.unit_values.air_range(enemy) < enemy.distance_to(oracle) + 1: air_shooter_enemies.append(enemy) power.add_unit(enemy) if self.unit_values.is_static_air_defense(enemy): power.add(5) # can't beat turrets with oracle enemy_center = enemies.close_enemies.center for air_shooter in air_shooter_enemies: # type: Unit if air_shooter.is_light and not air_shooter.is_flying: power.add_units(air_shooter_enemies) else: power.add_units(air_shooter_enemies * 2) time = self.knowledge.ai.time if goal.move_type == MoveType.PanicRetreat and oracle.has_buff(BuffId.ORACLEWEAPON): return self.disable_beam(oracle) possible_targets = enemies.close_enemies.filter(lambda u: not u.is_flying and not u.is_structure and u.is_light) if possible_targets.exists: if oracle.energy > 50 and possible_targets.closest_distance_to(oracle) < 5 and not oracle.has_buff(BuffId.ORACLEWEAPON): return self.enable_beam(oracle) if power.air_power > 0 and power.air_power <= 3: target = air_shooter_enemies.closest_to(oracle) if target.is_light or target.health_percentage < 0.5: if not oracle.has_buff(BuffId.ORACLEWEAPON): return self.enable_beam(oracle) # Kill the target return [CombatAction(oracle, target, True)] #target_pos = self.knowledge.pathing_manager.find_weak_influence_air(goal.target, 7) #move_step = self.knowledge.pathing_manager.find_influence_air_path(oracle.position, target_pos) return [CombatAction(oracle, target.position, True)] elif goal.ready_to_shoot and possible_targets: return [CombatAction(oracle, possible_targets.closest_to(oracle), True)] elif power.air_power > 12: # Panic retreat to whatever direction if goal.move_type in offensive: new_target: Point2 = self.knowledge.pathing_manager.find_weak_influence_air(goal.target, 7) step = self.knowledge.pathing_manager.find_influence_air_path(oracle.position, new_target) # backstep: Point2 = self.knowledge.pathing_manager.find_weak_influence_air(oracle.position, 7) move_action = CombatAction(oracle, step, False) else: backstep = self.knowledge.pathing_manager.find_influence_air_path(oracle.position, goal.target) move_action = CombatAction(oracle, backstep, False) # Todo disable beam? return [move_action] elif power.air_power > 3: # Try kiting while killing the target target = self.knowledge.pathing_manager.find_weak_influence_air(goal.target, 7) backstep = self.knowledge.pathing_manager.find_influence_air_path(oracle.position, target) if goal.move_type in offensive: move_action = CombatAction(oracle, backstep, False) else: move_action = CombatAction(oracle, backstep, False) if oracle.has_buff(BuffId.ORACLEWEAPON): if possible_targets: closest = possible_targets.closest_to(oracle) if closest.distance_to(oracle) < 5: return [CombatAction(oracle, closest, True)] return [CombatAction(oracle, command.target, True), move_action] else: return [move_action] if possible_targets.exists: return [CombatAction(oracle, command.target, True)] else: return [CombatAction(oracle, command.target, False)]
def disable_beam(self, oracle): self.knowledge.print("[ORACLE] beam disabled") return [CombatAction(oracle, None, False, AbilityId.BEHAVIOR_PULSARBEAMOFF)]
def solve_combat(self, goal: CombatGoal, command: CombatAction, enemies: EnemyData) -> List[CombatAction]: actions: List[CombatAction] = [] phoenix: Unit = goal.unit # def is_beam_target_type(unit: Unit) -> bool: # if unit.type_id in self.always_ignore: # return False # # if phoenix.energy_percentage > 0.95: # # Anything but ignored types are fine with full energy # return True # # return unit.type_id in self.lift_priority friends: Units = self.combat_manager.ai.units.closer_than(8, phoenix) half_not_beaming = friends.amount / 2 > len( self.combat_manager.beaming_phoenix_tags) has_energy = phoenix.energy > GRAVITON_BEAM_ENERGY best_target: Optional[Unit] = None best_score: float = 0 for enemy in enemies.close_enemies: # type: Unit if enemy.has_buff(BuffId.GRAVITONBEAM): continue pos: Point2 = enemy.position score = self.lift_priority.get( enemy.type_id, -1) + (1 - pos.distance_to(phoenix) / 10) if score > best_score: best_target = enemy best_score = score # Use Graviton Beam if has_energy and half_not_beaming and best_target: if best_score > 5 or not enemies.close_enemies.flying.exists: self.print( f"Phoenix at {phoenix.position} lifting {best_target.type_id} at {best_target.position}" ) if phoenix.distance_to(best_target) > 8: destination = self.knowledge.pathing_manager.find_influence_air_path( phoenix.position, best_target.position) return [CombatAction(phoenix, destination, False)] return [ CombatAction(phoenix, best_target, False, ability=AbilityId.GRAVITONBEAM_GRAVITONBEAM) ] if enemies.close_enemies.closer_than( 11, phoenix.position ).exists and not enemies.close_enemies.flying.exists: # There is an enemy close by, but it doesn't fly so let's run away ! pathing_result = self.path_finder_air.lowest_influence_in_grid( enemies.our_median, 8) backstep = Point2(pathing_result[0]) #backstep: Point2 = phoenix.position.towards(enemies.enemy_center, -3) return [CombatAction(phoenix, backstep, False)] # Do you normal stuff return actions
def FinalSolve(self, goal: CombatGoal, command: CombatAction, enemies: EnemyData) -> CombatAction: prism = goal.unit warpgates: Units = self.knowledge.unit_cache.own(UnitTypeId.WARPGATE) count = len(warpgates) ready = 0 for gate in warpgates: # type: Unit if gate.is_transforming or self.cd_manager.is_ready(gate.tag, AbilityId.WARPGATETRAIN_ZEALOT): ready += 1 if (ready > 2 and ready >= count and goal.unit.type_id == UnitTypeId.WARPPRISM and self.ai.supply_left > 3 and self.cd_manager.is_ready(prism.tag, AbilityId.MORPH_WARPPRISMTRANSPORTMODE, 6)): # TODO: Is it safe to warp in? self.cd_manager.used_ability(prism.tag, AbilityId.MORPH_WARPPRISMPHASINGMODE) return CombatAction(goal.unit, None, False, AbilityId.MORPH_WARPPRISMPHASINGMODE) elif goal.unit.type_id == UnitTypeId.WARPPRISMPHASING: not_ready = self.knowledge.unit_cache.own(UnitValue.gate_types).not_ready if self.cd_manager.is_ready(prism.tag, AbilityId.MORPH_WARPPRISMPHASINGMODE, 2.5) \ and (len(not_ready) < 1 or not_ready.closest_distance_to(prism) > 4): self.cd_manager.used_ability(prism.tag, AbilityId.MORPH_WARPPRISMTRANSPORTMODE) return CombatAction(goal.unit, None, False, AbilityId.MORPH_WARPPRISMTRANSPORTMODE) if prism.cargo_used: for passenger in prism.passengers: # type: Unit if self.release_tags.get(passenger.tag, 0) < self.ai.time: if (not self.ai.in_pathing_grid(prism)): break stop_drop = False for enemy in enemies.close_enemies: # type: Unit if enemy.radius + 1 > prism.distance_to(enemy): stop_drop = True break if stop_drop: break #return CombatAction(prism, passenger, False, AbilityId.UNLOADALLAT_WARPPRISM) return CombatAction(prism, prism, False, AbilityId.UNLOADALLAT_WARPPRISM) if not enemies.powered_enemies.exists: return command # Let's find the safest position that's closest to enemies best_danger = self.knowledge.enemy_units_manager.danger_value(goal.unit, enemies.our_median) best_position = enemies.our_median if prism.cargo_left and prism.shield > 0 and prism.shield + prism.health > 50: best_score = 0 best_unit = None for own_unit in enemies.our_units: # type: Unit if own_unit.cargo_size > prism.cargo_left: continue if own_unit.shield: continue if own_unit.weapon_cooldown < 2: continue if own_unit.distance_to(prism) > 12: continue score = self.unit_values.ground_range(own_unit, self.knowledge) * (1.1 - own_unit.health_percentage) \ * self.unit_values.power(own_unit) - 1 if score > best_score: best_score = score best_unit = own_unit if best_unit is not None: self.release_tags[best_unit.tag] = self.ai.time + best_unit.weapon_cooldown / 22.4 return CombatAction(goal.unit, best_unit, False, AbilityId.SMART) priority_units = enemies.our_units.of_type([UnitTypeId.COLOSSUS, UnitTypeId.IMMORTAL, UnitTypeId.ARCHON, UnitTypeId.HIGHTEMPLAR]) for vector in self.grid_vectors: position: Point2 = goal.unit.position + vector * 3 if position.distance_to_point2(enemies.our_median) > 8: # Don't go too far away from our units continue danger = self.knowledge.enemy_units_manager.danger_value(goal.unit, position) coverage = 0 for unit in priority_units: # type: Unit if unit.distance_to(vector) < 6: coverage += self.unit_values.power_by_type(unit.type_id) * 10 if danger < best_danger - coverage: best_danger = danger best_position = position return CombatAction(goal.unit, best_position, False)