-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclasses.py
More file actions
343 lines (300 loc) · 10.7 KB
/
Copy pathclasses.py
File metadata and controls
343 lines (300 loc) · 10.7 KB
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
# Magic the Lambda-ing!
import random
class Card:
cardtype = 'Staff'
def __init__(self, name, attack, defense):
"""
Create a Card object with a name, attack,
and defense.
>>> staff_member = Card('staff', 400, 300)
>>> staff_member.name
'staff'
>>> staff_member.attack
400
>>> staff_member.defense
300
>>> other_staff = Card('other', 300, 500)
>>> other_staff.attack
300
>>> other_staff.defense
500
"""
self.name = name
self.attack = attack
self.defense = defense
def power(self, opponent_card):
"""
Calculate power as:
(player card's attack) - (opponent card's defense)/2
>>> staff_member = Card('staff', 400, 300)
>>> other_staff = Card('other', 300, 500)
>>> staff_member.power(other_staff)
150.0
>>> other_staff.power(staff_member)
150.0
>>> third_card = Card('third', 200, 400)
>>> staff_member.power(third_card)
200.0
>>> third_card.power(staff_member)
50.0
"""
pow = self.attack - opponent_card.defense / 2
return pow
def effect(self, opponent_card, player, opponent):
"""
Cards have no default effect.
"""
return
def __repr__(self):
"""
Returns a string which is a readable version of
a card, in the form:
<cardname>: <cardtype>, [<attack>, <defense>]
"""
return '{}: {}, [{}, {}]'.format(self.name, self.cardtype, self.attack, self.defense)
def copy(self):
"""
Returns a copy of this card.
"""
return Card(self.name, self.attack, self.defense)
class Player:
def __init__(self, deck, name):
"""Initialize a Player object.
A Player starts the game by drawing 5 cards from their deck. Each turn,
a Player draws another card from the deck and chooses one to play.
>>> test_card = Card('test', 100, 100)
>>> test_deck = Deck([test_card.copy() for _ in range(6)])
>>> test_player = Player(test_deck, 'tester')
>>> len(test_deck.cards)
1
>>> len(test_player.hand)
5
"""
self.deck = deck
self.name = name
hand = [deck.draw() for i in range(5)]
self.hand = hand
def draw(self):
"""Draw a card from the player's deck and add it to their hand.
>>> test_card = Card('test', 100, 100)
>>> test_deck = Deck([test_card.copy() for _ in range(6)])
>>> test_player = Player(test_deck, 'tester')
>>> test_player.draw()
>>> len(test_deck.cards)
0
>>> len(test_player.hand)
6
"""
assert not self.deck.is_empty(), 'Deck is empty!'
self.hand.append(self.deck.draw())
def play(self, card_index):
"""Remove and return a card from the player's hand at the given index.
>>> from cards import *
>>> test_player = Player(standard_deck, 'tester')
>>> ta1, ta2 = TACard("ta_1", 300, 400), TACard("ta_2", 500, 600)
>>> tutor1, tutor2 = TutorCard("t1", 200, 500), TutorCard("t2", 600, 400)
>>> test_player.hand = [ta1, ta2, tutor1, tutor2]
>>> test_player.play(0) is ta1
True
>>> test_player.play(2) is tutor2
True
>>> len(test_player.hand)
2
"""
currCard = self.hand[card_index]
self.hand.pop(card_index)
return currCard
def display_hand(self):
"""
Display the player's current hand to the user.
"""
print('Your hand:')
for card_index, displayed_card in zip(range(len(self.hand)), [str(card) for card in self.hand]):
indent = ' ' * (5 - len(str(card_index)))
print(card_index, indent + displayed_card)
def play_random(self):
"""
Play a random card from hand.
"""
return self.play(random.randrange(len(self.hand)))
######################
# Optional Questions #
######################
class AICard(Card):
cardtype = 'AI'
def effect(self, opponent_card, player, opponent):
"""
Reduce the opponent's card's attack by its defense,
then double its defense.
>>> from cards import *
>>> player1, player2 = Player(player_deck, 'p1'), Player(opponent_deck, 'p2')
>>> opponent_card = Card('other', 300, 600)
>>> ai_test = AICard('AI', 500, 500)
>>> ai_test.effect(opponent_card, player1, player2)
>>> opponent_card.attack
0
>>> opponent_card.defense
1200
>>> opponent_card = Card('other', 600, 400)
>>> ai_test = AICard('AI', 500, 500)
>>> ai_test.effect(opponent_card, player1, player2)
>>> opponent_card.attack
200
>>> opponent_card.defense
800
"""
"*** YOUR CODE HERE ***"
def copy(self):
"""
Create a copy of this card.
"""
return AICard(self.name, self.attack, self.defense)
class TutorCard(Card):
cardtype = 'Tutor'
def effect(self, opponent_card, player, opponent):
"""
Discard the first 3 cards in the opponent's hand and have
them draw the same number of cards from their deck.
>>> from cards import *
>>> player1, player2 = Player(player_deck, 'p1'), Player(opponent_deck, 'p2')
>>> opponent_card = Card('other', 500, 500)
>>> tutor_test = TutorCard('Tutor', 500, 500)
>>> initial_deck_length = len(player2.deck.cards)
>>> tutor_test.effect(opponent_card, player1, player2)
p2 discarded and re-drew 3 cards!
>>> len(player2.hand)
5
>>> len(player2.deck.cards) == initial_deck_length - 3
True
"""
"*** YOUR CODE HERE ***"
# You should add your implementation above this.
print('{} discarded and re-drew 3 cards!'.format(opponent.name))
def copy(self):
"""
Create a copy of this card.
"""
return TutorCard(self.name, self.attack, self.defense)
class TACard(Card):
cardtype = 'TA'
def effect(self, opponent_card, player, opponent):
"""
Swap the attack and defense of an opponent's card.
>>> from cards import *
>>> player1, player2 = Player(player_deck, 'p1'), Player(opponent_deck, 'p2')
>>> opponent_card = Card('other', 300, 600)
>>> ta_test = TACard('TA', 500, 500)
>>> ta_test.effect(opponent_card, player1, player2)
>>> opponent_card.attack
600
>>> opponent_card.defense
300
"""
"*** YOUR CODE HERE ***"
def copy(self):
"""
Create a copy of this card.
"""
return TACard(self.name, self.attack, self.defense)
class InstructorCard(Card):
cardtype = 'Instructor'
def effect(self, opponent_card, player, opponent):
"""
Adds the attack and defense of the opponent's card to
all cards in the player's deck, then removes all cards
in the opponent's deck that share an attack or defense
stat with the opponent's card.
>>> test_card = Card('card', 300, 300)
>>> instructor_test = InstructorCard('Instructor', 500, 500)
>>> opponent_card = test_card.copy()
>>> test_deck = Deck([test_card.copy() for _ in range(8)])
>>> player1, player2 = Player(test_deck.copy(), 'p1'), Player(test_deck.copy(), 'p2')
>>> instructor_test.effect(opponent_card, player1, player2)
3 cards were discarded from p2's deck!
>>> [(card.attack, card.defense) for card in player1.deck.cards]
[(600, 600), (600, 600), (600, 600)]
>>> len(player2.deck.cards)
0
"""
orig_opponent_deck_length = len(opponent.deck.cards)
"*** YOUR CODE HERE ***"
# You should add your implementation above this.
discarded = orig_opponent_deck_length - len(opponent.deck.cards)
if discarded:
print('{} cards were discarded from {}\'s deck!'.format(discarded, opponent.name))
return
def copy(self):
return InstructorCard(self.name, self.attack, self.defense)
########################################
# Do not edit anything below this line #
########################################
class Deck:
def __init__(self, cards):
"""
With a list of cards as input, create a deck.
This deck should keep track of the cards it contains, and
we should be able to draw from the deck, taking a random
card out of it.
"""
self.cards = cards
def draw(self):
"""
Draw a random card and remove it from the deck.
"""
assert self.cards, 'The deck is empty!'
rand_index = random.randrange(len(self.cards))
return self.cards.pop(rand_index)
def is_empty(self):
return len(self.cards) == 0
def copy(self):
"""
Create a copy of this deck.
"""
return Deck([card.copy() for card in self.cards])
class Game:
win_score = 8
def __init__(self, player1, player2):
"""
Initialize a game of <REPLACE NAME>.
"""
self.player1, self.player2 = player1, player2
self.p1_score = 0
self.p2_score = 0
def play_round(self, p1_card, p2_card):
"""
After each player picks a card, play them against
each other.
"""
p1_card.effect(p2_card, self.player1, self.player2)
p2_card.effect(p1_card, self.player2, self.player1)
p1_power = p1_card.power(p2_card)
p2_power = p2_card.power(p1_card)
if p1_power > p2_power:
# Player 1 wins the round.
self.p1_score += 1
result = 'won'
elif p2_power > p1_power:
# Player 2 wins the round.
self.p2_score += 1
result = 'lost'
else:
# This round is a draw.
result = 'tied'
# Display results to user.
print('You {} this round!'.format(result))
print('{}\'s card: {}; Power: {}'.format(self.player1.name, p1_card, p1_power))
print('Opponent\'s card: {}; Power: {}'.format(p2_card, p2_power))
def game_won(self):
"""
Check if the game is won and, if so,
which player won.
"""
if self.p1_score < self.win_score and self.p2_score < self.win_score:
return 0
return 1 if self.p1_score > self.p2_score else 2
def display_scores(self):
"""
Display players' scores to the user.
"""
print('{}\'s score: {}'.format(self.player1.name, self.p1_score))
print('Opponent\'s score: {}'.format(self.p2_score))