Files
cards/tests/net_bot.gd
Team3 24a03ed1ee
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-10-02 19:57:02 +02:00

105 lines
3.5 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 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
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]:
net.send_action({"type": "play", "hand": i})
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
if game.can_draw(me)[0]:
net.send_action({"type": "draw"})
return
net.send_action({"type": "end"})