poker-reinforcement-learning 0.1.8__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- poker_reinforcement_learning/__init__.py +10 -0
- poker_reinforcement_learning/client.py +220 -0
- poker_reinforcement_learning/deck.py +99 -0
- poker_reinforcement_learning/dummy_agent.py +240 -0
- poker_reinforcement_learning/limp_agent.py +236 -0
- poker_reinforcement_learning/poker_host.py +340 -0
- poker_reinforcement_learning/server.py +415 -0
- poker_reinforcement_learning-0.1.8.dist-info/LICENSE.txt +674 -0
- poker_reinforcement_learning-0.1.8.dist-info/METADATA +897 -0
- poker_reinforcement_learning-0.1.8.dist-info/RECORD +12 -0
- poker_reinforcement_learning-0.1.8.dist-info/WHEEL +5 -0
- poker_reinforcement_learning-0.1.8.dist-info/top_level.txt +1 -0
@@ -0,0 +1,220 @@
|
|
1
|
+
# client.py
|
2
|
+
import sys
|
3
|
+
# Import deck from parent directory
|
4
|
+
# sys.path.append("../")
|
5
|
+
import socket
|
6
|
+
import json
|
7
|
+
from .poker_host import Player
|
8
|
+
from .deck import Card
|
9
|
+
|
10
|
+
class Client:
|
11
|
+
def __init__(self):
|
12
|
+
# initialize cliennt socket with localhost ip address on port 5555
|
13
|
+
self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
14
|
+
self.host = "127.0.0.1"
|
15
|
+
self.port = 5555
|
16
|
+
self.client_socket.connect((self.host, self.port))
|
17
|
+
self.player_number = int(self.client_socket.recv(1024).decode())
|
18
|
+
self.player = Player(self.player_number)
|
19
|
+
self.player.chips *= self.player_number
|
20
|
+
print(f"You are Player {self.player_number}")
|
21
|
+
|
22
|
+
# Client messages Server
|
23
|
+
def send_message(self, message):
|
24
|
+
message = str(message)
|
25
|
+
self.client_socket.send(message.encode())
|
26
|
+
|
27
|
+
# Server messages Client
|
28
|
+
def receive_data(self):
|
29
|
+
data = self.client_socket.recv(1024).decode()
|
30
|
+
try:
|
31
|
+
return json.loads(data)
|
32
|
+
except json.JSONDecodeError:
|
33
|
+
return data
|
34
|
+
|
35
|
+
# Logic to play the game
|
36
|
+
def play_game(self):
|
37
|
+
def is_int(value):
|
38
|
+
try:
|
39
|
+
int(value)
|
40
|
+
return True
|
41
|
+
except ValueError:
|
42
|
+
return False
|
43
|
+
def is_str(value):
|
44
|
+
try:
|
45
|
+
str(value)
|
46
|
+
return True
|
47
|
+
except ValueError:
|
48
|
+
return False
|
49
|
+
|
50
|
+
while True:
|
51
|
+
game_state = self.receive_data()
|
52
|
+
# Wait for start code
|
53
|
+
if isinstance(game_state, str) and game_state == "GAME STARTED":
|
54
|
+
print("Game has started!")
|
55
|
+
|
56
|
+
|
57
|
+
# Big Blind
|
58
|
+
elif isinstance(game_state, str) and ("BIG" in game_state):
|
59
|
+
self.player.chips -= 2
|
60
|
+
# TODO: Handle when player cannot afford big blind
|
61
|
+
if (self.player.chips < 0):
|
62
|
+
self.player.chips = 0
|
63
|
+
|
64
|
+
# Small Blind
|
65
|
+
elif isinstance(game_state, str) and ("SMALL" in game_state):
|
66
|
+
self.player.chips -= 1
|
67
|
+
|
68
|
+
# Server gives chips back to player
|
69
|
+
elif isinstance(game_state, str) and ("GIVE" in game_state):
|
70
|
+
first_tilde_pos = game_state.find("~")
|
71
|
+
second_tilde_pos = game_state.find("~", first_tilde_pos + 1)
|
72
|
+
# Extract the value between the tilde characters
|
73
|
+
if first_tilde_pos != -1 and second_tilde_pos != -1:
|
74
|
+
chips = game_state[first_tilde_pos + 1:second_tilde_pos]
|
75
|
+
self.player.chips += int(chips)
|
76
|
+
print(f"You got {chips} chips back!")
|
77
|
+
else:
|
78
|
+
print("Tilde characters not found or value not present.")
|
79
|
+
|
80
|
+
# If the data is the cards make bets
|
81
|
+
elif isinstance(game_state, dict):
|
82
|
+
self.player.chips = game_state['chips'][str(self.player_number)]
|
83
|
+
# print(f"Round: {game_state['round']}")
|
84
|
+
if (game_state['round'] == 'Showdown!'):
|
85
|
+
self.print_showdown_cards(game_state)
|
86
|
+
if self.player.player_number == game_state['winner']:
|
87
|
+
self.player.chips += int(game_state['pot'])
|
88
|
+
chips_str = "\033[92m{}\033[0m".format(str(self.player.chips))
|
89
|
+
print(f"You now have {chips_str} chips!")
|
90
|
+
continue
|
91
|
+
|
92
|
+
# Add cards into players hands if hand is empty
|
93
|
+
if len(self.player.hand) == 0:
|
94
|
+
for card_str in game_state["player_hand"]:
|
95
|
+
card = Card.from_str(card_str)
|
96
|
+
self.player.hand.append(card)
|
97
|
+
|
98
|
+
print("\nCurrent Cards:")
|
99
|
+
self.print_cards(game_state)
|
100
|
+
# Active player makes their move
|
101
|
+
if game_state['current_player'] == self.player_number:
|
102
|
+
# Game Info
|
103
|
+
print(f"Current Player: Player {game_state['current_player']}", end=" | ")
|
104
|
+
print(f"Current Dealer: Player {game_state['current_dealer']}", end=" | ")
|
105
|
+
print(f"Current Pot: {game_state['pot']}")
|
106
|
+
chips_str = "\033[92m{}\033[0m".format(str(self.player.chips))
|
107
|
+
print(f"You have {chips_str} chips")
|
108
|
+
if (game_state['current_bet'] == 0):
|
109
|
+
print("What would you like to do?\nType 1 to check, 2 to raise, and 3 to fold")
|
110
|
+
if (game_state['current_bet'] > 0):
|
111
|
+
print("What would you like to do?\nType 1 to call, 2 to raise, and 3 to fold")
|
112
|
+
print("Bets:")
|
113
|
+
print("| ",end="")
|
114
|
+
for player,bet in game_state['bets'].items():
|
115
|
+
if bet < 0:
|
116
|
+
bet = 0
|
117
|
+
print(f"Player {player}: {bet} chips", end=" | ")
|
118
|
+
print(f"Current Bet: {game_state['current_bet']} |")
|
119
|
+
|
120
|
+
# Get players choice
|
121
|
+
action = input("Enter your move (1-3): ")
|
122
|
+
while ((not is_int(action)) or (int(action) < 1) or (int(action) > 3)):
|
123
|
+
print("Invalid choice.")
|
124
|
+
action = input("Enter your move (1-3): ")
|
125
|
+
|
126
|
+
self.send_message(action)
|
127
|
+
# TODO: Handle when player cannot bet but tries to anyways
|
128
|
+
if int(action) == 2:
|
129
|
+
bet = input("Enter your bet:")
|
130
|
+
|
131
|
+
# Player cannot make bet if the bet is not a number,
|
132
|
+
while ((not is_int(bet)) or (int(bet) < 0) or ((int(bet) + game_state['current_bet']) > self.player.chips)):
|
133
|
+
print("Invalid bet.")
|
134
|
+
bet = input("Enter your bet:")
|
135
|
+
self.player.chips -= int(bet) + game_state['current_bet']
|
136
|
+
self.send_message(bet)
|
137
|
+
elif int(action) == 1:
|
138
|
+
if game_state['bets'][str(self.player.player_number)] >= 0:
|
139
|
+
self.player.chips += game_state['bets'][str(self.player.player_number)]
|
140
|
+
self.player.chips -= int(game_state['current_bet'])
|
141
|
+
|
142
|
+
print()
|
143
|
+
else:
|
144
|
+
print("Waiting for the other player's move...")
|
145
|
+
# If the move is invalid, the player is prompted again
|
146
|
+
elif isinstance(game_state, str) and game_state == "INVALID_MOVE":
|
147
|
+
print("Invalid move. Please try again.")
|
148
|
+
continue
|
149
|
+
|
150
|
+
elif isinstance(game_state, str) and ("WIN" in game_state):
|
151
|
+
print("Congratulations! You won!")
|
152
|
+
self.player.hand = []
|
153
|
+
|
154
|
+
action = input("Do you want to play again? (y/n)")
|
155
|
+
action = action.lower()
|
156
|
+
while not is_str(action) or (action != "y" and action != "n"):
|
157
|
+
print('invalid entry')
|
158
|
+
action = input("Do you want to play again? (y/n)")
|
159
|
+
action = action.lower()
|
160
|
+
self.send_message(action)
|
161
|
+
|
162
|
+
elif isinstance(game_state, str) and ("LOSS" in game_state):
|
163
|
+
print("Sorry, you lost...")
|
164
|
+
self.player.hand = []
|
165
|
+
|
166
|
+
action = input("Do you want to play again? (y/n)")
|
167
|
+
action = action.lower()
|
168
|
+
while not is_str(action) or (action != "y" and action != "n"):
|
169
|
+
print('invalid entry')
|
170
|
+
action = input("Do you want to play again? (y/n)")
|
171
|
+
action = action.lower()
|
172
|
+
self.send_message(action)
|
173
|
+
|
174
|
+
# Break code when the game ends
|
175
|
+
elif isinstance(game_state, str) and ("END" in game_state):
|
176
|
+
print("Game ended.")
|
177
|
+
break
|
178
|
+
elif isinstance(game_state, str):
|
179
|
+
print(game_state)
|
180
|
+
|
181
|
+
# Close client socket
|
182
|
+
def close_connection(self):
|
183
|
+
self.client_socket.close()
|
184
|
+
|
185
|
+
# Helper methods for formatting
|
186
|
+
@staticmethod
|
187
|
+
def print_cards(game_state):
|
188
|
+
print(f"Your Hand:")
|
189
|
+
print("| ", end="")
|
190
|
+
for card_str in game_state["player_hand"]:
|
191
|
+
card = Card.from_str(card_str)
|
192
|
+
print(card.print_card(),end = " | ")
|
193
|
+
print("\n---------------------------")
|
194
|
+
if (len(game_state['community_cards']) > 0):
|
195
|
+
print(f"Community Cards:")
|
196
|
+
print("| ", end="")
|
197
|
+
for card_str in game_state["community_cards"]:
|
198
|
+
card = Card.from_str(card_str)
|
199
|
+
print(card.print_card(),end = " | ")
|
200
|
+
print()
|
201
|
+
@staticmethod
|
202
|
+
def print_showdown_cards(game_state):
|
203
|
+
for player, hand in game_state['players_hand'].items():
|
204
|
+
print(f"Player {player}'s Hand:")
|
205
|
+
print("| ", end="")
|
206
|
+
for card_str in hand:
|
207
|
+
card = Card.from_str(card_str)
|
208
|
+
print(card.print_card(),end = " | ")
|
209
|
+
print("\n---------------------------")
|
210
|
+
if (len(game_state['community_cards']) > 0):
|
211
|
+
print(f"Community Cards:")
|
212
|
+
print("| ", end="")
|
213
|
+
for card_str in game_state["community_cards"]:
|
214
|
+
card = Card.from_str(card_str)
|
215
|
+
print(card.print_card(),end = " | ")
|
216
|
+
print()
|
217
|
+
|
218
|
+
|
219
|
+
|
220
|
+
|
@@ -0,0 +1,99 @@
|
|
1
|
+
import random
|
2
|
+
|
3
|
+
class Card:
|
4
|
+
|
5
|
+
|
6
|
+
def __init__(self, name, color, suit):
|
7
|
+
self.name = name
|
8
|
+
self.color = color
|
9
|
+
self.suit = suit
|
10
|
+
self.value = self.calculate_poker_value()
|
11
|
+
|
12
|
+
@classmethod
|
13
|
+
def from_str(cls, card_str):
|
14
|
+
# Assuming the format of card_str is "Name of Suit (Color)"
|
15
|
+
parts = card_str.split()
|
16
|
+
name = parts[0]
|
17
|
+
suit = parts[2]
|
18
|
+
color = parts[3][1:-1] # Remove parentheses from color
|
19
|
+
|
20
|
+
return cls(name, color, suit)
|
21
|
+
|
22
|
+
def calculate_blackjack_value(self):
|
23
|
+
if self.name in ['Jack', 'Queen', 'King']:
|
24
|
+
return 10
|
25
|
+
elif self.name == 'Ace':
|
26
|
+
return 1
|
27
|
+
else:
|
28
|
+
return int(self.name)
|
29
|
+
|
30
|
+
def calculate_poker_value(self):
|
31
|
+
if self.name == 'Jack':
|
32
|
+
return 11
|
33
|
+
elif self.name == 'Queen':
|
34
|
+
return 12
|
35
|
+
elif self.name == 'King':
|
36
|
+
return 13
|
37
|
+
elif self.name == 'Ace':
|
38
|
+
return 14
|
39
|
+
else:
|
40
|
+
return int(self.name)
|
41
|
+
|
42
|
+
def __str__(self):
|
43
|
+
return f"{self.name} of {self.suit} ({self.color})"
|
44
|
+
|
45
|
+
def print_card(self):
|
46
|
+
symbols = {"Spade": "♠", "Clover":"♣","Heart":"♥","Diamond":"♦"}
|
47
|
+
def print_black(text):
|
48
|
+
return "\033[30m{}\033[0m".format(text)
|
49
|
+
def print_red(text):
|
50
|
+
return "\033[91m{}\033[0m".format(text)
|
51
|
+
if (self.color =="black"):
|
52
|
+
return f"{self.name} {print_black(symbols[self.suit])}"
|
53
|
+
if (self.color =="red"):
|
54
|
+
return f"{self.name} {print_red(symbols[self.suit])}"
|
55
|
+
class Deck:
|
56
|
+
def __init__(self):
|
57
|
+
self.cards = []
|
58
|
+
self.populate_deck()
|
59
|
+
|
60
|
+
def populate_deck(self):
|
61
|
+
names = ['Ace', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'Jack', 'Queen', 'King']
|
62
|
+
suits = ['Diamond', 'Clover', 'Spade', 'Heart']
|
63
|
+
|
64
|
+
for suit in suits:
|
65
|
+
for name in names:
|
66
|
+
color = 'red' if suit in ['Diamond', 'Heart'] else 'black'
|
67
|
+
card = Card(name, color, suit)
|
68
|
+
self.cards.append(card)
|
69
|
+
|
70
|
+
def shuffle(self):
|
71
|
+
random.shuffle(self.cards)
|
72
|
+
|
73
|
+
def deal_card(self):
|
74
|
+
if len(self.cards) > 0:
|
75
|
+
return self.cards.pop()
|
76
|
+
else:
|
77
|
+
print("No more cards in the deck.")
|
78
|
+
return None
|
79
|
+
|
80
|
+
def combine_decks(deck1, deck2):
|
81
|
+
combined_deck = Deck()
|
82
|
+
combined_deck.cards = deck1.cards + deck2.cards
|
83
|
+
return combined_deck
|
84
|
+
|
85
|
+
|
86
|
+
if __name__ == "__main__":
|
87
|
+
deck1 = Deck()
|
88
|
+
deck2 = Deck()
|
89
|
+
|
90
|
+
# deck1.shuffle()
|
91
|
+
deck2.shuffle()
|
92
|
+
|
93
|
+
combined_deck = combine_decks(deck1, deck2)
|
94
|
+
|
95
|
+
print("Deck:")
|
96
|
+
for _ in range(52):
|
97
|
+
card = deck1.deal_card()
|
98
|
+
if card:
|
99
|
+
print(card)
|
@@ -0,0 +1,240 @@
|
|
1
|
+
# client.py
|
2
|
+
import sys
|
3
|
+
# Import deck from parent directory
|
4
|
+
import socket
|
5
|
+
import json
|
6
|
+
from .poker_host import Player
|
7
|
+
from .deck import Card
|
8
|
+
|
9
|
+
|
10
|
+
"""
|
11
|
+
Limp Agent:
|
12
|
+
This agent participates based on the concept of "limping" through games. Essentially, the agent will simply match bets so that it can stay in the game but not increase bets to try and gain an advantage.
|
13
|
+
In the poker community, this is quite looked down upon. It kills the excitement of the game and becomes "predictable" and drags on games where players with bad hands should fold.
|
14
|
+
This is a perfect default agent for our purposes! It's strategically weak, extremely easy to implement, and if bugs are thrown I know that it's not because of internal logic.
|
15
|
+
Decision Making Logic:
|
16
|
+
The decision making function will return 1 every time to call every hand.
|
17
|
+
"""
|
18
|
+
class DummyAgent:
|
19
|
+
def __init__(self, logic):
|
20
|
+
# initialize cliennt socket with localhost ip address on port 5555
|
21
|
+
self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
22
|
+
self.host = "127.0.0.1"
|
23
|
+
self.port = 5555
|
24
|
+
self.client_socket.connect((self.host, self.port))
|
25
|
+
self.player_number = int(self.client_socket.recv(1024).decode())
|
26
|
+
self.player = Player(self.player_number)
|
27
|
+
self.player.chips *= self.player_number
|
28
|
+
print(f"You are Player {self.player_number}")
|
29
|
+
|
30
|
+
self.logic = logic
|
31
|
+
|
32
|
+
# Client messages Server
|
33
|
+
def send_message(self, message):
|
34
|
+
message = str(message)
|
35
|
+
self.client_socket.send(message.encode())
|
36
|
+
|
37
|
+
# Server messages Client
|
38
|
+
def receive_data(self):
|
39
|
+
data = self.client_socket.recv(1024).decode()
|
40
|
+
try:
|
41
|
+
return json.loads(data)
|
42
|
+
except json.JSONDecodeError:
|
43
|
+
return data
|
44
|
+
|
45
|
+
# Logic to play the game
|
46
|
+
def play_game(self):
|
47
|
+
def is_int(value):
|
48
|
+
try:
|
49
|
+
int(value)
|
50
|
+
return True
|
51
|
+
except ValueError:
|
52
|
+
return False
|
53
|
+
def is_str(value):
|
54
|
+
try:
|
55
|
+
str(value)
|
56
|
+
return True
|
57
|
+
except ValueError:
|
58
|
+
return False
|
59
|
+
|
60
|
+
while True:
|
61
|
+
game_state = self.receive_data()
|
62
|
+
# Wait for start code
|
63
|
+
if isinstance(game_state, str) and game_state == "GAME STARTED":
|
64
|
+
print("Game has started!")
|
65
|
+
|
66
|
+
|
67
|
+
# Big Blind
|
68
|
+
elif isinstance(game_state, str) and ("BIG" in game_state):
|
69
|
+
self.player.chips -= 2
|
70
|
+
# TODO: Handle when player cannot afford big blind
|
71
|
+
if (self.player.chips < 0):
|
72
|
+
self.player.chips = 0
|
73
|
+
|
74
|
+
# Small Blind
|
75
|
+
elif isinstance(game_state, str) and ("SMALL" in game_state):
|
76
|
+
self.player.chips -= 1
|
77
|
+
|
78
|
+
# Server gives chips back to player
|
79
|
+
elif isinstance(game_state, str) and ("GIVE" in game_state):
|
80
|
+
first_tilde_pos = game_state.find("~")
|
81
|
+
second_tilde_pos = game_state.find("~", first_tilde_pos + 1)
|
82
|
+
# Extract the value between the tilde characters
|
83
|
+
if first_tilde_pos != -1 and second_tilde_pos != -1:
|
84
|
+
chips = game_state[first_tilde_pos + 1:second_tilde_pos]
|
85
|
+
self.player.chips += int(chips)
|
86
|
+
print(f"You got {chips} chips back!")
|
87
|
+
else:
|
88
|
+
print("Tilde characters not found or value not present.")
|
89
|
+
|
90
|
+
# If the data is the cards make bets
|
91
|
+
elif isinstance(game_state, dict):
|
92
|
+
self.player.chips = game_state['chips'][str(self.player_number)]
|
93
|
+
# print(f"Round: {game_state['round']}")
|
94
|
+
if (game_state['round'] == 'Showdown!'):
|
95
|
+
self.print_showdown_cards(game_state)
|
96
|
+
if self.player.player_number == game_state['winner']:
|
97
|
+
self.player.chips += int(game_state['pot'])
|
98
|
+
chips_str = "\033[92m{}\033[0m".format(str(self.player.chips))
|
99
|
+
print(f"You now have {chips_str} chips!")
|
100
|
+
continue
|
101
|
+
|
102
|
+
# Add cards into players hands if hand is empty
|
103
|
+
if len(self.player.hand) == 0:
|
104
|
+
for card_str in game_state["player_hand"]:
|
105
|
+
card = Card.from_str(card_str)
|
106
|
+
self.player.hand.append(card)
|
107
|
+
|
108
|
+
print("\nCurrent Cards:")
|
109
|
+
self.print_cards(game_state)
|
110
|
+
# Active player makes their move
|
111
|
+
if game_state['current_player'] == self.player_number:
|
112
|
+
# Game Info
|
113
|
+
print(f"Current Player: Player {game_state['current_player']}", end=" | ")
|
114
|
+
print(f"Current Dealer: Player {game_state['current_dealer']}", end=" | ")
|
115
|
+
print(f"Current Pot: {game_state['pot']}")
|
116
|
+
chips_str = "\033[92m{}\033[0m".format(str(self.player.chips))
|
117
|
+
print(f"You have {chips_str} chips")
|
118
|
+
if (game_state['current_bet'] == 0):
|
119
|
+
print("What would you like to do?\nType 1 to check, 2 to raise, and 3 to fold")
|
120
|
+
if (game_state['current_bet'] > 0):
|
121
|
+
print("What would you like to do?\nType 1 to call, 2 to raise, and 3 to fold")
|
122
|
+
print("Bets:")
|
123
|
+
print("| ",end="")
|
124
|
+
for player,bet in game_state['bets'].items():
|
125
|
+
if bet < 0:
|
126
|
+
bet = 0
|
127
|
+
print(f"Player {player}: {bet} chips", end=" | ")
|
128
|
+
print(f"Current Bet: {game_state['current_bet']} |")
|
129
|
+
|
130
|
+
# Get players choice
|
131
|
+
action, bet = self.make_decision(game_state=game_state, logic=self.logic)
|
132
|
+
while ((not is_int(action)) or (int(action) < 1) or (int(action) > 3)):
|
133
|
+
print("Invalid choice.")
|
134
|
+
raise Exception("Dummy Agent chose an invalid action.")
|
135
|
+
action = self.make_decision(game_state=game_state)
|
136
|
+
|
137
|
+
self.send_message(action)
|
138
|
+
# TODO: Handle when player cannot bet but tries to anyways
|
139
|
+
if int(action) == 2:
|
140
|
+
|
141
|
+
# Player cannot make bet if the bet is not a number,
|
142
|
+
while ((not is_int(bet)) or (int(bet) < 0) or ((int(bet) + game_state['current_bet']) > self.player.chips)):
|
143
|
+
print("Invalid bet.")
|
144
|
+
raise Exception("Invalid Bet has occurred from automated bot")
|
145
|
+
self.player.chips -= int(bet) + game_state['current_bet']
|
146
|
+
self.send_message(bet)
|
147
|
+
|
148
|
+
# Action should always be 1
|
149
|
+
if int(action) == 1:
|
150
|
+
print("AI Called!!!")
|
151
|
+
if game_state['bets'][str(self.player.player_number)] >= 0:
|
152
|
+
self.player.chips += game_state['bets'][str(self.player.player_number)]
|
153
|
+
self.player.chips -= int(game_state['current_bet'])
|
154
|
+
|
155
|
+
print()
|
156
|
+
else:
|
157
|
+
print("Waiting for the other player's move...")
|
158
|
+
# If the move is invalid, the player is prompted again
|
159
|
+
elif isinstance(game_state, str) and game_state == "INVALID_MOVE":
|
160
|
+
print("Invalid move. Please try again.")
|
161
|
+
continue
|
162
|
+
|
163
|
+
elif isinstance(game_state, str) and ("WIN" in game_state):
|
164
|
+
print("Congratulations! You won!")
|
165
|
+
self.player.hand = []
|
166
|
+
|
167
|
+
action = input("Do you want to play again? (y/n)")
|
168
|
+
action = action.lower()
|
169
|
+
while not is_str(action) or (action != "y" and action != "n"):
|
170
|
+
print('invalid entry')
|
171
|
+
action = input("Do you want to play again? (y/n)")
|
172
|
+
action = action.lower()
|
173
|
+
self.send_message(action)
|
174
|
+
|
175
|
+
elif isinstance(game_state, str) and ("LOSS" in game_state):
|
176
|
+
print("Sorry, you lost...")
|
177
|
+
self.player.hand = []
|
178
|
+
|
179
|
+
action = input("Do you want to play again? (y/n)")
|
180
|
+
action = action.lower()
|
181
|
+
while not is_str(action) or (action != "y" and action != "n"):
|
182
|
+
print('invalid entry')
|
183
|
+
action = input("Do you want to play again? (y/n)")
|
184
|
+
action = action.lower()
|
185
|
+
self.send_message(action)
|
186
|
+
|
187
|
+
# Break code when the game ends
|
188
|
+
elif isinstance(game_state, str) and ("END" in game_state):
|
189
|
+
print("Game ended.")
|
190
|
+
break
|
191
|
+
elif isinstance(game_state, str):
|
192
|
+
print(game_state)
|
193
|
+
|
194
|
+
# Close client socket
|
195
|
+
def close_connection(self):
|
196
|
+
self.client_socket.close()
|
197
|
+
|
198
|
+
@staticmethod
|
199
|
+
def make_decision(game_state, logic):
|
200
|
+
return logic(game_state)
|
201
|
+
|
202
|
+
|
203
|
+
# Helper methods for formatting
|
204
|
+
@staticmethod
|
205
|
+
def print_cards(game_state):
|
206
|
+
print(f"Your Hand:")
|
207
|
+
print("| ", end="")
|
208
|
+
for card_str in game_state["player_hand"]:
|
209
|
+
card = Card.from_str(card_str)
|
210
|
+
print(card.print_card(),end = " | ")
|
211
|
+
print("\n---------------------------")
|
212
|
+
if (len(game_state['community_cards']) > 0):
|
213
|
+
print(f"Community Cards:")
|
214
|
+
print("| ", end="")
|
215
|
+
for card_str in game_state["community_cards"]:
|
216
|
+
card = Card.from_str(card_str)
|
217
|
+
print(card.print_card(),end = " | ")
|
218
|
+
print()
|
219
|
+
@staticmethod
|
220
|
+
def print_showdown_cards(game_state):
|
221
|
+
for player, hand in game_state['players_hand'].items():
|
222
|
+
print(f"Player {player}'s Hand:")
|
223
|
+
print("| ", end="")
|
224
|
+
for card_str in hand:
|
225
|
+
card = Card.from_str(card_str)
|
226
|
+
print(card.print_card(),end = " | ")
|
227
|
+
print("\n---------------------------")
|
228
|
+
if (len(game_state['community_cards']) > 0):
|
229
|
+
print(f"Community Cards:")
|
230
|
+
print("| ", end="")
|
231
|
+
for card_str in game_state["community_cards"]:
|
232
|
+
card = Card.from_str(card_str)
|
233
|
+
print(card.print_card(),end = " | ")
|
234
|
+
print()
|
235
|
+
|
236
|
+
|
237
|
+
|
238
|
+
|
239
|
+
|
240
|
+
|