import pygame
import sys
import random
import time
from enum import Enum

# 初始化Pygame
pygame.init()

# -------------------------- 常量定义 --------------------------
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
FPS = 60
CELL_SIZE = 40

# 颜色定义（高级配色）
COLORS = {
    "bg": (17, 24, 39),          # 深色背景
    "wall": (59, 130, 246),      # 蓝色墙壁
    "path": (31, 41, 55),        # 路径底色
    "player": (234, 179, 8),     # 黄色玩家
    "exit": (34, 197, 94),       # 绿色出口
    "text": (243, 244, 246),     # 白色文字
    "highlight": (236, 72, 153), # 粉色高亮
    "prop1": (168, 85, 247),     # 瞬移道具（紫色）
    "prop2": (20, 184, 166),     # 视野道具（青色）
    "prop3": (249, 115, 22),     # 暂停道具（橙色）
}

# 道具类型枚举
class PropType(Enum):
    TELEPORT = 1  # 瞬移
    VISION = 2    # 视野扩大
    PAUSE = 3     # 时间暂停

# -------------------------- 游戏类 --------------------------
class MazeGame:
    def __init__(self):
        self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
        pygame.display.set_caption("高级迷宫闯关游戏")
        self.clock = pygame.time.Clock()
        self.font = pygame.font.Font(None, 40)
        self.small_font = pygame.font.Font(None, 25)
        
        # 游戏状态
        self.game_state = "start"  # start:开始界面, game:游戏中, win:通关, select:关卡选择
        self.current_level = 1
        self.max_level = 3  # 可扩展更多关卡
        self.unlocked_levels = 1  # 解锁的关卡数
        
        # 游戏数据
        self.player_pos = (1, 1)
        self.exit_pos = None
        self.maze = []
        self.props = {}  # 道具位置字典: (x,y): PropType
        self.prop_effects = {
            "vision": False,
            "pause": False,
            "teleport_used": False
        }
        self.start_time = 0
        self.game_time = 0
        self.score = 0
        
        # 加载初始关卡
        self.load_level(self.current_level)

    def generate_maze(self, width, height):
        """生成随机迷宫（递归回溯算法）"""
        # 初始化迷宫（全部为墙）
        maze = [[1 for _ in range(width)] for _ in range(height)]
        stack = [(1, 1)]
        maze[1][1] = 0
        directions = [(0, 2), (2, 0), (0, -2), (-2, 0)]
        
        while stack:
            x, y = stack[-1]
            random.shuffle(directions)
            found = False
            
            for dx, dy in directions:
                nx, ny = x + dx, y + dy
                if 1 <= nx < width-1 and 1 <= ny < height-1 and maze[ny][nx] == 1:
                    maze[ny][nx] = 0
                    maze[y + dy//2][x + dx//2] = 0
                    stack.append((nx, ny))
                    found = True
                    break
            
            if not found:
                stack.pop()
        
        # 设置出口（右下角）
        exit_x, exit_y = width-2, height-2
        maze[exit_y][exit_x] = 0
        self.exit_pos = (exit_x, exit_y)
        
        return maze

    def load_level(self, level):
        """加载指定关卡"""
        self.prop_effects = {
            "vision": False,
            "pause": False,
            "teleport_used": False
        }
        self.score = 0
        self.start_time = time.time()
        
        # 根据关卡设置迷宫大小和难度
        if level == 1:
            maze_width, maze_height = 15, 10
        elif level == 2:
            maze_width, maze_height = 18, 12
        elif level == 3:
            maze_width, maze_height = 20, 14
        
        # 生成迷宫
        self.maze = self.generate_maze(maze_width, maze_height)
        
        # 重置玩家位置
        self.player_pos = (1, 1)
        
        # 生成道具（每个关卡2-3个道具）
        self.props = {}
        prop_count = 2 if level == 1 else 3
        prop_types = [PropType.TELEPORT, PropType.VISION, PropType.PAUSE][:prop_count]
        
        for prop_type in prop_types:
            # 随机生成道具位置（确保在路径上且不是玩家/出口位置）
            while True:
                x = random.randint(1, maze_width-2)
                y = random.randint(1, maze_height-2)
                if self.maze[y][x] == 0 and (x, y) != self.player_pos and (x, y) != self.exit_pos:
                    self.props[(x, y)] = prop_type
                    break

    def draw_maze(self):
        """绘制迷宫"""
        maze_width = len(self.maze[0])
        maze_height = len(self.maze)
        
        # 计算迷宫偏移（居中显示）
        offset_x = (SCREEN_WIDTH - maze_width * CELL_SIZE) // 2
        offset_y = (SCREEN_HEIGHT - maze_height * CELL_SIZE) // 2 - 20
        
        # 绘制迷宫背景
        self.screen.fill(COLORS["bg"])
        
        # 绘制迷宫格子
        for y in range(maze_height):
            for x in range(maze_width):
                rect = pygame.Rect(
                    offset_x + x * CELL_SIZE,
                    offset_y + y * CELL_SIZE,
                    CELL_SIZE,
                    CELL_SIZE
                )
                
                # 墙
                if self.maze[y][x] == 1:
                    pygame.draw.rect(self.screen, COLORS["wall"], rect)
                    pygame.draw.rect(self.screen, (75, 140, 250), rect, 2)  # 边框
                # 路径
                else:
                    pygame.draw.rect(self.screen, COLORS["path"], rect)
                    
                    # 绘制道具
                    if (x, y) in self.props:
                        prop_type = self.props[(x, y)]
                        if prop_type == PropType.TELEPORT:
                            color = COLORS["prop1"]
                            icon = "T"
                        elif prop_type == PropType.VISION:
                            color = COLORS["prop2"]
                            icon = "V"
                        else:
                            color = COLORS["prop3"]
                            icon = "P"
                        
                        pygame.draw.circle(self.screen, color, rect.center, CELL_SIZE//3)
                        text = self.small_font.render(icon, True, COLORS["text"])
                        self.screen.blit(text, text.get_rect(center=rect.center))
        
        # 绘制出口
        exit_rect = pygame.Rect(
            offset_x + self.exit_pos[0] * CELL_SIZE,
            offset_y + self.exit_pos[1] * CELL_SIZE,
            CELL_SIZE,
            CELL_SIZE
        )
        pygame.draw.rect(self.screen, COLORS["exit"], exit_rect)
        pygame.draw.polygon(self.screen, COLORS["text"], [
            (exit_rect.centerx, exit_rect.top + 5),
            (exit_rect.right - 5, exit_rect.centery),
            (exit_rect.centerx, exit_rect.bottom - 5),
            (exit_rect.left + 5, exit_rect.centery)
        ])
        
        # 绘制玩家
        player_rect = pygame.Rect(
            offset_x + self.player_pos[0] * CELL_SIZE,
            offset_y + self.player_pos[1] * CELL_SIZE,
            CELL_SIZE,
            CELL_SIZE
        )
        pygame.draw.circle(self.screen, COLORS["player"], player_rect.center, CELL_SIZE//3 + 2)
        
        # 视野效果（只显示玩家周围区域）
        if not self.prop_effects["vision"]:
            mask_surface = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA)
            mask_surface.fill((0, 0, 0, 180))  # 半透明遮罩
            # 绘制可视区域
            vision_radius = 2  # 基础视野半径
            for dy in range(-vision_radius, vision_radius+1):
                for dx in range(-vision_radius, vision_radius+1):
                    nx, ny = self.player_pos[0] + dx, self.player_pos[1] + dy
                    if 0 <= nx < maze_width and 0 <= ny < maze_height:
                        vis_rect = pygame.Rect(
                            offset_x + nx * CELL_SIZE,
                            offset_y + ny * CELL_SIZE,
                            CELL_SIZE,
                            CELL_SIZE
                        )
                        mask_surface.fill((0, 0, 0, 0), vis_rect)
            self.screen.blit(mask_surface, (0, 0))

    def draw_ui(self):
        """绘制游戏UI"""
        # 时间显示
        if not self.prop_effects["pause"]:
            self.game_time = int(time.time() - self.start_time)
        time_text = self.small_font.render(f"时间: {self.game_time}s", True, COLORS["text"])
        self.screen.blit(time_text, (20, 20))
        
        # 得分显示
        score_text = self.small_font.render(f"得分: {self.score}", True, COLORS["text"])
        self.screen.blit(score_text, (20, 50))
        
        # 关卡显示
        level_text = self.small_font.render(f"关卡: {self.current_level}", True, COLORS["text"])
        self.screen.blit(level_text, (SCREEN_WIDTH - 120, 20))
        
        # 道具效果提示
        if self.prop_effects["vision"]:
            vision_text = self.small_font.render("视野扩大!", True, COLORS["prop2"])
            self.screen.blit(vision_text, (SCREEN_WIDTH - 120, 50))
        
        if self.prop_effects["pause"]:
            pause_text = self.small_font.render("时间暂停!", True, COLORS["prop3"])
            self.screen.blit(pause_text, (SCREEN_WIDTH - 120, 80))
        
        # 指法指引
        guide_text = self.small_font.render("↑↓←→ 移动 | 空格 使用瞬移道具", True, COLORS["highlight"])
        self.screen.blit(guide_text, (SCREEN_WIDTH//2 - 150, SCREEN_HEIGHT - 30))

    def draw_start_screen(self):
        """绘制开始界面"""
        self.screen.fill(COLORS["bg"])
        
        # 标题
        title_text = self.font.render("高级迷宫闯关游戏", True, COLORS["highlight"])
        self.screen.blit(title_text, title_text.get_rect(center=(SCREEN_WIDTH//2, SCREEN_HEIGHT//2 - 80)))
        
        # 开始按钮
        start_rect = pygame.Rect(SCREEN_WIDTH//2 - 100, SCREEN_HEIGHT//2, 200, 50)
        pygame.draw.rect(self.screen, COLORS["player"], start_rect, border_radius=10)
        start_text = self.font.render("开始游戏", True, COLORS["bg"])
        self.screen.blit(start_text, start_text.get_rect(center=start_rect.center))
        
        # 关卡选择按钮
        select_rect = pygame.Rect(SCREEN_WIDTH//2 - 100, SCREEN_HEIGHT//2 + 70, 200, 50)
        pygame.draw.rect(self.screen, COLORS["wall"], select_rect, border_radius=10)
        select_text = self.font.render("关卡选择", True, COLORS["text"])
        self.screen.blit(select_text, select_text.get_rect(center=select_rect.center))
        
        # 提示文字
        hint_text = self.small_font.render("收集道具可以获得特殊能力哦!", True, COLORS["text"])
        self.screen.blit(hint_text, hint_text.get_rect(center=(SCREEN_WIDTH//2, SCREEN_HEIGHT - 50)))
        
        return start_rect, select_rect

    def draw_level_select(self):
        """绘制关卡选择界面"""
        self.screen.fill(COLORS["bg"])
        
        # 标题
        title_text = self.font.render("选择关卡", True, COLORS["highlight"])
        self.screen.blit(title_text, title_text.get_rect(center=(SCREEN_WIDTH//2, 80)))
        
        # 关卡按钮
        level_rects = []
        for i in range(1, self.max_level + 1):
            x = SCREEN_WIDTH//2 + (i - (self.max_level + 1)//2) * 120
            y = SCREEN_HEIGHT//2
            rect = pygame.Rect(x - 40, y, 80, 80)
            
            # 解锁/锁定样式
            if i <= self.unlocked_levels:
                pygame.draw.rect(self.screen, COLORS["player"], rect, border_radius=10)
                level_text = self.font.render(str(i), True, COLORS["bg"])
            else:
                pygame.draw.rect(self.screen, (107, 114, 128), rect, border_radius=10)
                level_text = self.font.render("🔒", True, COLORS["text"])
            
            self.screen.blit(level_text, level_text.get_rect(center=rect.center))
            level_rects.append(rect)
        
        # 返回按钮
        back_rect = pygame.Rect(50, SCREEN_HEIGHT - 70, 100, 40)
        pygame.draw.rect(self.screen, (107, 114, 128), back_rect, border_radius=8)
        back_text = self.small_font.render("返回", True, COLORS["text"])
        self.screen.blit(back_text, back_text.get_rect(center=back_rect.center))
        
        return level_rects, back_rect

    def draw_win_screen(self):
        """绘制通关界面"""
        self.screen.fill(COLORS["bg"])
        
        # 通关文字
        win_text = self.font.render(f"恭喜通关! 关卡 {self.current_level}", True, COLORS["exit"])
        self.screen.blit(win_text, win_text.get_rect(center=(SCREEN_WIDTH//2, SCREEN_HEIGHT//2 - 80)))
        
        # 时间和得分
        time_text = self.small_font.render(f"用时: {self.game_time}s", True, COLORS["text"])
        self.screen.blit(time_text, (SCREEN_WIDTH//2 - 60, SCREEN_HEIGHT//2 - 20))
        
        score_text = self.small_font.render(f"最终得分: {self.score + (60 - self.game_time)}", True, COLORS["text"])
        self.screen.blit(score_text, (SCREEN_WIDTH//2 - 80, SCREEN_HEIGHT//2 + 20))
        
        # 按钮
        next_rect = pygame.Rect(SCREEN_WIDTH//2 - 110, SCREEN_HEIGHT//2 + 70, 100, 50)
        menu_rect = pygame.Rect(SCREEN_WIDTH//2 + 10, SCREEN_HEIGHT//2 + 70, 100, 50)
        
        # 下一关按钮（如果有）
        if self.current_level < self.max_level:
            pygame.draw.rect(self.screen, COLORS["player"], next_rect, border_radius=10)
            next_text = self.small_font.render("下一关", True, COLORS["bg"])
        else:
            pygame.draw.rect(self.screen, (107, 114, 128), next_rect, border_radius=10)
            next_text = self.small_font.render("已通关", True, COLORS["text"])
        
        # 主菜单按钮
        pygame.draw.rect(self.screen, COLORS["wall"], menu_rect, border_radius=10)
        menu_text = self.small_font.render("主菜单", True, COLORS["text"])
        
        self.screen.blit(next_text, next_text.get_rect(center=next_rect.center))
        self.screen.blit(menu_text, menu_text.get_rect(center=menu_rect.center))
        
        return next_rect, menu_rect

    def handle_input(self):
        """处理玩家输入"""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            
            # 键盘输入
            if event.type == pygame.KEYDOWN:
                if self.game_state == "game" and not self.prop_effects["pause"]:
                    # 移动控制
                    px, py = self.player_pos
                    if event.key == pygame.K_UP and self.maze[py-1][px] == 0:
                        self.player_pos = (px, py-1)
                    elif event.key == pygame.K_DOWN and self.maze[py+1][px] == 0:
                        self.player_pos = (px, py+1)
                    elif event.key == pygame.K_LEFT and self.maze[py][px-1] == 0:
                        self.player_pos = (px-1, py)
                    elif event.key == pygame.K_RIGHT and self.maze[py][px+1] == 0:
                        self.player_pos = (px+1, py)
                    # 使用瞬移道具
                    elif event.key == pygame.K_SPACE and self.prop_effects["teleport_used"]:
                        self.player_pos = self.exit_pos
                        self.prop_effects["teleport_used"] = False
                
                # 回车键（开始/重新开始）
                elif event.key == pygame.K_RETURN:
                    if self.game_state == "start":
                        self.game_state = "game"
                    elif self.game_state == "win":
                        self.game_state = "game"
                        self.load_level(self.current_level)
            
            # 鼠标点击
            if event.type == pygame.MOUSEBUTTONDOWN:
                mouse_pos = pygame.mouse.get_pos()
                
                # 开始界面按钮
                if self.game_state == "start":
                    start_rect, select_rect = self.draw_start_screen()
                    if start_rect.collidepoint(mouse_pos):
                        self.game_state = "game"
                        self.load_level(self.current_level)
                    elif select_rect.collidepoint(mouse_pos):
                        self.game_state = "select"
                
                # 关卡选择界面
                elif self.game_state == "select":
                    level_rects, back_rect = self.draw_level_select()
                    # 选择关卡
                    for i, rect in enumerate(level_rects):
                        if rect.collidepoint(mouse_pos) and (i+1) <= self.unlocked_levels:
                            self.current_level = i+1
                            self.game_state = "game"
                            self.load_level(self.current_level)
                            break
                    # 返回按钮
                    if back_rect.collidepoint(mouse_pos):
                        self.game_state = "start"
                
                # 通关界面按钮
                elif self.game_state == "win":
                    next_rect, menu_rect = self.draw_win_screen()
                    if next_rect.collidepoint(mouse_pos) and self.current_level < self.max_level:
                        self.current_level += 1
                        self.unlocked_levels = max(self.unlocked_levels, self.current_level)
                        self.game_state = "game"
                        self.load_level(self.current_level)
                    elif menu_rect.collidepoint(mouse_pos):
                        self.game_state = "start"

    def check_collisions(self):
        """检查碰撞（道具/出口）"""
        # 到达出口
        if self.player_pos == self.exit_pos:
            self.game_state = "win"
            self.score += 100 - self.game_time  # 时间越短得分越高
            if self.current_level >= self.unlocked_levels:
                self.unlocked_levels += 1
        
        # 收集道具
        if self.player_pos in self.props:
            prop_type = self.props[self.player_pos]
            self.score += 20  # 收集道具加分
            
            # 应用道具效果
            if prop_type == PropType.TELEPORT:
                self.prop_effects["teleport_used"] = True
                self.score += 10
            elif prop_type == PropType.VISION:
                self.prop_effects["vision"] = True
                self.score += 10
            elif prop_type == PropType.PAUSE:
                self.prop_effects["pause"] = True
                # 暂停5秒
                pygame.time.set_timer(pygame.USEREVENT, 5000)
                self.score += 10
            
            # 移除已收集的道具
            del self.props[self.player_pos]

    def handle_events(self):
        """处理游戏事件（如道具时间结束）"""
        for event in pygame.event.get():
            if event.type == pygame.USEREVENT:
                self.prop_effects["pause"] = False
                pygame.time.set_timer(pygame.USEREVENT, 0)

    def run(self):
        """游戏主循环"""
        while True:
            # 处理输入
            self.handle_input()
            self.handle_events()
            
            # 绘制界面
            if self.game_state == "start":
                self.draw_start_screen()
            elif self.game_state == "select":
                self.draw_level_select()
            elif self.game_state == "win":
                self.draw_win_screen()
            elif self.game_state == "game":
                # 检查碰撞
                self.check_collisions()
                # 绘制游戏内容
                self.draw_maze()
                self.draw_ui()
            
            # 更新屏幕
            pygame.display.flip()
            self.clock.tick(FPS)

# -------------------------- 运行游戏 --------------------------
if __name__ == "__main__":
    # 安装依赖（如果未安装）
    try:
        import pygame
    except ImportError:
        import os
        os.system("pip install pygame")
        import pygame
    
    game = MazeGame()
    game.run()