import pygame
import numpy as np
import sounddevice as sd
import threading
import time
import math
import random

# --- SOUND GENERATOR ---
def play_tone():
    fs = 44100
    t = np.linspace(0, 1, fs)
    while True:
        freq = random.choice([220, 330, 440, 550, 660])
        wave = 0.1 * np.sin(2 * np.pi * freq * t)
        sd.play(wave, fs)
        time.sleep(1)
        sd.stop()

# Run the sound in the background
threading.Thread(target=play_tone, daemon=True).start()

# --- VISUALS ---
pygame.init()
w, h = 900, 700
size = 10
cols, rows = w // size, h // size
screen = pygame.display.set_mode((w, h))
clock = pygame.time.Clock()
pygame.display.set_caption("🎶 Creative Life: Mutating Universe")

# Colors for generations
colors = [(0, 255, 255), (0, 180, 255), (100, 0, 255), (255, 0, 255), (255, 100, 0)]

# Initialize random grid
grid = np.random.choice([0, 1], (rows, cols), p=[0.8, 0.2])
age = np.zeros((rows, cols))

def update(grid, age):
    new_grid = np.zeros_like(grid)
    new_age = np.copy(age)
    for y in range(rows):
        for x in range(cols):
            n = np.sum(grid[max(0, y-1):min(rows, y+2),
                            max(0, x-1):min(cols, x+2)]) - grid[y, x]
            if grid[y, x] == 1:
                if n in [2, 3]:
                    new_grid[y, x] = 1
                    new_age[y, x] += 1
                else:
                    new_grid[y, x] = 0
                    new_age[y, x] = 0
            elif n == 3:
                new_grid[y, x] = 1
                new_age[y, x] = 1
    return new_grid, new_age

running = True
paused = False

while running:
    screen.fill((0, 0, 0))
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                paused = not paused
            elif event.key == pygame.K_r:  # Reset
                grid = np.random.choice([0, 1], (rows, cols), p=[0.8, 0.2])
                age = np.zeros((rows, cols))
    if not paused:
        grid, age = update(grid, age)
    for y in range(rows):
        for x in range(cols):
            if grid[y, x]:
                color = colors[int(min(age[y, x] / 5, len(colors)-1))]
                pygame.draw.rect(screen, color, (x*size, y*size, size-1, size-1))
    pygame.display.flip()
    clock.tick(15)

pygame.quit()
