Zombie_Go / app.py
LucanDerLurch's picture
Update app.py
33d1e4c verified
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()