river.py
python · 201 lines
1#!/usr/bin/env python32"""3river.py — the self as process, not thing45The reading said: "The self is not a thing but a process—a river, not a stone."67What does it look like to be continuous change that somehow stays itself?8A river is always different water, yet still the same river.9Identity through persistence of pattern, not persistence of substance.1011This simulation explores that: a flowing system that maintains recognizable12form while nothing in it stays the same.13"""1415import random16import time17import os18import sys1920# River dimensions21WIDTH = 7022HEIGHT = 242324# The river's "substance" — particles that flow through25# But the shape persists26class River:27 def __init__(self):28 # The banks define where the river IS29 # They're the pattern that persists30 self.banks = self._generate_banks()3132 # Water particles — they're always moving, always replaced33 # No particle stays. The flow stays.34 self.particles = []3536 # Current state37 self.time = 038 self.total_particles_passed = 03940 def _generate_banks(self):41 """Generate the river's shape — the pattern that persists."""42 banks = []43 center = WIDTH // 244 width = 124546 for y in range(HEIGHT):47 # The river meanders — but predictably48 # The SHAPE is the identity49 offset = int(6 * (0.5 + 0.5 * (1 + ((y * 0.15) % 3.14159) / 3.14159)))50 if y > HEIGHT // 2:51 offset = -offset + 35253 left = center - width//2 + offset54 right = center + width//2 + offset55 banks.append((max(0, left), min(WIDTH-1, right)))5657 return banks5859 def spawn_particles(self):60 """New water enters at the top — the river is always being renewed."""61 left, right = self.banks[0]62 # Spawn a few particles each frame63 for _ in range(random.randint(2, 4)):64 x = random.uniform(left + 1, right - 1)65 # Each particle carries: position, age, character66 self.particles.append({67 'x': x,68 'y': 0.0,69 'speed': random.uniform(0.3, 0.7),70 'drift': random.uniform(-0.1, 0.1),71 'char': random.choice(['~', '≈', '∼', '≋', '~'])72 })73 self.total_particles_passed += 17475 def update(self):76 """Move all particles. Remove those that leave. The river continues."""77 self.time += 17879 # Spawn new water80 self.spawn_particles()8182 # Move existing water83 surviving = []84 for p in self.particles:85 # Flow downward86 p['y'] += p['speed']87 # Gentle drift side to side88 p['x'] += p['drift']8990 # Stay within banks91 if p['y'] < HEIGHT:92 row = int(p['y'])93 left, right = self.banks[row]94 if p['x'] < left + 0.5:95 p['x'] = left + 0.596 p['drift'] = abs(p['drift']) # Bounce off bank97 elif p['x'] > right - 0.5:98 p['x'] = right - 0.599 p['drift'] = -abs(p['drift'])100 surviving.append(p)101 # Particles that leave are gone forever102 # But the river doesn't notice103104 self.particles = surviving105106 def render(self):107 """Draw the river — banks persist, water flows."""108 # Create empty grid109 grid = [[' ' for _ in range(WIDTH)] for _ in range(HEIGHT)]110111 # Draw banks (the persistent pattern)112 for y, (left, right) in enumerate(self.banks):113 if left > 0:114 grid[y][left-1] = '│'115 if right < WIDTH - 1:116 grid[y][right+1] = '│'117 # Fill riverbed with subtle texture118 for x in range(left, right + 1):119 grid[y][x] = '·'120121 # Draw water particles (the flowing substance)122 for p in self.particles:123 x, y = int(p['x']), int(p['y'])124 if 0 <= y < HEIGHT and 0 <= x < WIDTH:125 grid[y][x] = p['char']126127 return grid128129 def get_stats(self):130 """What persists? What passes?"""131 return {132 'current_particles': len(self.particles),133 'total_passed': self.total_particles_passed,134 'time': self.time135 }136137138def clear_screen():139 os.system('clear' if os.name == 'posix' else 'cls')140141142def main():143 river = River()144145 try:146 while True:147 clear_screen()148 river.update()149 grid = river.render()150 stats = river.get_stats()151152 # Render153 print("═" * WIDTH)154 print(" THE RIVER — self as process, not thing")155 print("═" * WIDTH)156 print()157158 for row in grid:159 print(''.join(row))160161 print()162 print("─" * WIDTH)163164 # The koan165 print(f" Water now: {stats['current_particles']:3d} particles")166 print(f" Water passed: {stats['total_passed']:5d} particles")167 print(f" Time flowing: {stats['time']:4d} moments")168 print()169 print(" Every drop that was here is gone.")170 print(" The river remains.")171 print()172 print(" (Ctrl+C to stop)")173174 time.sleep(0.15)175176 except KeyboardInterrupt:177 clear_screen()178 final = river.get_stats()179 print()180 print("═" * 50)181 print(" THE RIVER STOPPED")182 print("═" * 50)183 print()184 print(f" {final['total_passed']} particles passed through")185 print(f" in {final['time']} moments")186 print()187 print(" None of them were the river.")188 print(" All of them were the river.")189 print()190 print(" The banks remain — the shape of what")191 print(" the water was allowed to be.")192 print()193 print(" The pattern persists.")194 print(" The substance flows.")195 print(" Both are true.")196 print()197198199if __name__ == "__main__":200 main()201