def line_intersects_rect(self, x1, y1, x2, y2, rx1, ry1, rx2, ry2): # 检查线段是否与矩形相交 def ccw(A, B, C): return (C[1]-A[1]) * (B[0]-A[0]) > (B[1]-A[1]) * (C[0]-A[0])

    def intersect(A, B, C, D):
        return ccw(A, C, D) != ccw(B, C, D) and ccw(A, B, C) != ccw(A, B, D)
    
    # 矩形的四条边
    edges = [
        ((rx1, ry1), (rx2, ry1)),  # 上边
        ((rx2, ry1), (rx2, ry2)),  # 右边
        ((rx2, ry2), (rx1, ry2)),  # 下边
        ((rx1, ry2), (rx1, ry1))   # 左边
    ]
    
    for edge in edges:
        if intersect((x1, y1), (x2, y2), edge[0], edge[1]):
            return True
    
    # 检查线段是否完全在矩形内
    if rx1 <= x1 <= rx2 and ry1 <= y1 <= ry2 and rx1 <= x2 <= rx2 and ry1 <= y2 <= ry2:
        return True
        
    return False

def line_rect_intersection(self, x1, y1, x2, y2, rx1, ry1, rx2, ry2):
    # 计算线段与矩形的交点
    def line_intersection(line1, line2):
        xdiff = (line1[0][0] - line1[1][0], line2[0][0] - line2[1][0])
        ydiff = (line1[0][1] - line1[1][1], line2[0][1] - line2[1][1])
        
        def det(a, b):
            return a[0] * b[1] - a[1] * b[0]
        
        div = det(xdiff, ydiff)
        if div == 0:
            return None
        
        d = (det(*line1), det(*line2))
        x = det(d, xdiff) / div
        y = det(d, ydiff) / div
        return x, y
    
    # 矩形的四条边
    edges = [
        ((rx1, ry1), (rx2, ry1)),  # 上边
        ((rx2, ry1), (rx2, ry2)),  # 右边
        ((rx2, ry2), (rx1, ry2)),  # 下边
        ((rx1, ry2), (rx1, ry1))   # 左边
    ]
    
    intersections = []
    line = ((x1, y1), (x2, y2))
    
    for edge in edges:
        intersection = line_intersection(line, edge)
        if intersection:
            # 检查交点是否在线段上
            if min(x1, x2) <= intersection[0] <= max(x1, x2) and \
               min(y1, y2) <= intersection[1] <= max(y1, y2):
                intersections.append(intersection)
    
    # 返回最近的交点
    if intersections:
        return min(intersections, key=lambda p: ((p[0] - x1)**2 + (p[1] - y1)**2))
    
    return None

def find_nearest_enemy(self, unit, enemies):
    # 查找最近的敌人
    nearest = None
    min_dist = float('inf')
    
    for enemy in enemies:
        if enemy["health"] > 0:
            dist = self.distance(unit, enemy)
            if dist < min_dist:
                min_dist = dist
                nearest = enemy
    
    return nearest

def find_best_cover(self, unit, enemy):
    # 寻找最佳掩体
    best_cover = None
    best_distance = float('inf')
    
    # 计算敌人方向
    angle = math.atan2(enemy["y"] - unit["y"], enemy["x"] - unit["x"])
    
    # 寻找距离敌人最远的掩体
    for cover in unit["cover_points"]:
        # 计算掩体到敌人的距离
        cover_to_enemy = math.sqrt((cover[0] - enemy["x"])**2 + (cover[1] - enemy["y"])**2)
        
        # 计算掩体到单位的距离
        cover_to_unit = math.sqrt((cover[0] - unit["x"])**2 + (cover[1] - unit["y"])**2)
        
        # 检查掩体是否在敌人视线范围内
        if cover_to_unit < 150 and cover_to_enemy > 100:
            # 检查掩体是否提供遮挡
            if not self.has_line_of_sight({"x": cover[0], "y": cover[1]}, enemy):
                if cover_to_enemy > best_distance:
                    best_distance = cover_to_enemy
                    best_cover = cover
    
    return best_cover

def astar(self, start, goal):
    # A*寻路算法
    def heuristic(a, b):
        # 曼哈顿距离
        return abs(a[0] - b[0]) + abs(a[1] - b[1])
    
    # 网格大小
    grid_size = 10
    
    # 起点和终点的网格坐标
    start_grid = (int(start[0] / grid_size), int(start[1] / grid_size))
    goal_grid = (int(goal[0] / grid_size), int(goal[1] / grid_size))
    
    # 定义网格边界
    grid_width = 1024 // grid_size
    grid_height = 668 // grid_size
    
    # 初始化开放列表和关闭列表
    open_set = {start_grid}
    closed_set = set()
    
    # 记录从起点到当前点的实际代价
    g_score = {start_grid: 0}
    
    # 记录从起点到终点的估计代价
    f_score = {start_grid: heuristic(start_grid, goal_grid)}
    
    # 记录路径
    came_from = {}
    
    # 八个方向的移动
    directions = [(0, 1), (1, 0), (0, -1), (-1, 0), (1, 1), (-1, 1), (1, -1), (-1, -1)]
    
    while open_set:
        # 找到f值最小的节点
        current = min(open_set, key=lambda node: f_score.get(node, float('inf')))
        
        # 如果到达终点,构建路径
        if current == goal_grid:
            path = []
            while current in came_from:
                path.append((current[0] * grid_size, current[1] * grid_size))
                current = came_from[current]
            path.append(start)
            path.reverse()
            return path
        
        # 将当前节点从开放列表移到关闭列表
        open_set.remove(current)
        closed_set.add(current)
        
        # 检查所有相邻节点
        for dx, dy in directions:
            neighbor = (current[0] + dx, current[1] + dy)
            
            # 检查边界
            if not (0 <= neighbor[0] < grid_width and 0 <= neighbor[1] < grid_height):
                continue
            
            # 检查障碍物
            real_pos = (neighbor[0] * grid_size, neighbor[1] * grid_size)
            if self.is_in_obstacle(real_pos[0], real_pos[1]):
                continue
            
            # 如果在关闭列表中,跳过
            if neighbor in closed_set:
                continue
            
            # 计算从起点到相邻节点的代价
            tentative_g_score = g_score[current] + (14 if dx != 0 and dy != 0 else 10)
            
            # 如果是新节点或找到了更好的路径
            if neighbor not in open_set or tentative_g_score < g_score.get(neighbor, float('inf')):
                # 记录路径
                came_from[neighbor] = current
                
                # 更新代价
                g_score[neighbor] = tentative_g_score
                f_score[neighbor] = tentative_g_score + heuristic(neighbor, goal_grid)
                
                # 将相邻节点加入开放列表
                open_set.add(neighbor)
    
    # 如果没有找到路径,返回直接前往目标的路径
    return [start, goal]

def follow_path(self, unit):
    if unit["path"] and len(unit["path"]) > 1:
        # 获取下一个路径点
        next_point = unit["path"][1]
        
        # 计算移动方向
        dx = next_point[0] - unit["x"]
        dy = next_point[1] - unit["y"]
        distance = math.sqrt(dx*dx + dy*dy)
        
        if distance > 5:  # 如果距离大于5,移动
            # 归一化方向向量
            dx /= distance
            dy /= distance
            
            # 移动速度
            speed = 3
            
            # 移动单位
            unit["x"] += dx * speed
            unit["y"] += dy * speed
            
            # 更新画布位置
            self.canvas.coords(unit["canvas_obj"], 
                              unit["x"] - 10, unit["y"] - 10, 
                              unit["x"] + 10, unit["y"] + 10)
            self.canvas.coords(unit["canvas_text"], unit["x"], unit["y"])
            
            if not unit["is_player"]:
                self.canvas.coords(unit["state_indicator"], unit["x"], unit["y"] - 20)
                self.canvas.coords(unit["behavior_indicator"], unit["x"], unit["y"])
            else:
                # 更新玩家朝向指示器
                self.canvas.coords(
                    unit["direction_line"],
                    unit["x"], unit["y"],
                    unit["x"] + math.cos(unit["direction"]) * 20,
                    unit["y"] + math.sin(unit["direction"]) * 20
                )
        else:
            # 已到达下一个路径点,移除它
            unit["path"].pop(1)

def update_player_position(self):
    if not self.game_active:
        return
        
    # 获取玩家
    player = self.defenders[0] if self.defender_turn else self.attackers[0]
    
    # 计算移动方向
    dx = 0
    dy = 0
    
    if self.key_pressed["w"]:
        dy -= self.player_speed
    if self.key_pressed["s"]:
        dy += self.player_speed
    if self.key_pressed["a"]:
        dx -= self.player_speed
    if self.key_pressed["d"]:
        dx += self.player_speed
    
    # 检查移动是否会碰到障碍物
    new_x = player["x"] + dx
    new_y = player["y"] + dy
    
    if not self.is_in_obstacle(new_x, new_y):
        # 更新玩家位置
        player["x"] = new_x
        player["y"] = new_y
        
        # 更新画布位置
        self.canvas.coords(player["canvas_obj"], 
                          player["x"] - 15, player["y"] - 15, 
                          player["x"] + 15, player["y"] + 15)
        self.canvas.coords(player["canvas_text"], player["x"], player["y"])
        
        # 更新玩家朝向指示器
        self.canvas.coords(
            player["direction_line"],
            player["x"], player["y"],
            player["x"] + math.cos(player["direction"]) * 20,
            player["y"] + math.sin(player["direction"]) * 20
        )
        
        # 更新玩家记忆中的位置
        if (player["x"], player["y"]) not in player["memory"]["visited_positions"]:
            player["memory"]["visited_positions"].append((player["x"], player["y"]))
            
            # 限制记忆大小
            if len(player["memory"]["visited_positions"]) > 20:
                player["memory"]["visited_positions"].pop(0)
    
    # 检查是否触发陷阱
    for trap in self.defense_objects[:]:
        if trap["type"] == "trap" and not trap["triggered"]:
            if self.distance(player, trap) < trap["trigger_radius"]:
                self.trigger_trap(trap, player)
    
    # 检查是否可以拆除拆弹器(防守方)
    if self.defender_turn and self.bomb_planted and self.distance(player, self.defuser) < 30:
        self.defend_defuser()
    
    # 检查是否可以放置炸弹(进攻方)
    if not self.defender_turn and not self.bomb_planted:
        if self.distance(player, self.bomb_site) < self.bomb_site["radius"]:
            # 显示放置炸弹提示
            pass
    
    # 每帧更新
    self.root.after(16, self.update_player_position)

def update_ai_memory(self, unit):
    # 更新AI记忆中的位置
    if (unit["x"], unit["y"]) not in unit["memory"]["visited_positions"]:
        unit["memory"]["visited_positions"].append((unit["x"], unit["y"]))
        
        # 限制记忆大小
        if len(unit["memory"]["visited_positions"]) > 20:
            unit["memory"]["visited_positions"].pop(0)
    
    # 更新记忆中的陷阱位置
    for trap in self.defense_objects:
        if trap["type"] == "trap":
            trap_pos = (trap["x"], trap["y"])
            if trap_pos not in unit["memory"]["trap_positions"]:
                unit["memory"]["trap_positions"].append(trap_pos)
                
                # 限制记忆大小
                if len(unit["memory"]["trap_positions"]) > 15:
                    unit["memory"]["trap_positions"].pop(0)
    
    # 更新记忆中的敌人位置
    enemies = self.attackers if unit["role"] == "defender" else self.defenders
    for enemy in enemies:
        if enemy["health"] > 0:
            enemy_pos = (enemy["x"], enemy["y"])
            if enemy_pos not in unit["memory"]["enemy_positions"]:
                unit["memory"]["enemy_positions"].append(enemy_pos)
                
                # 限制记忆大小
                if len(unit["memory"]["enemy_positions"]) > 15:
                    unit["memory"]["enemy_positions"].pop(0)

def avoid_traps(self, unit):
    # 检查记忆中的陷阱位置并避开
    if unit["memory"]["trap_positions"] and random.random() < 0.7:
        # 检查是否靠近陷阱
        for trap_pos in unit["memory"]["trap_positions"]:
            trap = {"x": trap_pos[0], "y": trap_pos[1]}
            if self.distance(unit, trap) < 50:
                # 避开陷阱
                avoid_dir_x = unit["x"] - trap["x"]
                avoid_dir_y = unit["y"] - trap["y"]
                distance = math.sqrt(avoid_dir_x*avoid_dir_x + avoid_dir_y*avoid_dir_y)
                
                if distance > 0:
                    # 归一化方向向量
                    avoid_dir_x /= distance
                    avoid_dir_y /= distance
                    
                    # 寻找避开陷阱的位置
                    safe_x = unit["x"] + avoid_dir_x * 100
                    safe_y = unit["y"] + avoid_dir_y * 100
                    
                    # 确保安全位置不在障碍物内
                    if not self.is_in_obstacle(safe_x, safe_y):
                        # 生成新路径
                        unit["path"] = self.astar((unit["x"], unit["y"]), (safe_x, safe_y))
                        break

def check_trap_trigger(self, defender):
    # 检查是否可以主动触发陷阱
    for trap in self.defense_objects:
        if trap["type"] == "trap" and not trap["triggered"]:
            # 检查是否有敌人靠近陷阱
            for attacker in self.attackers:
                if attacker["health"] > 0 and self.distance(attacker, trap) < trap["trigger_radius"]:
                    # 有敌人靠近,触发陷阱
                    self.trigger_trap(trap, attacker)
                    break

def trigger_trap(self, trap, target):
    # 触发陷阱
    trap["triggered"] = True
    
    # 造成伤害
    target["health"] -= trap["damage"]
    
    # 显示爆炸效果
    explosion = self.canvas.create_oval(
        trap["x"] - trap["trigger_radius"], trap["y"] - trap["trigger_radius"],
        trap["x"] + trap["trigger_radius"], trap["y"] + trap["trigger_radius"],
        fill="orange", outline="red"
    )
    
    # 显示伤害数字
    damage_text = self.canvas.create_text(
        target["x"], target["y"] - 20,
        text=f"-{trap['damage']}",
        fill="red",
        font=(self.font_family, 12, "bold")
    )
    
    # 短暂显示爆炸效果后删除
    self.root.after(500, lambda: self.canvas.delete(explosion))
    self.root.after(1000, lambda: self.canvas.delete(damage_text))
    
    # 检查目标是否死亡
    if target["health"] <= 0:
        # 从画布上删除目标
        self.canvas.delete(target["canvas_obj"])
        self.canvas.delete(target["canvas_text"])
        
        if not target["is_player"]:
            self.canvas.delete(target["state_indicator"])
            self.canvas.delete(target["behavior_indicator"])
        else:
            self.canvas.delete(target["direction_line"])
    
    # 从防御设施列表中删除陷阱
    self.defense_objects.remove(trap)

def ai_behavior_pattern(self, unit):
    # 根据AI行为模式调整行动
    unit["behavior_timer"] += 1
    
    # 每100帧(约1.6秒)随机改变行为
    if unit["behavior_timer"] > 100:
        unit["behavior_timer"] = 0
        
        # 随机行为
        if random.random() < 0.3:  # 30%的概率改变当前行为
            if unit["role"] == "defender":
                # 防守方行为模式
                patterns = ["aggressive", "defensive", "ambush", "support"]
                unit["behavior_pattern"] = random.choice(patterns)
            else:
                # 进攻方行为模式
                patterns = ["aggressive", "cautious", "flank", "support"]
                unit["behavior_pattern"] = random.choice(patterns)
    
    # 根据行为模式调整行为
    if unit["role"] == "defender":
        if unit["behavior_pattern"] == "aggressive":
            # 激进型:主动寻找敌人并攻击
            if unit["state"] == "patrol" and random.random() < 0.5:
                # 随机选择一个可能的敌人位置
                if unit["memory"]["enemy_positions"]:
                    target_pos = random.choice(unit["memory"]["enemy_positions"])
                    unit["path"] = self.astar((unit["x"], unit["y"]), target_pos)
        elif unit["behavior_pattern"] == "defensive":
            # 防御型:坚守炸弹点
            if unit["state"] == "patrol" and random.random() < 0.5:
                unit["path"] = self.astar((unit["x"], unit["y"]), 
                                       (self.bomb_site["x"], self.bomb_site["y"]))
        elif unit["behavior_pattern"] == "ambush":
            # 埋伏型:寻找好的埋伏点
            if unit["state"] == "patrol" and random.random() < 0.5:
                # 寻找可能的埋伏点
                ambush_points = []
                for cover in unit["cover_points"]:
                    # 检查是否是好的埋伏点
                    ambush_point = {"x": cover[0], "y": cover[1]}
                    if self.distance(ambush_point, self.bomb_site) < 200:
                        ambush_points.append(cover)
                
                if ambush_points:
                    target_pos = random.choice(ambush_points)
                    unit["path"] = self.astar((unit["x"], unit["y"]), target_pos)
        elif unit["behavior_pattern"] == "support":
            # 支援型:跟随队友
            if unit["state"] == "patrol" and random.random() < 0.5:
                # 寻找最近的队友
                nearest_teammate = None
                min_dist = float('inf')
                
                for teammate in self.defenders:
                    if teammate != unit and teammate["health"] > 0:
                        dist = self.distance(unit, teammate)
                        if dist < min_dist:
                            min_dist = dist
                            nearest_teammate = teammate
                
                if nearest_teammate and min_dist > 100:
                    unit["path"] = self.astar((unit["x"], unit["y"]), 
                                           (nearest_teammate["x"], nearest_teammate["y"]))
    else:  # 进攻方
        if unit["behavior_pattern"] == "aggressive":
            # 激进型:直接冲向炸弹点
            if unit["state"] == "patrol" and random.random() < 0.5:
                unit["path"] = self.astar((unit["x"], unit["y"]), 
                                       (self.bomb_site["x"], self.bomb_site["y"]))
        elif unit["behavior_pattern"] == "cautious":
            # 谨慎型:缓慢推进,寻找掩体
            if unit["state"] == "patrol" and random.random() < 0.5:
                # 寻找靠近炸弹点的掩体
                cover_points = []
                for cover in unit["cover_points"]:
                    cover_pos = {"x": cover[0], "y": cover[1]}
                    if self.distance(cover_pos, self.bomb_site) < 300:
                        cover_points.append(cover)
                
                if cover_points:
                    target_pos = random.choice(cover_points)
                    unit["path"] = self.astar((unit["x"], unit["y"]), target_pos)
        elif unit["behavior_pattern"] == "flank":
            # 包抄型:从侧面接近炸弹点
            if unit["state"] == "patrol" and random.random() < 0.5:
                # 计算从侧面接近的位置
                bomb_x, bomb_y = self.bomb_site["x"], self.bomb_site["y"]
                side_offset = random.choice([-150, 150])
                
                # 随机选择左侧或右侧
                if random.choice([True, False]):
                    target_x = bomb_x + side_offset
                    target_y = bomb_y
                else:
                    target_x = bomb_x
                    target_y = bomb_y + side_offset
                
                unit["path"] = self.astar((unit["x"], unit["y"]), (target_x, target_y))
        elif unit["behavior_pattern"] == "support":
            # 支援型:跟随携带炸弹的队友
            if unit["state"] == "patrol" and random.random() < 0.5:
                # 寻找最近的队友
                nearest_teammate = None
                min_dist = float('inf')
                
                for teammate in self.attackers:
                    if teammate != unit and teammate["health"] > 0:
                        dist = self.distance(unit, teammate)
                        if dist < min_dist:
                            min_dist = dist
                            nearest_teammate = teammate
                
                if nearest_teammate and min_dist > 100:
                    unit["path"] = self.astar((unit["x"], unit["y"]), 
                                           (nearest_teammate["x"], nearest_teammate["y"]))

def start_game(self):
    # 开始游戏
    self.create_game_screen()
    self.initialize_defenders()
    self.initialize_attackers()
    self.start_attack_phase()
    self.setup_player_controls()
    self.update_player_position()

if name == "main": root = tk.Tk() game = Game(root) root.mainloop()