import os import gradio as gr from huggingface_hub import InferenceClient # Token aus den Hugging Face Secrets laden token = os.environ.get("HF_TOKEN") text_client = InferenceClient("google/gemma-1.1-7b-it", token=token) # Wir brauchen SDXL Turbo für extrem schnelle Bilder am Handy! bild_client = InferenceClient("stabilityai/sdxl-turbo", token=token) # Unser neues, ultra-atmosphärisches CSS (Gestaltungscode) # Wir fügen die Styles für das gestapelte Logbuch hinzu. geiles_design = """ @import url('https://fonts.googleapis.com/css2?family=Special+Elite&display=swap'); body, .gradio-container { /* Düsteres Apokalypse-Hintergrundbild aus dem Netz */ background-image: url('https://images.unsplash.com/photo-1485603099951-40344d18721c?q=80&w=2000&auto=format&fit=crop') !important; background-size: cover !important; background-position: center !important; background-attachment: fixed !important; font-family: sans-serif; } /* Der Hauptbereich wird schwarz und leicht durchsichtig */ .haupt-bereich { background: rgba(0, 0, 0, 0.7) !important; border-radius: 10px; padding: 20px !important; max-width: 800px !important; margin: 0 auto !important; backdrop-filter: blur(3px); /* Macht das Hintergrundbild leicht unscharf */ border: 1px solid rgba(255, 255, 255, 0.1); } h1 { color: #d4af37 !important; text-align: center; text-transform: uppercase; font-size: 2.5em !important; text-shadow: 2px 2px 4px #000; margin-bottom: 20px !important;} /* Der Rucksack */ .rucksack-anzeige { background: rgba(0, 0, 0, 0.8) !important; border: 1px solid #8b0000 !important; padding: 12px !important; color: #d4af37 !important; text-align: center; border-radius: 5px; margin-bottom: 20px !important; font-weight: bold; } /* Der Notizzettel für die Story! */ .notizzettel { background: #e3dec6 !important; /* Schmutzige Papier-Farbe */ color: #1a1a1a !important; font-family: 'Special Elite', monospace !important; /* Echte Schreibmaschinen-Schrift */ font-size: 1.3em !important; line-height: 1.6 !important; padding: 25px !important; border-radius: 2px !important; box-shadow: 3px 3px 15px rgba(0,0,0,0.8) !important; transform: rotate(-1deg); /* Leichte Drehung für den echten Zettel-Look */ margin: 20px 5px !important; border-left: 4px solid #8b0000 !important; /* Roter Rand */ } /* Rahmen für das generierte Bild */ .output-bild { border: 2px solid #555 !important; border-radius: 3px !important; box-shadow: 0 5px 15px rgba(0,0,0,0.9) !important;} /* Eingabefeld durchsichtig machen */ input, textarea { background: rgba(0, 0, 0, 0.6) !important; color: #fff !important; border: 1px solid #8b0000 !important; font-size: 1.2em !important; border-radius: 5px !important; } /* Aggressiver Action-Button */ button { background: #8b0000 !important; color: #fff !important; border: none !important; font-weight: bold !important; text-transform: uppercase !important; font-size: 1.2em !important; padding: 12px !important; border-radius: 5px !important; box-shadow: 0 4px 6px rgba(0,0,0,0.6) !important; } button:hover { background: #aa0000 !important; } """ def spiel_zug(nachricht, aktueller_rucksack): if not nachricht: return None, "Du musst schon was tun!", aktueller_rucksack, f"🎒 INVENTAR: {aktueller_rucksack}", "" system_prompt = f"""Du bist 'Zombie Go'. Inventar des Spielers: {aktueller_rucksack}. Regel: Der Spieler darf NUR Dinge nutzen, die im Inventar sind. Erfinde keine Waffen für ihn. Füge neu gefundene Gegenstände oder gesammeltes 'Go' logisch zum Rucksack hinzu. Aktion des Spielers: '{nachricht}'. Antworte EXAKT in dieser Form (ohne Ausnahmen): STORY: [Beschreibe in max 3 spannenden Sätzen, was passiert] RUCKSACK: [Liste der Items] | GO: [Anzahl]""" try: antwort = text_client.text_generation(system_prompt, max_new_tokens=200) # Split (Text zerteilen): Wir trennen Story und Rucksack am Wort "RUCKSACK:" if "RUCKSACK:" in antwort: teile = antwort.split("RUCKSACK:") story_text = teile[0].replace("STORY:", "").strip() neuer_rucksack = teile[1].strip() else: # Falls die KI den Befehl vermasselt, behalten wir den alten Rucksack story_text = antwort.replace("STORY:", "").strip() neuer_rucksack = aktueller_rucksack except Exception as e: story_text = "Die Verbindung stottert... die KI schnappt nach Luft." neuer_rucksack = aktueller_rucksack # Bild-KI (SDXL Turbo - EXTREM SCHNELL!) # Wir fügen düstere englische Begriffe hinzu, damit die KI das Zombie-Go-Thema versteht bild_prompt = f"dark zombie apocalypse survival scene, first person view, {nachricht}, eerie green lighting from glowing crystals, highly detailed, realistic texture, derelict ruined city, atmospheric" try: # SDXL Turbo braucht extrem wenige Schritte und ist fast sofort fertig! bild = bild_client.text_to_image(bild_prompt, num_inference_steps=1) except: bild = None rucksack_ui_text = f"🎒 INVENTAR: {neuer_rucksack}" # Gibt alles zurück: Chat, Bild, leeres Textfeld, schicke Anzeige, unsichtbarer Speicher return bild, story_text, neuer_rucksack, rucksack_ui_text, "" with gr.Blocks(css=geiles_design, theme=gr.themes.Base()) as spiel_oberflaeche: # Wir geben dem Haupt-Bereich die CSS-Klasse 'haupt-bereich' with gr.Column(elem_classes="haupt-bereich"): gr.Markdown("# 🧟 ZOMBIE GO") # State (unsichtbarer Speicher) für deinen Start-Rucksack rucksack_speicher = gr.State("Taschenlampe, leere Wasserflasche | GO: 0") rucksack_ui = gr.Markdown("🎒 INVENTAR: Taschenlampe, leere Wasserflasche | GO: 0", elem_classes="rucksack-anzeige") # Das generierte Bild szene_bild = gr.Image(label="Visuelles Echo", type="pil", elem_classes="output-bild") # Der Notizzettel für die Story! story_ausgabe = gr.Markdown("*Warte auf Eingabe... (Tipp: 'Umschauen')*", elem_classes="notizzettel") gr.Markdown("---") # Eingabe-Bereich eingabe = gr.Textbox(label="", placeholder="Was tust du? (z.B. Zombies looten)", lines=1) senden_btn = gr.Button("▶ AKTION EINTRAGEN") # Verknüpfungen der Knöpfe (wichtige Reihenfolge der Outputs!) senden_btn.click( spiel_zug, inputs=[eingabe, rucksack_speicher], outputs=[szene_bild, story_ausgabe, rucksack_speicher, rucksack_ui, eingabe] ) eingabe.submit( spiel_zug, inputs=[eingabe, rucksack_speicher], outputs=[szene_bild, story_ausgabe, rucksack_speicher, rucksack_ui, eingabe] ) # Startet das Game spiel_oberflaeche.launch()