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.
@@ -0,0 +1,10 @@
1
+ from .deck import *
2
+ from .poker_host import *
3
+
4
+ from .client import *
5
+ from .server import *
6
+ from .dummy_agent import *
7
+ from .limp_agent import *
8
+
9
+
10
+ __all__ = ["Client", "Server", "Deck", "Card", "LimpAgent", "DummyAgent"]
@@ -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
+