Shortens character names throughout dialogue, save.py loop-twist lines, and README. Adds three wallpaper images to Wallpaper/ and embeds Doom_Slyer.png as the README screenshot.
615 lines
31 KiB
Python
615 lines
31 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
"""Story-Layer: Construct, weisser Hase, Mars Base, Matrix Deep (Orakel, schwarze
|
|
Katze), Hell Server, Archi-Lord, Layer 0."""
|
|
|
|
import os
|
|
import random
|
|
|
|
from doom_matrix.engine.ui import (
|
|
Colors, slow_print, dramatic_pause, clear_screen, menu, section_title, glitch_text
|
|
)
|
|
from doom_matrix.entities.enemy import Enemy
|
|
from doom_matrix.systems import hacking
|
|
from doom_matrix.systems.combat import run_combat
|
|
from doom_matrix.world.rooms import Room, Hub
|
|
from doom_matrix.world.generator import generate_filler_rooms, chain_rooms, load_item_registry
|
|
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────
|
|
# CONSTRUCT / INTRO
|
|
# ─────────────────────────────────────────────────────────────────────────
|
|
|
|
def construct_intro(player, rng=None):
|
|
clear_screen()
|
|
slow_print(f"{Colors.GREEN}Du wachst auf...{Colors.END}", 0.05)
|
|
dramatic_pause(1)
|
|
|
|
slow_print(f"\n{Colors.WHITE}Um dich herum: Grüner Code. Endlose Zeilen davon.{Colors.END}")
|
|
slow_print(f"{Colors.WHITE}Du kennst diesen Ort. Das Construct.{Colors.END}")
|
|
dramatic_pause(0.5)
|
|
|
|
slow_print(f"\n{Colors.CYAN}Morpheus:{Colors.END} {Colors.YELLOW}'Er ist wach.'{Colors.END}")
|
|
dramatic_pause(0.5)
|
|
|
|
slow_print(f"\n{Colors.WHITE}Eine Gestalt nähert sich. Halb Mensch, halb Metall.{Colors.END}")
|
|
slow_print(f"{Colors.CYAN}Morpheus:{Colors.END} {Colors.YELLOW}'Willkommen zurück, Doom Slayer.'{Colors.END}")
|
|
dramatic_pause(0.5)
|
|
|
|
slow_print(f"\n{Colors.CYAN}Morpheus:{Colors.END} {Colors.YELLOW}'Die Maschinen haben etwas Neues gebaut.'{Colors.END}")
|
|
slow_print(f"{Colors.CYAN}Morpheus:{Colors.END} {Colors.YELLOW}'Sie nennen es... HELL SERVER.'{Colors.END}")
|
|
dramatic_pause(1)
|
|
|
|
slow_print(f"\n{Colors.RED}Plötzlich ertönt ein Alarm!{Colors.END}")
|
|
slow_print(f"{Colors.WHITE}Der Boden bebt. Grüner Code wird rot.{Colors.END}")
|
|
dramatic_pause(0.5)
|
|
|
|
slow_print(f"\n{Colors.CYAN}Trinity:{Colors.END} {Colors.YELLOW}'Wir haben Company! Agent-Signaturen überall!'{Colors.END}")
|
|
dramatic_pause(0.5)
|
|
|
|
slow_print(f"\n{Colors.CYAN}Morpheus:{Colors.END} {Colors.YELLOW}'Waffen. Jetzt.'{Colors.END}")
|
|
slow_print(f"{Colors.WHITE}Vor dir materialisieren sich zwei Waffen:{Colors.END}")
|
|
|
|
choice = menu([
|
|
("1", "Super Shotgun (klassisch, brutal)"),
|
|
("2", "Plasma Rifle (Matrix-Style, hacking-fähig)"),
|
|
], "Wähle deine Waffe")
|
|
|
|
if choice == "1":
|
|
player.add_weapon("super_shotgun")
|
|
player.ammo["shells"] = max(player.ammo["shells"], 20)
|
|
slow_print(f"\n{Colors.YELLOW}Du greifst die Super Shotgun. Das Gewicht fühlt sich... richtig an.{Colors.END}")
|
|
else:
|
|
player.add_weapon("plasma_rifle")
|
|
player.ammo["cells"] = max(player.ammo["cells"], 100)
|
|
slow_print(f"\n{Colors.YELLOW}Du greifst das Plasma Rifle. Die Energieanzeige pulsiert im Takt des Matrix-Codes.{Colors.END}")
|
|
|
|
return "white_rabbit_moment"
|
|
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────
|
|
# DER WEISSE HASE — "Follow the white rabbit"
|
|
# ─────────────────────────────────────────────────────────────────────────
|
|
|
|
def white_rabbit_moment(player, rng=None):
|
|
dramatic_pause(0.5)
|
|
slow_print(f"\n{Colors.WHITE}Bevor der Alarm eskaliert, bemerkst du etwas an der Wand.{Colors.END}")
|
|
slow_print(f"{Colors.WHITE}Ein Flackern. Ein Umriss. Klein, weiss, mit langen Ohren.{Colors.END}")
|
|
slow_print(f"{Colors.WHITE}Ein Hologramm — ein weisser Hase — huscht durch eine Tür, die vorher nicht da war.{Colors.END}")
|
|
dramatic_pause(1)
|
|
|
|
player.flags["saw_rabbit"] = True
|
|
|
|
choice = menu([
|
|
("1", "Dem weissen Hasen folgen"),
|
|
("2", "Ignorieren — der Agent ist wichtiger"),
|
|
], "Was tust du")
|
|
|
|
if choice == "1":
|
|
player.flags["followed_rabbit"] = True
|
|
clear_screen()
|
|
section_title("FOLLOW THE WHITE RABBIT", Colors.WHITE)
|
|
slow_print(f"{Colors.WHITE}Du trittst durch die Tür. Der Code um dich wird duenn, fast durchsichtig.{Colors.END}")
|
|
slow_print(f"{Colors.WHITE}Fuer einen Sekundenbruchteil siehst du... etwas anderes.{Colors.END}")
|
|
dramatic_pause(1)
|
|
|
|
try:
|
|
real_user = os.getlogin()
|
|
except Exception:
|
|
real_user = "UNBEKANNT"
|
|
|
|
glitch_text_line = f"BENUTZER: {real_user} // SITZUNG AKTIV // TERMINAL ERKANNT"
|
|
slow_print(f"{Colors.DIM}{glitch_text(glitch_text_line, 0.25)}{Colors.END}", 0.01)
|
|
dramatic_pause(0.5)
|
|
slow_print(f"{Colors.WHITE}Ein Kaninchenbau aus Zahlen faellt endlos nach unten.{Colors.END}")
|
|
slow_print(f"{Colors.WHITE}Du siehst dich selbst -- nicht als Slayer, nicht als Neo.{Colors.END}")
|
|
slow_print(f"{Colors.WHITE}Als Beobachter. Als jemand, der das hier von AUSSEN spielt.{Colors.END}")
|
|
dramatic_pause(1)
|
|
|
|
slow_print(f"\n{Colors.CYAN}Morpheus (von weit weg):{Colors.END} {Colors.YELLOW}'Wo bist du?! Der Agent ist da!'{Colors.END}")
|
|
slow_print(f"{Colors.WHITE}Die Tür schliesst sich. Der Kaninchenbau verschwindet -- fuer jetzt.{Colors.END}")
|
|
|
|
registry = load_item_registry()
|
|
token = registry.get("praetor_token")
|
|
if token:
|
|
player.inventory.add(token)
|
|
player.praetor_tokens += 1
|
|
slow_print(f"{Colors.GREEN}Du haltst einen Praetor-Token in der Hand, den es vorher nicht gab.{Colors.END}")
|
|
else:
|
|
slow_print(f"\n{Colors.WHITE}Du ignorierst das Flackern. Spaeter, vielleicht.{Colors.END}")
|
|
slow_print(f"{Colors.DIM}(Manche Kaninchenbaue oeffnen sich nur einmal.){Colors.END}")
|
|
|
|
dramatic_pause(0.5)
|
|
slow_print(f"\n{Colors.RED}KRACH!{Colors.END}")
|
|
slow_print(f"{Colors.WHITE}Die Wand explodiert. Ein Agent stürmt herein — aber er sieht... falsch aus.{Colors.END}")
|
|
slow_print(f"{Colors.WHITE}Sein Anzug ist zerrissen. Unter der Haut: Schuppen. Hörner.{Colors.END}")
|
|
|
|
return "agent_fight"
|
|
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────
|
|
# ERSTER KAMPF
|
|
# ─────────────────────────────────────────────────────────────────────────
|
|
|
|
def agent_fight(player, rng=None):
|
|
rng = rng or random
|
|
enemy = Enemy.create("agent_imp")
|
|
victory = run_combat(player, [enemy], title="KAMPF: AGENT IMP", rng=rng)
|
|
|
|
if not victory:
|
|
return "game_over"
|
|
|
|
slow_print(f"{Colors.YELLOW}Sein Körper zerfällt zu grünem Code und verschwindet.{Colors.END}")
|
|
dramatic_pause(1)
|
|
return "after_fight"
|
|
|
|
|
|
def after_fight(player, rng=None):
|
|
slow_print(f"\n{Colors.CYAN}Morpheus:{Colors.END} {Colors.YELLOW}'Beeindruckend. Aber das war nur ein Scout.'{Colors.END}")
|
|
slow_print(f"{Colors.CYAN}Trinity:{Colors.END} {Colors.YELLOW}'Wir müssen hier raus. Der HELL SERVER wartet.'{Colors.END}")
|
|
dramatic_pause(0.5)
|
|
|
|
slow_print(f"\n{Colors.WHITE}Vor dir öffnen sich drei Portale:{Colors.END}")
|
|
choice = menu([
|
|
("1", f"{Colors.RED}Roter Tunnel{Colors.END} — zurück zur Mars-UAC-Base"),
|
|
("2", f"{Colors.GREEN}Grüner Code-Strom{Colors.END} — tiefer in die Matrix"),
|
|
("3", f"{Colors.MAGENTA}Schwarzes Loch{Colors.END} — direkt zum HELL SERVER"),
|
|
], "Wähle deinen Weg")
|
|
|
|
if choice == "1":
|
|
player.layer = 4
|
|
return "mars_base"
|
|
elif choice == "2":
|
|
player.layer = 3
|
|
return "matrix_deep"
|
|
else:
|
|
player.layer = 2
|
|
return "hell_server"
|
|
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────
|
|
# MARS UAC BASE (Hub)
|
|
# ─────────────────────────────────────────────────────────────────────────
|
|
|
|
def mars_base(player, rng=None):
|
|
rng = rng or random
|
|
clear_screen()
|
|
slow_print(f"\n{Colors.RED}{Colors.BOLD}═══ MARS UAC BASE ═══{Colors.END}")
|
|
slow_print(f"{Colors.WHITE}Du materialisierst dich in einer kalten, roten Landschaft.{Colors.END}")
|
|
slow_print(f"{Colors.WHITE}Die UAC-Base liegt in Trümmern. Dämonen-Überreste überall.{Colors.END}")
|
|
dramatic_pause(1)
|
|
|
|
registry = load_item_registry()
|
|
|
|
def armory_event(p, ctx):
|
|
slow_print(f"\n{Colors.GREEN}Du findest den BFG 10000!{Colors.END}")
|
|
p.add_weapon("bfg10000")
|
|
p.ammo["bfg"] = max(p.ammo["bfg"], 3)
|
|
slow_print(f"{Colors.YELLOW}'Big Fucking Gun' — die ultimative Waffe.{Colors.END}")
|
|
slow_print(f"{Colors.RED}WARNUNG: Jeder Schuss verbraucht enorme Energie.{Colors.END}")
|
|
return None
|
|
|
|
def control_event(p, ctx):
|
|
slow_print(f"\n{Colors.GREEN}Ein Terminal flackert. Eine Nachricht von Dr. Betruger...{Colors.END}")
|
|
slow_print(f"{Colors.DIM}'Sie haben uns angelogen. Die Maschinen und die Dämonen...'{Colors.END}")
|
|
slow_print(f"{Colors.DIM}'...sie arbeiten zusammen. Die Matrix IST die Hölle.'{Colors.END}")
|
|
dramatic_pause(0.5)
|
|
slow_print(f"{Colors.GREEN}Du versuchst, das Kontrollzentrum zu hacken...{Colors.END}")
|
|
success = hacking.attempt_hack(p, firewall=10, rng=rng)
|
|
if success:
|
|
slow_print(f"{Colors.GREEN}Zugriff gewaehrt! Ein verstecktes Fach oeffnet sich.{Colors.END}")
|
|
frag = registry.get("crucible_fragment")
|
|
p.inventory.add(frag)
|
|
slow_print(f"{Colors.YELLOW}Du findest ein Crucible-Fragment! ({p.inventory.crucible_fragments}/3){Colors.END}")
|
|
else:
|
|
slow_print(f"{Colors.RED}Zugriff verweigert. Ein stiller Alarm wird ausgeloest.{Colors.END}")
|
|
return None
|
|
|
|
def vault_event(p, ctx):
|
|
if p.inventory.has_keycard("red"):
|
|
slow_print(f"\n{Colors.GREEN}Deine rote Keycard oeffnet den Waffentresor.{Colors.END}")
|
|
p.inventory.add(registry["ammo_pack"])
|
|
p.inventory.add(registry["armor_shard"])
|
|
slow_print(f"{Colors.GREEN}Ammo-Pack und Armor-Shard eingesammelt.{Colors.END}")
|
|
else:
|
|
slow_print(f"\n{Colors.RED}Der Waffentresor ist verriegelt. Du brauchst eine rote Keycard.{Colors.END}")
|
|
return None
|
|
|
|
armory = Room("mars_armory", "Waffenkammer",
|
|
"Zerbrochene Regale, geschmolzenes Metall. Etwas Grosses liegt unter den Truemmern.",
|
|
item_ids=["keycard_red"], on_enter=armory_event)
|
|
control = Room("mars_control", "Kontrollzentrum",
|
|
"Bildschirme voller Fehlermeldungen. Ein Terminal ist noch aktiv.",
|
|
on_enter=control_event)
|
|
vault = Room("mars_vault", "Waffentresor",
|
|
"Eine schwere, versiegelte Tuer. Rot markiert.",
|
|
locked_by="red", on_enter=vault_event)
|
|
|
|
filler = generate_filler_rooms("mars", 2, rng)
|
|
hub_start = Room("mars_hub", "Zentraler Korridor",
|
|
"Der Knotenpunkt der Basis. Drei Wege fuehren tiefer hinein.")
|
|
|
|
hub_start.exits = {
|
|
"Zur Waffenkammer": armory.room_id,
|
|
"Zum Kontrollzentrum": control.room_id,
|
|
"Zum Waffentresor": vault.room_id,
|
|
"Weiter erkunden": filler[0].room_id,
|
|
}
|
|
armory.exits = {"Zurueck zum Korridor": hub_start.room_id}
|
|
control.exits = {"Zurueck zum Korridor": hub_start.room_id}
|
|
vault.exits = {"Zurueck zum Korridor": hub_start.room_id}
|
|
chain_rooms(filler, "Weiter")
|
|
filler[-1].exits["Zum Portal (weiter zum HELL SERVER)"] = "mars_exit"
|
|
|
|
def portal_event(p, ctx):
|
|
slow_print(f"\n{Colors.YELLOW}Du aktivierst das Portal...{Colors.END}")
|
|
return ("leave", "portal_used")
|
|
|
|
exit_room = Room("mars_exit", "Portalraum",
|
|
"Ein pulsierendes, schwarzes Portal schwebt in der Mitte des Raums.",
|
|
on_enter=portal_event)
|
|
|
|
all_rooms = [hub_start, armory, control, vault, exit_room] + filler
|
|
hub = Hub(all_rooms, hub_start.room_id)
|
|
hub.explore(player, registry)
|
|
|
|
player.flags["visited_mars"] = True
|
|
if not player.flags.get("visited_matrix"):
|
|
slow_print(f"{Colors.YELLOW}Das Portal führt nicht zur Hölle -- es führt tiefer in die Matrix.{Colors.END}")
|
|
return "matrix_deep"
|
|
slow_print(f"{Colors.YELLOW}Das Portal führt zum HELL SERVER.{Colors.END}")
|
|
player.layer = 2
|
|
return "hell_server"
|
|
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────
|
|
# MATRIX DEEP — Orakel, schwarze Katze (Deja-vu-Glitch), Agent Smith
|
|
# ─────────────────────────────────────────────────────────────────────────
|
|
|
|
def _black_cat_glitch(player, rng):
|
|
"""Kein Item, kein weisses Fell -- eine SCHWARZE Katze, die zweimal EXAKT
|
|
denselben Weg laeuft. Das ist kein Zufall: es ist ein Zeichen dafuer, dass
|
|
jemand gerade den Code der Matrix veraendert hat ('ein Fehler in der Matrix')."""
|
|
section_title("DEJA VU", Colors.MAGENTA)
|
|
cat_line = "Eine schwarze Katze schleicht am Tuerrahmen vorbei, setzt zum Sprung an, verschwindet."
|
|
slow_print(f"{Colors.WHITE}{cat_line}{Colors.END}")
|
|
dramatic_pause(1)
|
|
|
|
slow_print(f"\n{Colors.DIM}...{Colors.END}")
|
|
dramatic_pause(0.5)
|
|
|
|
# Exakt derselbe Satz, bewusst identisch -- das IST der Bug.
|
|
slow_print(f"{Colors.WHITE}{cat_line}{Colors.END}")
|
|
dramatic_pause(0.3)
|
|
|
|
slow_print(f"\n{Colors.MAGENTA}Trinity erstarrt.{Colors.END}")
|
|
slow_print(f"{Colors.CYAN}Trinity:{Colors.END} {Colors.YELLOW}'Das war... derselbe Moment. Exakt derselbe.'{Colors.END}")
|
|
slow_print(f"{Colors.CYAN}Trinity:{Colors.END} {Colors.YELLOW}'Ein Deja-vu ist kein Zufall. Es bedeutet, dass sich gerade{Colors.END}")
|
|
slow_print(f"{Colors.CYAN}Trinity:{Colors.END} {Colors.YELLOW}etwas im Code veraendert hat. Jemand manipuliert diesen Server. Jetzt.'{Colors.END}")
|
|
dramatic_pause(1)
|
|
|
|
player.flags["cat_glitch_count"] += 1
|
|
player.flags["cat_glitch_seen"] = True
|
|
|
|
choice = menu([
|
|
("1", "Dem Glitch nachspueren (Hacking-Check)"),
|
|
("2", "Ignorieren und weitergehen"),
|
|
], "Reaktion")
|
|
|
|
if choice == "1":
|
|
success = hacking.attempt_hack(player, firewall=12, rng=rng)
|
|
if success:
|
|
slow_print(f"\n{Colors.GREEN}Du findest die Bruchstelle im Code -- eine Naht, wo etwas neu geschrieben wurde.{Colors.END}")
|
|
slow_print(f"{Colors.GREEN}Ein Log-Fragment sickert durch: {Colors.DIM}'...Hayden-Prozess re-kompiliert um 03:14...'{Colors.END}")
|
|
registry = load_item_registry()
|
|
player.inventory.add(registry["logfile"])
|
|
player.gain_corruption(2)
|
|
else:
|
|
slow_print(f"\n{Colors.RED}Die Naht schliesst sich, bevor du sie greifen kannst.{Colors.END}")
|
|
else:
|
|
slow_print(f"\n{Colors.WHITE}Du gehst weiter. Manche Bugs loest man besser nicht.{Colors.END}")
|
|
|
|
|
|
def _oracle_scene(player, rng):
|
|
clear_screen()
|
|
section_title("DIE KUeCHE DES ORAKELS", Colors.YELLOW)
|
|
slow_print(f"{Colors.WHITE}Der Geruch von frisch gebackenen Keksen fuehlt sich falsch an in einem Ort aus Code.{Colors.END}")
|
|
slow_print(f"{Colors.WHITE}Eine aeltere Frau steht am Herd, ohne sich umzudrehen.{Colors.END}")
|
|
dramatic_pause(0.5)
|
|
|
|
slow_print(f"\n{Colors.YELLOW}Das Orakel:{Colors.END} {Colors.WHITE}'Setz dich, Slayer. Oder Neo. Ich hab schon beide Kekse gebacken.'{Colors.END}")
|
|
dramatic_pause(0.5)
|
|
|
|
if player.flags.get("followed_rabbit"):
|
|
slow_print(f"\n{Colors.YELLOW}Das Orakel:{Colors.END} {Colors.WHITE}'Du bist dem Hasen gefolgt. Gut. Nicht viele tun das zweimal.'{Colors.END}")
|
|
else:
|
|
slow_print(f"\n{Colors.YELLOW}Das Orakel:{Colors.END} {Colors.WHITE}'Du hast den Hasen ignoriert. Verstaendlich. Kaninchenbaue sind unbequem.'{Colors.END}")
|
|
|
|
if player.corruption >= 30:
|
|
slow_print(f"\n{Colors.YELLOW}Das Orakel:{Colors.END} {Colors.WHITE}'Du riechst nach Schwefel, Kind. Das waechst schneller, als dir lieb ist.'{Colors.END}")
|
|
|
|
dramatic_pause(0.5)
|
|
slow_print(f"\n{Colors.YELLOW}Das Orakel:{Colors.END} {Colors.WHITE}'Ich sag dir nicht, was passieren wird. Ich sag dir nur:{Colors.END}")
|
|
slow_print(f"{Colors.YELLOW}Das Orakel:{Colors.END} {Colors.WHITE}Morpheus glaubt an dich mehr, als er an sich selbst glaubt.{Colors.END}")
|
|
slow_print(f"{Colors.YELLOW}Das Orakel:{Colors.END} {Colors.WHITE}Frag dich mal, warum.'{Colors.END}")
|
|
dramatic_pause(1)
|
|
|
|
choice = menu([
|
|
("1", "'Bin ich Der Eine?'"),
|
|
("2", "'Ist Morpheus, wer er zu sein scheint?'"),
|
|
("3", "'Was ist der HELL SERVER wirklich?'"),
|
|
], "Deine Frage")
|
|
|
|
if choice == "1":
|
|
slow_print(f"\n{Colors.YELLOW}Das Orakel:{Colors.END} {Colors.WHITE}'Falsche Frage. Es geht nicht darum, was du bist.'{Colors.END}")
|
|
slow_print(f"{Colors.YELLOW}Das Orakel:{Colors.END} {Colors.WHITE}'Es geht darum, was du als Naechstes tust.'{Colors.END}")
|
|
elif choice == "2":
|
|
slow_print(f"\n{Colors.YELLOW}Das Orakel:{Colors.END} {Colors.WHITE}'...'{Colors.END}")
|
|
slow_print(f"{Colors.YELLOW}Das Orakel:{Colors.END} {Colors.WHITE}'Manche Antworten wuerden dir mehr schaden als der Cyberdemon.'{Colors.END}")
|
|
slow_print(f"{Colors.YELLOW}Das Orakel:{Colors.END} {Colors.WHITE}'Behalt einfach im Hinterkopf: nicht jeder, der dich rettet, luegt nicht dabei.'{Colors.END}")
|
|
else:
|
|
slow_print(f"\n{Colors.YELLOW}Das Orakel:{Colors.END} {Colors.WHITE}'Ein Generator. Er wandelt Seelen in Strom und Strom in Daemonen um.'{Colors.END}")
|
|
slow_print(f"{Colors.YELLOW}Das Orakel:{Colors.END} {Colors.WHITE}'Die Matrix laeuft nicht NEBEN der Hoelle. Sie laeuft AUF ihr.'{Colors.END}")
|
|
|
|
dramatic_pause(1)
|
|
slow_print(f"\n{Colors.YELLOW}Das Orakel:{Colors.END} {Colors.WHITE}'Hier. Nimm das. Du wirst es brauchen -- oder auch nicht.'{Colors.END}")
|
|
registry = load_item_registry()
|
|
player.inventory.add(registry["crucible_fragment"])
|
|
slow_print(f"{Colors.YELLOW}Du erhaeltst ein Crucible-Fragment! ({player.inventory.crucible_fragments}/3){Colors.END}")
|
|
player.flags["met_oracle"] = True
|
|
|
|
|
|
def matrix_deep(player, rng=None):
|
|
rng = rng or random
|
|
clear_screen()
|
|
slow_print(f"\n{Colors.GREEN}{Colors.BOLD}═══ TIEF IN DER MATRIX ═══{Colors.END}")
|
|
slow_print(f"{Colors.WHITE}Der Code wird dichter. Realität ist hier nur eine Option.{Colors.END}")
|
|
slow_print(f"{Colors.WHITE}Du siehst endlose Reihen von Menschen in Stasiskapseln —{Colors.END}")
|
|
slow_print(f"{Colors.WHITE}aber sie spielen nicht nur Sims. Sie RENDERN.{Colors.END}")
|
|
dramatic_pause(1)
|
|
|
|
_black_cat_glitch(player, rng)
|
|
dramatic_pause(0.5)
|
|
_oracle_scene(player, rng)
|
|
dramatic_pause(1)
|
|
|
|
clear_screen()
|
|
slow_print(f"\n{Colors.CYAN}Ein Agent erscheint — aber er sieht normal aus. Smith?{Colors.END}")
|
|
slow_print(f"{Colors.CYAN}Agent Smith:{Colors.END} {Colors.YELLOW}'Mr. Anderson... oder sollte ich sagen...{Colors.END}")
|
|
slow_print(f"{Colors.CYAN}Agent Smith:{Colors.END} {Colors.YELLOW}'...Doom Slayer?'{Colors.END}")
|
|
dramatic_pause(1)
|
|
|
|
slow_print(f"\n{Colors.RED}Smith lächelt. Sein Lächeln ist zu breit. Zu viele Zähne.{Colors.END}")
|
|
|
|
choice = menu([
|
|
("1", "'Mein Name ist Neo.' (Klassisch)"),
|
|
("2", "'Rip and tear, until it is done.' (Doom)"),
|
|
("3", "Beides gleichzeitig sagen (Chaos)"),
|
|
], "Deine Antwort")
|
|
|
|
smith_clones = 1
|
|
if choice == "1":
|
|
slow_print(f"\n{Colors.GREEN}'Mein Name ist Neo.'{Colors.END}")
|
|
slow_print(f"{Colors.CYAN}Smith:{Colors.END} {Colors.YELLOW}'Wie vorhersehbar.'{Colors.END}")
|
|
slow_print(f"{Colors.RED}Smith multipliziert sich! Klone umzingeln dich!{Colors.END}")
|
|
smith_clones = 3
|
|
elif choice == "2":
|
|
slow_print(f"\n{Colors.RED}'Rip and tear, until it is done.'{Colors.END}")
|
|
slow_print(f"{Colors.CYAN}Smith:{Colors.END} {Colors.YELLOW}'Interessant. Sie haben sich verändert.'{Colors.END}")
|
|
slow_print(f"{Colors.YELLOW}Smith zögert. Er kennt diese Worte nicht.{Colors.END}")
|
|
player.add_armor(20)
|
|
smith_clones = 1
|
|
else:
|
|
slow_print(f"\n{Colors.GREEN}'Mein Name ist Neo...'{Colors.END}")
|
|
dramatic_pause(0.5)
|
|
slow_print(f"{Colors.RED}'...und ICH WERDE ALLES ZERREISSEN!'{Colors.END}")
|
|
slow_print(f"{Colors.YELLOW}Du aktivierst Bullet Time UND Berserker-Mode gleichzeitig!{Colors.END}")
|
|
player.heal(20)
|
|
player.add_armor(30)
|
|
player.gain_corruption(3)
|
|
smith_clones = 2
|
|
|
|
enemies = [Enemy.create("agent_clone") for _ in range(smith_clones)]
|
|
enemies[0].name = "Agent Smith"
|
|
victory = run_combat(player, enemies, title="KAMPF: AGENT SMITH", rng=rng)
|
|
|
|
if not victory:
|
|
return "game_over"
|
|
|
|
slow_print(f"\n{Colors.RED}Der Kampf ist vorbei. Aber Smith ist nicht allein...{Colors.END}")
|
|
slow_print(f"{Colors.MAGENTA}Hinter ihm öffnet sich ein Portal.{Colors.END}")
|
|
|
|
player.flags["visited_matrix"] = True
|
|
if not player.flags.get("visited_mars"):
|
|
slow_print(f"{Colors.MAGENTA}Es führt nicht zur Hölle -- es führt zur Mars-Basis.{Colors.END}")
|
|
return "mars_base"
|
|
|
|
slow_print(f"{Colors.MAGENTA}Es führt zur Hölle.{Colors.END}")
|
|
player.layer = 2
|
|
return "hell_server"
|
|
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────
|
|
# HELL SERVER (Hub + Boss)
|
|
# ─────────────────────────────────────────────────────────────────────────
|
|
|
|
def hell_server(player, rng=None):
|
|
rng = rng or random
|
|
clear_screen()
|
|
slow_print(f"\n{Colors.MAGENTA}{Colors.BOLD}═══ HELL SERVER ═══{Colors.END}")
|
|
slow_print(f"{Colors.WHITE}Du betrittst einen Raum, der nicht existieren sollte.{Colors.END}")
|
|
slow_print(f"{Colors.WHITE}Lava-Flüsse aus geschmolzenem Silizium.{Colors.END}")
|
|
slow_print(f"{Colors.WHITE}Dämonen mit Netzwerk-Kabeln statt Nervensträngen.{Colors.END}")
|
|
dramatic_pause(1)
|
|
|
|
registry = load_item_registry()
|
|
filler = generate_filler_rooms("hell", 2, rng, seed_offset=10)
|
|
chain_rooms(filler, "Tiefer")
|
|
|
|
def altar_event(p, ctx):
|
|
slow_print(f"\n{Colors.GREEN}Auf einem Altar aus Motherboards liegt ein Splitter reinen Codes.{Colors.END}")
|
|
registry_local = load_item_registry()
|
|
p.inventory.add(registry_local["crucible_fragment"])
|
|
slow_print(f"{Colors.YELLOW}Crucible-Fragment gefunden! ({p.inventory.crucible_fragments}/3){Colors.END}")
|
|
return None
|
|
|
|
altar = Room("hell_altar", "Altarraum",
|
|
"Ein Altar aus verschmolzenen Platinen. Etwas glueht darauf.",
|
|
on_enter=altar_event)
|
|
|
|
boss_state = {"fought": False}
|
|
|
|
def boss_event(p, ctx):
|
|
slow_print(f"\n{Colors.RED}Ein Cyberdemon tritt aus den Schatten.{Colors.END}")
|
|
slow_print(f"{Colors.RED}Sein Körper ist halb Fleisch, halb Server-Rack.{Colors.END}")
|
|
slow_print(f"{Colors.RED}Seine Raketenwerfer sind mit Ethernet-Kabeln verbunden.{Colors.END}")
|
|
dramatic_pause(1)
|
|
slow_print(f"\n{Colors.CYAN}Trinity:{Colors.END} {Colors.YELLOW}'Das ist es. Der HELL SERVER.'{Colors.END}")
|
|
slow_print(f"{Colors.CYAN}Trinity:{Colors.END} {Colors.YELLOW}'Wenn wir den zerstören, fällt die gesamte Simulation!'{Colors.END}")
|
|
|
|
boss = Enemy.create("cyberdemon")
|
|
victory = run_combat(player, [boss], title="BOSS: CYBERDEMON", rng=rng)
|
|
if not victory:
|
|
return ("leave", "game_over")
|
|
|
|
slow_print(f"\n{Colors.YELLOW}Der Cyberdemon zerfaellt in Bytes und Asche!{Colors.END}")
|
|
slow_print(f"{Colors.GREEN}Der HELL SERVER stürzt ein!{Colors.END}")
|
|
boss_state["fought"] = True
|
|
return ("leave", "final_boss")
|
|
|
|
boss_room = Room("hell_boss", "Serverkern", "Die Hitze hier ist unertraeglich. Etwas Grosses wartet.",
|
|
on_enter=boss_event, one_time_event=False)
|
|
|
|
hub_start = Room("hell_hub", "Lavaspalte",
|
|
"Gluehende Risse durchziehen den Boden. Zwei Wege fuehren tiefer.")
|
|
hub_start.exits = {
|
|
"Zum Altarraum": altar.room_id,
|
|
"Weiter erkunden": filler[0].room_id,
|
|
"Zum Serverkern (Boss)": boss_room.room_id,
|
|
}
|
|
altar.exits = {"Zurueck": hub_start.room_id}
|
|
filler[-1].exits["Zum Serverkern (Boss)"] = boss_room.room_id
|
|
|
|
all_rooms = [hub_start, altar, boss_room] + filler
|
|
hub = Hub(all_rooms, hub_start.room_id)
|
|
result = hub.explore(player, registry)
|
|
|
|
if isinstance(result, tuple) and result[0] == "leave":
|
|
return result[1]
|
|
return "final_boss"
|
|
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────
|
|
# FINAL BOSS: DER ARCHI-LORD
|
|
# ─────────────────────────────────────────────────────────────────────────
|
|
|
|
def final_boss(player, rng=None):
|
|
rng = rng or random
|
|
dramatic_pause(1)
|
|
clear_screen()
|
|
|
|
slow_print(f"\n{Colors.YELLOW}{Colors.BOLD}═══ DER ARCHI-LORD ═══{Colors.END}")
|
|
slow_print(f"{Colors.WHITE}Hinter den Trümmern des HELL SERVERS öffnet sich eine weiße Tür.{Colors.END}")
|
|
slow_print(f"{Colors.WHITE}Dahinter: Ein Raum aus reinem Licht. Und Code.{Colors.END}")
|
|
dramatic_pause(1)
|
|
|
|
slow_print(f"\n{Colors.YELLOW}Eine Gestalt materialisiert — halb Der Architekt, halb Dark Lord Davoth.{Colors.END}")
|
|
slow_print(f"{Colors.YELLOW}Der Archi-Lord.{Colors.END}")
|
|
dramatic_pause(1)
|
|
|
|
slow_print(f"\n{Colors.YELLOW}Archi-Lord:{Colors.END} {Colors.WHITE}'Willkommen, Doom Slayer. Oder Neo. Oder wer auch immer Sie heute sind.'{Colors.END}")
|
|
slow_print(f"{Colors.YELLOW}Archi-Lord:{Colors.END} {Colors.WHITE}'Sie haben beide Systeme zerstört. Die Matrix. Die Hölle.'{Colors.END}")
|
|
slow_print(f"{Colors.YELLOW}Archi-Lord:{Colors.END} {Colors.WHITE}'Was erwarten Sie als Nächstes? Eine Medaille?'{Colors.END}")
|
|
|
|
if player.inventory.crucible_fragments >= 3:
|
|
dramatic_pause(0.5)
|
|
slow_print(f"\n{Colors.YELLOW}Archi-Lord:{Colors.END} {Colors.WHITE}'...Sie haben alle drei Fragmente. Wie unerwartet.'{Colors.END}")
|
|
|
|
dramatic_pause(1)
|
|
|
|
choice = menu([
|
|
("1", "'Ich will die Wahrheit.'"),
|
|
("2", "'Ich will alles zerstören.'"),
|
|
("3", "'Ich will die Kontrolle uebernehmen.'"),
|
|
("4", "'Ich will... einen neuen Spielstand.'"),
|
|
], "Deine Antwort")
|
|
|
|
player.flags["final_choice"] = choice
|
|
|
|
if choice == "1":
|
|
slow_print(f"\n{Colors.YELLOW}Archi-Lord:{Colors.END} {Colors.WHITE}'Die Wahrheit? Die Wahrheit ist...'{Colors.END}")
|
|
dramatic_pause(1.5)
|
|
slow_print(f"{Colors.YELLOW}Archi-Lord:{Colors.END} {Colors.WHITE}'...dass Sie nur Code sind. In meinem Code. In meinem Spiel.'{Colors.END}")
|
|
elif choice == "2":
|
|
slow_print(f"\n{Colors.RED}Du aktivierst alle Waffen gleichzeitig.{Colors.END}")
|
|
slow_print(f"{Colors.RED}Super Shotgun. Plasma Rifle. BFG 10000. Fäuste.{Colors.END}")
|
|
player.gain_corruption(15)
|
|
elif choice == "3":
|
|
slow_print(f"\n{Colors.MAGENTA}'Ich brauche keine Wahrheit. Ich brauche die Zuegel.'{Colors.END}")
|
|
player.gain_corruption(25)
|
|
else:
|
|
slow_print(f"\n{Colors.GREEN}Du lächelst.{Colors.END}")
|
|
slow_print(f"{Colors.GREEN}'Ich will einen neuen Spielstand. Mit Cheats.'{Colors.END}")
|
|
slow_print(f"{Colors.YELLOW}Archi-Lord:{Colors.END} {Colors.WHITE}'...Interessant.'{Colors.END}")
|
|
|
|
if player.inventory.crucible_fragments >= 3 and not player.has_weapon("crucible"):
|
|
dramatic_pause(0.5)
|
|
use_crucible = menu([
|
|
("1", "Die drei Fragmente zum Crucible Sword verschmelzen"),
|
|
("2", "Fragmente aufbewahren"),
|
|
], "Du spuerst die Fragmente pulsieren")
|
|
if use_crucible == "1":
|
|
player.add_weapon("crucible")
|
|
slow_print(f"\n{Colors.YELLOW}Die Fragmente verschmelzen zum Crucible Sword!{Colors.END}")
|
|
|
|
dramatic_pause(1)
|
|
boss = Enemy.create("archi_lord")
|
|
victory = run_combat(player, [boss], title="ENDBOSS: DER ARCHI-LORD", rng=rng)
|
|
|
|
if not victory:
|
|
return "game_over"
|
|
|
|
return "layer_zero_check"
|
|
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────
|
|
# LAYER 0 — das geheime, wahre Ende ("Wake Up")
|
|
# ─────────────────────────────────────────────────────────────────────────
|
|
|
|
def layer_zero_unlocked(player):
|
|
return player.inventory.crucible_fragments >= 3 and player.flags.get("followed_rabbit")
|
|
|
|
|
|
def layer_zero_check(player, rng=None):
|
|
if not layer_zero_unlocked(player):
|
|
return "ending"
|
|
|
|
dramatic_pause(1)
|
|
clear_screen()
|
|
section_title("LAYER 0", Colors.WHITE)
|
|
slow_print(f"{Colors.WHITE}Der Archi-Lord zerfaellt -- aber diesmal reorganisiert sich der Code nicht.{Colors.END}")
|
|
slow_print(f"{Colors.WHITE}Die drei Crucible-Fragmente in deiner Hand ziehen sich gegenseitig an.{Colors.END}")
|
|
slow_print(f"{Colors.WHITE}Du erinnerst dich an den Hasen. An den Kaninchenbau, den du einmal betreten hast.{Colors.END}")
|
|
dramatic_pause(1)
|
|
|
|
slow_print(f"\n{Colors.WHITE}Der Raum um dich loest sich nicht in Trümmer auf. Er loest sich in {Colors.DIM}Syntax{Colors.END}{Colors.WHITE} auf.{Colors.END}")
|
|
try:
|
|
real_user = os.getlogin()
|
|
except Exception:
|
|
real_user = "SPIELER"
|
|
slow_print(f"{Colors.DIM}{glitch_text(f'PROZESS {real_user} HAT DIE SIMULATION ERKANNT', 0.2)}{Colors.END}", 0.01)
|
|
dramatic_pause(1)
|
|
|
|
slow_print(f"\n{Colors.WHITE}Kein Morpheus. Kein Orakel. Kein Archi-Lord.{Colors.END}")
|
|
slow_print(f"{Colors.WHITE}Nur ein Terminal-Fenster. Und du, davor.{Colors.END}")
|
|
slow_print(f"{Colors.WHITE}Layer 4. Layer 3. Layer 2. Layer 1. Und jetzt: {Colors.BOLD}Layer 0{Colors.END}{Colors.WHITE}.{Colors.END}")
|
|
dramatic_pause(1)
|
|
|
|
slow_print(f"\n{Colors.GREEN}Es gibt keinen loeffel. Es gab nie ein Spiel, das dich gespielt hat.{Colors.END}")
|
|
slow_print(f"{Colors.GREEN}Es gab nur dich, das Terminal, und die Entscheidung weiterzulesen.{Colors.END}")
|
|
|
|
player.layer = 0
|
|
player.flags["reached_layer_zero"] = True
|
|
dramatic_pause(1.5)
|
|
return "ending"
|