104 lines
3.6 KiB
GDScript
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"})
|