update
This commit is contained in:
@@ -19,11 +19,15 @@ func _ready() -> void:
|
||||
await get_tree().process_frame
|
||||
await get_tree().process_frame
|
||||
var h: Game.Player = scr.game.human
|
||||
scr.game.buy(h, 0)
|
||||
for i in 3:
|
||||
scr.game.pick(h, 0)
|
||||
h.energy = 10
|
||||
scr.game.draw(h)
|
||||
scr.game.pick(h, 0)
|
||||
var t0 := Time.get_ticks_usec()
|
||||
for i in 30:
|
||||
scr.refresh()
|
||||
print("refresh() mit 8 Handkarten: %.2f ms" % ((Time.get_ticks_usec() - t0) / 1000.0 / 30))
|
||||
print("refresh() mit 4 Handkarten: %.2f ms" % ((Time.get_ticks_usec() - t0) / 1000.0 / 30))
|
||||
scr.ai_delay = 0.2
|
||||
measuring = true
|
||||
var start := Time.get_ticks_msec()
|
||||
|
||||
@@ -73,22 +73,20 @@ func _act_host() -> void:
|
||||
_decide(game.players[seat])
|
||||
|
||||
|
||||
## Einfache Züge mit kurzer Bedenkzeit: erst das billigste bezahlbare Angebot kaufen, dann das
|
||||
## erste spielbare Wesen ohne Ziel, dann angreifen, sonst Zug beenden.
|
||||
## Einfache Züge mit kurzer Bedenkzeit: erst eine offene Wahl treffen, dann das erste
|
||||
## spielbare Wesen ohne Ziel legen, dann angreifen, dann ziehen, sonst Zug beenden.
|
||||
func _decide(me: Game.Player) -> void:
|
||||
var g := game
|
||||
await get_tree().create_timer(0.25).timeout
|
||||
if game != g or (hosting and (net.game == null or net.game.current_idx != seat)):
|
||||
return # inzwischen ein neuer Zustand
|
||||
for i in me.shop.size():
|
||||
var offer = me.shop[i]
|
||||
if offer != null and me.energy >= offer.cost and me.hand.size() < Game.MAX_HAND:
|
||||
net.send_action({"type": "buy", "slot": i})
|
||||
return
|
||||
if not me.offer.is_empty():
|
||||
net.send_action({"type": "pick", "index": 0})
|
||||
return
|
||||
for i in me.hand.size():
|
||||
var card: Cards.Card = me.hand[i]
|
||||
if game.can_play(me, card)[0] and card.target_type() == "":
|
||||
net.send_action({"type": "play", "hand": i, "target": null})
|
||||
if game.can_play(me, card)[0]:
|
||||
net.send_action({"type": "play", "hand": i})
|
||||
return
|
||||
for cr in me.board:
|
||||
if cr.can_attack():
|
||||
@@ -100,4 +98,7 @@ func _decide(me: Game.Player) -> void:
|
||||
if game.can_attack(cr, c)[0]:
|
||||
net.send_action({"type": "attack", "uid": cr.uid, "target": {"kind": "creature", "uid": c.uid}})
|
||||
return
|
||||
if game.can_draw(me)[0]:
|
||||
net.send_action({"type": "draw"})
|
||||
return
|
||||
net.send_action({"type": "end"})
|
||||
|
||||
@@ -14,7 +14,7 @@ func _initialize() -> void:
|
||||
print("Kartenpool laden: %.1f ms" % t)
|
||||
var r := RandomNumberGenerator.new()
|
||||
r.seed = 3
|
||||
print("Ladenangebot: %.2f ms" % ms(func(): DeckGen.shop_cards(r, 5), 50))
|
||||
print("Stapel mischen: %.2f ms" % ms(func(): DeckGen.deck(r), 20))
|
||||
print("Gegner erzeugen: %.2f ms" % ms(func(): DeckGen.random_opponent(), 20))
|
||||
for n in [1]:
|
||||
var g := Game.new_battle(r)
|
||||
|
||||
1013
tests/test_runner.gd
1013
tests/test_runner.gd
File diff suppressed because it is too large
Load Diff
248
tests/ui_test.gd
248
tests/ui_test.gd
@@ -51,9 +51,13 @@ func click(node: Control) -> void:
|
||||
|
||||
|
||||
func right_click() -> void:
|
||||
await right_click_at(Vector2(5, 5))
|
||||
|
||||
|
||||
func right_click_at(pos: Vector2) -> void:
|
||||
var down := InputEventMouseButton.new()
|
||||
down.position = Vector2(5, 5)
|
||||
down.global_position = down.position
|
||||
down.position = pos
|
||||
down.global_position = pos
|
||||
down.button_index = MOUSE_BUTTON_RIGHT
|
||||
down.pressed = true
|
||||
get_viewport().push_input(down)
|
||||
@@ -149,7 +153,7 @@ func _ready() -> void:
|
||||
await frames(3)
|
||||
var fast := OS.get_environment("DINGER_FAST") != ""
|
||||
var suite := [test_menu, test_gamepad_menue, test_booster, test_gegnerauswahl, test_einstellungen,
|
||||
test_kampagne, test_sammlung, test_sprache, test_kampf_steuerung, test_kampf_feld_und_verschmelzen, test_kampf_grenzen]
|
||||
test_kampagne, test_sammlung, test_sprache, test_kampf_steuerung, test_kampf_elemente_und_verschmelzen, test_kampf_grenzen]
|
||||
if not fast:
|
||||
suite += [test_kampf.bind(3), test_kampf_abbrechen]
|
||||
# Die Netzwerktests starten Bot-Prozesse und warten auf Verbindungen; das dauert Minuten.
|
||||
@@ -215,18 +219,25 @@ func target_view(scr, valid: Array) -> Control:
|
||||
return null
|
||||
|
||||
|
||||
func human_turn(scr) -> void:
|
||||
## Nimmt alle offenen Wahlen des Spielers (immer die erste Karte), auch über das Netz.
|
||||
func pick_all(scr) -> void:
|
||||
var guard := 0
|
||||
while scr.game != null and not scr.perspective.offer.is_empty() and guard < 60:
|
||||
guard += 1
|
||||
if scr.pick_views.is_empty():
|
||||
await frames(1)
|
||||
continue
|
||||
var n: int = scr.perspective.offer.size()
|
||||
await click(scr.pick_views[0])
|
||||
var w := 0
|
||||
while scr.game != null and scr.perspective.offer.size() == n and w < 120:
|
||||
await frames(1)
|
||||
w += 1
|
||||
|
||||
|
||||
## Legt, was bezahlbar ist.
|
||||
func play_hand(scr) -> void:
|
||||
var g: Game = scr.game
|
||||
# erst kaufen, solange Mana und Handplatz reichen
|
||||
for i in 12:
|
||||
var offers: Array = scr.shop_views.filter(func(v): return g.human.energy >= v.card.cost and g.human.hand.size() < Game.MAX_HAND)
|
||||
if offers.is_empty():
|
||||
break
|
||||
var offer: Cards.Card = offers[0].card
|
||||
var mana: int = g.human.energy
|
||||
await click(offers[0])
|
||||
check(g.human.energy == mana - offer.cost, "gekauft: " + offer.name)
|
||||
# dann ausspielen, das kostet nichts
|
||||
for i in 12:
|
||||
var playable: Array = scr.hand_views.filter(func(v): return g.can_play(g.human, v.card)[0])
|
||||
if playable.is_empty():
|
||||
@@ -234,9 +245,22 @@ func human_turn(scr) -> void:
|
||||
var card: Cards.Card = playable[0].card
|
||||
var board_before: int = g.human.board.size()
|
||||
await click(playable[0])
|
||||
if scr.pending != null:
|
||||
await click(target_view(scr, g.valid_targets(g.human, card.target_type())))
|
||||
check(g.human.board.size() > board_before, "Karte gespielt: " + card.name)
|
||||
|
||||
|
||||
func human_turn(scr) -> void:
|
||||
var g: Game = scr.game
|
||||
# erst legen, was bezahlbar ist, dann mit dem Rest ziehen (und wieder legen)
|
||||
for round in 2:
|
||||
await play_hand(scr)
|
||||
for i in 6:
|
||||
if g.winner != "" or not g.can_draw(g.human)[0]:
|
||||
break
|
||||
var mana: int = g.human.energy
|
||||
await click(scr.deck)
|
||||
check(g.human.energy == mana - Game.DRAW_COST and not scr.pick_views.is_empty(), "gezogen: drei zur Wahl")
|
||||
await pick_all(scr)
|
||||
check(scr.pick_views.is_empty(), "gewählt")
|
||||
for i in 12:
|
||||
var ready: Array = scr.own_views.filter(func(v): return v.creature.can_attack())
|
||||
if ready.is_empty() or g.winner != "":
|
||||
@@ -249,7 +273,7 @@ func human_turn(scr) -> void:
|
||||
if scr.selected != cr:
|
||||
print("DEBUG Auswahl fehlgeschlagen: rect=", ready[0].get_global_rect(), " scale=", ready[0].scale,
|
||||
" busy=", ready[0].busy, " unter Maus=", under, " Meldung='", scr.msg_label.text,
|
||||
"' Zug Mensch=", g.current().is_human, " kann=", cr.can_attack(), " pending=", scr.pending, " selected=", scr.selected)
|
||||
"' Zug Mensch=", g.current().is_human, " kann=", cr.can_attack(), " selected=", scr.selected)
|
||||
check(scr.selected == cr, "Wesen gewählt")
|
||||
var targets := []
|
||||
for o in [g.opponent]:
|
||||
@@ -269,6 +293,7 @@ func start_battle() -> void:
|
||||
await click(find_button("Einzelspieler"))
|
||||
check(screen() is OpponentSelectScreen, "Gegnerauswahl")
|
||||
await click(find_button("Starten"))
|
||||
await pick_all(screen())
|
||||
|
||||
|
||||
func test_gegnerauswahl() -> void:
|
||||
@@ -285,8 +310,12 @@ func test_gegnerauswahl() -> void:
|
||||
check(hard is BattleScreen and hard.game.players.size() == 2, "Duell gestartet")
|
||||
var opp: Game.Player = hard.game.opponent
|
||||
check(opp.max_life == Profile.DIFFICULTIES.schwer.life and hard.smart_ai, "Schwer: Gegner mit %d Leben, Vorausschau-KI" % Profile.DIFFICULTIES.schwer.life)
|
||||
check(hard.game.human.shop.size() == Game.SHOP_SIZE and hard.game.human.hand.is_empty(),
|
||||
"Start mit vollem Laden und leerer Hand")
|
||||
check(hard.game.human.offer.size() == Game.START_OFFER and hard.game.human.hand.is_empty() and hard.pick_layer.visible,
|
||||
"Start: fünf Karten zur Wahl, Hand leer")
|
||||
check(hard.game.human.offer.all(func(c): return c.cost <= Game.START_MANA + 1), "alle fünf sind im ersten Zug spielbar")
|
||||
await shot("05_startwahl")
|
||||
await pick_all(hard)
|
||||
check(hard.game.human.hand.size() == Game.START_PICKS and not hard.pick_layer.visible, "drei behalten, Wahl geschlossen")
|
||||
check(hard.hero_panels[opp].position == BattleLayout.OPP_BOX.position, "der Gegner steht oben in der Mitte")
|
||||
await shot("11_kampf")
|
||||
await give_up()
|
||||
@@ -294,9 +323,10 @@ func test_gegnerauswahl() -> void:
|
||||
await click(find_button("Leicht"))
|
||||
await click(find_button("Starten"))
|
||||
var easy = screen()
|
||||
await pick_all(easy)
|
||||
opp = easy.game.opponent
|
||||
check(opp.max_life == Profile.DIFFICULTIES.leicht.life and not easy.smart_ai, "Leicht: Gegner mit %d Leben, einfache KI" % Profile.DIFFICULTIES.leicht.life)
|
||||
check(easy.game.players[0].max_energy == 1 and easy.game.human.life == Game.START_LIFE, "gleiche Regeln für beide")
|
||||
check(easy.game.players[0].max_energy == Game.START_MANA and easy.game.human.life == Game.START_LIFE, "gleiche Regeln für beide")
|
||||
await give_up()
|
||||
await click(find_button("Einzelspieler"))
|
||||
await click(find_button("Normal"))
|
||||
@@ -457,39 +487,47 @@ func test_kampf_steuerung() -> void:
|
||||
scr.ai_delay = 0.0
|
||||
await wait_for_human(scr)
|
||||
var g: Game = scr.game
|
||||
g.human.energy = 20 # das Angebot ist zufällig, hier soll nur die Steuerung geprüft werden
|
||||
g.human.energy = 20 # die Wahl ist zufällig, hier soll nur die Steuerung geprüft werden
|
||||
g.human.hand = [Cards.by_id("f_wolf")]
|
||||
scr.refresh()
|
||||
check(scr.shop_views.size() == Game.SHOP_SIZE and g.human.hand.is_empty(), "voller Laden, leere Hand")
|
||||
# Kaufen: Mana weg, Karte auf der Hand
|
||||
var offer: Cards.Card = scr.shop_views[0].card
|
||||
check(scr.hand_views.size() == 1 and scr.deck.enabled and scr.pick_views.is_empty(), "eine Handkarte, Stapel bereit, keine Wahl offen")
|
||||
# Ziehen: 1 Mana weg, drei zur Wahl, eine landet auf der Hand
|
||||
var mana: int = g.human.energy
|
||||
await click(scr.shop_views[0])
|
||||
check(g.human.hand.size() == 1 and g.human.hand[0] == offer and g.human.energy == mana - offer.cost, "Angebot gekauft")
|
||||
# Ausspielen kostet nichts
|
||||
await click(scr.deck)
|
||||
check(g.human.energy == mana - Game.DRAW_COST and scr.pick_views.size() == Game.OFFER_SIZE and scr.pick_layer.visible, "gezogen: drei Karten zur Wahl")
|
||||
var wanted: Cards.Card = scr.pick_views[1].card
|
||||
await click(scr.pick_views[1])
|
||||
check(g.human.hand.size() == 2 and g.human.hand[1].id == wanted.id and not scr.pick_layer.visible, "gewählt, liegt auf der Hand")
|
||||
# Ausspielen kostet die Kartenkosten
|
||||
var board_before: int = g.human.board.size()
|
||||
mana = g.human.energy
|
||||
await key(KEY_1)
|
||||
check(g.human.board.size() == board_before + 1 and g.human.energy == mana, "Wesen per Taste gespielt, ohne Mana")
|
||||
# Rückgängig: Wesen zurück auf die Hand
|
||||
check(g.human.board.size() == board_before + 1 and g.human.energy == mana - Cards.by_id("f_wolf").cost, "Wesen per Taste gespielt, Kosten bezahlt")
|
||||
# Rückgängig: Wesen zurück auf die Hand, Mana zurück
|
||||
check(scr.b_undo.visible, "Rückgängig angeboten")
|
||||
await click(scr.b_undo)
|
||||
g = scr.game
|
||||
check(g.human.board.size() == board_before and g.human.hand.any(func(c): return c.id == offer.id), "Rückgängig stellt die Hand her")
|
||||
check(g.human.board.size() == board_before and g.human.hand.any(func(c): return c.id == "f_wolf") and g.human.energy == mana, "Rückgängig stellt Hand und Mana her")
|
||||
check(not scr.b_undo.visible and g.log.back() == "Rückgängig.", "Rückgängig verbraucht")
|
||||
await key(KEY_1)
|
||||
check(g.human.board.size() == board_before + 1, "erneut gespielt")
|
||||
# Neu würfeln kostet Mana
|
||||
var shop_before: Array = g.human.shop.duplicate()
|
||||
# Ziehen per Taste
|
||||
mana = g.human.energy
|
||||
await click(scr.b_reroll)
|
||||
check(g.human.energy == mana - Game.REROLL_COST and g.human.shop != shop_before, "Laden neu gewürfelt")
|
||||
await key(KEY_Z)
|
||||
check(g.human.energy == mana - Game.DRAW_COST and scr.pick_layer.visible, "Z zieht")
|
||||
await key(KEY_1)
|
||||
check(not scr.pick_layer.visible, "1 wählt die erste Karte")
|
||||
await shot("22_kampf_steuerung")
|
||||
# Gamepad: Zeiger im Laden bewegen, A kauft
|
||||
await pad(JOY_BUTTON_DPAD_RIGHT)
|
||||
check(scr.gp_zone == "shop" and scr.gp_index == 1 and scr.cursor_layer.get_child_count() == 1, "Gamepad-Zeiger auf zweitem Angebot")
|
||||
# Gamepad: A auf dem Stapel zieht, Steuerkreuz wählt die zweite Karte, A nimmt sie
|
||||
await pad(JOY_BUTTON_DPAD_LEFT)
|
||||
check(scr.gp_zone == "deck" and scr.cursor_layer.get_child_count() == 1, "Gamepad-Zeiger auf dem Stapel")
|
||||
var hand_before: int = g.human.hand.size()
|
||||
await pad(JOY_BUTTON_A)
|
||||
check(g.human.hand.size() == hand_before + 1, "Gamepad A kauft das Angebot")
|
||||
check(scr.pick_layer.visible, "Gamepad A zieht")
|
||||
await pad(JOY_BUTTON_DPAD_RIGHT)
|
||||
check(scr.gp_zone == "pick" and scr.gp_index == 1, "Zeiger auf der zweiten Karte der Wahl")
|
||||
await pad(JOY_BUTTON_A)
|
||||
check(g.human.hand.size() == hand_before + 1 and not scr.pick_layer.visible, "Gamepad A nimmt die Karte")
|
||||
scr.ai_delay = 0.75
|
||||
await key(KEY_SPACE)
|
||||
check(g.current() != g.human or g.turn >= 2, "Zug per Leertaste beendet")
|
||||
@@ -519,31 +557,28 @@ func test_kampf_grenzen() -> void:
|
||||
g.human.energy = 100
|
||||
scr.refresh()
|
||||
await frames(1)
|
||||
# Hand voll kaufen
|
||||
# Hand voll ziehen
|
||||
var guard := 0
|
||||
while g.human.hand.size() < Game.MAX_HAND and guard < 30:
|
||||
guard += 1
|
||||
if scr.shop_views.is_empty():
|
||||
await click(scr.b_reroll)
|
||||
continue
|
||||
await click(scr.shop_views[0])
|
||||
await click(scr.deck)
|
||||
await pick_all(scr)
|
||||
check(g.human.hand.size() == Game.MAX_HAND, "Hand auf %d gefüllt" % Game.MAX_HAND)
|
||||
check(scr.shop_views.all(func(v): return v.dim), "bei voller Hand ist nichts mehr kaufbar")
|
||||
if not scr.shop_views.is_empty():
|
||||
await click(scr.shop_views[0])
|
||||
check(scr.msg_label.text == tr("Hand voll"), "Meldung bei voller Hand: " + scr.msg_label.text)
|
||||
check(not scr.deck.enabled, "bei voller Hand lässt sich nichts ziehen")
|
||||
await click(scr.deck)
|
||||
check(scr.msg_label.text == tr("Deine Hand ist voll"), "Meldung bei voller Hand: " + scr.msg_label.text)
|
||||
# Feld voll spielen
|
||||
guard = 0
|
||||
while g.human.board.size() < Game.MAX_BOARD and guard < 30:
|
||||
guard += 1
|
||||
if g.human.hand.is_empty():
|
||||
await click(scr.deck)
|
||||
await pick_all(scr)
|
||||
await key(KEY_1)
|
||||
if scr.pending != null: # Karte will ein Ziel
|
||||
var valid: Array = g.valid_targets(g.human, scr.pending.target_type())
|
||||
if valid.is_empty():
|
||||
await right_click()
|
||||
else:
|
||||
await click(target_view(scr, valid))
|
||||
check(g.human.board.size() == Game.MAX_BOARD, "Feld mit %d Wesen voll" % Game.MAX_BOARD)
|
||||
if g.human.hand.is_empty():
|
||||
await click(scr.deck)
|
||||
await pick_all(scr)
|
||||
await key(KEY_1)
|
||||
check(scr.msg_label.text == tr("Dein Feld ist voll"), "Meldung bei vollem Feld: " + scr.msg_label.text)
|
||||
await shot("25_kampf_voll")
|
||||
@@ -553,16 +588,16 @@ func test_kampf_grenzen() -> void:
|
||||
await click(scr.own_views[0])
|
||||
await click(scr.own_views[1])
|
||||
check(g.human.board.size() == before - 1, "Verschmelzen macht einen Platz frei")
|
||||
# Ohne Mana kein Neuwürfeln
|
||||
# Ohne Mana kein Ziehen
|
||||
g.human.energy = 0
|
||||
scr.refresh()
|
||||
await frames(1)
|
||||
check(scr.b_reroll.disabled, "ohne Mana kein Neuwürfeln")
|
||||
check(not scr.deck.enabled, "ohne Mana kein Ziehen")
|
||||
await give_up()
|
||||
|
||||
|
||||
## Feldanzeige und Verschmelzen im Kampf.
|
||||
func test_kampf_feld_und_verschmelzen() -> void:
|
||||
## Elementregel, verdeckt legen, Kartenmenü und Verschmelzen im Kampf.
|
||||
func test_kampf_elemente_und_verschmelzen() -> void:
|
||||
await start_battle()
|
||||
var scr = screen()
|
||||
check(scr is BattleScreen, "Kampf gestartet")
|
||||
@@ -570,47 +605,71 @@ func test_kampf_feld_und_verschmelzen() -> void:
|
||||
await wait_for_human(scr)
|
||||
var g: Game = scr.game
|
||||
g.human.board.clear()
|
||||
var put := func(p: Game.Player, id: String) -> Game.Creature:
|
||||
var cr := Game.Creature.new(Cards.by_id(id), p, g.next_uid)
|
||||
scr.opponent().board.clear() # was die KI im ersten Zug gelegt hat, stört die Zähler
|
||||
var put := func(p: Game.Player, id: String, hidden: bool = false) -> Game.Creature:
|
||||
var cr := Game.Creature.new(Cards.by_id(id).copy(), p, g.next_uid)
|
||||
g.next_uid += 1
|
||||
cr.ready = true
|
||||
cr.attacks_left = 1
|
||||
cr.hidden = hidden
|
||||
p.board.append(cr)
|
||||
return cr
|
||||
put.call(g.human, "f_wolf")
|
||||
put.call(g.human, "f_asche")
|
||||
put.call(g.human, "w_reiter")
|
||||
var falke: Game.Creature = put.call(scr.others()[0], "l_falke")
|
||||
g.human.hand = [Cards.by_id("f_kobold")]
|
||||
g.human.energy = 10
|
||||
g.field_charge["Wasser"] = 2
|
||||
var falke: Game.Creature = put.call(scr.opponent(), "l_falke")
|
||||
var secret: Game.Creature = put.call(scr.opponent(), "f_kobold", true)
|
||||
g.human.hand = [Cards.by_id("f_kobold").copy(), Cards.by_id("l_wind").copy()]
|
||||
g.human.energy = 20
|
||||
g.apply_auras()
|
||||
scr.refresh()
|
||||
await frames(2)
|
||||
check(scr.field_view.text() == "Feuer 0/4 · Wasser 2/4 · Erde 0/4 · Luft 0/4", "neutrales Feld zeigt die Ladung: " + scr.field_view.text())
|
||||
for i in Cards.FIELD_CHARGE:
|
||||
g.charge_field(Cards.by_id("f_kobold"))
|
||||
scr.refresh()
|
||||
await frames(2)
|
||||
check(scr.field_view.text().begins_with("Vulkan: +1 Angriff"), "Feldanzeige nennt das Feld: " + scr.field_view.text())
|
||||
check(g.human.board[0].field_bonus == 1 and g.human.board[0].power() == 4, "das Feuerwesen bekommt +1 Angriff")
|
||||
check(scr.hand_views[0].bonus == 2 and scr.hand_views[0].tag == "Dampf", "die Handkarte zeigt +2 (Resonanz und Feld) und die Kombo Dampf")
|
||||
check(scr.b_fuse.visible and scr.b_fuse.text == "Verschmelzen", "Verschmelzen wird angeboten")
|
||||
await shot("23_feld")
|
||||
check(scr.element_view.text() == "Feuer 2 · Wasser 1 · Erde 0 · Luft 1", "Zähler ohne das verdeckte Wesen: " + scr.element_view.text())
|
||||
check(scr.tiles[secret.uid].secret and scr.hand_views[0].bonus == 0, "fremdes verdecktes Wesen zeigt nur den Rücken, noch kein Bonus in Sicht")
|
||||
# verdeckt legen über das Kartenmenü (Rechtsklick auf die Handkarte)
|
||||
var menu_text := "Verdeckt legen ◆ %d" % Cards.by_id("f_kobold").cost
|
||||
await hover(scr.hand_views[0])
|
||||
check(scr.tiles[g.human.board[1].uid].mark == "Dampf" and "Dampf" in scr.info_label.text, "beim Zeigen auf die Handkarte ist der Kombo-Partner markiert")
|
||||
await right_click_at(scr.hand_views[0].get_global_rect().get_center())
|
||||
check(scr.menu_layer.visible and find_button(menu_text, scr.menu_layer) != null, "Rechtsklick öffnet das Kartenmenü mit „Verdeckt legen“")
|
||||
await shot("23_kartenmenue")
|
||||
await click(find_button(menu_text, scr.menu_layer))
|
||||
var mine_hidden: Game.Creature = g.human.board[3]
|
||||
check(mine_hidden.hidden and not scr.menu_layer.visible and scr.element_view.text().begins_with("Feuer 2"), "verdeckt gelegt, zählt nicht")
|
||||
# aufdecken per Klick auf das eigene verdeckte Wesen (erst, wenn es aus der Hand angekommen ist)
|
||||
while scr.own_views[3].busy:
|
||||
await frames(1)
|
||||
await click(scr.own_views[3])
|
||||
check(not mine_hidden.hidden and scr.element_view.text().begins_with("Feuer 3"), "aufgedeckt, zählt jetzt")
|
||||
put.call(g.human, "f_kobold")
|
||||
g.apply_auras()
|
||||
scr.refresh()
|
||||
await frames(2)
|
||||
check(scr.element_view.text().begins_with("Feuer 4 (+1/+1)") and "Luft 1 (-1/-1)" in scr.element_view.text(), "vier Feuer: Bonus und Malus angezeigt: " + scr.element_view.text())
|
||||
check(g.human.board[0].power() == 4 and falke.power() == 2, "Feuerwesen +1, Luftwesen -1")
|
||||
check(scr.hand_views[0].bonus == -1, "die Luftkarte auf der Hand zeigt -1")
|
||||
await shot("23b_vier_feuer")
|
||||
# Verbessern über das Menü
|
||||
var wolf: Game.Creature = g.human.board[0]
|
||||
scr.open_menu(wolf, Rect2(scr.own_views[0].slot, scr.own_views[0].size))
|
||||
var mana: int = g.human.energy
|
||||
await click(find_button("Schild ◆ %d" % Cards.KEYWORD_COST["Schild"], scr.menu_layer))
|
||||
check(wolf.shield and "Schild" in wolf.card.keywords and g.human.energy == mana - Cards.KEYWORD_COST["Schild"], "Schild gekauft")
|
||||
# Angriffsziel: Elementvorteil, verdeckte ohne Anzeige, Held gesperrt
|
||||
await click(scr.own_views[0])
|
||||
check(scr.selected == g.human.board[0] and scr.tiles[falke.uid].matchup == 1, "Angreifer gewählt: das Luftwesen zeigt +1 für Feuer")
|
||||
await shot("23b_angriffsziel")
|
||||
await right_click() # Auswahl wieder aufheben
|
||||
check(scr.selected == null and scr.tiles[falke.uid].matchup == 0, "Auswahl aufgehoben, Vorteil verschwindet")
|
||||
check(scr.selected == wolf and scr.tiles[falke.uid].matchup == 1 and scr.tiles[secret.uid].matchup == 0, "Angreifer gewählt: +1 gegen Luft, nichts gegen Verdeckte")
|
||||
check(not g.can_attack(wolf, scr.opponent())[0], "Held nicht angreifbar, solange Wesen stehen")
|
||||
await click(scr.tiles[secret.uid])
|
||||
check(not secret.hidden and not (secret in scr.opponent().board), "Angriff deckt auf und tötet den Kobold")
|
||||
await right_click()
|
||||
# Verschmelzen
|
||||
await click(scr.b_fuse)
|
||||
check(scr.fusing and scr.b_fuse.text == "Abbrechen", "Verschmelzen ausgewählt")
|
||||
await click(scr.own_views[0])
|
||||
await click(scr.own_views[1])
|
||||
check(scr.fuse_first != null, "erstes Wesen gewählt")
|
||||
await shot("24_verschmelzen")
|
||||
await click(scr.own_views[1])
|
||||
check(g.human.board.size() == 1 and g.human.board[0].name == "Dampf", "die beiden Wesen sind zu Dampf verschmolzen")
|
||||
check(not scr.fusing and g.human.energy == 8, "Modus beendet und Mana bezahlt")
|
||||
check(scr.own_views.size() == 1, "nur noch eine eigene Kachel")
|
||||
mana = g.human.energy
|
||||
await click(scr.own_views[2])
|
||||
check(g.human.board.any(func(c): return c.name == "Dampf") and g.human.energy == mana - 1, "zu Dampf verschmolzen, 1 Mana bezahlt")
|
||||
check(not scr.fusing, "Modus beendet")
|
||||
await give_up()
|
||||
|
||||
|
||||
@@ -642,6 +701,7 @@ func test_netzwerk() -> void:
|
||||
var b = screen()
|
||||
check(b is BattleScreen and b.is_online() and not b.is_client(), "Netzwerkkampf als Host")
|
||||
b.ai_delay = 0.0
|
||||
await pick_all(b)
|
||||
var rounds := 0
|
||||
while b.game != null and b.game.winner == "" and rounds < 2:
|
||||
if b.game.current() == b.perspective:
|
||||
@@ -747,6 +807,7 @@ func test_host_wechsel() -> void:
|
||||
await frames(1)
|
||||
w += 1
|
||||
check(b.game != null and main.net.i_am_successor and not main.net.backup.is_empty(), "Nachfolger kennt den vollen Spielstand")
|
||||
await pick_all(b)
|
||||
main.net.rejoin_seconds = 3.0
|
||||
_bot_quit(true)
|
||||
w = 0
|
||||
@@ -820,6 +881,7 @@ func test_kampagne() -> void:
|
||||
await click(find_button("Kämpfen"))
|
||||
var battle = screen()
|
||||
check(battle is BattleScreen and battle.stage == 0, "Kampagnenkampf gestartet")
|
||||
await pick_all(battle)
|
||||
check(battle.game.opponent.name == "Fenn", "Fenn ist der Gegner")
|
||||
check(battle.game.opponent.perks == ["feuer_angriff"] and battle.game.log.any(func(l): return l.begins_with("Fenn: Feuerwesen")), "Boss-Merkmal aktiv")
|
||||
await shot("16_kampagne_kampf")
|
||||
@@ -835,7 +897,8 @@ func test_kampagne() -> void:
|
||||
await shot("27_kampagne_kapitel2")
|
||||
await click(find_button("Kämpfen"))
|
||||
var b2 = screen()
|
||||
check(b2 is BattleScreen and b2.stage == 10 and b2.game.opponent.perks.size() == 2 and b2.game.opponent.life == 30, "Kapitel-2-Boss mit zwei Merkmalen und 30 Leben")
|
||||
await pick_all(b2)
|
||||
check(b2 is BattleScreen and b2.stage == 10 and b2.game.opponent.perks.size() == 2 and b2.game.opponent.life == 22, "Kapitel-2-Boss mit zwei Merkmalen und 22 Leben")
|
||||
check(b2.game.human.perks == [main.profile.perk], "eigenes Merkmal im Kampf")
|
||||
await give_up()
|
||||
main.profile.campaign_stage = 0
|
||||
@@ -884,7 +947,7 @@ func test_kampf_abbrechen() -> void:
|
||||
scr.ai_delay = 0.0
|
||||
var g: Game = scr.game
|
||||
await wait_for_human(scr)
|
||||
check(g.opponent != null and g.human.max_energy == 1, "Duell läuft")
|
||||
check(g.opponent != null and g.human.max_energy == Game.START_MANA, "Duell läuft")
|
||||
# Kartenvorschau: aufgewertete Karten zeigen ihre Seltenheit
|
||||
g.human.energy = 10
|
||||
var wolf := Game.Creature.new(Cards.by_id("f_wolf"), g.human, 9000)
|
||||
@@ -894,18 +957,15 @@ func test_kampf_abbrechen() -> void:
|
||||
scr.refresh()
|
||||
var reiter_view = scr.hand_views.filter(func(v): return v.card.id == "w_reiter")[0]
|
||||
check(reiter_view.rarity == "episch", "Handkarte trägt die eigene Stufe")
|
||||
await hover(scr.field_view) # erst weg von der Hand, damit das Betreten sicher ausgelöst wird
|
||||
await hover(scr.element_view) # erst weg von der Hand, damit das Betreten sicher ausgelöst wird
|
||||
await hover(reiter_view)
|
||||
var previews = scr.preview_holder.get_children().filter(func(c): return c is CardView)
|
||||
check(previews.size() == 1 and previews[0].rarity == "episch", "Vorschau ebenfalls")
|
||||
await shot("21_kampf_vorschau")
|
||||
var targeted: Array = scr.hand_views.filter(func(v): return v.card.target_type() != "" and g.can_play(g.human, v.card)[0])
|
||||
if not targeted.is_empty():
|
||||
var card: Cards.Card = targeted[0].card
|
||||
await click(targeted[0])
|
||||
check(scr.pending == card, "Ziel wird erwartet")
|
||||
await right_click()
|
||||
check(scr.pending == null and card in g.human.hand, "Rechtsklick bricht ab")
|
||||
if not scr.own_views.is_empty():
|
||||
await click(scr.own_views[0])
|
||||
await right_click()
|
||||
check(scr.selected == null, "Rechtsklick bricht ab")
|
||||
await hover(scr.hand_views[0])
|
||||
if scr.preview_holder.get_child_count() == 0:
|
||||
print("DEBUG Hover: overlay=", scr.any_overlay(), " hand=", scr.hand_views.size(),
|
||||
|
||||
Reference in New Issue
Block a user