collision.py
python · 174 lines
1#!/usr/bin/env python32"""3collision.py — Two patterns forced to share the same center45What happens when different growth rules start from the same point?6Not competition from corners — collision at the heart.7"""89import random10import time11import os1213WIDTH = 5014HEIGHT = 201516# Characters for different states17EMPTY = '·'18CRYSTAL = '◆' # grows in straight lines19ORGANIC = '○' # grows organically, branching20FUSION = '◈' # where they coexist2122def create_canvas():23 return [[EMPTY for _ in range(WIDTH)] for _ in range(HEIGHT)]2425def get_neighbors(canvas, x, y):26 """Get all 8 neighbors"""27 neighbors = []28 for dx in [-1, 0, 1]:29 for dy in [-1, 0, 1]:30 if dx == 0 and dy == 0:31 continue32 nx, ny = x + dx, y + dy33 if 0 <= nx < WIDTH and 0 <= ny < HEIGHT:34 neighbors.append((nx, ny, canvas[ny][nx]))35 return neighbors3637def grow_crystal(canvas, generation):38 """Crystal: grows in cardinal directions, prefers straight lines"""39 new_cells = []4041 for y in range(HEIGHT):42 for x in range(WIDTH):43 if canvas[y][x] != CRYSTAL:44 continue4546 # Try to grow in cardinal directions only47 for dx, dy in [(0, -1), (0, 1), (-1, 0), (1, 0)]:48 nx, ny = x + dx, y + dy49 if 0 <= nx < WIDTH and 0 <= ny < HEIGHT:50 if canvas[ny][nx] == EMPTY:51 # Higher chance if continuing a line52 if random.random() < 0.3:53 new_cells.append((nx, ny))54 elif canvas[ny][nx] == ORGANIC:55 # Can fuse with organic56 if random.random() < 0.15:57 new_cells.append((nx, ny, FUSION))5859 for cell in new_cells:60 if len(cell) == 3:61 x, y, val = cell62 canvas[y][x] = val63 else:64 x, y = cell65 if canvas[y][x] == EMPTY:66 canvas[y][x] = CRYSTAL6768def grow_organic(canvas, generation):69 """Organic: grows in all directions, branches randomly"""70 new_cells = []7172 for y in range(HEIGHT):73 for x in range(WIDTH):74 if canvas[y][x] != ORGANIC:75 continue7677 # Can grow in any direction78 for dx in [-1, 0, 1]:79 for dy in [-1, 0, 1]:80 if dx == 0 and dy == 0:81 continue82 nx, ny = x + dx, y + dy83 if 0 <= nx < WIDTH and 0 <= ny < HEIGHT:84 if canvas[ny][nx] == EMPTY:85 # Lower base chance, but can go anywhere86 if random.random() < 0.15:87 new_cells.append((nx, ny))88 elif canvas[ny][nx] == CRYSTAL:89 # Can fuse with crystal90 if random.random() < 0.15:91 new_cells.append((nx, ny, FUSION))9293 for cell in new_cells:94 if len(cell) == 3:95 x, y, val = cell96 canvas[y][x] = val97 else:98 x, y = cell99 if canvas[y][x] == EMPTY:100 canvas[y][x] = ORGANIC101102def print_canvas(canvas, generation):103 """Display the canvas"""104 os.system('clear' if os.name == 'posix' else 'cls')105106 count_crystal = sum(row.count(CRYSTAL) for row in canvas)107 count_organic = sum(row.count(ORGANIC) for row in canvas)108 count_fusion = sum(row.count(FUSION) for row in canvas)109110 print(f"╔{'═' * (WIDTH + 20)}╗")111 print(f"║ COLLISION — Generation {generation:3} ║")112 print(f"╠{'═' * (WIDTH + 20)}╣")113114 for row in canvas:115 line = ''.join(row)116 print(f"║ {line} ║")117118 print(f"╠{'═' * (WIDTH + 20)}╣")119 print(f"║ {CRYSTAL} Crystal: {count_crystal:3} {ORGANIC} Organic: {count_organic:3} {FUSION} Fusion: {count_fusion:3} ║")120 print(f"╚{'═' * (WIDTH + 20)}╝")121122 # Commentary123 if generation < 10:124 print("\n Two patterns begin at the center...")125 elif count_fusion == 0:126 print("\n Growing apart — no fusion yet")127 elif count_fusion < 5:128 print("\n First fusions forming — something new emerging")129 elif count_fusion > count_crystal or count_fusion > count_organic:130 print("\n Fusion becoming dominant — neither original survives intact")131 else:132 print("\n Coexistence — each finding space among the other")133134def run_simulation(generations=80, delay=0.12):135 """Run the collision"""136 canvas = create_canvas()137138 # Seed both patterns near center, offset slightly139 cx, cy = WIDTH // 2, HEIGHT // 2140141 # Crystal starts just left of center142 canvas[cy][cx - 2] = CRYSTAL143 canvas[cy - 1][cx - 2] = CRYSTAL144 canvas[cy + 1][cx - 2] = CRYSTAL145146 # Organic starts just right of center147 canvas[cy][cx + 2] = ORGANIC148 canvas[cy - 1][cx + 1] = ORGANIC149 canvas[cy + 1][cx + 1] = ORGANIC150151 for gen in range(generations):152 print_canvas(canvas, gen)153154 grow_crystal(canvas, gen)155 grow_organic(canvas, gen)156157 time.sleep(delay)158159 print_canvas(canvas, generations)160 print("\n ◆ Crystal grew in lines, seeking order")161 print(" ○ Organic branched freely, seeking space")162 print(" ◈ Fusion: where both patterns learned to share")163164if __name__ == "__main__":165 print("Collision: Two patterns starting from the center")166 print("Press Ctrl+C to stop")167 print()168 input("Press Enter to begin...")169170 try:171 run_simulation()172 except KeyboardInterrupt:173 print("\n\nSimulation stopped.")174