""" 战场系统实现 包含HQ、前线、支援线的战场布局和管理 """ from typing import List, Optional, Dict, Tuple from dataclasses import dataclass from uuid import UUID from ..core.enums import LineType from ..units.unit import Unit @dataclass class HQ: """总部类""" defense: int = 20 current_defense: int = 20 player_id: str = "" def take_damage(self, damage: int) -> int: """总部受到伤害""" actual_damage = min(damage, self.current_defense) self.current_defense -= actual_damage return actual_damage def is_destroyed(self) -> bool: """判断总部是否被摧毁""" return self.current_defense <= 0 def __str__(self) -> str: return f"HQ ({self.current_defense}/{self.defense})" class BattleLine: """战线类(前线或支援线)""" def __init__(self, line_type: LineType, max_positions: int = 5): self.line_type = line_type self.max_positions = max_positions self.positions: List[Optional[Unit]] = [None] * max_positions def deploy_unit(self, unit: Unit, position: int) -> bool: """在指定位置部署单位""" if not self.is_position_valid(position): return False if self.positions[position] is not None: return False # 位置被占用 self.positions[position] = unit unit.position = (self.line_type, position) return True def remove_unit(self, position: int) -> Optional[Unit]: """移除指定位置的单位""" if not self.is_position_valid(position): return None unit = self.positions[position] if unit: self.positions[position] = None unit.position = None return unit def get_unit_at(self, position: int) -> Optional[Unit]: """获取指定位置的单位""" if not self.is_position_valid(position): return None return self.positions[position] def get_all_units(self) -> List[Unit]: """获取战线上所有单位""" return [unit for unit in self.positions if unit is not None] def find_unit_position(self, unit: Unit) -> Optional[int]: """查找单位在战线上的位置""" try: return self.positions.index(unit) except ValueError: return None def is_position_valid(self, position: int) -> bool: """检查位置是否有效""" return 0 <= position < self.max_positions def is_position_empty(self, position: int) -> bool: """检查位置是否为空""" return self.is_position_valid(position) and self.positions[position] is None def get_adjacent_positions(self, position: int) -> List[int]: """获取相邻位置""" if not self.is_position_valid(position): return [] adjacent = [] if position > 0: adjacent.append(position - 1) if position < self.max_positions - 1: adjacent.append(position + 1) return adjacent def get_adjacent_units(self, position: int) -> List[Unit]: """获取相邻单位""" adjacent_positions = self.get_adjacent_positions(position) return [self.positions[pos] for pos in adjacent_positions if self.positions[pos] is not None] def is_full(self) -> bool: """检查战线是否已满""" return all(pos is not None for pos in self.positions) def get_empty_positions(self) -> List[int]: """获取所有空位置""" return [i for i, pos in enumerate(self.positions) if pos is None] def __str__(self) -> str: unit_strs = [] for i, unit in enumerate(self.positions): if unit: unit_strs.append(f"{i}:{unit.name}") else: unit_strs.append(f"{i}:空") return f"{self.line_type} [{', '.join(unit_strs)}]" class Battlefield: """战场类,管理整个战场状态""" def __init__(self, player1_id: str, player2_id: str): # 玩家信息 self.player1_id = player1_id self.player2_id = player2_id # HQ self.player1_hq = HQ(player_id=player1_id) self.player2_hq = HQ(player_id=player2_id) # 战线 self.player1_support = BattleLine(LineType.SUPPORT) self.player1_front = BattleLine(LineType.FRONT) self.player2_support = BattleLine(LineType.SUPPORT) self.player2_front = BattleLine(LineType.FRONT) # 单位索引(快速查找) self.unit_registry: Dict[UUID, Unit] = {} def get_player_hq(self, player_id: str) -> Optional[HQ]: """获取玩家的HQ""" if player_id == self.player1_id: return self.player1_hq elif player_id == self.player2_id: return self.player2_hq return None def get_player_line(self, player_id: str, line_type: LineType) -> Optional[BattleLine]: """获取玩家的战线""" if player_id == self.player1_id: return self.player1_support if line_type == LineType.SUPPORT else self.player1_front elif player_id == self.player2_id: return self.player2_support if line_type == LineType.SUPPORT else self.player2_front return None def get_enemy_line(self, player_id: str, line_type: LineType) -> Optional[BattleLine]: """获取敌方的战线""" enemy_id = self.get_enemy_player_id(player_id) return self.get_player_line(enemy_id, line_type) if enemy_id else None def get_enemy_player_id(self, player_id: str) -> Optional[str]: """获取敌方玩家ID""" if player_id == self.player1_id: return self.player2_id elif player_id == self.player2_id: return self.player1_id return None def deploy_unit(self, unit: Unit, player_id: str, line_type: LineType, position: int) -> bool: """部署单位到战场""" battle_line = self.get_player_line(player_id, line_type) if not battle_line: return False if battle_line.deploy_unit(unit, position): unit.owner = player_id self.unit_registry[unit.id] = unit return True return False def remove_unit(self, unit: Unit) -> bool: """从战场移除单位""" if unit.position is None: return False line_type, position = unit.position battle_line = self.get_player_line(unit.owner, line_type) if battle_line and battle_line.remove_unit(position): if unit.id in self.unit_registry: del self.unit_registry[unit.id] return True return False def get_all_units(self, player_id: Optional[str] = None) -> List[Unit]: """获取所有单位,可按玩家筛选""" all_units = [] lines = [] if player_id is None: lines = [self.player1_support, self.player1_front, self.player2_support, self.player2_front] else: support = self.get_player_line(player_id, LineType.SUPPORT) front = self.get_player_line(player_id, LineType.FRONT) if support and front: lines = [support, front] for line in lines: all_units.extend(line.get_all_units()) return all_units def find_unit(self, unit_id: UUID) -> Optional[Unit]: """通过ID查找单位""" return self.unit_registry.get(unit_id) def get_units_with_keyword(self, keyword: str, player_id: Optional[str] = None) -> List[Unit]: """获取具有特定关键词的所有单位""" units = self.get_all_units(player_id) return [unit for unit in units if unit.has_keyword(keyword)] def is_game_over(self) -> Tuple[bool, Optional[str]]: """检查游戏是否结束,返回(是否结束, 胜利者ID)""" if self.player1_hq.is_destroyed(): return True, self.player2_id elif self.player2_hq.is_destroyed(): return True, self.player1_id return False, None def get_valid_attack_targets(self, attacker: Unit) -> List[Unit]: """获取单位可以攻击的所有目标""" if not attacker.owner: return [] enemy_id = self.get_enemy_player_id(attacker.owner) if not enemy_id: return [] enemy_units = self.get_all_units(enemy_id) valid_targets = [] for target in enemy_units: if (attacker.can_attack_target(target, self) and target.can_be_attacked_by(attacker, self)): valid_targets.append(target) return valid_targets def __str__(self) -> str: return f""" === 战场状态 === 玩家1 ({self.player1_id}): HQ: {self.player1_hq} {self.player1_support} {self.player1_front} 玩家2 ({self.player2_id}): HQ: {self.player2_hq} {self.player2_support} {self.player2_front} ================== """