Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -14,21 +14,22 @@ geiles_design = """
|
|
| 14 |
@import url('https://fonts.googleapis.com/css2?family=Special+Elite&display=swap');
|
| 15 |
|
| 16 |
body, .gradio-container {
|
| 17 |
-
/*
|
| 18 |
-
background-image: url('
|
| 19 |
background-size: cover !important;
|
| 20 |
background-position: center !important;
|
| 21 |
background-attachment: fixed !important;
|
| 22 |
font-family: sans-serif;
|
| 23 |
}
|
| 24 |
|
|
|
|
| 25 |
.haupt-bereich {
|
| 26 |
background: rgba(0, 0, 0, 0.7) !important;
|
| 27 |
border-radius: 10px;
|
| 28 |
padding: 20px !important;
|
| 29 |
max-width: 800px !important;
|
| 30 |
margin: 0 auto !important;
|
| 31 |
-
backdrop-filter: blur(
|
| 32 |
border: 1px solid rgba(255, 255, 255, 0.1);
|
| 33 |
}
|
| 34 |
|
|
@@ -46,47 +47,25 @@ h1 { color: #d4af37 !important; text-align: center; text-transform: uppercase; f
|
|
| 46 |
font-weight: bold;
|
| 47 |
}
|
| 48 |
|
| 49 |
-
/*
|
| 50 |
-
.
|
| 51 |
-
|
| 52 |
-
/* --- Das Logbuch --- */
|
| 53 |
-
/* Dies ist der Container für den Chat-Verlauf, der wie ein Stapel Notizen aussieht */
|
| 54 |
-
.logbuch-stapel {
|
| 55 |
-
margin: 20px 0 !important;
|
| 56 |
-
height: 400px !important;
|
| 57 |
-
overflow-y: scroll !important; /* Scrollen, wenn der Stapel zu lang wird */
|
| 58 |
-
}
|
| 59 |
-
|
| 60 |
-
/* Jeder Eintrag (dein Text ODER der KI-Text) wird zu einem eigenen Notizzettel */
|
| 61 |
-
.notizzettel-eintrag {
|
| 62 |
-
background: #e3dec6 !important;
|
| 63 |
color: #1a1a1a !important;
|
| 64 |
-
font-family: 'Special Elite', monospace !important;
|
| 65 |
font-size: 1.3em !important;
|
| 66 |
line-height: 1.6 !important;
|
| 67 |
-
padding:
|
| 68 |
border-radius: 2px !important;
|
| 69 |
-
box-shadow:
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
border-left: 4px solid #8b0000 !important;
|
| 73 |
-
}
|
| 74 |
-
|
| 75 |
-
/* Deine Notizen sind links */
|
| 76 |
-
.user-notiz {
|
| 77 |
-
transform: rotate(0.5deg);
|
| 78 |
-
margin-right: 15% !important;
|
| 79 |
-
border-left-color: #d4af37 !important;
|
| 80 |
-
opacity: 0.9;
|
| 81 |
}
|
| 82 |
|
| 83 |
-
/*
|
| 84 |
-
.
|
| 85 |
-
transform: rotate(-0.5deg);
|
| 86 |
-
margin-left: 15% !important;
|
| 87 |
-
}
|
| 88 |
|
| 89 |
-
/*
|
| 90 |
input, textarea {
|
| 91 |
background: rgba(0, 0, 0, 0.6) !important;
|
| 92 |
color: #fff !important;
|
|
@@ -95,6 +74,7 @@ input, textarea {
|
|
| 95 |
border-radius: 5px !important;
|
| 96 |
}
|
| 97 |
|
|
|
|
| 98 |
button {
|
| 99 |
background: #8b0000 !important;
|
| 100 |
color: #fff !important;
|
|
@@ -109,40 +89,22 @@ button {
|
|
| 109 |
button:hover { background: #aa0000 !important; }
|
| 110 |
"""
|
| 111 |
|
| 112 |
-
|
| 113 |
-
def generiere_logbuch_html(verlauf):
|
| 114 |
-
html = '<div class="logbuch-stapel">'
|
| 115 |
-
# Start-Text hinzufügen, wenn der Verlauf leer ist
|
| 116 |
-
if not verlauf:
|
| 117 |
-
start_text = "Tag 1. Mein Kopf dröhnt. Ich bin in einem verlassenen Supermarkt aufgewacht. Die Regale sind geplündert, draußen brennen Autos. Ich höre ein ekliges Kratzen an den vernagelten Fenstern. Neben mir liegt ein altes Brecheisen. Ich muss hier raus..."
|
| 118 |
-
html += f'<div class="notizzettel-eintrag ai-notiz"> {start_text} </div>'
|
| 119 |
-
else:
|
| 120 |
-
# Den Verlauf durchgehen und Notizen stapeln
|
| 121 |
-
for user_text, ai_text in verlauf:
|
| 122 |
-
if user_text:
|
| 123 |
-
html += f'<div class="notizzettel-eintrag user-notiz"> {user_text} </div>'
|
| 124 |
-
if ai_text:
|
| 125 |
-
html += f'<div class="notizzettel-eintrag ai-notiz"> {ai_text} </div>'
|
| 126 |
-
html += '</div>'
|
| 127 |
-
return html
|
| 128 |
-
|
| 129 |
-
def spiel_zug(nachricht, verlauf, aktueller_rucksack):
|
| 130 |
if not nachricht:
|
| 131 |
-
return
|
| 132 |
-
f"🎒 INVENTAR: {aktueller_rucksack}", "")
|
| 133 |
|
| 134 |
-
# Die KI soll die Story UND den Rucksack verwalten
|
| 135 |
system_prompt = f"""Du bist 'Zombie Go'.
|
| 136 |
Inventar des Spielers: {aktueller_rucksack}.
|
| 137 |
Regel: Der Spieler darf NUR Dinge nutzen, die im Inventar sind. Erfinde keine Waffen für ihn.
|
|
|
|
| 138 |
Aktion des Spielers: '{nachricht}'.
|
| 139 |
|
| 140 |
Antworte EXAKT in dieser Form (ohne Ausnahmen):
|
| 141 |
-
STORY: [Beschreibe in max 3 spannenden Sätzen, was passiert
|
| 142 |
RUCKSACK: [Liste der Items] | GO: [Anzahl]"""
|
| 143 |
|
| 144 |
try:
|
| 145 |
-
antwort = text_client.text_generation(system_prompt, max_new_tokens=
|
| 146 |
|
| 147 |
# Split (Text zerteilen): Wir trennen Story und Rucksack am Wort "RUCKSACK:"
|
| 148 |
if "RUCKSACK:" in antwort:
|
|
@@ -155,16 +117,11 @@ def spiel_zug(nachricht, verlauf, aktueller_rucksack):
|
|
| 155 |
neuer_rucksack = aktueller_rucksack
|
| 156 |
|
| 157 |
except Exception as e:
|
| 158 |
-
story_text = "Die
|
| 159 |
neuer_rucksack = aktueller_rucksack
|
| 160 |
|
| 161 |
-
# Den Chat-Verlauf aktualisieren
|
| 162 |
-
verlauf.append((nachricht, story_text))
|
| 163 |
-
|
| 164 |
-
# Das Logbuch-HTML neu generieren (inklusive neuer Aktionen)
|
| 165 |
-
logbuch_html = generiere_logbuch_html(verlauf)
|
| 166 |
-
|
| 167 |
# Bild-KI (SDXL Turbo - EXTREM SCHNELL!)
|
|
|
|
| 168 |
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"
|
| 169 |
try:
|
| 170 |
# SDXL Turbo braucht extrem wenige Schritte und ist fast sofort fertig!
|
|
@@ -174,46 +131,41 @@ def spiel_zug(nachricht, verlauf, aktueller_rucksack):
|
|
| 174 |
|
| 175 |
rucksack_ui_text = f"🎒 INVENTAR: {neuer_rucksack}"
|
| 176 |
|
| 177 |
-
# Gibt alles zurück:
|
| 178 |
-
return
|
| 179 |
|
| 180 |
|
| 181 |
-
# Wir laden das eigene CSS direkt in den Baukasten
|
| 182 |
with gr.Blocks(css=geiles_design, theme=gr.themes.Base()) as spiel_oberflaeche:
|
|
|
|
| 183 |
with gr.Column(elem_classes="haupt-bereich"):
|
| 184 |
gr.Markdown("# 🧟 ZOMBIE GO")
|
| 185 |
|
| 186 |
-
#
|
| 187 |
-
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
# Die sichtbare Anzeige für das Inventar
|
| 191 |
-
rucksack_ui = gr.Markdown("🎒 INVENTAR: Brecheisen, leere Wasserflasche | GO: 0", elem_classes="rucksack-anzeige")
|
| 192 |
|
| 193 |
# Das generierte Bild
|
| 194 |
szene_bild = gr.Image(label="Visuelles Echo", type="pil", elem_classes="output-bild")
|
| 195 |
|
| 196 |
-
#
|
| 197 |
-
|
| 198 |
-
logbuch_ui = gr.HTML(generiere_logbuch_html([]), elem_classes="logbuch-stapel")
|
| 199 |
|
| 200 |
gr.Markdown("---")
|
| 201 |
|
| 202 |
# Eingabe-Bereich
|
| 203 |
-
eingabe = gr.Textbox(label="", placeholder="Was tust du? (z.B.
|
| 204 |
senden_btn = gr.Button("▶ AKTION EINTRAGEN")
|
| 205 |
|
| 206 |
# Verknüpfungen der Knöpfe (wichtige Reihenfolge der Outputs!)
|
| 207 |
-
# Wir aktualisieren jetzt das logbuch_ui und chat_verlauf
|
| 208 |
senden_btn.click(
|
| 209 |
spiel_zug,
|
| 210 |
-
inputs=[eingabe,
|
| 211 |
-
outputs=[
|
| 212 |
)
|
| 213 |
eingabe.submit(
|
| 214 |
spiel_zug,
|
| 215 |
-
inputs=[eingabe,
|
| 216 |
-
outputs=[
|
| 217 |
)
|
| 218 |
|
| 219 |
# Startet das Game
|
|
|
|
| 14 |
@import url('https://fonts.googleapis.com/css2?family=Special+Elite&display=swap');
|
| 15 |
|
| 16 |
body, .gradio-container {
|
| 17 |
+
/* Düsteres Apokalypse-Hintergrundbild aus dem Netz */
|
| 18 |
+
background-image: url('https://images.unsplash.com/photo-1485603099951-40344d18721c?q=80&w=2000&auto=format&fit=crop') !important;
|
| 19 |
background-size: cover !important;
|
| 20 |
background-position: center !important;
|
| 21 |
background-attachment: fixed !important;
|
| 22 |
font-family: sans-serif;
|
| 23 |
}
|
| 24 |
|
| 25 |
+
/* Der Hauptbereich wird schwarz und leicht durchsichtig */
|
| 26 |
.haupt-bereich {
|
| 27 |
background: rgba(0, 0, 0, 0.7) !important;
|
| 28 |
border-radius: 10px;
|
| 29 |
padding: 20px !important;
|
| 30 |
max-width: 800px !important;
|
| 31 |
margin: 0 auto !important;
|
| 32 |
+
backdrop-filter: blur(3px); /* Macht das Hintergrundbild leicht unscharf */
|
| 33 |
border: 1px solid rgba(255, 255, 255, 0.1);
|
| 34 |
}
|
| 35 |
|
|
|
|
| 47 |
font-weight: bold;
|
| 48 |
}
|
| 49 |
|
| 50 |
+
/* Der Notizzettel für die Story! */
|
| 51 |
+
.notizzettel {
|
| 52 |
+
background: #e3dec6 !important; /* Schmutzige Papier-Farbe */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 53 |
color: #1a1a1a !important;
|
| 54 |
+
font-family: 'Special Elite', monospace !important; /* Echte Schreibmaschinen-Schrift */
|
| 55 |
font-size: 1.3em !important;
|
| 56 |
line-height: 1.6 !important;
|
| 57 |
+
padding: 25px !important;
|
| 58 |
border-radius: 2px !important;
|
| 59 |
+
box-shadow: 3px 3px 15px rgba(0,0,0,0.8) !important;
|
| 60 |
+
transform: rotate(-1deg); /* Leichte Drehung für den echten Zettel-Look */
|
| 61 |
+
margin: 20px 5px !important;
|
| 62 |
+
border-left: 4px solid #8b0000 !important; /* Roter Rand */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 63 |
}
|
| 64 |
|
| 65 |
+
/* Rahmen für das generierte Bild */
|
| 66 |
+
.output-bild { border: 2px solid #555 !important; border-radius: 3px !important; box-shadow: 0 5px 15px rgba(0,0,0,0.9) !important;}
|
|
|
|
|
|
|
|
|
|
| 67 |
|
| 68 |
+
/* Eingabefeld durchsichtig machen */
|
| 69 |
input, textarea {
|
| 70 |
background: rgba(0, 0, 0, 0.6) !important;
|
| 71 |
color: #fff !important;
|
|
|
|
| 74 |
border-radius: 5px !important;
|
| 75 |
}
|
| 76 |
|
| 77 |
+
/* Aggressiver Action-Button */
|
| 78 |
button {
|
| 79 |
background: #8b0000 !important;
|
| 80 |
color: #fff !important;
|
|
|
|
| 89 |
button:hover { background: #aa0000 !important; }
|
| 90 |
"""
|
| 91 |
|
| 92 |
+
def spiel_zug(nachricht, aktueller_rucksack):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 93 |
if not nachricht:
|
| 94 |
+
return None, "Du musst schon was tun!", aktueller_rucksack, f"🎒 INVENTAR: {aktueller_rucksack}", ""
|
|
|
|
| 95 |
|
|
|
|
| 96 |
system_prompt = f"""Du bist 'Zombie Go'.
|
| 97 |
Inventar des Spielers: {aktueller_rucksack}.
|
| 98 |
Regel: Der Spieler darf NUR Dinge nutzen, die im Inventar sind. Erfinde keine Waffen für ihn.
|
| 99 |
+
Füge neu gefundene Gegenstände oder gesammeltes 'Go' logisch zum Rucksack hinzu.
|
| 100 |
Aktion des Spielers: '{nachricht}'.
|
| 101 |
|
| 102 |
Antworte EXAKT in dieser Form (ohne Ausnahmen):
|
| 103 |
+
STORY: [Beschreibe in max 3 spannenden Sätzen, was passiert]
|
| 104 |
RUCKSACK: [Liste der Items] | GO: [Anzahl]"""
|
| 105 |
|
| 106 |
try:
|
| 107 |
+
antwort = text_client.text_generation(system_prompt, max_new_tokens=200)
|
| 108 |
|
| 109 |
# Split (Text zerteilen): Wir trennen Story und Rucksack am Wort "RUCKSACK:"
|
| 110 |
if "RUCKSACK:" in antwort:
|
|
|
|
| 117 |
neuer_rucksack = aktueller_rucksack
|
| 118 |
|
| 119 |
except Exception as e:
|
| 120 |
+
story_text = "Die Verbindung stottert... die KI schnappt nach Luft."
|
| 121 |
neuer_rucksack = aktueller_rucksack
|
| 122 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 123 |
# Bild-KI (SDXL Turbo - EXTREM SCHNELL!)
|
| 124 |
+
# Wir fügen düstere englische Begriffe hinzu, damit die KI das Zombie-Go-Thema versteht
|
| 125 |
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"
|
| 126 |
try:
|
| 127 |
# SDXL Turbo braucht extrem wenige Schritte und ist fast sofort fertig!
|
|
|
|
| 131 |
|
| 132 |
rucksack_ui_text = f"🎒 INVENTAR: {neuer_rucksack}"
|
| 133 |
|
| 134 |
+
# Gibt alles zurück: Chat, Bild, leeres Textfeld, schicke Anzeige, unsichtbarer Speicher
|
| 135 |
+
return bild, story_text, neuer_rucksack, rucksack_ui_text, ""
|
| 136 |
|
| 137 |
|
|
|
|
| 138 |
with gr.Blocks(css=geiles_design, theme=gr.themes.Base()) as spiel_oberflaeche:
|
| 139 |
+
# Wir geben dem Haupt-Bereich die CSS-Klasse 'haupt-bereich'
|
| 140 |
with gr.Column(elem_classes="haupt-bereich"):
|
| 141 |
gr.Markdown("# 🧟 ZOMBIE GO")
|
| 142 |
|
| 143 |
+
# State (unsichtbarer Speicher) für deinen Start-Rucksack
|
| 144 |
+
rucksack_speicher = gr.State("Taschenlampe, leere Wasserflasche | GO: 0")
|
| 145 |
+
rucksack_ui = gr.Markdown("🎒 INVENTAR: Taschenlampe, leere Wasserflasche | GO: 0", elem_classes="rucksack-anzeige")
|
|
|
|
|
|
|
|
|
|
| 146 |
|
| 147 |
# Das generierte Bild
|
| 148 |
szene_bild = gr.Image(label="Visuelles Echo", type="pil", elem_classes="output-bild")
|
| 149 |
|
| 150 |
+
# Der Notizzettel für die Story!
|
| 151 |
+
story_ausgabe = gr.Markdown("*Warte auf Eingabe... (Tipp: 'Umschauen')*", elem_classes="notizzettel")
|
|
|
|
| 152 |
|
| 153 |
gr.Markdown("---")
|
| 154 |
|
| 155 |
# Eingabe-Bereich
|
| 156 |
+
eingabe = gr.Textbox(label="", placeholder="Was tust du? (z.B. Zombies looten)", lines=1)
|
| 157 |
senden_btn = gr.Button("▶ AKTION EINTRAGEN")
|
| 158 |
|
| 159 |
# Verknüpfungen der Knöpfe (wichtige Reihenfolge der Outputs!)
|
|
|
|
| 160 |
senden_btn.click(
|
| 161 |
spiel_zug,
|
| 162 |
+
inputs=[eingabe, rucksack_speicher],
|
| 163 |
+
outputs=[szene_bild, story_ausgabe, rucksack_speicher, rucksack_ui, eingabe]
|
| 164 |
)
|
| 165 |
eingabe.submit(
|
| 166 |
spiel_zug,
|
| 167 |
+
inputs=[eingabe, rucksack_speicher],
|
| 168 |
+
outputs=[szene_bild, story_ausgabe, rucksack_speicher, rucksack_ui, eingabe]
|
| 169 |
)
|
| 170 |
|
| 171 |
# Startet das Game
|