Lava abgeschwächt, Archetypen aus Datei mit CI-Messlauf, Kartentext folgt Schriftgröße, Gamepad in Menüs, Anleitung 2 mit sicherem Angriff, Übersetzungsprüfung, Lint und gestaffelte CI

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QPgKvy5W9WRNFHjkm5QsHx
This commit is contained in:
Team3
2026-09-16 17:02:59 +02:00
parent f68ac07550
commit 77d1b318d6
19 changed files with 285 additions and 36 deletions

View File

@@ -111,6 +111,7 @@ func _initialize() -> void:
test_kurve_statistik_vorschlag_verbesserung()
test_wasser_antworten()
test_ki_zeitbudget()
test_uebersetzung_vollstaendig()
print("%d Prüfungen bestanden, %d fehlgeschlagen" % [passed, failed])
quit(1 if failed > 0 else 0)
@@ -532,15 +533,16 @@ func test_feldkombos() -> void:
g.play_card(h, C("w_reiter"))
check(strong.frozen and not weak.frozen, "Dampf friert das stärkste Wesen")
check(g.log.any(func(l): return l.begins_with("Feldkombo Dampf")), "Feldkombo im Verlauf")
# Lava: 1 Schaden an alle gegnerischen Wesen
# Lava: 1 Schaden an das stärkste gegnerische Wesen
s = setup(["e_golem"])
g = s[0]
h = s[1]
o = s[2][0]
put(h, "f_wolf")
var k := put(o, "f_kobold")
var big := put(o, "e_troll")
g.play_card(h, C("e_golem"))
check(not (k in o.board), "Lava tötet den 2/1 Kobold")
check(k in o.board and big.health == 5, "Lava trifft nur das stärkste Wesen")
# Blitz: 2 Schaden an den schwächsten Gegner
s = setup(["l_wind"], [], 2)
g = s[0]
@@ -1119,7 +1121,7 @@ func test_neue_fallen() -> void:
g.end_turn()
g.play_card(o, C("e_troll"))
check(o.board.size() == 1 and o.board[0].frozen and h.traps.size() == 1, "Sandfalle friert ein, eine Falle je Auslöser")
g.play_card(o, C("w_reiter")) # Wasser neben Erde: Schlamm heilt nur, der Windgeist überlebt
g.play_card(o, C("w_reiter")) # Wasser neben Erde: Schlamm heilt nur
check(h.board.size() == 1 and h.board[0].name == "Windgeist", "Spiegelfalle beschwört Windgeist beim zweiten Wesen")
check(h.traps.is_empty(), "beide Fallen verbraucht")
# Nebelfalle bricht ab und zieht, Dornenfalle verletzt und heilt
@@ -1240,7 +1242,7 @@ func test_deckstaerke_und_schwierigkeit() -> void:
func test_starter_gegen_passende_gegner() -> void:
check(Game.archetypes("leicht").size() == 5 and Game.archetypes("schwer").size() == 5 and Game.archetypes().size() == 10, "Archetypen geteilt")
var table: Dictionary = DeckGen.ARCHETYPE_STRENGTH
var table: Dictionary = DeckGen.strength()
var keys: Array = table.keys()
keys.sort_custom(func(a, b): return table[a] < table[b])
check(keys[0] in Game.archetypes("leicht") and keys[-1] in Game.archetypes("schwer"), "schwächster Archetyp in Leicht, stärkster in Schwer")
@@ -1358,3 +1360,37 @@ func test_ki_zeitbudget() -> void:
check(Cards.by_id("wl_gischt").keywords == ["Flink"] and Cards.by_id("wl_gischt").combo() == "Sturm", "Gischtläufer für Sturm")
var v := Profile.from_dict(JSON.parse_string(JSON.stringify(Profile.starter().to_dict())))
check(v.settings.has("big_font") and not v.tutorial2_done and v.records.margins is Array, "Version 5 mit neuen Feldern")
## Jeder tr("...")-Text in der Oberfläche und jeder Anleitungsschritt hat einen englischen Eintrag.
func test_uebersetzung_vollstaendig() -> void:
var keys := {}
var csv := FileAccess.get_file_as_string("res://translations/ui.csv")
for line in csv.split("\n"):
if line.is_empty() or line.begins_with("keys,"):
continue
var key := line
if line.begins_with("\""):
key = line.substr(1, line.find("\",", 1) - 1)
else:
key = line.substr(0, line.find(","))
keys[key] = true
var missing := []
var d := DirAccess.open("res://scripts/ui")
d.list_dir_begin()
var name := d.get_next()
while name != "":
if name.ends_with(".gd"):
var src := FileAccess.get_file_as_string("res://scripts/ui/" + name)
var rx := RegEx.new()
rx.compile("tr\\(\"([^\"]+)\"\\)")
for m in rx.search_all(src):
var k: String = m.get_string(1)
if not keys.has(k) and not (k in missing):
missing.append(k)
name = d.get_next()
for stepset in [BattleTutorial.STEPS1, BattleTutorial.STEPS2]:
for st in stepset:
if not keys.has(st[0]):
missing.append(st[0])
check(missing.is_empty(), "fehlende Übersetzungen: %s" % [missing])