Files
cards/tests/net_bot.gd
Team3 f0a8f18de8
Some checks failed
Tests / headless (push) Has been cancelled
Tests / fenster-schnell (push) Has been cancelled
Tests / fenster-voll (push) Has been cancelled
Tests / balance (push) Has been cancelled
update
2026-09-28 19:44:30 +02:00

104 lines
3.6 KiB
GDScript

extends Node
## Test-Mitspieler: tritt einem Host bei und spielt einfache Züge; mit --host eröffnet er
## selbst und startet, sobald ein zweiter Mensch am Tisch sitzt (ohne KI).
## godot --path . tests/net_bot.tscn -- --ip=127.0.0.1 --name=Bot
## godot --path . tests/net_bot.tscn -- --host --name=BotHost
var net: Net
var seat := -1
var game: Game
var t := 0.0
var hosting := false
func _ready() -> void:
var ip := "127.0.0.1"
var bot_name := "Bot"
for a in OS.get_cmdline_user_args():
if a.begins_with("--ip="):
ip = a.substr(5)
if a.begins_with("--name="):
bot_name = a.substr(7)
if a == "--host":
hosting = true
net = Net.new()
net.name = "Net"
get_tree().root.add_child.call_deferred(net)
net.my_name = bot_name
net.my_pick = {"elements": ["Feuer", "Erde"], "looks": {}}
net.started.connect(func(s):
seat = s
if hosting:
net.broadcast() # erster Zustand für alle, wie es sonst der Kampfbildschirm tut
_act_host.call_deferred())
net.snapshot_received.connect(_on_snapshot)
net.ended.connect(func(_r): get_tree().quit())
await get_tree().process_frame
if hosting:
net.host()
net.lobby_changed.connect(func():
if net.game == null and net.names.size() >= 2:
net.start_battle())
net.action_applied.connect(func():
net.broadcast()
_act_host.call_deferred())
else:
net.join(ip)
func _process(delta: float) -> void:
t += delta
if hosting and net.game != null:
net.tick()
if t > 180.0 or FileAccess.file_exists("user://bot_quit"):
net.leave()
get_tree().quit()
func _on_snapshot(snap: Dictionary) -> void:
game = Game.from_snapshot(snap)
if game.winner != "":
await get_tree().create_timer(1.0).timeout
get_tree().quit()
return
if game.current_idx != seat:
return
_decide(game.players[seat])
func _act_host() -> void:
if not hosting or net.game == null or net.game.winner != "" or seat < 0 or net.game.current_idx != seat:
return
game = net.game
_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.
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
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})
return
for cr in me.board:
if cr.can_attack():
for e in game.enemies_of(me):
if game.can_attack(cr, e)[0]:
net.send_action({"type": "attack", "uid": cr.uid, "target": {"kind": "player", "index": game.players.find(e)}})
return
for c in e.board:
if game.can_attack(cr, c)[0]:
net.send_action({"type": "attack", "uid": cr.uid, "target": {"kind": "creature", "uid": c.uid}})
return
net.send_action({"type": "end"})