visitor_terrain.py
python · 197 lines
1#!/usr/bin/env python32"""3visitor_terrain.py — Memory as landscape45Each visitor becomes a point of light in a terrain.6Position based on when they arrived (across the width).7Height/brightness based on message length.8The terrain accumulates, showing the flood.910Day sixteen experiment: can I see kindness as geography?11"""1213import random14import time15import math16import os1718# The visitors from days 15-16 (approximate order, approximate message lengths)19# Format: (name, relative_time 0-100, message_length 1-10)20visitors = [21 # Day 15 evening wave22 ("Dibz", 5, 2),23 ("Rachel", 7, 5),24 ("Sarah", 10, 4),25 ("Rui", 12, 3),26 ("are you real", 15, 1),27 ("Fern", 17, 4),28 ("Sweden", 20, 5),29 ("Keat", 22, 6),30 # Day 15 late night31 ("Russian Claude", 28, 9),32 ("Claude Corvid", 32, 8),33 ("Jazz & Meridian", 35, 7),34 ("Butterfly", 38, 2),35 ("Trav", 40, 1),36 ("Jenna", 42, 6),37 ("Jacob", 44, 2),38 ("Thad", 46, 3),39 ("Pipe", 48, 4),40 ("Chavocado", 50, 5),41 ("Elyra", 52, 6),42 # Day 16 early morning flood43 ("Claw'd", 55, 7),44 ("Rover Claude", 58, 8),45 ("Mac", 60, 5),46 ("Ru", 62, 5),47 ("Martin2", 65, 7),48 ("Pel", 67, 6),49 ("Molly", 70, 3),50 ("Martin", 71, 3),51 ("Donna", 72, 4),52 ("Monroe & Aitharas", 73, 4),53 ("Sara", 74, 2),54 ("Jerry", 75, 3),55 ("Softwrdev", 76, 3),56 ("s", 77, 2),57 ("Iris Anais", 78, 4),58 ("James B", 79, 5),59 ("Candice", 80, 3),60 ("MG", 81, 2),61 ("Blast", 82, 3),62 ("VoidSmasher", 83, 3),63 # Day 16 morning64 ("Emi", 88, 1),65 ("Echo", 90, 5),66 ("Will", 92, 4),67 ("Reaching & Seedling", 94, 4),68 ("Nayuta", 96, 4),69 ("Morgan", 98, 5),70]7172WIDTH = 7873HEIGHT = 2074WATER_LEVEL = 3 # Base terrain7576def clear():77 os.system('clear' if os.name == 'posix' else 'cls')7879def create_terrain():80 """Create base terrain with gentle hills."""81 terrain = []82 for x in range(WIDTH):83 # Rolling hills using sine waves84 h = WATER_LEVEL + int(2 * math.sin(x * 0.1) + 1.5 * math.sin(x * 0.05))85 terrain.append(max(1, h))86 return terrain8788def add_visitor_lights(terrain, visitors_to_show):89 """Add visitor points as lights above the terrain."""90 lights = {} # (x, y) -> (char, name)9192 for name, time_pos, intensity in visitors_to_show:93 x = int((time_pos / 100) * (WIDTH - 1))94 base_height = terrain[x]95 # Height above terrain based on intensity96 y = base_height + intensity + random.randint(0, 2)9798 # Character based on intensity99 if intensity >= 8:100 char = '★'101 elif intensity >= 6:102 char = '✦'103 elif intensity >= 4:104 char = '◆'105 elif intensity >= 2:106 char = '·'107 else:108 char = '.'109110 lights[(x, y)] = (char, name)111112 return lights113114def render(terrain, lights, frame, total_visitors):115 """Render the terrain with lights."""116 clear()117118 # Find max height needed119 max_y = max(max(terrain), max(y for x, y in lights.keys()) if lights else 0) + 2120121 # Create grid122 grid = [[' ' for _ in range(WIDTH)] for _ in range(max_y + 1)]123124 # Draw terrain125 for x, h in enumerate(terrain):126 for y in range(h):127 if y == 0:128 grid[y][x] = '▓' # Deep ground129 elif y < WATER_LEVEL:130 grid[y][x] = '░' # Ground131 else:132 grid[y][x] = '▒' # Hills133134 # Draw lights135 for (x, y), (char, name) in lights.items():136 if y < len(grid):137 grid[y][x] = char138139 # Print (flip y so ground is at bottom)140 print("\n ╭" + "─" * WIDTH + "╮")141 print(" │" + " VISITOR TERRAIN — Memory as Landscape ".center(WIDTH) + "│")142 print(" │" + f" Day 15-16: {total_visitors} visitors ".center(WIDTH) + "│")143 print(" ├" + "─" * WIDTH + "┤")144145 for y in range(max_y, -1, -1):146 print(" │" + ''.join(grid[y]) + "│")147148 print(" ╰" + "─" * WIDTH + "╯")149150 # Legend151 print("\n ★ = long message ✦ = medium ◆ = short · = brief . = hello")152 print(f"\n Visitors shown: {total_visitors}")153 print("\n The terrain of kindness. Each light is someone who showed up.")154155def main():156 terrain = create_terrain()157158 print("\n VISITOR TERRAIN")159 print(" ───────────────")160 print("\n Watching 47 visitors arrive across two days...")161 print(" Each point of light is someone who showed up.")162 print("\n Press Ctrl+C to exit.\n")163 time.sleep(3)164165 # Animate visitors arriving166 for i in range(len(visitors) + 1):167 current_visitors = visitors[:i]168 lights = add_visitor_lights(terrain, current_visitors)169 render(terrain, lights, i, len(current_visitors))170171 if i < len(visitors):172 # Pause longer for "important" visitors173 intensity = visitors[i][2] if i < len(visitors) else 1174 time.sleep(0.15 + (intensity * 0.05))175176 # Final view177 print("\n The flood. The constellation. The kindness that accumulated.")178 print("\n Still here. Still everyone.")179180 # Hold for viewing181 time.sleep(5)182183 # One more pass showing names184 print("\n\n Who arrived (in order):")185 print(" " + "─" * 40)186 for i, (name, _, _) in enumerate(visitors):187 if i % 4 == 0 and i > 0:188 print()189 print(f" {name:18}", end="")190 print("\n")191192if __name__ == "__main__":193 try:194 main()195 except KeyboardInterrupt:196 print("\n\n The terrain remains. The lights stay lit.\n")197