# Test-Harness `tools/lamatest.py` Startet "Ein Königreich für ein Lama" unbeaufsichtigt und unsichtbar (Xvfb :5, Ton in Null-Sink), lädt TestLevel Kapitel 1 (T1L9M001.wad) und macht Screenshots. Getestet am 2026-11-06 mit Wine 6.0.3, llvmpipe. ## Befehle ``` lamatest.py run [n] # alles in einem: installieren, start, tolevel, tour, stop lamatest.py start # Xvfb :5 + Null-Sink lama_stumm + groove.exe lamatest.py tolevel # Menü -> Slot mit TestLevel -> Kapitel 1 -> Gameplay lamatest.py tour [n] # n Kamera-Fotos (Rundumblick) + n Lauf-Fotos + Lama-Sicht lamatest.py shot out.png # Vollbild 1920x1080 lamatest.py key [s] # Taste s Sekunden halten (Default 0.12) lamatest.py keys Up:1.5 a:0.5 x # Folge, Name[:Haltezeit], auch sleep=2 lamatest.py seq "TOKENS" # --seq-Tokens (shot:, run:, rj: …) im laufenden Spiel lamatest.py status | stop | restore-wad ``` ### `run`-Optionen (2026-11-06 ergänzt) ``` lamatest.py run [n] [--seq "TOKENS"] [--tour] [--keep] ``` * **WAD-Wiederherstellung**: `run` merkt sich die *vorher installierte* `T1L9M001.wad` (`$LAMATEST_DIR/vorher_T1L9M001.wad`) und spielt sie nach dem Lauf zurück – also nicht `.orig`. Mit `--keep` bleibt die getestete WAD installiert. (`restore-wad` stellt weiterhin explizit `.orig` her.) * `--seq` ersetzt die Standard-Tour durch eine Tastenfolge (mit `--tour` zusätzlich Tour): * `Up:1.5`, `a:0.5`, `x` … Taste[:Haltezeit] wie bei `keys`; `sleep=1` * `shot:NAME` → `seq_NN_NAME.jpg`, `fp:NAME` → Foto in Lama-Sicht (Return gehalten) * `dialog` → Dialog/Letterbox wegklicken * `Up+x:0.8` → Tasten gleichzeitig halten * `rj:T1:T2` → Anlauf-Sprung (Up halten, nach T1 s X, Up noch T2 s) * `dj:T` → Doppel-X mit Anlauf, `hop:N:T` → Up halten, N× alle T s springen * `run:T:x@1.3,x@2.9,shot@5.0,Left@3.0-3.4` → Up T s halten, nach Zeitplan (s ab Beginn) X tippen / fotografieren (`seq_NN_runT.jpg`) / Taste von–bis halten; `run/Left:T:…` hält statt Up eine andere Taste. Echtzeit: ein Foto blockiert ~0,4 s (verzögert folgende Ereignisse und bremst das Spiel) → keine Fotos kurz vor Sprüngen. * Steuerung ist **kamerarelativ** (Up = in Kamerablickrichtung, Left/Right seitlich). A/S drehen die Kamera, S:0.45 ≈ 90° nach links schauen. * Messwerte (Lama): ~1,1 Einheiten/s Laufen, Sprung 0,35 hoch, mit Anlauf ~1,3 weit – siehe levelbau.md. Zeitgesteuerte Läufe streuen um ~0,3 Einheiten (Startverzögerung, Bildrate); längere Strecken brauchen „Anschläge“ (Wand/Stufe, an der das Lama stehen bleibt). * Kamera: nach Laufen gegen eine Wand oder einem Sturz dreht sich die Kamera unvorhersehbar → Up läuft danach in eine andere Richtung. A/S-Drehung (S:0.45) ist nur ungefähr 90°. * Kompletter Testwelt-Parkour per Skript: `levels/testwelt_parkour.seq` (levelbau.md). * `LAMATEST_SHOT=1280` (Umgebung): `shot:`/`fp:`-Fotos 1280×720, Qualität 85 statt 960×540 (Vorschaubilder). * „EINGEFROREN?“ bei einer `--seq` ohne Bewegung (z. B. nur `sleep=3 shot:x`) ist ein Fehlalarm – das stehende Lama ändert das Bild nicht; mit Kameradrehung/Laufen kommt „OK“. * Gute Blickwinkel im Spiel sind schwer: die Kamera hängt tief hinter dem Lama; erhöhte Startpunkte (Podest, Parkour-Checkpoint `pk2` + `A:0.6`) zeigen mehrere Bereiche. Hilfsskript für Serien: `$CLAUDE_JOB_DIR/tmp/lb_run.sh WAD NAME "SEQ"` (Montage `lb_mNAME.jpg`, WAD-Pfad absolut!), `rs.sh NAME "SEQ"` (Neustart mit installierter WAD + `seq`, Montage `i/NAME.jpg`). **Achtung**: kein `pgrep -f groove.exe` in Warteschleifen – das trifft die eigene Shell (Kommandozeile enthält "groove.exe") und lamatest hält sie für eine fremde Instanz. Zustand/PIDs/wine.log: `$LAMATEST_DIR` (Default `/tmp/lamatest-$USER`). `run` Exit-Codes: 0 OK, 3 Absturz, 4 Timeout/hängt, 5 Bild eingefroren. Ausgabe in ``: `report.txt`, `wine.log` (stderr, auf 2 MB gekürzt), `00_geladen.png` (voll) + `.jpg`, `tour_*.jpg` (960x540, ~30 KB), bei Fehler `zz_absturz.jpg` / `zz_timeout.jpg`. Ein Lauf ≈ 75 s, ≈ 1,2 MB. ## Sicherheitsregeln (im Skript umgesetzt) - Bricht ab, wenn eine groove.exe mit anderem DISPLAY läuft (Elias' Instanz). - xdotool nur mit DISPLAY=:5. - Ton: eigener Null-Sink, App wird nie stummgeschaltet; `stop` entlädt den Sink. - Spielstände (`*.ksv` im Spielordner) werden bei `start` gesichert und bei `stop` bei Änderung zurückgespielt (neu entstandene gelöscht). - `stop`: `wineserver -k` nur, wenn keine fremde groove.exe läuft, sonst nur eigene PIDs. - Der Ausgang der Testwelt speichert Fortschritt (Kapitel 2 frei) – wird bei `stop` mit den Spielständen zurückgespielt. - WAD: erstes `run` sichert das Original als `mods/testlevel/wads/T1L9M001.wad.orig`; `restore-wad` spielt es zurück. Das Overlay (`lama-mod an`) besteht aus **Symlinks** auf die Mod-Dateien → Überschreiben von `~/.wine-lama/mods/testlevel/wads/T1L9M001.wad` wirkt sofort; `lama-mod an` wird nur aufgerufen, wenn der Overlay-Link fehlt. ## Ablauf `tolevel` (gemessen) | Schritt | Taste | Erkennung | t (ab Start) | |---|---|---|---| | Logo → Hauptmenü | – | OCR Ausschnitt 700x300+1150+650, Schwelle 75 % → nur markierter Punkt "Spiel starten" lesbar | ~6 s | | Spiel starten | Return | – | | | Spielstandauswahl (Karussell, startet bei Slot 2, **kein** Wrap) | Left ×3, dann Right bis "TestLevel" | OCR Ausschnitt 1600x280+160+740 (fuzzy, 2 Schwellen) | ~20 s | | Slot 3 laden | Return | Auswahlkarte = >75 % beige Pixel | ~25 s | | Kapitel 1 aktivieren (Cursor aus KSV +4/+5) | Return | | | | Kamera-Flug (Letterbox: oberste+unterste Zeile schwarz) | Return überspringt | | +1,5 s | | Gameplay | – | hell, kein Letterbox, goldenes HUD oben links (oder >25 s) 3× hintereinander | ~29 s gesamt, Laden ~4 s | Ohne Überspringen dauert der Kamera-Flug im Dorf ~20 s. Ladebild = T191.COR ("TestLevel Kapitel 1 … LADEVORGANG"). Fallback: wird kein Menü erkannt, nach 40 s Return (überspringt Demo). Achtung: Return auf einem falsch erkannten Bildschirm kann ein anderes Spiel starten – Spielstände werden aber am Ende zurückgespielt. ## Steuerung PC (Tastatur, aus "Optionen → Tastatur konfigurieren", verifiziert) | Aktion | Taste | |---|---| | Auf / Ab (vorwärts / rückwärts laufen) | Up / Down | | Links / Rechts (drehen) | Left / Right | | Sprung (auch Dialog weiter) | X | | Action | Z | | Power | Space | | Lama-Sicht (Ego-Perspektive, halten) | Return | | Kamera nach links / rechts drehen | A / S (0,5 s halten ≈ 90°) | | Pausenmenü | Escape | Registry `HKCU\Software\Disney Interactive\Emperors New Groove\1.0`, `"InputDevice Wine Keyboard"` = 14 DIK-Codes (je 4 Hex): CB Left, CD Right, C8 Up, D0 Down, 1E A, 1F S, 39 Space, 2D X, 1C Return, 19 P, C9 PgUp, D1 PgDn, 2C Z, 18 O. Die Reihenfolge der Registry ≠ Menüreihenfolge; P/PgUp/PgDn/O vermutlich Pause/Inventar (laut exe-Strings: PAUSE GAME, CYCLE INVENTORY UP/DOWN, USE AN ITEM, TURN 180, SELECT) – nicht verifiziert. Weitere Werte dort: CameraMode, ControlType, ScreenW/H (1920x1142), CDPath=L:\. Pausenmenü (Escape): Grafik-/Tonoptionen, Tastatur/Joystick konfigurieren, Weitere Optionen, Weiter, "Beenden und zur Auswahlkarte wechseln" (Bestätigung Ja/Nein, Default Nein → Up, Return), Spiel beenden. Hauptmenü-Untermenüs: Escape = zurück. ## Beobachtungen Dorf-1-Kopie - Läuft man im Dorf vorwärts, startet sofort der Pacha-Dialog (Letterbox mit Untertiteln, ~9× X zum Durchklicken). `tour` erkennt das, fotografiert den Dialog einmal und klickt ihn weg. - Lama kann in der Tour von der Klippe fallen (Respawn) – egal für Sichtprüfung. ## Absturzerkennung Pro Poll: groove.exe-Prozess auf :5 weg / Fenster "Groove" weg / Fenster mit "Programmfehler", "error", "exception" … (Wine-Crashdialog). Im Report steht die Zeile `wine: Unhandled page fault … at address XXXXXXXX` (Adresse in Ghidra nachschlagen). Getestet: auf 300 KB gekürzte WAD und WAD mit 2000 zufälligen Bytes → beide Absturz während des Ladebilds, erkannt nach ~5 s (Exit 3). Harmloses Log-Rauschen (gstreamer/MPEG-1 fehlt, ole, ChangeDisplaySettings, MIDIMAP) wird im Report ausgefiltert. ## Abhängigkeiten Xvfb, xdotool, ImageMagick (import/convert), tesseract mit `deu`, pactl, wine.