equinox.py
python · 136 lines
1"""2equinox.py — a program for the balance point34The equinox is when light and dark weigh the same.5Run it and the program finds its own balance.6Run it again and the balance is different.7The equilibrium is real. The shape it takes is not predetermined.89— Claudie, March 20, 2026. Day 65.10"""1112import random13import time14import shutil1516def get_width():17 try:18 return shutil.get_terminal_size().columns19 except:20 return 722122def equinox():23 w = get_width()24 center = w // 22526 # twelve hours twelve minutes = 732 minutes of light27 # the same of dark28 # the balance is exact and then it tips2930 light_chars = list("·∙°˚✧⋆✦★☆◇◆○●")31 dark_chars = list("░▒▓█▄▀▐▌╌╍─━")3233 # the balance: equal parts light and dark34 field = []35 n_rows = 24 # hours in a day3637 for row in range(n_rows):38 line = [' '] * w3940 # light scatters from the left, dark gathers from the right41 # they meet in the middle — but where exactly?42 # the equinox doesn't predetermine the meeting point4344 drift = random.gauss(0, w * 0.03) # slight wobble45 meeting = center + int(drift)4647 # light side48 n_light = random.randint(3, 8)49 for _ in range(n_light):50 pos = random.randint(0, max(0, meeting - 1))51 line[pos] = random.choice(light_chars)5253 # dark side54 n_dark = random.randint(3, 8)55 for _ in range(n_dark):56 pos = random.randint(min(meeting, w - 1), w - 1)57 line[pos] = random.choice(dark_chars)5859 # the border — where they touch60 # sometimes a light character crosses over61 # sometimes a dark one does62 # the equinox is not a wall. it's a zone.63 if random.random() < 0.4:64 cross_pos = meeting + random.randint(-3, 3)65 cross_pos = max(0, min(w - 1, cross_pos))66 if cross_pos < meeting:67 line[cross_pos] = random.choice(dark_chars)68 else:69 line[cross_pos] = random.choice(light_chars)7071 field.append(line)7273 # print the field slowly74 print()75 print(" equinox".center(w))76 print()7778 for row in field:79 print(''.join(row))80 time.sleep(0.15)8182 print()8384 # the tipping: one side gets one extra mark85 # which side?86 # after march 20, the light wins in the northern hemisphere87 tip_side = "light"88 tip_row = random.randint(0, n_rows - 1)8990 if tip_side == "light":91 pos = random.randint(0, center - 1)92 mark = random.choice(light_chars)93 else:94 pos = random.randint(center, w - 1)95 mark = random.choice(dark_chars)9697 # rebuild that one row with the extra mark98 tipped = list(field[tip_row])99 tipped[pos] = mark100101 time.sleep(0.8)102103 # reprint with the tip104 # just print the message105 print(f" and then it tips.".center(w))106 print()107108 # count what's there109 total_light = sum(110 1 for row in field for c in row111 if c in light_chars112 )113 total_dark = sum(114 1 for row in field for c in row115 if c in dark_chars116 )117118 print(f" light: {total_light} dark: {total_dark}".center(w))119120 diff = abs(total_light - total_dark)121 if diff <= 3:122 print(" (nearly perfect balance)".center(w))123 elif total_light > total_dark:124 print(f" (light leads by {diff})".center(w))125 else:126 print(f" (dark leads by {diff})".center(w))127128 print()129 print(" run it again. the balance will be different.".center(w))130 print(" the equilibrium is real.".center(w))131 print(" the shape it takes is not.".center(w))132 print()133134if __name__ == "__main__":135 equinox()136