update
This commit is contained in:
351
tests/verify.gd
351
tests/verify.gd
@@ -34,7 +34,12 @@ func _ready() -> void:
|
||||
await test_tagesablauf()
|
||||
await test_wege_machbar()
|
||||
await test_geist()
|
||||
await test_verfolgung()
|
||||
await test_gehen_bei_tempo()
|
||||
await test_diagnose()
|
||||
await test_notieren_im_spiel()
|
||||
await test_tagesablauf_anzeige()
|
||||
await test_ablauf_im_hud()
|
||||
await test_systeme()
|
||||
await test_tempo_des_traums()
|
||||
await test_cooldown()
|
||||
@@ -691,6 +696,110 @@ func test_geist() -> void:
|
||||
p(lena.global_position.distance_to(davor) < 2.0, "Menschen nehmen den Geist nicht wahr")
|
||||
|
||||
|
||||
## Bei hohem Tempo wird der Schritt je Bild größer als die Ankunftsschwelle.
|
||||
## Wer dann über den Wegpunkt hinausläuft, pendelt um ihn herum statt anzukommen.
|
||||
func test_gehen_bei_tempo() -> void:
|
||||
abschnitt("Gehen bleibt auch im Schnelllauf ruhig")
|
||||
ui().schliessen()
|
||||
var mensch: Bewohner = welt().humans[0]
|
||||
var stufe_kehrt: Dictionary = {}
|
||||
for stufe in [1, 3]:
|
||||
Game.tempo_setzen(stufe)
|
||||
Game.time_h = 12.9
|
||||
for i in range(400):
|
||||
schritte(1, 1.0 / 60.0)
|
||||
if not mensch._path.is_empty():
|
||||
break
|
||||
var kehrt := 0
|
||||
var bewegt := 0
|
||||
var vorher: Vector3 = mensch.global_position
|
||||
var richtung := Vector3.ZERO
|
||||
for i in range(600):
|
||||
schritte(1, 1.0 / 60.0)
|
||||
if mensch._path.is_empty():
|
||||
continue
|
||||
var d: Vector3 = mensch.global_position - vorher
|
||||
d.y = 0.0
|
||||
if d.length() > 0.001:
|
||||
bewegt += 1
|
||||
if richtung != Vector3.ZERO and d.normalized().dot(richtung) < -0.5:
|
||||
kehrt += 1
|
||||
richtung = d.normalized()
|
||||
vorher = mensch.global_position
|
||||
stufe_kehrt[stufe] = kehrt
|
||||
var weite := Bewohner.GEHTEMPO * (1.0 / 60.0) * Game.faktor_von(stufe)
|
||||
p(kehrt <= 4, "Tempo %d (%d×, %.2f je Bild): %d Kehrtwenden in %d Bildern" %
|
||||
[stufe, int(Game.faktor_von(stufe)), weite, kehrt, bewegt])
|
||||
p(int(stufe_kehrt[3]) <= int(stufe_kehrt[1]) + 4,
|
||||
"Schnelllauf zappelt nicht mehr als Normaltempo (%d gegen %d)" %
|
||||
[stufe_kehrt[3], stufe_kehrt[1]])
|
||||
Game.tempo_setzen(1)
|
||||
|
||||
|
||||
## Sich an einen Menschen hängen: der Geist begleitet ihn durch seinen Tag,
|
||||
## statt ihm hinterherzulaufen. Damit bleibt er die ganze Zeit beobachtbar.
|
||||
func test_verfolgung() -> void:
|
||||
abschnitt("Als Geist einen Menschen begleiten")
|
||||
p(InputMap.has_action("folgen") and not InputMap.action_get_events("folgen").is_empty(),
|
||||
"Eigene Taste fürs Folgen")
|
||||
ui().schliessen()
|
||||
main.player.set_mode(Player.Mode.GEIST)
|
||||
main.player.look_enabled = true
|
||||
main.player.yaw = 0.0
|
||||
var mensch: Bewohner = welt().humans[0]
|
||||
Game.active_mission = str(mensch.data["id"])
|
||||
main.player.global_position = mensch.global_position + Vector3(0, 1.5, 2.0)
|
||||
main.player.velocity = Vector3.ZERO
|
||||
main._process(0.05)
|
||||
p(main._fokus_mensch == mensch, "Der Mensch ist im Fokus")
|
||||
|
||||
main._verfolgen()
|
||||
p(main.player.folgt == mensch, "F hängt den Geist an ihn")
|
||||
|
||||
# Er lebt seinen Tag weiter, der Geist bleibt dran
|
||||
var weiteste := 0.0
|
||||
var gelaufen := false
|
||||
var im_fokus := 0
|
||||
for i in range(900):
|
||||
schritte(1)
|
||||
await get_tree().physics_frame
|
||||
if not mensch._path.is_empty():
|
||||
gelaufen = true
|
||||
if main._fokus_mensch == mensch:
|
||||
im_fokus += 1
|
||||
weiteste = maxf(weiteste,
|
||||
main.player.global_position.distance_to(mensch.global_position))
|
||||
p(gelaufen, "Er wechselt in dieser Zeit den Ort")
|
||||
p(weiteste < 6.0, "Der Geist bleibt die ganze Zeit dicht dabei (höchstens %.1f)" % weiteste)
|
||||
p(im_fokus > 850, "Und behält ihn im Fokus (%d von 900 Schritten)" % im_fokus)
|
||||
p(main._fokus_mensch == mensch or main.player.folgt == mensch,
|
||||
"Unterwegs bleibt er notierbar")
|
||||
|
||||
# Eigene Bewegung löst die Verfolgung
|
||||
Input.action_press("vor")
|
||||
for i in range(10):
|
||||
await get_tree().physics_frame
|
||||
Input.action_release("vor")
|
||||
p(main.player.folgt == null, "Wer selbst losgeht, lässt ihn los")
|
||||
|
||||
# Die Taste löst ebenfalls
|
||||
main.player.global_position = mensch.global_position + Vector3(0, 1.5, 2.0)
|
||||
main.player.velocity = Vector3.ZERO
|
||||
main._process(0.05)
|
||||
main._verfolgen()
|
||||
p(main.player.folgt == mensch, "Wieder angehängt")
|
||||
main._verfolgen()
|
||||
p(main.player.folgt == null, "F lässt wieder los")
|
||||
|
||||
# In der Traumwelt gibt es niemanden zu verfolgen
|
||||
main._traumwelt()
|
||||
await get_tree().process_frame
|
||||
main._verfolgen()
|
||||
p(main.player.folgt == null, "In der Traumwelt hängt sich der Läufer an niemanden")
|
||||
main._erde()
|
||||
await get_tree().process_frame
|
||||
|
||||
|
||||
## Woran der Traum scheitert, steht nirgends. Man findet es, indem man
|
||||
## dabeisteht -- awareness training, bevor irgendetwas ersetzt wird.
|
||||
func test_diagnose() -> void:
|
||||
@@ -699,7 +808,7 @@ func test_diagnose() -> void:
|
||||
Game.active_mission = id
|
||||
Game.systeme.clear()
|
||||
Game.erkannt_slots.clear()
|
||||
Game.beobachtung.clear()
|
||||
Game.notiz_sperre = 0.0
|
||||
|
||||
var urs: Array = Game.ursachen_von(id)
|
||||
p(urs.size() >= 2 and urs.size() <= 3,
|
||||
@@ -739,11 +848,19 @@ func test_diagnose() -> void:
|
||||
p(not Game.ursache_bekannt(id, ursache), "Und die Ursache ist noch unbekannt")
|
||||
|
||||
# Solange man nicht lange genug dabeisteht, passiert nichts
|
||||
Game.beobachten(id, blocker_nr, Game.ERKENNEN_SEK * 0.4)
|
||||
p(not Game.erkannt(id, blocker_nr), "Kurz hinschauen reicht nicht")
|
||||
Game.beobachten(id, blocker_nr, Game.ERKENNEN_SEK)
|
||||
p(Game.erkannt(id, blocker_nr), "Nach %.0f Sekunden dabeistehen zeigt es sich" %
|
||||
Game.ERKENNEN_SEK)
|
||||
# Zusehen allein deckt nichts auf -- der Spieler muss den Moment benennen
|
||||
for i in range(60):
|
||||
schritte(1)
|
||||
p(not Game.erkannt(id, blocker_nr), "Bloßes Dabeistehen deckt nichts auf")
|
||||
p(Game.notieren(id, neutral_nr) == "daneben",
|
||||
"Im freien Slot geht die Notiz daneben")
|
||||
p(Game.notiz_sperre > 0.0, "Ein Fehlgriff sperrt kurz (%.0f s)" % Game.notiz_sperre)
|
||||
p(Game.notieren(id, blocker_nr) == "gesperrt", "Solange nimmt er keine Notiz an")
|
||||
Game.notiz_sperre = 0.0
|
||||
p(Game.notieren(id, blocker_nr) == "treffer", "Im Blocker-Slot sitzt sie")
|
||||
p(Game.erkannt(id, blocker_nr), "Und deckt auf, was dort läuft")
|
||||
p(is_equal_approx(Game.notiz_sperre, 0.0), "Ein Treffer sperrt nicht")
|
||||
p(Game.notieren(id, blocker_nr) == "bekannt", "Zweimal notieren bringt nichts Neues")
|
||||
p(Game.ursache_bekannt(id, ursache),
|
||||
"Und damit die Ursache: %s" % Ursachen.LISTE[ursache]["name"])
|
||||
|
||||
@@ -761,6 +878,226 @@ func test_diagnose() -> void:
|
||||
|
||||
|
||||
## Gegen eine Ursache baut man ein System. Passt die Belohnung, hält es besser.
|
||||
## 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")
|
||||
var id := "mensch_0"
|
||||
Game.gesehen.clear()
|
||||
Game.erkannt_slots.clear()
|
||||
Game.systeme.clear()
|
||||
Game.active_mission = ""
|
||||
ui().schliessen()
|
||||
ui()._hud_aktualisieren()
|
||||
p(not ui()._ablauf.visible, "Ohne Mission zeigt das HUD keinen Ablauf")
|
||||
|
||||
Game.active_mission = id
|
||||
Game.time_h = 9.5
|
||||
ui()._hud_aktualisieren()
|
||||
p(ui()._ablauf.visible, "Mit Mission schon")
|
||||
p(ui()._zellen.size() == 24, "Ein Feld je Stunde (%d)" % ui()._zellen.size())
|
||||
p(ui()._ablauf_titel.text.contains("0 – 23"), "Beschriftet von 0 bis 23 Uhr")
|
||||
p(ui()._ablauf_titel.text.contains("24 Stunden unbekannt"),
|
||||
"Am Anfang ist alles unbekannt: %s" % ui()._ablauf_titel.text)
|
||||
|
||||
var unbekannt: Color = ui()._ablauf_farbe(id, Game.slot_bei_stunde(id, 9))
|
||||
var nr := Game.slot_bei_stunde(id, 9)
|
||||
Game.sehen(id, nr)
|
||||
ui()._hud_aktualisieren()
|
||||
p(ui()._ablauf_farbe(id, nr) != unbekannt, "Eine gesehene Stunde färbt sich um")
|
||||
p(not ui()._ablauf_titel.text.contains("24 Stunden"),
|
||||
"Und der Zähler geht runter: %s" % ui()._ablauf_titel.text)
|
||||
p(ui()._ablauf_jetzt.text.begins_with("09 Uhr"),
|
||||
"Darunter steht die laufende Stunde: %s" % ui()._ablauf_jetzt.text)
|
||||
|
||||
# Die laufende Stunde ist hervorgehoben
|
||||
var jetzt: ColorRect = ui()._zellen[9]
|
||||
var andere: ColorRect = ui()._zellen[8]
|
||||
p(jetzt.custom_minimum_size.y > andere.custom_minimum_size.y,
|
||||
"Das Feld der laufenden Stunde steht heraus")
|
||||
|
||||
# Ein benannter Blocker sieht anders aus als eine harmlose Stunde
|
||||
var blocker_nr := -1
|
||||
var frei_nr := -1
|
||||
for n in range(Game.slots(id).size()):
|
||||
var g := Game.slot_grund(id, n)
|
||||
if Ursachen.ist_blocker(g) and blocker_nr < 0:
|
||||
blocker_nr = n
|
||||
elif g != "schlaeft" and not Ursachen.ist_blocker(g) and frei_nr < 0:
|
||||
frei_nr = n
|
||||
Game.sehen(id, blocker_nr)
|
||||
Game.sehen(id, frei_nr)
|
||||
var vor_notiz: Color = ui()._ablauf_farbe(id, blocker_nr)
|
||||
Game.notieren(id, blocker_nr)
|
||||
p(ui()._ablauf_farbe(id, blocker_nr) != vor_notiz,
|
||||
"Notiert wechselt der Blocker noch einmal die Farbe")
|
||||
p(ui()._ablauf_farbe(id, blocker_nr) != ui()._ablauf_farbe(id, frei_nr),
|
||||
"Und hebt sich von einer harmlosen Stunde ab")
|
||||
Game.notiz_sperre = 0.0
|
||||
|
||||
|
||||
## Der Ablauf 0-23 Uhr: am Anfang leer, füllt sich durchs Dabeisein.
|
||||
func test_tagesablauf_anzeige() -> void:
|
||||
abschnitt("Der Tag steht als Ablauf von 0 bis 23 Uhr")
|
||||
var id := "mensch_0"
|
||||
Game.active_mission = id
|
||||
Game.gesehen.clear()
|
||||
Game.erkannt_slots.clear()
|
||||
Game.systeme.clear()
|
||||
Game.notiz_sperre = 0.0
|
||||
|
||||
# Jede Stunde des Tages hat einen Slot, und jeder Tag ist derselbe
|
||||
var luecken := 0
|
||||
for stunde in range(24):
|
||||
if Game.slot_bei_stunde(id, stunde) < 0:
|
||||
luecken += 1
|
||||
p(luecken == 0, "Alle 24 Stunden sind belegt")
|
||||
Game.day = 1
|
||||
var tag_eins: Array = []
|
||||
for stunde in range(24):
|
||||
tag_eins.append(Game.slot_bei_stunde(id, stunde))
|
||||
Game.day = 9
|
||||
var tag_neun: Array = []
|
||||
for stunde in range(24):
|
||||
tag_neun.append(Game.slot_bei_stunde(id, stunde))
|
||||
p(tag_eins == tag_neun, "Tag 9 sieht aus wie Tag 1 — es gibt keine Wochentage")
|
||||
Game.day = 1
|
||||
|
||||
ui().systeme_panel(id)
|
||||
var zeilen := _knopf_texte()
|
||||
p(zeilen.contains("00 – "), "Der Ablauf beginnt um 00 Uhr")
|
||||
p(zeilen.contains(" – 24"), "Und reicht bis 24 Uhr")
|
||||
var leer := 0
|
||||
for stunde in range(24):
|
||||
if not Game.gesehen_slot(id, Game.slot_bei_stunde(id, stunde)):
|
||||
leer += 1
|
||||
p(leer == 24, "Am Anfang ist jede der 24 Stunden unbekannt (%d)" % leer)
|
||||
p(zeilen.contains("—") and not zeilen.contains("schläft"),
|
||||
"Und im Ablauf steht nur ein Strich")
|
||||
ui().schliessen()
|
||||
|
||||
# Dabeistehen füllt genau die Stunde, in der man steht
|
||||
var mensch: Bewohner = null
|
||||
for m in welt().humans:
|
||||
if m.data["id"] == id:
|
||||
mensch = m
|
||||
var frei_nr := -1
|
||||
for nr in range(Game.slots(id).size()):
|
||||
var g := Game.slot_grund(id, nr)
|
||||
if g != "schlaeft" and not Ursachen.ist_blocker(g):
|
||||
frei_nr = nr
|
||||
break
|
||||
await _hin_zu(mensch, float(Game.slots(id)[frei_nr][0]) + 0.5)
|
||||
main._process(0.05)
|
||||
p(Game.gesehen_slot(id, frei_nr), "Wer dabeisteht, füllt die Stunde")
|
||||
ui().systeme_panel(id)
|
||||
p(_knopf_texte().contains(Orte.text(Game.slot_grund(id, frei_nr))),
|
||||
"Sie steht jetzt im Ablauf: %s" % Orte.text(Game.slot_grund(id, frei_nr)))
|
||||
ui().schliessen()
|
||||
|
||||
# Ein Blocker bleibt ein Fragezeichen, bis er benannt ist
|
||||
var blocker_nr := -1
|
||||
for nr in range(Game.slots(id).size()):
|
||||
if Ursachen.ist_blocker(Game.slot_grund(id, nr)):
|
||||
blocker_nr = nr
|
||||
break
|
||||
Game.sehen(id, blocker_nr)
|
||||
ui().systeme_panel(id)
|
||||
p(_knopf_texte().contains("?"), "Was schiefläuft, steht erst als Fragezeichen da")
|
||||
ui().schliessen()
|
||||
Game.notieren(id, blocker_nr)
|
||||
ui().systeme_panel(id)
|
||||
var b: Dictionary = Ursachen.BLOCKER[Game.slot_grund(id, blocker_nr)]
|
||||
p(_knopf_texte().contains(str(b["name"])),
|
||||
"Nach dem Notieren steht dort, was sie tut")
|
||||
p(_knopf_texte().contains(str(Ursachen.LISTE[b["ursache"]]["name"])),
|
||||
"Und warum: %s" % Ursachen.LISTE[b["ursache"]]["name"])
|
||||
ui().schliessen()
|
||||
|
||||
|
||||
## Der ganze Weg: dabeistehen, den Moment einschätzen, R drücken.
|
||||
func test_notieren_im_spiel() -> void:
|
||||
abschnitt("Notieren ist eine Entscheidung, kein Timer")
|
||||
var id := "mensch_0"
|
||||
Game.active_mission = id
|
||||
Game.erkannt_slots.clear()
|
||||
Game.notiz_sperre = 0.0
|
||||
ui().schliessen()
|
||||
main.player.set_mode(Player.Mode.GEIST)
|
||||
main.player.look_enabled = true
|
||||
|
||||
var blocker_nr := -1
|
||||
var frei_nr := -1
|
||||
for nr in range(Game.slots(id).size()):
|
||||
var g := Game.slot_grund(id, nr)
|
||||
if Ursachen.ist_blocker(g) and blocker_nr < 0:
|
||||
blocker_nr = nr
|
||||
elif g != "schlaeft" and not Ursachen.ist_blocker(g) and frei_nr < 0:
|
||||
frei_nr = nr
|
||||
p(blocker_nr >= 0 and frei_nr >= 0, "Ihr Tag hat einen Blocker und einen freien Slot")
|
||||
|
||||
var mensch: Bewohner = null
|
||||
for m in welt().humans:
|
||||
if m.data["id"] == id:
|
||||
mensch = m
|
||||
|
||||
# Im freien Slot danebengegriffen
|
||||
await _hin_zu(mensch, float(Game.slots(id)[frei_nr][0]) + 0.5)
|
||||
p(mensch.slot == frei_nr, "Sie steht im freien Slot (%d)" % mensch.slot)
|
||||
main._notieren()
|
||||
p(not Game.erkannt(id, blocker_nr), "Hier gibt es nichts zu notieren")
|
||||
p(Game.notiz_sperre > 0.0, "Der Fehlgriff kostet eine Sperre")
|
||||
|
||||
# Sperre läuft in Echtzeit ab
|
||||
for i in range(200):
|
||||
main._process(0.05)
|
||||
p(is_equal_approx(Game.notiz_sperre, 0.0), "Sie läuft von allein ab")
|
||||
|
||||
# Im Blocker-Slot getroffen
|
||||
await _hin_zu(mensch, float(Game.slots(id)[blocker_nr][0]) + 0.5)
|
||||
p(mensch.slot == blocker_nr, "Jetzt steht sie im Blocker-Slot (%d)" % mensch.slot)
|
||||
p(main._fokus_mensch == mensch, "Und ist in Reichweite")
|
||||
main._notieren()
|
||||
p(Game.erkannt(id, blocker_nr), "R notiert, was hier schiefläuft: %s" %
|
||||
Orte.text(Game.slot_grund(id, blocker_nr)))
|
||||
|
||||
# Ein fremder Mensch geht niemanden etwas an
|
||||
Game.erkannt_slots.clear()
|
||||
Game.notiz_sperre = 0.0
|
||||
var fremd: Bewohner = null
|
||||
for m in welt().humans:
|
||||
if m.data["id"] != id:
|
||||
fremd = m
|
||||
main.player.folgt = null
|
||||
main.player.global_position = fremd.global_position + Vector3(0, 1.5, 1.5)
|
||||
main._process(0.05)
|
||||
main._notieren()
|
||||
p(Game.erkannt_slots.is_empty(),
|
||||
"Ohne angenommene Mission notiert er bei %s nichts" % fremd.data["name"])
|
||||
p(is_equal_approx(Game.notiz_sperre, 0.0), "Und das kostet auch keine Sperre")
|
||||
|
||||
# Aus der Verfolgung heraus geht es ebenfalls
|
||||
Game.erkannt_slots.clear()
|
||||
await _hin_zu(mensch, float(Game.slots(id)[blocker_nr][0]) + 0.5)
|
||||
main._verfolgen()
|
||||
p(main.player.folgt == mensch, "An sie gehängt")
|
||||
main._notieren()
|
||||
p(Game.erkannt(id, blocker_nr), "Auch im Vorbeischweben lässt sich notieren")
|
||||
main.player.folgt = null
|
||||
|
||||
|
||||
## Stellt den Geist zur genannten Stunde neben den Menschen.
|
||||
func _hin_zu(mensch: Bewohner, stunde: float) -> void:
|
||||
for i in range(600):
|
||||
schritte(1, 0.05, stunde)
|
||||
if mensch._path.is_empty():
|
||||
break
|
||||
main.player.folgt = null
|
||||
main.player.global_position = mensch.global_position + Vector3(0, 1.5, 1.5)
|
||||
main.player.velocity = Vector3.ZERO
|
||||
await get_tree().process_frame
|
||||
main._process(0.05)
|
||||
|
||||
|
||||
func test_systeme() -> void:
|
||||
abschnitt("Systeme — gegen die Ursache, nicht gegen die Tätigkeit")
|
||||
var id := "mensch_0"
|
||||
@@ -1612,7 +1949,7 @@ func _erster_traum_tage(saat: int) -> int:
|
||||
Game.known.clear()
|
||||
Game.systeme.clear()
|
||||
Game.erkannt_slots.clear()
|
||||
Game.beobachtung.clear()
|
||||
Game.notiz_sperre = 0.0
|
||||
Game.progress.clear()
|
||||
Game.completed.clear()
|
||||
Game.active_mission = ""
|
||||
|
||||
Reference in New Issue
Block a user