added winning determination algorithm (not entirely working yet)

This commit is contained in:
2025-07-15 14:42:06 +02:00
parent ecfe5955b7
commit 231e861416
9 changed files with 180 additions and 11 deletions
+45 -1
View File
@@ -33,7 +33,51 @@ func get_card_texture(card_id: int, style: CardStyle = CardStyle.STICKMAN) -> Te
CardStyle.STICKMAN: CardStyle.STICKMAN:
style_name = "stickman" style_name = "stickman"
return load("res://cards/textures/" + style_name + "/" + _get_card_name(card_id) + ".webp") return load("res://cards/textures/" + style_name + "/" + _get_card_name(card_id) + ".webp")
func get_winning_card(card_ids: Array[int], trump: int) -> int:
if card_ids.has(56) or card_ids.has(57) or card_ids.has(58) or card_ids.has(59):
# cards contain magician
for card_id in card_ids:
if full_deck[card_id].card_type == Card.CardType.MAGICIAN:
return card_id
return -1 # should not happen
elif not trump == -1:
# trump exists, determine winner from this
var largest_trump_card_id: int = -1
var trump_color: Card.CardColor = full_deck[trump].color
for card_id in card_ids:
if full_deck[card_id].color == trump_color and card_id > largest_trump_card_id:
largest_trump_card_id = card_id
if not largest_trump_card_id == -1:
return largest_trump_card_id
# no trump played; determine from highest played card
# TODO check for white cards here!
return _get_largest_non_trump_card(card_ids)
else:
# no trump exists
return _get_largest_non_trump_card(card_ids)
func _get_largest_non_trump_card(card_ids: Array[int]) -> int:
var largest_card_id: int = -1
var first_color: Card.CardColor = _get_first_color_card(card_ids)
if first_color == Card.CardColor.WHITE:
return card_ids[0] # first one wins if all played cards are white
else:
for card_id in card_ids:
if full_deck[card_id].color == first_color and card_id > largest_card_id:
largest_card_id = card_id
return largest_card_id
## Returns the color of the first non-white card played.
## Returns WHITE if all cards played are white.
func _get_first_color_card(card_ids: Array[int]) -> Card.CardColor:
for card_id in card_ids:
if not full_deck[card_id].color == Card.CardColor.WHITE:
return full_deck[card_id].color
return Card.CardColor.WHITE
func _get_card_name(card_id: int) -> String: func _get_card_name(card_id: int) -> String:
var color: String var color: String
var suffix: String var suffix: String
+21 -5
View File
@@ -38,9 +38,11 @@ signal connection_status_changed(new_status: ConnectionStatus)
signal client_order_received(client_ids: Array[String]) signal client_order_received(client_ids: Array[String])
signal cards_received(cards: Dictionary) signal cards_received(cards: Dictionary)
signal trump_received(trump_id: int)
signal received_bet_request(disallowed_bet: int) signal received_bet_request(disallowed_bet: int)
signal received_win()
signal notify_play_card_request()
signal received_played_card(client_id: String, card_id: int)
signal received_play_winner_request() signal received_play_winner_request()
signal request_next_round() signal request_next_round()
@@ -135,20 +137,26 @@ func _handle_response(response: String) -> void:
var received_cards = data["cards"] var received_cards = data["cards"]
print(received_cards) print(received_cards)
cards_received.emit.call_deferred(received_cards) cards_received.emit.call_deferred(received_cards)
trump_received.emit.call_deferred(data["trump"])
"client_submitted_bet": "client_submitted_bet":
print(data) print(data)
"request_bet": "request_bet":
received_bet_request.emit.call_deferred(data["disallowed_bet"]) received_bet_request.emit.call_deferred(data["disallowed_bet"])
"begin_playing_cards": "begin_playing_cards":
# all players know it's time to play
print(data) print(data)
"request_card": "request_card":
print(data) # individual player asked to play card
notify_play_card_request.emit.call_deferred()
"play_card": "play_card":
print(data) print(data)
"determine_play_winner_request": # single card go-around "determine_play_winner_request": # single card go-around
received_play_winner_request.emit.call_deferred() received_play_winner_request.emit.call_deferred()
"client_played_card":
received_played_card.emit.call_deferred(data["client_id"], data["played_card"])
"client_won_play": "client_won_play":
print(data) if data["client_id"] == _client_id:
received_win.emit.call_deferred()
func _handle_join(data) -> void: func _handle_join(data) -> void:
match data["status"]: match data["status"]:
@@ -217,6 +225,14 @@ func start_next_round(round_count: int) -> void:
"cards": CardManager.get_shuffled_cards(_connected_client_ids, round_count), "cards": CardManager.get_shuffled_cards(_connected_client_ids, round_count),
})) }))
func play_card(card_id: int) -> void:
_send_message(JSON.stringify({
"response": "play_card",
"lobby_id": _lobby_id,
"client_id": _client_id,
"played_card": card_id,
}))
func submit_bet(bet: int, current_round: int) -> void: func submit_bet(bet: int, current_round: int) -> void:
_send_message(JSON.stringify({ _send_message(JSON.stringify({
"response": "submit_bet", "response": "submit_bet",
@@ -226,7 +242,7 @@ func submit_bet(bet: int, current_round: int) -> void:
"bet": bet, "bet": bet,
})) }))
func submit_round_winner(winning_client_id: String) -> void: func submit_play_winner(winning_client_id: String) -> void:
_send_message(JSON.stringify({ _send_message(JSON.stringify({
"response": "submit_play_winner", "response": "submit_play_winner",
"lobby_id": _lobby_id, "lobby_id": _lobby_id,
+14
View File
@@ -0,0 +1,14 @@
class_name Play
extends Resource
## Card - player association
@export var client_id: String
@export var card_id: int
func _init(
client_id: String,
card_id: int,
) -> void:
self.client_id = client_id
self.card_id = card_id
+1
View File
@@ -0,0 +1 @@
uid://cml22kioyddag
+3 -1
View File
@@ -41,6 +41,7 @@ func add_cards(card_ids: Array[int], client_id: String) -> void:
func remove_card(card: PlayingCard) -> void: func remove_card(card: PlayingCard) -> void:
self.remove_child(card) self.remove_child(card)
card.queue_free()
_arrange_cards() _arrange_cards()
func _arrange_cards() -> void: func _arrange_cards() -> void:
@@ -78,6 +79,7 @@ func _on_play_card_button_pressed() -> void:
return return
card_played.emit(_selected_card.card_details.card_id) card_played.emit(_selected_card.card_details.card_id)
_selected_card.unselect() remove_card(_selected_card)
#_selected_card.unselect()
_selected_card = null _selected_card = null
card_selected.emit(-1) card_selected.emit(-1)
+34
View File
@@ -3,6 +3,10 @@ extends Node3D
var hand_associations: Dictionary[String, PlayerHand] var hand_associations: Dictionary[String, PlayerHand]
@export var web_client: WebClientTCP
@export var trump_container: Node3D
# In gameplay order # In gameplay order
#var hand_associations: Dictionary[int, PlayerHandAssociation] #var hand_associations: Dictionary[int, PlayerHandAssociation]
var _own_client_id: String var _own_client_id: String
@@ -21,6 +25,11 @@ var _own_client_id: String
@export var hand_markers_6: Array[Marker3D] @export var hand_markers_6: Array[Marker3D]
@export var player_hand_scene: PackedScene @export var player_hand_scene: PackedScene
@export var card_scene: PackedScene
## Cards played in the current play.
var _plays: Array[Play]
var _trump_id: int = -1
func _on_web_client_tcp_client_order_received(client_ids: Array[String]) -> void: func _on_web_client_tcp_client_order_received(client_ids: Array[String]) -> void:
var marker_positions: Array[Marker3D] var marker_positions: Array[Marker3D]
@@ -80,3 +89,28 @@ func _on_web_client_tcp_cards_received(cards: Dictionary) -> void:
var card_ids: Array[int] var card_ids: Array[int]
card_ids.assign(cards[client_id]) card_ids.assign(cards[client_id])
hand_associations[client_id].add_cards(card_ids, client_id) hand_associations[client_id].add_cards(card_ids, client_id)
func _on_web_client_tcp_received_played_card(client_id: String, card_id: int) -> void:
print(client_id + " played card " + str(card_id))
_plays.append(Play.new(client_id, card_id))
func _on_web_client_tcp_received_play_winner_request() -> void:
if not $"../HBoxContainer/GameUI"._is_host:
return
var card_ids: Array[int] = []
card_ids.assign(_plays.map(func(p: Play): return p.card_id))
var winning_card_id: int = CardManager.get_winning_card(card_ids, _trump_id)
for play in _plays:
if play.card_id == winning_card_id:
web_client.submit_play_winner(play.client_id)
return
func _on_web_client_tcp_trump_received(trump_id: int) -> void:
if trump_container.get_child_count() > 0:
trump_container.remove_child(trump_container.get_child(0))
_trump_id = trump_id
var trump_card: PlayingCard = card_scene.instantiate()
trump_card.setup_card_details(_trump_id)
trump_container.add_child(trump_card)
+42 -2
View File
@@ -1,10 +1,11 @@
[gd_scene load_steps=9 format=3 uid="uid://gqrdpjslr4np"] [gd_scene load_steps=10 format=3 uid="uid://gqrdpjslr4np"]
[ext_resource type="Script" uid="uid://p5gvnyhjqe6o" path="res://components/web_client_tcp.gd" id="1_feb5d"] [ext_resource type="Script" uid="uid://p5gvnyhjqe6o" path="res://components/web_client_tcp.gd" id="1_feb5d"]
[ext_resource type="Script" uid="uid://c0cqkatyo4uj1" path="res://components/client_interface.gd" id="2_e2o6t"] [ext_resource type="Script" uid="uid://c0cqkatyo4uj1" path="res://components/client_interface.gd" id="2_e2o6t"]
[ext_resource type="Script" uid="uid://utt8atbh7b2a" path="res://game_client.gd" id="3_feb5d"] [ext_resource type="Script" uid="uid://utt8atbh7b2a" path="res://game_client.gd" id="3_feb5d"]
[ext_resource type="Script" uid="uid://bipfa366flrfa" path="res://environment_manager.gd" id="4_7jktm"] [ext_resource type="Script" uid="uid://bipfa366flrfa" path="res://environment_manager.gd" id="4_7jktm"]
[ext_resource type="PackedScene" uid="uid://jlovgr2iojrg" path="res://elements/player_hand.tscn" id="4_fc0e3"] [ext_resource type="PackedScene" uid="uid://jlovgr2iojrg" path="res://elements/player_hand.tscn" id="4_fc0e3"]
[ext_resource type="PackedScene" uid="uid://b55xpcxk7g5ph" path="res://cards/playing_card.tscn" id="6_eow3j"]
[ext_resource type="PackedScene" uid="uid://dj1wye7o27vil" path="res://assets/table.glb" id="7_eow3j"] [ext_resource type="PackedScene" uid="uid://dj1wye7o27vil" path="res://assets/table.glb" id="7_eow3j"]
[sub_resource type="SystemFont" id="SystemFont_80nbo"] [sub_resource type="SystemFont" id="SystemFont_80nbo"]
@@ -183,6 +184,7 @@ disabled = true
text = "Play Card" text = "Play Card"
[node name="BetContainer" type="VBoxContainer" parent="HBoxContainer/GameUI"] [node name="BetContainer" type="VBoxContainer" parent="HBoxContainer/GameUI"]
visible = false
layout_mode = 1 layout_mode = 1
anchors_preset = 2 anchors_preset = 2
anchor_top = 1.0 anchor_top = 1.0
@@ -200,14 +202,43 @@ layout_mode = 2
layout_mode = 2 layout_mode = 2
text = "submit bet" text = "submit bet"
[node name="EnvironmentManager" type="Node3D" parent="." node_paths=PackedStringArray("own_player_hand", "hand_markers_3", "hand_markers_4", "hand_markers_5", "hand_markers_6")] [node name="Label" type="Label" parent="HBoxContainer/GameUI"]
visible = false
layout_mode = 1
anchors_preset = 5
anchor_left = 0.5
anchor_right = 0.5
offset_left = -88.0
offset_top = 300.0
offset_right = 88.0
offset_bottom = 323.0
grow_horizontal = 2
text = "it's your turn DUMMY!!"
[node name="WinLabel" type="Label" parent="HBoxContainer/GameUI"]
visible = false
layout_mode = 1
anchors_preset = 5
anchor_left = 0.5
anchor_right = 0.5
offset_left = -20.0
offset_top = 350.0
offset_right = 20.0
offset_bottom = 373.0
grow_horizontal = 2
text = "YOU WON!!!!!!"
[node name="EnvironmentManager" type="Node3D" parent="." node_paths=PackedStringArray("web_client", "trump_container", "own_player_hand", "hand_markers_3", "hand_markers_4", "hand_markers_5", "hand_markers_6")]
script = ExtResource("4_7jktm") script = ExtResource("4_7jktm")
web_client = NodePath("../WebClientTCP")
trump_container = NodePath("TrumpPosition")
own_player_hand = NodePath("PlayerHand0") own_player_hand = NodePath("PlayerHand0")
hand_markers_3 = [NodePath("HandMarker1"), NodePath("HandMarker2")] hand_markers_3 = [NodePath("HandMarker1"), NodePath("HandMarker2")]
hand_markers_4 = [NodePath("HandMarker1"), NodePath("HandMarker3"), NodePath("HandMarker2")] hand_markers_4 = [NodePath("HandMarker1"), NodePath("HandMarker3"), NodePath("HandMarker2")]
hand_markers_5 = [NodePath("HandMarker4"), NodePath("HandMarker1"), NodePath("HandMarker3"), NodePath("HandMarker2")] hand_markers_5 = [NodePath("HandMarker4"), NodePath("HandMarker1"), NodePath("HandMarker3"), NodePath("HandMarker2")]
hand_markers_6 = [NodePath("HandMarker4"), NodePath("HandMarker1"), NodePath("HandMarker3"), NodePath("HandMarker2"), NodePath("HandMarker5")] hand_markers_6 = [NodePath("HandMarker4"), NodePath("HandMarker1"), NodePath("HandMarker3"), NodePath("HandMarker2"), NodePath("HandMarker5")]
player_hand_scene = ExtResource("4_fc0e3") player_hand_scene = ExtResource("4_fc0e3")
card_scene = ExtResource("6_eow3j")
[node name="Camera3D" type="Camera3D" parent="EnvironmentManager"] [node name="Camera3D" type="Camera3D" parent="EnvironmentManager"]
transform = Transform3D(1, 0, 0, 0, 0.992546, 0.121869, 0, -0.121869, 0.992546, 0, 1.128, 3.933) transform = Transform3D(1, 0, 0, 0, 0.992546, 0.121869, 0, -0.121869, 0.992546, 0, 1.128, 3.933)
@@ -239,6 +270,9 @@ transform = Transform3D(-0.5, 0, 0.866025, 0, 1, 0, -0.866025, 0, -0.5, 3.2, 0.4
[node name="Table" parent="EnvironmentManager" instance=ExtResource("7_eow3j")] [node name="Table" parent="EnvironmentManager" instance=ExtResource("7_eow3j")]
[node name="TrumpPosition" type="Marker3D" parent="EnvironmentManager"]
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0.167186, 0)
[connection signal="cards_received" from="WebClientTCP" to="EnvironmentManager" method="_on_web_client_tcp_cards_received"] [connection signal="cards_received" from="WebClientTCP" to="EnvironmentManager" method="_on_web_client_tcp_cards_received"]
[connection signal="client_joined_lobby" from="WebClientTCP" to="HBoxContainer/ClientInterface" method="_on_web_client_tcp_client_joined_lobby"] [connection signal="client_joined_lobby" from="WebClientTCP" to="HBoxContainer/ClientInterface" method="_on_web_client_tcp_client_joined_lobby"]
[connection signal="client_joined_lobby" from="WebClientTCP" to="HBoxContainer/GameUI" method="_on_web_client_tcp_client_joined_lobby"] [connection signal="client_joined_lobby" from="WebClientTCP" to="HBoxContainer/GameUI" method="_on_web_client_tcp_client_joined_lobby"]
@@ -251,11 +285,16 @@ transform = Transform3D(-0.5, 0, 0.866025, 0, 1, 0, -0.866025, 0, -0.5, 3.2, 0.4
[connection signal="connection_status_changed" from="WebClientTCP" to="HBoxContainer/ClientInterface" method="_on_web_client_tcp_connection_status_changed"] [connection signal="connection_status_changed" from="WebClientTCP" to="HBoxContainer/ClientInterface" method="_on_web_client_tcp_connection_status_changed"]
[connection signal="disconnected_from_lobby" from="WebClientTCP" to="HBoxContainer/ClientInterface" method="_on_web_client_tcp_disconnected_from_lobby"] [connection signal="disconnected_from_lobby" from="WebClientTCP" to="HBoxContainer/ClientInterface" method="_on_web_client_tcp_disconnected_from_lobby"]
[connection signal="disconnected_from_server" from="WebClientTCP" to="HBoxContainer/ClientInterface" method="_on_web_client_tcp_disconnected_from_server"] [connection signal="disconnected_from_server" from="WebClientTCP" to="HBoxContainer/ClientInterface" method="_on_web_client_tcp_disconnected_from_server"]
[connection signal="notify_play_card_request" from="WebClientTCP" to="HBoxContainer/GameUI" method="_on_web_client_tcp_notify_play_card_request"]
[connection signal="received_bet_request" from="WebClientTCP" to="HBoxContainer/GameUI" method="_on_web_client_tcp_received_bet_request"] [connection signal="received_bet_request" from="WebClientTCP" to="HBoxContainer/GameUI" method="_on_web_client_tcp_received_bet_request"]
[connection signal="received_chat_message" from="WebClientTCP" to="HBoxContainer/ClientInterface" method="_on_web_client_tcp_received_chat_message"] [connection signal="received_chat_message" from="WebClientTCP" to="HBoxContainer/ClientInterface" method="_on_web_client_tcp_received_chat_message"]
[connection signal="received_client_id" from="WebClientTCP" to="EnvironmentManager" method="_on_web_client_tcp_received_client_id"] [connection signal="received_client_id" from="WebClientTCP" to="EnvironmentManager" method="_on_web_client_tcp_received_client_id"]
[connection signal="received_connection_message" from="WebClientTCP" to="HBoxContainer/ClientInterface" method="_on_web_client_tcp_received_connection_message"] [connection signal="received_connection_message" from="WebClientTCP" to="HBoxContainer/ClientInterface" method="_on_web_client_tcp_received_connection_message"]
[connection signal="received_play_winner_request" from="WebClientTCP" to="EnvironmentManager" method="_on_web_client_tcp_received_play_winner_request"]
[connection signal="received_played_card" from="WebClientTCP" to="EnvironmentManager" method="_on_web_client_tcp_received_played_card"]
[connection signal="received_win" from="WebClientTCP" to="HBoxContainer/GameUI" method="_on_web_client_tcp_received_win"]
[connection signal="request_next_round" from="WebClientTCP" to="HBoxContainer/GameUI" method="_on_web_client_tcp_request_next_round"] [connection signal="request_next_round" from="WebClientTCP" to="HBoxContainer/GameUI" method="_on_web_client_tcp_request_next_round"]
[connection signal="trump_received" from="WebClientTCP" to="EnvironmentManager" method="_on_web_client_tcp_trump_received"]
[connection signal="pressed" from="HBoxContainer/ClientInterface/MarginContainer/VBoxContainer/ServerInputs/ConnectButton" to="HBoxContainer/ClientInterface" method="_on_connect_button_pressed"] [connection signal="pressed" from="HBoxContainer/ClientInterface/MarginContainer/VBoxContainer/ServerInputs/ConnectButton" to="HBoxContainer/ClientInterface" method="_on_connect_button_pressed"]
[connection signal="pressed" from="HBoxContainer/ClientInterface/MarginContainer/VBoxContainer/ServerInputs/CreateLobbyButton" to="HBoxContainer/ClientInterface" method="_on_create_lobby_button_pressed"] [connection signal="pressed" from="HBoxContainer/ClientInterface/MarginContainer/VBoxContainer/ServerInputs/CreateLobbyButton" to="HBoxContainer/ClientInterface" method="_on_create_lobby_button_pressed"]
[connection signal="pressed" from="HBoxContainer/ClientInterface/MarginContainer/VBoxContainer/ServerInputs/CreateLobbyButton" to="HBoxContainer/GameUI" method="_on_create_lobby_button_pressed"] [connection signal="pressed" from="HBoxContainer/ClientInterface/MarginContainer/VBoxContainer/ServerInputs/CreateLobbyButton" to="HBoxContainer/GameUI" method="_on_create_lobby_button_pressed"]
@@ -266,4 +305,5 @@ transform = Transform3D(-0.5, 0, 0.866025, 0, 1, 0, -0.866025, 0, -0.5, 3.2, 0.4
[connection signal="pressed" from="HBoxContainer/GameUI/StartGameButton" to="HBoxContainer/GameUI" method="_on_start_game_button_pressed"] [connection signal="pressed" from="HBoxContainer/GameUI/StartGameButton" to="HBoxContainer/GameUI" method="_on_start_game_button_pressed"]
[connection signal="pressed" from="HBoxContainer/GameUI/PlayCardButton" to="EnvironmentManager/PlayerHand0" method="_on_play_card_button_pressed"] [connection signal="pressed" from="HBoxContainer/GameUI/PlayCardButton" to="EnvironmentManager/PlayerHand0" method="_on_play_card_button_pressed"]
[connection signal="pressed" from="HBoxContainer/GameUI/BetContainer/SubmitBetButton" to="HBoxContainer/GameUI" method="_on_submit_bet_button_pressed"] [connection signal="pressed" from="HBoxContainer/GameUI/BetContainer/SubmitBetButton" to="HBoxContainer/GameUI" method="_on_submit_bet_button_pressed"]
[connection signal="card_played" from="EnvironmentManager/PlayerHand0" to="HBoxContainer/GameUI" method="_on_player_hand_0_card_played"]
[connection signal="card_selected" from="EnvironmentManager/PlayerHand0" to="HBoxContainer/GameUI" method="_on_player_hand_card_selected"] [connection signal="card_selected" from="EnvironmentManager/PlayerHand0" to="HBoxContainer/GameUI" method="_on_player_hand_card_selected"]
+12
View File
@@ -67,3 +67,15 @@ func _on_web_client_tcp_received_bet_request(disallowed_bet: int) -> void:
func _on_web_client_tcp_request_next_round() -> void: func _on_web_client_tcp_request_next_round() -> void:
_start_next_round() _start_next_round()
func _on_player_hand_0_card_played(card_id: int) -> void:
web_client.play_card(card_id)
$Label.hide()
func _on_web_client_tcp_notify_play_card_request() -> void:
$Label.show()
func _on_web_client_tcp_received_win() -> void:
$WinLabel.show()
await get_tree().create_timer(1.0).timeout
$WinLabel.hide()
+8 -2
View File
@@ -220,7 +220,7 @@ class LobbyManager:
json.dumps({ json.dumps({
"response": "client_played_card", "response": "client_played_card",
"client_id": client_id, "client_id": client_id,
"card": played_card, "played_card": played_card,
}), }),
) )
@@ -466,6 +466,8 @@ async def process_input(message: str, websocket) -> None:
}), }),
) )
print("Sent game start")
playing_client_id = lobby_manager.get_lobby(lobby_id).client_playing_order[0] playing_client_id = lobby_manager.get_lobby(lobby_id).client_playing_order[0]
await lobby_manager.send_message( await lobby_manager.send_message(
@@ -475,6 +477,8 @@ async def process_input(message: str, websocket) -> None:
"response": "request_card", "response": "request_card",
}), }),
) )
print(f"Playing client is {playing_client_id}")
else: else:
# bets are not finished; continue asking for bets # bets are not finished; continue asking for bets
disallowed_bet = -1 disallowed_bet = -1
@@ -506,7 +510,7 @@ async def process_input(message: str, websocket) -> None:
lobby_id, lobby_id,
lobby_manager.get_lobby_host_client_id(lobby_id), lobby_manager.get_lobby_host_client_id(lobby_id),
json.dumps({ json.dumps({
"response": "determine_round_winner_request", "response": "determine_play_winner_request",
}) })
) )
else: else:
@@ -527,6 +531,8 @@ async def process_input(message: str, websocket) -> None:
data_object["client_id"], data_object["client_id"],
) )
print(f"DING DING DING we have a winner!!! {data_object['client_id']}")
if __name__ == '__main__': if __name__ == '__main__':
run_local = False run_local = False
# Run locally without SSL certificate # Run locally without SSL certificate