def focus_fire(step: MicroStep, unit: Unit, current_command: Action, prio: Optional[Dict[UnitTypeId, int]]) -> Action: shoot_air = step.unit_values.can_shoot_air(unit) shoot_ground = step.unit_values.can_shoot_ground(unit) air_range = step.unit_values.air_range(unit) ground_range = step.unit_values.ground_range(unit) lookup = min(air_range + 3, ground_range + 3) enemies = step.cache.enemy_in_range(unit.position, lookup) last_target = step.last_targeted(unit) if not enemies: # No enemies to shoot at return current_command value_func: Callable[[Unit], float] if prio: value_func = ( lambda u: 1 if u.type_id in changelings else prio.get(u.type_id, -1) * (1 - u.shield_health_percentage)) else: value_func = ( lambda u: 1 if u.type_id in changelings else 2 * step.unit_values. power_by_type(u.type_id, 1 - u.shield_health_percentage)) best_target: Optional[Unit] = None best_score: float = 0 for enemy in enemies: # type: Unit if not step.is_target(enemy): continue if not shoot_air and enemy.is_flying: continue if not shoot_ground and not enemy.is_flying: continue pos: Point2 = enemy.position score = value_func(enemy) + (1 - pos.distance_to(unit) / lookup) if enemy.tag == last_target: score += 3 if step.focus_fired.get(enemy.tag, 0) > enemy.health: score *= 0.1 if score > best_score: best_target = enemy best_score = score if best_target: step.focus_fired[best_target.tag] = ( step.focus_fired.get(best_target.tag, 0) + unit.calculate_damage_vs_target(best_target)[0]) return Action(best_target, True) return current_command
def melee_focus_fire( step: MicroStep, unit: Unit, current_command: Action, prio: Optional[Dict[UnitTypeId, int]] ) -> Action: ground_range = step.unit_values.ground_range(unit) lookup = ground_range + 3 enemies = step.cache.enemy_in_range(unit.position, lookup) last_target = step.last_targeted(unit) if not enemies: # No enemies to shoot at return current_command def melee_value(u: Unit): val = 1 - u.shield_health_percentage range = step.unit_values.real_range(unit, u) if unit.distance_to(u) < range: val += 2 if step.knowledge.enemy_race == Race.Terran and unit.is_structure and unit.build_progress < 1: # if building isn't finished, focus on the possible scv instead val -= 2 if unit.is_structure and not unit.can_attack: # if building val -= 6 return val value_func = melee_value close_enemies = step.cache.enemy_in_range(unit.position, lookup) best_target: Optional[Unit] = None best_score: float = 0 for enemy in close_enemies: # type: Unit if enemy.type_id in ignored_types: continue if enemy.is_flying: continue pos: Point2 = enemy.position score = value_func(enemy) + (1 - pos.distance_to(unit) / lookup) if enemy.tag == last_target: score += 1 if step.focus_fired.get(enemy.tag, 0) > enemy.health: score *= 0.1 if score > best_score: best_target = enemy best_score = score if best_target: step.focus_fired[best_target.tag] = step.focus_fired.get(best_target.tag, 0) return Action(best_target, True) return current_command
def init_micro_group(step: MicroStep, group: CombatUnits, units: Units, enemy_groups: List[CombatUnits], move_type: MoveType): ready_to_attack = 0 step.closest_group = group.closest_target_group(enemy_groups) if step.closest_group: step.closest_group_distance = group.center.distance_to( step.closest_group.center) else: step.closest_group_distance = 100000 step.enemy_groups = enemy_groups step.center = units.center step.enemies_near_by = step.knowledge.unit_cache.enemy_in_range( step.center, 15 + len(group.units) * 0.1) step.engaged_power.add_units(step.enemies_near_by) engage_count = 0 can_engage_count = 0 step.attack_range = 0 step.enemy_attack_range = 0 attack_range_count = 0 enemy_attack_range_count = 0 for unit in units: closest_distance = 1000 if step.ready_to_shoot(unit): ready_to_attack += 1 engage_added = False can_engage_added = False for enemy_near in step.enemies_near_by: # type: Unit d = enemy_near.distance_to(unit) if d < closest_distance: step.closest_units[unit.tag] = enemy_near closest_distance = d att_range = step.unit_values.real_range(enemy_near, unit) step.enemy_attack_range += att_range enemy_attack_range_count += 1 if not engage_added and d < att_range: engage_count += 1 engage_added = True att_range = step.unit_values.real_range(unit, enemy_near) step.attack_range += att_range attack_range_count += 1 if not can_engage_added and d < att_range: can_engage_count += 1 can_engage_added = True if attack_range_count > 0: step.attack_range = step.attack_range / attack_range_count if enemy_attack_range_count > 0: step.enemy_attack_range = step.enemy_attack_range / enemy_attack_range_count step.ready_to_attack_ratio = ready_to_attack / len(units) step.engage_ratio = engage_count / len(units) step.can_engage_ratio = can_engage_count / len(units)