-
Notifications
You must be signed in to change notification settings - Fork 0
/
broker.py
422 lines (306 loc) · 13.5 KB
/
broker.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
from deck import Deck
from card import Card
from coin import Coin
from player import Player
from hand import Hand
from pile import Pile
class Broker():
"""
This class plays the Buy, Sell, or Negotiate card game.
It has a Deck, a Pile and two Players as instance variables.
It also contains an instance variable for counting the number
of rounds and negotiations and which Player won them.
It contains an optional parameter that you can set to stop
the play after a certain number of rounds, called limit.
"""
def __init__(self, limit = 1000):
"""
Here is the algorithm for class construction:
1. Initializes round limit.
2. Creates the Deck and Pile.
3. Creates both Players and places them in a list.
4. Creates the lists holding round and negotiation counts.
"""
# 1. Initialize round limit
self.__limit = limit
# 2. Creates the Deck and Pile
self.__deck = Deck()
self.__pile = Pile()
# 3. Creates both Players and places them in a list
self.__players = [None, Player(), Player()]
# 4. Creates the lists holding round and negotiation counts
self.__round_wins = [0, 0, 0]
def setup(self):
"""
Here is the algorithm for game setup:
1. Initializes the Deck.
2. Shuffles the Deck 5 times and displays it.
3. Deals the Cards.
4. Displays the dealt Hands.
"""
print("=============SETUP===============")
# 1. Initializes the Deck
print("The new deck:")
self.__deck.initialize()
# 2. Shuffles the Deck 5 times and displays it
for d in range(5):
self.__deck.shuffle()
print("The shuffled deck:")
print(self.__deck)
# 3. Deals the cards
for c in range(26):
for p in range(1,3):
card = self.__deck.deal()
player = self.__players[p]
player.add_card(card)
# 4. Displays the dealt hands
print("Original hands:")
for p in range(1,3):
player = self.__players[p]
print("Player{}:".format(p))
player.display_hand()
def play(self):
"""
Here is the algorithm for playing a game:
Loop for each round of play
Game ends when someone wins or after round limit
1. Each player plays a Card to the pile
Display the first two top Cards on the Pile
2. Call determine_pile_winner to determine the winner
Winner is returned as player number (1 or 2)
or 0, if cards are equal
3. If Cards are equal,
winner is determined through negotiation
If Cards are not equal, winner gets pile
A. Cards are equal:
If both players have at least one Card,
Call negotiate to determine winner
B. One player does not have enough Cards,
use Coin flip to see if he survives
4. Cards are not equal: winning Player adds Pile to Hand
5. Check for game over: meaning a Player has no Cards
6. Increment the number of rounds
"""
print("=============== PLAY ===============")
rounds = 1
game_over = False
# Loop for each round of play
# Game ends when someone wins or after round limit
while not game_over and rounds <= self.__limit:
print("\nRound{}: ".format(rounds))
# 1. Each player plays a Card to the pile
# Display the first two top Cards on the Pile
for p in range(1,3):
player = self.__players[p]
player.play_card(self.__pile)
p1_card, p2_card = self.__pile.top_two_cards()
print("Player1: Card: " + str(p1_card))
print("Player2: Card: " + str(p2_card))
# 2. Call determine_pile_winner to determine the winner
# Winner is returned as player number (1 or 2)
# or 0, if cards are equal
winner = self.determine_pile_winner()
print("Winner: Player" + str(winner))
# 3. If Cards are equal,
# winner is determined through negotiation
# If Cards are not equal, winner gets pile
if winner == 0:
print("\nLet the NEGOTIATIONs Begin!!!")
# A. Cards are equal:
# If both players have at least one Card,
# Call negotiate to determine winner
p1_num_cards = self.__players[1].get_num_cards()
p2_num_cards = self.__players[2].get_num_cards()
if (p1_num_cards >= 1) and (p2_num_cards >= 1):
winner = self.negotiate()
print("Winner: Player" + str(winner))
if winner == 0:
game_over = self.use_coin_flip_for_neg()
else:
self.__players[winner].add_pile(self.__pile)
# B. One player does not have enough Cards,
# use Coin flip to see if he survives
else:
game_over = self.use_coin_flip_for_neg()
# 4. Cards are not equal: winning Player adds Pile to Hand
else:
self.__players[winner].add_pile(self.__pile)
self.__round_wins[0] += 1
self.__round_wins[winner] += 1
# 5. Check for game over: meaning a Player has no Cards
if (self.__players[1].get_num_cards() == 0 or
self.__players[2].get_num_cards() == 0):
game_over = True
# 6. Increment the number of rounds
rounds += 1
def determine_pile_winner(self):
"""
Here is the algorithm for determining a pile winner:
1. Retrieve the top two Cards from the Pile
2. Compare the Cards:
A. Cards are equal:
Return winner = 0
B. Flip Coin to see whether the low Card
or the high Card wins the play
1. If the flip is heads, make high card holder the winner
2. If the flip is tails, make low card holder the winner
"""
# 1. Retrieve the top two Cards from the Pile
p1_card, p2_card = self.__pile.top_two_cards()
# 2. Compare the Cards:
compare_result = p1_card.compare(p2_card)
if compare_result == 0:
# A. Cards are equal:
# Return winner = 0
return 0
else:
# B. Flip Coin to see whether the low Card
# or the high Card wins the play
face = Coin().flip()
print("Face: {}".format(face))
# 1. If the flip is heads, make high card holder the winner
if face == "Heads":
if compare_result > 0:
return 1
else:
return 2
# 2. If the flip is tails, make low card holder the winner
else:
if compare_result > 0:
return 2
else:
return 1
def negotiate(self):
"""
Here is the algorithm for negotiation:
1. Loop while there is no clear winner (winner == 0)
A. Loop for each player to play Cards for the Pile,
up to four Cards, as long as both Players have Cards
1. If both Players have Cards:
Display the first two top Cards on the Pile
2. Break if a player is out of Cards
B. Call determine_pile_winner to find who won
the negotiation
C. If no clear winner and one player is out of Cards
then break
2. Return winner
"""
# 1. Loop while there is no clear winner (winner == 0)
# Clear winner: determine_pile_winner returns 1 or 2
winner = 0
while winner == 0:
# A. Loop for each player to play Cards for the Pile,
# up to four Cards
low_on_cards = False
for c in range(4):
# 1. If both Players have Cards,
# Display the first two top Cards on the Pile
if (self.__players[1].get_num_cards() >= 1 and
self.__players[2].get_num_cards() >= 1):
for p in range(1,3):
player = self.__players[p]
player.play_card(self.__pile)
p1_card, p2_card = self.__pile.top_two_cards()
print("Player1: Card: " + str(p1_card))
print("Player2: Card: " + str(p2_card))
# 2. Break if a player is out of Cards
else:
low_on_cards = True
break
# B. Call determine_pile_winner to find who won
# the negotiation
winner = self.determine_pile_winner()
# C. If no clear winner and one player is out of Cards
# then break
if winner == 0 and low_on_cards:
break
# 2. Return winner
return winner
def use_coin_flip_for_neg(self):
"""
When one of the Players has only one Card and the game
is in negotiation:
Use a Coin flip to determine who gets the Pile of Cards
Here is the algorithm for flipping Coin during negotiation:
1. If the Coin is heads, the Player with the most Cards
adds the Pile of Cards to his Hand and wins the game
2. Else the Coin is tails, the Player with the least
amount of Cards adds the Pile of Cards to his Hand
and the game is continued
"""
game_over = False
print("Using coin flip to settle negotiation")
face = Coin().flip()
print("Face: " + str(face))
p1_num_cards = self.__players[1].get_num_cards()
p2_num_cards = self.__players[2].get_num_cards()
# 1. If the Coin is heads, the Player with the most Cards
# adds the Pile of Cards to his Hand and wins the game
if face == "Heads":
game_over = True
if p1_num_cards < p2_num_cards:
winner = 2
else:
winner = 1
self.__players[winner].add_pile(self.__pile)
# 2. Else the Coin is tails, the Player with the least
# amount of Cards adds the Pile of Cards to his Hand
# and the game is continued
else:
p1_num_cards = self.__players[1].get_num_cards()
p2_num_cards = self.__players[2].get_num_cards()
if p1_num_cards > p2_num_cards:
winner = 2
else:
winner = 1
self.__players[winner].add_pile(self.__pile)
return game_over
def display_results(self):
"""
Displays the game results, when game is over
Here is the algorithm for displaying results at game end
1. The game ends when the round limit is reached,
or a player is out of Cards.
A. Round limit was reached.
The winner is the one with the most Cards.
B. A player is out of Cards.
The winner is the one with all the Cards.
2. Display Hands, if both players still have Cards.
"""
print()
print("========== Game Over - show results ============")
print()
print("Number of Rounds:", self.__round_wins[0])
print("Number of Rounds won by Player 1:", self.__round_wins[1])
print("Number of Rounds won by Player 2:", self.__round_wins[2])
# 1. The game ends when the round limit is reached,
# or a player is out of Cards
p1_num_cards = self.__players[1].get_num_cards()
p2_num_cards = self.__players[2].get_num_cards()
winner = 0
if self.__round_wins[0] >= self.__limit:
# A. Round limit was reached,
# The winner is the one with the most Cards
print("Round limit of {} rounds reached".format(self.__limit))
if p1_num_cards == p2_num_cards:
print("Game is tied")
else:
if p1_num_cards > p2_num_cards:
winner = 1
else:
winner = 2
print("Player{} has won the game".format(winner))
else:
# B. A player is out of Cards
# The winner is the one with all the Cards
if p1_num_cards > p2_num_cards:
winner = 1
else:
winner = 2
print("Player{} has won the game".format(winner))
# 2. Display Hands, if both players still have Cards
if winner == 0 or self.__players[winner].get_num_cards() < 52:
for p in range(1,3):
print("Player{} Cards:".format(p))
self.__players[p].display_hand()
print()