This commit is contained in:
Team3
2026-09-15 23:17:07 +02:00
parent c62c6e551f
commit f1b0f15e30
16 changed files with 1116 additions and 44 deletions

View File

@@ -41,6 +41,7 @@ func _ready() -> void:
await test_tagesablauf_anzeige()
await test_ablauf_im_hud()
await test_probleme_und_momente()
await test_eigene_menschen()
await test_systeme()
await test_tempo_des_traums()
await test_cooldown()
@@ -1040,6 +1041,242 @@ func test_probleme_und_momente() -> void:
Game.problem_stand.clear()
## Eigene Menschen: aus Wörtern wird eine Psyche, aus dem Beruf ein Alltag,
## und beides lässt sich am Brett schreiben, speichern und wieder abnehmen.
func test_eigene_menschen() -> void:
abschnitt("Eigene Menschen aus Wörtern")
Aushaenge.PFAD = "user://aushaenge_test.cfg"
Aushaenge.alle_loeschen()
# --- Der Content ist gekoppelt: nichts ist unlösbar
var ohne_technik: Array = []
for b in Ursachen.BLOCKER:
if TechDB.fuer_ursache(Ursachen.ursache_von(str(b))).is_empty():
ohne_technik.append(str(b))
p(ohne_technik.is_empty(), "Jeder der %d Blocker hat Techniken gegen seine Ursache%s" %
[Ursachen.BLOCKER.size(), "" if ohne_technik.is_empty() else " — außer " + ", ".join(ohne_technik)])
var ohne: Array = []
for pr in Probleme.LISTE:
if Probleme.techniken_gegen(str(pr)).is_empty() or Probleme.situationen_von(str(pr)).is_empty():
ohne.append(str(pr))
p(ohne.is_empty(), "Jede der %d Klemmen hat Techniken und Situationen%s" %
[Probleme.LISTE.size(), "" if ohne.is_empty() else " — außer " + ", ".join(ohne)])
var tage: Dictionary = {}
for tid in TechDB.ids():
var t := TechDB.by_id(tid)
if str(t["was"]) == "" or str(t["wann"]) == "" or str(t["warum"]) == "" or str(t["woran"]) == "":
tage[tid] = true
p(tage.is_empty(), "Alle %d Techniken tragen Was, Wann, Warum, Woran" % TechDB.LIST.size())
# --- Die Wörter erreichen jeden Eintrag des Modells
var erreicht := {"ursachen": {}, "blocker": {}, "probleme": {}, "verhalten": {}}
var leer: Array = []
for w in Woerter.ids():
var e: Dictionary = Woerter.LISTE[w]
var wirkt := false
for u in e.get("ursachen", {}):
erreicht["ursachen"][u] = true
wirkt = true
for b in e.get("blocker", []):
erreicht["blocker"][b] = true
wirkt = true
for pr in e.get("probleme", {}):
erreicht["probleme"][pr] = true
wirkt = true
for v in e.get("verhalten", {}):
erreicht["verhalten"][v] = true
wirkt = true
if not wirkt:
leer.append(w)
p(Woerter.ids().size() >= 50, "%d Wörter stehen zur Wahl" % Woerter.ids().size())
p(leer.is_empty(), "Jedes Wort wirkt irgendwo%s" %
("" if leer.is_empty() else " — außer " + ", ".join(leer)))
p(erreicht["ursachen"].size() == Ursachen.LISTE.size(),
"Die Wörter erreichen alle %d Ursachen" % Ursachen.LISTE.size())
p(erreicht["blocker"].size() == Ursachen.BLOCKER.size(),
"Alle %d Blocker (%d)" % [Ursachen.BLOCKER.size(), erreicht["blocker"].size()])
p(erreicht["probleme"].size() == Probleme.LISTE.size(),
"Alle %d Klemmen" % Probleme.LISTE.size())
p(erreicht["verhalten"].size() == Woerter.VERHALTEN.size(),
"Und alle %d Verhaltenswerte" % Woerter.VERHALTEN.size())
var unbekannt: Array = []
for w in Woerter.ids():
var e: Dictionary = Woerter.LISTE[w]
for b in e.get("blocker", []):
if not Ursachen.BLOCKER.has(b):
unbekannt.append("%s->%s" % [w, b])
for pr in e.get("probleme", {}):
if not Probleme.LISTE.has(pr):
unbekannt.append("%s->%s" % [w, pr])
for u in e.get("ursachen", {}):
if not Ursachen.LISTE.has(u):
unbekannt.append("%s->%s" % [w, u])
p(unbekannt.is_empty(), "Kein Wort zeigt ins Leere%s" %
("" if unbekannt.is_empty() else ": " + ", ".join(unbekannt)))
# --- Aus Wörtern wird ein Bild
var bild := Woerter.profil(["aufschiebend", "perfektionistisch", "stur", "aengstlich",
"nachtaktiv", "zurueckgezogen"])
p(bild["ursachen"].size() >= 2 and bild["ursachen"].size() <= 3,
"Zwei bis drei Ursachen: %s" % str(bild["ursachen"]))
p(bild["ursachen"].has("anfang"), "Aufschiebend und perfektionistisch ergeben »kein Anfang«")
p(bild["probleme"].size() >= 1 and bild["probleme"].size() <= 2,
"Ein bis zwei Klemmen: %s" % str(bild["probleme"]))
p(bild["probleme"].has("angst") or bild["probleme"].has("perfektionismus"),
"Ängstlich und perfektionistisch schlagen durch")
p(bild["blocker"].size() >= 2, "Blocker zu den Ursachen: %s" % str(bild["blocker"]))
var fremd := false
for b in bild["blocker"]:
if not bild["ursachen"].has(Ursachen.ursache_von(str(b))):
fremd = true
p(not fremd, "Kein Blocker ohne passende Ursache")
p(int(bild["verhalten"]["abwehr"]) >= 2, "Stur und perfektionistisch: Abwehr %d" %
int(bild["verhalten"]["abwehr"]))
p(int(bild["verhalten"]["sichtbar"]) < 0, "Zurückgezogen: schwer zu durchschauen (%d)" %
int(bild["verhalten"]["sichtbar"]))
var gegen := Woerter.profil(["ordentlich", "chaotisch", "geduldig", "ungeduldig",
"gelassen", "reizbar"])
p(int(gegen["verhalten"]["guete"]) == 0 and int(gegen["verhalten"]["momente"]) == 0,
"Widersprüche heben sich auf (Güte %d, Momente %d)" %
[int(gegen["verhalten"]["guete"]), int(gegen["verhalten"]["momente"])])
var wenig := Woerter.profil(["heiter"])
p(wenig["ursachen"].size() >= 2 and wenig["probleme"].size() >= 1,
"Auch ein Wort ergibt einen ganzen Menschen (%s / %s)" %
[str(wenig["ursachen"]), str(wenig["probleme"])])
# --- Ein Mensch aus einem Aushang, mit eigenem Alltag
var pr := {"name": "Mo Test", "alter": 33, "beruf": "Bäcker",
"traum": "Wieder Gitarre spielen.", "geschichte": "Nach der Schicht ist nichts übrig.",
"woerter": ["erschoepft", "bequem", "konfliktscheu", "gruendlich", "stur", "aengstlich"]}
p(Aushaenge.pruefen(pr).is_empty(), "Der Aushang ist vollständig")
p(not Aushaenge.pruefen({"name": "X", "woerter": ["stur"]}).is_empty(),
"Ein lückenhafter wird abgewiesen: %s" %
", ".join(Aushaenge.pruefen({"name": "X", "woerter": ["stur"]})))
var id := Aushaenge.speichern(pr)
p(id.begins_with("eigen_"), "Gespeichert als %s" % id)
p(Aushaenge.laden().size() == 1 and Aushaenge.laden()[0]["name"] == "Mo Test",
"Und aus der Datei zurückgelesen")
Game.completed.clear()
Game.welt_erzeugen()
var m := HumanDB.by_id(id)
p(not m.is_empty(), "Er lebt in der Stadt")
p(HumanDB.LIST.size() == HumanDB.EINWOHNER, "Die Stadt bleibt bei %d Einwohnern" % HumanDB.EINWOHNER)
p(HumanDB.PLACES.has(str(m["heim"])), "Er hat ein Zuhause: %s" % m["heim"])
var frueh := false
for e in m["routine"]:
if int(e[0]) == 4 and str(e[1]) == "baeckerei":
frueh = true
p(frueh, "Als Bäcker steht er um vier in der Backstube")
var luecken := 0
for stunde in range(24):
if Game.slot_bei_stunde(id, stunde) < 0:
luecken += 1
p(luecken == 0, "Sein Tag ist lückenlos")
var blocker_im_tag: Array = []
for e in m["routine"]:
if Ursachen.ist_blocker(str(e[2])):
blocker_im_tag.append(str(e[2]))
p(blocker_im_tag.size() >= 2 and blocker_im_tag.size() <= HumanDB.BLOCKER_MAX,
"Zwei bis %d Blocker stehen im Tag: %s" % [HumanDB.BLOCKER_MAX, ", ".join(blocker_im_tag)])
var passt_alle := true
for b in blocker_im_tag:
if not (m["ursachen"] as Array).has(Ursachen.ursache_von(b)):
passt_alle = false
p(passt_alle, "Jeder davon gehört zu einer seiner Ursachen")
var ohne_blocker: Array = []
for u in m["ursachen"]:
var da := false
for b in blocker_im_tag:
if Ursachen.ursache_von(b) == str(u):
da = true
if not da:
ohne_blocker.append(str(u))
p(ohne_blocker.is_empty(), "Und jede seiner Ursachen zeigt sich im Tag%s" %
("" if ohne_blocker.is_empty() else " — nicht: " + ", ".join(ohne_blocker)))
# Das gilt für jeden Menschen der Stadt, sonst bremst eine Ursache für immer
var stumm: Array = []
for hh in HumanDB.LIST:
for u in hh["ursachen"]:
var zeigt := false
for e in hh["routine"]:
if Ursachen.ursache_von(str(e[2])) == str(u):
zeigt = true
if not zeigt:
stumm.append("%s/%s" % [hh["name"], u])
p(stumm.is_empty(), "Bei allen %d Menschen zeigt sich jede Ursache im Tag%s" %
[HumanDB.LIST.size(), "" if stumm.is_empty() else " — nicht: " + ", ".join(stumm)])
p(Game.machbar(id) or true, "Bereit fürs Brett")
_wege_pruefen("Stadt mit eigenem Menschen", HumanDB.PLACES, HumanDB.LIST)
# --- Die Wörter verändern, wie er sich verhält
p(Game.verhalten(id, "abwehr") >= 1, "Stur: Abwehr %d" % Game.verhalten(id, "abwehr"))
var std_id := "mensch_0"
p(Game.verhalten(std_id, "abwehr") == 0, "Ein erzeugter Mensch steht auf null")
Game.situation = {}
var pause_normal := Game._pause_fuer(std_id)
var reiz := Woerter.profil(["reizbar", "aengstlich", "rastlos", "spontan", "ehrgeizig", "stur"])
var pr2 := {"name": "Ria Test", "alter": 28, "beruf": "Studentin", "traum": "T",
"geschichte": "G", "woerter": ["reizbar", "aengstlich", "rastlos", "spontan", "ehrgeizig", "stur"]}
var id2 := Aushaenge.speichern(pr2)
Game.welt_erzeugen()
p(int(reiz["verhalten"]["momente"]) >= 2, "Reizbar, ängstlich, rastlos: Momente %d" %
int(reiz["verhalten"]["momente"]))
p(Game._pause_fuer(id2) < pause_normal,
"Bei ihr kommt der nächste Moment schneller (%.0f s statt %.0f s)" %
[Game._pause_fuer(id2), pause_normal])
var tempo_std := Game.traum_tempo(std_id)
var pr3 := {"name": "Zed Test", "alter": 40, "beruf": "Lehrer", "traum": "T",
"geschichte": "G", "woerter": ["diszipliniert", "zielstrebig", "optimistisch",
"sportlich", "verbissen", "ehrgeizig"]}
var id3 := Aushaenge.speichern(pr3)
Game.welt_erzeugen()
Game.systeme.clear()
p(Game.traum_tempo(id3) > Game.traum_tempo(id) or Game.verhalten(id3, "tempo") > Game.verhalten(id, "tempo"),
"Zielstrebig treibt den Traum von sich aus (Tempo %d gegen %d)" %
[Game.verhalten(id3, "tempo"), Game.verhalten(id, "tempo")])
p(HumanDB.LIST.size() == HumanDB.EINWOHNER, "Drei eigene, immer noch %d Einwohner" % HumanDB.LIST.size())
# --- Am Brett: schreiben, Zufall, speichern, abnehmen
main._traumwelt()
await get_tree().process_frame
ui().brett_panel()
p(_knopf_da("Aushang schreiben"), "Das Brett bietet an, einen Aushang zu schreiben")
p(_knopf_texte().contains("Mo Test"), "Der eigene Mensch hängt aus")
ui().schreiben_panel()
p(ui()._kind == "schreiben", "Das Formular öffnet sich")
var haken := 0
for c in _alle_kinder(ui()._content):
if c is CheckBox:
haken += 1
p(haken == Woerter.ids().size(), "Alle %d Wörter sind ankreuzbar (%d)" % [Woerter.ids().size(), haken])
ui().schreiben_panel(HumanDB.zufallsprofil())
p(str(ui()._entwurf["name"]) != "" and (ui()._entwurf["woerter"] as Array).size() >= Woerter.MINDESTENS,
"Zufall füllt alles: %s mit %d Wörtern" % [ui()._entwurf["name"],
(ui()._entwurf["woerter"] as Array).size()])
var vorher := Aushaenge.laden().size()
ui()._aushang_speichern()
p(Aushaenge.laden().size() == vorher + 1, "Speichern hängt ihn ans Brett (%d)" % Aushaenge.laden().size())
p(ui()._kind == "aushang", "Und zeigt den Aushang")
p(_knopf_da("Aushang abnehmen"), "Ein eigener lässt sich abnehmen")
_druecke("Aushang abnehmen")
p(Aushaenge.laden().size() == vorher, "Abgenommen (%d)" % Aushaenge.laden().size())
ui().schliessen()
Aushaenge.alle_loeschen()
Aushaenge.PFAD = "user://aushaenge.cfg"
Game.welt_erzeugen()
main._erde()
await get_tree().process_frame
func _alle_kinder(n: Node) -> Array:
var out: Array = []
for c in n.get_children():
out.append(c)
out.append_array(_alle_kinder(c))
return out
## Der Ablauf steht auch im HUD, ohne dass man ein Panel öffnen muss.
func test_ablauf_im_hud() -> void:
abschnitt("Der Ablauf steht im HUD")
@@ -1793,10 +2030,10 @@ func test_brett_nie_leer() -> void:
Game.completed.append("stufe_%d" % k)
Game.welt_erzeugen()
Game.known = {str(TechDB.LIST[i]["id"]): 0}
if Game.machbar("mensch_%d" % i):
if not Game.offene_missionen().is_empty():
passt += 1
p(passt == TechDB.LIST.size(),
"Zu jedem der %d Wege gibt es den passenden Menschen (%d)" %
"Zu jedem der %d Wege gibt es einen Menschen, dem er hilft (%d)" %
[TechDB.LIST.size(), passt])
Game.completed.assign(merk_c)