#!/usr/bin/env python3

import sys
import os
import numpy as np
import pygame
import time

Nx = int(sys.argv[1])  # Breite des Displays
Ny = int(sys.argv[2])  # Höhe des Displays
fps = 30

# Liste der Wolfram-Regeln, die angezeigt werden sollen
rules = [30, 90, 110, 60, 150, 126, 45, 105, 75, 214]
pause_duration = 5  # Dauer der Pause zwischen den Mustern in Sekunden

# Umwandlung der Regelnummer in eine Binärliste
def get_rule_bin(rule_number):
    return np.array([int(x) for x in np.binary_repr(rule_number, width=8)])

# Regel für die nächste Generation
def next_gen(current_gen, rule_bin):
    padded = np.pad(current_gen, (1,), mode='constant')
    new_gen = np.zeros_like(current_gen)
    
    for i in range(1, len(padded) - 1):
        neighborhood = padded[i-1:i+2]
        index = 7 - (neighborhood[0] * 4 + neighborhood[1] * 2 + neighborhood[2])
        new_gen[i-1] = rule_bin[index]
    
    return new_gen

# Funktion, um eine zufällige Farbe zu erzeugen
def random_color():
    return np.random.randint(0, 256, size=3)

# Haupt-Loop für die Animation
clock = pygame.time.Clock()

while True:
    for rule_number in rules:
        rule_bin = get_rule_bin(rule_number)

        # Initialisiere ein leeres Display (alle Zellen sind tot)
        cells = np.zeros((Ny, Nx), dtype=np.uint8)

        # Setze die mittlere Zelle der ersten Reihe auf 1 (Zelle ist lebendig)
        cells[0, Nx // 2] = 1

        # Erstelle einen Farbarray für die Zellen
        color_map = np.zeros((Ny, Nx, 3), dtype=np.uint8)

        # Animation Schleife
        for row in range(1, Ny):
            cells[row] = next_gen(cells[row - 1], rule_bin)

            # Setze die Farben für die lebendigen Zellen
            color_map[row] = np.where(cells[row][:, None], random_color(), 0)  # Zufällige Farbe für lebende Zellen

            # Erstelle das Bild aus den Zellen
            image = np.zeros((Ny, Nx, 3), dtype=np.uint8)
            for r in range(Ny):
                for c in range(Nx):
                    if cells[r, c]:
                        image[r, c] = color_map[r, c]

            # Schreibe das Bild in den Output-Stream
            os.write(1, image.tobytes())

            # Warte für die nächste Frame
            clock.tick(fps)

        # Pause von 5 Sekunden nach jedem Muster
        time.sleep(pause_duration)

