""" 目标选择系统 用于选择能力和效果的作用目标 """ from typing import List, Optional, TYPE_CHECKING from abc import ABC, abstractmethod if TYPE_CHECKING: from ..units.unit import Unit from ..battlefield.battlefield import Battlefield from ..abilities.abilities import TargetType from ..core.enums import LineType class TargetSelector: """目标选择器""" def get_targets_by_type(self, source: 'Unit', battlefield: 'Battlefield', target_type: TargetType) -> List['Unit']: """根据目标类型获取有效目标列表""" if target_type == TargetType.SELF: return [source] elif target_type == TargetType.NO_TARGET: return [] elif target_type == TargetType.FRIENDLY_UNIT: friendly_units = battlefield.get_all_units(source.owner) return [unit for unit in friendly_units if unit.id != source.id] elif target_type == TargetType.ENEMY_UNIT: enemy_id = battlefield.get_enemy_player_id(source.owner) return battlefield.get_all_units(enemy_id) if enemy_id else [] elif target_type == TargetType.ANY_UNIT: all_units = battlefield.get_all_units() return [unit for unit in all_units if unit.id != source.id] elif target_type == TargetType.ALL_FRIENDLY: return battlefield.get_all_units(source.owner) elif target_type == TargetType.ALL_ENEMY: enemy_id = battlefield.get_enemy_player_id(source.owner) return battlefield.get_all_units(enemy_id) if enemy_id else [] elif target_type == TargetType.ADJACENT_FRIENDLY: return self.get_adjacent_friendly_units(source, battlefield) elif target_type == TargetType.FRIENDLY_HQ: # HQ目标需要特殊处理,这里返回空列表 return [] elif target_type == TargetType.ENEMY_HQ: # HQ目标需要特殊处理,这里返回空列表 return [] return [] def get_adjacent_friendly_units(self, source: 'Unit', battlefield: 'Battlefield') -> List['Unit']: """获取相邻的友方单位""" if not source.position: return [] line_type, position = source.position battle_line = battlefield.get_player_line(source.owner, line_type) if not battle_line: return [] adjacent_units = battle_line.get_adjacent_units(position) return [unit for unit in adjacent_units if unit.owner == source.owner] def get_units_in_line(self, source: 'Unit', battlefield: 'Battlefield', line_type: LineType, friendly: bool = True) -> List['Unit']: """获取指定战线上的单位""" target_player = source.owner if friendly else battlefield.get_enemy_player_id(source.owner) if not target_player: return [] battle_line = battlefield.get_player_line(target_player, line_type) return battle_line.get_all_units() if battle_line else [] def get_units_with_keyword(self, source: 'Unit', battlefield: 'Battlefield', keyword: str, friendly: bool = True) -> List['Unit']: """获取具有指定关键词的单位""" target_player = source.owner if friendly else battlefield.get_enemy_player_id(source.owner) return battlefield.get_units_with_keyword(keyword, target_player) def get_damaged_units(self, source: 'Unit', battlefield: 'Battlefield', friendly: bool = True) -> List['Unit']: """获取受伤的单位""" target_player = source.owner if friendly else battlefield.get_enemy_player_id(source.owner) units = battlefield.get_all_units(target_player) return [unit for unit in units if unit.stats.current_defense < unit.stats.defense] def get_units_by_type(self, source: 'Unit', battlefield: 'Battlefield', unit_type, friendly: bool = True) -> List['Unit']: """获取指定类型的单位""" target_player = source.owner if friendly else battlefield.get_enemy_player_id(source.owner) units = battlefield.get_all_units(target_player) return [unit for unit in units if unit.unit_type == unit_type] class TargetFilter: """目标过滤器""" @staticmethod def filter_by_attack_range(units: List['Unit'], min_attack: int = 0, max_attack: int = float('inf')) -> List['Unit']: """按攻击力范围过滤""" return [unit for unit in units if min_attack <= unit.get_effective_attack() <= max_attack] @staticmethod def filter_by_defense_range(units: List['Unit'], min_defense: int = 0, max_defense: int = float('inf')) -> List['Unit']: """按防御力范围过滤""" return [unit for unit in units if min_defense <= unit.stats.current_defense <= max_defense] @staticmethod def filter_by_keywords(units: List['Unit'], required_keywords: List[str] = None, forbidden_keywords: List[str] = None) -> List['Unit']: """按关键词过滤""" if required_keywords is None: required_keywords = [] if forbidden_keywords is None: forbidden_keywords = [] filtered = [] for unit in units: # 检查必需关键词 if required_keywords and not all(unit.has_keyword(kw) for kw in required_keywords): continue # 检查禁止关键词 if forbidden_keywords and any(unit.has_keyword(kw) for kw in forbidden_keywords): continue filtered.append(unit) return filtered @staticmethod def filter_by_position(units: List['Unit'], line_type: LineType = None, positions: List[int] = None) -> List['Unit']: """按位置过滤""" filtered = [] for unit in units: if not unit.position: continue unit_line, unit_pos = unit.position # 检查战线类型 if line_type is not None and unit_line != line_type: continue # 检查具体位置 if positions is not None and unit_pos not in positions: continue filtered.append(unit) return filtered @staticmethod def get_random_target(units: List['Unit'], count: int = 1) -> List['Unit']: """随机选择目标""" import random if count >= len(units): return units.copy() return random.sample(units, count) @staticmethod def get_highest_attack_targets(units: List['Unit'], count: int = 1) -> List['Unit']: """选择攻击力最高的目标""" if not units: return [] sorted_units = sorted(units, key=lambda u: u.get_effective_attack(), reverse=True) return sorted_units[:count] @staticmethod def get_lowest_defense_targets(units: List['Unit'], count: int = 1) -> List['Unit']: """选择防御力最低的目标""" if not units: return [] sorted_units = sorted(units, key=lambda u: u.stats.current_defense) return sorted_units[:count] class TargetingRule: """目标选择规则""" def __init__(self, name: str): self.name = name def apply(self, source: 'Unit', potential_targets: List['Unit'], battlefield: 'Battlefield') -> List['Unit']: """应用目标选择规则""" return potential_targets class SmartTargetingRule(TargetingRule): """智能目标选择规则""" def __init__(self): super().__init__("SMART_TARGETING") def apply(self, source: 'Unit', potential_targets: List['Unit'], battlefield: 'Battlefield') -> List['Unit']: """智能选择最优目标""" if not potential_targets: return [] # 优先级:能一击击杀 > 攻击力高 > 防御力低 killable_targets = [t for t in potential_targets if t.stats.current_defense <= source.get_effective_attack()] if killable_targets: # 在可击杀的目标中选择攻击力最高的 return TargetFilter.get_highest_attack_targets(killable_targets, 1) # 选择防御力最低的目标 return TargetFilter.get_lowest_defense_targets(potential_targets, 1) class RandomTargetingRule(TargetingRule): """随机目标选择规则""" def __init__(self): super().__init__("RANDOM_TARGETING") def apply(self, source: 'Unit', potential_targets: List['Unit'], battlefield: 'Battlefield') -> List['Unit']: """随机选择目标""" return TargetFilter.get_random_target(potential_targets, 1) class PriorityTargetingRule(TargetingRule): """优先级目标选择规则""" def __init__(self, priority_keywords: List[str] = None): super().__init__("PRIORITY_TARGETING") self.priority_keywords = priority_keywords or [] def apply(self, source: 'Unit', potential_targets: List['Unit'], battlefield: 'Battlefield') -> List['Unit']: """按优先级选择目标""" if not potential_targets: return [] # 按优先级关键词排序 for keyword in self.priority_keywords: priority_targets = [t for t in potential_targets if t.has_keyword(keyword)] if priority_targets: return TargetFilter.get_highest_attack_targets(priority_targets, 1) # 如果没有优先级目标,选择攻击力最高的 return TargetFilter.get_highest_attack_targets(potential_targets, 1)