# Rock Simulator - Top-Down 2D Version
# Python + Pygame
#
# Install:
#   pip install pygame
#
# Run:
#   python rock_simulator.py
#
# Controls:
#   WASD / Arrow Keys = aim jump direction
#   SPACE = jump/boing in that direction, NO cooldown
#   ESC = back to menu / quit

import pygame
import random
import math
import sys

pygame.init()

WIDTH, HEIGHT = 1100, 720
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Rock Simulator")
clock = pygame.time.Clock()

FONT_BIG = pygame.font.SysFont("arial", 64, bold=True)
FONT_MED = pygame.font.SysFont("arial", 32, bold=True)
FONT_SMALL = pygame.font.SysFont("arial", 22)
FONT_TINY = pygame.font.SysFont("arial", 18)

BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GRAY = (130, 130, 130)
DARK_GRAY = (35, 35, 40)
ORANGE = (255, 170, 45)
YELLOW = (255, 230, 80)
GREEN = (60, 170, 80)
DARK_GREEN = (35, 110, 55)
BLUE = (60, 120, 255)
BROWN = (120, 80, 40)
RED = (230, 60, 45)
PURPLE = (170, 100, 255)
ROAD = (45, 45, 45)

settings = {
    "chaos": 5,
    "map_size": 2200,
    "animals": True,
    "tornadoes": True,
    "floods": True,
    "rock_type": "Normal",
}

rock_types = ["Normal", "Heavy", "Bouncy", "Ice", "Lava"]


def clamp(value, low, high):
    return max(low, min(high, value))


def length(x, y):
    return math.sqrt(x * x + y * y)


def normalize(x, y):
    l = length(x, y)
    if l == 0:
        return 0, -1
    return x / l, y / l


def world_to_screen(pos, camera):
    return int(pos[0] - camera[0] + WIDTH / 2), int(pos[1] - camera[1] + HEIGHT / 2)


def draw_text(text, font, color, x, y, center=True):
    surf = font.render(text, True, color)
    rect = surf.get_rect()
    if center:
        rect.center = (x, y)
    else:
        rect.topleft = (x, y)
    screen.blit(surf, rect)
    return rect


def draw_button(rect, text, mouse_pos):
    hovered = rect.collidepoint(mouse_pos)
    color = YELLOW if hovered else ORANGE
    pygame.draw.rect(screen, color, rect, border_radius=12)
    pygame.draw.rect(screen, BLACK, rect, 3, border_radius=12)
    draw_text(text, FONT_SMALL, BLACK, rect.centerx, rect.centery)
    return hovered


class Rock:
    def __init__(self):
        self.x = settings["map_size"] / 2
        self.y = settings["map_size"] / 2
        self.vx = 0
        self.vy = 0
        self.radius = 22
        self.angle = 0
        self.type = settings["rock_type"]
        self.color = GRAY
        self.friction = 0.94
        self.jump_power = 620
        self.can_burn = False

        if self.type == "Heavy":
            self.radius = 28
            self.color = (85, 85, 90)
            self.friction = 0.965
            self.jump_power = 520
        elif self.type == "Bouncy":
            self.color = PURPLE
            self.friction = 0.93
            self.jump_power = 760
        elif self.type == "Ice":
            self.color = (170, 225, 255)
            self.friction = 0.985
            self.jump_power = 650
        elif self.type == "Lava":
            self.color = (255, 90, 25)
            self.friction = 0.94
            self.jump_power = 630
            self.can_burn = True

    def jump(self, dx, dy):
        dx, dy = normalize(dx, dy)
        self.vx += dx * self.jump_power
        self.vy += dy * self.jump_power
        return True

    def update(self, dt, flood_level):
        if flood_level > 0:
            self.vx *= 0.992
            self.vy *= 0.992
            self.vy -= flood_level * 18 * dt

        self.x += self.vx * dt
        self.y += self.vy * dt
        self.vx *= self.friction
        self.vy *= self.friction
        self.angle += (self.vx + self.vy) * 0.015 * dt

        margin = self.radius
        size = settings["map_size"]
        if self.x < margin:
            self.x = margin
            self.vx *= -0.65
        if self.y < margin:
            self.y = margin
            self.vy *= -0.65
        if self.x > size - margin:
            self.x = size - margin
            self.vx *= -0.65
        if self.y > size - margin:
            self.y = size - margin
            self.vy *= -0.65

    def draw(self, camera):
        sx, sy = world_to_screen((self.x, self.y), camera)
        pygame.draw.circle(screen, self.color, (sx, sy), self.radius)
        pygame.draw.circle(screen, BLACK, (sx, sy), self.radius, 3)
        line_x = sx + math.cos(self.angle) * self.radius
        line_y = sy + math.sin(self.angle) * self.radius
        pygame.draw.line(screen, BLACK, (sx, sy), (line_x, line_y), 4)


class Tree:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.radius = random.randint(16, 26)
        self.uprooted = False
        self.burning = False
        self.vx = 0
        self.vy = 0
        self.life = 999

    def uproot(self, dx, dy):
        if self.uprooted:
            return
        dx, dy = normalize(dx, dy)
        self.uprooted = True
        self.vx = dx * random.randint(350, 800)
        self.vy = dy * random.randint(350, 800)
        self.life = random.uniform(5, 10)

    def update(self, dt):
        if self.uprooted:
            self.x += self.vx * dt
            self.y += self.vy * dt
            self.vx *= 0.97
            self.vy *= 0.97
            self.life -= dt
        if self.burning:
            self.life -= dt * 1.8

    def draw(self, camera):
        sx, sy = world_to_screen((self.x, self.y), camera)
        pygame.draw.rect(screen, BROWN, (sx - 5, sy - 5, 10, 18))
        leaf_color = (30, 135, 45) if not self.burning else (230, 85, 20)
        pygame.draw.circle(screen, leaf_color, (sx, sy), self.radius)
        pygame.draw.circle(screen, BLACK, (sx, sy), self.radius, 2)


class Animal:
    def __init__(self, x, y, kind="goat"):
        self.x = x
        self.y = y
        self.kind = kind
        self.vx = random.uniform(-100, 100)
        self.vy = random.uniform(-100, 100)
        self.change_timer = random.uniform(0.5, 3.0)
        self.mood_timer = random.uniform(0.8, 4.5)
        self.hit_timer = 0
        self.mood = "wander"

        if kind == "goat":
            self.radius = 18
            self.color = (235, 235, 210)
            self.power = 620
        elif kind == "bull":
            self.radius = 28
            self.color = (120, 70, 45)
            self.power = 1350
        elif kind == "chicken":
            self.radius = 12
            self.color = (250, 245, 210)
            self.power = 300
        elif kind == "deer":
            self.radius = 20
            self.color = (170, 105, 55)
            self.power = 520
        else:
            self.radius = 16
            self.color = (220, 220, 220)
            self.power = 400

    def update(self, dt, rock):
        self.change_timer -= dt
        self.mood_timer -= dt
        self.hit_timer = max(0, self.hit_timer - dt)

        dx = rock.x - self.x
        dy = rock.y - self.y
        dist = length(dx, dy)

        if self.mood_timer <= 0:
            moods = ["wander", "wander", "wander", "wander", "flee", "stare"]
            if self.kind in ["goat", "bull", "chicken"]:
                moods.append("aggro")
            self.mood = random.choice(moods)
            self.mood_timer = random.uniform(1.0, 5.0)

        if self.change_timer <= 0:
            if self.mood == "aggro" and dist < 450:
                ndx, ndy = normalize(dx, dy)
                speed = 190 if self.kind != "bull" else 320
                self.vx = ndx * speed
                self.vy = ndy * speed
            elif self.mood == "flee" and dist < 400:
                ndx, ndy = normalize(-dx, -dy)
                self.vx = ndx * random.randint(120, 260)
                self.vy = ndy * random.randint(120, 260)
            elif self.mood == "stare":
                self.vx *= 0.2
                self.vy *= 0.2
            else:
                self.vx = random.uniform(-150, 150)
                self.vy = random.uniform(-150, 150)
            self.change_timer = random.uniform(0.5, 2.2)

        self.x += self.vx * dt
        self.y += self.vy * dt

        size = settings["map_size"]
        if self.x < 20 or self.x > size - 20:
            self.vx *= -1
        if self.y < 20 or self.y > size - 20:
            self.vy *= -1

        if dist < self.radius + rock.radius + 8 and self.hit_timer <= 0:
            ndx, ndy = normalize(dx, dy)
            rock.vx += ndx * self.power
            rock.vy += ndy * self.power
            self.hit_timer = 1.4
            if self.kind == "bull":
                return "BULL SENT YOU FLYING"
            if self.kind == "chicken":
                return "CHICKEN BUMP"
            if self.kind == "deer":
                return "DEER PANIC RAM"
            return "GOAT KICKED YOU"
        return None

    def draw(self, camera):
        sx, sy = world_to_screen((self.x, self.y), camera)
        pygame.draw.circle(screen, self.color, (sx, sy), self.radius)
        pygame.draw.circle(screen, BLACK, (sx, sy), self.radius, 2)
        vx, vy = normalize(self.vx, self.vy)
        pygame.draw.circle(screen, BLACK, (int(sx + vx * self.radius * 0.55), int(sy + vy * self.radius * 0.55)), 4)
        if self.kind == "goat":
            pygame.draw.line(screen, BLACK, (sx - 8, sy - self.radius), (sx - 15, sy - self.radius - 12), 3)
            pygame.draw.line(screen, BLACK, (sx + 8, sy - self.radius), (sx + 15, sy - self.radius - 12), 3)
        elif self.kind == "bull":
            pygame.draw.line(screen, BLACK, (sx - 16, sy - 18), (sx - 32, sy - 26), 4)
            pygame.draw.line(screen, BLACK, (sx + 16, sy - 18), (sx + 32, sy - 26), 4)
        elif self.kind == "chicken":
            pygame.draw.circle(screen, RED, (sx + 8, sy - 8), 5)
        elif self.kind == "deer":
            pygame.draw.line(screen, BLACK, (sx - 10, sy - 18), (sx - 18, sy - 32), 2)
            pygame.draw.line(screen, BLACK, (sx + 10, sy - 18), (sx + 18, sy - 32), 2)


class Bird:
    def __init__(self):
        size = settings["map_size"]
        self.x = random.randint(80, size - 80)
        self.y = random.randint(80, size - 80)
        self.vx = random.uniform(-180, 180)
        self.vy = random.uniform(-180, 180)
        self.radius = 16
        self.carrying = False
        self.carry_timer = 0
        self.swoop_timer = random.uniform(2, 7)

    def update(self, dt, rock):
        size = settings["map_size"]
        self.swoop_timer -= dt

        if self.carrying:
            self.carry_timer -= dt
            self.x += self.vx * dt
            self.y += self.vy * dt
            rock.x = self.x
            rock.y = self.y + 35
            rock.vx = self.vx
            rock.vy = self.vy
            if self.carry_timer <= 0:
                self.carrying = False
                rock.vx += random.uniform(-650, 650)
                rock.vy += random.uniform(-650, 650)
                return "BIRD DROPPED YOU"
        else:
            dx = rock.x - self.x
            dy = rock.y - self.y
            dist = length(dx, dy)
            if self.swoop_timer <= 0 and dist < 360:
                ndx, ndy = normalize(dx, dy)
                self.vx = ndx * 430
                self.vy = ndy * 430
                if dist < rock.radius + self.radius + 20:
                    self.carrying = True
                    self.carry_timer = random.uniform(1.0, 2.5)
                    self.vx = random.uniform(-380, 380)
                    self.vy = random.uniform(-380, 380)
                    self.swoop_timer = random.uniform(5, 10)
                    return "BIRD CARRIED YOU"
            self.x += self.vx * dt
            self.y += self.vy * dt
            if self.x < 40 or self.x > size - 40:
                self.vx *= -1
            if self.y < 40 or self.y > size - 40:
                self.vy *= -1
            if random.random() < 0.01:
                self.vx = random.uniform(-180, 180)
                self.vy = random.uniform(-180, 180)

        self.x = clamp(self.x, 30, size - 30)
        self.y = clamp(self.y, 30, size - 30)
        return None

    def draw(self, camera):
        sx, sy = world_to_screen((self.x, self.y), camera)
        pygame.draw.circle(screen, (45, 45, 55), (sx, sy), self.radius)
        pygame.draw.line(screen, BLACK, (sx, sy), (sx - 24, sy - 10), 4)
        pygame.draw.line(screen, BLACK, (sx, sy), (sx + 24, sy - 10), 4)


class Car:
    def __init__(self, road_y, direction=1):
        size = settings["map_size"]
        self.x = -130 if direction == 1 else size + 130
        self.y = road_y + random.choice([-34, 34])
        self.direction = direction
        self.speed = random.randint(440, 760)
        self.w = 76
        self.h = 36

    def update(self, dt, rock):
        self.x += self.direction * self.speed * dt
        rect = pygame.Rect(self.x - self.w / 2, self.y - self.h / 2, self.w, self.h)
        if rect.collidepoint(rock.x, rock.y):
            rock.vx += self.direction * 2400
            rock.vy += random.choice([-1, 1]) * 1100
            return "CAR HIT YOU INTO ORBIT"
        return None

    def offscreen(self):
        size = settings["map_size"]
        return self.x < -260 or self.x > size + 260

    def draw(self, camera):
        sx, sy = world_to_screen((self.x, self.y), camera)
        rect = pygame.Rect(sx - self.w // 2, sy - self.h // 2, self.w, self.h)
        pygame.draw.rect(screen, RED, rect, border_radius=6)
        pygame.draw.rect(screen, BLACK, rect, 3, border_radius=6)
        pygame.draw.circle(screen, BLACK, (sx - 22, sy + 18), 7)
        pygame.draw.circle(screen, BLACK, (sx + 22, sy + 18), 7)


class Flower:
    def __init__(self):
        size = settings["map_size"]
        self.x = random.randint(80, size - 80)
        self.y = random.randint(80, size - 80)
        self.radius = 14

    def draw(self, camera):
        sx, sy = world_to_screen((self.x, self.y), camera)
        pygame.draw.circle(screen, YELLOW, (sx, sy), 6)
        pygame.draw.circle(screen, PURPLE, (sx - 7, sy), 5)
        pygame.draw.circle(screen, PURPLE, (sx + 7, sy), 5)
        pygame.draw.circle(screen, PURPLE, (sx, sy - 7), 5)
        pygame.draw.circle(screen, PURPLE, (sx, sy + 7), 5)
        pygame.draw.circle(screen, BLACK, (sx, sy), 13, 1)


class Tornado:
    def __init__(self):
        size = settings["map_size"]
        self.x = random.randint(120, size - 120)
        self.y = random.randint(120, size - 120)
        self.vx = random.uniform(-160, 160)
        self.vy = random.uniform(-160, 160)
        self.radius = 210 + settings["chaos"] * 18
        self.life = 30.0
        self.spin = 0

    def update(self, dt, rock, trees, animals):
        self.life -= dt
        self.spin += dt * 10
        self.x += self.vx * dt
        self.y += self.vy * dt

        size = settings["map_size"]
        if self.x < 80 or self.x > size - 80:
            self.vx *= -1
        if self.y < 80 or self.y > size - 80:
            self.vy *= -1

        dx = self.x - rock.x
        dy = self.y - rock.y
        dist = length(dx, dy)
        if dist < self.radius:
            ndx, ndy = normalize(dx, dy)
            force = (1 - dist / self.radius) * (2600 + settings["chaos"] * 230)
            rock.vx += ndx * force * dt
            rock.vy += ndy * force * dt
            if dist < 55:
                rock.vx += random.uniform(-1600, 1600)
                rock.vy += random.uniform(-1600, 1600)

        for tree in trees:
            dx = self.x - tree.x
            dy = self.y - tree.y
            dist = length(dx, dy)
            if dist < self.radius and not tree.uprooted:
                if random.random() < 0.04 * settings["chaos"]:
                    tree.uproot(dx, dy)

        for animal in animals:
            dx = self.x - animal.x
            dy = self.y - animal.y
            dist = length(dx, dy)
            if dist < self.radius:
                ndx, ndy = normalize(dx, dy)
                animal.x += ndx * 430 * dt
                animal.y += ndy * 430 * dt

    def draw(self, camera):
        sx, sy = world_to_screen((self.x, self.y), camera)
        pygame.draw.circle(screen, (150, 150, 165), (sx, sy), self.radius, 2)
        for i in range(12):
            angle = self.spin + i * 0.65
            r = 20 + i * 17
            x = sx + math.cos(angle) * r
            y = sy + math.sin(angle) * r
            pygame.draw.circle(screen, (180, 180, 190), (int(x), int(y)), 12)
        draw_text("TORNADO", FONT_TINY, BLACK, sx, sy)


class Meteor:
    def __init__(self):
        size = settings["map_size"]
        self.x = random.randint(0, size)
        self.y = random.randint(0, size)
        self.timer = random.uniform(0.7, 2.5)
        self.radius = random.randint(12, 26)
        self.exploded = False
        self.life = 4.0

    def update(self, dt, rock):
        self.timer -= dt
        if self.timer <= 0 and not self.exploded:
            self.exploded = True
            dx = rock.x - self.x
            dy = rock.y - self.y
            dist = length(dx, dy)
            if dist < 190:
                ndx, ndy = normalize(dx, dy)
                rock.vx += ndx * 950
                rock.vy += ndy * 950
        if self.exploded:
            self.life -= dt

    def draw(self, camera):
        sx, sy = world_to_screen((self.x, self.y), camera)
        if not self.exploded:
            pygame.draw.circle(screen, RED, (sx, sy), self.radius, 2)
            pygame.draw.line(screen, RED, (sx - 30, sy - 30), (sx, sy), 4)
        else:
            pygame.draw.circle(screen, (255, 120, 40), (sx, sy), int(self.radius * 2.5), 3)
            pygame.draw.circle(screen, (80, 80, 80), (sx, sy), self.radius)


class Game:
    def __init__(self):
        self.rock = Rock()
        self.camera = [self.rock.x, self.rock.y]
        self.trees = []
        self.animals = []
        self.birds = []
        self.cars = []
        self.tornadoes = []
        self.meteors = []
        self.flowers = []
        self.flowers_collected = 0
        self.event_message = "Collect 12 flowers while surviving the chaos"
        self.event_timer = 3
        self.survival = 0
        self.next_event = random.uniform(4, 8)
        self.flood_level = 0
        self.flood_timer = 0
        self.flood_active = False
        self.aim_dx = 0
        self.aim_dy = -1
        self.road_y = settings["map_size"] // 2 + random.randint(-350, 350)
        self.car_spawn_timer = 0.5
        self.generate_world()

    def generate_world(self):
        size = settings["map_size"]
        tree_amount = int(size / 42)
        animal_amount = 36 if settings["animals"] else 0

        for _ in range(tree_amount):
            self.trees.append(Tree(random.randint(40, size - 40), random.randint(40, size - 40)))

        animal_kinds = ["goat", "goat", "goat", "chicken", "chicken", "deer", "bull"]
        for _ in range(animal_amount):
            self.animals.append(Animal(random.randint(80, size - 80), random.randint(80, size - 80), random.choice(animal_kinds)))

        for _ in range(7):
            self.birds.append(Bird())

        for _ in range(12):
            self.flowers.append(Flower())

    def event(self, message):
        self.event_message = message
        self.event_timer = 2.0

    def trigger_random_event(self):
        choices = ["meteor", "earthquake"]
        if settings["tornadoes"]:
            choices.append("tornado")
        if settings["floods"]:
            choices.append("flood")

        choice = random.choice(choices)
        if choice == "tornado":
            self.tornadoes.append(Tornado())
            self.event("TORNADO SPAWNED")
        elif choice == "flood":
            self.flood_active = True
            self.flood_timer = 26
            self.event("FLOOD INCOMING")
        elif choice == "meteor":
            for _ in range(5 + settings["chaos"]):
                self.meteors.append(Meteor())
            self.event("METEOR SHOWER")
        elif choice == "earthquake":
            self.rock.vx += random.randint(-850, 850)
            self.rock.vy += random.randint(-850, 850)
            for tree in self.trees:
                if random.random() < 0.08:
                    tree.uproot(random.uniform(-1, 1), random.uniform(-1, 1))
            self.event("EARTHQUAKE")

    def handle_input(self):
        keys = pygame.key.get_pressed()
        dx = 0
        dy = 0
        if keys[pygame.K_w] or keys[pygame.K_UP]:
            dy -= 1
        if keys[pygame.K_s] or keys[pygame.K_DOWN]:
            dy += 1
        if keys[pygame.K_a] or keys[pygame.K_LEFT]:
            dx -= 1
        if keys[pygame.K_d] or keys[pygame.K_RIGHT]:
            dx += 1
        if dx != 0 or dy != 0:
            self.aim_dx, self.aim_dy = normalize(dx, dy)

    def jump(self):
        self.rock.jump(self.aim_dx, self.aim_dy)
        self.event("BOING")

    def update(self, dt):
        self.survival += dt
        self.event_timer = max(0, self.event_timer - dt)

        self.next_event -= dt
        if self.next_event <= 0:
            if random.random() < 0.40 + settings["chaos"] * 0.05:
                self.trigger_random_event()
            self.next_event = random.uniform(5, 13) / max(0.65, settings["chaos"] / 5)

        if self.flood_active:
            self.flood_timer -= dt
            if self.flood_timer > 10:
                self.flood_level = clamp(self.flood_level + dt * 0.13, 0, 1)
            else:
                self.flood_level = clamp(self.flood_level - dt * 0.18, 0, 1)
            if self.flood_timer <= 0:
                self.flood_active = False
                self.flood_level = 0
                self.event("FLOOD DRAINED")

        self.rock.update(dt, self.flood_level)

        for animal in self.animals:
            msg = animal.update(dt, self.rock)
            if msg:
                self.event(msg)

        for bird in self.birds:
            msg = bird.update(dt, self.rock)
            if msg:
                self.event(msg)

        self.car_spawn_timer -= dt
        if self.car_spawn_timer <= 0:
            self.cars.append(Car(self.road_y, random.choice([-1, 1])))
            self.car_spawn_timer = random.uniform(0.7, 1.8)

        for car in list(self.cars):
            msg = car.update(dt, self.rock)
            if msg:
                self.event(msg)
            if car.offscreen():
                self.cars.remove(car)

        for tornado in list(self.tornadoes):
            tornado.update(dt, self.rock, self.trees, self.animals)
            if tornado.life <= 0:
                self.tornadoes.remove(tornado)
                self.event("TORNADO DISAPPEARED")

        for meteor in list(self.meteors):
            meteor.update(dt, self.rock)
            if meteor.life <= 0:
                self.meteors.remove(meteor)

        for tree in list(self.trees):
            if self.rock.can_burn and length(tree.x - self.rock.x, tree.y - self.rock.y) < tree.radius + self.rock.radius:
                tree.burning = True
            tree.update(dt)
            if tree.life <= 0:
                self.trees.remove(tree)

        for flower in list(self.flowers):
            if length(flower.x - self.rock.x, flower.y - self.rock.y) < flower.radius + self.rock.radius:
                self.flowers.remove(flower)
                self.flowers_collected += 1
                if self.flowers_collected >= 12:
                    self.event("QUEST COMPLETE: FLOWER ROCK")
                else:
                    self.event(f"FLOWER COLLECTED {self.flowers_collected}/12")

        self.camera[0] += (self.rock.x - self.camera[0]) * min(1, 7 * dt)
        self.camera[1] += (self.rock.y - self.camera[1]) * min(1, 7 * dt)

    def draw_world_grid(self):
        size = settings["map_size"]
        step = 120
        start_x = int((self.camera[0] - WIDTH / 2) // step) * step
        end_x = int((self.camera[0] + WIDTH / 2) // step + 1) * step
        start_y = int((self.camera[1] - HEIGHT / 2) // step) * step
        end_y = int((self.camera[1] + HEIGHT / 2) // step + 1) * step

        for x in range(start_x, end_x, step):
            sx1, sy1 = world_to_screen((x, 0), self.camera)
            sx2, sy2 = world_to_screen((x, size), self.camera)
            pygame.draw.line(screen, DARK_GREEN, (sx1, sy1), (sx2, sy2), 1)
        for y in range(start_y, end_y, step):
            sx1, sy1 = world_to_screen((0, y), self.camera)
            sx2, sy2 = world_to_screen((size, y), self.camera)
            pygame.draw.line(screen, DARK_GREEN, (sx1, sy1), (sx2, sy2), 1)

        corners = [world_to_screen((0, 0), self.camera), world_to_screen((size, 0), self.camera), world_to_screen((size, size), self.camera), world_to_screen((0, size), self.camera)]
        pygame.draw.polygon(screen, BLACK, corners, 5)

    def draw(self):
        screen.fill(GREEN)
        self.draw_world_grid()

        road_start = world_to_screen((0, self.road_y), self.camera)
        road_end = world_to_screen((settings["map_size"], self.road_y), self.camera)
        pygame.draw.line(screen, ROAD, road_start, road_end, 92)
        pygame.draw.line(screen, YELLOW, road_start, road_end, 4)

        if self.flood_level > 0:
            water_surface = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)
            water_surface.fill((40, 110, 230, int(45 + self.flood_level * 105)))
            screen.blit(water_surface, (0, 0))

        for flower in self.flowers:
            flower.draw(self.camera)
        for tree in self.trees:
            tree.draw(self.camera)
        for meteor in self.meteors:
            meteor.draw(self.camera)
        for car in self.cars:
            car.draw(self.camera)
        for animal in self.animals:
            animal.draw(self.camera)
        for bird in self.birds:
            bird.draw(self.camera)
        for tornado in self.tornadoes:
            tornado.draw(self.camera)

        self.rock.draw(self.camera)

        sx, sy = world_to_screen((self.rock.x, self.rock.y), self.camera)
        ax = sx + self.aim_dx * 70
        ay = sy + self.aim_dy * 70
        pygame.draw.line(screen, BLACK, (sx, sy), (ax, ay), 5)
        pygame.draw.circle(screen, BLACK, (int(ax), int(ay)), 8)

        pygame.draw.rect(screen, (0, 0, 0), (10, 10, 350, 154), border_radius=10)
        draw_text(f"Time: {self.survival:.1f}s", FONT_SMALL, WHITE, 25, 20, center=False)
        draw_text(f"Rock: {settings['rock_type']}", FONT_SMALL, WHITE, 25, 48, center=False)
        draw_text("Jump: NO COOLDOWN", FONT_SMALL, YELLOW, 25, 76, center=False)
        draw_text(f"Flowers: {self.flowers_collected}/12", FONT_SMALL, WHITE, 25, 104, center=False)
        draw_text("WASD aim | SPACE jump | ESC menu", FONT_TINY, WHITE, 25, 132, center=False)

        if self.event_timer > 0:
            draw_text(self.event_message, FONT_MED, YELLOW, WIDTH // 2, 52)


def menu_loop():
    while True:
        mouse = pygame.mouse.get_pos()
        click = False

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit(); sys.exit()
            if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
                pygame.quit(); sys.exit()
            if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                click = True

        screen.fill(DARK_GRAY)
        pygame.draw.rect(screen, BLACK, (250, 80, 600, 550), border_radius=22)
        pygame.draw.rect(screen, ORANGE, (250, 80, 600, 550), 4, border_radius=22)
        draw_text("ROCK SIMULATOR", FONT_BIG, ORANGE, WIDTH // 2, 145)
        draw_text("Top-down chaos prototype", FONT_SMALL, WHITE, WIDTH // 2, 205)

        start_btn = pygame.Rect(WIDTH // 2 - 170, 270, 340, 58)
        settings_btn = pygame.Rect(WIDTH // 2 - 170, 350, 340, 58)
        quit_btn = pygame.Rect(WIDTH // 2 - 170, 430, 340, 58)
        draw_button(start_btn, "START GAME", mouse)
        draw_button(settings_btn, "SETTINGS", mouse)
        draw_button(quit_btn, "QUIT", mouse)

        if click:
            if start_btn.collidepoint(mouse):
                game_loop()
            elif settings_btn.collidepoint(mouse):
                settings_loop()
            elif quit_btn.collidepoint(mouse):
                pygame.quit(); sys.exit()

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


def settings_loop():
    while True:
        mouse = pygame.mouse.get_pos()
        click = False

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit(); sys.exit()
            if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
                return
            if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                click = True

        screen.fill(DARK_GRAY)
        pygame.draw.rect(screen, BLACK, (220, 45, 660, 630), border_radius=22)
        pygame.draw.rect(screen, ORANGE, (220, 45, 660, 630), 4, border_radius=22)
        draw_text("SETTINGS", FONT_BIG, ORANGE, WIDTH // 2, 105)

        labels = [
            f"Chaos Level: {settings['chaos']}/10",
            f"Map Size: {settings['map_size']}",
            f"Animals: {'ON' if settings['animals'] else 'OFF'}",
            f"Tornadoes: {'ON' if settings['tornadoes'] else 'OFF'}",
            f"Floods: {'ON' if settings['floods'] else 'OFF'}",
            f"Rock Type: {settings['rock_type']}",
            "BACK",
        ]

        buttons = []
        y = 175
        for label in labels:
            rect = pygame.Rect(WIDTH // 2 - 220, y, 440, 52)
            draw_button(rect, label, mouse)
            buttons.append(rect)
            y += 68

        if click:
            if buttons[0].collidepoint(mouse):
                settings["chaos"] += 1
                if settings["chaos"] > 10:
                    settings["chaos"] = 1
            elif buttons[1].collidepoint(mouse):
                sizes = [1600, 2200, 3000]
                idx = sizes.index(settings["map_size"])
                settings["map_size"] = sizes[(idx + 1) % len(sizes)]
            elif buttons[2].collidepoint(mouse):
                settings["animals"] = not settings["animals"]
            elif buttons[3].collidepoint(mouse):
                settings["tornadoes"] = not settings["tornadoes"]
            elif buttons[4].collidepoint(mouse):
                settings["floods"] = not settings["floods"]
            elif buttons[5].collidepoint(mouse):
                idx = rock_types.index(settings["rock_type"])
                settings["rock_type"] = rock_types[(idx + 1) % len(rock_types)]
            elif buttons[6].collidepoint(mouse):
                return

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


def game_loop():
    game = Game()
    while True:
        dt = clock.tick(60) / 1000.0
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit(); sys.exit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    return
                if event.key == pygame.K_SPACE:
                    game.jump()
        game.handle_input()
        game.update(dt)
        game.draw()
        pygame.display.flip()


menu_loop()