# Magic the Lambda-ing! import random class Card(object): 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 """ "*** YOUR CODE HERE ***" def power(self, other_card): """ Calculate power as: (player card's attack) - (opponent card's defense)/2 where other_card is the opponent's card. >>> 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 """ "*** YOUR CODE HERE ***" def effect(self, other_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: : , [, ] """ 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(object): 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 "*** YOUR CODE HERE ***" 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!' "*** YOUR CODE HERE ***" 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 """ "*** YOUR CODE HERE ***" 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 TutorCard(Card): cardtype = 'Tutor' def effect(self, other_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') >>> other_card = Card('other', 500, 500) >>> tutor_test = TutorCard('Tutor', 500, 500) >>> initial_deck_length = len(player2.deck.cards) >>> tutor_test.effect(other_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 ***" #Uncomment the line below when you've finished implementing this method! #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, other_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') >>> other_card = Card('other', 300, 600) >>> ta_test = TACard('TA', 500, 500) >>> ta_test.effect(other_card, player1, player2) >>> other_card.attack 600 >>> other_card.defense 300 """ "*** YOUR CODE HERE ***" def copy(self): """ Create a copy of this card. """ return TACard(self.name, self.attack, self.defense) class ProfessorCard(Card): cardtype = 'Professor' def effect(self, other_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) >>> professor_test = ProfessorCard('Professor', 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') >>> professor_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 ***" discarded = orig_opponent_deck_length - len(opponent.deck.cards) if discarded: #Uncomment the line below when you've finished implementing this method! #print('{} cards were discarded from {}\'s deck!'.format(discarded, opponent.name)) return def copy(self): return ProfessorCard(self.name, self.attack, self.defense) ######################################## # Do not edit anything below this line # ######################################## class Deck(object): 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(object): win_score = 8 def __init__(self, player1, player2): """ Initialize a game of . """ 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))