import pygame
import random
import sys
import math
from enum import Enum
from collections import deque

# ==================== 初始化 ====================
pygame.init()
WINDOW_WIDTH = 1024
WINDOW_HEIGHT = 768
FPS = 60

# ==================== 颜色 ====================
COLORS = {
    'bg': (20, 20, 25),
    'wall_l0': (180, 160, 130),
    'wall_l0_dark': (140, 120, 95),
    'floor_l0': (210, 190, 165),
    'wall_l1': (130, 130, 140),
    'wall_l1_dark': (100, 100, 110),
    'floor_l1': (80, 80, 90),
    'wall_l2': (150, 100, 80),
    'wall_l2_dark': (120, 75, 55),
    'floor_l2': (100, 70, 60),
    'wall_l3': (90, 120, 80),
    'wall_l3_dark': (70, 100, 60),
    'floor_l3': (110, 140, 100),
    'player': (70, 150, 220),
    'player_glow': (100, 200, 255),
    'exit': (60, 200, 80),
    'exit_glow': (100, 255, 150),
    'item': (255, 220, 100),
    'item_glow': (255, 240, 150),
    'monster': (200, 50, 50),
    'monster_eye': (255, 255, 200),
    'hunter': (180, 50, 50),
    'smiler': (255, 200, 200),
    'ui_bg': (10, 10, 15, 200),
    'text': (220, 210, 190),
    'text_dark': (150, 140, 130),
    'danger': (230, 80, 80),
    'sanity_bar': (80, 200, 80),
    'sanity_bar_low': (230, 80, 80),
    'fog': (10, 10, 15),
    'stamina_bar': (100, 180, 255),
}

# ==================== 游戏常量 ====================
MAP_W, MAP_H = 60, 60
CELL_SIZE = 16
ROOM_MIN, ROOM_MAX = 4, 9
VIEW_RADIUS = 7
TORCH_RADIUS = 4
TORCH_DURATION = 300
SANITY_MAX = 100
SANITY_DRAIN = 0.012
MONSTER_DETECT = 6
MOVE_SPEED = 0.12
MOVE_SPEED_SPRINT = 0.22
SPRINT_COST = 0.3
STAMINA_MAX = 100
STAMINA_REGEN = 0.08
HOLD_DELAY = 10
MOVE_COOLDOWN = 2
TOTAL_LEVELS = 40

# ==================== 字体 ====================
def get_font(size):
    return pygame.font.Font(None, size)

font_small = get_font(18)
font_medium = get_font(26)
font_large = get_font(38)
font_title = get_font(48)

# ==================== 辅助函数 ====================
def dist(a, b):
    return math.hypot(a[0]-b[0], a[1]-b[1])

# ==================== 地图生成 ====================
class Room:
    def __init__(self, x, y, w, h):
        self.x, self.y, self.w, self.h = x, y, w, h
        self.cx, self.cy = x + w//2, y + h//2

def generate_dungeon(w, h, room_count=30, theme=0):
    dungeon = [[1 for _ in range(w)] for _ in range(h)]
    rooms = []
    for _ in range(room_count * 3):
        rw = random.randint(ROOM_MIN, ROOM_MAX)
        rh = random.randint(ROOM_MIN, ROOM_MAX)
        rx = random.randint(1, w - rw - 1)
        ry = random.randint(1, h - rh - 1)
        new_room = Room(rx, ry, rw, rh)
        overlap = False
        for r in rooms:
            if (rx < r.x + r.w + 1 and rx + rw + 1 > r.x and
                ry < r.y + r.h + 1 and ry + rh + 1 > r.y):
                overlap = True
                break
        if not overlap:
            rooms.append(new_room)
            for iy in range(ry, ry + rh):
                for ix in range(rx, rx + rw):
                    dungeon[iy][ix] = 0
    for i in range(len(rooms)-1):
        x1, y1 = rooms[i].cx, rooms[i].cy
        x2, y2 = rooms[i+1].cx, rooms[i+1].cy
        for x in range(min(x1,x2), max(x1,x2)+1):
            dungeon[y1][x] = 0
        for y in range(min(y1,y2), max(y1,y2)+1):
            dungeon[y][x2] = 0
    furniture = []
    for r in rooms:
        if random.random() < 0.35:
            fx = r.x + random.randint(1, r.w-2)
            fy = r.y + random.randint(1, r.h-2)
            if dungeon[fy][fx] == 0:
                dungeon[fy][fx] = 2
                furniture.append((fx, fy))
    return dungeon, rooms, furniture

# ==================== 物品 ====================
class ItemType(Enum):
    KEY = 1
    NOTE = 2
    ALMOND_WATER = 3
    TORCH = 4
    BANDAGE = 5
    PASSWORD = 6
    LEVER = 7
    BATTERY = 8
    MEDKIT = 9
    MAP = 10

class Item:
    def __init__(self, x, y, item_type, extra=""):
        self.x, self.y = x, y
        self.type = item_type
        self.extra = extra
        self.collected = False

    @staticmethod
    def get_name(item_type):
        return {
            ItemType.KEY: "Key",
            ItemType.NOTE: "Note",
            ItemType.ALMOND_WATER: "Almond Water",
            ItemType.TORCH: "Torch",
            ItemType.BANDAGE: "Bandage",
            ItemType.PASSWORD: "Password",
            ItemType.LEVER: "Lever",
            ItemType.BATTERY: "Battery",
            ItemType.MEDKIT: "Medkit",
            ItemType.MAP: "Map",
        }.get(item_type, "Unknown")

    @staticmethod
    def get_color(item_type):
        """返回物品在物品栏和地图上的基础颜色（用于发光）"""
        return {
            ItemType.KEY: (200, 180, 100),        # 金色
            ItemType.NOTE: (220, 220, 180),       # 米白
            ItemType.ALMOND_WATER: (180, 220, 255), # 淡蓝
            ItemType.TORCH: (255, 220, 100),      # 橙色
            ItemType.BANDAGE: (255, 180, 180),    # 淡红
            ItemType.PASSWORD: (200, 200, 200),   # 银灰
            ItemType.LEVER: (180, 180, 220),      # 淡紫
            ItemType.BATTERY: (255, 200, 50),     # 亮黄
            ItemType.MEDKIT: (255, 100, 100),     # 红色
            ItemType.MAP: (200, 200, 255),        # 淡蓝紫
        }.get(item_type, (200,200,200))

    @staticmethod
    def get_emoji(item_type):
        return {
            ItemType.KEY: "🔑",
            ItemType.NOTE: "📄",
            ItemType.ALMOND_WATER: "🧊",
            ItemType.TORCH: "🔦",
            ItemType.BANDAGE: "🩹",
            ItemType.PASSWORD: "🔐",
            ItemType.LEVER: "🎛️",
            ItemType.BATTERY: "🔋",
            ItemType.MEDKIT: "💊",
            ItemType.MAP: "🗺️",
        }.get(item_type, "❓")

# ==================== 怪物系统（10种） ====================
MONSTER_TYPES = [
    "hunter", "smiler", "chaser", "stalker", "brute",
    "swift", "phantom", "spitter", "lurker", "shambler"
]

class Monster:
    def __init__(self, x, y, mtype="hunter"):
        self.x, self.y = x, y
        self.type = mtype
        self.state = "idle"
        self.move_timer = 0
        self.direction = random.choice([(0,1),(0,-1),(1,0),(-1,0)])
        self.attack_cooldown = 0
        self.health = 1

        if mtype == "hunter":
            self.detect_range = 6
            self.speed = 0.02
            self.chase_speed = 0.07
            self.damage = 12
            self.attack_range = 1.2
            self.color = (180, 50, 50)
        elif mtype == "smiler":
            self.detect_range = 4
            self.speed = 0.015
            self.chase_speed = 0.04
            self.damage = 10
            self.attack_range = 1.0
            self.color = (255, 200, 200)
            self.invisible = True
        elif mtype == "chaser":
            self.detect_range = 12
            self.speed = 0.05
            self.chase_speed = 0.12
            self.damage = 15
            self.attack_range = 0.8
            self.color = (200, 0, 0)
        elif mtype == "stalker":
            self.detect_range = 3
            self.speed = 0.01
            self.chase_speed = 0.03
            self.damage = 8
            self.attack_range = 1.0
            self.color = (80, 80, 80)
        elif mtype == "brute":
            self.detect_range = 5
            self.speed = 0.008
            self.chase_speed = 0.02
            self.damage = 25
            self.attack_range = 1.5
            self.color = (150, 50, 150)
            self.health = 3
        elif mtype == "swift":
            self.detect_range = 8
            self.speed = 0.04
            self.chase_speed = 0.15
            self.damage = 6
            self.attack_range = 0.7
            self.color = (50, 200, 200)
        elif mtype == "phantom":
            self.detect_range = 7
            self.speed = 0.02
            self.chase_speed = 0.06
            self.damage = 14
            self.attack_range = 1.3
            self.color = (200, 200, 255)
            self.teleport_timer = 0
        elif mtype == "spitter":
            self.detect_range = 9
            self.speed = 0.01
            self.chase_speed = 0.02
            self.damage = 18
            self.attack_range = 3.0
            self.color = (100, 200, 100)
            self.spit_cooldown = 0
        elif mtype == "lurker":
            self.detect_range = 5
            self.speed = 0.015
            self.chase_speed = 0.04
            self.damage = 10
            self.attack_range = 1.0
            self.color = (100, 100, 60)
            self.lurking = True
        elif mtype == "shambler":
            self.detect_range = 4
            self.speed = 0.005
            self.chase_speed = 0.01
            self.damage = 30
            self.attack_range = 1.6
            self.color = (80, 40, 40)
            self.health = 2

        self.speed *= random.uniform(0.9, 1.1)
        self.chase_speed *= random.uniform(0.9, 1.1)

    def update(self, player_pos, dungeon, player):
        dx = player_pos[0] - self.x
        dy = player_pos[1] - self.y
        d = math.hypot(dx, dy)

        if self.type == "phantom" and self.state == "chase" and d > 8:
            self.teleport_timer -= 1
            if self.teleport_timer <= 0 and d > 3:
                angle = random.uniform(0, 2*math.pi)
                r = random.uniform(2, 4)
                nx = player_pos[0] + math.cos(angle)*r
                ny = player_pos[1] + math.sin(angle)*r
                gx, gy = int(round(nx)), int(round(ny))
                if 0 <= gx < len(dungeon[0]) and 0 <= gy < len(dungeon) and dungeon[gy][gx] == 0:
                    self.x, self.y = nx, ny
                self.teleport_timer = random.randint(60, 180)

        see = self.has_line_of_sight(player_pos, dungeon)
        if self.type == "smiler" and player.sanity > 60:
            see = False

        if d < self.detect_range and see:
            self.state = "chase"
        elif d < self.detect_range * 1.5:
            self.state = "chase"
        else:
            self.state = "idle"

        if self.attack_cooldown > 0:
            self.attack_cooldown -= 1

        if d < self.attack_range and self.attack_cooldown == 0:
            self.attack_cooldown = 30
            return True

        if self.state == "idle":
            self.move_timer -= 1
            if self.move_timer <= 0:
                self.direction = random.choice([(0,1),(0,-1),(1,0),(-1,0)])
                self.move_timer = random.randint(20, 80)
            self.try_move(self.direction[0], self.direction[1], dungeon)
        elif self.state == "chase":
            if d > 0.5:
                step_x = dx / d * self.chase_speed
                step_y = dy / d * self.chase_speed
                self.try_move(step_x, 0, dungeon)
                self.try_move(0, step_y, dungeon)

        return False

    def try_move(self, dx, dy, dungeon):
        nx, ny = self.x + dx, self.y + dy
        gx, gy = int(round(nx)), int(round(ny))
        if 0 <= gx < len(dungeon[0]) and 0 <= gy < len(dungeon):
            if dungeon[gy][gx] == 0:
                self.x, self.y = nx, ny
                return True
        return False

    def has_line_of_sight(self, target, dungeon):
        x0, y0 = int(round(self.x)), int(round(self.y))
        x1, y1 = int(round(target[0])), int(round(target[1]))
        dx = abs(x1-x0); dy = -abs(y1-y0)
        sx = 1 if x0<x1 else -1
        sy = 1 if y0<y1 else -1
        err = dx + dy
        while True:
            if (x0,y0) == (x1,y1):
                return True
            if dungeon[y0][x0] == 1 or dungeon[y0][x0] == 2:
                return False
            e2 = 2*err
            if e2 >= dy:
                err += dy; x0 += sx
            if e2 <= dx:
                err += dx; y0 += sy

    def take_damage(self):
        self.health -= 1
        return self.health <= 0

# ==================== 玩家 ====================
class Player:
    def __init__(self, x, y):
        self.x = float(x)
        self.y = float(y)
        self.grid_x = x
        self.grid_y = y
        self.moving = False
        self.move_progress = 0.0
        self.move_from = (0.0, 0.0)
        self.move_to = (0.0, 0.0)
        self.move_speed = MOVE_SPEED
        self.move_queue = deque()
        self.hold_timer = 0
        self.move_cooldown = 0
        self.sanity = SANITY_MAX
        self.health = 100
        self.max_health = 100
        self.stamina = STAMINA_MAX
        self.max_stamina = STAMINA_MAX
        self.inventory = []
        self.inv_limit = 8
        self.torch_active = False
        self.torch_timer = 0
        self.steps = 0
        self.attack_cooldown = 0
        self.hit_flash = 0
        self.has_key = False
        self.found_password = False
        self.password = ""
        self.sprinting = False
        self.levers_pulled = 0
        self.monsters_killed = 0
        self.items_collected = 0
        self.levels_completed = 0

    def start_move(self, dx, dy, dungeon, sprint=False):
        if self.moving or self.move_cooldown > 0:
            self.move_queue.append((dx, dy))
            return
        nx = self.grid_x + dx
        ny = self.grid_y + dy
        if 0 <= nx < len(dungeon[0]) and 0 <= ny < len(dungeon):
            cell = dungeon[int(ny)][int(nx)]
            if cell == 0:
                self.move_from = (self.x, self.y)
                self.move_to = (float(nx), float(ny))
                self.moving = True
                self.move_progress = 0.0
                self.grid_x = int(nx)
                self.grid_y = int(ny)
                self.move_speed = MOVE_SPEED_SPRINT if sprint else MOVE_SPEED
                self.steps += 1
                self.move_cooldown = MOVE_COOLDOWN
                return True
            elif cell == 3:
                return "locked"
            elif cell == 4:
                return "password"
            elif cell == 5:
                return "lever"
        return False

    def update(self, dungeon):
        if self.move_cooldown > 0:
            self.move_cooldown -= 1
        if self.moving:
            self.move_progress += self.move_speed
            if self.move_progress >= 1.0:
                self.move_progress = 1.0
                self.x, self.y = self.move_to
                self.moving = False
                if self.move_queue:
                    dx, dy = self.move_queue.popleft()
                    self.start_move(dx, dy, dungeon, self.sprinting)
            else:
                t = self.move_progress
                t = t * t * (3 - 2 * t)
                self.x = self.move_from[0] + (self.move_to[0] - self.move_from[0]) * t
                self.y = self.move_from[1] + (self.move_to[1] - self.move_from[1]) * t
        if not self.sprinting:
            self.stamina = min(self.max_stamina, self.stamina + STAMINA_REGEN)
        self.sanity = max(0, self.sanity - SANITY_DRAIN * (0.8 + 0.2 * (1 - self.sanity/SANITY_MAX)))
        if self.torch_active:
            self.torch_timer -= 1
            if self.torch_timer <= 0:
                self.torch_active = False
        if self.attack_cooldown > 0:
            self.attack_cooldown -= 1
        if self.hit_flash > 0:
            self.hit_flash -= 1

    def get_pos(self):
        return (self.x, self.y)

    def get_cell(self):
        return (int(round(self.grid_x)), int(round(self.grid_y)))

    def use_item(self, idx):
        if idx < len(self.inventory):
            item_type = self.inventory.pop(idx)
            if item_type == ItemType.ALMOND_WATER:
                self.sanity = min(SANITY_MAX, self.sanity + 25)
            elif item_type == ItemType.TORCH:
                self.torch_active = True
                self.torch_timer = TORCH_DURATION
            elif item_type == ItemType.BANDAGE:
                self.health = min(self.max_health, self.health + 20)
            elif item_type == ItemType.KEY:
                self.has_key = True
            elif item_type == ItemType.PASSWORD:
                self.found_password = True
            elif item_type == ItemType.LEVER:
                self.levers_pulled += 1
            elif item_type == ItemType.BATTERY:
                if self.torch_active:
                    self.torch_timer = min(TORCH_DURATION, self.torch_timer + 150)
                else:
                    self.torch_active = True
                    self.torch_timer = 150
            elif item_type == ItemType.MEDKIT:
                self.health = min(self.max_health, self.health + 40)
            elif item_type == ItemType.MAP:
                pass
            self.items_collected += 1
            return True
        return False

    def pick_item(self, items):
        cx, cy = self.get_cell()
        for item in items:
            if not item.collected and abs(item.x-cx)<=1 and abs(item.y-cy)<=1:
                if len(self.inventory) < self.inv_limit:
                    if item.type == ItemType.KEY:
                        self.has_key = True
                        item.collected = True
                        self.items_collected += 1
                        return True
                    if item.type == ItemType.PASSWORD:
                        self.found_password = True
                        self.password = item.extra
                        item.collected = True
                        self.items_collected += 1
                        return True
                    if item.type == ItemType.LEVER:
                        self.levers_pulled += 1
                        item.collected = True
                        self.items_collected += 1
                        return True
                    self.inventory.append(item.type)
                    item.collected = True
                    self.items_collected += 1
                    return True
        return False

# ==================== 关卡管理器 ====================
class Level:
    def __init__(self, level_id):
        self.id = level_id
        theme = level_id % 4
        difficulty = min(level_id // 10, 3)
        room_count = 30 + difficulty * 5
        self.dungeon, self.rooms, self.furniture = generate_dungeon(MAP_W, MAP_H, room_count, theme)
        self.width, self.height = len(self.dungeon[0]), len(self.dungeon)
        start_room = self.rooms[0]
        exit_room = self.rooms[-1]
        self.start = (start_room.cx, start_room.cy)
        self.exit = (exit_room.cx, exit_room.cy)
        self.items = []
        self.monsters = []
        self.locked_doors = []
        self.password_doors = []
        self.lever_doors = []
        self.chase_monster = None
        self.setup_level()

    def setup_level(self):
        level = self.id
        base_items = [ItemType.ALMOND_WATER, ItemType.TORCH, ItemType.BANDAGE]
        if random.random() < 0.3:
            base_items.append(ItemType.MEDKIT)
        if random.random() < 0.2:
            base_items.append(ItemType.MAP)

        puzzle = level % 3
        if puzzle == 0:
            base_items.append(ItemType.KEY)
            self.place_locked_door()
        elif puzzle == 1:
            need = 1 + (level % 3)
            base_items.append(ItemType.LEVER)
            self.place_lever_door(need)
        else:
            base_items.append(ItemType.PASSWORD)
            self.place_password_door()

        count = 12 + level % 6
        self.spawn_items(base_items, count)

        monster_count = 2 + (level % 5) + (level // 10)
        self.spawn_monsters(monster_count)

        if level > 5 and random.random() < 0.2:
            self.place_chase_sequence()

    def spawn_items(self, types, count):
        for _ in range(count):
            x = random.randint(2, self.width-3)
            y = random.randint(2, self.height-3)
            if self.dungeon[y][x] == 0 and (x,y) != self.start and (x,y) != self.exit:
                typ = random.choice(types)
                extra = ""
                if typ == ItemType.PASSWORD:
                    extra = str(random.randint(1000, 9999))
                elif typ == ItemType.NOTE:
                    extra = "Clue: Exit is " + random.choice(["north", "south", "east", "west"])
                self.items.append(Item(x, y, typ, extra))

    def spawn_monsters(self, count):
        available = MONSTER_TYPES.copy()
        if self.id < 5:
            available = [t for t in available if t not in ["brute", "phantom", "spitter"]]
        if self.id < 10:
            available = [t for t in available if t not in ["chaser", "swift"]]

        for _ in range(count):
            for _ in range(100):
                x = random.randint(2, self.width-3)
                y = random.randint(2, self.height-3)
                if self.dungeon[y][x] == 0 and (x,y) != self.start and (x,y) != self.exit:
                    if dist((x,y), self.start) > 6:
                        mtype = random.choice(available)
                        self.monsters.append(Monster(x, y, mtype))
                        break

    def place_locked_door(self):
        ex, ey = self.exit
        for dx, dy in [(1,0),(-1,0),(0,1),(0,-1)]:
            nx, ny = ex+dx, ey+dy
            if 0<=nx<self.width and 0<=ny<self.height and self.dungeon[ny][nx]==0:
                self.dungeon[ny][nx] = 3
                self.locked_doors.append((nx, ny))
                break

    def place_lever_door(self, required):
        ex, ey = self.exit
        for dx, dy in [(1,0),(-1,0),(0,1),(0,-1)]:
            nx, ny = ex+dx, ey+dy
            if 0<=nx<self.width and 0<=ny<self.height and self.dungeon[ny][nx]==0:
                self.dungeon[ny][nx] = 5
                self.lever_doors.append((nx, ny, required))
                break

    def place_password_door(self):
        ex, ey = self.exit
        for dx, dy in [(1,0),(-1,0),(0,1),(0,-1)]:
            nx, ny = ex+dx, ey+dy
            if 0<=nx<self.width and 0<=ny<self.height and self.dungeon[ny][nx]==0:
                self.dungeon[ny][nx] = 4
                self.password_doors.append((nx, ny))
                break

    def place_chase_sequence(self):
        ex, ey = self.exit
        for _ in range(50):
            x = random.randint(ex-5, ex+5)
            y = random.randint(ey-5, ey+5)
            if 0<=x<self.width and 0<=y<self.height and self.dungeon[y][x]==0:
                if dist((x,y), self.start) > 10:
                    self.chase_monster = Monster(x, y, "chaser")
                    break

    def unlock_door(self, x, y, player):
        if (x,y) in self.locked_doors and player.has_key:
            self.dungeon[y][x] = 0
            self.locked_doors.remove((x,y))
            return True
        return False

    def unlock_lever(self, x, y, player):
        for door in self.lever_doors:
            if door[0] == x and door[1] == y:
                if player.levers_pulled >= door[2]:
                    self.dungeon[y][x] = 0
                    self.lever_doors.remove(door)
                    return True
                else:
                    return False
        return False

    def unlock_password(self, x, y, player, password_input):
        if (x,y) in self.password_doors and player.found_password and player.password == password_input:
            self.dungeon[y][x] = 0
            self.password_doors.remove((x,y))
            return True
        return False

    def get_theme_colors(self):
        theme = self.id % 4
        if theme == 0:
            return COLORS['wall_l0'], COLORS['wall_l0_dark'], COLORS['floor_l0']
        elif theme == 1:
            return COLORS['wall_l1'], COLORS['wall_l1_dark'], COLORS['floor_l1']
        elif theme == 2:
            return COLORS['wall_l2'], COLORS['wall_l2_dark'], COLORS['floor_l2']
        else:
            return COLORS['wall_l3'], COLORS['wall_l3_dark'], COLORS['floor_l3']

# ==================== 游戏主类 ====================
class Game:
    def __init__(self):
        self.screen = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
        pygame.display.set_caption("Backrooms: 40 Levels - EN")
        self.clock = pygame.time.Clock()
        self.running = True
        self.state = "playing"

        self.current_level = 0
        self.max_level = TOTAL_LEVELS
        self.level = Level(self.current_level)
        self.player = Player(self.level.start[0], self.level.start[1])
        self.camera_x = 0
        self.camera_y = 0
        self.flicker = 0
        self.whisper_timer = 0
        self.whisper_text = ""
        self.hallucination = False
        self.input_password = ""
        self.show_password_prompt = False
        self.password_door_target = None
        self.keys_pressed = {}
        self.transition_timer = 0
        self.transition_text = ""

        self.total_steps = 0
        self.total_monsters_killed = 0
        self.total_items_collected = 0
        self.game_over_reason = ""
        self.frame = 0

    def reset_game(self):
        self.__init__()

    def handle_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.running = False
            if event.type == pygame.KEYDOWN:
                if self.state != "playing":
                    if event.key == pygame.K_r:
                        self.reset_game()
                    if event.key == pygame.K_ESCAPE:
                        self.running = False
                    continue

                if self.show_password_prompt:
                    if event.key == pygame.K_RETURN:
                        if self.level.unlock_password(self.password_door_target[0],
                                                      self.password_door_target[1],
                                                      self.player, self.input_password):
                            self.show_password_prompt = False
                            self.whisper_text = "Password correct! Door opened."
                            self.whisper_timer = 60
                        else:
                            self.whisper_text = "Wrong password!"
                            self.whisper_timer = 60
                            self.input_password = ""
                    elif event.key == pygame.K_BACKSPACE:
                        self.input_password = self.input_password[:-1]
                    elif event.key == pygame.K_ESCAPE:
                        self.show_password_prompt = False
                    else:
                        if event.unicode.isdigit() and len(self.input_password) < 8:
                            self.input_password += event.unicode
                    continue

                if event.key == pygame.K_e:
                    self.player.pick_item(self.level.items)
                if event.key == pygame.K_SPACE:
                    self.player_attack()
                if event.key in [pygame.K_1, pygame.K_2, pygame.K_3, pygame.K_4,
                                 pygame.K_5, pygame.K_6, pygame.K_7, pygame.K_8]:
                    idx = event.key - pygame.K_1
                    self.player.use_item(idx)

                if event.key in (pygame.K_UP, pygame.K_w):
                    self.keys_pressed['up'] = True
                if event.key in (pygame.K_DOWN, pygame.K_s):
                    self.keys_pressed['down'] = True
                if event.key in (pygame.K_LEFT, pygame.K_a):
                    self.keys_pressed['left'] = True
                if event.key in (pygame.K_RIGHT, pygame.K_d):
                    self.keys_pressed['right'] = True

            if event.type == pygame.KEYUP:
                if event.key in (pygame.K_UP, pygame.K_w):
                    self.keys_pressed['up'] = False
                if event.key in (pygame.K_DOWN, pygame.K_s):
                    self.keys_pressed['down'] = False
                if event.key in (pygame.K_LEFT, pygame.K_a):
                    self.keys_pressed['left'] = False
                if event.key in (pygame.K_RIGHT, pygame.K_d):
                    self.keys_pressed['right'] = False
                if event.key == pygame.K_LSHIFT or event.key == pygame.K_RSHIFT:
                    self.player.sprinting = False

    def player_attack(self):
        px, py = self.player.get_pos()
        for monster in self.level.monsters[:]:
            if dist((monster.x, monster.y), (px, py)) < 1.8:
                if monster.take_damage():
                    self.level.monsters.remove(monster)
                    self.player.monsters_killed += 1
                    self.total_monsters_killed += 1
                    self.whisper_text = "Monster defeated!"
                    self.whisper_timer = 30
                    break
                else:
                    self.whisper_text = "Monster hit!"
                    self.whisper_timer = 20
                    break
        if self.level.chase_monster:
            if dist((self.level.chase_monster.x, self.level.chase_monster.y), (px, py)) < 1.8:
                if self.level.chase_monster.take_damage():
                    self.level.chase_monster = None
                    self.player.monsters_killed += 1
                    self.total_monsters_killed += 1
                    self.whisper_text = "Chaser defeated!"
                    self.whisper_timer = 30
                else:
                    self.whisper_text = "Chaser hit!"
                    self.whisper_timer = 20

    def handle_movement(self):
        if self.state != "playing":
            return
        if self.show_password_prompt:
            return
        player = self.player
        if player.moving:
            return
        keys = pygame.key.get_pressed()
        sprint = keys[pygame.K_LSHIFT] or keys[pygame.K_RSHIFT]
        if sprint and player.stamina > 5:
            player.sprinting = True
            player.stamina = max(0, player.stamina - SPRINT_COST)
        else:
            player.sprinting = False

        dx, dy = 0, 0
        if self.keys_pressed.get('up', False):
            dy = -1
        elif self.keys_pressed.get('down', False):
            dy = 1
        elif self.keys_pressed.get('left', False):
            dx = -1
        elif self.keys_pressed.get('right', False):
            dx = 1

        if dx == 0 and dy == 0:
            player.hold_timer = 0
            return

        if player.hold_timer == 0:
            self.try_move(dx, dy, sprint)
            player.hold_timer = 1
        elif player.hold_timer >= HOLD_DELAY:
            if player.move_cooldown == 0:
                self.try_move(dx, dy, sprint)
            player.hold_timer = HOLD_DELAY
        else:
            player.hold_timer += 1

    def try_move(self, dx, dy, sprint):
        result = self.player.start_move(dx, dy, self.level.dungeon, sprint)
        if result == "locked":
            self.whisper_text = "Need a key!"
            self.whisper_timer = 60
        elif result == "password":
            nx = self.player.grid_x + dx
            ny = self.player.grid_y + dy
            self.show_password_prompt = True
            self.password_door_target = (nx, ny)
            self.input_password = ""
        elif result == "lever":
            nx = self.player.grid_x + dx
            ny = self.player.grid_y + dy
            if self.level.unlock_lever(nx, ny, self.player):
                self.whisper_text = f"Lever activated! ({self.player.levers_pulled})"
                self.whisper_timer = 60
            else:
                self.whisper_text = "Need more levers!"
                self.whisper_timer = 60

    def update(self):
        self.frame += 1
        if self.state != "playing":
            return

        self.handle_movement()
        self.player.update(self.level.dungeon)

        ppos = self.player.get_pos()

        for monster in self.level.monsters[:]:
            if monster.update(ppos, self.level.dungeon, self.player):
                self.player.health -= monster.damage
                self.player.hit_flash = 12
                if self.player.health <= 0:
                    self.state = "gameover"
                    self.game_over_reason = "monster"

        if self.level.chase_monster:
            if self.level.chase_monster.update(ppos, self.level.dungeon, self.player):
                self.player.health -= self.level.chase_monster.damage
                self.player.hit_flash = 12
                if self.player.health <= 0:
                    self.state = "gameover"
                    self.game_over_reason = "chaser"

        cx, cy = self.player.get_cell()
        if (cx, cy) == self.level.exit:
            if self.level.chase_monster:
                if dist((self.level.chase_monster.x, self.level.chase_monster.y), (cx, cy)) < 3:
                    self.whisper_text = "Chaser blocks exit! Defeat it!"
                    self.whisper_timer = 60
                else:
                    self.next_level()
            else:
                self.next_level()

        for monster in self.level.monsters:
            if dist((monster.x, monster.y), (self.player.x, self.player.y)) < 5:
                self.player.sanity = max(0, self.player.sanity - 0.06)
        if self.level.chase_monster:
            if dist((self.level.chase_monster.x, self.level.chase_monster.y), (self.player.x, self.player.y)) < 8:
                self.player.sanity = max(0, self.player.sanity - 0.08)

        if self.player.sanity <= 0:
            self.state = "gameover"
            self.game_over_reason = "sanity"

        if random.random() < 0.003:
            self.flicker = random.randint(15, 40)
        if self.flicker > 0:
            self.flicker -= 1

        if self.player.sanity < 30 and random.random() < 0.01:
            self.hallucination = True
        else:
            self.hallucination = False

        if self.whisper_timer > 0:
            self.whisper_timer -= 1
        else:
            self.whisper_text = ""

        if self.transition_timer > 0:
            self.transition_timer -= 1

        px, py = self.player.get_pos()
        self.camera_x = px * CELL_SIZE - WINDOW_WIDTH // 2
        self.camera_y = py * CELL_SIZE - WINDOW_HEIGHT // 2

    def next_level(self):
        self.current_level += 1
        self.player.levels_completed += 1
        self.total_steps += self.player.steps
        if self.current_level >= self.max_level:
            self.state = "win"
            return
        self.transition_text = f"Level {self.current_level + 1}"
        self.transition_timer = 60
        self.level = Level(self.current_level)
        self.player = Player(self.level.start[0], self.level.start[1])
        self.player.monsters_killed = 0
        self.player.levers_pulled = 0
        self.whisper_text = f"Entering Level {self.current_level + 1}..."
        self.whisper_timer = 90

    def get_ending(self):
        p = self.player
        steps = self.total_steps + p.steps
        sanity = p.sanity
        kills = self.total_monsters_killed + p.monsters_killed
        items = self.total_items_collected + p.items_collected
        levels = p.levels_completed

        if sanity > 80 and kills > 20 and levels == self.max_level:
            ending = "The True Escape: You kept your mind intact, slew many horrors, and found the way out. You are a survivor."
        elif sanity > 50 and levels == self.max_level:
            ending = "A Faint Glimmer: You escaped, but the nightmares will linger. You wonder if you really left."
        elif sanity <= 30 and levels == self.max_level:
            ending = "Lost in Madness: You reached the exit, but your mind is shattered. You will never be the same."
        elif kills > 30:
            ending = "The Slayer: You killed everything that moved. But at what cost? You lost yourself in the carnage."
        elif items > 40:
            ending = "The Collector: You gathered all you could find. But treasures mean nothing in a place like this."
        elif steps > 3000:
            ending = "Wanderer: You walked a long, long way. You escaped, but your soul is forever lost in the endless halls."
        else:
            ending = "You escaped. Or did you? The backrooms have a way of pulling you back."
        return ending

    def render(self):
        self.screen.fill(COLORS['bg'])
        offset_x = -self.camera_x
        offset_y = -self.camera_y

        view_radius = VIEW_RADIUS + (TORCH_RADIUS if self.player.torch_active else 0)
        px, py = self.player.get_pos()
        wall_color, wall_dark, floor_color = self.level.get_theme_colors()

        for y in range(max(0, int(py-view_radius-1)), min(self.level.height, int(py+view_radius+2))):
            for x in range(max(0, int(px-view_radius-1)), min(self.level.width, int(px+view_radius+2))):
                d = math.hypot(x-px, y-py)
                if d > view_radius + 1:
                    continue
                rect = pygame.Rect(offset_x + x*CELL_SIZE, offset_y + y*CELL_SIZE, CELL_SIZE, CELL_SIZE)
                cell = self.level.dungeon[y][x]
                if cell == 1:
                    color = wall_dark if (x+y)%2 else wall_color
                    pygame.draw.rect(self.screen, color, rect)
                elif cell == 2:
                    color = (120, 100, 80) if self.current_level%4==0 else (90, 90, 100)
                    pygame.draw.rect(self.screen, color, rect)
                    pygame.draw.rect(self.screen, (50,50,50), rect, 1)
                elif cell == 3:
                    pygame.draw.rect(self.screen, (100, 80, 60), rect)
                    pygame.draw.rect(self.screen, (200, 180, 100), rect.inflate(-4, -4), 2)
                    lock = font_small.render("🔒", True, (200,200,100))
                    self.screen.blit(lock, (rect.x+2, rect.y))
                elif cell == 4:
                    pygame.draw.rect(self.screen, (80, 80, 100), rect)
                    pygame.draw.rect(self.screen, (150, 150, 200), rect.inflate(-4, -4), 2)
                    lock = font_small.render("🔐", True, (200,200,150))
                    self.screen.blit(lock, (rect.x+2, rect.y))
                elif cell == 5:
                    pygame.draw.rect(self.screen, (100, 100, 140), rect)
                    pygame.draw.rect(self.screen, (200, 200, 255), rect.inflate(-4, -4), 2)
                    lever_text = font_small.render("🎛️", True, (200,200,255))
                    self.screen.blit(lever_text, (rect.x+2, rect.y))
                else:
                    color = floor_color
                    if (x+y)%2: color = tuple(c-15 for c in color)
                    pygame.draw.rect(self.screen, color, rect)

        # ----- 绘制物品（不同颜色） -----
        for item in self.level.items:
            if item.collected: continue
            if dist((item.x, item.y), (px, py)) <= view_radius+1:
                rect = pygame.Rect(offset_x + item.x*CELL_SIZE, offset_y + item.y*CELL_SIZE, CELL_SIZE, CELL_SIZE)
                # 根据物品类型获取颜色
                base_color = Item.get_color(item.type)
                # 调亮作为发光色
                glow_color = (min(255, base_color[0]+60),
                              min(255, base_color[1]+60),
                              min(255, base_color[2]+60))
                glow = pygame.Surface((CELL_SIZE, CELL_SIZE), pygame.SRCALPHA)
                pygame.draw.circle(glow, (*glow_color, 120), (CELL_SIZE//2, CELL_SIZE//2), CELL_SIZE//2)
                self.screen.blit(glow, rect)
                # 绘制 emoji，使用白色保证清晰
                emoji = Item.get_emoji(item.type)
                text = font_small.render(emoji, True, (255,255,255))
                self.screen.blit(text, (rect.x+2, rect.y+2))
        # ---------------------------------

        for monster in self.level.monsters:
            if dist((monster.x, monster.y), (px, py)) <= view_radius+1:
                rect = pygame.Rect(offset_x + monster.x*CELL_SIZE - CELL_SIZE//2,
                                   offset_y + monster.y*CELL_SIZE - CELL_SIZE//2,
                                   CELL_SIZE, CELL_SIZE)
                if monster.type == "smiler":
                    if self.player.sanity < 60:
                        pygame.draw.circle(self.screen, (255,200,200), rect.center, CELL_SIZE//2)
                        for i in range(-4,5):
                            tx = rect.centerx + i*3
                            ty = rect.centery + 4
                            pygame.draw.rect(self.screen, (255,255,255), (tx-2, ty-2, 4, 4))
                    else:
                        pygame.draw.circle(self.screen, (100,100,100,30), rect.center, CELL_SIZE//2, 1)
                else:
                    color = monster.color
                    pygame.draw.circle(self.screen, color, rect.center, CELL_SIZE//2)
                    dx, dy = px - monster.x, py - monster.y
                    ang = math.atan2(dy, dx)
                    for side in [-1,1]:
                        ex = rect.centerx + math.cos(ang + side*0.6)*5
                        ey = rect.centery + math.sin(ang + side*0.6)*5
                        pygame.draw.circle(self.screen, (255,255,200), (int(ex), int(ey)), 3)
                    if monster.health > 1:
                        bar_w = CELL_SIZE
                        bar_h = 3
                        bar_x = rect.x
                        bar_y = rect.y - 6
                        pygame.draw.rect(self.screen, (60,60,60), (bar_x, bar_y, bar_w, bar_h))
                        fill = (bar_w * monster.health) // 3
                        pygame.draw.rect(self.screen, (255,0,0), (bar_x, bar_y, fill, bar_h))

        if self.level.chase_monster:
            m = self.level.chase_monster
            if dist((m.x, m.y), (px, py)) <= view_radius+2:
                rect = pygame.Rect(offset_x + m.x*CELL_SIZE - CELL_SIZE,
                                   offset_y + m.y*CELL_SIZE - CELL_SIZE,
                                   CELL_SIZE*2, CELL_SIZE*2)
                glow = pygame.Surface((CELL_SIZE*2, CELL_SIZE*2), pygame.SRCALPHA)
                pygame.draw.circle(glow, (255,0,0,80), (CELL_SIZE, CELL_SIZE), CELL_SIZE)
                self.screen.blit(glow, rect)
                crect = pygame.Rect(offset_x + m.x*CELL_SIZE - CELL_SIZE//2,
                                    offset_y + m.y*CELL_SIZE - CELL_SIZE//2,
                                    CELL_SIZE, CELL_SIZE)
                pygame.draw.circle(self.screen, (200,0,0), crect.center, CELL_SIZE//2)
                dx, dy = px - m.x, py - m.y
                ang = math.atan2(dy, dx)
                for side in [-1,1]:
                    ex = crect.centerx + math.cos(ang + side*0.6)*6
                    ey = crect.centery + math.sin(ang + side*0.6)*6
                    pygame.draw.circle(self.screen, (255,50,50), (int(ex), int(ey)), 4)
                    pygame.draw.circle(self.screen, (255,255,200), (int(ex), int(ey)), 2)

        ex, ey = self.level.exit
        if dist((ex, ey), (px, py)) <= view_radius+2:
            rect = pygame.Rect(offset_x + ex*CELL_SIZE, offset_y + ey*CELL_SIZE, CELL_SIZE, CELL_SIZE)
            glow = pygame.Surface((CELL_SIZE*2, CELL_SIZE*2), pygame.SRCALPHA)
            pygame.draw.circle(glow, (*COLORS['exit_glow'], 120), (CELL_SIZE, CELL_SIZE), CELL_SIZE)
            self.screen.blit(glow, (rect.x-CELL_SIZE//2, rect.y-CELL_SIZE//2))
            pygame.draw.rect(self.screen, COLORS['exit'], rect)
            pygame.draw.rect(self.screen, (200,255,200), rect.inflate(-4,-4))
            text = font_medium.render("EXIT", True, (0,80,0))
            self.screen.blit(text, (rect.x+4, rect.y+2))

        ppos = self.player.get_pos()
        prect = pygame.Rect(offset_x + ppos[0]*CELL_SIZE - CELL_SIZE//2,
                            offset_y + ppos[1]*CELL_SIZE - CELL_SIZE//2,
                            CELL_SIZE, CELL_SIZE)
        glow = pygame.Surface((CELL_SIZE*2, CELL_SIZE*2), pygame.SRCALPHA)
        pygame.draw.circle(glow, (*COLORS['player_glow'], 80), (CELL_SIZE, CELL_SIZE), CELL_SIZE)
        self.screen.blit(glow, (prect.x-CELL_SIZE//2, prect.y-CELL_SIZE//2))
        if self.player.hit_flash > 0:
            pygame.draw.circle(self.screen, (255,0,0), prect.center, CELL_SIZE//2-2)
        else:
            pygame.draw.circle(self.screen, COLORS['player'], prect.center, CELL_SIZE//2-2)
        ex = prect.centerx - 3; ey = prect.centery - 2
        pygame.draw.circle(self.screen, (255,255,255), (ex-2, ey), 2)
        pygame.draw.circle(self.screen, (255,255,255), (ex+4, ey), 2)
        pygame.draw.circle(self.screen, (0,0,0), (ex-1, ey+1), 1)
        pygame.draw.circle(self.screen, (0,0,0), (ex+5, ey+1), 1)

        self.render_fog(ppos, view_radius)

        if self.flicker > 0:
            overlay = pygame.Surface((WINDOW_WIDTH, WINDOW_HEIGHT))
            overlay.fill((0,0,0))
            alpha = random.randint(30, 150)
            overlay.set_alpha(alpha)
            self.screen.blit(overlay, (0,0))

        if self.hallucination:
            self.screen.blit(self.screen, (random.randint(-3,3), random.randint(-3,3)))

        if self.show_password_prompt:
            self.render_password_prompt()

        if self.transition_timer > 0:
            alpha = min(255, self.transition_timer * 4)
            overlay = pygame.Surface((WINDOW_WIDTH, WINDOW_HEIGHT))
            overlay.fill((0,0,0))
            overlay.set_alpha(alpha)
            self.screen.blit(overlay, (0,0))
            text = font_title.render(self.transition_text, True, (255,255,255))
            self.screen.blit(text, (WINDOW_WIDTH//2 - text.get_width()//2, WINDOW_HEIGHT//2))

        self.render_ui()

        if self.state == "win":
            self.render_win()
        elif self.state == "gameover":
            self.render_gameover()

        pygame.display.flip()

    def render_fog(self, player_pos, radius):
        mask = pygame.Surface((WINDOW_WIDTH, WINDOW_HEIGHT), pygame.SRCALPHA)
        cx, cy = WINDOW_WIDTH//2, WINDOW_HEIGHT//2
        r = radius * CELL_SIZE
        for i in range(r, 0, -5):
            alpha = int(200 * (1 - i/r))
            if alpha < 0: alpha = 0
            pygame.draw.circle(mask, (0,0,0, min(alpha, 180)), (cx, cy), i)
        self.screen.blit(mask, (0,0))

    def render_ui(self):
        ui_rect = pygame.Rect(0, WINDOW_HEIGHT-110, WINDOW_WIDTH, 110)
        ui_surf = pygame.Surface((WINDOW_WIDTH, 110), pygame.SRCALPHA)
        ui_surf.fill((10,10,15,200))
        self.screen.blit(ui_surf, (0, WINDOW_HEIGHT-110))

        bar_x, bar_y = 20, WINDOW_HEIGHT-95
        bar_w, bar_h = 120, 14
        ratio = self.player.sanity / SANITY_MAX
        pygame.draw.rect(self.screen, (60,60,60), (bar_x, bar_y, bar_w, bar_h))
        color = COLORS['sanity_bar'] if ratio>0.3 else COLORS['sanity_bar_low']
        pygame.draw.rect(self.screen, color, (bar_x+2, bar_y+2, int((bar_w-4)*ratio), bar_h-4))
        self.screen.blit(font_small.render(f"Sanity {int(self.player.sanity)}%", True, (255,255,255)), (bar_x+5, bar_y+1))

        hp_x = bar_x + bar_w + 8
        hp_w = 80
        pygame.draw.rect(self.screen, (60,60,60), (hp_x, bar_y, hp_w, bar_h))
        pygame.draw.rect(self.screen, (200,50,50), (hp_x+2, bar_y+2, int((hp_w-4)*(self.player.health/self.player.max_health)), bar_h-4))
        self.screen.blit(font_small.render(f"HP {int(self.player.health)}%", True, (255,255,255)), (hp_x+5, bar_y+1))

        st_x = hp_x + hp_w + 8
        st_w = 80
        pygame.draw.rect(self.screen, (60,60,60), (st_x, bar_y, st_w, bar_h))
        pygame.draw.rect(self.screen, COLORS['stamina_bar'], (st_x+2, bar_y+2, int((st_w-4)*(self.player.stamina/self.player.max_stamina)), bar_h-4))
        self.screen.blit(font_small.render(f"Stamina {int(self.player.stamina)}%", True, (255,255,255)), (st_x+5, bar_y+1))

        info_x = st_x + st_w + 8
        self.screen.blit(font_small.render(f"Lv {self.current_level+1}/{self.max_level}", True, COLORS['text']), (info_x, bar_y))
        self.screen.blit(font_small.render(f"Steps: {self.player.steps}", True, COLORS['text']), (info_x, bar_y+18))
        if self.player.levers_pulled > 0:
            self.screen.blit(font_small.render(f"Levers: {self.player.levers_pulled}", True, (200,200,255)), (info_x, bar_y+36))

        inv_x = 20
        inv_y = WINDOW_HEIGHT-65
        self.screen.blit(font_small.render("Items [1-8]:", True, COLORS['text']), (inv_x, inv_y))
        inv_x += 110
        for i, item_type in enumerate(self.player.inventory):
            color = Item.get_color(item_type)
            rect = pygame.Rect(inv_x + i*34, inv_y, 30, 26)
            pygame.draw.rect(self.screen, color, rect)
            pygame.draw.rect(self.screen, (200,200,200), rect, 1)
            emoji = Item.get_emoji(item_type)
            self.screen.blit(font_small.render(emoji, True, (0,0,0)), (rect.x+4, rect.y+2))
            num = font_small.render(str(i+1), True, (150,150,150))
            self.screen.blit(num, (rect.x+20, rect.y+14))

        if self.player.torch_active:
            self.screen.blit(font_small.render(f"🔦 {self.player.torch_timer//60}s", True, (255,220,100)), (WINDOW_WIDTH-160, WINDOW_HEIGHT-95))
        if self.player.has_key:
            self.screen.blit(font_small.render("🔑 Has Key", True, (200,200,100)), (WINDOW_WIDTH-160, WINDOW_HEIGHT-75))
        if self.player.sprinting:
            self.screen.blit(font_small.render("💨 Sprinting", True, (100,200,255)), (WINDOW_WIDTH-160, WINDOW_HEIGHT-55))

        if self.whisper_timer > 0:
            text = font_medium.render(self.whisper_text, True, COLORS['danger'])
            self.screen.blit(text, (WINDOW_WIDTH//2 - text.get_width()//2, 80))

        tips = "WASD move | Shift sprint | Space attack | E pickup | R reset"
        tip_text = font_small.render(tips, True, COLORS['text_dark'])
        self.screen.blit(tip_text, (WINDOW_WIDTH - 420, WINDOW_HEIGHT - 30))

    def render_password_prompt(self):
        overlay = pygame.Surface((WINDOW_WIDTH, WINDOW_HEIGHT), pygame.SRCALPHA)
        overlay.fill((0,0,0,180))
        self.screen.blit(overlay, (0,0))
        rect = pygame.Rect(WINDOW_WIDTH//2-150, WINDOW_HEIGHT//2-60, 300, 80)
        pygame.draw.rect(self.screen, (60,60,70), rect)
        pygame.draw.rect(self.screen, (200,200,200), rect, 2)
        prompt = font_medium.render("Enter Password (4-8 digits):", True, (255,255,255))
        self.screen.blit(prompt, (rect.x+20, rect.y+10))
        show = "*" * len(self.input_password)
        pass_text = font_medium.render(show, True, (100,200,255))
        self.screen.blit(pass_text, (rect.x+20, rect.y+45))
        info = font_small.render("Enter to confirm  ESC to cancel", True, (180,180,180))
        self.screen.blit(info, (rect.x+20, rect.y+70))

    def render_win(self):
        overlay = pygame.Surface((WINDOW_WIDTH, WINDOW_HEIGHT))
        overlay.fill((0,0,0))
        overlay.set_alpha(180)
        self.screen.blit(overlay, (0,0))
        ending = self.get_ending()
        lines = ending.split('. ')
        y_offset = WINDOW_HEIGHT//2 - 60
        for line in lines:
            if line:
                text = font_medium.render(line + '.', True, (200,255,200))
                self.screen.blit(text, (WINDOW_WIDTH//2 - text.get_width()//2, y_offset))
                y_offset += 40
        title = font_title.render("🎉 You Escaped!", True, (100,255,150))
        self.screen.blit(title, (WINDOW_WIDTH//2 - title.get_width()//2, y_offset+20))
        restart = font_small.render("Press R to restart  ESC to quit", True, (180,180,180))
        self.screen.blit(restart, (WINDOW_WIDTH//2 - restart.get_width()//2, y_offset+80))

    def render_gameover(self):
        overlay = pygame.Surface((WINDOW_WIDTH, WINDOW_HEIGHT))
        overlay.fill((0,0,0))
        overlay.set_alpha(200)
        self.screen.blit(overlay, (0,0))
        text = font_title.render("💀 You are lost...", True, (255,80,80))
        self.screen.blit(text, (WINDOW_WIDTH//2 - text.get_width()//2, WINDOW_HEIGHT//2-60))
        reason = "Sanity lost" if self.game_over_reason=="sanity" else "Health depleted"
        sub = font_medium.render(f"Reason: {reason}", True, (200,200,200))
        self.screen.blit(sub, (WINDOW_WIDTH//2 - sub.get_width()//2, WINDOW_HEIGHT//2))
        restart = font_small.render("Press R to restart  ESC to quit", True, (180,180,180))
        self.screen.blit(restart, (WINDOW_WIDTH//2 - restart.get_width()//2, WINDOW_HEIGHT//2+50))

    def run(self):
        while self.running:
            self.handle_events()
            self.update()
            self.render()
            self.clock.tick(FPS)
        pygame.quit()
        sys.exit()

if __name__ == "__main__":
    game = Game()
    game.run()