This commit is contained in:
team3
2026-09-16 17:00:41 +02:00
parent f1c78f66f4
commit 9800c614bb
21 changed files with 497 additions and 191 deletions

View File

@@ -57,7 +57,7 @@ func _lauf() -> void:
for d in game.table.dice_of(i):
print(" Wuerfel Platz %d: pos=%s sleeping=%s freeze=%s settled=%s flat=%.2f" % [
i, d.global_position, d.sleeping, d.freeze, d.is_settled(), d.flatness()])
_pruef("Partie endet (%s, Stufe %d, %d Runden, %.0fs Spielzeit)" % [game.banner, DiceAI.stufe, runden, t], game.phase == "over")
_pruef("Partie endet (%s, Stufe %d, %d Runden, %.0fs Spielzeit)" % [game.banner, DiceAI.stufe, game.runde, t], game.phase == "over")
_pruef("Münzen wurden geworfen (%d)" % zaehler[" wirft "], zaehler[" wirft "] > 0)
_pruef("Topf wurde vergeben (%d)" % zaehler["Topf"], zaehler["Topf"] > 0)
print(" Genau-Rufe=%d, vom Tisch=%d, Topf am Ende=%d" % [zaehler["Genau"], zaehler["vom Tisch"], game.topf.size()])

View File

@@ -88,6 +88,36 @@ func _lauf() -> void:
_pruef("Würfeln endet trotz verirrtem Würfel, Wert gelesen",
d0.global_position.y > 0.5 and game.host_values[me][0] >= 1 and game.host_values[me][0] <= 6)
# --- KI nutzt, was Spähen und Zählen verraten
var r := RandomNumberGenerator.new()
r.seed = 7
var gebot := {"seat": 1, "count": 4, "face": 5}
var a: Dictionary = DiceAI.choose_action([1, 2, 3], 9, gebot, false, r, {"fenster": {5: [1, 2]}})
_pruef("KI: Zählfenster unter der Ansage -> Anfechten", a.type == "challenge")
a = DiceAI.choose_action([5, 5, 2], 9, gebot, false, r, {"bekannt": [5, 5, 5]})
_pruef("KI: aufgedeckte Fünfen machen die Ansage sicher -> kein Anfechten", a.type != "challenge")
a = DiceAI.choose_action([1, 2, 3], 9, gebot, false, r, {"fenster": {5: [4, 4]}})
_pruef("KI: exaktes Fenster -> Genau", a.type == "exact")
# --- Tastatur: Taste tut nur, was der Knopf gerade darf
var taste := func(code: Key) -> void:
var ev := InputEventKey.new()
ev.keycode = code
ev.pressed = true
hud._unhandled_key_input(ev)
var gebote := []
hud.bid_pressed.connect(func(c, f): gebote.append([c, f]))
game._push_state()
await get_tree().create_timer(0.3).timeout
taste.call(KEY_3)
taste.call(KEY_PLUS)
taste.call(KEY_ENTER)
_pruef("Tastatur: 3, +, Enter sagt 2 x 3 an", gebote == [[2, 3]])
var angefochten := []
hud.challenge_pressed.connect(func(): angefochten.append(1))
taste.call(KEY_A)
_pruef("Tastatur: A ohne Ansage tut nichts", angefochten.is_empty())
# --- Protokoll und Tipp-Schranke im HUD
game._push_state()
await get_tree().create_timer(0.3).timeout

2
tests/out/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
*
!.gitignore

52
tests/shots.gd Normal file
View File

@@ -0,0 +1,52 @@
extends "res://tests/basis.gd"
## Bilder vom Spiel und vom Menü für die Sichtprüfung. Braucht ein Display -
## oder xvfb, siehe tests/shots.sh. Schreibt nach tests/out/.
var game: Node
const OUT := "res://tests/out"
func _ready() -> void:
DirAccess.make_dir_recursive_absolute(ProjectSettings.globalize_path(OUT))
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
DisplayServer.window_set_size(Vector2i(1280, 720))
var main := preload("res://scenes/main.tscn").instantiate()
add_child(main)
await get_tree().process_frame
main.menu._show("regeln")
await get_tree().create_timer(0.3).timeout
await _bild("menue_regeln")
main.menu._show("main")
await get_tree().create_timer(0.2).timeout
await _bild("menue_start")
Net.start_singleplayer("Tester", 3, 1)
_lauf()
func _bild(name: String) -> void:
await RenderingServer.frame_post_draw
var ok := get_viewport().get_texture().get_image().save_png("%s/%s.png" % [OUT, name])
_pruef("Bild %s" % name, ok == OK)
func _lauf() -> void:
await _warte(func(): game = _find(get_tree().root, "Game"); return game != null, 20.0)
await _warte(func(): return game.phase == "bid", 40.0)
var me: int = game.local_seat
game.hand[me] = ["gag", "peek", "count"]
game._push_state()
await get_tree().create_timer(0.4).timeout
await _bild("tisch_zug")
await game._do_play(me, "gag", 0)
await game._do_play(me, "peek", 0)
await get_tree().create_timer(1.2).timeout
await _bild("tisch_topf")
game.hud.hand_box.get_child(0).mouse_entered.emit()
await get_tree().create_timer(0.3).timeout
await _bild("tisch_erklaerung")
var n5: int = game._count_face(5)
game.bid = {"seat": 1, "count": maxi(1, n5), "face": 5}
game._phase_reveal({"challenger": me, "bid": game.bid, "exact": false})
await get_tree().create_timer(1.3 + 1.2).timeout
await _bild("aufdecken_zaehlen")
_fertig()

14
tests/shots.sh Executable file
View File

@@ -0,0 +1,14 @@
#!/usr/bin/env bash
# Screenshots für die Sichtprüfung nach tests/out/. Mit Display direkt, ohne
# Display über xvfb-run (Paket xvfb). Aufruf: make shots
set -u
GODOT="${GODOT:-$HOME/bin/godot}"
cd "$(dirname "$0")/.."
if [ -n "${DISPLAY:-}${WAYLAND_DISPLAY:-}" ]; then
timeout 120 "$GODOT" --path . res://tests/shots.tscn 2>&1 | grep -E "^(OK |FEHL|TEST:)"
elif command -v xvfb-run >/dev/null; then
timeout 120 xvfb-run -a -s "-screen 0 1280x720x24" "$GODOT" --path . res://tests/shots.tscn 2>&1 | grep -E "^(OK |FEHL|TEST:)"
else
echo "Kein Display und kein xvfb-run - Screenshots übersprungen."; exit 0
fi
ls -1 tests/out/

6
tests/shots.tscn Normal file
View File

@@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=3]
[ext_resource type="Script" path="res://tests/shots.gd" id="1"]
[node name="Test" type="Node"]
script = ExtResource("1")

View File

@@ -29,18 +29,13 @@ func _lauf() -> void:
Net.start_singleplayer("Tester", 2, stufe, 3)
await _warte(func(): game = _find(get_tree().root, "Game"); return game != null and game.phase != "lobby", 20.0)
game.tempo = 0.0
game.simulation = true
game.seats[game.local_seat].ai = true
var runden := 0
var letzte := ""
var gesehen := {}
var t := 0.0
while game.phase != "over" and t < 300.0:
await get_tree().create_timer(0.1).timeout
t += 0.1
if game.phase != letzte:
letzte = game.phase
if letzte == "roll":
runden += 1
await get_tree().create_timer(0.02).timeout
t += 0.02
for z in game.log_lines:
if gesehen.has(z):
continue
@@ -49,8 +44,8 @@ func _lauf() -> void:
genau += 1
if " wirft " in z:
wuerfe += 1
runden_summe += runden
laengste = maxi(laengste, runden)
runden_summe += game.runde
laengste = maxi(laengste, game.runde)
var sieger := ""
for s in game.seats:
if s.alive: