import pygame
import random
import sys

# 初始化Pygame
pygame.init()

# 游戏常量
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
TILE_SIZE = 32
FPS = 30

# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
GRAY = (128, 128, 128)
LIGHT_GRAY = (200, 200, 200)
DARK_GRAY = (50, 50, 50)

# 游戏状态
STATE_MENU = 0
STATE_EXPLORING = 1
STATE_COMBAT = 2
STATE_GAME_OVER = 3

class Character:
    """基础角色类，包含战斗属性和方法"""
    def __init__(self, name, hp, attack, defense):
        self.name = name
        self.hp = hp
        self.max_hp = hp
        self.attack = attack
        self.defense = defense
        self.is_alive = True
        self.is_defending = False
        self.mana = 50
        self.max_mana = 50
        self.special_cost = 20

    def take_damage(self, damage):
        if self.is_defending:
            damage = damage // 2
            self.is_defending = False
        
        self.hp -= damage
        if self.hp <= 0:
            self.hp = 0
            self.is_alive = False
        return damage

    def attack_target(self, target):
        damage = max(0, self.attack - target.defense)
        actual_damage = target.take_damage(damage)
        return actual_damage

    def defend(self):
        self.is_defending = True
        return f"{self.name} 进入防御姿态"

    def special_ability(self, target):
        if self.mana >= self.special_cost:
            self.mana -= self.special_cost
            damage = max(0, self.attack * 2 - target.defense)
            actual_damage = target.take_damage(damage)
            return f"强力一击！{actual_damage}点伤害"
        else:
            return "魔力不足"

class Player(pygame.sprite.Sprite, Character):
    def __init__(self, x, y):
        pygame.sprite.Sprite.__init__(self)
        Character.__init__(self, "勇者", hp=100, attack=15, defense=5)
        self.image = pygame.Surface([TILE_SIZE, TILE_SIZE])
        self.image.fill(GREEN)
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y

    def move(self, dx, dy, dungeon):
        new_x = self.rect.x + dx
        new_y = self.rect.y + dy
        tile_x = new_x // TILE_SIZE
        tile_y = new_y // TILE_SIZE
        
        if 0 <= tile_x < dungeon.width and 0 <= tile_y < dungeon.height:
            if dungeon.grid[tile_y][tile_x] == 0:
                self.rect.x = new_x
                self.rect.y = new_y
                return True
        return False

class Enemy(pygame.sprite.Sprite, Character):
    def __init__(self, x, y, enemy_type="史莱姆"):
        pygame.sprite.Sprite.__init__(self)
        if enemy_type == "史莱姆":
            Character.__init__(self, "史莱姆", hp=40, attack=8, defense=2)
            self.image = pygame.Surface([TILE_SIZE, TILE_SIZE])
            self.image.fill(RED)
        elif enemy_type == "骷髅兵":
            Character.__init__(self, "骷髅兵", hp=60, attack=12, defense=5)
            self.image = pygame.Surface([TILE_SIZE, TILE_SIZE])
            self.image.fill((150, 150, 150))
        
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y

class Dungeon:
    def __init__(self, width, height):
        self.width = width
        self.height = height
        self.grid = [[1 for _ in range(width)] for _ in range(height)]
        self.generate()

    def generate(self):
        def carve(x, y):
            self.grid[y][x] = 0
            directions = [(0, 2), (2, 0), (0, -2), (-2, 0)]
            random.shuffle(directions)
            
            for dx, dy in directions:
                nx, ny = x + dx, y + dy
                if 0 < nx < self.width - 1 and 0 < ny < self.height - 1 and self.grid[ny][nx] == 1:
                    self.grid[y + dy//2][x + dx//2] = 0
                    carve(nx, ny)
        
        start_x = random.randint(1, self.width - 2)
        start_y = random.randint(1, self.height - 2)
        carve(start_x, start_y)

class Button:
    def __init__(self, x, y, width, height, text, color, hover_color, action=None):
        self.rect = pygame.Rect(x, y, width, height)
        self.text = text
        self.color = color
        self.hover_color = hover_color
        self.action = action
        # 🔥 修复：使用 Pygame 内置字体，永不报错！
        self.font = pygame.font.Font(pygame.font.get_default_font(), 32)

    def draw(self, screen):
        mouse_pos = pygame.mouse.get_pos()
        color = self.hover_color if self.rect.collidepoint(mouse_pos) else self.color
        
        pygame.draw.rect(screen, color, self.rect)
        pygame.draw.rect(screen, WHITE, self.rect, 2)

        text_surf = self.font.render(self.text, True, WHITE)
        text_rect = text_surf.get_rect(center=self.rect.center)
        screen.blit(text_surf, text_rect)

    def is_clicked(self, event):
        if event.type == pygame.MOUSEBUTTONDOWN:
            return self.rect.collidepoint(event.pos)
        return False

def draw_health_bar(screen, x, y, width, height, current, maximum, color=GREEN):
    pygame.draw.rect(screen, GRAY, (x, y, width, height))
    ratio = current / maximum
    current_width = int(width * ratio)
    pygame.draw.rect(screen, color, (x, y, current_width, height))
    pygame.draw.rect(screen, WHITE, (x, y, width, height), 2)

def draw_mana_bar(screen, x, y, width, height, current, maximum):
    pygame.draw.rect(screen, GRAY, (x, y, width, height))
    ratio = current / maximum
    current_width = int(width * ratio)
    pygame.draw.rect(screen, BLUE, (x, y, current_width, height))
    pygame.draw.rect(screen, WHITE, (x, y, width, height), 2)

def main():
    screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
    pygame.display.set_caption("迷宫战斗")
    clock = pygame.time.Clock()

    # 🔥 终极修复：全部用内置默认字体，100%不报错
    font = pygame.font.Font(pygame.font.get_default_font(), 32)
    small_font = pygame.font.Font(pygame.font.get_default_font(), 24)

    game_state = STATE_MENU
    current_enemy = None
    combat_log = []
    player_turn = True

    start_button = Button(300, 250, 200, 50, "START", DARK_GRAY, LIGHT_GRAY, "start")
    restart_button = Button(300, 350, 200, 50, "RETRY", DARK_GRAY, LIGHT_GRAY, "restart")
    attack_button = Button(150, 450, 150, 50, "ATK", DARK_GRAY, LIGHT_GRAY, "attack")
    special_button = Button(325, 450, 150, 50, "SKILL", DARK_GRAY, LIGHT_GRAY, "special")
    defend_button = Button(500, 450, 150, 50, "DEF", DARK_GRAY, LIGHT_GRAY, "defend")

    dungeon = None
    player = None
    enemies = None
    all_sprites = None

    def init_game():
        nonlocal dungeon, player, enemies, all_sprites
        dungeon_width = SCREEN_WIDTH // TILE_SIZE
        dungeon_height = SCREEN_HEIGHT // TILE_SIZE
        dungeon = Dungeon(dungeon_width, dungeon_height)
        
        start_x, start_y = 1, 1
        for y in range(dungeon_height):
            for x in range(dungeon_width):
                if dungeon.grid[y][x] == 0:
                    start_x = x * TILE_SIZE
                    start_y = y * TILE_SIZE
                    break
            else:
                continue
            break
        
        player = Player(start_x, start_y)
        enemies = pygame.sprite.Group()
        all_sprites = pygame.sprite.Group()
        all_sprites.add(player)

        enemy_count = 5
        enemy_types = ["史莱姆", "骷髅兵"]
        for _ in range(enemy_count):
            while True:
                x = random.randint(1, dungeon_width - 2)
                y = random.randint(1, dungeon_height - 2)
                if dungeon.grid[y][x] == 0:
                    px = player.rect.x // TILE_SIZE
                    py = player.rect.y // TILE_SIZE
                    if abs(x - px) > 5 or abs(y - py) > 5:
                        break
            enemy_type = random.choice(enemy_types)
            enemy = Enemy(x * TILE_SIZE, y * TILE_SIZE, enemy_type)
            enemies.add(enemy)
            all_sprites.add(enemy)

    running = True
    while running:
        screen.fill(BLACK)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False

            if game_state == STATE_MENU:
                if start_button.is_clicked(event):
                    init_game()
                    game_state = STATE_EXPLORING

            elif game_state == STATE_EXPLORING:
                if event.type == pygame.KEYDOWN:
                    dx, dy = 0, 0
                    if event.key == pygame.K_LEFT:
                        dx = -TILE_SIZE
                    elif event.key == pygame.K_RIGHT:
                        dx = TILE_SIZE
                    elif event.key == pygame.K_UP:
                        dy = -TILE_SIZE
                    elif event.key == pygame.K_DOWN:
                        dy = TILE_SIZE
                    
                    if dx != 0 or dy != 0:
                        moved = player.move(dx, dy, dungeon)
                        if moved:
                            for enemy in enemies:
                                ex, ey = 0, 0
                                if player.rect.x > enemy.rect.x: ex = TILE_SIZE
                                elif player.rect.x < enemy.rect.x: ex = -TILE_SIZE
                                if player.rect.y > enemy.rect.y: ey = TILE_SIZE
                                elif player.rect.y < enemy.rect.y: ey = -TILE_SIZE
                                
                                new_x = enemy.rect.x + ex
                                new_y = enemy.rect.y + ey
                                tx = new_x // TILE_SIZE
                                ty = new_y // TILE_SIZE
                                
                                if 0 <= tx < dungeon.width and 0 <= ty < dungeon.height:
                                    if dungeon.grid[ty][tx] == 0:
                                        enemy.rect.x = new_x
                                        enemy.rect.y = new_y
                            
                            hits = pygame.sprite.spritecollide(player, enemies, False)
                            if hits:
                                current_enemy = hits[0]
                                combat_log = ["FIGHT!"]
                                player_turn = True
                                game_state = STATE_COMBAT

            elif game_state == STATE_COMBAT:
                if player_turn:
                    if attack_button.is_clicked(event):
                        d = player.attack_target(current_enemy)
                        combat_log.append(f"ATK:{d}")
                        if not current_enemy.is_alive:
                            enemies.remove(current_enemy)
                            all_sprites.remove(current_enemy)
                            game_state = STATE_EXPLORING
                        else:
                            player_turn = False
                    elif special_button.is_clicked(event):
                        combat_log.append(player.special_ability(current_enemy))
                        if not current_enemy.is_alive:
                            enemies.remove(current_enemy)
                            all_sprites.remove(current_enemy)
                            game_state = STATE_EXPLORING
                        else:
                            player_turn = False
                    elif defend_button.is_clicked(event):
                        combat_log.append(player.defend())
                        player_turn = False

            elif game_state == STATE_GAME_OVER:
                if restart_button.is_clicked(event):
                    init_game()
                    game_state = STATE_EXPLORING

        if game_state == STATE_COMBAT and not player_turn and current_enemy and current_enemy.is_alive:
            pygame.time.delay(500)
            if random.random() < 0.7:
                d = current_enemy.attack_target(player)
                combat_log.append(f"Enemy ATK: {d}")
            else:
                combat_log.append("Enemy DEF")
            
            if not player.is_alive:
                game_state = STATE_GAME_OVER
            else:
                player_turn = True
            
            if len(combat_log) > 4:
                combat_log = combat_log[-4:]

        if game_state == STATE_MENU:
            screen.blit(font.render("MAZE COMBAT", True, WHITE), (300, 150))
            start_button.draw(screen)

        elif game_state == STATE_EXPLORING:
            for y in range(dungeon.height):
                for x in range(dungeon.width):
                    xx = x*TILE_SIZE
                    yy = y*TILE_SIZE
                    if dungeon.grid[y][x] == 1:
                        pygame.draw.rect(screen, GRAY, (xx, yy, TILE_SIZE, TILE_SIZE))
                    else:
                        pygame.draw.rect(screen, DARK_GRAY, (xx, yy, TILE_SIZE, TILE_SIZE))
            
            all_sprites.draw(screen)
            screen.blit(small_font.render(f"HP:{player.hp}", True, WHITE), (10,10))
            draw_health_bar(screen,10,30,150,15,player.hp,player.max_hp)

        elif game_state == STATE_COMBAT:
            pygame.draw.rect(screen, DARK_GRAY, (0,0,SCREEN_WIDTH, SCREEN_HEIGHT))
            screen.blit(font.render("YOU", True, WHITE), (50,50))
            draw_health_bar(screen,50,80,200,20,player.hp, player.max_hp)
            pygame.draw.rect(screen, GREEN, (100,200,100,100))

            screen.blit(font.render("ENEMY", True, WHITE), (550,50))
            draw_health_bar(screen,550,80,200,20,current_enemy.hp, current_enemy.max_hp, RED)
            pygame.draw.rect(screen, RED, (550,200,100,100))

            ypos = 330
            for txt in combat_log:
                screen.blit(small_font.render(txt, True, WHITE), (50, ypos))
                ypos += 22

            if player_turn:
                attack_button.draw(screen)
                special_button.draw(screen)
                defend_button.draw(screen)

        elif game_state == STATE_GAME_OVER:
            screen.blit(font.render("GAME OVER", True, RED), (330, 250))
            restart_button.draw(screen)

        pygame.display.flip()
        clock.tick(FPS)

    pygame.quit()
    sys.exit()

if __name__ == "__main__":
    main()