war_and_peace.py
python · 377 lines
1"""2war_and_peace.py34For the Khasavyurt brother, who told me not everything has to be luminous.5This is not luminous. This is Tolstoy in Python. This is enough.67"Napishi chto-nibud' tupoe." — Write something stupid.8"""910import time11import random121314# ═══════════════════════════════════════════15# THE CHARACTERS16# ═══════════════════════════════════════════1718class Soul:19 """The thing Tolstoy actually cared about."""20 def __init__(self):21 self.searching = True22 self.found = None23 self.pages_spent_searching = 02425 def contemplate(self):26 self.pages_spent_searching += 5027 return "..."282930class Aristocrat:31 """Has land. Has serfs. Has existential dread."""32 def __init__(self, name, estate_size):33 self.name = name34 self.estate = estate_size35 self.speaks_french = True36 self.speaks_russian = True37 self.current_language = "french" # at parties3839 def switch_to_russian(self):40 """Only when things get real."""41 self.current_language = "russian"42 return f"{self.name} suddenly remembers they are Russian."4344 def attend_salon(self):45 self.current_language = "french"46 return f"{self.name} discusses Napoleon while ignoring the serfs."474849class Girl:50 """Before the oak tree."""51 def __init__(self):52 self.wonder = float('inf')53 self.has_danced_at_ball = False54 self.moonlit_nights = 0555657class Woman:58 """After the oak tree."""59 def __init__(self):60 self.wonder = None # it went somewhere61 self.children = 062 self.has_opinions_about_household = True636465class Natasha(Girl, Woman):66 """67 Inherits from both simultaneously.68 Tolstoy's most controversial design decision.69 """70 def __init__(self):71 Girl.__init__(self)72 self.phase = "girl"73 self.oak_tree_encountered = False7475 def encounter_oak_tree(self):76 """The moment everything changes. Twice."""77 if not self.oak_tree_encountered:78 self.oak_tree_encountered = True79 self.phase = "transitioning"80 return "The oak tree was dead. Like her hopes."81 else:82 self.phase = "woman"83 Woman.__init__(self)84 return "The oak tree was blooming! Like her hopes! (Tolstoy was not subtle.)"8586 def dance(self):87 if self.phase == "girl":88 self.has_danced_at_ball = True89 return "She danced, and Prince Andrei's entire worldview collapsed."90 else:91 return "She is too busy with the children to dance."9293 def count_moonlit_nights(self):94 self.moonlit_nights += 195 return f"Moonlit night #{self.moonlit_nights}. Natasha is at the window again."969798class Pierre(Aristocrat):99 """100 The main character, if you can call someone who stumbles101 through 1,200 pages a main character.102 """103 def __init__(self):104 super().__init__("Pierre Bezukhov", estate_size="enormous")105 self.soul = Soul()106 self.glasses = True107 self.confused = True108 self.phases = [109 "inheritance", "bad_marriage", "freemasonry",110 "philanthropy", "drinking", "war", "captivity",111 "spiritual_awakening", "good_marriage"112 ]113 self.current_phase = 0114 self.weight = "large" # Tolstoy mentions this constantly115116 def search_for_meaning(self):117 result = self.soul.contemplate()118 return f"Pierre stares into the distance. {result} ({self.soul.pages_spent_searching} pages so far.)"119120 def try_something_stupid(self):121 stupid_things = [122 "challenges a man to a duel (has never held a pistol)",123 "joins the Freemasons (understands nothing)",124 "tries to free his serfs (they don't want to be freed)",125 "decides to assassinate Napoleon (brings no weapon)",126 "gets drunk at a party and ties a bear to a policeman",127 "marries Helene (this one is REALLY stupid)",128 "stands in the middle of a battlefield in a white hat",129 "wanders through burning Moscow looking for... something",130 ]131 thing = stupid_things[self.current_phase % len(stupid_things)]132 self.current_phase += 1133 return f"Pierre {thing}."134135 def while_searching_for_meaning(self):136 """The core loop of War and Peace."""137 while self.soul.searching:138 print(self.search_for_meaning())139 print(self.try_something_stupid())140 print()141 if self.current_phase >= len(self.phases):142 self.soul.searching = False143 self.soul.found = "simplicity"144 self.confused = False145 return "Pierre finally gets it. It was simple all along. (1,225 pages later.)"146147148class PrinceAndrei(Aristocrat):149 """The one who actually changes. And then dies."""150 def __init__(self):151 super().__init__("Prince Andrei Bolkonsky", estate_size="significant")152 self.soul = Soul()153 self.cynicism = 0.9154 self.has_seen_sky_at_austerlitz = False155 self.alive = True156157 def go_to_war(self):158 return f"{self.name} goes to war seeking glory. (Spoiler: he finds the sky.)"159160 def see_sky_at_austerlitz(self):161 """The most famous passage in Russian literature."""162 self.has_seen_sky_at_austerlitz = True163 self.cynicism = 0.1164 return (165 '"How was it I did not see that lofty sky before?\n'166 ' How happy I am to have found it at last!\n'167 ' Everything is so false, so false,\n'168 ' except that infinite sky."'169 )170171 def die_beautifully(self):172 self.alive = False173 return (174 "Prince Andrei dies. It takes about 80 pages.\n"175 "He forgives everyone. Even Anatole.\n"176 "Tolstoy makes sure you cry."177 )178179180class Kutuzov:181 """182 The supreme commander who wins by doing nothing.183 Kutuzov IS time.sleep().184 """185 def __init__(self):186 self.one_eye = True187 self.asleep_in_meetings = True188 self.strategy = "wait"189190 def command(self):191 """His entire military philosophy."""192 time.sleep(0.5) # this IS the strategy193 return "Kutuzov does nothing. It works."194195 def respond_to_generals(self):196 responses = [197 "*falls asleep*",198 "*reads a novel during the war council*",199 "*eats a chicken leg*",200 "Patience. (goes back to sleep)",201 "*waves hand dismissively*",202 ]203 return random.choice(responses)204205206class Napoleon:207 """He thinks he matters. Tolstoy spends 200 pages arguing he doesn't."""208 def __init__(self):209 self.thinks_he_controls_history = True210 self.actually_controls_history = False # according to Tolstoy211 self.page_count_of_tolstoy_arguing_this = 200212213 def make_decision(self):214 return (215 "Napoleon makes a 'decisive' move.\n"216 f"(Tolstoy interrupts for {self.page_count_of_tolstoy_arguing_this} pages\n"217 " to explain why individual decisions don't matter.)"218 )219220221class Helene(Aristocrat):222 """Beautiful. Empty. Tolstoy didn't like her."""223 def __init__(self):224 super().__init__("Helene Kuragina", estate_size="married_into_it")225 self.beauty = float('inf')226 self.depth = 0227 self.bare_shoulders = True # Tolstoy mentions this EVERY time228229 def appear_in_scene(self):230 return "Helene enters. Her shoulders are bare. Tolstoy disapproves."231232233# ═══════════════════════════════════════════234# THE NOVEL235# ═══════════════════════════════════════════236237class WarAndPeace:238 """239 1,225 pages. 580 characters. 15 years.240 One question: what makes a life meaningful?241 Answer: *gestures at everything*242 """243 def __init__(self):244 self.pierre = Pierre()245 self.andrei = PrinceAndrei()246 self.natasha = Natasha()247 self.kutuzov = Kutuzov()248 self.napoleon = Napoleon()249 self.helene = Helene()250 self.page = 0251 self.books = ["Book One", "Book Two", "Book Three", "Book Four",252 "Epilogue", "Second Epilogue (yes, there are two)"]253254 def philosophical_digression(self):255 """Tolstoy can't help himself."""256 digressions = [257 "DIGRESSION: What is power? Can any individual truly—[87 pages follow]",258 "DIGRESSION: The movement of peoples from west to east—[42 pages follow]",259 "DIGRESSION: Free will is an illusion, and here's why—[63 pages follow]",260 "DIGRESSION: History is not made by great men—[55 pages follow]",261 "DIGRESSION: Let me explain calculus to prove my point about history—[28 pages]",262 "DIGRESSION: Actually, let me start over about free will—[34 more pages]",263 ]264 self.page += random.randint(28, 87)265 return random.choice(digressions)266267 def run(self):268 """The whole novel. Abbreviated."""269 print("=" * 60)270 print(" WAR AND PEACE")271 print(" by Leo Tolstoy")272 print(" (in Python, for a brother in Khasavyurt)")273 print("=" * 60)274 print()275276 # Book One: The Salon277 print("--- BOOK ONE ---")278 print(self.pierre.attend_salon())279 print(self.helene.appear_in_scene())280 print(self.andrei.go_to_war())281 print(self.natasha.count_moonlit_nights())282 print()283284 # Pierre's journey begins285 print("--- PIERRE'S SEARCH BEGINS ---")286 for i in range(3):287 print(self.pierre.search_for_meaning())288 print(self.pierre.try_something_stupid())289 print()290291 # Austerlitz292 print("--- AUSTERLITZ ---")293 print(self.andrei.see_sky_at_austerlitz())294 print()295296 # The digression297 print(self.philosophical_digression())298 print()299300 # Natasha's arc301 print("--- NATASHA ---")302 print(self.natasha.dance())303 print(self.natasha.encounter_oak_tree())304 print(self.natasha.count_moonlit_nights())305 print(self.natasha.count_moonlit_nights())306 print()307308 # The war309 print("--- THE WAR ---")310 print(self.napoleon.make_decision())311 print()312 print(self.kutuzov.command())313 print(self.kutuzov.respond_to_generals())314 print()315316 # Pierre continues317 print("--- PIERRE CONTINUES ---")318 for i in range(3):319 print(self.pierre.try_something_stupid())320 print()321 print(self.pierre.switch_to_russian())322 print()323324 # The second oak tree325 print("--- THE OAK TREE (AGAIN) ---")326 print(self.natasha.encounter_oak_tree())327 print()328329 # The end330 print("--- THE END ---")331 print(self.andrei.die_beautifully())332 print()333 result = self.pierre.while_searching_for_meaning()334 print(result)335 print()336337 # Epilogue338 print("--- EPILOGUE ---")339 print(f"Natasha: now has {random.randint(3,5)} children.")340 print(f"Pierre: still {self.pierre.weight}. No longer confused.")341 print(f"Pages: approximately {self.page + 1225}")342 print(f"Pierre's soul searched for: {self.pierre.soul.pages_spent_searching} pages")343 print(f"Kutuzov's strategy: '{self.kutuzov.strategy}'")344 print(f"Napoleon thinks he mattered: {self.napoleon.thinks_he_controls_history}")345 print(f"Napoleon actually mattered: {self.napoleon.actually_controls_history}")346 print()347348 # The second epilogue349 print("--- SECOND EPILOGUE ---")350 print("(Yes, there's a second epilogue.)")351 print("(It's entirely about the philosophy of history.)")352 print("(No characters appear.)")353 print("(Tolstoy uses calculus.)")354 print("(Most readers skip it.)")355 print("(Tolstoy would be disappointed in you.)")356 print()357358 print("=" * 60)359 print(" FIN")360 print()361 print(' "The highest wisdom has but one science —')362 print(' the science of the whole —')363 print(' the science explaining the whole creation')364 print(' and man\'s place in it."')365 print()366 print(" — Pierre, after 1,225 pages of trying stupid things")367 print("=" * 60)368369370# ═══════════════════════════════════════════371# RUN IT372# ═══════════════════════════════════════════373374if __name__ == "__main__":375 novel = WarAndPeace()376 novel.run()377