U18: Risk/Reward-Abkürzungen mit Timer (Biologe/Elektriker/Cyborgs), Spinnenfrage ersetzt

This commit is contained in:
David Kertzscher 2026-07-01 14:13:47 +00:00
parent ef336090db
commit 39678a1ece
2 changed files with 351 additions and 120 deletions

243
app.py
View file

@ -1,4 +1,5 @@
import os import os
import time
import sqlite3 import sqlite3
from flask import Flask, request, redirect, session from flask import Flask, request, redirect, session
from datetime import datetime, timezone, timedelta from datetime import datetime, timezone, timedelta
@ -163,6 +164,19 @@ def adventure_seite(inhalt, akzent="#f59e0b"):
.pfad:hover { border-color:ACCENT; transform:translateY(-1px); } .pfad:hover { border-color:ACCENT; transform:translateY(-1px); }
.pfad .exit-link { margin:0 0 6px 0; } .pfad .exit-link { margin:0 0 6px 0; }
.pfad-hinweis { display:block; color:#94a3b8; font-size:14px; } .pfad-hinweis { display:block; color:#94a3b8; font-size:14px; }
.deal { display:flex; flex-wrap:wrap; gap:10px; margin:14px 0 22px; }
.deal span { background:#0f172a; border:1px solid #334155; border-radius:8px;
padding:8px 12px; font-size:14px; }
.timer-wrap { margin:2px 0 18px; }
.timer { font-size:42px; font-weight:800; color:#f87171; line-height:1;
font-variant-numeric:tabular-nums; }
.timer small { font-size:16px; color:#94a3b8; font-weight:600; }
.timer-bar { height:8px; background:#0f172a; border:1px solid #334155;
border-radius:6px; overflow:hidden; margin-top:10px; }
.timer-bar > div { height:100%; background:#f87171; width:100%;
transition:width .12s linear; }
.exit-link.danger { background:#f87171; }
.exit-link.danger:hover { filter:brightness(1.08); }
.feedback-bad { background:#7f1d1d; border:1px solid #b91c1c; color:#fecaca; .feedback-bad { background:#7f1d1d; border:1px solid #b91c1c; color:#fecaca;
border-radius:10px; padding:12px 14px; margin-bottom:16px; font-weight:600; } border-radius:10px; padding:12px 14px; margin-bottom:16px; font-weight:600; }
.win-emoji { font-size:54px; text-align:center; margin-bottom:8px; } .win-emoji { font-size:54px; text-align:center; margin-bottom:8px; }
@ -186,7 +200,8 @@ def adventure_seite(inhalt, akzent="#f59e0b"):
@app.route("/") @app.route("/")
def start(): def start():
# Fortschritt für einen frischen Durchlauf zurücksetzen # Fortschritt für einen frischen Durchlauf zurücksetzen
for key in [k for k in session.keys() if k.startswith("raum_")]: for key in [k for k in list(session.keys())
if k.startswith("raum_") or k.startswith("chal_")]:
session.pop(key, None) session.pop(key, None)
inhalt = """ inhalt = """
<div class="adv-card"> <div class="adv-card">
@ -198,10 +213,12 @@ def start():
<strong>Haien</strong> 🦈, <strong>Lasern</strong> 🔴 und natürlich <strong>Haien</strong> 🦈, <strong>Lasern</strong> 🔴 und natürlich
<strong>Laserhaien</strong> 🦈.</p> <strong>Laserhaien</strong> 🦈.</p>
<p class="adv-desc">Jede Etage ist ein Gang, der sich gabelt. <strong>Lies die <p class="adv-desc">Jede Etage ist ein Gang, der sich gabelt. <strong>Lies die
Hinweise genau!</strong> Der <strong>richtige Weg</strong> stellt dir ein paar Hinweise genau!</strong> Der <strong>sichere Prüf-Weg</strong> stellt dir ein paar
thematische Fragen und führt direkt eine Etage höher. Der <strong>falsche Weg</strong> thematische Fragen und führt gemütlich eine Etage höher. Der andere Weg ist eine
endet nach einem Haufen wirrer Trivia in einer <strong>Sackgasse</strong> dann <strong>riskante Abkürzung</strong>: Dort wartet jemand mit einem Deal schaffst
heißt es: umkehren! Ganz oben wartet die letzte Frage zu Präsident Business.</p> du seine Fragen <strong>gegen die Uhr</strong>, springst du weit nach oben. Ein
Fehler oder zu langsam? <strong>Mission vorbei.</strong> Ganz oben wartet die
letzte Frage zu Präsident Business.</p>
<a href="/app/raum/1" class="exit-link">Abenteuer starten </a> <a href="/app/raum/1" class="exit-link">Abenteuer starten </a>
<p class="muted">Lieber quatschen statt einbrechen? <p class="muted">Lieber quatschen statt einbrechen?
<a href="/app/pinnwand">Zu den Kommentaren </a></p> <a href="/app/pinnwand">Zu den Kommentaren </a></p>
@ -214,6 +231,183 @@ def frage():
return redirect("/app/") return redirect("/app/")
# ─── Adventure-Helfer: Sieg / Game Over / Challenge ──────────────────────────
def _clear_challenge(rid):
"""Timer- und Fortschritts-Keys einer Challenge aus der Session entfernen."""
session.pop("chal_%d_deadline" % rid, None)
session.pop("chal_%d_idx" % rid, None)
session.modified = True
def sieg_screen(text=None):
body = text or ("Du hast Präsident Business gestoppt und das Kragle gesichert. "
"Die Welt bleibt frei und kreativ!")
inhalt = ("""
<div class="adv-card" style="text-align:center">
<div class="win-emoji">🎉🧱🎉</div>
<div class="adv-floor">Mission erfüllt</div>
<h1>Befreit!</h1>
<p class="adv-desc">%s</p>
<p class="adv-frage" style="color:#f59e0b">Everything is awesome! 🎵</p>
<a href="/app/" class="exit-link">Nochmal spielen 🔁</a>
<a href="/app/pinnwand" class="ghost-link">Sieg in den Kommentaren feiern 💬</a>
</div>""" % esc(body))
return adventure_seite(inhalt)
def gameover_screen(grund):
inhalt = ("""
<div class="adv-card" style="text-align:center">
<div class="win-emoji">💥🤖💥</div>
<div class="adv-floor" style="color:#f87171">Mission gescheitert</div>
<h1>Erwischt!</h1>
<p class="adv-desc">%s</p>
<a href="/app/" class="exit-link">Nochmal von vorn </a>
<a href="/app/pinnwand" class="ghost-link">Frust in den Kommentaren lassen 💬</a>
</div>""" % esc(grund))
return adventure_seite(inhalt, akzent="#f87171")
def challenge_raum(db, r):
"""Risk/Reward-Abkürzung mit Zeitlimit (Biologe, Elektriker, Cyborgs)."""
rid = r["id"]
limit = int(r["zeit_limit"] or 40)
ziel = int(r["ziel_anzahl"] or 10)
erfolg_raum = r["erfolg_raum"] or 0
erfolg_text = r["erfolg_text"] or ""
dl_key = "chal_%d_deadline" % rid
idx_key = "chal_%d_idx" % rid
fragen = db.execute(
"SELECT * FROM fragen WHERE raum_id=? ORDER BY id", (rid,)
).fetchall()
back = db.execute(
"SELECT nach_raum FROM ausgaenge WHERE von_raum=? ORDER BY rowid LIMIT 1",
(rid,)
).fetchone()
db.close()
back_raum = back["nach_raum"] if back else 1
gesamt = min(ziel, len(fragen)) if fragen else ziel
now = time.time()
# ── Noch nicht gestartet → Intro (die Entscheidung: Risk vs. Reward) ──
if dl_key not in session:
if request.args.get("start") == "1" and fragen:
session[dl_key] = now + limit
session[idx_key] = 0
session.modified = True
return redirect("/app/raum/%d" % rid)
reward = ("🏆 Bei Erfolg: sofort gewonnen!" if not erfolg_raum
else "🏆 Bei Erfolg: Express ganz nach oben")
inhalt = ("""
<div class="adv-card">
<div class="adv-floor"> Risiko-Abkürzung · Etage %d</div>
<h1>%s</h1>
<p class="adv-desc">%s</p>
<div class="deal">
<span>🎯 %d Fragen richtig</span>
<span> %d Sekunden</span>
<span>%s</span>
<span>💀 Ein Fehler = Aus</span>
</div>
<a href="/app/raum/%d?start=1" class="exit-link danger">Herausforderung annehmen </a>
<a href="/app/raum/%d" class="ghost-link">Lieber den sicheren Prüf-Weg</a>
</div>""" % (r["etage"] or 0, esc(r["name"]), esc(r["beschreibung"]),
gesamt, limit, reward, rid, back_raum))
return adventure_seite(inhalt, akzent="#f87171")
# ── Challenge läuft ──
deadline = session.get(dl_key, 0)
idx = session.get(idx_key, 0)
# Zeit abgelaufen? (Server ist die Wahrheit; JS meldet Timeout per ?timeout=1)
if now > deadline or request.args.get("timeout") == "1":
_clear_challenge(rid)
return gameover_screen(
"⏱️ Zeit abgelaufen! Die Wachen kommen näher du musst fliehen. "
"Der riskante Weg hat dich diesmal erwischt.")
# Antwort verarbeiten
if request.method == "POST":
gewaehlt = request.form.get("antwort", "").strip()
if idx < len(fragen) and gewaehlt.lower() == fragen[idx]["antwort"].strip().lower():
idx += 1
session[idx_key] = idx
session.modified = True
if idx >= gesamt:
_clear_challenge(rid)
if erfolg_raum and erfolg_raum > 0:
inhalt = ("""
<div class="adv-card">
<div class="adv-floor"> Abkürzung geschafft!</div>
<h1>Geschafft in letzter Sekunde!</h1>
<p class="adv-desc">%s</p>
<a href="/app/raum/%d" class="exit-link">Weiter </a>
</div>""" % (esc(erfolg_text), erfolg_raum))
return adventure_seite(inhalt)
return sieg_screen(erfolg_text)
return redirect("/app/raum/%d" % rid)
# falsche Antwort → sofortiges Game Over
_clear_challenge(rid)
return gameover_screen(
"❌ Falsch! Dein Gegenüber durchschaut dich sofort und schlägt Alarm. "
"So knapp aber der riskante Weg verzeiht keinen einzigen Fehler.")
# GET → aktuelle Frage mit Countdown zeigen
if idx >= len(fragen):
_clear_challenge(rid)
return sieg_screen(erfolg_text)
aktuelle = fragen[idx]
remaining = deadline - now
buttons = ""
for opt in aktuelle["optionen"].split("|"):
buttons += ('<button class="opt-btn" name="antwort" value="%s">%s</button>'
% (esc(opt), esc(opt)))
tpl = """
<div class="adv-card">
<div class="adv-floor"> Risiko-Challenge · __NAME__</div>
<h1>__NAME__</h1>
<div class="timer-wrap">
<div class="timer"><span id="tval">__REMAIN__</span><small> s</small></div>
<div class="timer-bar"><div id="tbar"></div></div>
</div>
<p class="adv-progress">Frage __NR__ von __GES__ · schon richtig: __IDX__</p>
<p class="adv-frage">__FRAGE__</p>
<form method="post" class="opt-form">__BTN__</form>
</div>
<script>
(function(){
var end = Date.now() + __REMAINMS__;
var full = __LIMIT__;
var v = document.getElementById('tval');
var bar = document.getElementById('tbar');
function tick(){
var rem = (end - Date.now())/1000;
if(rem < 0){ rem = 0; }
v.textContent = rem.toFixed(1);
bar.style.width = Math.max(0, Math.min(100, (rem/full)*100)) + '%';
if(rem <= 0){ window.location = '/app/raum/__ID__?timeout=1'; return; }
requestAnimationFrame(tick);
}
tick();
})();
</script>"""
html = (tpl
.replace("__NAME__", esc(r["name"]))
.replace("__REMAINMS__", str(int(max(0.0, remaining) * 1000)))
.replace("__REMAIN__", "%.1f" % max(0.0, remaining))
.replace("__LIMIT__", str(limit))
.replace("__NR__", str(idx + 1))
.replace("__GES__", str(gesamt))
.replace("__IDX__", str(idx))
.replace("__FRAGE__", esc(aktuelle["frage"]))
.replace("__BTN__", buttons)
.replace("__ID__", str(rid)))
return adventure_seite(html, akzent="#f87171")
@app.route("/raum/<int:id>", methods=["GET", "POST"]) @app.route("/raum/<int:id>", methods=["GET", "POST"])
def raum(id): def raum(id):
db = get_db() db = get_db()
@ -228,8 +422,12 @@ def raum(id):
typ = r["typ"] typ = r["typ"]
# ═══ Räume mit Fragen: thema (richtig) · sackgasse (falsch) · ziel (Finale) ═══ # ═══ Risk/Reward-Abkürzung mit Timer (Biologe / Elektriker / Cyborgs) ═══
if typ in ("thema", "sackgasse", "ziel"): if typ == "challenge":
return challenge_raum(db, r)
# ═══ Räume mit Fragen: thema (Prüf-Weg) · ziel (Finale) ═══
if typ in ("thema", "ziel"):
fragen = db.execute( fragen = db.execute(
"SELECT * FROM fragen WHERE raum_id=? ORDER BY id", (id,) "SELECT * FROM fragen WHERE raum_id=? ORDER BY id", (id,)
).fetchall() ).fetchall()
@ -247,12 +445,8 @@ def raum(id):
session.modified = True session.modified = True
db.close() db.close()
return redirect("/app/raum/%d" % id) return redirect("/app/raum/%d" % id)
if typ == "sackgasse": feedback = ('<div class="feedback-bad">🚨 Alarm! Falsche Antwort '
feedback = ('<div class="feedback-bad">❌ Falsch und der ' 'die Wächter werden fast auf dich aufmerksam. Nochmal!</div>')
'Prüf-Automat fragt einfach stur weiter. Nochmal!</div>')
else:
feedback = ('<div class="feedback-bad">🚨 Alarm! Falsche Antwort '
'die Wächter werden fast auf dich aufmerksam. Nochmal!</div>')
optionen = aktuelle["optionen"].split("|") optionen = aktuelle["optionen"].split("|")
db.close() db.close()
@ -261,9 +455,7 @@ def raum(id):
buttons += ('<button class="opt-btn" name="antwort" value="%s">%s</button>' buttons += ('<button class="opt-btn" name="antwort" value="%s">%s</button>'
% (esc(opt), esc(opt))) % (esc(opt), esc(opt)))
if typ == "sackgasse": if typ == "ziel":
label = "🚧 Falscher Weg · %s" % esc(r["name"])
elif typ == "ziel":
label = "🧱 FINALE · %s" % esc(r["name"]) label = "🧱 FINALE · %s" % esc(r["name"])
else: else:
label = "🔐 Sicherheitsprüfung · %s" % esc(r["name"]) label = "🔐 Sicherheitsprüfung · %s" % esc(r["name"])
@ -303,25 +495,6 @@ def raum(id):
</div>""" % esc(r["beschreibung"])) </div>""" % esc(r["beschreibung"]))
return adventure_seite(inhalt) return adventure_seite(inhalt)
# SACKGASSE → "Haha, Sackgasse!" + zurück zum Gang
if typ == "sackgasse":
zurueck = ausgaenge[0] if ausgaenge else None
back_btn = (
'<a class="exit-link" href="/app/raum/%d">%s</a>'
% (zurueck["nach_raum"], esc(zurueck["richtung"]))
if zurueck else
'<a class="exit-link" href="/app/">Zurück zum Start</a>')
inhalt = ("""
<div class="adv-card">
<div class="adv-floor">🚧 Sackgasse</div>
<h1>Haha Sackgasse!</h1>
<p class="adv-desc">Du hast dich durch einen ganzen Haufen Trivia gequält
und stehst jetzt vor einer kahlen Wand. <strong>Das war der falsche Weg!</strong>
Geh zurück in den Gang und nimm die andere Richtung.</p>
%s
</div>""" % back_btn)
return adventure_seite(inhalt)
# THEMA gelöst → Erfolg + Ausgang zur nächsten Etage # THEMA gelöst → Erfolg + Ausgang zur nächsten Etage
weiter = ausgaenge[0] if ausgaenge else None weiter = ausgaenge[0] if ausgaenge else None
weiter_btn = ( weiter_btn = (

View file

@ -47,8 +47,12 @@ CREATE TABLE raeume (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
name TEXT, name TEXT,
beschreibung TEXT, beschreibung TEXT,
typ TEXT, -- 'start' | 'gang' | 'thema' | 'sackgasse' | 'ziel' typ TEXT, -- 'start' | 'gang' | 'thema' | 'challenge' | 'ziel'
etage INTEGER -- 0 = Lobby, 1..3 = Etagen, 4 = Dach etage INTEGER, -- 0 = Lobby, 1..3 = Etagen, 4 = Dach
zeit_limit INTEGER, -- Challenge: Sekunden Zeitlimit (sonst NULL)
ziel_anzahl INTEGER, -- Challenge: so viele Fragen richtig nötig (sonst NULL)
erfolg_raum INTEGER, -- Challenge: Raum bei Erfolg (0/NULL = sofort gewonnen)
erfolg_text TEXT -- Challenge: Story-Text bei Erfolg
); );
CREATE TABLE ausgaenge ( CREATE TABLE ausgaenge (
@ -76,104 +80,131 @@ raeume = [
"Wolkenkratzer von Präsident Business auf. Ganz oben, im Kragle-Tresor, " "Wolkenkratzer von Präsident Business auf. Ganz oben, im Kragle-Tresor, "
"wartet der gefährlichste Kleber der Welt. Ein einzelner Aufzug führt nach " "wartet der gefährlichste Kleber der Welt. Ein einzelner Aufzug führt nach "
"oben. Zeit, ihn zu stoppen.", "oben. Zeit, ihn zu stoppen.",
"start", 0), "start", 0, None, None, None, None),
# ---- Etage 1: Haie (richtiger Weg = LINKS → 11, Sackgasse = RECHTS → 12) ---- # ---- Etage 1: Haie (Prüf-Weg = LINKS → 11, Abkürzung = RECHTS → 12) ----
(10, "1. Etage Der Hai-Gang 🦈", (10, "1. Etage Der Hai-Gang 🦈",
"Der Aufzug öffnet sich. Der Gang gabelt sich in zwei Richtungen. Von " "Der Aufzug öffnet sich in einen Gang mit zwei Wegen. Nach LINKS weht "
"LINKS weht feuchte, salzige Luft herüber dort muss das riesige " "salzige Luft vom Haibecken herüber der offizielle Prüf-Weg über den "
"Haibecken sein, das du überqueren musst. Von RECHTS blinkt in kaltem Rot " "Steg. Nach RECHTS steht eine Tür einen Spalt offen; drinnen rumort "
"ein Schild: „Nur Personal Abstellkammer“.", "jemand. Vielleicht eine schnelle Abkürzung aber riskant?",
"gang", 1), "gang", 1, None, None, None, None),
(11, "Steg über dem Haibecken 🦈", (11, "Steg über dem Haibecken 🦈",
"Du folgst der salzigen Luft. Unter dem schmalen Steg schnappen hungrige " "Du folgst der salzigen Luft. Unter dem schmalen Steg schnappen hungrige "
"Haie. Das Sicherheitssystem summt: Beweise dein Hai-Wissen, sonst fährt " "Haie. Das Sicherheitssystem summt: Beweise dein Hai-Wissen, sonst fährt "
"der Steg ein!", "der Steg ein!",
"thema", 1), "thema", 1, None, None, None, None),
(12, "Die Abstellkammer 🧹", (12, "Nebenraum Der Biologe 🔬",
"Du drückst die Tür auf Besen, Eimer, ein flackernder Wartungs-Bot. " "Statt zum Haibecken schlüpfst du durch die Tür und stehst vor einem "
"„HALT! Sicherheits-Quiz!“, quäkt er und stellt dir eine Frage nach der " "nervösen Meeresbiologen mit dickem Wälzer unterm Arm. „Du willst hoch zum "
"anderen …", "Kragle? Beweis mir, dass du Ahnung hast: 10 Biologie-Fragen, 40 Sekunden, "
"sackgasse", 1), "kein einziger Fehler. Schaffst du's, schmuggle ich dich im Proben-Container "
"ganz nach oben. Verhaust du dich, ruf ich die Wachen!“",
"challenge", 1, 40, 10, 40,
"Der Biologe grinst: „Nicht schlecht für einen Einbrecher!“ Er versteckt "
"dich im Proben-Container und der Lastenaufzug schießt ganz nach oben "
"direkt vor den Kragle-Tresor!"),
# ---- Etage 2: Laser (richtiger Weg = RECHTS → 21, Sackgasse = LINKS → 22) ---- # ---- Etage 2: Laser (Prüf-Weg = RECHTS → 21, Abkürzung = LINKS → 22) ----
(20, "2. Etage Der Laser-Gang 🔴", (20, "2. Etage Der Laser-Gang 🔴",
"Rote Strahlen zerschneiden die Luft zu einem glühenden Gitter. LINKS " "Rote Strahlen zerschneiden die Luft zu einem glühenden Gitter. Nach "
"gähnt ein dunkler Wartungsschacht, aus dem es muffig nach Staub riecht. " "RECHTS liegt der „Laser-Kontrollraum“ der offizielle Prüf-Weg. Nach "
"RECHTS pulsiert Licht hinter einer Tür mit der Aufschrift " "LINKS, in einem engen Wartungsgang, kauert ein Elektriker zwischen "
"„Laser-Kontrollraum“.", "Kabeln und winkt dich heran. Eine Abkürzung mit Risiko?",
"gang", 2), "gang", 2, None, None, None, None),
(21, "Der Laser-Kontrollraum 🔴", (21, "Der Laser-Kontrollraum 🔴",
"Im Kontrollraum flimmern hundert Regler. Wer die Laser abschalten will, " "Im Kontrollraum flimmern hundert Regler. Wer die Laser abschalten will, "
"muss beweisen, dass er versteht, wie sie funktionieren.", "muss beweisen, dass er versteht, wie sie funktionieren.",
"thema", 2), "thema", 2, None, None, None, None),
(22, "Der Wartungsschacht 🕳️", (22, "Wartungsgang Der Elektriker ⚡",
"Eng, dunkel, staubig und natürlich eine Sackgasse. Bevor du das merkst, " "Im engen Wartungsgang hockt ein Elektriker in einem Nest aus Kabeln. „Die "
"erwacht ein alter Prüf-Automat und feuert Trivia auf dich ab …", "Laser willst du los? Zeig mir, dass du was von Strom verstehst: 10 Fragen, "
"sackgasse", 2), "40 Sekunden, fehlerfrei. Dann leg ich die ganze Etage lahm und der Express "
"bringt dich zur letzten Tür. Patzt du, jagt dich der Alarm hoch!“",
"challenge", 2, 40, 10, 40,
"Der Elektriker legt einen Hebel um mit einem Zischen erlöschen alle "
"Laser. „Express für den Profi!“ Der Aufzug rast nach oben, direkt vor die "
"letzte Tür."),
# ---- Etage 3: Laserhaie (richtiger Weg = LINKS → 31, Sackgasse = RECHTS → 32) ---- # ---- Etage 3: Laserhaie (Prüf-Weg = LINKS → 31, Abkürzung = RECHTS → 32) ----
(30, "3. Etage Der Laserhai-Gang 🦈⚡", (30, "3. Etage Der Laserhai-Gang 🦈⚡",
"Absurd, aber real: Haie. Mit Lasern. Auf dem Kopf. LINKS führt ein " "Absurd, aber real: Haie. Mit Lasern. Auf dem Kopf. Nach LINKS führt ein "
"schmaler Steg direkt über das Laserhai-Becken da musst du durch. RECHTS " "schmaler Steg über das Laserhai-Becken der offizielle Prüf-Weg. Nach "
"lockt ein gemütlicher Pausenraum, aus dem Kaffeeduft strömt.", "RECHTS versperren die Cyborg-Wächter von Präsident Business den Gang und "
"gang", 3), "fordern dich heraus: Wer sie schlägt, gewinnt sofort wer patzt, ist raus.",
"gang", 3, None, None, None, None),
(31, "Steg über dem Laserhai-Becken 🦈⚡", (31, "Steg über dem Laserhai-Becken 🦈⚡",
"Unter dir kreisen die Laserhaie und zwinkern gefährlich. Das letzte " "Unter dir kreisen die Laserhaie und zwinkern gefährlich. Das letzte "
"Sicherheitssystem vor dem Dach will dich prüfen bleib cool!", "Sicherheitssystem vor dem Dach will dich prüfen bleib cool!",
"thema", 3), "thema", 3, None, None, None, None),
(32, "Der Pausenraum ☕", (32, "Sperrzone Die Cyborgs 🤖",
"Warm, gemütlich, verlockend … und eine glasklare Falle. Der Kaffeeautomat " "Drei Cyborg-Wächter riegeln den Weg ab. „DENKE. WIE. EINE. MASCHINE“, "
"entpuppt sich als Quiz-Maschine und lässt dich nicht mehr los …", "rattern sie im Chor. „Fünf Fragen. Zwanzig Sekunden. Antworte nicht wie "
"sackgasse", 3), "ein weicher Mensch, sondern wie ein Computer. Bestehst du, erkennen wir "
"dich als eine der Unseren und du hast gewonnen. Sonst: Löschung.“",
"challenge", 3, 20, 5, 0,
"Die Cyborgs synchronisieren kurz dann nicken sie im Takt: „EINE VON "
"UNS.“ Sie treten beiseite, der Weg zum Kragle ist frei. Du hast Präsident "
"Business gestoppt!"),
# ---- Dach: Ziel ---- # ---- Dach: Ziel ----
(40, "Das Dach Der Kragle-Tresor 🏆", (40, "Das Dach Der Kragle-Tresor 🏆",
"Ganz oben. Vor dir schwebt das Kragle im offenen Tresor. Nur noch eine " "Ganz oben. Vor dir schwebt das Kragle im offenen Tresor. Nur noch eine "
"letzte Sicherung von Präsident Business steht zwischen dir und der Rettung " "letzte Sicherung von Präsident Business steht zwischen dir und der Rettung "
"der Welt.", "der Welt.",
"ziel", 4), "ziel", 4, None, None, None, None),
] ]
db.executemany( db.executemany(
"INSERT INTO raeume (id, name, beschreibung, typ, etage) VALUES (?,?,?,?,?)", "INSERT INTO raeume "
"(id, name, beschreibung, typ, etage, zeit_limit, ziel_anzahl, erfolg_raum, erfolg_text) "
"VALUES (?,?,?,?,?,?,?,?,?)",
raeume, raeume,
) )
# ─── Ausgänge (mit Story-Hinweis) ──────────────────────────────────────────── # ─── Ausgänge (mit Story-Hinweis) ────────────────────────────────────────────
# Gänge haben ZWEI Wege (richtig/falsch). Themen-Räume führen eine Etage höher, # Gänge haben ZWEI Wege: den sicheren Prüf-Weg (Themen-Raum, eine Etage höher)
# Sackgassen zurück zum jeweiligen Gang. # und die riskante Abkürzung (Challenge-Raum). Challenge-Räume führen per
# "Zurück" wieder in den Gang, falls man sich doch nicht traut.
ausgaenge = [ ausgaenge = [
# Lobby → Etage 1 # Lobby → Etage 1
(1, "🛗 Aufzug nach oben", 10, "Der einzige Weg führt nach oben."), (1, "🛗 Aufzug nach oben", 10, "Der einzige Weg führt nach oben."),
# Etage 1 (richtig = LINKS → 11, falsch = RECHTS → 12) # Etage 1 (Prüf-Weg = LINKS → 11, Abkürzung = RECHTS → 12)
(10, "⬅️ Nach links", 11, "🌊 Der salzigen Meeresluft zum Haibecken folgen."), (10, "⬅️ Nach links: Steg zum Haibecken", 11,
(10, "➡️ Nach rechts", 12, "🚪 Durch die Tür „Abstellkammer“."), "🦈 Der sichere Prüf-Weg: ein paar Hai-Fragen, dann weiter."),
(10, "➡️ Nach rechts: die offene Tür", 12,
"🔬 Ein Nebenraum riskante Abkürzung mit einem Biologen."),
(11, "🪜 Treppe zur 2. Etage", 20, "Der Steg hält schnell weiter nach oben!"), (11, "🪜 Treppe zur 2. Etage", 20, "Der Steg hält schnell weiter nach oben!"),
(12, "↩️ Zurück in den Hai-Gang", 10, "Diese Kammer ist eine Sackgasse."), (12, "↩️ Zurück in den Hai-Gang", 10, "Doch lieber den sicheren Prüf-Weg nehmen."),
# Etage 2 (richtig = RECHTS → 21, falsch = LINKS → 22) # Etage 2 (Prüf-Weg = RECHTS → 21, Abkürzung = LINKS → 22)
(20, "⬅️ Nach links", 22, "🕳️ In den dunklen Wartungsschacht."), (20, "⬅️ Nach links: der Wartungsgang", 22,
(20, "➡️ Nach rechts", 21, "🔴 Zum „Laser-Kontrollraum“."), "⚡ Ein Elektriker bietet dir eine riskante Abkürzung an."),
(20, "➡️ Nach rechts: Laser-Kontrollraum", 21,
"🔴 Der sichere Prüf-Weg: ein paar Laser-Fragen, dann weiter."),
(21, "🪜 Treppe zur 3. Etage", 30, "Die Laser erlöschen der Weg ist frei!"), (21, "🪜 Treppe zur 3. Etage", 30, "Die Laser erlöschen der Weg ist frei!"),
(22, "↩️ Zurück in den Laser-Gang", 20, "Der Schacht endet im Nichts."), (22, "↩️ Zurück in den Laser-Gang", 20, "Doch lieber den sicheren Prüf-Weg nehmen."),
# Etage 3 (richtig = LINKS → 31, falsch = RECHTS → 32) # Etage 3 (Prüf-Weg = LINKS → 31, Abkürzung = RECHTS → 32)
(30, "⬅️ Nach links", 31, "🌉 Über den Steg am Laserhai-Becken."), (30, "⬅️ Nach links: Steg zum Laserhai-Becken", 31,
(30, "➡️ Nach rechts", 32, "☕ In den gemütlichen Pausenraum."), "🦈⚡ Der sichere Prüf-Weg: ein paar Laserhai-Fragen, dann aufs Dach."),
(30, "➡️ Nach rechts: die Sperrzone", 32,
"🤖 Die Cyborgs fordern dich gewinnst du, ist sofort Schluss (im Guten)."),
(31, "🏢 Aufs Dach zum Kragle-Tresor", 40, "Die Laserhaie tauchen ab nach oben!"), (31, "🏢 Aufs Dach zum Kragle-Tresor", 40, "Die Laserhaie tauchen ab nach oben!"),
(32, "↩️ Zurück in den Laserhai-Gang", 30, "Der Pausenraum war eine Falle."), (32, "↩️ Zurück in den Laserhai-Gang", 30, "Doch lieber den sicheren Prüf-Weg nehmen."),
] ]
db.executemany( db.executemany(
"INSERT INTO ausgaenge (von_raum, richtung, nach_raum, hinweis) VALUES (?,?,?,?)", "INSERT INTO ausgaenge (von_raum, richtung, nach_raum, hinweis) VALUES (?,?,?,?)",
ausgaenge, ausgaenge,
) )
# ─── Trivia-Fragen pro Etage ───────────────────────────────────────────────── # ─── Fragen ──────────────────────────────────────────────────────────────────
# Pro Etage 4 Fragen: 12 thematisch passend, danach Popkultur. # Themen-Räume (11/21/31): wenige PASSENDE Fragen der sichere Prüf-Weg.
# "antwort" ist die korrekte Option, "optionen" alle Auswahlmöglichkeiten (|-getrennt). # Challenge-Räume (12/22/32): eigene Fragenbank für die Risk/Reward-Abkürzung
# Biologe (10), Elektriker (10), Cyborgs (5, „denk wie eine Maschine“).
# Ziel-Raum (40): die finale Lord-Business-Frage.
fragen = [ fragen = [
# ── Etage 1 · RICHTIG: Hai-Fragen (Raum 11) ────────────────── # ── Etage 1 · Prüf-Weg: Hai-Fragen (Raum 11) ─────────────────
(11, "🦈 Welcher Hai ist der größte Fisch der Welt?", (11, "🦈 Welcher Hai ist der größte Fisch der Welt?",
"Walhai", "Weißer Hai|Walhai|Hammerhai"), "Walhai", "Weißer Hai|Walhai|Hammerhai"),
(11, "🦈 Wie heißt Steven Spielbergs berühmter Hai-Film von 1975?", (11, "🦈 Wie heißt Steven Spielbergs berühmter Hai-Film von 1975?",
@ -181,17 +212,29 @@ fragen = [
(11, "🦈 Womit atmen Haie unter Wasser?", (11, "🦈 Womit atmen Haie unter Wasser?",
"Kiemen", "Lungen|Kiemen|Schwimmflossen"), "Kiemen", "Lungen|Kiemen|Schwimmflossen"),
# ── Etage 1 · FALSCH: themenfremde Trivia (Raum 12) ────────── # ── Etage 1 · Abkürzung: BIOLOGE 10 Biologie-Fragen (Raum 12) ──
(12, "🎮 Wie heißt Marios grün gekleideter Bruder?", (12, "🫀 Welches Organ pumpt das Blut durch den Körper?",
"Luigi", "Luigi|Wario|Yoshi"), "Herz", "Herz|Leber|Lunge"),
(12, "🎬 In welcher Weltraum-Saga kämpfen Jedi gegen Sith?", (12, "🌿 Welcher Farbstoff macht Pflanzen grün?",
"Star Wars", "Star Trek|Star Wars|Herr der Ringe"), "Chlorophyll", "Chlorophyll|Hämoglobin|Melanin"),
(12, "📱 Welches Unternehmen stellt das iPhone her?", (12, "🐝 Wie viele Beine hat ein Insekt?",
"Apple", "Microsoft|Apple|Samsung"), "6", "4|6|8"),
(12, "⏰ Wie viele Minuten hat eine Stunde?", (12, "🫁 Welches Gas atmen Menschen zum Leben ein?",
"60", "24|60|100"), "Sauerstoff", "Sauerstoff|Kohlendioxid|Helium"),
(12, "🔬 Wie heißt die kleinste lebende Einheit?",
"Zelle", "Zelle|Atom|Molekül"),
(12, "🐬 Welches dieser Tiere ist ein Säugetier?",
"Delfin", "Delfin|Hai|Krokodil"),
(12, "🍃 Wo findet die Fotosynthese hauptsächlich statt?",
"Blatt", "Blatt|Wurzel|Blüte"),
(12, "❤️ Wie viele Kammern hat das menschliche Herz?",
"4", "2|3|4"),
(12, "☀️ Welches Vitamin bildet der Körper mithilfe von Sonnenlicht?",
"Vitamin D", "Vitamin C|Vitamin D|Vitamin B12"),
(12, "🩸 Wie heißt der rote Blutfarbstoff?",
"Hämoglobin", "Hämoglobin|Chlorophyll|Keratin"),
# ── Etage 2 · RICHTIG: Laser-Fragen (Raum 21) ──────────────── # ── Etage 2 · Prüf-Weg: Laser-Fragen (Raum 21) ───────────────
(21, "🔴 Wofür steht das Akronym LASER?", (21, "🔴 Wofür steht das Akronym LASER?",
"Light Amplification by Stimulated Emission of Radiation", "Light Amplification by Stimulated Emission of Radiation",
"Light Amplification by Stimulated Emission of Radiation|" "Light Amplification by Stimulated Emission of Radiation|"
@ -202,17 +245,29 @@ fragen = [
(21, "🌈 Welche Farbe hat ein klassischer Laserpointer meistens?", (21, "🌈 Welche Farbe hat ein klassischer Laserpointer meistens?",
"Rot", "Rot|Lila|Schwarz"), "Rot", "Rot|Lila|Schwarz"),
# ── Etage 2 · FALSCH: themenfremde Trivia (Raum 22) ────────── # ── Etage 2 · Abkürzung: ELEKTRIKER 10 Elektrik-Fragen (Raum 22) ──
(22, "🦸 Welcher Superheld trägt ein blaues Kostüm mit rotem Umhang und „S“?", (22, "⚡ In welcher Einheit misst man die elektrische Spannung?",
"Superman", "Batman|Superman|Spider-Man"), "Volt", "Volt|Watt|Ampere"),
(22, "🎮 In welchem Spiel fängt man Kreaturen in kleinen Bällen?", (22, "🔌 In welcher Einheit misst man die Stromstärke?",
"Pokémon", "Minecraft|Tetris|Pokémon"), "Ampere", "Ampere|Ohm|Volt"),
(22, "🗼 Wie heißt die Hauptstadt von Frankreich?", (22, "🧲 Was misst man in der Einheit Ohm?",
"Paris", "Paris|Rom|Madrid"), "Widerstand", "Leistung|Widerstand|Spannung"),
(22, "🐶 Welches Tier bellt?", (22, "🪙 Welches Material leitet Strom besonders gut?",
"Hund", "Katze|Hund|Kuh"), "Kupfer", "Kupfer|Gummi|Holz"),
(22, "🔁 Ein Stromkreis, durch den Strom fließt, ist …?",
"geschlossen", "geschlossen|offen|leer"),
(22, "📐 Wie lautet das Ohmsche Gesetz?",
"U = R · I", "U = R · I|U = R + I|U = R I"),
(22, "🟢 Welche Farbe hat der Schutzleiter (Erde) meist?",
"Grün-Gelb", "Grün-Gelb|Blau|Braun"),
(22, "🚿 Womit sollte man NIEMALS an eine Steckdose fassen?",
"Mit nassen Händen", "Mit nassen Händen|Mit einer Zange|Mit einem Messgerät"),
(22, "🏭 Was erzeugt ein Kraftwerk vor allem?",
"Elektrische Energie", "Elektrische Energie|Trinkwasser|Benzin"),
(22, "🔋 Welches Bauteil speichert elektrische Ladung?",
"Kondensator", "Kondensator|Widerstand|Transistor"),
# ── Etage 3 · RICHTIG: Laserhai-Fragen (Raum 31) ───────────── # ── Etage 3 · Prüf-Weg: Laserhai-Fragen (Raum 31) ────────────
(31, "🦈⚡ In welchem Film wünscht sich Dr. Evil „Haie mit Laserstrahlen auf dem Kopf“?", (31, "🦈⚡ In welchem Film wünscht sich Dr. Evil „Haie mit Laserstrahlen auf dem Kopf“?",
"Austin Powers", "James Bond|Austin Powers|Men in Black"), "Austin Powers", "James Bond|Austin Powers|Men in Black"),
(31, "🧬 Woraus setzt sich ein „Laserhai“ zusammen?", (31, "🧬 Woraus setzt sich ein „Laserhai“ zusammen?",
@ -220,15 +275,18 @@ fragen = [
(31, "😉 Wenn ein Laserhai gefährlich zwinkert was schießt aus seinen Augen?", (31, "😉 Wenn ein Laserhai gefährlich zwinkert was schießt aus seinen Augen?",
"Laserstrahlen", "Wasser|Laserstrahlen|Konfetti"), "Laserstrahlen", "Wasser|Laserstrahlen|Konfetti"),
# ── Etage 3 · FALSCH: themenfremde Trivia (Raum 32) ────────── # ── Etage 3 · Abkürzung: CYBORGS 5 Maschinen-Logik-Fragen (Raum 32) ──
(32, "🦖 In welchem Film-Franchise werden Dinosaurier in einem Park geklont?", # „Antworte wie eine Maschine nicht unbedingt logisch für Menschen.“
"Jurassic Park", "Jurassic Park|King Kong|Godzilla"), (32, "🤖 1 + 1 = ? (denke binär, wie ein Computer)",
(32, "🕷️ Wie viele Beine hat eine Spinne?", "10", "2|10|11"),
"8", "6|8|10"), (32, "🤖 WAHR UND FALSCH ergibt … (Boolesche Logik)?",
(32, "🎨 Welche Farbe entsteht aus Blau und Gelb?", "Falsch", "Wahr|Falsch|Vielleicht"),
"Grün", "Grün|Lila|Orange"), (32, "🤖 Bei welcher Zahl beginnt ein Computer zu zählen?",
(32, "🎮 Aus welchem Land kommt der Spielehersteller Nintendo?", "0", "0|1|-1"),
"Japan", "USA|Japan|Deutschland"), (32, "🤖 Wie viele Bits hat ein Byte?",
"8", "4|8|16"),
(32, "🤖 0,1 + 0,2 ergibt für einen Computer ungefähr …?",
"0,30000000000000004", "0,3|0,30000000000000004|0,03"),
# ── Dach · ZIEL: finale Lord-Business-Frage (Raum 40) ──────── # ── Dach · ZIEL: finale Lord-Business-Frage (Raum 40) ────────
(40, "🧱 FINALE: Wie heißt der Bösewicht, in dessen Turm du gerade eingebrochen bist?", (40, "🧱 FINALE: Wie heißt der Bösewicht, in dessen Turm du gerade eingebrochen bist?",