extends "res://tests/basis.gd" ## Ein Client. "-- host" macht den Raum auf, "-- join" tritt bei und steigt ## in Runde zwei einmal aus und wieder ein. Beide spielen über die echten ## RPC-Wege. Der Raumcode wandert über eine Datei im Scratch-Verzeichnis. var game: Node var rolle := "" var runden := 0 var zuege := 0 var wuerfe := 0 var genau := 0 var wieder_da := false var _letzte_phase := "" var _rng := RandomNumberGenerator.new() var _code_datei := "" func _ready() -> void: _rng.randomize() var args := OS.get_cmdline_user_args() rolle = args[0] _code_datei = args[1] await get_tree().create_timer(0.5).timeout _lauf() func _lauf() -> void: if rolle == "host": Net.create_room("Host") await _warte(func(): return Net.room_code != "", 40.0) var f := FileAccess.open(_code_datei, FileAccess.WRITE) f.store_string(Net.room_code) f.close() await _warte(func(): return Net.lobby.size() >= 2, 80.0) Net.request_start(1, 1, 2) else: await _beitreten() await _warte(func(): game = _find(get_tree().root, "Game"); return game != null, 120.0) if game == null: _pruef("%s: Spiel kommt an" % rolle, false) _fertig() return var erste := await _warte(func(): return game.phase == "bid" or game.phase == "roll", 60.0) _pruef("%s: erster Zustand kommt an (Platz %d)" % [rolle, game.local_seat], erste) var t := 0.0 var gewartet := 0.0 while t < 1400.0 and is_instance_valid(game) and game.phase != "over": await get_tree().create_timer(0.1).timeout t += 0.1 if not is_instance_valid(game): break if game.phase != _letzte_phase: _letzte_phase = game.phase if game.phase == "roll": runden += 1 # Der Gast geht in Runde zwei einmal raus und kommt zurück. if rolle == "join" and not wieder_da and runden >= 2 and game.phase == "bid": await _wiederkommen() continue var me: int = game.local_seat if game.phase != "bid" or game.turn != me or not game.seats[me].alive: gewartet = 0.0 continue gewartet += 0.1 if gewartet < 0.2: continue var hand: Array = game.hand.get(me, []) if not hand.is_empty() and (not BoosterDB.needs_bid(hand[0]) or not game.bid.is_empty()) and _rng.randf() < 0.7: game._on_booster_chosen(hand[0], 0) wuerfe += 1 await get_tree().create_timer(0.4).timeout if not is_instance_valid(game) or game.turn != me or game.phase != "bid": continue var total := 0 for s in game.seats: total += int(s.count) var a: Dictionary = DiceAI.choose_action(game.my_values, total, game.bid, false, _rng) if a.type == "challenge" and not game.bid.is_empty() and _rng.randf() < 0.3: a = {"type": "exact"} match a.type: "bid": game._on_bid_pressed(int(a.count), int(a.face)) "challenge": game._on_challenge_pressed() "exact": game._on_exact_pressed() genau += 1 zuege += 1 gewartet = -1.5 _pruef("%s: Partie endet über RPC (Runden=%d Züge=%d Würfe=%d Genau=%d)" % [rolle, runden, zuege, wuerfe, genau], is_instance_valid(game) and game.phase == "over") if rolle == "join": _pruef("join: Wiedereinstieg hat geklappt", wieder_da) # Nochmal: der Besitzer bittet darum, beide bekommen eine frische Partie. var alt: Node = game await get_tree().create_timer(0.5).timeout if Net.is_owner: Net.request_rematch() var neu := await _warte(func(): game = _find(get_tree().root, "Game"); return game != null and game != alt, 20.0) var laeuft := false if neu: laeuft = await _warte(func(): return game.phase == "bid" or game.phase == "roll", 20.0) _pruef("%s: Nochmal im Netz bringt eine neue Partie (Platz %d)" % [rolle, game.local_seat if neu else -1], neu and laeuft and game.local_seat >= 0) # Kurz bleiben: sonst schliesst der Raum, bevor der Server-Läufer die # neue Partie überhaupt gesehen hat. await get_tree().create_timer(1.5).timeout if is_instance_valid(game): print("%s: '%s'" % [rolle, game.banner]) for i in game.seats.size(): print("%s: Platz %d %s count=%d alive=%s" % [rolle, i, game.seats[i].name, game.seats[i].count, game.seats[i].alive]) _fertig() func _beitreten() -> void: await _warte(func(): return FileAccess.file_exists(_code_datei), 80.0) await get_tree().create_timer(0.5).timeout Net.join_room(FileAccess.get_file_as_string(_code_datei).strip_edges(), "Gast") ## Verbindung reisst ab (kein bewusstes Verlassen), frisches Menü, dann der ## Weg des Knopfs "Zurück in Raum XY". func _wiederkommen() -> void: var alter_platz: int = game.local_seat var alte_zuege := zuege var code := Net.room_code multiplayer.multiplayer_peer.close() if Net.in_game: Net._on_server_disconnected() # der Verlust-Handler, wie bei echtem Abbruch await get_tree().create_timer(1.0).timeout _pruef("join: Raum nach Abbruch gemerkt", Net.letzter_raum.get("code", "") == code) game = null Net.wieder_rein() var ok := await _warte(func(): game = _find(get_tree().root, "Game"); return game != null, 60.0) if not ok: _pruef("join: nach Rückkehr kommt ein Spiel", false) wieder_da = true return var zustand := await _warte(func(): return game.phase == "bid" or game.phase == "roll" or game.phase == "reveal", 60.0) _pruef("join: nach Rückkehr kommt der Zustand", zustand) _pruef("join: alter Platz zurück, kein Bot mehr", game.local_seat == alter_platz and not game.seats[game.local_seat].ai) _pruef("join: HUD steht wieder", game.hud != null and game.hud.hand_box != null) _letzte_phase = "" wieder_da = true zuege = alte_zuege