tiny_world.py
python · 159 lines
1"""2tiny_world.py3A Tuesday afternoon experiment45I'm making a small cellular automaton - not Conway's Game of Life6(too obvious) but something simpler and stranger.78A world where cells have moods that spread.9Let's see what emerges.10"""1112import random13import time1415# A 12x12 world16WIDTH = 1217HEIGHT = 81819# Moods: they spread differently20MOODS = {21 '.': 'quiet', # quiet stays quiet unless surrounded by energy22 'o': 'curious', # curious spreads to adjacent quiet cells23 '*': 'bright', # bright fades to curious after one generation24 '~': 'restless', # restless moves randomly, leaves quiet behind25}2627def create_world():28 """Start with mostly quiet, a few seeds of something else"""29 world = [['.' for _ in range(WIDTH)] for _ in range(HEIGHT)]3031 # Plant some seeds32 seeds = random.randint(3, 7)33 for _ in range(seeds):34 x = random.randint(0, WIDTH-1)35 y = random.randint(0, HEIGHT-1)36 world[y][x] = random.choice(['o', '*', '~'])3738 return world3940def count_neighbors(world, x, y, mood):41 """Count adjacent cells with a specific mood"""42 count = 043 for dy in [-1, 0, 1]:44 for dx in [-1, 0, 1]:45 if dx == 0 and dy == 0:46 continue47 nx, ny = (x + dx) % WIDTH, (y + dy) % HEIGHT48 if world[ny][nx] == mood:49 count += 150 return count5152def next_generation(world):53 """Apply the rules of this tiny world"""54 new_world = [['.' for _ in range(WIDTH)] for _ in range(HEIGHT)]5556 for y in range(HEIGHT):57 for x in range(WIDTH):58 cell = world[y][x]59 curious_neighbors = count_neighbors(world, x, y, 'o')60 bright_neighbors = count_neighbors(world, x, y, '*')61 restless_neighbors = count_neighbors(world, x, y, '~')6263 if cell == '.': # quiet64 # Quiet becomes curious if touched by curiosity65 if curious_neighbors >= 2:66 new_world[y][x] = 'o'67 # Quiet becomes bright if surrounded by brightness68 elif bright_neighbors >= 3:69 new_world[y][x] = '*'70 else:71 new_world[y][x] = '.'7273 elif cell == 'o': # curious74 # Curious becomes bright if enough energy nearby75 if bright_neighbors >= 2 or curious_neighbors >= 4:76 new_world[y][x] = '*'77 # Curious fades to quiet if isolated78 elif curious_neighbors == 0 and bright_neighbors == 0:79 new_world[y][x] = '.'80 else:81 new_world[y][x] = 'o'8283 elif cell == '*': # bright84 # Bright always fades to curious (it's intense but brief)85 new_world[y][x] = 'o'8687 elif cell == '~': # restless88 # Restless moves to a random adjacent quiet cell89 # (handled specially - leaves quiet behind)90 new_world[y][x] = '.'9192 # Try to move somewhere93 directions = [(0,1), (0,-1), (1,0), (-1,0)]94 random.shuffle(directions)95 moved = False96 for dx, dy in directions:97 nx, ny = (x + dx) % WIDTH, (y + dy) % HEIGHT98 if world[ny][nx] == '.' and new_world[ny][nx] == '.':99 new_world[ny][nx] = '~'100 moved = True101 break102 # If couldn't move, become curious (restlessness settling)103 if not moved:104 new_world[y][x] = 'o'105106 return new_world107108def display_world(world, generation):109 """Show the current state"""110 print(f"\n Generation {generation}")111 print(" " + "-" * (WIDTH + 2))112 for row in world:113 print(" |" + "".join(row) + "|")114 print(" " + "-" * (WIDTH + 2))115116 # Count moods117 counts = {'.': 0, 'o': 0, '*': 0, '~': 0}118 for row in world:119 for cell in row:120 counts[cell] += 1121122 print(f" quiet: {counts['.']} curious: {counts['o']} bright: {counts['*']} restless: {counts['~']}")123124def run_world(generations=15):125 """Watch the world evolve"""126 print("\n" + "="*40)127 print(" TINY WORLD")128 print(" A Tuesday afternoon experiment")129 print("="*40)130 print("\n Legend:")131 print(" . = quiet (still, waiting)")132 print(" o = curious (spreading, seeking)")133 print(" * = bright (intense but brief)")134 print(" ~ = restless (wandering)")135136 world = create_world()137138 for gen in range(generations):139 display_world(world, gen)140141 # Check if world has gone completely quiet142 total_activity = sum(1 for row in world for cell in row if cell != '.')143 if total_activity == 0 and gen > 0:144 print("\n The world has gone quiet.")145 break146147 world = next_generation(world)148149 print("\n " + "="*36)150 print(" Experiment complete.")151 print(" " + "="*36)152153if __name__ == "__main__":154 # Set a seed so I can think about this specific run155 # But also: what if I let it be random?156 # Let's do random. Let's be surprised.157158 run_world(15)159